pax_global_header00006660000000000000000000000064122330071050014503gustar00rootroot0000000000000052 comment=6589f6dec3e43632c076021a3e7b9994a2f45363 sofia-sip-1.12.11+20110422.1/000077500000000000000000000000001223300710500145665ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/.gitignore000066400000000000000000000003161223300710500165560ustar00rootroot00000000000000/open_c/config.h /win32/config.h /man/ /autom4te.cache/ /config.h /config.h.in~ /config.log /config.status /libtool /stamp-h1 Doxyfile Makefile TAGS .deps .libs *.a *.la *.lo *.o *_tag_ref.c *.sw[lmnop] sofia-sip-1.12.11+20110422.1/AUTHORS000066400000000000000000000047061223300710500156450ustar00rootroot00000000000000Current development team ------------------------ Pekka Pessi Martti Mela Kai Vehmanen Contributors (in alphabetical order, surname first) --------------------------------------------------- Alaoui, Youness Chan, Tat Ciarkowski, Andrzej Czapiga, Brian Denis-Courmont, Remi Ferrari, Fabio Filonenko Roman Haataja, Mikko Jacobs, Remeres Jalava, Teemu Jerris, Michael Katcipis, Tiago Knoblich, Stephan Legostayev, Denis Lenk, Jeff Leuenberger, Stefan Margarido, Fabio Maximov, Stas Morgado, Aleksander Neuner, Jarod Paul, Johan Pizarro, Paulo Prado, Dimitri E. Puolakka, Petteri Puustinen, Ismo Rene, Mathieu Rinne-Rahkola, Pasi Richards, Jerry Rondina, Daniele Rose, Inca Saari, Mika Sabatini, Stefano Samposalo, Kai Selin, Jari Suttner, Bernhard Underwood, Steve Urpalainen, Jari Verberne, Lee Wachter, Bernd Whittaker, Colin Zabaluev, Mikhail Zaikin, Maxim Note: for details on who did what, see the version control system change history, and release notes for past releases at http://sofia-sip.sourceforge.net/relnotes/ sofia-sip-1.12.11+20110422.1/COPYING000066400000000000000000000634651223300710500156370ustar00rootroot00000000000000 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. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! sofia-sip-1.12.11+20110422.1/COPYRIGHTS000066400000000000000000000262521223300710500162130ustar00rootroot00000000000000This package contains the Sofia-SIP library. Copyright (C) 2005-2006 Nokia Corporation and others (see the in individual files for a detailed list of copyright holders). Contact: Pekka Pessi 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 (LICENSE) for more details. ---------------------------------------------------------------------------- libsofia-sip-ua/su/inet_ntop.c The package also contains files licensed by Internet Software Consortium. These files are distributed with the following copyright notice: Copyright (c) 1996 by Internet Software Consortium. Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ---------------------------------------------------------------------------- libsofia-sip-ua/su/inet_pton.c The package also contains files licensed by Internet Software Consortium and Internet Systems Consortium, Inc.. These files are distributed with the following copyright notice: Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") Copyright (c) 1996,1999 by Internet Software Consortium. Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ---------------------------------------------------------------------------- libsofia-sip-ua/su/sofia-sip/su_addrinfo.h libsofia-sip-ua/su/su_addrinfo.c The package also contains files licensed by WIDE Project. These files are distributed with the following copyright notice: Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. All rights reserved. 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. Neither the name of the project nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``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 PROJECT OR CONTRIBUTORS 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. ---------------------------------------------------------------------------- libsofia-sip-ua/su/getopt.c The package also contains files licensed by IBM Corporation. These files are distributed with the following copyright notice: This module contains code made available by IBM Corporation on an AS IS basis. Any one receiving the module is considered to be licensed under IBM copyrights to use the IBM-provided source code in any way he or she deems fit, including copying it, compiling it, modifying it, and redistributing it, with or without modifications. No license under any IBM patents or patent applications is to be implied from this copyright license. A user of the module should understand that IBM cannot provide technical support for the module and will not be responsible for any consequences of use of the program. Any notices, including this one, are not to be removed from the module without the prior written consent of IBM. ---------------------------------------------------------------------------- libsofia-sip-ua/su/su_md5.c The package also contains files written by Colin Plumb. These files are distributed with the following copyright notice: This code implements the MD5 message-digest algorithm. The algorithm is due to Ron Rivest. This code was initially written by Colin Plumb in 1993, no copyright is claimed. This code is in the public domain; do with it what you wish. Equivalent code is available from RSA Data Security, Inc. This code has been tested against that, and is equivalent, except that you don't need to include two pages of legalese with every copy. ---------------------------------------------------------------------------- libsofia-sip-ua/su/strtoull.c The package also contains files licensed by University of California and Sun Microsystems. These files are distributed with the following copyright notice: Copyright (c) 1988 The Regents of the University of California. Copyright (c) 1994 Sun Microsystems, Inc. The following license.terms for information on usage and redistribution of this individual file, and for a DISCLAIMER OF ALL WARRANTIES. This software is copyrighted by the Regents of the University of California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState Corporation and other parties. The following terms apply to all files associated with the software unless explicitly disclaimed in individual files. The authors hereby grant permission to use, copy, modify, distribute, and license this software and its documentation for any purpose, provided that existing copyright notices are retained in all copies and that this notice is included verbatim in any distributions. No written agreement, license, or royalty fee is required for any of the authorized uses. Modifications to this software may be copyrighted by their authors and need not follow the licensing terms described here, provided that the new terms are clearly indicated on the first page of each file where they apply. IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. GOVERNMENT USE: If you are acquiring this software on behalf of the U.S. government, the Government shall have only "Restricted Rights" in the software and related documentation as defined in the Federal Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are acquiring the software on behalf of the Department of Defense, the software shall be classified as "Commercial Computer Software" and the Government shall have only "Restricted Rights" as defined in Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the authors grant the U.S. Government and others acting in its behalf permission to use and distribute the software in accordance with the terms specified in this license. ---------------------------------------------------------------------------- libsofia-sip-ua/ipt/rc4.c The package also contains files written by Pekka Pessi. These files are distributed with the following copyright notice: Copyright (c) 1996 Pekka Pessi. All rights reserved. This source code is provided for unrestricted use. Users may copy or modify this source code without charge. THIS SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. This source code is provided with no support and without any obligation on the part of author to assist in its use, correction, modification or enhancement. AUTHOR SHALL HAVE NO LIABILITY WITH RESPECT TO THE INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE OR ANY PART THEREOF. In no event will author be liable for any lost revenue or profits or other special, indirect and consequential damages, even if author has been advised of the possibility of such damages. ---------------------------------------------------------------------------- libsofia-sip-ua/su/poll.c The package also contains files from GNU C Library by Free Software Foundation. These files are distributed with the following copyright notice: Copyright (C) 1994,1996,1997,1998,1999,2001,2002 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C 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. The GNU C 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 the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ---------------------------------------------------------------------------- sofia-sip-1.12.11+20110422.1/ChangeLog000066400000000000000000000013021223300710500163340ustar00rootroot00000000000000=============================================================== ChangeLog / Sofia-SIP - SIP User-Agent library =============================================================== Sofia-SIP library ChangeLog files are available in the following places: - per subdirectory ChangeLog files - all non-trivial changes to files (unless documented elsewhere) - version control system changelogs - darcs and CVS tree repositories (see README.developers for latest repository location information) - RELEASE files - changes for the current version store in top-level RELEASE files of the source tree - old RELEASE files available at: http://sofia-sip.sourceforge.net/relnotes/ sofia-sip-1.12.11+20110422.1/ChangeLog.ext-trees000066400000000000000000004271461223300710500202750ustar00rootroot000000000000002006-05-12 Pekka Pessi * Release 1.11.8. * Updates for win32. Added SOFIAPUBFUN to few functions in msg_parser(). Added new C++ wrappers for C files that need C++ linkage in tport_test. Fixed setlocal braino in build_sources.cmd. * Compiling and linking torture_su_bm and torture_su_port as static on win32. * Added more warnings to ignore on VC to win32/config.h.in. * Added files missing from dist to win32/Makefile.am * Added msg_get_address() and msg_set_address() functions to Trying to solve ai_addrlen problem. * Put last fixes into RELEASE file. * Fixed binding problems in nua and nta.c. Returning more appropriate error code from tport_tbind(), too. This patch fixes tracked bugs #1485624 (nua not binding to 5060), #1485625 (nua_create() fails if STUN init fails) and #1485632 (ncorrect error message for nua bind error). Nua now also binds both to NUTAG_URL and NUTAG_SIPS_URL() URIs, nua_create() fails if binding either of them fails. * Fixed msg_addrlen() usage. msg_addrlen() returns a pointer to ai_addrlen field of struct addrinfo inside the msg_t object. ai_addrlen has type size_t. However, system calls taking a return valur pointer to address length, use type socklen_t. Typically size_t is unsigned long, socklen_t is int, so casting msg_addrlen() return value to (socklen_t *) will break on (high-endian) 64-bit platforms. svsp. * Re-enable natify in test_nua.c. * Updated nua_register() and NUTAG_OUTBOUND() documentation. Taking NUTAG_OUTBOUND() options correctly into account in outbound.c. Improved the contact validation process in outbound.c, too. * Silenced warnings caused by mismatching integral types. In nua_session, unsigned v. sip_time_t. In tport.c, size_t v. socklen_t. * Fixed socket semantics on test_nat.c for BSD, too. * Fixed type of msg_addrlen() to size_t in msg_addr.h/msg.c. POSIX socklen_t is not used in addrinfo. We use addrinfo. * Added Changes to RELEASE. * Fixed DIST_SUBDIRS at toplevel Makefile.am. * Fixed AM_LDFLAGS in sresolv/Makefile.am. * Not declaring inline functions with global scope in * Added su_source_create() prototype to su-glib/so_source.c. 2006-05-11 Pekka Pessi * Added more info about outbound, gruu and win32 DLL to RELEASE. * sres.c: storing last dot into the error record, too. Bug reported by Thomas Rosenblatt. * Added new files to dist, too. - libsofia-sip-ua/sresolv/sofia-resolv/sres_config.h - win32/libsofia-sip-ua-static/libsofia_sip_ua_static.dsp - win32/tests/test_nua/test_nat_tags.cpp * Now building libsofia_sip_ua.dll on win32. We define both IN_LIBSOFIA_SIP_UA and IN_LIBSOFIA_SRES in libsofia_sip_ua.dsp. Because of DLL linkage, we compile tags typedefs as C++ (see win32/tests/test_nua/test_nat_tags.cpp). Removed LIBSOFIA_SIP_UA_STATIC from win32/sofia-sip/su_configure.h. Added libsofia_sip_ua_static.lib, too. If you want to compile against that, you need define LIBSOFIA_SIP_UA_STATIC by yourself. Added libsofia-sip-ua-static/libsofia_sip_ua_static.dsp. Using multithreaded DLL runtime for all projects. * Added SOFIAPUBFUN/SOFIAPUBVAR to stun module, too. * Added test_nat_tags.c to nua module. * Fixed a memory leak in nta_outgoing_mcreate(). * Added SRESPUBFUN and sres_config.h to sresolv module. * Updated headers. Added sofia-sip/ prefix to documentation entries referring to include files. Added SOFIAPUBFUN and SOFIAPUBVAR to files that missed them. Removed some deprecated functions and macros. * Avoid #include ordering problem with sip_parser.h in sip_test_msg.c, too. * Silenced warnings in tport_type_tcp.c. * Added @deprecated to deprecated sip functions. * Moved ntlm functions to auth_ntlm.h from auth_plugin.h> in iptsec module. * Reordered #includes in http module. Avoid #include ordering problem with . * Removed utf8 and unicode-related stuff from library. Source files are still included in source tar. * Reordered #includes in sip module. Avoid #include ordering problem with sip_parser.h. * Updated ADD-A-HEADER file in sip module. * Added SOFIAPUBFUN and SOFIAPUBVAR to all public nua functions and variables. 2006-05-10 Pekka Pessi * nua/outbound.c: Adding Accept-Contact (a) to keepalive OPTIONS, too. Just in case the message gets forwarded. * Remove dependency to Makefile in targets for marshal file generation in nua_glib. * Fixed includes in outbound.[hc]. * Added Doxyfiles to libsofia-sip-ua-glib. Note that the files are not actually commented. * nua, soa: Adding Warnings to the response if appropriate. * Refactored outbound code in nua module. Added outbound.c, outbound.h. * Added registration refresh tests to test_nua.c. Added command line option --expensive and environment variable EXPENSIVE_CHECKS, too. * Updated refreshing of publications in nua_publish.c Added nua_publish_usage_refresh(), nua_publish_usage_shutdown(). * Updated dialog usage refreshes. Updated nua_dialog_usage_refresh(), nh_call_pending(). * Added expiration time settings to nua/test_proxy.[hc]. Added test_proxy_set_expiration() and test_proxy_get_expiration(). * Fixed timing problem when testing nat binding change. 2006-05-09 Pekka Pessi * nua_register.c: use nua-generated contact for refresh interval calculation. Allow SIPS uris in contacts, too. * nua_register.c: ignoring bad received parameters in Via header. * Updated config file handling in sresolv/sres.c. Using reference counting with config structure when copying resolver objects. Trying harder to avoid re-parsing resolv.conf and checking for updated servers. Changed SRES_UPDATE_INTERVAL_SECS to 5 for non-WIN32 platforms. * su/su_alloc.c, su/sofia-sip/su_alloc.h: su_home_ref() takes const pointer. 2006-05-08 kai.vehmanen@nokia.com * Added sip_dig and stunc to VC6/win32 workspace file. * Fixed sip_dig errors when building on VC6/win32. * Fixed STUN bugs when build with VC6/win32. * Updated STUN NAT type check interface to utilize current IETF BEHAVE terms. * Print sofia-sip version in stunc usage. 2006-05-08 Pekka Pessi * url module: using SOFIAPUBFUN and SOFIAPUBVAR instead of URL_DLL. * Fixed overflow problem with su_timer_run(). After 25 days the su_timer_run() timer started to misbehave, 1 < <31 milliseconds is bit more than 24 days, 20 hours, 31 minutes... 2006-05-06 kai.vehmanen@nokia.com * Pretty-print the NAT type check results with STUN stunc. * Do not use resend when doing NAT type checking with STUN. The resends do not currently include the request attribute bytes as they should do. * Minor mods to STUN module. * Added optional local port randomization to stunc. Making repeated checks from the same local port will produce unreliable results. * Fixed STUN's Test-IV. * Added lots more documentation about the STUN nattype algorithm. Added a Test-IV step that is improved over the RFC3489 algorithm. * Refactored the STUN nattype checks. There are still a few cases where the detection fails. * Moved req-specific states to stun.c, moved stun_nattype_t to public header, added documentation to all stun enum fields. * Removed deprecated STUN function definitions from stun.c. 2006-05-05 kai.vehmanen@nokia.com * Removed commented code segments. * nua-glib: added bind URL and STUN server parameters for nua_glib_constructor() * Fixed compiler warnings in stun. * Removed various deprecated functions that were already commented out from the code. Closed sf.net bug #1456403. * Fixed stunc argument parsing. It is now possible to given STUN server address as a hostname instead of requiring a dotted decimal IP-address. * Always install auth_ntlm.h as it is needed by auth_client.h. 2006-05-04 kai.vehmanen@nokia.com * Updated developer docs w.r.t. VCS system. Darcs is now the primary version control system and sf.net CVS is only used as a backup. * Fixed header paths and added missing libraries that caused errors with debug/release builds. * Added sip_options to the win32 SofiaSIP workspace. 2006-05-04 Pekka Pessi * sres_cache.c: fixed problem using macro as offsetof() argument. * test_sresolv.v: added more tests for A6 record parsing. * sres.c, sres_cache.c: records are now allocated in a single chunk. Bug hunted down by Thomas Rosenblatt: strings and domains belonging to record were allocated from resolver home, not from cache home. * Fixed problem with config without search domains in sresolv/sres.c. * Added information for COPYRIGHTS file to README.developers. * Setting send buffer size to at least 64K in Windows in tport_type_tcp.c. * Using SOFIAPUBFUN and SOFIAPUBVAR in bnf.h. * Silenced sprious warnings by MSG_HEADER_INIT() in msg_header.h. * NUTAG_KEEPALIVE() now uses milliseconds. Changes in sofia-sip/nua_tag.h, nua_params.c, nua_register.c, test_nua.c. * Renamed su_create_wait as su_wait_create in libsofia-sip-ua-glib/su-glib/su_source_test.c * stun/stun.c: s/su_destroy_timer/su_timer_destroy/. * Added sofia-sip/auth_ntlm.h auth_ntlm.c to dist in iptsec module. * Added license to Makefiles (kv) Added copyright lines and reference to LGPL license to the Makefile.am and configure.ac files. * poll_test.c: Renamed call s/su_create_wait/su_wait_create/. (kv) * Added libsofia-sip-ua-glib/ChangeLog to darcs (kv) * Added win32 registry name server discovery (kv) Based on a patch from Dimitri E. Prado. Decreased update interval to 180secs (SRES_UPDATE_INTERVAL_SECS). 2006-05-03 Pekka Pessi * Not using SU_MSG_RINITIALIZER anymore. Fixed nta/nta.c, nth/nth_client.c, su/su_root.c. * Added SOFIAPUBFUN and SOFIAPUBVAR to public include files in su module. * Not compiling tport_threadpool.c in win32. * Updated documentation in sip/sip_util.c. Updated sip_contact_create_from_via(), sip_contact_string_from_via(), and sip_contact_create_from_via_with_transport() documents. * Added _sips._udp SRV records to sresolv/example.com zonefile. Updated named.conf so it can be directly used to run bind. * Added public prototype for tport_is_dgram() into . * Added nta_outgoing_transport() to nta/nta.c and . * nua module: * Improved keepalive timeout handling in nua/nua_register.c. * Fixed double free in nua/nua_register.c. Let nua_stack_process_response() take care of removing REGISTER dialog usage. * Checking for Max-Forwards header and its contents in nua/test_proxy.c. * Fixed STUN_ERROR() macro in . * Fixed invalid check by nua_stack_init_instance() in nua/nua_params.c. * Updated nua/test_nua.c. Using nat by default. Added --symmetric and -N options, enabling symmetric nat and logging, respectively. * Added tags to nua/test_nat.[hc]. TESTNATTAG_SYMMETRIC(1) enables symmetric nat. TESTNATTAG_LOGGING(1) enables logging of nat binding changes. * Updated outbound protocol engine in nua/nua_register.c We enable rport and disable outbound by default. Fixed problem when nat binding was changed. Fixed syntax error problems when creating Accept-Contact header in OPTIONS request used to validate registration. * Added nua_generate_instance_identifier() to nua module. * Changed default values in nua_params.c. NUTAG_OUTBOUND() is "natify", and NUTAG_KEEPALIVE() is 120 seconds. * Fixed nua/test_proxy.c. Registrar was not returning all contacts in 200 OK to response to REGISTER. * iptsec module: * Added auc_copy_credentials(). Implementation in iptsec/auth_client.c, prototype in . Replaced msg_param_t with char const *, too. * Added SOFIAPUBFUN to auth_struct_copy(), too. * iptsec module (by Martti Mela): * ntlm support now compiles, not working. * added auth_ntlm.[ch] * more NTLM methods and header file auth_ntlm.h * still more ifdefs for NTLM enabling * added configure flag for enabling NTLM (disabled by default) * fixed gssapidatas * NTLM implementation continued. 2006-05-02 Pekka Pessi * iptsec module: * Updated headers in iptsec module. Added SOFIAPUBFUN and SOFIAPUBVAR where needed. Removed auc_with_uicc(). * Fixed memory management problems in iptsec module. The authenticator client in auth_client.c leaked memory when re-challenged. The client did not duplicate strings from challenge, and tried to use freed values after challenge was freed. Now we are actually running the tests in test_auth_digest.c, too. The problem was reported and patch submitted by Colin Whittaker. * sresolv module: * Updated sresolv API. Added sres_search() and sres_search_cached_answers() to the sresolv API. Added sres_blocking_search(). Added ignore_cache parameter to sres_blocking_query() and sres_blocking_query_sockaddr() prototypes. Renumbered SRES_TIMEOUT_ERR and SRES_RECORD_ERR so that they do not overlap with transaction signature errors. Added sres_record_type(). * Updated sresolv documentation. * Making cache threadsafe and locking it during sres_cache_store(). Problem reported by Thomas Rosenblatt. * Moved sip-dig from libsofia-sip-ua/sresolv/ to utils. * Updated utils/sip-dig.c manpage and -p option handling. * Added text about preloading and stack use to su/su_alloc.c. * Fixed handle leaks in nua_test.c. Added delay before nua_shutdown() in order to ease debugging. * Fixed nua handle reference counting problems in nua module. Problem reported by Colin Whittaker. * Updated documentation of auc_authorize() in iptsec/auth_client.c. * Added null pointer check to auc_authorize() in iptsec/auth_client.c. Patch proposed by Colin Whittaker. * Destroying session when initial INVITE is CANCELed. Patch proposed by Colin Whittaker. 2006-04-27 Pekka Pessi * sresolv module: Added SRESTAG_CACHE() to . Added ends0 and no-edns0 options in resolv.conf to sresolv/sres.c. Fixed sresolv #includes. Added #include and into sresolv/sres.c Added prerequisite #includes to sresolv files. Added @todo about cache poisoning. Updated sresolv documentation. Fixed bugs in sresolv/sres_blocking.c. Silenced printing spurious network errors in sresolv/sres.c. Added sres_is_blocking() to sres_blocking.c. Updated sres_resolver_get_async(), too. Added sip-dig.c to sresolv module. * tport module: Added missing "typedef" keyword to tport_pri_type_t in sofia-sip/tport_tag.h Fixed TPTAG_CONNECT() usage in tport/tport.c. Now running some SCTP tests in test_tport.c Updated tport_tls.c: - Not requiring client certificate in tls. - Tried to improve error handling, too. Now using stream-like sending semantics with SCTP. Updated datagram reception in tport_type_udp.c. We now avoid peeking and fussing around with message size, and simply allocate 64K buffer, receive(), then reduce the buffer size. Updated tport_recv_stun_dgram() in tport_stub_stun.c. Now using already received data within a msg_t. Updated SigComp interface in tport_stub_sigcomp.c and tport_sigcomp.c. Added a slot for stun handle to all primary transports. Changed tport_primary_t in tport_internal.h, updated tport_type_stun.c. Moved rest of the threadpool stuff into tport_threadpool.c. tport_threadpool.c does not work at the moment, disable it. Updated tport_connect() interface. Calling tport_alloc_seconary() when client socket has been created, making it possible to set socket options before connecting the socket. Currently, this benefits SCTP and TLS. This change affects tport_internal.h, tport.c, tport_type_sctp.c, tport_type_tcp.c, and tport_type_tls.c. Added TPORT_DLL to tport_keepalive(), too. Added tport_ref() and tport_unref() to tport module. Fixed bug #1473936 in tport/tport.c. tport_primary_by_name() now returns transports regardless of their protocol family if tpn->tpn_host is not a literal IP address. * msg module: Updated msg_recv_buffer() prototype. Reclaiming the un-committed part of buffer in msg/msg_parser.c. The allocation pattern for UDP has changed: now we allocate 64K, then realloc to the actual size. * nta module: Fixed bug #1472683 in nta/nta.c. The rport parameter was missing from ACK. The CANCEL had Via line with duplicate branch parameter. Fixed merge artifact in nta/test_nta_api.c. Always having NTATAG_SIGCOMP_OPTIONS() and storing its value. * nua module: Added explicit check for NULL pointers to unregister_expires_contacts(). Added missing events to nua.docs. More fixes to nua/nua_publish.c. nua_unpublish uses tags from initial nua_publish() 900 status is returned when there is no Expires header in 2XX response to PUBLISH. Re-indented nua_publish.c. Added better error checking to nua_creq_msg(). Fixed Service-Route header processing, too. Added nua_add_contact_by_aor() to nua_register.c. The nua_add_contact_by_aor() takes care of adding other registration-related headers like Service-Route, too. Moved nua_publish() documentation from nua.c/nua.docs to nua_publish.c. Updated documentation, added nua_r_unpublish documentation. Improved PUBLISH handling in nua/nua_publish.c. Saving the initial PUBLISH message along with message body and content type. They are re-used if 412 is received or if 2XX response contains Expires: 0. If 2XX response is received without Expires header, we report internal error to application. Fixed route handling in SUBSCRIBE in the file nua/nua_subnotref.c. There was a problem using dialog route set when there was an initial route original SUBSCRIBE. * Updated copyright year in sofia-footer.html.in. * Fixed prototype of host_is_domain(). * Fixed doxygen warnings in su module. * Updated sofia-sip.spec.in. Separated glib library to sofia-sip-glib and sofia-sip-glib-devel packages. Added sofia-sip-docs package. * Added su_timer_set_interval() to su/su_timer.c and sofia-sip/su_wait.h. * Defining __func__ in stun/stunc.c for the benefit of older C compilers. * Removed // comments. 2006-04-25 Pekka Pessi * Added compilation and run-time checks for MSG_TRUNC. M ./libsofia-sip-ua/tport/tport_internal.h -2 +3 M ./libsofia-sip-ua/tport/tport_threadpool.c -1 +1 M ./libsofia-sip-ua/tport/tport_type_udp.c -4 +34 M ./m4/sac-su2.m4 +5 * Fixed #includes in sresolv files. M ./libsofia-sip-ua/sresolv/sres_blocking.c +2 M ./libsofia-sip-ua/sresolv/sres_cache.c +3 M ./libsofia-sip-ua/sresolv/test_sresolv.c +9 * Fixed syntax error with G_DEFINE_TYPE(NuaGlib). M ./libsofia-sip-ua-glib/nua-glib/nua_glib.c -1 +1 * Added --with sctp and --without glib to sofia-sip.spec.in. M ./packages/sofia-sip.spec.in -3 +10 * Renumbered test case NUA-9.1.2 in test_nua.c M ./libsofia-sip-ua/nua/test_nua.c -2 +2 2006-04-20 Pekka Pessi * Not trying to set up stun transport unless we have stun server configured. Files: nua/nua_register.c. M ./libsofia-sip-ua/nua/Makefile.am +1 M ./libsofia-sip-ua/nua/nua_register.c -6 +16 * Fixed auth-int authentication for INVITE requests. Files: nua/nua_stack.c, nua/nua_session.c, iptsec/auth_client.c. M ./libsofia-sip-ua/iptsec/auth_client.c +6 M ./libsofia-sip-ua/nua/nua_stack.c -4 +5 * Added outbound_connect_gruuize() - generate gruu from gruu paramter in our contact. File: nua/nua_register.c. M ./libsofia-sip-ua/nua/nua_register.c +53 * Added "SSL_VERIFY_PEER" environment variable. M ./libsofia-sip-ua/tport/tport_tls.c -2 +2 * Restored SCTP in tport_type_sctp.c. Increased maximum message size to 64 K. M ./libsofia-sip-ua/tport/tport_type_sctp.c -7 +7 * Using SSL_VERIFY_NONE - do not ask for client certificate. It looks like openssl does not allow for client not to have certificate. M ./libsofia-sip-ua/tport/tport_tls.c -1 +2 * More memory management problems in stun. M ./libsofia-sip-ua/stun/stun_common.c -1 +1 * Fixed memory management problems in stun. M ./libsofia-sip-ua/stun/stun.c -1 * Fixed blunder in error record creation. sres_create_error_rr() in in sres.c. M ./libsofia-sip-ua/sresolv/sres.c -2 +4 * Using outbound keepalive interval of 15 seconds. outbound_connect_start_keepalive() in nua/nua_register.c M ./libsofia-sip-ua/nua/nua_register.c -2 +1 * Added nta_agent_init_sigcomp() and nta_agent_deinit_sigcomp(). M ./libsofia-sip-ua/nta/nta.c -3 +28 M ./libsofia-sip-ua/nta/nta_internal.h -9 +21 * Renamed tport_try_accept_sigcomp() as tport_sigcomp_accept_incomplete(). M ./libsofia-sip-ua/tport/tport.c -1 +1 M ./libsofia-sip-ua/tport/tport_internal.h -1 +1 M ./libsofia-sip-ua/tport/tport_stub_sigcomp.c -1 +1 * Maded tport stun plugin pointer private. M ./libsofia-sip-ua/tport/tport_stub_stun.c -2 +7 * Updated SCTP semantics to use "TCP". M ./libsofia-sip-ua/tport/tport.c -3 +8 M ./libsofia-sip-ua/tport/tport_type_sctp.c -6 +20 * Fixed C++ compilation on . * Fixed outbound problems. Not unregistering contacts with instance-id and reg-id. Avoiding crash when processing timeout responses. M ./libsofia-sip-ua/nua/nua_register.c -16 +31 * Addeed --enable-sctp. M ./m4/sac-tport.m4 -4 +6 M ./packages/sofia-sip.spec.in +1 * Updated compression interface in tport. Added tport_compressor_t type, tport_delivered_with_comp(). Removed tpac_sigcomp_accept() and tport_delivered_using_udvm(). M ./libsofia-sip-ua/tport/sofia-sip/tport.h -10 +8 M ./libsofia-sip-ua/tport/sofia-sip/tport_plugins.h -6 +93 M ./libsofia-sip-ua/tport/tport.c -24 +11 M ./libsofia-sip-ua/tport/tport_internal.h -15 +10 M ./libsofia-sip-ua/tport/tport_stub_sigcomp.c -114 +53 * Removed direct SigComp stuff from nta.c. Added nta_compressor_vtable. M ./libsofia-sip-ua/nta/nta.c -209 +100 M ./libsofia-sip-ua/nta/nta_internal.h +33 * Fixed aor/tport handling for sip/sips cases. M ./libsofia-sip-ua/nua/nua_register.c -4 +13 * Disabled ntlm client for now. 2006-04-17 Pekka Pessi * Removed - from ntlm variable names (mp) M ./libsofia-sip-ua/iptsec/auth_module.c -11 +11 M ./libsofia-sip-ua/iptsec/sofia-sip/auth_plugin.h -1 +1 * Fixed --without-sigcomp (mp) M ./m4/sac-tport.m4 -1 +1 * iptsec: started NTLM support (mm) M ./libsofia-sip-ua/iptsec/auth_client.c +9 M ./libsofia-sip-ua/iptsec/auth_module.c +390 M ./libsofia-sip-ua/iptsec/sofia-sip/auth_plugin.h +7 * Changed internal nua error responses to use 9XX status codes. M ./libsofia-sip-ua/nua/nua_event_server.c -9 +10 M ./libsofia-sip-ua/nua/nua_message.c -4 +4 M ./libsofia-sip-ua/nua/nua_options.c -3 +3 M ./libsofia-sip-ua/nua/nua_params.c -3 +3 M ./libsofia-sip-ua/nua/nua_publish.c -5 +5 M ./libsofia-sip-ua/nua/nua_register.c -6 +6 M ./libsofia-sip-ua/nua/nua_session.c -29 +30 M ./libsofia-sip-ua/nua/nua_stack.c -2 +4 M ./libsofia-sip-ua/nua/nua_stack.h -2 +2 M ./libsofia-sip-ua/nua/nua_subnotref.c -5 +7 * Added test for some of the internal errors. M ./libsofia-sip-ua/nua/test_nua.c +138 * Fixed NTA API test for SigComp options (they are now always processed). M ./libsofia-sip-ua/nta/test_nta_api.c -8 +4 * Added missing #includes to sres.c. * Removed experimental code enabling STUN. M ./libsofia-sip-ua/tport/tport.c -5 * Added su_init()/su_deinit() here. M ./libsofia-sip-ua/tport/test_tport.c -1 +5 * Removed some warnings (and fixed a bug) in encoding functions ofb stun_common.c M ./libsofia-sip-ua/stun/stun_common.c -9 +11 * Removed stupid VC98 warning from tport_threadpool.c M ./libsofia-sip-ua/tport/tport_threadpool.c -1 +1 * Added missing __func__ to tport_type_tcp and tport_threadpool.c. M ./libsofia-sip-ua/tport/tport.c -1 +1 M ./libsofia-sip-ua/tport/tport_threadpool.c +7 M ./libsofia-sip-ua/tport/tport_type_tcp.c +7 * Added inlined IN6_IS_ADDR_LOOPBACK() to su_localinfo.c. M ./libsofia-sip-ua/su/su_localinfo.c +16 * Fixed pointer artithmetics by memccpy() in su_strcat_all(). (function in su/su_strdup.c). * Added missing Winsock errors to * Fixed address scoping error in stun_mini.c. * Added missing __func__ to stun C files. * Added things missing from win32 to new sresolv modules. M ./libsofia-sip-ua/sresolv/sres.c -5 +35 M ./libsofia-sip-ua/sresolv/sres_blocking.c -4 +28 M ./libsofia-sip-ua/sresolv/sres_cache.c -1 +9 * Fixed C99ism in nua_register.c M ./libsofia-sip-ua/nua/nua_register.c -1 +3 * Removed automatically generated file tport_tag_ref.c from version control system. R ./libsofia-sip-ua/tport/tport_tag_ref.c 2006-04-11 Kai Vehmanen Synchronizing CVS with darcs (other contributors pp = Pekka Pessi, mm = Martti Mela). * NDEBUG oops. (pp) M ./libsofia-sip-ua/sresolv/sres.c -1 +1 * Added sres_resolver_copy(). (pp) Storing application-provided option strings in res_options. Removed warnigns. M ./libsofia-sip-ua/sresolv/sofia-resolv/sres.h +3 M ./libsofia-sip-ua/sresolv/sres.c -9 +90 M ./libsofia-sip-ua/sresolv/test_sresolv.c -1 +1 * Fixed stun miniserver (and stun stub in tport). (pp) M ./libsofia-sip-ua/stun/stun_common.c -12 +7 M ./libsofia-sip-ua/stun/stun_mini.c -4 +4 M ./libsofia-sip-ua/tport/tport_stub_stun.c -1 +1 * Updated copyrights for nua-glib. M ./COPYRIGHTS -1 +2 M ./libsofia-sip-ua-glib/nua-glib/nua_glib.c +2 M ./libsofia-sip-ua-glib/nua-glib/sofia-sip/nua_glib.h -1 +2 * Fixed segfault with stun_handle_destroy() on a NULL handle. M ./libsofia-sip-ua/tport/tport_type_stun.c -1 +2 * Updated RELEASE. (pp) M ./RELEASE -4 +13 * Disabled SIGCOMP until tport plugin is ready. (pp) Handling sigcomp options regarless of HAVE_SIGCOMP value. M ./libsofia-sip-ua/nta/nta.c -27 +30 * Added stun server and compression plugins. (pp) Added TPORT_STUN_SERVER(). Having stun server dependencies in . Moved sigcomp dependencies into . M ./libsofia-sip-ua/tport/Makefile.am -1 +3 M ./libsofia-sip-ua/tport/sofia-sip/tport.h -23 +15 A ./libsofia-sip-ua/tport/sofia-sip/tport_plugins.h M ./libsofia-sip-ua/tport/sofia-sip/tport_tag.h +7 M ./libsofia-sip-ua/tport/test_tport.c -2 +3 M ./libsofia-sip-ua/tport/tport.c -136 +82 M ./libsofia-sip-ua/tport/tport_internal.h -35 +72 M ./libsofia-sip-ua/tport/tport_sigcomp.c -150 +193 A ./libsofia-sip-ua/tport/tport_stub_sigcomp.c A ./libsofia-sip-ua/tport/tport_stub_stun.c M ./libsofia-sip-ua/tport/tport_tag.c +1 M ./libsofia-sip-ua/tport/tport_tag_ref.c +3 M ./libsofia-sip-ua/tport/tport_type_stun.c -3 +21 M ./libsofia-sip-ua/tport/tport_type_udp.c -144 +4 * http_add_tl() now accepts NULL http struct pointer. (pp) M ./libsofia-sip-ua/http/http_tag_class.c -1 +3 * Update documentation of msg_copy() and msg_dup(). (pp) M ./libsofia-sip-ua/msg/msg_header_copy.c -4 +7 * Removed some HAVE_SIGCOMP code. (pp) M ./libsofia-sip-ua/nta/nta.c -42 +13 M ./libsofia-sip-ua/nta/nta_internal.h -9 +2 * Added su_sockaddr_scope(). (pp) Using su_sockaddr_scope() in stun_mini.c. M ./libsofia-sip-ua/stun/stun_mini.c -15 +38 M ./libsofia-sip-ua/su/sofia-sip/su_localinfo.h +3 M ./libsofia-sip-ua/su/su_localinfo.c -1 +18 * Fixed nat testing code. (pp) M ./libsofia-sip-ua/nua/test_nat.c -4 +2 M ./libsofia-sip-ua/nua/test_nua.c +1 * Updated stack initialization. (pp) Transports are initialized by nua_stack_init_transport() in nua_register.c. UICC (you don't want to know) is initialized by nua_stack_set_from() in nua_params.c. M ./libsofia-sip-ua/nua/nua_params.c -4 +15 M ./libsofia-sip-ua/nua/nua_register.c -1 +70 M ./libsofia-sip-ua/nua/nua_stack.c -54 +18 M ./libsofia-sip-ua/nua/nua_stack.h -2 +4 M ./libsofia-sip-ua/nua/nua_tag.c -2 M ./libsofia-sip-ua/nua/sofia-sip/nua_tag.h -7 +6 * Fixed su_root_run() usage in docs. (pp) Thanks for hint by Julio Auto. M ./libsofia-sip-ua/nua/nua.docs -1 +1 * Fixed allocation bug. (pp) M ./libsofia-sip-ua/sresolv/test_sresolv.c -4 +3 * Change version back to 1.11.7work. M ./configure.ac -1 +1 * Changed outbound_connect_nat_detect() prototype. (pp) M ./libsofia-sip-ua/nua/nua_register.c -7 +11 * Removed obsoleted nua events. (pp) Removed nua events nua_i_media_event, nua_r_set_media_param, nua_r_get_media_param, nua_r_media_setup, nua_r_media_describe, nua_r_media_event, nua_i_announce, nua_i_describe, nua_i_get_parameter, nua_i_pause, nua_i_options2, nua_i_play, nua_i_record, nua_i_set_parameter, nua_i_setup, nua_i_teardown, nua_r_setup, nua_r_play, nua_r_record, nua_r_pause, nua_r_describe, nua_r_teardown, nua_r_options2, nua_r_announce, nua_r_get_parameter, and nua_r_set_parameter. Removed nua functions nua_announce(), nua_describe(), nua_get_media_param(), nua_get_parameter(), nua_media_describe(), nua_media_event(), nua_media_setup(), nua_options2(), nua_pause(), nua_play(), nua_record(), nua_set_media_param(), nua_set_parameter(), nua_setup(), and nua_teardown(), M ./libsofia-sip-ua/nua/sofia-sip/nua.h -33 * Moved preference/parameter setting/getting into its own nua_params.c module. (pp) M ./libsofia-sip-ua/nua/Makefile.am +1 M ./libsofia-sip-ua/nua/nua.c -140 A ./libsofia-sip-ua/nua/nua_params.c A ./libsofia-sip-ua/nua/nua_params.h M ./libsofia-sip-ua/nua/nua_stack.c -661 +42 M ./libsofia-sip-ua/nua/nua_stack.h -125 +10 M ./libsofia-sip-ua/nua/nua_tag.c -6 +9 M ./libsofia-sip-ua/nua/sofia-sip/nua_tag.h -24 +74 M ./libsofia-sip-ua/nua/test_nua.c -1 +24 * Removed obsoleted functions from nua. (pp) M ./libsofia-sip-ua/nua/nua.c -110 M ./libsofia-sip-ua/nua/sofia-sip/nua.h -54 * Updated documentation in nua. (pp) M ./libsofia-sip-ua/nua/Doxyfile -2 +2 M ./libsofia-sip-ua/nua/nua.c -68 +24 M ./libsofia-sip-ua/nua/nua.docs -27 +2 M ./libsofia-sip-ua/nua/nua_common.c -4 +4 M ./libsofia-sip-ua/nua/nua_dialog.c -12 +17 M ./libsofia-sip-ua/nua/nua_dialog.h -1 +1 M ./libsofia-sip-ua/nua/nua_event_server.c -14 +15 M ./libsofia-sip-ua/nua/nua_options.c -2 +2 M ./libsofia-sip-ua/nua/nua_register.c -22 +190 M ./libsofia-sip-ua/nua/nua_session.c -6 +7 M ./libsofia-sip-ua/nua/nua_stack.c -22 +31 M ./libsofia-sip-ua/nua/nua_stack.h -11 +1 M ./libsofia-sip-ua/nua/nua_subnotref.c -3 +3 * stun: fixed mem leaks with valgrind (mm) M ./libsofia-sip-ua/stun/sofia-sip/stun.h -1 +3 M ./libsofia-sip-ua/stun/stun.c -5 +50 M ./libsofia-sip-ua/stun/stun_common.c -12 +38 M ./libsofia-sip-ua/stun/stunc.c -8 +9 * changed tport to use stun_discovery_done instead of stun_bind_done (mm) M ./libsofia-sip-ua/tport/tport_type_stun.c -1 +1 * removed stun_bind_ enums and replaced with stun_discovery_ scheisse (mm) M ./libsofia-sip-ua/stun/sofia-sip/stun.h +5 M ./libsofia-sip-ua/stun/stun.c -6 +8 M ./libsofia-sip-ua/stun/stunc.c -3 +4 * Added test for su_home_unref()ing a cloned home. (pp) M ./libsofia-sip-ua/su/su_alloc_test.c -9 +13 M ./libsofia-sip-ua/su/su_strlst.c -2 +8 * Added new sresolv headers to packages. (pp) M ./libsofia-sip-ua/sresolv/Makefile.am -1 +6 M ./packages/sofia-sip.spec.in +1 * Update version to 1.11.8work as per new release guidelines. M ./configure.ac -1 +1 * Signal stun_error to the client if STUN DNS-SRV lookup is started but fails. M ./libsofia-sip-ua/stun/stun.c -36 +41 * Fixed stun compilation. M ./libsofia-sip-ua/stun/stun.c -3 +6 * Fixed operations on Transaction-ID. TID is a 128bit opaque value. M ./libsofia-sip-ua/stun/sofia-sip/stun_common.h +2 M ./libsofia-sip-ua/stun/stun.c -10 +8 M ./libsofia-sip-ua/stun/stun_common.c -2 +2 * Removed ssl headers from stun_common.h. Public headers should not have config.h dependent sections. M ./libsofia-sip-ua/stun/sofia-sip/stun_common.h -9 M ./libsofia-sip-ua/stun/stun_internal.h +9 * tls somehow works now (mm) M ./libsofia-sip-ua/stun/stun.c -2 +5 * updated stunc with cool features & cleanup. Removed stun_request_t from public callbacks (mm) M ./libsofia-sip-ua/stun/sofia-sip/stun.h -2 M ./libsofia-sip-ua/stun/stun.c -33 +69 M ./libsofia-sip-ua/stun/stun_internal.h +1 M ./libsofia-sip-ua/stun/stunc.c -99 +140 * Using HAVE_CONFIG_H. (pp) M ./libsofia-sip-ua/stun/stun_common.c -2 +2 * Added test for . (pp) Removed HAVE_SU_WAIT_H - nobody is using it anymore. M ./m4/sac-su2.m4 -12 +4 * Updated win32/config.h.in. (pp) M ./win32/config.h.in -7 +67 * Updated (for testing stun). (pp) M ./libsofia-sip-ua/nua/test_nat.c -175 +183 * Added quick hack for using stun. (pp) M ./libsofia-sip-ua/tport/tport.c +7 * Updated tport_stun_bind_done(). (pp) M ./libsofia-sip-ua/tport/tport_type_stun.c -11 +9 * No need to define HAVE_SU_WAIT_H. (pp) M ./libsofia-sip-ua/stun/stun_dns.c -1 * Update documents. (pp) M ./libsofia-sip-ua/sresolv/resolve_sip.c -1 +1 M ./libsofia-sip-ua/sresolv/sres.c -5 +9 M ./libsofia-sip-ua/sresolv/sres_blocking.c -4 +9 M ./libsofia-sip-ua/sresolv/sres_cache.c -4 +39 M ./libsofia-sip-ua/sresolv/sresolv.c +34 M ./libsofia-sip-ua/sresolv/test_sresolv.c -3 +8 * stunc works, kikkelis kokkelis!! (mm) M ./libsofia-sip-ua/stun/sofia-sip/stun.h -1 +3 M ./libsofia-sip-ua/stun/stun.c -5 +19 M ./libsofia-sip-ua/stun/stunc.c -50 +169 * Added stun_mini_t. (pp) M ./libsofia-sip-ua/stun/Makefile.am -1 +1 M ./libsofia-sip-ua/stun/sofia-sip/stun.h -4 +19 A ./libsofia-sip-ua/stun/stun_mini.c * Updated stun todo-file in stun.docs. M ./libsofia-sip-ua/stun/stun.docs -4 +1 * Also mark deprecated typedefs and defines. M ./libsofia-sip-ua/stun/sofia-sip/stun.h -9 +9 * Adds interface to query active primary server address. M ./libsofia-sip-ua/stun/sofia-sip/stun.h +1 M ./libsofia-sip-ua/stun/stun.c -30 +39 M ./libsofia-sip-ua/stun/stun_internal.h -1 +1 * Minor update to STUN DNS-SRV interface. M ./libsofia-sip-ua/stun/ChangeLog +4 M ./libsofia-sip-ua/stun/lookup_stun_server.c -17 +31 M ./libsofia-sip-ua/stun/sofia-sip/stun.h -5 +4 M ./libsofia-sip-ua/stun/stun.c -3 +4 M ./libsofia-sip-ua/stun/stun_dns.c -34 +67 * Using updated tport_keepalive() prototype. (pp) M ./libsofia-sip-ua/nta/nta.c -1 +2 * Added STUN tport. (pp) Moved upnp stuff to its own file. M ./libsofia-sip-ua/tport/Makefile.am -3 +3 M ./libsofia-sip-ua/tport/tport.c +1 M ./libsofia-sip-ua/tport/tport_type_stun.c -422 +88 * Updated tport_keepalive() prototype. (pp) Implemented tport_is_updating(), added tport_has_been_updated(). M ./libsofia-sip-ua/tport/sofia-sip/tport.h -1 +2 M ./libsofia-sip-ua/tport/tport.c -8 +40 M ./libsofia-sip-ua/tport/tport_internal.h -5 +10 M ./libsofia-sip-ua/tport/tport_threadpool.c -2 +2 M ./libsofia-sip-ua/tport/tport_type_connect.c -2 +2 M ./libsofia-sip-ua/tport/tport_type_sctp.c -4 +4 M ./libsofia-sip-ua/tport/tport_type_tcp.c -2 +2 M ./libsofia-sip-ua/tport/tport_type_tls.c -6 +6 M ./libsofia-sip-ua/tport/tport_type_udp.c -1 +1 * Removed torture_stun.c. M ./libsofia-sip-ua/stun/Makefile.am -10 +1 R ./libsofia-sip-ua/stun/torture_stun.c * Fix STUNTAG_DOMAIN with test_nattype and test_lifetime processes. M ./libsofia-sip-ua/stun/stun.c -7 +28 * Renamed all get_nattype and get_lifetime functions and enums to test_nattype and test_lifetime. M ./libsofia-sip-ua/stun/ChangeLog +4 M ./libsofia-sip-ua/stun/sofia-sip/stun.h -14 +8 M ./libsofia-sip-ua/stun/stun.c -52 +30 M ./libsofia-sip-ua/stun/stunc.c -6 +9 * Moved deprecated functions at the end of stun.c. Fixed postponing shared-secret and bind discovery processes for DNS-SRV lookups. M ./libsofia-sip-ua/stun/stun.c -159 +172 * stun_request_shared_secret() renamed to stun_obtain_shared_secret(). M ./libsofia-sip-ua/stun/sofia-sip/stun.h -4 +1 * stun.h: Deprecated stun_handle_release(). M ./libsofia-sip-ua/stun/ChangeLog -3 +4 M ./libsofia-sip-ua/stun/sofia-sip/stun.h -1 +2 * tag list stored for stun_obtain_shared_secret (mm) M ./libsofia-sip-ua/stun/stun.c -1 +11 * non-compiling: need args for stun_obtain_shared_secret() (mm) M ./libsofia-sip-ua/stun/stun.c -1 +1 * stun api upd's also for tls; tport (mm) M ./libsofia-sip-ua/stun/sofia-sip/stun.h -4 +14 M ./libsofia-sip-ua/stun/sofia-sip/stun_tag.h -4 +4 M ./libsofia-sip-ua/stun/stun.c -17 +150 M ./libsofia-sip-ua/stun/stun_common.c -3 +5 M ./libsofia-sip-ua/stun/stun_tag.c -8 +9 M ./libsofia-sip-ua/tport/tport_type_stun.c -5 +5 * Removed separate virtual function for compression initialization. (pp) M ./libsofia-sip-ua/tport/tport.c -3 M ./libsofia-sip-ua/tport/tport_internal.h -2 M ./libsofia-sip-ua/tport/tport_sigcomp.c -2 M ./libsofia-sip-ua/tport/tport_threadpool.c -1 M ./libsofia-sip-ua/tport/tport_type_connect.c -1 M ./libsofia-sip-ua/tport/tport_type_sctp.c -2 M ./libsofia-sip-ua/tport/tport_type_stun.c -4 +3 M ./libsofia-sip-ua/tport/tport_type_tcp.c -2 M ./libsofia-sip-ua/tport/tport_type_tls.c -2 M ./libsofia-sip-ua/tport/tport_type_udp.c -2 * Added su_socket() wrapper function. (pp) M ./libsofia-sip-ua/su/sofia-sip/su.h -2 M ./libsofia-sip-ua/su/su.c -6 +12 * Removee v-p from the vtable names. (pp) M ./libsofia-sip-ua/tport/tport.c -20 +20 M ./libsofia-sip-ua/tport/tport_internal.h -11 +11 M ./libsofia-sip-ua/tport/tport_threadpool.c -1 +1 M ./libsofia-sip-ua/tport/tport_type_connect.c -4 +1 M ./libsofia-sip-ua/tport/tport_type_sctp.c -2 +2 M ./libsofia-sip-ua/tport/tport_type_stun.c -1 +1 M ./libsofia-sip-ua/tport/tport_type_tcp.c -2 +2 M ./libsofia-sip-ua/tport/tport_type_tls.c -2 +2 M ./libsofia-sip-ua/tport/tport_type_udp.c -2 +2 * Removed temp test program from sresolv. (pp) M ./libsofia-sip-ua/sresolv/Makefile.am -2 +1 * Added 3.f.f.e.1.2.0.0.3.0.1.2.c.0.0.0.arpa. (pp) A ./libsofia-sip-ua/sresolv/3.f.f.e.1.2.0.0.3.0.1.2.c.0.0.0.arpa M ./libsofia-sip-ua/sresolv/Makefile.am -1 +2 * Added notes to RELEASE. (pp) M ./RELEASE +17 * Sanitized stun_common.[hc] slightly. (pp) M ./libsofia-sip-ua/stun/sofia-sip/stun_common.h -1 +1 M ./libsofia-sip-ua/stun/stun_common.c -45 +53 * Added notes about string and header manipulation function. (pp) M! ./RELEASE -10 * Fixed problem with initial un-REGISTER by test_nua.c in test_proxy.c (pp) M ./libsofia-sip-ua/nua/test_proxy.c -4 +7 * Fixed problems with updated API. Added sres_resolver_update(). (pp) M ./libsofia-sip-ua/sresolv/Makefile.am -1 +2 M ./libsofia-sip-ua/sresolv/sofia-resolv/sres.h -55 +21 A ./libsofia-sip-ua/sresolv/sofia-resolv/sres_async.h M ./libsofia-sip-ua/sresolv/sofia-sip/sresolv.h -2 +3 M ./libsofia-sip-ua/sresolv/sres.c -17 +37 M ./libsofia-sip-ua/sresolv/sres_blocking.c +1 M ./libsofia-sip-ua/sresolv/sresolv.c -36 +52 M ./libsofia-sip-ua/sresolv/test_sresolv.c -2 +2 * Fixed AC_CHECK_HEADERS depending on . (pp) M ./m4/sac-su2.m4 -1 +3 * Fixed HAVE_SOCKADDR_LL in case we have . (pp) M ./libsofia-sip-ua/su/su_uniqueid.c -1 +1 * Fixed su_timer_set_for_ever(). (pp) M ./libsofia-sip-ua/su/su_timer.c -6 +9 * Fixed stupid bug with su_home_desctructor(). (pp) M ./libsofia-sip-ua/su/su_alloc.c +10 M ./libsofia-sip-ua/su/su_alloc_test.c -2 +13 * New API working with test program. (pp) M ./libsofia-sip-ua/sresolv/Makefile.am -1 +1 M ./libsofia-sip-ua/sresolv/run_test_sresolv +5 M ./libsofia-sip-ua/sresolv/sofia-resolv/sres.h -15 +62 M ./libsofia-sip-ua/sresolv/sofia-resolv/sres_cache.h -1 +1 M ./libsofia-sip-ua/sresolv/sofia-sip/sresolv.h -14 +1 M ./libsofia-sip-ua/sresolv/sres.c -143 +237 A ./libsofia-sip-ua/sresolv/sres_blocking.c M ./libsofia-sip-ua/sresolv/sres_cache.c -2 +2 M ./libsofia-sip-ua/sresolv/sresolv.c -56 +57 M ./libsofia-sip-ua/sresolv/test_sresolv.c -198 +117 * Initial change for multithreaded and synchronous resolver (pp) ./libsofia-sip-ua/sresolv/sofia-sip/sresolv.h -> ./libsofia-sip-ua/sresolv/sofia-resolv/sres.h ./libsofia-sip-ua/sresolv/sresolv.c -> ./libsofia-sip-ua/sresolv/sres.c M ./libsofia-sip-ua/sresolv/Makefile.am -1 +1 A ./libsofia-sip-ua/sresolv/sofia-resolv/ M ./libsofia-sip-ua/sresolv/sofia-resolv/sres.h -259 +90 A ./libsofia-sip-ua/sresolv/sofia-resolv/sres_cache.h A ./libsofia-sip-ua/sresolv/sofia-resolv/sres_record.h A ./libsofia-sip-ua/sresolv/sofia-sip/sresolv.h M ./libsofia-sip-ua/sresolv/sres.c -1075 +852 A ./libsofia-sip-ua/sresolv/sres_cache.c A ./libsofia-sip-ua/sresolv/sresolv.c M ./libsofia-sip-ua/sresolv/sresolv.docs -7 +71 M ./libsofia-sip-ua/sresolv/test_sresolv.c -29 +20 * Fixed make top-level rules for manpage creation when doxygen is not installed. M ./Makefile.am -1 +1 * Abort connect timer if socket connect() refused. M ./libsofia-sip-ua/stun/stun.c -7 +5 * Updated nua_stack_tport_update(). (pp) M ./libsofia-sip-ua/nua/nua_register.c -6 +6 * Renamed register_usage as outbound_connect. (pp) Added tags NUTAG_OUTBOUND(), NUTAG_OUTBOUND_SET1(), NUTAG_OUTBOUND_SET2(), NUTAG_OUTBOUND_SET3(), and NUTAG_OUTBOUND_SET4(). M ./libsofia-sip-ua/nua/nua_options.c -3 +4 M ./libsofia-sip-ua/nua/nua_register.c -363 +498 M ./libsofia-sip-ua/nua/nua_stack.c -3 +11 M ./libsofia-sip-ua/nua/nua_stack.h -10 +8 M ./libsofia-sip-ua/nua/nua_tag.c +6 M ./libsofia-sip-ua/nua/sofia-sip/nua_tag.h +110 * Added usage_peer_info method to dialog usage. (pp) M ./libsofia-sip-ua/nua/nua_dialog.c +6 M ./libsofia-sip-ua/nua/nua_dialog.h +3 * Added possibility to run tests with external proxy. (pp) M ./libsofia-sip-ua/nua/test_nua.c -37 +98 * Added auth_status_init_with(), as_profile and as_alt_uri. (pp) M ./libsofia-sip-ua/iptsec/auth_module.c -4 +16 M ./libsofia-sip-ua/iptsec/sofia-sip/auth_module.h -2 +12 * Fixed url_param(). (pp) M ./libsofia-sip-ua/url/url.c -9 +18 * Use "_" instead of "+" in token64_e(). (pp) M ./libsofia-sip-ua/ipt/token64.c -3 +3 * Added tport with HTTP CONNECT, too. (pp) A ./libsofia-sip-ua/tport/tport_type_connect.c * Split tport.c into multiple modules. (pp) STUN, UPnP and SigComp still need some polishing. M ./libsofia-sip-ua/tport/Makefile.am -3 +7 M ./libsofia-sip-ua/tport/test_tport.c -13 +11 M ./libsofia-sip-ua/tport/tport.c -4114 +156 A ./libsofia-sip-ua/tport/tport_internal.h A ./libsofia-sip-ua/tport/tport_logging.c A ./libsofia-sip-ua/tport/tport_sigcomp.c A ./libsofia-sip-ua/tport/tport_tag_ref.c A ./libsofia-sip-ua/tport/tport_threadpool.c A ./libsofia-sip-ua/tport/tport_type_sctp.c A ./libsofia-sip-ua/tport/tport_type_stun.c A ./libsofia-sip-ua/tport/tport_type_tcp.c A ./libsofia-sip-ua/tport/tport_type_tls.c A ./libsofia-sip-ua/tport/tport_type_udp.c * Completed HTTP CONNECT. (pp) Added --http-proxy to sip-options. M ./libsofia-sip-ua/tport/sofia-sip/tport_tag.h +1 M ./libsofia-sip-ua/tport/tport.c -11 +55 M ./utils/sip-options.c -1 +6 * Generating Contact from public vias if no local Vias are available. (pp) M ./libsofia-sip-ua/nta/nta.c -3 +11 * Added HTTP CONNECT. (pp) M ./libsofia-sip-ua/tport/tport.c -682 +981 * Added http to LDADD and INCLUDE. (pp) M ./libsofia-sip-ua/nea/Makefile.am -1 +2 M ./libsofia-sip-ua/nta/Makefile.am +1 M ./libsofia-sip-ua/nua/Makefile.am -1 +1 M ./libsofia-sip-ua/tport/Makefile.am +2 * Clean up timers upon destroy in stun. M ./libsofia-sip-ua/stun/stun.c -9 +20 * Fixed typo in stun. M ./libsofia-sip-ua/stun/stun.c -1 +1 * Adding Vias belonging to public transport to sa_public_vias list. Now testing nta_agent_public_via(), too. (pp) M ./libsofia-sip-ua/nta/Makefile.am +1 M ./libsofia-sip-ua/nta/nta.c -26 +63 M ./libsofia-sip-ua/nta/test_nta_api.c -1 +14 * Using tport_tcreate() instead of tport_create(). (pp) M ./libsofia-sip-ua/nth/nth_client.c -1 +1 * Added vtables for transports. (pp) API: tport_is_public(). M ./libsofia-sip-ua/tport/sofia-sip/tport.h -7 +3 M ./libsofia-sip-ua/tport/sofia-sip/tport_tag.h -1 +14 M ./libsofia-sip-ua/tport/test_tport.c +7 M ./libsofia-sip-ua/tport/tport.c -1069 +1136 M ./libsofia-sip-ua/tport/tport_tls.c -43 +22 * STUN documentation update - no functional changes. (pp) M ./libsofia-sip-ua/stun/sofia-sip/stun.h -39 +31 M ./libsofia-sip-ua/stun/stun.c -26 +30 * Fixed bugs STUN DNS-SRV implementation. (pp) M ./libsofia-sip-ua/stun/stun.c -20 +38 * restructured nat scheisse in tport, nta, nua. Lost weight for about 200 lines. (mm) M ./libsofia-sip-ua/nta/nta.c -4 M ./libsofia-sip-ua/nua/nua_stack.c +4 M ./libsofia-sip-ua/tport/sofia-sip/tport.h +8 M ./libsofia-sip-ua/tport/sofia-sip/tport_tag.h +7 M ./libsofia-sip-ua/tport/tport.c -62 +38 M ./libsofia-sip-ua/tport/tport_tag.c +1 * initial support for dynamic address changes for register (mm) M ./libsofia-sip-ua/nua/nua_register.c +18 M ./libsofia-sip-ua/tport/sofia-sip/tport_tag.h +7 M ./libsofia-sip-ua/tport/tport.c -76 +136 M ./libsofia-sip-ua/tport/tport_tag.c +1 * updated RELEASE (pp) M ./RELEASE +9 * Cleanup STUN headers. M ./libsofia-sip-ua/stun/sofia-sip/stun.h -10 +3 M ./libsofia-sip-ua/stun/stun.c -1 +3 M ./libsofia-sip-ua/stun/stun_dns.c -1 * Added initial DNS-SRV lookup support to stun. M ./libsofia-sip-ua/nth/Makefile.am +1 M ./libsofia-sip-ua/stun/Makefile.am +1 M ./libsofia-sip-ua/stun/sofia-sip/stun.h -14 +17 M ./libsofia-sip-ua/stun/stun.c -82 +196 M ./libsofia-sip-ua/stun/stun_dns.c +9 M ./libsofia-sip-ua/tport/Makefile.am +1 * Add direct doxygen links to the public STUN APIs. M ./libsofia-sip-ua/stun/stun.docs -4 +8 * The correct tcp service name for STUN server discovery is 'stun', not 'stun-tls'. M ./libsofia-sip-ua/stun/lookup_stun_server.c -1 +1 M ./libsofia-sip-ua/stun/stun_dns.c -6 +6 * Fixed manpage generation rule to work with automake-1.8.5. M ./Makefile.am -1 +1 * updated STUN API, tport-stun-http mods in progress (mm) M ./libsofia-sip-ua/nta/nta.c -1 +1 M ./libsofia-sip-ua/stun/sofia-sip/stun.h -24 +74 M ./libsofia-sip-ua/stun/stun.c -23 +101 M ./libsofia-sip-ua/stun/stunc.c -4 +4 M ./libsofia-sip-ua/tport/tport.c -30 +122 * Added STUNTAG_DOMAIN to suitable places. Added more doxygen documentation - especially considering tag params to functions. M ./libsofia-sip-ua/stun/stun.c -7 +39 * Added STUN DNS-SRV functionality to stun module. A simple test app is also provided. This code is not yet used by other parts of the stun module. M ./RELEASE +1 M ./libsofia-sip-ua/stun/Makefile.am -8 +5 A ./libsofia-sip-ua/stun/lookup_stun_server.c M ./libsofia-sip-ua/stun/sofia-sip/stun.h -3 +24 A ./libsofia-sip-ua/stun/stun_dns.c * Updates to stun module doxygen documentation. M ./libsofia-sip-ua/stun/sofia-sip/stun.h -44 +31 M ./libsofia-sip-ua/stun/stun.c -15 +38 * async stun bind in tport, callback to NTA (mm) M ./libsofia-sip-ua/nta/nta.c -8 +18 M ./libsofia-sip-ua/stun/sofia-sip/stun.h +24 M ./libsofia-sip-ua/stun/sofia-sip/stun_tag.h +5 M ./libsofia-sip-ua/stun/stun.c -31 +122 M ./libsofia-sip-ua/stun/stun_common.c -1 M ./libsofia-sip-ua/stun/stun_tag.c +19 M ./libsofia-sip-ua/stun/stunc.c -4 +4 M ./libsofia-sip-ua/stun/torture_stun.c -1 +1 M ./libsofia-sip-ua/tport/tport.c -78 +331 * Checking for re-registration upon nat binding change. (pp) M ./libsofia-sip-ua/nua/test_nua.c -10 +66 * Added keepalive and probe OPTIONS to registration. (pp) M ./libsofia-sip-ua/nua/nua_options.c +3 M ./libsofia-sip-ua/nua/nua_register.c -309 +685 M ./libsofia-sip-ua/nua/nua_stack.h +6 * Removed warning. (pp) M ./libsofia-sip-ua/nua/nua_subnotref.c -1 +1 * Removing dialog usages when handle is being destroyed. (pp) M ./libsofia-sip-ua/nua/nua_stack.c -2 +7 * Added nua_dialog_usage_refresh() and nua_dialog_usage_public(). (pp) M ./libsofia-sip-ua/nua/nua_dialog.c +15 M ./libsofia-sip-ua/nua/nua_dialog.h -2 +13 * Added test_nat_flush(). (pp) M ./libsofia-sip-ua/nua/test_nat.c -14 +109 M ./libsofia-sip-ua/nua/test_nat.h +2 * Handling multiple bindings in test_proxy.c. (pp) M ./libsofia-sip-ua/nua/test_proxy.c -46 +244 * Added nta_agent_bind_tport_update(), nta_agent_tport_is_updating() functions. (pp) Added tport_is_updating(), too. Removed NTATAG_UPDATE_TPORT(). M ./libsofia-sip-ua/nta/nta.c -5 +19 M ./libsofia-sip-ua/nta/nta_internal.h +2 M ./libsofia-sip-ua/nta/nta_tag.c -1 M ./libsofia-sip-ua/nta/sofia-sip/nta_tag.h -9 M ./libsofia-sip-ua/nta/sofia-sip/nta_tport.h -1 +10 M ./libsofia-sip-ua/tport/sofia-sip/tport.h -2 +2 M ./libsofia-sip-ua/tport/tport.c +6 * Added nua_prack(). (pp) M ./libsofia-sip-ua/nua/nua.c -9 +29 * Do not log error if su_timer_set() is called with NULL timer. (pp) M ./libsofia-sip-ua/su/su_timer.c -3 +1 * Added su_task_execute(). (pp) M ./libsofia-sip-ua/su/sofia-sip/su_wait.h +4 M ./libsofia-sip-ua/su/su_root.c +71 * Fixed event saving and handling. (pp) Now we have a separate list for special events (nua_i_outbound). M ./libsofia-sip-ua/nua/test_nua.c -304 +356 * Added nua_i_outbound. (pp) M ./libsofia-sip-ua/nua/nua_common.c +1 M ./libsofia-sip-ua/nua/sofia-sip/nua.h +2 * Deregistering wait events. (pp) M ./libsofia-sip-ua/nua/test_nat.c -1 +8 * Mention Sofia-SIP User Agent Library instead Nokia UA Library in dox. (pp) M ./libsofia-sip-ua/nua/nua.c -3 +3 M ./libsofia-sip-ua/nua/nua_dialog.h -1 +1 M ./libsofia-sip-ua/nua/nua_stack.c -1 +1 M ./libsofia-sip-ua/nua/nua_stack.h -1 +1 M ./libsofia-sip-ua/nua/sofia-sip/nua.h -1 +2 M ./libsofia-sip-ua/nua/sofia-sip/nua_tag.h -2 +2 * Fixed request line handling bug in nta_msg_request_complete(). (pp) M ./libsofia-sip-ua/nta/nta.c -3 +9 * Using SOFIAPUBFUN in msg_header.h. Avoiding use of msg_param_t where possible. (pp) API CHANGE: Allowing NULL as message public pointer (using default) in calls to msg_serialize(), msg_header_add(), msg_header_prepend(), msg_header_add_dup(), msg_header_add_dup_as(), msg_header_add_make(), msg_header_add_str(), msg_header_insert(), msg_header_remove(), msg_header_remove_all(), and msg_header_replace(). M ./libsofia-sip-ua/msg/msg_parser.c -155 +182 M ./libsofia-sip-ua/msg/msg_parser_util.c -3 +3 M ./libsofia-sip-ua/msg/sofia-sip/msg_header.h -89 +138 * Added OPTIONS keepalive to nua_register.c. (pp) M ./libsofia-sip-ua/nua/nua_register.c -208 +526 * Added nta_default_leg(). (pp) M ./libsofia-sip-ua/nta/nta.c +7 M ./libsofia-sip-ua/nta/sofia-sip/nta.h +2 * Added process_options() to test_proxy. (pp) M ./libsofia-sip-ua/nua/test_proxy.c -28 +132 * Added nua_creq_save_restart() to nua_stack. (pp) M ./libsofia-sip-ua/nua/nua_stack.c -20 +39 M ./libsofia-sip-ua/nua/nua_stack.h +6 * Added url_cmp_all(). (pp) M ./libsofia-sip-ua/url/sofia-sip/url.h -1 +5 M ./libsofia-sip-ua/url/torture_url.c -3 +21 M ./libsofia-sip-ua/url/url.c -15 +177 * nua_dialog_store_peer_info() now optionally removes peer info. (pp) If the SIP message given to nua_dialog_store_peer_info() is redirection response, reset peer info. M ./libsofia-sip-ua/nua/nua_dialog.c +14 * Fixed bug in sip_transport_d() parsing different tls transports. (pp) This bug affected mainly parsing futuristic Via headers. M ./libsofia-sip-ua/sip/sip_parser.c -2 +3 M ./libsofia-sip-ua/sip/torture_sip.c +48 * Fixed sip_contact_string_from_via() (pp) M ./libsofia-sip-ua/sip/sip_util.c -2 +2 * Registering successfully behind NAT. (pp) M ./libsofia-sip-ua/nua/nua_register.c -125 +589 M ./libsofia-sip-ua/nua/nua_stack.c -121 +49 M ./libsofia-sip-ua/nua/nua_stack.h +6 M ./libsofia-sip-ua/nua/nua_subnotref.c -9 +10 M ./libsofia-sip-ua/nua/nua_tag.c +3 M ./libsofia-sip-ua/nua/sofia-sip/nua_tag.h +20 * Added sip_contact_string_from_via(), sip_transport_has_tls(). (pp) M ./libsofia-sip-ua/sip/sip_basic.c -53 +1 M ./libsofia-sip-ua/sip/sip_util.c -37 +133 M ./libsofia-sip-ua/sip/sofia-sip/sip_util.h +11 2006-03-16 Pekka Pessi Synchronizing CVS with darcs. * Fixed lib-sofia-sip-ua-glib Makefile.ams. Tried to sanitize glib-less compilation. M ./Makefile.am -2 +6 M ./libsofia-sip-ua-glib/Makefile.am -12 +4 M ./libsofia-sip-ua-glib/nua-glib/Makefile.am -2 * Added host_has_domain_invalid(). M ./libsofia-sip-ua/bnf/bnf.c -3 +23 M ./libsofia-sip-ua/bnf/sofia-sip/hostdomain.h +1 M ./libsofia-sip-ua/bnf/torture_bnf.c +18 * More string manipulation functions Added: - su_strcat_all() - su_slprintf(), su_slvprintf() - su_strlst_create_with(), su_strlst_vcreate_with() - su_strlst_create_with_dup(), su_strlst_vcreate_with_dup() M ./libsofia-sip-ua/su/sofia-sip/su_alloc.h -1 +4 M ./libsofia-sip-ua/su/sofia-sip/su_strlst.h -1 +23 M ./libsofia-sip-ua/su/su_alloc_test.c -32 +74 M ./libsofia-sip-ua/su/su_sprintf.c -1 +1 M ./libsofia-sip-ua/su/su_strdup.c -6 +53 M ./libsofia-sip-ua/su/su_strlst.c -23 +197 * Binding the endpoint behind "nat" to both IP families, if possible. M ./libsofia-sip-ua/nua/test_nua.c -3 +13 * Removed nutag_media_subsystem and nutag_media_session. M ./libsofia-sip-ua/nua/nua_tag.c -3 * Using nua_500_error. M ./libsofia-sip-ua/nua/nua_event_server.c -2 +2 * Allowing intending of #include directives in fix-include-sofia-sip. M ./scripts/fix-include-sofia-sip -197 +197 2006-03-13 Pekka Pessi * Release 1.11.7 * Synchronized CVS with darcs. * Added man pages to dist. * Updated libsofia-sip-ua-glib dist targets. M ./libsofia-sip-ua-glib/Makefile.am -2 +4 M ./libsofia-sip-ua-glib/nua-glib/Makefile.am -26 +25 M ./libsofia-sip-ua-glib/su-glib/Makefile.am -2 +6 M ./libsofia-sip-ua/sofia.am -1 +1 * Removed warnings on 64bit platforms. M ./libsofia-sip-ua/soa/soa.c -3 +3 M ./libsofia-sip-ua/stun/stun_common.c -8 +19 M ./libsofia-sip-ua/su/su_timer_test.c -2 +1 * Added missing files to dist. M ./libsofia-sip-ua/bnf/Makefile.am -1 +1 M ./libsofia-sip-ua/nua/Makefile.am -1 +1 * Using alarm() with su_test.c. * Fixed hc_print usage in msg_header_prepare(). Some headers use snprintf() which may return -1 on some platforms if buffer is too small. * Fixed problems in test_nua on win32. * Fixed problem of using destroying registered handle in su_root. This is a bug showing only in win32. * Cleaning ACK transactions in test_proxy * Fixed source file building rules for GNU make >= 3.80. The way VPATH is handled and $@ expands has changed between GNU make 3.79 and 3.80. M ./libsofia-sip-ua/http/Makefile.am -6 +14 M ./libsofia-sip-ua/msg/Makefile.am -13 +13 M ./libsofia-sip-ua/sip/Makefile.am -7 +18 M ./libsofia-sip-ua/sofia.am -1 +1 * Using sofia-sip/su_errno.h for error codes not present in win32. M ./libsofia-sip-ua/msg/msg_mime.c -6 +1 M ./libsofia-sip-ua/msg/msg_parser.c -4 M ./libsofia-sip-ua/soa/soa.c -8 +1 M ./libsofia-sip-ua/su/sofia-sip/su_errno.h +36 M ./libsofia-sip-ua/su/su_errno.c -6 +22 M ./win32/sofia-sip/su_configure.h -7 * Fixed problems with nua timers. M ./libsofia-sip-ua/nua/nua_dialog.c -2 +2 M ./libsofia-sip-ua/nua/nua_session.c -3 +7 M ./libsofia-sip-ua/nua/nua_stack.c -1 +1 2006-03-13 Martti Mela * win32 defs, compiles and installs in mingw environment 2006-03-09 Kai Vehmanen * Synchronized darcs and CVS. * Added missing su_source_test.c file. A ./libsofia-sip-ua-glib/su-glib/su_source_test.c * Added missing Makefile.am for su-glib. A ./libsofia-sip-ua-glib/su-glib/Makefile.am * Modified Makefile.ams to correctly build the new glib library. M ./configure.ac +4 A ./libsofia-sip-ua-glib/Makefile.am * Added sofia-sip-ua-glib to the packaging files. M ./packages/Makefile.am -2 +2 A ./packages/sofia-sip-ua-glib.pc.in M ./packages/sofia-sip-ua.pc.in -2 +2 M ./packages/sofia-sip.spec.in -4 +7 * Added nua-glib module to the tree. A ./libsofia-sip-ua-glib/nua-glib/ A ./libsofia-sip-ua-glib/nua-glib/Doxyfile A ./libsofia-sip-ua-glib/nua-glib/Makefile.am A ./libsofia-sip-ua-glib/nua-glib/nua_glib.c A ./libsofia-sip-ua-glib/nua-glib/nua_glib.docs A ./libsofia-sip-ua-glib/nua-glib/nua_glib_marshal.list A ./libsofia-sip-ua-glib/nua-glib/sofia-sip/ A ./libsofia-sip-ua-glib/nua-glib/sofia-sip/nua_glib.h A ./libsofia-sip-ua-glib/nua-glib/test_nua_glib.c * Moved glib stuff from libsofia-sip-ua to libsofia-sip-ua-glib. ./libsofia-sip-ua/su/su_source.c -> ./libsofia-sip-ua-glib/su-glib/su_source.c ./libsofia-sip-ua/su/sofia-sip/su_source.h -> ./libsofia-sip-ua-glib/su-glib/sofia-sip/su_source.h A ./libsofia-sip-ua-glib/su-glib/ A ./libsofia-sip-ua-glib/su-glib/sofia-sip/ M ./libsofia-sip-ua-glib/su-glib/su_source.c -1 +3 M ./libsofia-sip-ua/Makefile.am -1 M ./libsofia-sip-ua/su/Makefile.am -10 +7 M ./libsofia-sip-ua/su/sofia-sip/su_configure.h.in -2 M ./libsofia-sip-ua/su/su_root_test.c -4 M ./libsofia-sip-ua/su/su_test.c -18 +2 M ./m4/sac-su2.m4 -5 +9 * Created libsofia-sip-ua-glib. M ./Makefile.am -1 +1 A ./libsofia-sip-ua-glib/ 2006-03-09 Pekka Pessi * Updated globally unique identifier (uuid) generation. Using getifaddrs() and /dev/urandom. Added checks for /dev/urandom and (for link-level addresses). M ./configure.ac -13 +5 M ./libsofia-sip-ua/su/sofia-sip/su_uniqueid.h +3 M ./libsofia-sip-ua/su/su_uniqueid.c -15 +91 M ./m4/sac-general.m4 +16 M ./m4/sac-su2.m4 -1 +1 * Cache checked functions a bit more efficiently in sac-su2.m4. M ./m4/sac-su2.m4 -25 +28 * Added sip_via_port(). M ./libsofia-sip-ua/nta/nta.c -15 +1 M ./libsofia-sip-ua/sip/sip_basic.c +38 M ./libsofia-sip-ua/sip/sofia-sip/sip_header.h -1 +4 * Using sofia-sip/sofia_features.h. M ./libsofia-sip-ua/features/features.c -1 +1 * Using nua_owner_t instead of nua_handle_t with . Prepare to move nua_dialog.[hc] to nta or to its own module. M ./libsofia-sip-ua/nua/nua_dialog.c -114 +75 M ./libsofia-sip-ua/nua/nua_dialog.h -28 +19 M ./libsofia-sip-ua/nua/nua_register.c -1 +1 M ./libsofia-sip-ua/nua/nua_session.c -7 +8 M ./libsofia-sip-ua/nua/nua_stack.c -2 +2 M ./libsofia-sip-ua/nua/nua_stack.h -5 +5 M ./libsofia-sip-ua/nua/nua_subnotref.c -10 +10 * Added fake "nat" to test_nua M ./libsofia-sip-ua/nua/Makefile.am -1 +2 A ./libsofia-sip-ua/nua/test_nat.c A ./libsofia-sip-ua/nua/test_nat.h M ./libsofia-sip-ua/nua/test_nua.c -30 +242 * Removed spurious message when sofia-sip subdirectory is recreated. M ./libsofia-sip-ua/http/Makefile.am -1 +1 M ./libsofia-sip-ua/msg/Makefile.am -2 +2 M ./libsofia-sip-ua/sip/Makefile.am -1 +1 2006-03-08 Pekka Pessi * Renamed sofia-sip/features.h as sofia-sip/sofia_features.h. M ./RELEASE +3 M ./configure.ac -1 +1 M ./libsofia-sip-ua/features/Makefile.am -1 +1 M ./libsofia-sip-ua/features/sofia-sip/features.h.in -2 +4 M ./scripts/fix-include-sofia-sip -2 +5 * Generating man pages in $(srcdir). M ./Makefile.am -5 +3 * Split nua_stack.c into multiple files. M ./libsofia-sip-ua/nua/Makefile.am +6 M ./libsofia-sip-ua/nua/nua.c -52 +13 A ./libsofia-sip-ua/nua/nua_dialog.c A ./libsofia-sip-ua/nua/nua_dialog.h A ./libsofia-sip-ua/nua/nua_event_server.c A ./libsofia-sip-ua/nua/nua_message.c A ./libsofia-sip-ua/nua/nua_options.c A ./libsofia-sip-ua/nua/nua_publish.c A ./libsofia-sip-ua/nua/nua_register.c A ./libsofia-sip-ua/nua/nua_session.c M ./libsofia-sip-ua/nua/nua_stack.c -5026 +177 M ./libsofia-sip-ua/nua/nua_stack.h -125 +166 A ./libsofia-sip-ua/nua/nua_subnotref.c A ./libsofia-sip-ua/nua/nua_tag_ref.c * Added nta_check_*() functions. M ./libsofia-sip-ua/nta/Makefile.am -1 +1 A ./libsofia-sip-ua/nta/nta_check.c M ./libsofia-sip-ua/nta/sofia-sip/nta.h +26 * msg_parser.awk was printing spurious errors by SIP-ETag header etc. * Removed doxygen crud from . * Added SIPS_DEFAULT_PORT and SIPS_DEFAULT_SERV. M ./libsofia-sip-ua/sip/sofia-sip/sip.h -1 +7 * Removed redundant reference to . M ./libsofia-sip-ua/nea/nea.c -2 M ./libsofia-sip-ua/nea/nea_server.c -1 * Added some error checking to the win32 autogen scripts. M ./win32/Makefile.am -1 +1 M ./win32/autogen.cmd -2 +4 M ./win32/build_sources.cmd -22 +53 M ./win32/version_files.cmd +1 2006-03-03 Pekka Pessi * Do not use glib upon --without-glib-dir or --without-glib in configure. M ./m4/sac-su2.m4 -4 +4 * Returning unparsed remote SDP in SOATAG_REMOTE_SDP_STR() M ./libsofia-sip-ua/soa/soa.c -2 +2 * Using SU_HAVE_PTHREADS to check for pthread support in nua_stack.h M ./libsofia-sip-ua/nua/nua_stack.h -1 +5 * Fixed documentation problems. M ./Makefile.am -2 +3 M ./utils/sip-date.c -2 +2 * Fixed problems when there is no stun available. M ./libsofia-sip-ua/tport/tport.c -9 +5 * Fixed BDSSOCK checks in sac-su2.m4. M ./libsofia-sip-ua/su/su_addrinfo.c -1 +1 M ./m4/sac-su2.m4 -55 +73 * Using int as SOATAG_AF() value. M ./libsofia-sip-ua/soa/sofia-sip/soa_tag.h -2 +2 M ./libsofia-sip-ua/soa/test_soa.c -1 +1 2006-03-03 Martti Mela martti.mela@nokia.com * mingw support M ./configure.ac -3 +5 M ./libsofia-sip-ua/stun/Makefile.am -4 +4 M ./libsofia-sip-ua/su/sofia-sip/su_addrinfo.h +11 M ./libsofia-sip-ua/su/su_addrinfo.c +9 M ./m4/sac-general.m4 +1 M ./m4/sac-su2.m4 -1 +9 * mingw mods M ./configure.ac -1 +2 M ./libsofia-sip-ua/stun/Makefile.am -1 +1 M ./libsofia-sip-ua/stun/stun.c -3 +34 M ./libsofia-sip-ua/stun/stun_common.c +10 M ./libsofia-sip-ua/su/su_addrinfo.c -6 +2 M ./libsofia-sip-ua/su/su_source.c -1 +5 M ./libsofia-sip-ua/su/su_time0.c -1 +7 M ./libsofia-sip-ua/tport/tport.c -4 +8 M ./m4/sac-general.m4 +30 M ./m4/sac-su2.m4 -31 +72 M ./packages/sofia-sip.spec.in -1 +1 2006-03-01 Pekka Pessi * Synchronized darcs and CVS. * Added utils/Doxyfile A ./utils/Doxyfile * Changed output from localinfo so that emacs is not fooled anymore. M ./libsofia-sip-ua/su/run_addrinfo -1 +1 M ./libsofia-sip-ua/su/run_localinfo -1 +1 * Added SU_ADDRLEN() macro. M ./libsofia-sip-ua/su/sofia-sip/su.h +16 * Not creating sofia-sip when building sip_parser_table.c M ./libsofia-sip-ua/sip/Makefile.am -1 * Printing warning message if resolv.conf nameserver address is IPv6. M ./libsofia-sip-ua/sresolv/sresolv.c -4 +5 * Fixed problems with sa_len in nth_test.c. Added explicit su_wait() to to send_request(). M ./libsofia-sip-ua/nth/nth_test.c -2 +8 * Disabling IPv6 resolving in nta test. Not reying in ICMP in nta test. M ./libsofia-sip-ua/nta/run_test_nta -1 +2 M ./libsofia-sip-ua/nta/test_nta.c -2 +15 * Fixed problem of BSD awk returning -0 from 10 % 5. M ./libsofia-sip-ua/msg/msg_parser.awk -1 +3 * Fixed problems in stun/tport. M ./libsofia-sip-ua/stun/stun.c +3 M ./libsofia-sip-ua/tport/tport.c -9 +12 * Fixed signedness problem in msg_date_d(). M ./libsofia-sip-ua/msg/msg_date.c -2 +3 * Fixed url_cmp() crashing with invalid URLs. M ./libsofia-sip-ua/url/sofia-sip/url.h -2 +3 M ./libsofia-sip-ua/url/url.c -2 +6 * Removed warnings on BSDish systems. M ./libsofia-sip-ua/su/su.c -2 +2 * Added tests for getifaddrs(), using it in su_localinfo.c. M ./libsofia-sip-ua/su/su_localinfo.c -40 +161 M ./libsofia-sip-ua/su/su_port.c +2 M ./m4/sac-su2.m4 -11 +8 * Fixed typo in utils/sip-date.c M ./utils/sip-date.c -1 +1 * Defining missing SOL_TCP. M ./libsofia-sip-ua/stun/stun.c +5 * Fixed A6 record handling, sa_len usage. Removed some warnings, too. Disabled IN6 nameservers for the moment. M ./libsofia-sip-ua/sresolv/sresolv.c -15 +20 * Disabled a badly designed test failing in BSD systems. M ./libsofia-sip-ua/sresolv/test_sresolv.c -1 +16 * Removed debugging feature from msg_parser.awk making it fail with BSD awk. M ./libsofia-sip-ua/msg/msg_parser.awk -36 +36 * Using default sip and sips port in url comparisons if url has IP address M ./libsofia-sip-ua/url/torture_url.c +26 M ./libsofia-sip-ua/url/url.c +4 2006-02-20 martti.mela@nokia.com * stun: initial keepalive support M ./libsofia-sip-ua/nta/nta.c +10 M ./libsofia-sip-ua/nta/sofia-sip/nta.h +2 M ./libsofia-sip-ua/nua/nua_stack.c +4 M ./libsofia-sip-ua/stun/ChangeLog +31 M ./libsofia-sip-ua/stun/sofia-sip/stun.h -1 +11 M ./libsofia-sip-ua/stun/stun.c -79 +219 M ./libsofia-sip-ua/stun/stun_internal.h -1 M ./libsofia-sip-ua/tport/sofia-sip/tport.h +3 M ./libsofia-sip-ua/tport/tport.c -1 +90 * stun: dst addr improvements M! ./libsofia-sip-ua/stun/ChangeLog -18 M! ./libsofia-sip-ua/stun/stun.c -7 +16 2006-02-20 Pekka Pessi * If opaque is not given, do not include it in challenge (auth_module.c). M ./libsofia-sip-ua/iptsec/auth_module.c -2 +4 * Generating man pages for utilities. M ./Makefile.am -4 +22 M ./configure.ac +3 M ./libsofia-sip-ua/su/Doxyfile -3 +1 M ./libsofia-sip-ua/su/addrinfo.c -29 +24 M ./libsofia-sip-ua/su/localinfo.c -35 +29 M ./utils/Makefile.am +3 M ./utils/sip-date.c -44 +34 M ./utils/sip-options.c -30 +42 * Including for getpid() in test_nta.c. * Added install script. A ./win32/install.cmd M ./win32/libsofia-sip-ua/libsofia_sip_ua.dsp -4 +4 * Simplified use of sofia-sip/su_configure.h in win32 ./win32/su_configure_win32.h -> ./win32/sofia-sip/su_configure.h M ./win32/autogen.cmd -4 +3 A ./win32/sofia-sip/ * Fixed tests of unsigned tag values in test_nua.c Tests pass now on amd64, too. M ./libsofia-sip-ua/nua/test_nua.c -4 +4 2006-02-15 Pekka Pessi * Release 1.11.6. * Fixed problems in doxygen documentation and dist. * Updated PRACK and nta_outgoing_prack(). nta_outgoing_prack() accepts now RSeq sequence numbers in NTATAG_RSEQ(). When PRACK is sent using nta_outgoing_tmcreate(), there is functions nta_outgoing_setrseq() and nta_outgoing_rseq() for updating the rseq number within transaction. * Corrected su_torture.c, Shutdown semantics differ on WINSOCK/BSDSOCK. * Fixed su_wait() with 0 wait objects in windows. * Fixed win32-compatibility problems in test programs. * Not using NULL restart pointer in ua_authenticate(). 2006-02-14 Pekka Pessi * Fixed problems with sofia-sip/ header prefix in win32. * Fixed win32/VC configuration problems. * Fixed win32 pthread dist. * Fixed include paths. * Use #include . * Be explicit with input when generating source files. * Added make target clean-built-sources. * Fixed #include su_module_debug.h. * Moved public include files to sofia-sip subdirectories. All public include files installed in ${sofiadir} are now in sofia-sip subdirectories. They are installed to ${sofiadir}/sofia-sip, too. ${sofiadir} is defined by configure script relative to your ${prefix}, by default ${sofidir} is ${prefix}/include/sofia-sip-1.11. The default prefix is /usr/local and ${sofiadir} is /usr/local/include/sofia-sip-1.11. When using package manager, the ${prefix} is usually /usr and ${sofiadir} is /usr/include/sofia-sip-1.11. The public include files should be referenced using sofia-sip path, e.g., . You can either fix your applications to use the new include file names with the fix-include-sofia-sip sed script found in scripts/ directory, or add both ${sofiadir} and ${sofiadir}/sofia-sip into your include path, e.g., INCLUDES = -I/usr/include/sofia-1.11 -I/usr/include/sofia-1.11/sofia-sip At the same time, I took the liberty to rename two include files sofia_sip_features.h => sofia-sip/features.h su_memmem.h => sofia-sip/su_bm.h The fix-include-sofia-sip sed script takes care of both of them. * Improved 100rel handling in nua. Added test_100rel to test_nua.c. * Using CONDITION_PARAMS macro instead of CONDITION_FUNCTION in test_nua.c * Improving getaddrinfo replacements. Testing functions getaddrinfo()/freeaddrinfo(), getnameinfo() and gai_strerror() separately. There is no gai_strerror() in windows, I think. 2006-02-03 Pekka Pessi * Code cleanup and memory leak fix in soa/sdp. Fixed memory leak related to parsing sdp in soa. Cleaned up handling of rejected media (related to bug report #1419078). ./libsofia-sip-ua/sdp/run-tests -> ./libsofia-sip-ua/sdp/run_test_sdp ./libsofia-sip-ua/sdp/sdp_test.c -> ./libsofia-sip-ua/sdp/test_sdp.c ./libsofia-sip-ua/sdp/sdp_torture.c -> ./libsofia-sip-ua/sdp/torture_sdp.c M ./libsofia-sip-ua/sdp/Makefile.am -4 +4 M ./libsofia-sip-ua/sdp/run_test_sdp -4 +4 M ./libsofia-sip-ua/sdp/sdp_parse.c -8 +11 M ./libsofia-sip-ua/sdp/sdp_print.c -1 +5 M ./libsofia-sip-ua/sdp/test_sdp.c -6 +6 M ./libsofia-sip-ua/sdp/torture_sdp.c -47 +38 M ./libsofia-sip-ua/soa/soa.c -13 +20 M ./libsofia-sip-ua/soa/soa_static.c -11 2006-02-02 Pekka Pessi * Add helper functions to update or modify sdp attributes. Feature request #1420698: Added sdp_attribute_append(), sdp_attribute_replace(), and sdp_attribute_remove(). M ./libsofia-sip-ua/sdp/sdp.c -18 +115 M ./libsofia-sip-ua/sdp/sdp.h -9 +21 M ./libsofia-sip-ua/sdp/sdp_torture.c -1 +22 * Using unsigned in bit fields. M ./libsofia-sip-ua/sdp/sdp_print.c -2 +2 * Fixed bug in sending error response to a request containing Record-Route. M ./libsofia-sip-ua/nta/nta.c -30 +33 2006-01-25 Pekka Pessi * Updated autoconf macros. Using cache for various checks. Deprecated HAVE_LONG_LONG (use #ifdef longlong instead). Collected information used by su_localinfo.c to one place. M ./libsofia-sip-ua/su/su_taglist.c -2 +2 M ./m4/sac-su2.m4 -64 +103 * Updated Win32 port. Added autogen.cmd, build_sources.cmd, version_files.cmd and version.awk. Fixed problems with configuration. Updated pthread-w32 to version 2.7.0. * Fixed VC/Win32 problems in libsofia-sip-ua. Signedness problems, includes, linkage, winsock initialization. M ./libsofia-sip-ua/msg/msg_types.h -1 +2 M ./libsofia-sip-ua/nta/nta.c -2 +2 M ./libsofia-sip-ua/nua/test_nua.c -5 +5 M ./libsofia-sip-ua/nua/test_proxy.c -7 +11 M ./libsofia-sip-ua/su/su_root.c +8 M ./libsofia-sip-ua/su/su_types.h +2 M ./libsofia-sip-ua/su/su_wait.h +2 * Fixed gawk internal error in msg_parser.awk. It looks like some gawk versions had problems when a function argument was an unitialized variable. M ./libsofia-sip-ua/msg/msg_parser.awk -1 +6 * Defining missing error codes in . M ./libsofia-sip-ua/msg/msg_mime.c -7 M ./libsofia-sip-ua/soa/soa.c -7 M ./libsofia-sip-ua/stun/stun.c -6 M ./libsofia-sip-ua/su/su_errno.h +12 M ./libsofia-sip-ua/su/su_memmem.c -7 +2 M ./libsofia-sip-ua/tport/tport.c -5 * Added checks for different net includes. Checks for sys/ioctl.h, netinet/in.h, net/if.h net/if_types.h and sys/ioctl.h. M ./libsofia-sip-ua/su/su_localinfo.c -12 +16 M ./m4/sac-su2.m4 -2 +7 * Fixed rejection of subscriptions in nea server. Event server does not send extra NOTIFY before 403 response anymore. M ./libsofia-sip-ua/nea/nea_server.c -1 +1 * Added functions for scanning domain names and IP addresses. Added span_ip4_address()/scan_ip4_address(), span_ip6_address()/scan_ip6_address(), span_ip6_reference()/scan_ip6_reference(), span_ip_address()/scan_ip_address(), span_domain()/scan_domain(), and span_host()/scan_host(). M ./libsofia-sip-ua/bnf/bnf.c -2 +588 M ./libsofia-sip-ua/bnf/bnf.h -2 +18 M ./libsofia-sip-ua/bnf/torture_bnf.c -25 +220 2006-01-23 Pekka Pessi * Removed *_dll.h files - defining *_DLL macros in . * Using random probe when finding port that is available with all transports. * Updated auth_mod API. Added auth_status_ref(). Removed antique functions auth_mod_check_ireq(), auth_mod_check_ireq2() and auth_mod_check_msg(). 2006-01-10 Pekka Pessi * Fixed doxygen input files (kv). * Using su_home_t reference counting in nua. * Modified cloned su_home_t semantics. Now we allow reference counting for clones as well as threadsafeness for them. Added su_home_is_threadsafe(), modified prototype of su_home_unref(). * Fixed memory leaks in nea test code. * Fixed memory leak in nea_server.c 2006-01-09 Pekka Pessi * Restorered tag lists for modules. M ./libsofia-sip-ua/nta/Makefile.am +2 M ./libsofia-sip-ua/nta/nta_tag.h +3 M ./libsofia-sip-ua/nth/nth_tag.h +3 M ./libsofia-sip-ua/nua/Makefile.am +2 M ./libsofia-sip-ua/nua/nua_tag.h +3 M ./libsofia-sip-ua/sip/sip_tag.c.in +13 M ./libsofia-sip-ua/sip/sip_tag.h.in +3 M ./libsofia-sip-ua/soa/Makefile.am +1 M ./libsofia-sip-ua/soa/soa_tag.h +3 M ./libsofia-sip-ua/stun/Makefile.am -2 +8 M ./libsofia-sip-ua/su/tag_dll.awk -3 +5 M ./libsofia-sip-ua/tport/tport_tag.h -1 +4 M ./utils/Makefile.am +4 * Fixed test code for pthread_rwlock_trywrlock(). M ./m4/sac-su2.m4 -3 +3 2006-01-05 Pekka Pessi 2nd sync today for darcs and CVS. * Added namespace-specific filter tags. * Freeing nua_r_authorize events. * Added NSTAG_TYPEDEF(t) and ns_tag_class[]. * Not using . Synching darcs and CVS. * Not using msg_auth.h anymore. M ./libsofia-sip-ua/msg/msg_auth.c -1 M ./libsofia-sip-ua/msg/test_msg.c -1 * Really adding expires=0 to all contacts when un-registering. M ./libsofia-sip-ua/nua/nua_stack.c -1 +1 M ./libsofia-sip-ua/nua/test_nua.c -3 +26 * Removed sip_rfc2543 files. R ./libsofia-sip-ua/sip/sip_rfc2543.c R ./libsofia-sip-ua/sip/sip_rfc2543.h.in * Adding nua_authenticate() tags to request. M ./libsofia-sip-ua/nua/nua_stack.c -2 +1 M ./libsofia-sip-ua/nua/test_nua.c +12 * Using unsigned in sdp_media_t::m_mode bitfield. enum is signed in VC6. M ./libsofia-sip-ua/sdp/sdp.h -1 +1 * Documented sdp_f_mode_manual and sdp_f_mode_always better. M ./libsofia-sip-ua/sdp/sdp.h -1 +1 M ./libsofia-sip-ua/sdp/sdp_print.c -8 +10 2006-01-03 Pekka Pessi Syncinc darcs and CVS. * Added more tests for call hold. * Using msg_header_replace_param() in nua_stack.c. * Using ss_retry_after in nea.c. * Marking two single headers in a message as fatal error. * Made headers C++-safe (bug #1376379). * Removed dead #include files * Removed Last modified things. * Removed msg_bnf.h * Added NTATAG_TCP_RPORT(). Do not use rport with TCP by default. * Added test for comp=sigcomp. The comp=sigcomp should not be included if destination does not support compression. Modernized parameter handling, too. * Documented TP_AI_ flags. Test our TP_AI_ assumptions. Added a test for asymmetric SigComp on TCP. We use TP_AI_COMPRESSED flag in this test. * Added TPTAG_FRESH() and a test for it. * Augmented documentation for SIPTAG_HEADER_STR(). * Use #include for FILE. * Fixed include_sofiadir handling in pkg-config and rpm files. 2005-12-27 Martti Mela Syncing darcs and CVS. * Added stun_internal.h to dist. M ./libsofia-sip-ua/stun/Makefile.am -1 +1 * Better handling of optional tags in nta_agent_get_params(). M ./libsofia-sip-ua/nta/nta.c +4 M ./libsofia-sip-ua/nta/test_nta_api.c -8 +9 * Removed warnings from su_perror() (moved to su_log.h). M ./libsofia-sip-ua/su/poll_test.c +1 M ./libsofia-sip-ua/su/su_test.c +2 M ./libsofia-sip-ua/su/su_timer_test.c +1 * Added su_errno.h and su_errno.c. M ./libsofia-sip-ua/su/Makefile.am -2 +2 M ./libsofia-sip-ua/su/su.c -103 M ./libsofia-sip-ua/su/su.h -15 +3 A ./libsofia-sip-ua/su/su_errno.c A ./libsofia-sip-ua/su/su_errno.h M ./libsofia-sip-ua/su/su_log.c -2 +13 M ./libsofia-sip-ua/su/su_log.h -2 +6 * Prepare for 1.11.5pre1. M ./RELEASE -2 +41 M ./TODO -2 +5 M ./configure.ac -2 +9 * Added su_home_destructor() to su_alloc.[hc]. M ./libsofia-sip-ua/su/su_alloc.c -9 +56 M ./libsofia-sip-ua/su/su_alloc.h -6 +11 M ./libsofia-sip-ua/su/su_alloc_lock.c -15 +18 M ./libsofia-sip-ua/su/su_alloc_test.c -20 +40 * Building features module first after su. M ./libsofia-sip-ua/Makefile.am -2 +2 * Using su_home_new(size) instead of su_home_clone(NULL, size). M ./libsofia-sip-ua/http/test_http.c -1 +1 M ./libsofia-sip-ua/iptsec/auth_module.c -1 +1 M ./libsofia-sip-ua/iptsec/test_auth_digest.c -2 +2 M ./libsofia-sip-ua/nea/nea.c -1 +1 M ./libsofia-sip-ua/nea/nea_server.c -1 +1 M ./libsofia-sip-ua/sip/torture_sip.c -7 +7 * Improved argument checking in sresolv. M ./libsofia-sip-ua/sresolv/sresolv.c -67 +118 M ./libsofia-sip-ua/sresolv/sresolv.h -4 +3 M ./libsofia-sip-ua/sresolv/test_sresolv.c -13 +26 * Updated function names in conformance.docs. M ./libsofia-sip-ua/docs/conformance.docs -17 +17 * Fixed problems with autogenerating files with header boilerplates. M ./libsofia-sip-ua/http/Makefile.am -2 +4 M ./libsofia-sip-ua/sip/Makefile.am -2 +5 * Added explicit dependencies for autogenerated sources. M ./libsofia-sip-ua/msg/Makefile.am -2 +6 * Using parameter manipulation functions and shortcuts. M ./libsofia-sip-ua/nea/nea.c -3 +2 M ./libsofia-sip-ua/nta/nta.c -5 +5 M ./libsofia-sip-ua/nta/test_nta.c -2 +2 M ./libsofia-sip-ua/nua/nua_stack.c -6 +18 * Fixed su_home_auto() problems. M ./libsofia-sip-ua/su/su_alloc.c -4 +8 * Added hc_update member to msg_hclass_t. The hc_update is used to update shortcuts to well-known parameters. Updated manipulation functions for header parameters to use hc_update. Added updating functions for SIP headers. M ./libsofia-sip-ua/http/http_parser.h -4 +6 M ./libsofia-sip-ua/msg/msg_basic.c -4 +10 M ./libsofia-sip-ua/msg/msg_header_copy.c +6 M ./libsofia-sip-ua/msg/msg_mime.c -60 +86 M ./libsofia-sip-ua/msg/msg_mime.h -2 +2 M ./libsofia-sip-ua/msg/msg_mime_protos.h.in +5 M ./libsofia-sip-ua/msg/msg_mime_table.c.in -2 +5 M ./libsofia-sip-ua/msg/msg_parser.c +3 M ./libsofia-sip-ua/msg/msg_parser.h -14 +18 M ./libsofia-sip-ua/msg/msg_parser_util.c -20 +152 M ./libsofia-sip-ua/msg/msg_tag.c -1 +8 M ./libsofia-sip-ua/msg/msg_types.h +4 M ./libsofia-sip-ua/msg/test_class.c -2 +4 M ./libsofia-sip-ua/msg/test_msg.c -1 +1 M ./libsofia-sip-ua/sip/sip.h -4 +5 M ./libsofia-sip-ua/sip/sip_basic.c -158 +124 M ./libsofia-sip-ua/sip/sip_caller_prefs.c -54 +40 M ./libsofia-sip-ua/sip/sip_event.c -53 +49 M ./libsofia-sip-ua/sip/sip_extra.c -37 +36 M ./libsofia-sip-ua/sip/sip_mime.c -70 +15 M ./libsofia-sip-ua/sip/sip_parser.h -7 +10 M ./libsofia-sip-ua/sip/sip_prack.c +1 M ./libsofia-sip-ua/sip/sip_reason.c -15 +23 M ./libsofia-sip-ua/sip/sip_refer.c -36 +53 M ./libsofia-sip-ua/sip/sip_security.c -13 +35 M ./libsofia-sip-ua/sip/sip_session.c -2 +22 M ./libsofia-sip-ua/sip/torture_sip.c -13 +137 * Added manipulation functions for header parameters. msg_header_find_param(), msg_header_add_param(), msg_header_replace_param(), and msg_header_remove_param(). M ./libsofia-sip-ua/http/http_basic.c -1 +1 M ./libsofia-sip-ua/iptsec/auth_client.c -4 +5 M ./libsofia-sip-ua/iptsec/auth_module.c -3 +3 M ./libsofia-sip-ua/msg/msg_header.h -5 +9 M ./libsofia-sip-ua/msg/msg_mime.c -3 +3 M ./libsofia-sip-ua/msg/msg_parser.c -5 +5 M ./libsofia-sip-ua/msg/msg_parser_util.c +62 M ./libsofia-sip-ua/msg/test_msg.c +24 Tue Dec 20 19:51:57 EET 2005 Pekka.Pessi@nokia.com * Reduced overhead in su_home_auto(). M ./libsofia-sip-ua/su/su_alloc.c -5 +8 M ./libsofia-sip-ua/su/su_alloc.h -2 +5 M ./libsofia-sip-ua/su/su_alloc_test.c +12 * Fixed bug in histogram bucket search. Bug was detected using coverity. M ./libsofia-sip-ua/sip/validator.c -2 +2 * Updated param type and usage in SIP headers. A single param has type "char const *". Via has no "hidden" anymore, but "rport" and "comp" were added. Contact has no "action" anymore. M ./libsofia-sip-ua/sip/sip.h -42 +44 M ./libsofia-sip-ua/sip/sip_basic.c -12 +23 M ./libsofia-sip-ua/sip/sip_header.h -1 +1 M ./libsofia-sip-ua/sip/sip_util.c -9 +8 M ./libsofia-sip-ua/sip/sip_util.h -8 +5 M ./libsofia-sip-ua/sip/torture_sip.c +11 * Updated documentation of SIP headers. M ./libsofia-sip-ua/sip/sip_event.c -10 +11 M ./libsofia-sip-ua/sip/sip_extra.c -5 +6 * Refactored sres_resolver_sockets(). M ./libsofia-sip-ua/sresolv/sresolv.c -57 +80 * Added stateless operation to test_proxy. Using nta_incoming_default() and nta_outgoing_default(). M ./libsofia-sip-ua/nua/test_nua.c -3 +6 M ./libsofia-sip-ua/nua/test_proxy.c +46 M ./libsofia-sip-ua/nua/test_proxy.h -15 +2 * Added nta_outgoing_default(), nta_incoming_default(). Stateless response processing can be done with default transactions. Also added nta_incoming_method_name(), nta_incoming_method_name() and nta_incoming_gettag(). Deprecated nta_msg_response_complete(). Updated API tests. M ./libsofia-sip-ua/nta/Makefile.am -3 +5 M ./libsofia-sip-ua/nta/nta.c -51 +268 M ./libsofia-sip-ua/nta/nta.h +8 M ./libsofia-sip-ua/nta/nta_internal.h -1 +5 A ./libsofia-sip-ua/nta/run_test_nta_api A ./libsofia-sip-ua/nta/test_nta_api.c * Replaced nta_msg_response_complete() with nta_incoming_complete_response(). M ./libsofia-sip-ua/nta/nta.c -61 +83 M ./libsofia-sip-ua/nta/nta.h -5 +9 M ./libsofia-sip-ua/nta/test_nta.c -628 +67 * Documented GUID format. M ./libsofia-sip-ua/sip/sip_basic.c +6 * Added test_sec_ext() for testing security agreement headers. M ./libsofia-sip-ua/sip/torture_sip.c +62 * Fixed handling of 6XX responses in sip_response_terminates_dialog(). Bug found by coverity. M ./libsofia-sip-ua/sip/sip_util.c -1 +1 * Fixed bugs with auto allocation. In C89 and later, the automatic variable may go away when block is exited. The buggy code relied on behaviour of K&R C, where automatic variables are reclaimed when function returns. M ./libsofia-sip-ua/nea/nea.c -3 +2 M ./libsofia-sip-ua/nea/nea_server.c -5 +4 M ./libsofia-sip-ua/nta/nta.c -7 +4 M ./libsofia-sip-ua/nua/nua_stack.c -8 +6 M ./libsofia-sip-ua/su/su_localinfo.c -2 +2 M ./libsofia-sip-ua/tport/tport.c -2 +3 * Added ELI_BADHINTS to su_localinfo. M ./libsofia-sip-ua/su/su_localinfo.c +3 M ./libsofia-sip-ua/su/su_localinfo.h -2 +3 2005-12-02 Pekka Pessi Again, syncing darcs and CVS. * Disabling stun for the moment, use --enable-stun to use it. [pp] M ./configure.ac -2 +9 * working async stun support [mm] M ./libsofia-sip-ua/stun/stun.c -139 +131 M ./libsofia-sip-ua/stun/stun.h -1 +3 M ./libsofia-sip-ua/stun/stun_common.c -14 +18 M ./libsofia-sip-ua/stun/stunc.c -21 +15 M ./libsofia-sip-ua/stun/torture_stun.c -1 +1 * initial async stun support. Does not work with tport yet. [mm] M ./libsofia-sip-ua/stun/stun.c -269 +350 M ./libsofia-sip-ua/stun/stun.h -6 +28 M ./libsofia-sip-ua/stun/stun_common.c -5 +23 M ./libsofia-sip-ua/stun/stun_common.h -1 +1 M ./libsofia-sip-ua/stun/stun_internal.h -4 +5 M ./libsofia-sip-ua/stun/stunc.c -3 +10 M ./libsofia-sip-ua/stun/torture_stun.c -2 +2 * async stunning contd. Juhui! [mm] M ./libsofia-sip-ua/stun/stun.c -19 +13 M ./libsofia-sip-ua/stun/stun_common.c -4 +9 M ./libsofia-sip-ua/stun/stun_internal.h -1 +16 * stun asyncing contd. NOT WORKING [mm] M ./libsofia-sip-ua/stun/stun.c -70 +86 M ./libsofia-sip-ua/stun/stun.h -9 +7 M ./libsofia-sip-ua/stun/stun_common.c -3 +8 M ./libsofia-sip-ua/stun/stun_common.h -1 +4 M ./libsofia-sip-ua/stun/stun_internal.h -3 +6 M ./libsofia-sip-ua/stun/stunc.c -13 +17 M ./libsofia-sip-ua/stun/torture_stun.c -12 +15 * stun async contd. [mm] M ./libsofia-sip-ua/stun/stun.c -26 +56 M ./libsofia-sip-ua/stun/stun.h +4 M ./libsofia-sip-ua/stun/stunc.c -4 +9 * DON'T APPLY THIS: does not work. I need this for syncing. [mm] M ./libsofia-sip-ua/stun/stun.c -81 +209 M ./libsofia-sip-ua/stun/stun.h -3 +15 M ./libsofia-sip-ua/stun/stun_internal.h -1 +1 M ./libsofia-sip-ua/stun/stunc.c -3 +7 M ./libsofia-sip-ua/stun/torture_stun.c -4 +4 * async connect continued [mm] M ./libsofia-sip-ua/stun/stun.c -24 +71 * async stun continued [mm] M ./libsofia-sip-ua/stun/stun.c -27 +53 M ./libsofia-sip-ua/stun/torture_stun.c +7 M ./libsofia-sip-ua/tport/test_tport.c -1 +8 M ./libsofia-sip-ua/tport/tport.c -1 +2 * su_localinfo returns now valid address also in Windows [mm] M ./libsofia-sip-ua/nua/test_nua.c +3 M ./libsofia-sip-ua/su/su_localinfo.c +4 * tport cygwin modifications [mm] M ./libsofia-sip-ua/tport/tport.c -3 +7 * Declaring h_errno as a variable imported from DLL (when using WIN32). [pp] M ./libsofia-sip-ua/su/su_addrinfo.c -3 +8 * Try random port next if a port is taken. [pp] M ./libsofia-sip-ua/tport/tport.c -1 +2 * Moved LGPL reference so that it will be included in the autogenerated files. [pp] M ./libsofia-sip-ua/http/http_parser_table.c.in -8 +8 M ./libsofia-sip-ua/http/http_protos.h.in -6 +6 M ./libsofia-sip-ua/http/http_tag.c.in -8 +8 M ./libsofia-sip-ua/http/http_tag.h.in -7 +7 M ./libsofia-sip-ua/msg/msg_mime_protos.h.in -6 +6 M ./libsofia-sip-ua/msg/msg_protos.h.in -6 +6 M ./libsofia-sip-ua/msg/test_protos.h.in -7 +7 M ./libsofia-sip-ua/sip/sip_hclasses.h.in -6 +7 M ./libsofia-sip-ua/sip/sip_parser_table.c.in -7 +7 M ./libsofia-sip-ua/sip/sip_protos.h.in -5 +5 M ./libsofia-sip-ua/sip/sip_rfc2543.h.in -6 +5 M ./libsofia-sip-ua/sip/sip_tag.c.in -7 +7 M ./libsofia-sip-ua/sip/sip_tag.h.in -7 +7 * Collected copyrights belonging someone else but Nokia to COPYRIGHTS file. [pp] M ./COPYRIGHTS -1 +223 M ./libsofia-sip-ua/ipt/rc4.c -24 M ./libsofia-sip-ua/su/getopt.c -24 M ./libsofia-sip-ua/su/su_md5.c -11 +14 * Fixed bug in su_addrinfo.c [FIX]. [pp] Setting ai_addrlen even if there is no sa_len. M ./libsofia-sip-ua/su/su_addrinfo.c +1 * sresolv now compiles without IPv6 [mm] M ./libsofia-sip-ua/nua/nua.h -2 M ./libsofia-sip-ua/sresolv/sresolv.c -1 +1 M ./libsofia-sip-ua/tport/tport.c -1 +1 * using 500 timers instead of 500000 timers in su_timer_test [mm] M ./libsofia-sip-ua/su/su_timer_test.c -2 +2 * added #include to stun_common.h [mm] M ./libsofia-sip-ua/nth/Makefile.am -3 +2 M ./libsofia-sip-ua/stun/stun_common.h +1 * added stun_internal.h [mm] A ./libsofia-sip-ua/stun/stun_internal.h * tport_stun_cb parameter type change [mm] R ./libsofia-sip-ua/sip/sip_p_tag.c M ./libsofia-sip-ua/tport/tport.c -1 +1 * initial async stun, compiles not works. [mm] M ./libsofia-sip-ua/nth/Makefile.am -2 +3 M ./libsofia-sip-ua/sip/sip_p_tag.c -105 M ./libsofia-sip-ua/stun/stun.c -65 +121 M ./libsofia-sip-ua/stun/stun.h -23 +18 M ./libsofia-sip-ua/stun/stunc.c -2 +26 M ./libsofia-sip-ua/stun/torture_stun.c -4 +29 M ./libsofia-sip-ua/tport/tport.c -3 +17 * Removed sip_rfc2543{.h,.h.in,.c} from dist. [pp] M ./libsofia-sip-ua/sip/Makefile.am -3 +2 2005-12-02 Pekka Pessi Again, syncing darcs and CVS. * Disabling stun for the moment, use --enable-stun to use it. [pp] M ./configure.ac -2 +9 * working async stun support [mm] M ./libsofia-sip-ua/stun/stun.c -139 +131 M ./libsofia-sip-ua/stun/stun.h -1 +3 M ./libsofia-sip-ua/stun/stun_common.c -14 +18 M ./libsofia-sip-ua/stun/stunc.c -21 +15 M ./libsofia-sip-ua/stun/torture_stun.c -1 +1 * initial async stun support. Does not work with tport yet. [mm] M ./libsofia-sip-ua/stun/stun.c -269 +350 M ./libsofia-sip-ua/stun/stun.h -6 +28 M ./libsofia-sip-ua/stun/stun_common.c -5 +23 M ./libsofia-sip-ua/stun/stun_common.h -1 +1 M ./libsofia-sip-ua/stun/stun_internal.h -4 +5 M ./libsofia-sip-ua/stun/stunc.c -3 +10 M ./libsofia-sip-ua/stun/torture_stun.c -2 +2 * async stunning contd. Juhui! [mm] M ./libsofia-sip-ua/stun/stun.c -19 +13 M ./libsofia-sip-ua/stun/stun_common.c -4 +9 M ./libsofia-sip-ua/stun/stun_internal.h -1 +16 * stun asyncing contd. NOT WORKING [mm] M ./libsofia-sip-ua/stun/stun.c -70 +86 M ./libsofia-sip-ua/stun/stun.h -9 +7 M ./libsofia-sip-ua/stun/stun_common.c -3 +8 M ./libsofia-sip-ua/stun/stun_common.h -1 +4 M ./libsofia-sip-ua/stun/stun_internal.h -3 +6 M ./libsofia-sip-ua/stun/stunc.c -13 +17 M ./libsofia-sip-ua/stun/torture_stun.c -12 +15 * stun async contd. [mm] M ./libsofia-sip-ua/stun/stun.c -26 +56 M ./libsofia-sip-ua/stun/stun.h +4 M ./libsofia-sip-ua/stun/stunc.c -4 +9 * DON'T APPLY THIS: does not work. I need this for syncing. [mm] M ./libsofia-sip-ua/stun/stun.c -81 +209 M ./libsofia-sip-ua/stun/stun.h -3 +15 M ./libsofia-sip-ua/stun/stun_internal.h -1 +1 M ./libsofia-sip-ua/stun/stunc.c -3 +7 M ./libsofia-sip-ua/stun/torture_stun.c -4 +4 * async connect continued [mm] M ./libsofia-sip-ua/stun/stun.c -24 +71 * async stun continued [mm] M ./libsofia-sip-ua/stun/stun.c -27 +53 M ./libsofia-sip-ua/stun/torture_stun.c +7 M ./libsofia-sip-ua/tport/test_tport.c -1 +8 M ./libsofia-sip-ua/tport/tport.c -1 +2 * su_localinfo returns now valid address also in Windows [mm] M ./libsofia-sip-ua/nua/test_nua.c +3 M ./libsofia-sip-ua/su/su_localinfo.c +4 * tport cygwin modifications [mm] M ./libsofia-sip-ua/tport/tport.c -3 +7 * Declaring h_errno as a variable imported from DLL (when using WIN32). [pp] M ./libsofia-sip-ua/su/su_addrinfo.c -3 +8 * Try random port next if a port is taken. [pp] M ./libsofia-sip-ua/tport/tport.c -1 +2 * Moved LGPL reference so that it will be included in the autogenerated files. [pp] M ./libsofia-sip-ua/http/http_parser_table.c.in -8 +8 M ./libsofia-sip-ua/http/http_protos.h.in -6 +6 M ./libsofia-sip-ua/http/http_tag.c.in -8 +8 M ./libsofia-sip-ua/http/http_tag.h.in -7 +7 M ./libsofia-sip-ua/msg/msg_mime_protos.h.in -6 +6 M ./libsofia-sip-ua/msg/msg_protos.h.in -6 +6 M ./libsofia-sip-ua/msg/test_protos.h.in -7 +7 M ./libsofia-sip-ua/sip/sip_hclasses.h.in -6 +7 M ./libsofia-sip-ua/sip/sip_parser_table.c.in -7 +7 M ./libsofia-sip-ua/sip/sip_protos.h.in -5 +5 M ./libsofia-sip-ua/sip/sip_rfc2543.h.in -6 +5 M ./libsofia-sip-ua/sip/sip_tag.c.in -7 +7 M ./libsofia-sip-ua/sip/sip_tag.h.in -7 +7 * Collected copyrights belonging someone else but Nokia to COPYRIGHTS file. [pp] M ./COPYRIGHTS -1 +223 M ./libsofia-sip-ua/ipt/rc4.c -24 M ./libsofia-sip-ua/su/getopt.c -24 M ./libsofia-sip-ua/su/su_md5.c -11 +14 * Fixed bug in su_addrinfo.c [FIX]. [pp] Setting ai_addrlen even if there is no sa_len. M ./libsofia-sip-ua/su/su_addrinfo.c +1 * sresolv now compiles without IPv6 [mm] M ./libsofia-sip-ua/nua/nua.h -2 M ./libsofia-sip-ua/sresolv/sresolv.c -1 +1 M ./libsofia-sip-ua/tport/tport.c -1 +1 * using 500 timers instead of 500000 timers in su_timer_test [mm] M ./libsofia-sip-ua/su/su_timer_test.c -2 +2 * added #include to stun_common.h [mm] M ./libsofia-sip-ua/nth/Makefile.am -3 +2 M ./libsofia-sip-ua/stun/stun_common.h +1 * added stun_internal.h [mm] A ./libsofia-sip-ua/stun/stun_internal.h * tport_stun_cb parameter type change [mm] R ./libsofia-sip-ua/sip/sip_p_tag.c M ./libsofia-sip-ua/tport/tport.c -1 +1 * initial async stun, compiles not works. [mm] M ./libsofia-sip-ua/nth/Makefile.am -2 +3 M ./libsofia-sip-ua/sip/sip_p_tag.c -105 M ./libsofia-sip-ua/stun/stun.c -65 +121 M ./libsofia-sip-ua/stun/stun.h -23 +18 M ./libsofia-sip-ua/stun/stunc.c -2 +26 M ./libsofia-sip-ua/stun/torture_stun.c -4 +29 M ./libsofia-sip-ua/tport/tport.c -3 +17 * Removed sip_rfc2543{.h,.h.in,.c} from dist. [pp] M ./libsofia-sip-ua/sip/Makefile.am -3 +2 2005-12-02 Pekka Pessi Syncing darcs and CVS. * Removed debugging printf()s. [pp] M ./libsofia-sip-ua/su/su_root.c -16 +2 * Removed duplicate function msg_params_matching(). [pp] M ./libsofia-sip-ua/msg/msg_header.h -2 M ./libsofia-sip-ua/msg/msg_parser_util.c -36 M ./libsofia-sip-ua/sip/sip_pref_util.c -1 +1 * Compilation support for non-IPv6 environments [pp] M ./libsofia-sip-ua/nta/nta.c +9 M ./libsofia-sip-ua/nta/portbind.c -1 +2 M ./libsofia-sip-ua/nta/test_nta.c +5 M ./libsofia-sip-ua/sip/Makefile.am -2 +2 M ./libsofia-sip-ua/soa/soa.c +7 M ./libsofia-sip-ua/su/su.h +6 M ./libsofia-sip-ua/su/su_root.c +14 M ./libsofia-sip-ua/tport/test_tport.c -1 +1 M ./libsofia-sip-ua/tport/tport.c -1 +58 * additional #ifdefs for IPv6 (un)support. [mm] M ./libsofia-sip-ua/sresolv/sresolv.c +13 M ./libsofia-sip-ua/sresolv/sresolv.h +4 M ./libsofia-sip-ua/sresolv/test_sresolv.c +18 * Added check for socket library. [pp] M ./configure.ac -1 M ./m4/sac-su.m4 +2 * Fixed .h file generation. [pp] M ./libsofia-sip-ua/msg/Makefile.am -1 +5 * Added test for recursive pthread_rwlock_rdlock()/pthread_rwlock_unlock(). M ./m4/sac-su2.m4 +41 * Using TP_AI flags not overlapping with AI flags in . [pp] M ./libsofia-sip-ua/tport/tport.c -4 +6 * Using red-black tree in su_timer.c. [pp] Added test using 500000 timers in su_timer_test.c. M ./libsofia-sip-ua/su/su_timer.c -130 +216 M ./libsofia-sip-ua/su/su_timer_test.c -13 +54 * Fixed bug in sdp_rtpmap_find_matching(). [pp] M ./libsofia-sip-ua/sdp/sdp.c -3 +1 * Cleaned up su_addrinfo.c. [pp] Cleaned up comments. Using SU_HAVE_ flags. Added support for SCTP in getaddrinfo() replacement. M ./libsofia-sip-ua/su/su_addrinfo.c -10 +38 * Declaring sockaddr_storage in su.h if it is not provided in environment. M ./libsofia-sip-ua/su/su.h +23 M ./libsofia-sip-ua/su/su_configure.h.in +3 M ./libsofia-sip-ua/su/su_configure_win32.h +6 M ./m4/sac-su2.m4 +7 * Support for CygWin's (buggy) pthread implementation. [mm] Added SU_HAVE_IN6 for disabling IPv6 support from the environments that do not support IPv6. M ./libsofia-sip-ua/su/addrinfo.c +11 M ./libsofia-sip-ua/su/localinfo.c +6 M ./libsofia-sip-ua/su/su_localinfo.c -1 +4 M ./libsofia-sip-ua/su/su_port.c -1 +38 M ./libsofia-sip-ua/su/su_proxy.c +2 M ./libsofia-sip-ua/su/su_root_test.c -1 +3 M ./libsofia-sip-ua/su/su_test.c -4 +6 2005-11-30 Pekka Pessi Syncing darcs with CVS. * Silenced warning in su_addrinfo.c. M ./libsofia-sip-ua/su/su_addrinfo.c -1 +2 * Added su_getaddrinfo() and su_getnameinfo() replacement functions. M ./libsofia-sip-ua/su/Makefile.am -2 +3 M ./libsofia-sip-ua/su/su.c -58 M ./libsofia-sip-ua/su/su.h -15 +1 A ./libsofia-sip-ua/su/su_addrinfo.c A ./libsofia-sip-ua/su/su_addrinfo.h M ./libsofia-sip-ua/su/su_configure.h.in +3 M ./libsofia-sip-ua/su/su_localinfo.c -3 +3 M ./libsofia-sip-ua/su/su_wait.h -2 +2 M ./m4/sac-su2.m4 -2 +8 * Not using Unix network includes, use Sofia includes. M ./libsofia-sip-ua/sresolv/sresolv.c -1 +1 * Using AC_GNU_SOURCE. M ./configure.ac -2 +2 * Using sip-options consistently in utils/sip-options.c. M ./utils/sip-options.c -8 +9 * Updated RELEASE and TODO. M ./RELEASE +4 M ./TODO -2 +2 * Using nua_i_state event in nua_cli.c. M ./utils/nua_cli.c -76 +88 * Updated ABNF grammar for Subscription-State in sip_event.c. Added more tests for Subscription-State. M ./libsofia-sip-ua/sip/sip_event.c -12 +17 M ./libsofia-sip-ua/sip/torture_sip.c -13 +16 * Fixed test_class.c documentation. M ./libsofia-sip-ua/msg/test_class.c -2 +2 * Proofread conformance specification. M ./libsofia-sip-ua/docs/conformance.docs -375 +547 * Fixed doxytags for main doxygen pages. M ./libsofia-sip-ua/docs/Doxyfile -16 +16 * Fixed types of NUATAGs Changed type of NUTAG_INVITE_TIMER, NUTAG_SESSION_TIMER, and NUTAG_MIN_SE value to unsigned. M ./libsofia-sip-ua/nua/nua_tag.c -3 +3 * Added test for handlin refer subscriptions. M ./libsofia-sip-ua/nua/test_nua.c -1 +58 * Added test_mime_negotiation() to test_nua.c M ./libsofia-sip-ua/nua/test_nua.c +166 * Cosmetic changes in nua_dialog_usage_t in nua_stack.h. M ./libsofia-sip-ua/nua/nua_stack.c -2 +1 M ./libsofia-sip-ua/nua/nua_stack.h -3 +3 * Added NHP_ISSET() to nua_stack.h. M ./libsofia-sip-ua/nua/nua_stack.h -1 +5 * Added process_subsribe() for refer subscriptions in nua_stack.c. M ./libsofia-sip-ua/nua/nua_stack.c +88 * Removed duplicate nua_i_subscription. M ./libsofia-sip-ua/nua/nua_common.c -2 * Renumbered test cases, state transitions in nua.docs and test_nua.c. M ./libsofia-sip-ua/nua/nua.docs -79 +79 M ./libsofia-sip-ua/nua/nua_stack.c +3 M ./libsofia-sip-ua/nua/test_nua.c -78 +131 * Added NUTAG_REFER_EXPIRES() with default value of 300. Handling expiration of implicit subscriptions created by REFER. M ./libsofia-sip-ua/nua/nua_stack.c -1 +75 M ./libsofia-sip-ua/nua/nua_stack.h +4 M ./libsofia-sip-ua/nua/nua_tag.c +2 M ./libsofia-sip-ua/nua/nua_tag.h +26 * Refactored register_expires_contacts() Fixed memory leak, bug in '*'handling. M ./libsofia-sip-ua/nua/nua_stack.c -10 +18 * Rewrote uas_check_session_content(). Returning empty Accept-Encoding header in 415/406 responses. M ./libsofia-sip-ua/nua/nua_stack.c -21 +41 * Do not throttle at termination. [FIX] nea_server now sends NOTIFYs that terminate subscription even if the previous NOTIFY transaction has not completed yet. This fixes the race condition in nua_terminate() (where terminating NOTIFY was is never sent). M ./libsofia-sip-ua/nea/nea_server.c -1 +4 * Fixed rule to build sip_tag_ref.c. M ./libsofia-sip-ua/sip/Makefile.am -2 +1 * Explicitly saving and destroying messages in ua_signal(). M ./libsofia-sip-ua/nua/nua_stack.c -23 +23 M ./libsofia-sip-ua/nua/nua_stack.h +1 * Updated Content-Encoding (e) header parsing. M ./libsofia-sip-ua/sip/sip.h -1 +1 M ./libsofia-sip-ua/sip/sip_mime.c -4 +4 M ./libsofia-sip-ua/sip/torture_sip.c -3 +4 * Updated Session-Expires and Min-SE header to RFC 4028. A parameter list was added to Min-SE header. M ./libsofia-sip-ua/sip/sip.h +1 M ./libsofia-sip-ua/sip/sip_session.c -18 +30 M ./libsofia-sip-ua/sip/torture_sip.c +10 * Update RELEASE. Added text about API changes related nua_authorize(), nua_i_subscription and NEATAG_SUB(), NUTAG_HOLD(), sdp_rtpmap_t. Mentioning su_getlocalinfo() bug. M ./RELEASE -3 +16 * Fixed installing and distributing m4 files. Not installing m4/sac-su2.m4. Including m4/sac-tport.m4 and m4/sac-openssl.m4 in distribution. M ./Makefile.am -1 +2 * Deprecated NUTAG_HOLD(). * Updated documentation in nea, nua, nta, sip and tport modules. * Updated documentation. M ./libsofia-sip-ua/docs/Doxyfile.aliases +1 M ./libsofia-sip-ua/docs/conformance.docs -172 +177 M ./libsofia-sip-ua/docs/mainpage.docs -5 +7 * Updated subscriptuion authorization and nua_terminate() semantics. Subscription authorization now rejects SUBSCRIBE if NUTAG_SUBSTATE(nua_substate_terminated) parameter is set. Correct status code is relayed to application, too. nua_terminate() now always terminates whole notifier. M ./libsofia-sip-ua/nua/nua_stack.c -49 +65 * Fixed nua_handle_has_active_call() in nua_stack.c. M ./libsofia-sip-ua/nua/nua_stack.c +10 M ./libsofia-sip-ua/nua/test_nua.c +32 * Renamed authenticate_watcher() as authorize_watcher(). M ./libsofia-sip-ua/nua/nua_stack.c -13 +13 * Cleanup of subscription logging and comments in nua_stack.c. M ./libsofia-sip-ua/nua/nua_stack.c -21 +41 * Using SIPTAG_END() in nua_stack.c. We now pass NTATAG and TPTAG to lower layers. Beware. M ./libsofia-sip-ua/nua/nua_stack.c -28 +29 * Added NH_PISSET() macro to . M ./libsofia-sip-ua/nua/nua_stack.c -2 +8 M ./libsofia-sip-ua/nua/nua_stack.h +7 * Fixed doxytag file names for modules nea and features. M ./libsofia-sip-ua/docs/Doxyfile -1 +1 M ./libsofia-sip-ua/features/Doxyfile -1 +1 M ./libsofia-sip-ua/nea/Doxyfile -1 +1 * Moved typedefs nua_t and nua_handle_t into M ./libsofia-sip-ua/nua/nua.h -6 M ./libsofia-sip-ua/nua/nua_tag.h -3 +6 * Added sip_add_tagis() and SIPTAG_END(). SIPTAG_END() allows grouping tags into blocks. M ./libsofia-sip-ua/sip/sip_header.h +3 M ./libsofia-sip-ua/sip/sip_tag.c.in -1 +2 M ./libsofia-sip-ua/sip/sip_tag.h.in +4 M ./libsofia-sip-ua/sip/sip_tag_class.c -12 +38 M ./libsofia-sip-ua/sip/torture_sip.c +12 * Fixed scope for V4MAPPED and V4COMPAT IP6 addresses in su_localinfo.c. M ./libsofia-sip-ua/su/su_localinfo.c -6 +21 * Cleaned up debug printing in su_memmem.c. M ./libsofia-sip-ua/su/su_memmem.c -11 +21 * Added end_tag_class[]. M ./libsofia-sip-ua/su/su_tag_class.h -13 +1 M ./libsofia-sip-ua/su/su_tag_inline.h -1 +1 M ./libsofia-sip-ua/su/su_taglist.c -48 +84 * Added replacement functions memccpy(). Also moved memcspn() to a file of its own. M ./libsofia-sip-ua/su/Makefile.am -5 +13 A ./libsofia-sip-ua/su/memccpy.c A ./libsofia-sip-ua/su/memcspn.c M ./libsofia-sip-ua/su/memspn.c -50 +1 M ./libsofia-sip-ua/su/strcasestr.c -1 +1 M ./m4/sac-su2.m4 -2 +13 * Added win32/config.h.in M ./configure.ac +1 A ./win32/config.h.in * Added AC_TYPE_LONGLONG. M ./configure.ac -3 +2 M ./m4/sac-general.m4 -7 +5 * Tried to fix automatic generation of source files. M ./libsofia-sip-ua/http/Makefile.am -10 +9 M ./libsofia-sip-ua/msg/Makefile.am -22 +14 M ./libsofia-sip-ua/sip/Makefile.am -13 +12 * Moved bitfields last in sdp_rtpmap_t aka struct sdp_rtpmap_s. M ./libsofia-sip-ua/sdp/sdp.c -1 +3 M ./libsofia-sip-ua/sdp/sdp.h -5 +5 M ./libsofia-sip-ua/sdp/sdp_parse.c -2 +2 M ./libsofia-sip-ua/sdp/sdp_torture.c -4 +9 * Removed RFC2543-compatible tag code. M ./libsofia-sip-ua/nta/nta.c -95 +46 M ./libsofia-sip-ua/nta/nta.h -4 +3 M ./libsofia-sip-ua/nta/nta_tag.h -2 +2 M ./libsofia-sip-ua/nta/test_nta.c -18 +20 * Fixed memory leaks in tport.c and nta.c. M ./libsofia-sip-ua/nta/nta.c +11 M ./libsofia-sip-ua/tport/tport.c +2 * Fixed a memory leak when processing re-SUBSCRIBE in nea_server.c. M ./libsofia-sip-ua/nea/nea_server.c -2 +2 * Cleaned #including standard headers in msg module. M ./libsofia-sip-ua/msg/msg_header.h +1 M ./libsofia-sip-ua/msg/test_msg.c -7 +7 * Removed extra prototype. M ./libsofia-sip-ua/iptsec/auth_plugin_delayed.c -4 * Casting getpid() return type to something accepted by printf(). M ./libsofia-sip-ua/nua/test_nua.c -1 +1 * Doing system #include after sofia #include. M ./libsofia-sip-ua/nua/test_nua.c -12 +11 * Not using nta_incoming_tag_3261() anymore. M ./libsofia-sip-ua/nua/nua_stack.c -4 +2 * Added #include to libsofia-sip-ua/su/su.h. M ./libsofia-sip-ua/su/su.h -2 +3 * Added client timeout and NTHTAG_EXPIRES() to nth http client library. M ./libsofia-sip-ua/nth/nth_client.c -7 +29 M ./libsofia-sip-ua/nth/nth_tag.c -1 +2 M ./libsofia-sip-ua/nth/nth_tag.h -1 +7 M ./libsofia-sip-ua/nth/nth_test.c -9 +111 * Fixed RFC 1890/RFC 1891. M ./libsofia-sip-ua/docs/Doxyfile.aliases +2 * Added conformance.docs M ./libsofia-sip-ua/docs/Doxyfile -1 +1 A ./libsofia-sip-ua/docs/conformance.docs * Moved memspn from msg module to su ./libsofia-sip-ua/msg/memspn.c -> ./libsofia-sip-ua/su/memspn.c * Using package-specific install directory for public header files. Default install directory for public header file has been changed from '${prefix}/include/' to '${prefix}/include/sofia-sip-MAJOR.MINOR'. The pkgconfig .pc file has been updated accordingly. * Removed R ./win32/config.h 2005-11-28 Martti Mela * Added nua_authorize(), enhanced nua_i_subscription. Added nua_notifier test cases for test_nua. With great help from Pekka. M ./libsofia-sip-ua/nea/Makefile.am M ./libsofia-sip-ua/nea/nea.h M ./libsofia-sip-ua/nea/nea_tag.c M ./libsofia-sip-ua/nta/test_nta.c M ./libsofia-sip-ua/nua/nua.c M ./libsofia-sip-ua/nua/nua.docs M ./libsofia-sip-ua/nua/nua.h M ./libsofia-sip-ua/nua/nua_common.c M ./libsofia-sip-ua/nua/nua_stack.c M ./libsofia-sip-ua/nua/nua_stack.h M ./libsofia-sip-ua/nua/test_nua.c M ./libsofia-sip-ua/nua/test_proxy.c M ./utils/Makefile.am 2005-11-28 Martti Mela * nua.h: added event nua_i_subscription * nua_commmon.c: added event nua_i_subscription * nua_stack.c: ua_event for nua_i_subscription (nea subscribers) * nea.h, nea_tag.c, nea_tag_ref.c, nea_server.c: support for a new tag, NEATAG_SUB(). Added nea_sub_get_request(). 2005-11-15 Kai Vehmanen * configure.ac: Added VER_LIBSOFIA_SIP_UA variables. 2005-11-14 Pekka Pessi tagged rel-sofia-sip-1_11_4 * Fixed Win32 includes for XP. Added win32/README.txt. M ./libsofia-sip-ua/su/su.h -4 +5 M ./win32/Makefile.am -1 +2 A ./win32/README.txt * Added a blurb about win32 bugs into RELEASE. M ./RELEASE -1 +3 2005-11-11 Pekka Pessi * Updated RELEASE. M ./RELEASE -1 +9 * Updated dua documentation. M ./libsofia-sip-ua/nua/nua.c +4 M ./libsofia-sip-ua/nua/nua.docs -10 +12 M ./libsofia-sip-ua/nua/nua_stack.h -2 +3 * Fixed warnings in libsofia-sip-ua/tport/tport.c. M ./libsofia-sip-ua/tport/tport.c -2 +1 * Fixed WIN32 test cases in libsofia-sip-ua/su/su_torture.c. Using SU_WAIT_TIMEOUT and correct IP address. M ./libsofia-sip-ua/su/su_torture.c -2 +2 * Added codec-level negotiation and codec selection for RTP media. Added SOATAG_RTP_SELECT(), SOATAG_RTP_SORT() and SOATAG_RTP_MISMATCH() for indicating sdp negotiation preferences. Select the RTP codec according to the preferences when sending or processing the answer. M ./libsofia-sip-ua/soa/soa.c -7 +52 M ./libsofia-sip-ua/soa/soa_session.h +5 M ./libsofia-sip-ua/soa/soa_static.c -21 +320 M ./libsofia-sip-ua/soa/soa_tag.c +89 M ./libsofia-sip-ua/soa/soa_tag.h +19 M ./libsofia-sip-ua/soa/test_soa.c -19 +382 * Added funtions for rtp payload type management. Added sdp_media_uses_rtp(), sdp_rtpmap_match(), sdp_rtpmap_find_matching() and sdp_rtpmap_well_known[]. Fixed RTP timestamp rate for G722: it was 16000 but it should be 8000. M ./libsofia-sip-ua/sdp/sdp.c -1 +76 M ./libsofia-sip-ua/sdp/sdp.h +12 M ./libsofia-sip-ua/sdp/sdp_parse.c -37 +94 M ./libsofia-sip-ua/sdp/sdp_torture.c -11 +140 * Generating browsing info for win32 projects. M ./win32/libsofia-sip-ua/libsofia_sip_ua.dsp -2 +2 M ./win32/nta_test/nta_test.dsp -1 +1 M ./win32/su/su_alloc_test/su_alloc_test.dsp -2 +2 M ./win32/su/su_root_test/su_root_test.dsp -2 +2 M ./win32/su/su_tag_test/su_tag_test.dsp -2 +2 M ./win32/su/su_test/su_test.dsp -2 +2 M ./win32/su/su_time_test/su_time_test.dsp -2 +2 M ./win32/su/su_timer_test/su_timer_test.dsp -2 +2 M ./win32/su/su_torture/su_torture.dsp -2 +2 M ./win32/su/test_memmem/test_memmem.dsp -2 +2 M ./win32/su/torture_htable/torture_htable.dsp -2 +2 M ./win32/su/torture_rbtree/torture_rbtree.dsp -2 +2 M ./win32/su/torture_su_memmem/torture_su_memmem.dsp -2 +2 M ./win32/su/torture_su_port/torture_su_port.dsp -2 +2 * Added tests for su_vsend() and su_vrecv() in su_torture.c. M ./libsofia-sip-ua/su/su_torture.c +89 * Added #include to nua_stack.c (because MSG_TIME_MAX). M ./libsofia-sip-ua/nua/nua_stack.c +1 * Added SU_WAIT_CONNECT. Fixed su_vrecv() and su_vsend() on Win32. M ./libsofia-sip-ua/su/su.c -9 +10 M ./libsofia-sip-ua/su/su_wait.h +3 * Fixed tport.c on Win32 port. Added a separate "connecting" phase. Checking EWOULDBLOCK in addition to EAGAIN. Fixed TP_AI_CLOSE and TP_AI_SHUTDOWN flags. Improved logging. M ./libsofia-sip-ua/tport/tport.c -35 +98 * Removed 1.11.3 stuff from RELEASE. M ./RELEASE -16 +2 * Removed Last modified from ipt module. M ./libsofia-sip-ua/ipt/rc4.h -1 M ./libsofia-sip-ua/ipt/torture_base64.c -1 M ./libsofia-sip-ua/ipt/ucs2.c -1 M ./libsofia-sip-ua/ipt/ucs4.c -1 M ./libsofia-sip-ua/ipt/uniqueid.h -1 M ./libsofia-sip-ua/ipt/utf8.c -1 M ./libsofia-sip-ua/ipt/utf8.h -1 M ./libsofia-sip-ua/ipt/utf8internal.h -1 M ./libsofia-sip-ua/ipt/utf8test.c -1 * Removed Last modified from sdp module. M ./libsofia-sip-ua/sdp/sdp.c -1 M ./libsofia-sip-ua/sdp/sdp.h -1 M ./libsofia-sip-ua/sdp/sdp_parse.c -1 M ./libsofia-sip-ua/sdp/sdp_rtp.h -1 M ./libsofia-sip-ua/sdp/sdp_tag.c -1 M ./libsofia-sip-ua/sdp/sdp_tag.h -1 M ./libsofia-sip-ua/sdp/sdp_test.c -1 M ./libsofia-sip-ua/sdp/sdp_torture.c -1 2005-11-10 Pekka Pessi * Avoid comp=sigcomp in Via in nta/nta.c Not inserting comp=sigcomp in topmost Via of request if there is no comp=sigcomp in request-URI or route-URI. M ./libsofia-sip-ua/nta/nta.c -20 +15 * Added Doxygen entries for SIPTAG_*_REF. M ./libsofia-sip-ua/sip/sip_tag.h.in -5 +17 * Fixed AC_DEFINE([HAVE_SOFIA_SIGCOMP]) M ./m4/sac-tport.m4 -1 +1 * Not using $(srcdir)/../ for Makefile.am inclusion. M ./libsofia-sip-ua/features/Makefile.am -1 +1 M ./libsofia-sip-ua/nua/Makefile.am -1 +1 M ./libsofia-sip-ua/sdp/Makefile.am -1 +1 M ./libsofia-sip-ua/soa/Makefile.am -1 +1 * Added PACKAGE_NAME and PACKAGE_VERSION to msg_parser.awk. M ./libsofia-sip-ua/msg/msg_parser.awk +2 * Not using ancient MSG_DUMP and MSG_STREAM_LOG env variables. Use TPORT_DUMP and TPORT_LOG instead. M ./utils/nua_env -3 +3 * Fixed --without-glib case in m4/sac-su2.m4. M ./m4/sac-su2.m4 -4 +7 * Removed m4/sac-glib.m4 R ./m4/sac-glib.m4 2005-11-09 Pekka Pessi * Updated documentation of nta_agent_add_tport(). The uri parameter to nta_agent_add_tport() is used to control which sockets the tport binds the server sockets as well as which transport, encryption and compression protocols are used. M ./libsofia-sip-ua/nta/nta.c -1 +46 2005-11-08 Pekka Pessi tagged rel-sofia-sip-1_11_3 * Not using sip_params_replace(). M ./libsofia-sip-ua/nua/nua_stack.c -2 +2 * Using sip_complete_message instead of sip_message_complete in nua_stack.c. M ./libsofia-sip-ua/nua/nua_stack.c -1 +1 * Removed $(srcdir)s from built_sources targets in libsofia-sip-ua/sofia.am M ./libsofia-sip-ua/sofia.am -2 +2 * Updated nta ChangeLog. M ./libsofia-sip-ua/nta/ChangeLog +4 * Renamed tport_test.c as test_tport.c ./libsofia-sip-ua/tport/tport_test.c -> ./libsofia-sip-ua/tport/test_tport.c M ./libsofia-sip-ua/tport/ChangeLog +4 M ./libsofia-sip-ua/tport/Doxyfile -1 +1 M ./libsofia-sip-ua/tport/Makefile.am -7 +9 M ./libsofia-sip-ua/tport/test_tport.c -1 +1 R ./libsofia-sip-ua/tport/tport_test.h * Renamed test modules and programs. Renamed msg_test.c as test_msg.c. Renamed msg_test_class.[hc] as test_class.[hc], msg_test_protos.h(.in) as test_protos.h(.in), msg_test_table.c(.in) as test_table.c(.in). ./libsofia-sip-ua/msg/msg_test.c -> ./libsofia-sip-ua/msg/test_msg.c ./libsofia-sip-ua/msg/msg_test_class.c -> ./libsofia-sip-ua/msg/test_class.c ./libsofia-sip-ua/msg/msg_test_class.h -> ./libsofia-sip-ua/msg/test_class.h ./libsofia-sip-ua/msg/msg_test_protos.h.in -> ./libsofia-sip-ua/msg/test_protos.h.in ./libsofia-sip-ua/msg/msg_test_table.c.in -> ./libsofia-sip-ua/msg/test_table.c.in M ./libsofia-sip-ua/msg/ChangeLog +8 M ./libsofia-sip-ua/msg/Makefile.am -28 +36 M ./libsofia-sip-ua/msg/msg.docs -1 +1 M ./libsofia-sip-ua/msg/msg_name_hash.c -1 +1 M ./libsofia-sip-ua/msg/test_class.c -8 +8 M ./libsofia-sip-ua/msg/test_class.h -3 +3 M ./libsofia-sip-ua/msg/test_msg.c -5 +5 M ./libsofia-sip-ua/msg/test_protos.h.in -7 +7 M ./libsofia-sip-ua/msg/test_table.c.in -7 +7 M ./libsofia-sip-ua/tport/tport_test.c -2 +2 * Renamed auth_digest_test.c as test_auth_digest.c. ./libsofia-sip-ua/iptsec/auth_digest_test.c -> ./libsofia-sip-ua/iptsec/test_auth_digest.c M ./libsofia-sip-ua/iptsec/ChangeLog +4 M ./libsofia-sip-ua/iptsec/Makefile.am -3 +3 M ./libsofia-sip-ua/iptsec/test_auth_digest.c -4 +4 * Renamed http_test.c as test_http.c. ./libsofia-sip-ua/http/http_test.c -> ./libsofia-sip-ua/http/test_http.c M ./libsofia-sip-ua/http/ChangeLog +4 M ./libsofia-sip-ua/http/Makefile.am -3 +3 M ./libsofia-sip-ua/http/test_http.c -6 +6 2005-11-07 Pekka Pessi * Using new nta_agent_create() prototype in utils/sip-options.c M ./utils/sip-options.c -1 +1 * Added test proxy to nua module. M ./libsofia-sip-ua/nua/Makefile.am +2 M ./libsofia-sip-ua/nua/test_nua.c -35 +175 A ./libsofia-sip-ua/nua/test_proxy.c A ./libsofia-sip-ua/nua/test_proxy.h * Cleaned up sip parser. Renamed msg_name_addr_d/msg_name_addr_e as sip_name_addr_d/sip_name_addr_e (because the function is sip-specific). Not using old sip-specific parser macros. M ./libsofia-sip-ua/sip/sip.docs -6 +3 M ./libsofia-sip-ua/sip/sip.h -1 +1 M ./libsofia-sip-ua/sip/sip_basic.c -100 +284 M ./libsofia-sip-ua/sip/sip_caller_prefs.c -13 +13 M ./libsofia-sip-ua/sip/sip_event.c -32 +32 M ./libsofia-sip-ua/sip/sip_extra.c -13 +13 M ./libsofia-sip-ua/sip/sip_feature.c -8 +8 M ./libsofia-sip-ua/sip/sip_header.c -36 +3 M ./libsofia-sip-ua/sip/sip_mime.c -18 +18 M ./libsofia-sip-ua/sip/sip_parser.c -12 +12 M ./libsofia-sip-ua/sip/sip_parser.h -3 +14 M ./libsofia-sip-ua/sip/sip_prack.c -2 +2 M ./libsofia-sip-ua/sip/sip_pref_util.c -2 +2 M ./libsofia-sip-ua/sip/sip_reason.c -6 +6 M ./libsofia-sip-ua/sip/sip_refer.c -24 +24 M ./libsofia-sip-ua/sip/sip_rfc2543.c -2 +2 M ./libsofia-sip-ua/sip/sip_security.c -10 +10 M ./libsofia-sip-ua/sip/sip_session.c -6 +6 M ./libsofia-sip-ua/sip/sip_tag_class.c -11 +14 M ./libsofia-sip-ua/sip/sip_time.c -1 +1 M ./libsofia-sip-ua/sip/sip_util.c -47 +19 M ./libsofia-sip-ua/sip/torture_sip.c -8 +56 * Updated documentation in url module. M ./libsofia-sip-ua/url/torture_url.c -3 +2 M ./libsofia-sip-ua/url/url.c -3 +5 M ./libsofia-sip-ua/url/url.h -3 +1 M ./libsofia-sip-ua/url/url_tag.c -4 +2 M ./libsofia-sip-ua/url/url_tag.h -3 +2 M ./libsofia-sip-ua/url/url_tag_class.h -3 +2 * Using updated nta api in nua module. M ./libsofia-sip-ua/nua/nua_stack.c -23 +34 * Not using msg_copy_all(). M ./libsofia-sip-ua/nth/nth_client.c -11 +6 * Not misusing SIP_NONE. M ./libsofia-sip-ua/sip/torture_sip.c -2 +2 * Updated documentation in msg module. Removed bogus @ingroup msg. M ./libsofia-sip-ua/msg/msg.c -3 +1 M ./libsofia-sip-ua/msg/msg.h -4 +1 M ./libsofia-sip-ua/msg/msg_addr.h -2 +1 M ./libsofia-sip-ua/msg/msg_buffer.h -2 +1 M ./libsofia-sip-ua/msg/msg_dll.h -3 +1 M ./libsofia-sip-ua/msg/msg_tag.c -2 +1 M ./libsofia-sip-ua/msg/msg_tag_class.h -4 +1 * Updated msg module interfaces. Added msg_header_free(), msg_header_free_all(). Removed msg_dup_all() and msg_copy_all(). M ./libsofia-sip-ua/msg/msg.h -2 +2 M ./libsofia-sip-ua/msg/msg_header.h -3 +8 M ./libsofia-sip-ua/msg/msg_header_copy.c +159 M ./libsofia-sip-ua/msg/msg_internal.h -2 +28 M ./libsofia-sip-ua/msg/msg_mime.c -48 +47 M ./libsofia-sip-ua/msg/msg_parser.c -198 +21 M ./libsofia-sip-ua/msg/msg_parser_util.c -171 +14 M ./libsofia-sip-ua/msg/msg_test.c -69 +41 M ./libsofia-sip-ua/msg/msg_test_class.c -28 +24 M ./libsofia-sip-ua/msg/msg_test_class.h -3 +2 M ./libsofia-sip-ua/msg/msg_test_protos.h.in -2 +2 * Removed msg_clone() from msg module. Moved msg_set_parent() into msg/msg.c. M ./libsofia-sip-ua/msg/msg.c +23 M ./libsofia-sip-ua/msg/msg.h -2 M ./libsofia-sip-ua/msg/msg_parser.c -46 * Cleaned up nta module interfaces. Use uint32_t instead of sip_u32_t. Removed old funtions not using reference counting with messages: Replaced nta_outgoing_getresponse() with nta_outgoing_getresponse_ref(), and nta_outgoing_getrequest() with nta_outgoing_getrequest_ref(). Removed nta_incoming_getresponse(), nta_leg_stateful(). Removed nta_outgoing_tmcreate(): use nta_outgoing_mcreate() instead. M ./libsofia-sip-ua/nta/nta.c -298 +243 M ./libsofia-sip-ua/nta/nta.h -21 +14 M ./libsofia-sip-ua/nta/nta_compat.c -6 +132 M ./libsofia-sip-ua/nta/nta_compat.h +3 M ./libsofia-sip-ua/nta/nta_internal.h -11 +4 M ./libsofia-sip-ua/nta/nta_stateless.h -9 +5 M ./libsofia-sip-ua/nta/run_test_nta -5 +5 M ./libsofia-sip-ua/nta/sl_utils_log.c -1 +1 M ./libsofia-sip-ua/nta/sl_utils_print.c -1 +1 M ./libsofia-sip-ua/nta/test_nta.c -24 +14 * Not using msg_clone(). M ./libsofia-sip-ua/nth/nth_client.c -1 +1 * Not using stateless functions anymore in nea. M ./libsofia-sip-ua/nea/nea.h -12 +3 M ./libsofia-sip-ua/nea/nea_server.c -8 +3 * Removed sip_complete_response(). M ./libsofia-sip-ua/sip/sip_parser.c -47 M ./libsofia-sip-ua/sip/sip_util.h -7 * Not using sip_none anymore. M ./libsofia-sip-ua/sip/sip_header.c -1 +1 * Fixed sip_object() prototype. M ./libsofia-sip-ua/sip/sip_protos.h.in -1 +1 * Cleaned up sip types. Not using special typedefs sip_u32_t or sip_u16_t. M ./libsofia-sip-ua/sip/sip.h -15 +11 M ./libsofia-sip-ua/sip/sip_basic.c -4 +4 M ./libsofia-sip-ua/sip/sip_header.h -2 +2 M ./libsofia-sip-ua/sip/sip_util.c -2 +2 M ./libsofia-sip-ua/sip/sip_util.h -1 +1 * Defining MSG_TIME_MAX both in msg_types.h and msg_time.h. M ./libsofia-sip-ua/msg/msg_date.h -3 +6 M ./libsofia-sip-ua/msg/msg_types.h -1 +6 * Removed sip_transport.c. R ./libsofia-sip-ua/sip/sip_transport.c * Removed annoying Last modified from iptsec. 2005-11-04 Pekka Pessi * Removed annoying Last modified from msg module. * Removed Last modified things from sip module. * Removed sip/sip_transport.[hc], not used anymore. R ./libsofia-sip-ua/sip/sip_transport.c R ./libsofia-sip-ua/sip/sip_transport.h 2005-11-03 Pekka Pessi * Renamed nta_test as test_nta. ./libsofia-sip-ua/nta/nta_test.c -> ./libsofia-sip-ua/nta/test_nta.c ./libsofia-sip-ua/nta/run_nta_test -> ./libsofia-sip-ua/nta/run_test_nta M ./libsofia-sip-ua/nta/Makefile.am -4 +4 M ./libsofia-sip-ua/nta/run_test_nta -2 +2 * Updated libsofia-sip-ua/nua/ChangeLog. M ./libsofia-sip-ua/nua/ChangeLog +21 * Fixed race in nea/nea_server.c. Do not free subscribers while they are being processed by application. M ./libsofia-sip-ua/nea/nea_server.c -5 +7 * Added unpublish, unregister, do_register to nua/test_nua.c. M ./libsofia-sip-ua/nua/test_nua.c -8 +28 * Added test_events(). M ./libsofia-sip-ua/nua/test_nua.c +409 * Added nua_unpublish(). Some cosmetic changes, too. M ./libsofia-sip-ua/nua/nua.h -1 +4 M ./libsofia-sip-ua/nua/nua_stack.c -1 +1 * Cleaned up allocations in nua/test_nua.c. M ./libsofia-sip-ua/nua/test_nua.c -6 +8 * Added loopback message test. M ./libsofia-sip-ua/nua/test_nua.c +49 2005-11-02 Pekka Pessi * Fixed buglets in su/su_alloc.c. su_alloc() did zero memory. su_realloc() used su_alloc(). M ./libsofia-sip-ua/su/su_alloc.c -5 +7 * Closing /proc/net/if_inet6 after use in su/su_localinfo.c. M ./libsofia-sip-ua/su/su_localinfo.c +2 * Using su_home_new(). M ./libsofia-sip-ua/msg/msg.c -2 +2 * Fixed allocation code for message parser table. Allocating parser table as a single memory block. M ./libsofia-sip-ua/msg/msg_mclass.c -12 +12 M ./libsofia-sip-ua/sresolv/test_sresolv.c -3 +15 * Updated documentation in nta/nta_stateless.h. M ./libsofia-sip-ua/nta/nta_stateless.h -4 +4 * Plugging memory leaks in nta. Plugged memory leaks in 100rel code. M ./libsofia-sip-ua/nta/nta.c -38 +63 M ./libsofia-sip-ua/nta/nta_test.c -31 +109 * Moved deprecated functions to nta/nta_compat.c. nta_msg_vsend() and msg_msg_send() should not be used anymore. nta_msg_discard() is also deprecated, but getting rid of references to it takes time. M ./libsofia-sip-ua/nta/nta.c -43 +42 M ./libsofia-sip-ua/nta/nta_compat.c -1 +31 * Plugged memory leak in nth_engine_create() in nth/nth_client.c Use su_home_new() instead of su_salloc(). M ./libsofia-sip-ua/nth/nth_client.c -3 +2 2005-11-01 Pekka Pessi tagged rel-sofia-sip_1_11_2+win32 * Disabled listen-on-v6 in sresolv/run_test_sresolv. M ./libsofia-sip-ua/sresolv/run_test_sresolv -4 +15 * Fixed search path on sresolc/sresolv.c Not invoking callback on main query if subqueries are still running. M ./libsofia-sip-ua/sresolv/sresolv.c -11 +20 * Added ns record for root.zone. M ./libsofia-sip-ua/sresolv/root.zone -1 +5 * Using su_close() instead of close(). M ./libsofia-sip-ua/sresolv/test_sresolv.c -3 +3 M ./libsofia-sip-ua/stun/stun.c -1 +1 M ./libsofia-sip-ua/tport/tport.c -1 +1 * Fixed HAVE_SIGPIPE. M ./configure.ac -1 +2 * Using SU_HAVE_GLIB. M ./libsofia-sip-ua/su/su_test.c -2 +2 * Removed annoying last modified. M ./libsofia-sip-ua/sresolv/sresolv.c -2 M ./libsofia-sip-ua/sresolv/test_sresolv.c -1 M ./libsofia-sip-ua/stun/stun.c -1 * Using AC_DEFINE with HAVE_SOFIA_STUN. M ./configure.ac -1 +1 * Removed annoying Last modified from su and win32 files. * Not using sint32_t. M ./libsofia-sip-ua/su/su.c -1 M ./libsofia-sip-ua/su/su.h -1 M ./libsofia-sip-ua/su/su_localinfo.c -4 +4 * Fixed ipv6 side on libc replacement libsofia_sip_ua/su/inet_pton.c. M ./libsofia-sip-ua/su/inet_pton.c -20 +20 * Removed ntv6 files from win32 port. M ./win32/Makefile.am -23 +13 * Using win32 include files tpipv6.h and wspiapi.h provided by system. M ./win32/libsofia-sip-ua/libsofia_sip_ua.dsp -8 * Using SU_HAVE_IN6 on win32, too. M ./libsofia-sip-ua/su/su.c -1 +1 M ./libsofia-sip-ua/su/su.h -6 +6 M ./libsofia-sip-ua/su/su_torture.c -1 +1 M ./win32/config.h -3 +3 M ./win32/su_configure_win32.h -2 +1 * Added HAVE_SIGPIPE. M ./configure.ac +6 * Removed Microsoft include file win32/wspiapi.h. R ./win32/wspiapi.h * Removed win32 tpipv6.h file. R ./win32/tpipv6.h * Fixed win32 socket handling problems in su/su_root_test and torture_su_port.c. M ./libsofia-sip-ua/su/su_root_test.c +5 M ./libsofia-sip-ua/su/torture_su_port.c +4 * Renamed SU_SOCKADDR_INADDR_ANY as SU_HAS_INADDR_ANY() in su/su.h. M ./libsofia-sip-ua/su/su.h -2 +4 * Added "su" test programs to win32 port. * Fixed win32 config.h. M ./win32/config.h -3 +6 * Added su test programs to win32 workspace. M ./win32/SofiaSIP.dsw -1 +166 * Providing __func__ replacement in su/torture_su_port.c. M ./libsofia-sip-ua/su/torture_su_port.c -1 +7 * Not using IN6 if it is not found by configure. M ./libsofia-sip-ua/su/su_torture.c -1 +2 * Not using SIGPIPE if it is not found by configure. M ./libsofia-sip-ua/su/su_timer_test.c +2 * Not using glib in su/su_test.c if it is not found by configure. M ./libsofia-sip-ua/su/su_test.c -2 +6 * Added inet_pton() and inet_ntop() replacement functions. M ./libsofia-sip-ua/su/Makefile.am -1 +2 M ./libsofia-sip-ua/su/inet_ntop.c -57 +30 A ./libsofia-sip-ua/su/inet_pton.c M ./libsofia-sip-ua/su/su.h -11 +2 * Removed ntv6 from include path of win32 port. M ./win32/libsofia-sip-ua/libsofia_sip_ua.dsp -6 +10 * Removed ntv6 files. R ./libsofia-sip-ua/su/aton.c R ./libsofia-sip-ua/su/ntoa.c 2005-10-31 Pekka Pessi * Fixed testcases not working with libc implementation. M ./libsofia-sip-ua/su/test_memmem.c -6 +6 * Defining SU_DLL in su/su_config.h for non-WIN32 targets. M ./libsofia-sip-ua/su/su_config.h -1 +1 * Removing libsofia-sip-ua/nea/nea_dll.h from dist, too. M ./libsofia-sip-ua/nea/Makefile.am -1 +1 * Added strtoull.c, strcasestr.c and inet_ntop.c to distribution. M ./libsofia-sip-ua/su/Makefile.am -1 +1 * Added inet_ntop() to libsofia-sip-ua/su A ./libsofia-sip-ua/su/inet_ntop.c * Not inlining attribute functions in tport/tport.c. M ./libsofia-sip-ua/tport/tport.c -4 +4 * Updated _DLL linkage things. The DLL linkage macros SIP_DLL, NTA_DLL, etc. are now defined in win32-specific config.h file. M ./libsofia-sip-ua/bnf/bnf.h -4 +5 M ./libsofia-sip-ua/http/http.h -9 +1 M ./libsofia-sip-ua/http/http_dll.h -3 +3 M ./libsofia-sip-ua/http/http_header.h -2 M ./libsofia-sip-ua/http/http_status.h -1 M ./libsofia-sip-ua/ipt/utf8.h -4 +6 M ./libsofia-sip-ua/iptsec/auth_dll.h -3 +3 M ./libsofia-sip-ua/msg/msg_dll.h -6 +6 M ./libsofia-sip-ua/nea/nea.h -8 +8 M ./libsofia-sip-ua/nta/nta_dll.h -3 +4 M ./libsofia-sip-ua/nth/nth_tag.h -3 +3 M ./libsofia-sip-ua/sdp/sdp.h -8 M ./libsofia-sip-ua/sdp/sdp_tag.h -4 +3 M ./libsofia-sip-ua/sip/sip_dll.h -5 +4 M ./libsofia-sip-ua/su/su_config.h -7 +3 M ./libsofia-sip-ua/tport/tport.h -9 M ./libsofia-sip-ua/tport/tport_tag.h -3 +3 M ./libsofia-sip-ua/url/url_dll.h -4 +3 * Removed nea/nea_dll.h R ./libsofia-sip-ua/nea/nea_dll.h * Added prototype for strcasestr() replacement function. M ./libsofia-sip-ua/soa/soa_static.c +3 * Added tests for strcasestr() replacement function. M ./libsofia-sip-ua/su/test_memmem.c -19 +148 * Removed double const. VC98 does not support ANSI const. M ./libsofia-sip-ua/su/su_wait.h -3 +3 * Fixed __func__ usage. VC98++ does not have __func__. Use innocent value instead. M ./libsofia-sip-ua/nua/nua_stack.h +2 M ./libsofia-sip-ua/soa/soa.c +7 * Fixed C99-ism in sdp/sdp_parse.c. A variable was declared in the middle of block. M ./libsofia-sip-ua/sdp/sdp_parse.c -4 +6 * Fixed setsockopt() in tport/tport.c. Explicit (void *) cast for argument of setsockopt(). M ./libsofia-sip-ua/tport/tport.c -2 +4 * Added missing replacement functions. A ./libsofia-sip-ua/su/strcasestr.c A ./libsofia-sip-ua/su/strtoull.c * Using longlong instead of long long. longlong is defined in "config.h". M ./libsofia-sip-ua/sdp/sdp_parse.c +4 M ./libsofia-sip-ua/sdp/sdp_print.c -1 +1 M ./libsofia-sip-ua/soa/soa.c -2 +2 M ./libsofia-sip-ua/su/tstdef.h -1 +1 * Using su_seterrno() and su_errno(). Not using directly errno in soa/soa.c and tport/tport.c. M ./libsofia-sip-ua/soa/soa.c -37 +38 M ./libsofia-sip-ua/tport/tport.c -10 +10 * Removed whoami from msg/msg_parser.awk. whoami is not used. M ./libsofia-sip-ua/msg/msg_parser.awk -1 2005-10-27 Pekka Pessi * Added coverage files used by gcc 3.4.3 to MOSTLYCLEANFILES. M ./m4/sac-general.m4 -1 +1 2005-10-21 Pekka Pessi * Fixed lib64 problem. M ./packages/sofia-sip.spec.in -6 +9 2005-10-13 Pekka Pessi * Removed RCS/CVS Ids and dates from files in order to allow smoother darcs usage. 2005-10-12 Pekka Pessi * Defining SU_HAVE_TAGSTACK. M ./libsofia-sip-ua/su/su_configure.h.in +3 M ./m4/sac-su2.m4 +6 2005-10-10 Pekka Pessi * Added --without-glib option, added SU_HAVE_GLIB in su_configure.h. M ./configure.ac -5 M ./libsofia-sip-ua/su/Makefile.am +2 M ./libsofia-sip-ua/su/su_configure.h.in +2 M ./m4/sac-su2.m4 -1 +22 * Added --output (and --help) options to coverage script. M ./libsofia-sip-ua/sofia.am -1 +1 M ./scripts/coverage -2 +25 2005-10-06 Pekka Pessi * Renamed options as sip-options, sip_date as sip-date. ./utils/options.c -> ./utils/sip-options.c ./utils/sip_date.c -> ./utils/sip-date.c M ./utils/Makefile.am -1 +1 * Added all doc files. M ./packages/debian/control -2 +1 M ./packages/debian/docs +3 M ./packages/sofia-sip.spec.in -24 +22 * Added a separate Makefile.am in packages. A ./COPYRIGHTS M ./Makefile.am -6 +2 A ./packages/Makefile.am * Cleaned up output. M ./scripts/coverage -4 +8 * Adding +x to all scripts. M ./autogen.sh +3 * Added %{?dist} to release. M ./packages/sofia-sip.spec.in -1 +4 * sofia-sip-ua.pc is in packages, too. M ./Makefile.am -1 +1 * DIST_SUBDIR too deep in directory structure does not work. M ./configure.ac -4 M ./libsofia-sip-ua/docs/Makefile.am -3 +21 R ./libsofia-sip-ua/docs/pictures/Makefile.am M ./libsofia-sip-ua/sdp/Makefile.am -3 +11 M ./libsofia-sip-ua/sdp/tests/Makefile.am -11 M ./libsofia-sip-ua/sip/Makefile.am -3 +19 M ./libsofia-sip-ua/sip/images/Makefile.am -5 M ./libsofia-sip-ua/sip/tests/Makefile.am -55 * Added packages subdirectory for package stuff. ./sofia-sip-ua.pc.in -> ./packages/sofia-sip-ua.pc.in ./sofia-sip.spec.in -> ./packages/sofia-sip.spec.in M ./Makefile.am -1 +2 M ./configure.ac -2 +2 A ./packages/ * Added coverage and built-sources targets at top-level. M ./Makefile.am -2 +2 * Fixed coverage target in libsofia-sip-ua/Makefile.am. M ./libsofia-sip-ua/Makefile.am -4 +6 M ./libsofia-sip-ua/bnf/Makefile.am +2 M ./libsofia-sip-ua/http/Makefile.am +2 M ./libsofia-sip-ua/ipt/Makefile.am +2 M ./libsofia-sip-ua/iptsec/Makefile.am +2 M ./libsofia-sip-ua/msg/Makefile.am +2 M ./libsofia-sip-ua/nea/Makefile.am +2 M ./libsofia-sip-ua/nta/Makefile.am +2 M ./libsofia-sip-ua/nth/Makefile.am +2 M ./libsofia-sip-ua/nua/Makefile.am +2 M ./libsofia-sip-ua/sdp/Makefile.am +2 M ./libsofia-sip-ua/sip/Makefile.am +2 M ./libsofia-sip-ua/soa/Makefile.am +2 M ./libsofia-sip-ua/sresolv/Makefile.am +2 M ./libsofia-sip-ua/stun/Makefile.am +2 M ./libsofia-sip-ua/tport/Makefile.am +2 M ./libsofia-sip-ua/url/Makefile.am +2 * Removed su/su.mak. R ./libsofia-sip-ua/su/su.mak * Added EXPENSIVE_CHECKS. M ./configure.ac +1 M ./docs/build_system.txt +11 M ./m4/sac-general.m4 +13 * Moved 'testutils' as 'scripts' in toplevel. ./libsofia-sip-ua/testutils -> ./scripts M ./libsofia-sip-ua/sofia.am -1 +1 * Including only library sources in coverage output. M ./libsofia-sip-ua/su/Makefile.am -1 +1 * coverage prints error if check is not made, doesn't depend on check. M ./libsofia-sip-ua/sofia.am -2 +2 * Including all input files in output. M ./libsofia-sip-ua/testutils/coverage -20 +27 2005-10-04 Pekka Pessi * Importing darcs-to-cvs-2005-10-04. * Using DIST_SUBDIRS when including dist-only dirs M ./Makefile.am -1 +2 M ./libsofia-sip-ua/Makefile.am -1 +4 M ./libsofia-sip-ua/docs/Makefile.am -3 +1 M ./libsofia-sip-ua/sdp/Makefile.am -1 +1 M ./libsofia-sip-ua/sip/Makefile.am -1 +1 2005-10-03 Pekka Pessi * Importing darcs-to-cvs-2005-10-03. * Removed old .def files. R ./libsofia-sip-ua/ipt/ipt.def R ./libsofia-sip-ua/iptsec/iptsec.def R ./libsofia-sip-ua/msg/msg.def M ./libsofia-sip-ua/nta/nta.def -92 M ./libsofia-sip-ua/nta/sl_utils.def -15 R ./libsofia-sip-ua/nua/nua.def M ./libsofia-sip-ua/sdp/sdp.def -42 R ./libsofia-sip-ua/sip/sip.def R ./libsofia-sip-ua/su/su.def M ./libsofia-sip-ua/tport/tport.def -21 * Added automake conditional ENABLE_COVERAGE. M ./m4/sac-general.m4 +3 * Added make target for calculating coverage. M ./libsofia-sip-ua/Makefile.am -1 +5 M ./libsofia-sip-ua/sofia.am +5 M ./libsofia-sip-ua/su/Makefile.am +2 A ./libsofia-sip-ua/testutils/ A ./libsofia-sip-ua/testutils/coverage 2005-09-29 Pekka Pessi * Importing darcs-to-cvs-2005-09-29. 2005-09-28 Pekka Pessi * Added nua improvements. M ./TODO +3 2005-09-23 Pekka Pessi * darcs changes: Fri Sep 23 18:58:29 EEST 2005 Pekka.Pessi@nokia.com * Building msg_test class into msg_test library, use that in tport. M ./libsofia-sip-ua/msg/Makefile.am -5 +7 M ./libsofia-sip-ua/tport/Makefile.am -6 +2 Fri Sep 23 18:57:20 EEST 2005 Pekka.Pessi@nokia.com * Using --with-aclocal and ${ACLOCAL} to get correct aclocal install directory. M ./Makefile.am -2 M ./configure.ac +11 M ./sofia-sip.spec.in -1 +1 Fri Sep 23 18:36:46 EEST 2005 Pekka.Pessi@nokia.com * Added win32 into dist. M ./Makefile.am -1 +1 M ./configure.ac +1 A ./win32/Makefile.am Fri Sep 23 18:18:30 EEST 2005 Pekka.Pessi@nokia.com * Added nta/{agent.pem,cafile.pem} to EXTRA_DIST M ./libsofia-sip-ua/nta/Makefile.am -1 +2 Fri Sep 23 18:10:45 EEST 2005 Pekka.Pessi@nokia.com * Respect --without-sigcomp. M ./m4/sac-tport.m4 -1 +1 * darcs changes --from-tag pessi-darcs-2: Fri Sep 23 17:46:00 EEST 2005 Pekka.Pessi@nokia.com tagged pessi-darcs-2 Fri Sep 23 17:20:02 EEST 2005 Pekka.Pessi@nokia.com * Added msg_header_replace(). M ./libsofia-sip-ua/msg/msg_header.h +4 M ./libsofia-sip-ua/msg/msg_parser.c +85 M ./libsofia-sip-ua/msg/msg_test.c +76 Thu Sep 22 13:18:52 EEST 2005 Pekka.Pessi@nokia.com * Added nta_test project A ./win32/nta_test/ A ./win32/nta_test/nta_test.dsp Thu Sep 22 13:17:53 EEST 2005 Pekka.Pessi@nokia.com * Added build directory for win32. A ./win32/SofiaSIP.dsw A ./win32/config.h A ./win32/libsofia-sip-ua/ A ./win32/libsofia-sip-ua/libsofia_sip_ua.dsp A ./win32/libsofia-sip-ua/sofia-sip-ua.def A ./win32/su_configure_win32.h A ./win32/tpipv6.h A ./win32/unistd.h A ./win32/wspiapi.h Thu Sep 22 13:15:32 EEST 2005 Pekka.Pessi@nokia.com * Added win32 pthread library. A ./win32/pthread/ A ./win32/pthread/ChangeLog A ./win32/pthread/md5.sum.txt A ./win32/pthread/pthread.def A ./win32/pthread/pthread.dll A ./win32/pthread/pthread.h A ./win32/pthread/pthread.lib A ./win32/pthread/sched.h A ./win32/pthread/semaphore.h Thu Sep 22 13:13:03 EEST 2005 Pekka.Pessi@nokia.com * Added ntv6 library. A ./win32/ A ./win32/ntv6/ A ./win32/ntv6/include/ A ./win32/ntv6/include/icmp6.h A ./win32/ntv6/include/ip6.h A ./win32/ntv6/include/ip6addr.h A ./win32/ntv6/include/ip6exp.h A ./win32/ntv6/include/ipsec.h A ./win32/ntv6/include/ipv6.h A ./win32/ntv6/include/ntddip6.h A ./win32/ntv6/include/ntddnapt.h A ./win32/ntv6/include/ntddtcp.h A ./win32/ntv6/include/packoff.h A ./win32/ntv6/include/packon.h A ./win32/ntv6/include/tcp6info.h A ./win32/ntv6/include/tcpinfo.h A ./win32/ntv6/include/tdi.h A ./win32/ntv6/include/tdistat.h A ./win32/ntv6/include/ws2ip6.h A ./win32/ntv6/include/ws2tcpip-msr.h A ./win32/ntv6/lib/ A ./win32/ntv6/lib/wship6.lib Tue Sep 20 12:51:58 EEST 2005 Pekka.Pessi@nokia.com * Fixed typo. M ./libsofia-sip-ua/soa/soa.docs -1 +1 Tue Sep 20 12:51:41 EEST 2005 Pekka.Pessi@nokia.com * Added SIPS_PORT() M ./libsofia-sip-ua/sip/sip_header.h +3 Mon Sep 19 20:12:33 EEST 2005 Pekka.Pessi@nokia.com * Updated. Added rules for ignoring SDP. corrected some M ./libsofia-sip-ua/soa/soa.docs -8 +18 Fri Sep 16 10:23:14 EEST 2005 Pekka.Pessi@nokia.com * Parsing URI along with DNS entries in subjectAltName. M ./libsofia-sip-ua/tport/tport_tls.c -5 +12 Fri Sep 16 10:22:39 EEST 2005 Pekka.Pessi@nokia.com * Not requiring client to provide its certificate. M ./libsofia-sip-ua/tport/tport_tls.c -1 +1 Fri Sep 16 10:21:56 EEST 2005 Pekka.Pessi@nokia.com * Removed merge artifact. M ./libsofia-sip-ua/tport/tport.c -7 Fri Sep 16 10:21:32 EEST 2005 Pekka.Pessi@nokia.com * Fixed NAPTR service fields for SIPS/TLS and SIP/SCTP. M ./libsofia-sip-ua/nta/nta.c -2 +2 Thu Sep 15 09:57:38 EEST 2005 Pekka.Pessi@nokia.com * Included m4 files in devel rpm, too. M ./sofia-sip.spec.in +4 Thu Sep 15 09:56:25 EEST 2005 Pekka.Pessi@nokia.com * Added --with-sigcomp to tport. M ./m4/sac-tport.m4 +21 Thu Sep 15 09:55:57 EEST 2005 Pekka.Pessi@nokia.com * Moved SAC_GNU_SOURCE into sac-general.m4 M ./m4/sac-general.m4 +11 M ./m4/sac-su.m4 -10 Thu Sep 15 09:55:26 EEST 2005 Pekka.Pessi@nokia.com * Fixed debugging output in nua_stack.c. M ./libsofia-sip-ua/nua/nua_stack.c -3 +3 Thu Sep 15 09:53:11 EEST 2005 Pekka.Pessi@nokia.com * Installing m4data into m4dir M ./Makefile.am +4 2005-09-09 Pekka Pessi * darcs changes --from-tag pessi-darcs-1: Fri Sep 9 11:38:44 EEST 2005 Pekka.Pessi@nokia.com * Added --with sigcomp. M ./sofia-sip.spec.in +4 Fri Sep 9 00:33:36 EEST 2005 Pekka.Pessi@nokia.com * Including *.h.in files in devel package. M ./sofia-sip.spec.in +1 Thu Sep 8 18:52:06 EEST 2005 Pekka.Pessi@nokia.com * New version. M ./configure.ac -1 +1 Thu Sep 8 18:51:27 EEST 2005 Pekka.Pessi@nokia.com * Keeping section headers in configure script. M ./configure.ac -17 +16 Thu Sep 8 18:26:35 EEST 2005 Pekka.Pessi@nokia.com * Using autoconf to figure out 64-bit types. Avoid off_t and 64-bit constants. M ./configure.ac +6 M ./libsofia-sip-ua/nta/sl_read_payload.c -1 +1 M ./libsofia-sip-ua/nua/nua_stack.c -6 +5 M ./libsofia-sip-ua/sdp/sdp_parse.c -3 +2 M ./libsofia-sip-ua/sdp/sdp_print.c -5 +5 M ./libsofia-sip-ua/sip/validator.c -18 +18 M ./libsofia-sip-ua/soa/soa.c -3 +4 M ./libsofia-sip-ua/su/su_time.c -1 +1 M ./libsofia-sip-ua/su/tstdef.h -3 +3 Thu Sep 8 18:17:58 EEST 2005 Pekka.Pessi@nokia.com * Using RETSIGTYPE. M ./configure.ac -3 +4 M ./libsofia-sip-ua/nth/http-server.c -2 +2 M ./libsofia-sip-ua/soa/test_soa.c -1 +3 M ./libsofia-sip-ua/su/su_test.c -1 +1 M ./libsofia-sip-ua/su/su_timer_test.c -1 +1 Thu Sep 8 18:02:14 EEST 2005 Pekka.Pessi@nokia.com * Checking for netinet/tcp.h, too. M ./m4/sac-tport.m4 +2 2005-09-08 Kai Vehmanen * Makefile.am: Added requirement for automake-1.6.1 or newer. * autogen.sh: Fixed interop problem with older automake versions. * configure.ac: Do not compile STUN if OpenSSL is not available. 2005-07-20 Pekka Pessi * Makefile.am: Added doxygen target. sofia-sip-1.12.11+20110422.1/Makefile.am000066400000000000000000000042361223300710500166270ustar00rootroot00000000000000# # Makefile.am for sofia-sip package # # Copyright (C) 2005,2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. AUTOMAKE_OPTIONS = foreign 1.7 SUBDIRS = s2check libsofia-sip-ua $(GLIB_SUBDIRS) utils packages tests DIST_SUBDIRS = s2check libsofia-sip-ua libsofia-sip-ua-glib utils packages \ tests win32 open_c # note: when glib devel files are not available, make should not # enter the libsofia-sip-ua-glib subdir at all if HAVE_GLIB GLIB_SUBDIRS = libsofia-sip-ua-glib endif PACKAGE = @PACKAGE@ VERSION = @VERSION@ EXTRA_DIST = AUTHORS COPYING COPYRIGHTS ChangeLog.ext-trees \ README README.developers RELEASE TODO ACLOCAL_AMFLAGS = -I m4 EXTRA_DIST += m4/sac-general.m4 m4/sac-coverage.m4 \ m4/sac-su2.m4 m4/sac-tport.m4 m4/sac-openssl.m4 EXTRA_DIST += docs/build_system.txt \ docs/devel_platform_notes.txt \ docs/release_management.txt EXTRA_DIST += scripts/lcov-report scripts/uncovered \ scripts/hide_emails.sh dist_man_MANS = man/man1/sip-date.1 man/man1/sip-options.1 \ man/man1/localinfo.1 man/man1/addrinfo.1 \ man/man1/stunc.1 man/man1/sip-dig.1 $(dist_man_MANS): manpages manpages: -mkdir -p man man/man1 2> /dev/null if HAVE_DOXYGEN $(MAKE) $(AM_MAKEFLAGS) -C libsofia-sip-ua/docs built-sources @echo 'cd utils && $(DOXYGEN)' @cd utils && \ { exec 3>&1 1>&2; { $(DOXYGEN) 2>&1; echo $$? >& 3 ;} | \ fgrep -v 'Warning: explicit' ;} | { read x; exit $$x ;} @rm -f man/man1/_*.1 else -touch $(dist_man_MANS) endif CLEANFILES = $(dist_man_MANS) built-sources clean-built-sources valcheck doxygen: @failcom='exit 1'; for f in x $$MAKEFLAGS; do \ case $$f in *=* | --[!k]*);; *k*) failcom='fail=yes';; esac; done; \ for i in utils libsofia-sip-ua $(GLIB_SUBDIRS) ; do \ (cd $$i && $(MAKE) $(AM_MAKEFLAGS) $@) || eval $$failcom; \ done ; \ test -z "$$fail" PHONY = built-sources clean-built-sources valcheck doxygen manpages # s2check depends on generated headers within libsofia-sip-ua all check: built-sources if HAVE_LCOV include $(top_srcdir)/rules/lcov.am lcov-upload: lcov rsync -rvz -e ssh --delete lcov/* sofia-sip.org:/var/www/coverage/lcov/ endif .PHONY: $(PHONY) sofia-sip-1.12.11+20110422.1/Makefile.in000066400000000000000000001053531223300710500166420ustar00rootroot00000000000000# Makefile.in generated by automake 1.14 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 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 sofia-sip package # # Copyright (C) 2005,2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # # Generate lcov output # # # Copyright (C) 2007 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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@ DIST_COMMON = $(top_srcdir)/rules/lcov.am $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/configure \ $(am__configure_deps) $(srcdir)/config.h.in \ $(top_srcdir)/libsofia-sip-ua/su/sofia-sip/su_configure.h.in \ $(top_srcdir)/libsofia-sip-ua/features/sofia-sip/sofia_features.h.in \ $(dist_man_MANS) AUTHORS COPYING ChangeLog README TODO compile \ config.guess config.sub depcomp install-sh missing ltmain.sh @HAVE_GENPNG_TRUE@@HAVE_LCOV_TRUE@am__append_1 = --frames @HAVE_LCOV_TRUE@am__append_2 = lcov lcov-report lcov-rerun clean-lcov covcheck uncovered subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(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)/m4/sac-coverage.m4 \ $(top_srcdir)/m4/sac-general.m4 \ $(top_srcdir)/m4/sac-openssl.m4 \ $(top_srcdir)/m4/sac-pkg-config.m4 $(top_srcdir)/m4/sac-su2.m4 \ $(top_srcdir)/m4/sac-tport.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h \ $(top_builddir)/libsofia-sip-ua/su/sofia-sip/su_configure.h CONFIG_CLEAN_FILES = \ libsofia-sip-ua/features/sofia-sip/sofia_features.h 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 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; }; \ } man1dir = $(mandir)/man1 am__installdirs = "$(DESTDIR)$(man1dir)" NROFF = nroff MANS = $(dist_man_MANS) 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 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)` CTAGS = ctags CSCOPE = cscope 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 ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = -I m4 ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CHECK_CFLAGS = @CHECK_CFLAGS@ CHECK_LIBS = @CHECK_LIBS@ COVERAGE_FLAGS = @COVERAGE_FLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CWFLAG = @CWFLAG@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV = @GCOV@ GENHTML = @GENHTML@ GENPNG = @GENPNG@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GLIB_VERSION = @GLIB_VERSION@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVER_SOFIA_SIP_UA_AGE = @LIBVER_SOFIA_SIP_UA_AGE@ LIBVER_SOFIA_SIP_UA_CUR = @LIBVER_SOFIA_SIP_UA_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_AGE = @LIBVER_SOFIA_SIP_UA_GLIB_AGE@ LIBVER_SOFIA_SIP_UA_GLIB_CUR = @LIBVER_SOFIA_SIP_UA_GLIB_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_REV = @LIBVER_SOFIA_SIP_UA_GLIB_REV@ LIBVER_SOFIA_SIP_UA_GLIB_SOVER = @LIBVER_SOFIA_SIP_UA_GLIB_SOVER@ LIBVER_SOFIA_SIP_UA_REV = @LIBVER_SOFIA_SIP_UA_REV@ LIBVER_SOFIA_SIP_UA_SOVER = @LIBVER_SOFIA_SIP_UA_SOVER@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MINGW_ENVIRONMENT = @MINGW_ENVIRONMENT@ MKDIR_P = @MKDIR_P@ MOSTLYCLEANFILES = @MOSTLYCLEANFILES@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ RANLIB = @RANLIB@ REPLACE_LIBADD = @REPLACE_LIBADD@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ SOFIA_GLIB_CFLAGS = @SOFIA_GLIB_CFLAGS@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ SOFIA_PLAT_CFLAGS = @SOFIA_PLAT_CFLAGS@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ VERSION = @VERSION@ VER_LIBSOFIA_SIP_UA_MAJOR_MINOR = @VER_LIBSOFIA_SIP_UA_MAJOR_MINOR@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ include_sofiadir = @include_sofiadir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ openssl_CFLAGS = @openssl_CFLAGS@ openssl_LIBS = @openssl_LIBS@ 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@ AUTOMAKE_OPTIONS = foreign 1.7 SUBDIRS = s2check libsofia-sip-ua $(GLIB_SUBDIRS) utils packages tests DIST_SUBDIRS = s2check libsofia-sip-ua libsofia-sip-ua-glib utils packages \ tests win32 open_c # note: when glib devel files are not available, make should not # enter the libsofia-sip-ua-glib subdir at all @HAVE_GLIB_TRUE@GLIB_SUBDIRS = libsofia-sip-ua-glib EXTRA_DIST = AUTHORS COPYING COPYRIGHTS ChangeLog.ext-trees README \ README.developers RELEASE TODO m4/sac-general.m4 \ m4/sac-coverage.m4 m4/sac-su2.m4 m4/sac-tport.m4 \ m4/sac-openssl.m4 docs/build_system.txt \ docs/devel_platform_notes.txt docs/release_management.txt \ scripts/lcov-report scripts/uncovered scripts/hide_emails.sh dist_man_MANS = man/man1/sip-date.1 man/man1/sip-options.1 \ man/man1/localinfo.1 man/man1/addrinfo.1 \ man/man1/stunc.1 man/man1/sip-dig.1 CLEANFILES = $(dist_man_MANS) PHONY = built-sources clean-built-sources valcheck doxygen manpages \ $(am__append_2) # Scripts @HAVE_LCOV_TRUE@LCOV_UNCOVERED = ${top_srcdir}/scripts/uncovered @HAVE_LCOV_TRUE@LCOV_REPORT = ${top_srcdir}/scripts/lcov-report # Report directory @HAVE_LCOV_TRUE@lcovdir = ${top_builddir}/lcov # Options @HAVE_LCOV_TRUE@GENHTML_OPTIONS = --show-details --legend \ @HAVE_LCOV_TRUE@ $(am__append_1) # Fancy shell command that expands to directory relative to top_builddir @HAVE_LCOV_TRUE@expand_subdir = `pwd|sed "s'\`cd ${top_builddir};pwd\`''"` all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: am--refresh: Makefile @: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/lcov.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/rules/lcov.am: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ libsofia-sip-ua/su/sofia-sip/su_configure.h: libsofia-sip-ua/su/sofia-sip/stamp-h2 @test -f $@ || rm -f libsofia-sip-ua/su/sofia-sip/stamp-h2 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) libsofia-sip-ua/su/sofia-sip/stamp-h2 libsofia-sip-ua/su/sofia-sip/stamp-h2: $(top_srcdir)/libsofia-sip-ua/su/sofia-sip/su_configure.h.in $(top_builddir)/config.status @rm -f libsofia-sip-ua/su/sofia-sip/stamp-h2 cd $(top_builddir) && $(SHELL) ./config.status libsofia-sip-ua/su/sofia-sip/su_configure.h distclean-hdr: -rm -f config.h stamp-h1 libsofia-sip-ua/su/sofia-sip/su_configure.h libsofia-sip-ua/su/sofia-sip/stamp-h2 libsofia-sip-ua/features/sofia-sip/sofia_features.h: $(top_builddir)/config.status $(top_srcdir)/libsofia-sip-ua/features/sofia-sip/sofia_features.h.in cd $(top_builddir) && $(SHELL) ./config.status $@ mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool config.lt install-man1: $(dist_man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(dist_man_MANS)'; \ test -n "$(man1dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.1[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ done; } uninstall-man1: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man1dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man1dir)'; $(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" 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: $(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) | GZIP=$(GZIP_ENV) gzip -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 shar distribution archives 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 distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | GZIP=$(GZIP_ENV) gzip -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*) \ GZIP=$(GZIP_ENV) gzip -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*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(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 \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ && $(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 check: check-recursive all-am: Makefile $(MANS) config.h installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(man1dir)"; 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: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) 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." @HAVE_LCOV_FALSE@clean-local: 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-man 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-man1 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: uninstall-man uninstall-man: uninstall-man1 .MAKE: $(am__recursive_targets) all 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-man1 \ 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 uninstall-man \ uninstall-man1 $(dist_man_MANS): manpages manpages: -mkdir -p man man/man1 2> /dev/null @HAVE_DOXYGEN_TRUE@ $(MAKE) $(AM_MAKEFLAGS) -C libsofia-sip-ua/docs built-sources @HAVE_DOXYGEN_TRUE@ @echo 'cd utils && $(DOXYGEN)' @HAVE_DOXYGEN_TRUE@ @cd utils && \ @HAVE_DOXYGEN_TRUE@ { exec 3>&1 1>&2; { $(DOXYGEN) 2>&1; echo $$? >& 3 ;} | \ @HAVE_DOXYGEN_TRUE@ fgrep -v 'Warning: explicit' ;} | { read x; exit $$x ;} @HAVE_DOXYGEN_TRUE@ @rm -f man/man1/_*.1 @HAVE_DOXYGEN_FALSE@ -touch $(dist_man_MANS) built-sources clean-built-sources valcheck doxygen: @failcom='exit 1'; for f in x $$MAKEFLAGS; do \ case $$f in *=* | --[!k]*);; *k*) failcom='fail=yes';; esac; done; \ for i in utils libsofia-sip-ua $(GLIB_SUBDIRS) ; do \ (cd $$i && $(MAKE) $(AM_MAKEFLAGS) $@) || eval $$failcom; \ done ; \ test -z "$$fail" # s2check depends on generated headers within libsofia-sip-ua all check: built-sources # # Generate pretty coverage report (unless it has been already done) # @HAVE_LCOV_TRUE@lcov: @HAVE_LCOV_TRUE@ @-test -r ${lcovdir}${expand_subdir}/lcov.info \ @HAVE_LCOV_TRUE@ || make lcov-report # Generate pretty coverage report based on current coverage data @HAVE_LCOV_TRUE@lcov-report: @HAVE_LCOV_TRUE@ sub=${expand_subdir} odir=${lcovdir}$$sub ; \ @HAVE_LCOV_TRUE@ rm -rf $$odir ; mkdir -p $$odir && \ @HAVE_LCOV_TRUE@ ${LCOV_REPORT} ${GENHTML_OPTIONS} \ @HAVE_LCOV_TRUE@ --title "${PACKAGE_NAME}-${PACKAGE_VERSION}$$sub" \ @HAVE_LCOV_TRUE@ --srcdir=${srcdir} -o $$odir # Rerun checks before generating report @HAVE_LCOV_TRUE@lcov-rerun: clean-lcov @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) lcov-report # Show all uncovered lines as errors @HAVE_LCOV_TRUE@uncovered: @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} # Run check in current dir and show all uncovered lines as errors @HAVE_LCOV_TRUE@covcheck: @HAVE_LCOV_TRUE@ -find . -name "*.gcda" | xargs rm -rf @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} @HAVE_LCOV_TRUE@clean-local:: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true @HAVE_LCOV_TRUE@clean-lcov: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true @HAVE_LCOV_TRUE@lcov-upload: lcov @HAVE_LCOV_TRUE@ rsync -rvz -e ssh --delete lcov/* sofia-sip.org:/var/www/coverage/lcov/ .PHONY: $(PHONY) # 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: sofia-sip-1.12.11+20110422.1/README000066400000000000000000000036171223300710500154550ustar00rootroot00000000000000============================================================= README / Sofia-SIP - RFC3261 compliant SIP User-Agent library ============================================================= Introduction ------------ Sofia-SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification. It can be used as a building block for SIP client software for uses such as VoIP, IM, and many other real-time and person-to-person communication services. The primary target platform for Sofia-SIP is GNU/Linux. Sofia-SIP is based on a SIP stack developed at the Nokia Research Center. Sofia-SIP is licensed under the LGPL. Quick start ----------- Sofia-SIP uses the GNU autotools, so building procedure is the usual: sh> sh autogen.sh (if building from darcs) sh> ./configure sh> make sh> make install See also 'docs/devel_platform_notes.txt' for notes on compiling Sofia-SIP in different environments. See the "options-client-example" (available using darcs at http://sofia-sip.org/repos/options-client-example/ or with CVS as a module in Sofia-SIP CVS tree) for an example of a small app that is utilizing Sofia-SIP, and specifically the libsofia-sip-ua library component. There are also multiple example clients under the "sofia-sip/utils" directory: - sip-options, query using SIP OPTIONS method - sip-date, SIP date printer/parser The Sofia-SIP su submodule also provides some small utilities: - addrinfo (libsofia-sip-ua/su), resolve host names - localinfo (libsofia-sip-ua/su), prints information about local network interfaces References ---------- Project website: - http://sofia-sip.sourceforge.net - http://www.sourceforge.net/projects/sofia-sip Mailing list: - http://sourceforge.net/mail/?group_id=143636 Version control repositories: - see the project website (link above) Licensing --------- Sofia-SIP is licensed under terms of the GNU LGPL. See the file "COPYING" for more information. sofia-sip-1.12.11+20110422.1/README.developers000066400000000000000000000101151223300710500176130ustar00rootroot00000000000000=============================================================== README.developers - Sofia-SIP development practices =============================================================== Introduction ============ This file is a collection of practices and rules for Sofia-SIP development. If you have questions, or would like to make changes, raise the issue on sofia-sip-devel (see http://lists.sourceforge.net/lists/listinfo/sofia-sip-devel ). Important files for developers ============================== AUTHORS List of contributors. When contributing new code, add yourself to AUTHORS, and also remember to update the per source file copyright statements. COPYRIGHTS List of licenses and related copyright statements. While majority of Sofia-SIP is licensed under LGPL, there are a few files with different, but LGPL compatible, licensing terms. README.developers This file. TODO Not in active use yet. /ChangeLog files All non-trivial changes to the source code should be documented in the ChangeLog files. See also the top-level ChangeLog. Version numbering ================= Package version --------------- For public releases, the package version is: vMAJOR.MINOR.REVISION, where MINOR is even For development releases and snaphots the version is one of: vMAJOR.MINOR.REVISION, where minor is odd vMAJOR.MINOR.REVISION.YEAR.MONTH.DAY, where minor is odd For all releases, the version should be changed in configure.ac and committed to Darcs/CVS before making the release package. The person doing the release is responsible for updating the version number. Library interface versions -------------------------- Sofia-SIP libraries utilize libtool interface versioning. See - http://www.gnu.org/software/libtool/manual.html#Versioning - http://www.gnu.org/software/libtool/manual.html#Using-Automake The interface versions are set in top-level 'configure.ac' file. Additionally, the SONAME version (CURRENT-AGE) is set in the same place. These version numbers are available for use as autoconf variables (see the library 'Makefile.am' files and 'packages/sofia-sip.spec.in'). All changes to the library versions should be marked to the appropriate library 'ChangeLog' file. The library version should be changed at the same time as the first interface change is committed since the previous release. The interface version is frozen (should be marked to the 'ChangeLog' file) at the time the next release is tagged (in other words, intra-release changes need not be tracked with libtool versions). The goal should always be to avoid breaking the API/ABIs until absolutely necessary. Interfaces clearly marked as private can be changed without change to library interface version, but otherwise all public functions, types, variables and definitions fall under interface change control. Version control tags ==================== Tagging releases and snapshots ------------------------------ - source repository (*) - master Darcs tree at: http://sofia-sip.org/repos/sofia-sip - CVS tree (only used to track major releases) at: http://sourceforge.net/cvs/?group_id=143636 - tags: rel-sofia-sip-x_y_z - stable and development releases (matches release version sofia-sip-x.y.z) - tags: snapshot_rel_YEARMMDD - snapshot releases at http://sofia-sip.sourceforge.net/snapshots/ Notes (*): - Information about Darcs: http://abridgegame.org/darcs/ http://lwn.net/Articles/110516/ Sending patches =============== People without Darcs access --------------------------- Send your patches to sofia-sip-devel. Someone from the development team (see AUTHORS) will handle the patch. People with Darcs access ------------------------ Trivial changes can be committed without review. For non-trivial changes, you should first send a proposal to sofia-sip-devel and wait for comments. There are no strict approval rules so use of common sense is recommended. ;) Tips for making patches ----------------------- - test your patch on a clean checkout from version control system - remember to check for updates before pushing your changes to the master repository sofia-sip-1.12.11+20110422.1/RELEASE000066400000000000000000000072651223300710500156030ustar00rootroot00000000000000============================================== Release notes for current version of Sofia-SIP ============================================== Changes since last release -------------------------- Bugs in blaa and foo have been fixed. The stack now supports use of foobar... API/ABI changes and versioning ------------------------------ **template**: New features in API are marked with Doxytag macro @VERSION_1_XX_X. libsofia-sip-ua: - **template**: Added foobar() function (sofia-sip/foobar.h). - Added SOATAG_USER_O_LINE() tag (sofia-sip/soa_tag.h) - Added msg_q_value() function (sofia-sip/msg_mime.h). - Added msg_accept_match() function (sofia-sip/msg_mime.h). - Added NUTAG_AUTO100() tag (sofia-sip/nua_tag.h) - Added NUTAG_ACCEPT_MULTIPART() tag (sofia-sip/nua_tag.h). - Added NUTAG_MAX_RETRY_AFTER() tag (sofia-sip/nua_tag.h) - Added NUTAG_APPL_EVENT() tag (sofia-sip/nua_tag.h) - Added NUTAG_DEFERRABLE_TIMERS() tag (sofia-sip/nua_tag.h). - Added typedef su_time64_t and functions su_now64(), su_stamp64(), su_time64_to_time(), su_time_to_time64(), su_time64_add(), and su_duration64() (sofia-sip/su_time.h). - Added su_root_stamp64() and su_root_stamp64_offset() (sofia-sip/su_wait.h). - This release is ABI/API compatible with applications linked against any 1.12.x release. However, applications built against this release won't work against an older library. The ABI has been tested with the nua module unit test (test_nua) built against original 1.12.0 release. libsofia-sip-ua-glib: - No ABI/API changes, compatible with 1.12.0. Note, libsofia-sip-ua-glib interface is not considered stable and may change in a future 1.12.x release. Contributors to this release ---------------------------- - - **template**: First Surname (patch to nua/soa/msg) See the AUTHORS file in the distribution package. Notes on new features --------------------- Bugs fixed in this release -------------------------- < notable bugs fixed in this release - check the sf.net bug tracker; see closed bugs, sorted by closing date - other bugs as fixed in CVS/darcs /> - **template**: #9499652 sf.net bug item title - If initial OPTIONS used to verify registration fails, it is not retried after re-REGISTER. - Fixed multiple Coverity issues. - Updating SDP version on o= line if the SDP was changed processing answer. Thanks for Kristian Tronnberg for reporting the issue. - Incorporated fixes for multiple issues from Freeswitch. - MeeGo bug #15577: msg_addr_zero confuses sizeof pointer for sizeof *pointer - MeeGo bug #15573: su_task_init use of sizeof typedef causes analysis tool to fret (reports by timeless) - Now using same Call-ID when retransmitting authenticated requests by NUA (report by Olivier Deme) sofia-sip-1.12.11+20110422.1/TODO000066400000000000000000000016431223300710500152620ustar00rootroot00000000000000=============================================================== TODO / Sofia-SIP =============================================================== version: 20060907-2 Release roadmap --------------- 1.11/1.12 series - first version of the new nua+soa API - nua_respond_nit() (non-INVITEs) - nua_set_hparams()/nua_get_hparams() [DONE] - session object ownership changes [DONE] - allow multiple registrations (lines) and selecting service route, outbound proxy, and transport independently for each handle; NUTAG_IDENTITY - doxygen documentation updates [DONE] - rpm and dpkg packaging [DONE] - NAT work: STUN fixes (DNS support) [DONE] not roadmapped: - expand the call-state-change mechanism - update http headers TE, Cookie, Set-Cookie 2.0 serias - a verified stable API (1.12 is the current stable candidate) See README.developers for information about versioning. sofia-sip-1.12.11+20110422.1/aclocal.m4000066400000000000000000001256141223300710500164370ustar00rootroot00000000000000# generated automatically by aclocal 1.14 -*- Autoconf -*- # Copyright (C) 1996-2013 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'.])]) # Copyright (C) 2002-2013 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.14' 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.14], [], [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.14])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2013 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], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2013 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-2013 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-2013 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. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _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. FIXME. This creates each '.P' file that we will # 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" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2013 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: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target. 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: 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: . 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 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-2013 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}" != 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-2013 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])]) # Add --enable-maintainer-mode option to configure. -*- Autoconf -*- # From Jim Meyering # Copyright (C) 1996-2013 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_MAINTAINER_MODE([DEFAULT-MODE]) # ---------------------------------- # Control maintainer-specific portions of Makefiles. # Default is to disable them, unless 'enable' is passed literally. # For symmetry, 'disable' may be passed as well. Anyway, the user # can override the default with the --enable/--disable switch. AC_DEFUN([AM_MAINTAINER_MODE], [m4_case(m4_default([$1], [disable]), [enable], [m4_define([am_maintainer_other], [disable])], [disable], [m4_define([am_maintainer_other], [enable])], [m4_define([am_maintainer_other], [enable]) m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) dnl maintainer-mode's default is 'disable' unless 'enable' is passed AC_ARG_ENABLE([maintainer-mode], [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode], am_maintainer_other[ make rules and dependencies not useful (and sometimes confusing) to the casual installer])], [USE_MAINTAINER_MODE=$enableval], [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) AC_MSG_RESULT([$USE_MAINTAINER_MODE]) AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) MAINT=$MAINTAINER_MODE_TRUE AC_SUBST([MAINT])dnl ] ) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2013 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 to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2013 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-2013 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-2013 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-2013 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-2013 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-2013 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-2013 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-2013 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-2013 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 /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/libtool.m4]) m4_include([m4/ltoptions.m4]) m4_include([m4/ltsugar.m4]) m4_include([m4/ltversion.m4]) m4_include([m4/lt~obsolete.m4]) m4_include([m4/sac-coverage.m4]) m4_include([m4/sac-general.m4]) m4_include([m4/sac-openssl.m4]) m4_include([m4/sac-pkg-config.m4]) m4_include([m4/sac-su2.m4]) m4_include([m4/sac-tport.m4]) sofia-sip-1.12.11+20110422.1/autoconf-all.cmd000066400000000000000000000000511223300710500176330ustar00rootroot00000000000000@setlocal @cd open_c @call autogen.cmd sofia-sip-1.12.11+20110422.1/autogen.sh000077500000000000000000000003341223300710500165670ustar00rootroot00000000000000#!/bin/sh set -x AUTOMAKE=${AUTOMAKE:-automake} ACLOCAL=${ACLOCAL:-aclocal} export AUTOMAKE ACLOCAL ${AUTORECONF:-autoreconf} -if find . \( -name 'run*' -o -name '*.sh' \) -a -type f | xargs chmod +x chmod +x scripts/* sofia-sip-1.12.11+20110422.1/compile000077500000000000000000000162451223300710500161540ustar00rootroot00000000000000#! /bin/sh # Wrapper for compilers which do not understand '-c -o'. scriptversion=2012-10-14.11; # UTC # Copyright (C) 1999-2013 Free Software Foundation, Inc. # Written by Tom Tromey . # # 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 . # 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 or send patches to # . 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 . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; cl | *[/\\]cl | cl.exe | *[/\\]cl.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 '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: sofia-sip-1.12.11+20110422.1/config.guess000077500000000000000000001303611223300710500171120ustar00rootroot00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2013 Free Software Foundation, Inc. timestamp='2013-06-10' # 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 . # # 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. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD # # Please send patches with a ChangeLog entry 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. Operation modes: -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 ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2013 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 #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'` ;; 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=`(/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 ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in 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 # 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/[-_].*/\./'` ;; 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}" 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 ;; *: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 ;; 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 ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; 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 /* 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 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/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` 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:BSD:*) 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 #include 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 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) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW64*:*) echo ${UNAME_MACHINE}-pc-mingw64 exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; i*:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 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 ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-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 '[A-Z]' '[a-z]'``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 ;; 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 ;; 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; } ;; or1k:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; or32: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 ;; 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}-unknown-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.*:* | i*86:SYSTEM_V: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' /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 configury 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 echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # 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 ;; 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 [ "$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 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 ;; *: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 ;; esac eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; c34*) echo c34-convex-bsd exit ;; c38*) echo c38-convex-bsd exit ;; c4*) echo c4-convex-bsd exit ;; esac fi cat >&2 < in order to provide the needed 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 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: sofia-sip-1.12.11+20110422.1/config.h.in000066400000000000000000000333721223300710500166210ustar00rootroot00000000000000/* config.h.in. Generated from configure.ac by autoheader. */ /* Define if building universal (internal helper macro) */ #undef AC_APPLE_UNIVERSAL_BUILD /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP systems. This function is required for `alloca.c' support on those systems. */ #undef CRAY_STACKSEG_END /* Define to 1 if using `alloca.c'. */ #undef C_ALLOCA /* Define to the random number source name. */ #undef DEV_URANDOM /* Define to 1 if you have addrinfo structure. */ #undef HAVE_ADDRINFO /* Define to 1 if you have the `alarm' function. */ #undef HAVE_ALARM /* Define to 1 if you have `alloca', as a function or macro. */ #undef HAVE_ALLOCA /* Define to 1 if you have and it should be used (not on Ultrix). */ #undef HAVE_ALLOCA_H /* Define to 1 if you have the header file. */ #undef HAVE_ARPA_INET_H /* Define to 1 if printf supports C99 size specifiers */ #undef HAVE_C99_FORMAT /* Define to 1 if check library is available */ #undef HAVE_CHECK /* Define to 1 if you have the `clock_getcpuclockid' function. */ #undef HAVE_CLOCK_GETCPUCLOCKID /* Define to 1 if you have the `clock_gettime' function. */ #undef HAVE_CLOCK_GETTIME /* Define to 1 if you have CLOCK_MONOTONIC */ #undef HAVE_CLOCK_MONOTONIC /* Defined when gcov is enabled to force by changing config.h */ #undef HAVE_COVERAGE /* Define to 1 if you have /dev/urandom. */ #undef HAVE_DEV_URANDOM /* Define to 1 if you have the header file. */ #undef HAVE_DIRENT_H /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have epoll interface. */ #undef HAVE_EPOLL /* Define to 1 if you have the `epoll_create' function. */ #undef HAVE_EPOLL_CREATE /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Define to 1 if you have WIN32 FILETIME type and GetSystemTimeAsFileTime(). */ #undef HAVE_FILETIME /* Define to 1 if you have the `flock' function. */ #undef HAVE_FLOCK /* Define to 1 if you have the header file. */ #undef HAVE_FNMATCH_H /* Define to 1 if you have the `freeaddrinfo' function. */ #undef HAVE_FREEADDRINFO /* Define this as 1 if your c library does not crash with free(0) */ #undef HAVE_FREE_NULL /* Define to 1 if the C compiler supports __func__ */ #undef HAVE_FUNC /* Define to 1 if the C compiler supports __FUNCTION__ */ #undef HAVE_FUNCTION /* Define to 1 if you have the `gai_strerror' function. */ #undef HAVE_GAI_STRERROR /* Define to 1 if you have the `getaddrinfo' function. */ #undef HAVE_GETADDRINFO /* Define to 1 if you have the `getdelim' function. */ #undef HAVE_GETDELIM /* Define to 1 if you have the `gethostbyname' function. */ #undef HAVE_GETHOSTBYNAME /* Define to 1 if you have the `gethostname' function. */ #undef HAVE_GETHOSTNAME /* Define to 1 if you have the `getifaddrs' function. */ #undef HAVE_GETIFADDRS /* Define to 1 if you have the `getipnodebyname' function. */ #undef HAVE_GETIPNODEBYNAME /* Define to 1 if you have the `getline' function. */ #undef HAVE_GETLINE /* Define to 1 if you have the `getnameinfo' function. */ #undef HAVE_GETNAMEINFO /* Define to 1 if you have the `getpass' function. */ #undef HAVE_GETPASS /* Define to 1 if you have the `gettimeofday' function. */ #undef HAVE_GETTIMEOFDAY /* Define to 1 if you have the header file. */ #undef HAVE_IFADDR_H /* Define to 1 if you have SIOCGIFCONF */ #undef HAVE_IFCONF /* Define to 1 if you have SIOCGIFNUM ioctl */ #undef HAVE_IFNUM /* Define to 1 if you have ifr_ifindex in */ #undef HAVE_IFR_IFINDEX /* Define to 1 if you have ifr_index in */ #undef HAVE_IFR_INDEX /* Define to 1 if you have the `if_nameindex' function. */ #undef HAVE_IF_NAMEINDEX /* Define to 1 if you have the `inet_ntop' function. */ #undef HAVE_INET_NTOP /* Define to 1 if you have the `inet_pton' function. */ #undef HAVE_INET_PTON /* Define to 1 if you have the `initstate' function. */ #undef HAVE_INITSTATE /* Define to 1 if you have inlining compiler */ #undef HAVE_INLINE /* Define to 1 if you have WIN32 INTERFACE_INFO_EX type. */ #undef HAVE_INTERFACE_INFO_EX /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_IPHLPAPI_H /* Define to 1 if you have IPV6_RECVERR in */ #undef HAVE_IPV6_RECVERR /* Define to 1 if you have IP_ADD_MEMBERSHIP */ #undef HAVE_IP_ADD_MEMBERSHIP /* Define to 1 if you have IP_MTU_DISCOVER */ #undef HAVE_IP_MTU_DISCOVER /* Define to 1 if you have IP_MULTICAST_LOOP */ #undef HAVE_IP_MULTICAST_LOOP /* Define to 1 if you have IP_RECVERR in */ #undef HAVE_IP_RECVERR /* Define to 1 if you have the `kqueue' function. */ #undef HAVE_KQUEUE /* Define to 1 if you have the `crypto' library (-lcrypto). */ #undef HAVE_LIBCRYPTO /* Define to 1 if dl library is available */ #undef HAVE_LIBDL /* Define to 1 if you have the `gcov' library (-lgcov). */ #undef HAVE_LIBGCOV /* Define to 1 if you have the `pthread' library (-lpthread). */ #undef HAVE_LIBPTHREAD /* Define to 1 if you have the `socket' library (-lsocket). */ #undef HAVE_LIBSOCKET /* Define to 1 if you have the `ssl' library (-lssl). */ #undef HAVE_LIBSSL /* Define to 1 if you have the `memccpy' function. */ #undef HAVE_MEMCCPY /* Define to 1 if you have the `memcspn' function. */ #undef HAVE_MEMCSPN /* Define to 1 for memory-leak-related logging */ #undef HAVE_MEMLEAK_LOG /* Define to 1 if you have the `memmem' function. */ #undef HAVE_MEMMEM /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `memspn' function. */ #undef HAVE_MEMSPN /* Define to 1 if you are compiling in MinGW environment */ #undef HAVE_MINGW /* Define to 1 if you have MSG_TRUNC flag */ #undef HAVE_MSG_TRUNC /* Define to 1 if you have the header file. */ #undef HAVE_NETDB_H /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IN_H /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_SCTP_H /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_TCP_H /* Define to 1 if you have the header file. */ #undef HAVE_NETPACKET_PACKET_H /* Define to 1 if you have the header file. */ #undef HAVE_NET_IF_H /* Define to 1 if you have the header file. */ #undef HAVE_NET_IF_TYPES_H /* tcase_add_test() with allowed_exit_value argument */ #undef HAVE_NEW_TCASE_ADD_TEST /* Define to 1 if you have OpenSSL */ #undef HAVE_OPENSSL /* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_TLS1_H /* Define to 1 if you have the `poll' function. */ #undef HAVE_POLL /* Define to 1 if you use poll in su_port. */ #undef HAVE_POLL_PORT /* Define to 1 if you have /proc/net/if_inet6 control file */ #undef HAVE_PROC_NET_IF_INET6 /* Define to 1 if you have working pthread_rwlock_t implementation. A thread may hold multiple concurrent read locks on rwlock - that is, successfully call the pthread_rwlock_rdlock() function n times. If so, the application shall ensure that the thread performs matching unlocks - that is, it calls the pthread_rwlock_unlock() function n times. */ #undef HAVE_PTHREAD_RWLOCK /* Define to 1 if you have the `random' function. */ #undef HAVE_RANDOM /* Define to 1 if you have sa_len in struct sockaddr */ #undef HAVE_SA_LEN /* Define to 1 if you have SCTP */ #undef HAVE_SCTP /* Define to 1 if you have the `select' function. */ #undef HAVE_SELECT /* Define to 1 if you have Sofia sigcomp >= 2.5 */ #undef HAVE_SIGCOMP /* Define to 1 if you have the header file. */ #undef HAVE_SIGCOMP_H /* Define to 1 if you have the `signal' function. */ #undef HAVE_SIGNAL /* Define to 1 if you have SIGPIPE */ #undef HAVE_SIGPIPE /* Define to 1 if you have IPv6 structures and constants */ #undef HAVE_SIN6 /* Define to 1 if you have WIN32 WSAIoctl SIO_ADDRESS_LIST_QUERY. */ #undef HAVE_SIO_ADDRESS_LIST_QUERY /* Define to 1 if you have the `socketpair' function. */ #undef HAVE_SOCKETPAIR /* Define to 1 if we use HTTP parser library */ #undef HAVE_SOFIA_HTTP /* Define to 1 if we use NTH library */ #undef HAVE_SOFIA_NTH /* Define to 1 if we use NTLM library */ #undef HAVE_SOFIA_NTLM /* Define to 1 if you have Sofia sigcomp >= 2.5 */ #undef HAVE_SOFIA_SIGCOMP /* Define to 1 always */ #undef HAVE_SOFIA_SIP /* Define to 1 if we use S/MIME library */ #undef HAVE_SOFIA_SMIME /* Define to 1 if we use DNS library */ #undef HAVE_SOFIA_SRESOLV /* Define to 1 if we use STUN library */ #undef HAVE_SOFIA_STUN /* Define to 1 if you have socket option SO_RCVBUFFORCE */ #undef HAVE_SO_RCVBUFFORCE /* Define to 1 if you have socket option SO_SNDBUFFORCE */ #undef HAVE_SO_SNDBUFFORCE /* Define to 1 if we use SRTP */ #undef HAVE_SRTP /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strerror' function. */ #undef HAVE_STRERROR /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strnlen' function. */ #undef HAVE_STRNLEN /* Define to 1 if you have the `strtoull' function. */ #undef HAVE_STRTOULL /* Define to 1 if your CC supports C99 struct initialization */ #undef HAVE_STRUCT_KEYWORDS /* Define to 1 if you have the header file. */ #undef HAVE_SYS_DEVPOLL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_EPOLL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_FILIO_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_IOCTL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SELECT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SOCKET_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SOCKIO_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TIME_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the `tcsetattr' function. */ #undef HAVE_TCSETATTR /* Define to 1 if you have TLS */ #undef HAVE_TLS /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if we use UPnP */ #undef HAVE_UPNP /* Define to 1 you have WIN32 */ #undef HAVE_WIN32 /* Define to 1 if you have the header file. */ #undef HAVE_WINDEF_H /* Define to 1 if you have the header file. */ #undef HAVE_WINSOCK2_H /* Define to 1 if you have the header file. */ #undef HAVE_WS2TCPIP_H /* Format (%lli) for long long */ #undef LLI /* Format (%llu) for unsigned long long */ #undef LLU /* Format (%llx) for long long hex */ #undef LLX /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Define printf() modifier for ssize_t */ #undef MOD_ZD /* Define printf() modifier for size_t */ #undef MOD_ZU /* 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 as the return type of signal handlers (`int' or `void'). */ #undef RETSIGTYPE /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at runtime. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ #undef STACK_DIRECTION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define to 1 if you can safely include both and . */ #undef TIME_WITH_SYS_TIME /* 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 WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD # if defined __BIG_ENDIAN__ # define WORDS_BIGENDIAN 1 # endif #else # ifndef WORDS_BIGENDIAN # undef WORDS_BIGENDIAN # endif #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 /* Define to empty if `const' does not conform to ANSI C. */ #undef const /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus #undef inline #endif /* Define to a at least 64-bit int type */ #undef longlong /* Define to `unsigned int' if does not define. */ #undef size_t sofia-sip-1.12.11+20110422.1/config.sub000077500000000000000000001053541223300710500165610ustar00rootroot00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2013 Free Software Foundation, Inc. timestamp='2013-08-10' # 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 . # # 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 with a ChangeLog entry 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: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # 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 $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -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 ." version="\ GNU config.sub ($timestamp) Copyright 1992-2013 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 # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` 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* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; 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/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -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] | armv7[arm] \ | avr | avr32 \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ | epiphany \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | 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 \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 \ | or1k | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ | rl78 | rx \ | score \ | 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 \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | we32k \ | 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 ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; 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-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | 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-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ | 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-* \ | 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-unknown 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 ;; 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* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; 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 ;; hppa-next) os=-nextstep3 ;; 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 ;; i386-vsta | 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 ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; 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 ;; 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 ;; 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 | ppc-le | powerpc-little) 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 | ppc64-le | powerpc64-little) 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 ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | 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 ;; 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 ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; 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 ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; 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 ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; 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 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First 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* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # 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 | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -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 ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -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 ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -none) ;; *) # 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 ;; or1k-*) 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 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-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 ;; *-next) os=-nextstep3 ;; *-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 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: sofia-sip-1.12.11+20110422.1/configure000077500000000000000000020675501223300710500165140ustar00rootroot00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for sofia-sip 1.12.11devel. # # # 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 &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='sofia-sip' PACKAGE_TARNAME='sofia-sip' PACKAGE_VERSION='1.12.11devel' PACKAGE_STRING='sofia-sip 1.12.11devel' PACKAGE_BUGREPORT='' PACKAGE_URL='' ac_unique_file="libsofia-sip-ua/sip/sofia-sip/sip.h" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS HAVE_NTLM_FALSE HAVE_NTLM_TRUE HAVE_NTH_FALSE HAVE_NTH_TRUE HAVE_STUN_FALSE HAVE_STUN_TRUE HAVE_CHECK_FALSE HAVE_CHECK_TRUE CHECK_LIBS CHECK_CFLAGS HAVE_TLS_FALSE HAVE_TLS_TRUE openssl_LIBS openssl_CFLAGS REPLACE_LIBADD ALLOCA SOFIA_GLIB_PKG_REQUIRES GLIB_VERSION HAVE_GLIB_FALSE HAVE_GLIB_TRUE GLIB_LIBS GLIB_CFLAGS PKG_CONFIG COREFOUNDATION_FALSE COREFOUNDATION_TRUE SOFIA_PLAT_CFLAGS HAVE_DOXYGEN_FALSE HAVE_DOXYGEN_TRUE DOXYGEN ACLOCAL_AMFLAGS EXPENSIVE_CHECKS_FALSE EXPENSIVE_CHECKS_TRUE TESTS_ENVIRONMENT NDEBUG_FALSE NDEBUG_TRUE MOSTLYCLEANFILES COVERAGE_FLAGS GCOV HAVE_GENPNG_FALSE HAVE_GENPNG_TRUE HAVE_LCOV_FALSE HAVE_LCOV_TRUE ENABLE_COVERAGE_FALSE ENABLE_COVERAGE_TRUE GENPNG GENHTML LCOV HAVE_MINGW32_FALSE HAVE_MINGW32_TRUE MINGW_ENVIRONMENT SOFIA_GLIB_CFLAGS SOFIA_CFLAGS CWFLAG OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL MANIFEST_TOOL RANLIB ac_ct_AR DLLTOOL OBJDUMP LN_S NM ac_ct_DUMPBIN DUMPBIN FGREP SED LIBTOOL LD AR ETAGS EGREP GREP CPP am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC MAINT MAINTAINER_MODE_FALSE MAINTAINER_MODE_TRUE 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 LIBVER_SOFIA_SIP_UA_GLIB_SOVER LIBVER_SOFIA_SIP_UA_GLIB_AGE LIBVER_SOFIA_SIP_UA_GLIB_REV LIBVER_SOFIA_SIP_UA_GLIB_CUR LIBVER_SOFIA_SIP_UA_SOVER LIBVER_SOFIA_SIP_UA_AGE LIBVER_SOFIA_SIP_UA_REV LIBVER_SOFIA_SIP_UA_CUR include_sofiadir VER_LIBSOFIA_SIP_UA_MAJOR_MINOR 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' ac_subst_files='' ac_user_opts=' enable_option_checking enable_silent_rules enable_maintainer_mode enable_dependency_tracking enable_shared enable_static with_pic enable_fast_install with_gnu_ld with_sysroot enable_libtool_lock enable_coverage enable_ndebug enable_expensive_checks with_doxygen enable_64 enable_experimental enable_tag_cast enable_size_compat enable_corefoundation enable_ip6 with_rt with_glib with_glib_dir enable_poll_port with_openssl with_sigcomp enable_sctp enable_stun enable_nth enable_ntlm enable_memleak_log ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP SOFIA_CFLAGS SOFIA_GLIB_CFLAGS' # 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 sofia-sip 1.12.11devel 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/sofia-sip] --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 sofia-sip 1.12.11devel:";; 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-maintainer-mode enable make rules and dependencies not useful (and sometimes confusing) to the casual installer --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --enable-shared[=PKGS] build shared libraries [default=yes] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --enable-coverage compile test-coverage [disabled] --enable-ndebug compile with NDEBUG [disabled] --enable-expensive-checks run also expensive checks [disabled] --enable-64 build with 64 bit support --enable-experimental enable experimental features [disabled] --disable-tag-cast cast tag values with inlined functions [enabled] --disable-size-compat use compatibility size_t types [enabled] --enable-corefoundation compile with OSX COREFOUNDATION [disabled] --disable-ip6 disable IPv6 functionality [enabled] --disable-poll-port disable su_poll_port [enabled] Use this option in systems emulating poll with select --enable-sctp use SCTP [disabled] --disable-stun disable stun module (enabled) --disable-nth disable HTTP-related modules nth and http (enabled) --enable-ntlm enable NTLM support [disabled] --enable-memleak-log enable logging of possible memory leaks [disabled] 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-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-doxygen[=CMD] use doxygen command CMD [doxygen] --with-rt use POSIX realtime library [used by default] --with-glib=version use GLib (default=2.0) --with-glib-dir=PREFIX explicitly define GLib path --with-openssl use OpenSSL [enabled] --with-sigcomp=dir use Sofia SigComp package [not used] Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor SOFIA_CFLAGS CFLAGS not used during configure SOFIA_GLIB_CFLAGS Extra CFLAGS for libsofia-sip-ua-glib 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 sofia-sip configure 1.12.11devel 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 declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #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 # ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES # --------------------------------------------- # Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR # accordingly. ac_fn_c_check_decl () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack as_decl_name=`echo $2|sed 's/ *(.*//'` as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 $as_echo_n "checking whether $as_decl_name is declared... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { #ifndef $as_decl_name #ifdef __cplusplus (void) $as_decl_use; #else (void) $as_decl_name; #endif #endif ; return 0; } _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_decl 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 sofia-sip $as_me 1.12.11devel, 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 VER_LIBSOFIA_SIP_UA_MAJOR_MINOR=1.12 include_sofiadir='${includedir}/sofia-sip-1.12' LIBVER_SOFIA_SIP_UA_CUR=6 LIBVER_SOFIA_SIP_UA_REV=0 LIBVER_SOFIA_SIP_UA_AGE=6 LIBVER_SOFIA_SIP_UA_SOVER=0 # CUR-AGE LIBVER_SOFIA_SIP_UA_GLIB_CUR=3 LIBVER_SOFIA_SIP_UA_GLIB_REV=0 LIBVER_SOFIA_SIP_UA_GLIB_AGE=0 LIBVER_SOFIA_SIP_UA_GLIB_SOVER=3 # CUR-AGE ## calls AC_CANONICAL_ macros that are required by AM_INIT_AUTOMAKE 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}- { $as_echo "$as_me:${as_lineno-$LINENO}: checking cached information" >&5 $as_echo_n "checking cached information... " >&6; } hostcheck="$host" if ${ac_cv_hostcheck+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_hostcheck="$hostcheck" fi if test "$ac_cv_hostcheck" != "$hostcheck"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: changed" >&5 $as_echo "changed" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: config.cache exists!" >&5 $as_echo "$as_me: WARNING: config.cache exists!" >&2;} as_fn_error $? "you must do 'make distclean' first to compile for different host or different parameters." "$LINENO" 5 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi am__api_version='1.14' # 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}" != 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='sofia-sip' VERSION='1.12.11devel' 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: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target. 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: 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: . 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 $as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } # Check whether --enable-maintainer-mode was given. if test "${enable_maintainer_mode+set}" = set; then : enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval else USE_MAINTAINER_MODE=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 $as_echo "$USE_MAINTAINER_MODE" >&6; } if test $USE_MAINTAINER_MODE = yes; then MAINTAINER_MODE_TRUE= MAINTAINER_MODE_FALSE='#' else MAINTAINER_MODE_TRUE='#' MAINTAINER_MODE_FALSE= fi MAINT=$MAINTAINER_MODE_TRUE ac_config_headers="$ac_config_headers config.h" ### checks for programs ### ------------------- 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 DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # 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 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="gcc" 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 if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # 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_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="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 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="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 case "`uname -s`" in *win32* | *WIN32* ) # Extract the first word of "cl", so it can be a program name with args. set dummy cl; 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="cl" $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 ;; esac fi test -z "$CC" && as_fn_error $? "no acceptable cc found in \$PATH" "$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 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 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 #include 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 to if __STDC__ is defined, since # 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 #else # include #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 _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 to if __STDC__ is defined, since # 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 #else # include #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 _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 #include #include #include 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 _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 _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 #include #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 { $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 to if __STDC__ is defined, since # 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 #else # include #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 _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 to if __STDC__ is defined, since # 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 #else # include #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 _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 # Extract the first word of "etags", so it can be a program name with args. set dummy etags; 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_ETAGS+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ETAGS"; then ac_cv_prog_ETAGS="$ETAGS" # 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_ETAGS="etags" $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 test -z "$ac_cv_prog_ETAGS" && ac_cv_prog_ETAGS="echo" fi fi ETAGS=$ac_cv_prog_ETAGS if test -n "$ETAGS"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ETAGS" >&5 $as_echo "$ETAGS" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. set dummy ${ac_tool_prefix}ar; 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}ar" $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 fi if test -z "$ac_cv_prog_AR"; then ac_ct_AR=$AR # Extract the first word of "ar", so it can be a program name with args. set dummy ar; 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="ar" $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 if test "x$ac_ct_AR" = x; then AR="ar" 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 else AR="$ac_cv_prog_AR" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ld", so it can be a program name with args. set dummy ${ac_tool_prefix}ld; 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_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LD"; then ac_cv_prog_LD="$LD" # 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_LD="${ac_tool_prefix}ld" $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 LD=$ac_cv_prog_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 fi if test -z "$ac_cv_prog_LD"; then ac_ct_LD=$LD # Extract the first word of "ld", so it can be a program name with args. set dummy ld; 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_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_LD"; then ac_cv_prog_ac_ct_LD="$ac_ct_LD" # 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_LD="ld" $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_LD=$ac_cv_prog_ac_ct_LD if test -n "$ac_ct_LD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LD" >&5 $as_echo "$ac_ct_LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_LD" = x; then LD="ld" 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 LD=$ac_ct_LD fi else LD="$ac_cv_prog_LD" fi 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.2' macro_revision='1.3337' 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 "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test "$GCC" = yes; 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 "$with_gnu_ld" = yes; 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 &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 &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 case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) 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 "$lt_cv_path_NM" != "no"; 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 /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) 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; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # 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 $i != 17 # 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"} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 $as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 $as_echo "$xsi_shell" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 $as_echo_n "checking whether the shell understands \"+=\"... " >&6; } lt_shell_append=no ( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 $as_echo "$lt_shell_append" >&6; } 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 "$GCC" != yes; then reload_cmds=false fi ;; darwin*) if test "$GCC" = yes; 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 # which 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. # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. if ( test "$lt_cv_nm_interface" = "BSD nm" && 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* | netbsdelf*-gnu) 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*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; 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 ;; 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 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 "$ac_status" -eq 0; 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 "$ac_status" -ne 0; 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 "x$lt_cv_ar_at_file" = xno; 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 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 "$host_cpu" = ia64; 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 # 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 -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$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 -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/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 # and D for any global 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};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print 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 con'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* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$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 "$pipe_works" = yes; 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 "$GCC" = yes; 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; } # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test "x$enable_libtool_lock" != xno && 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 which ABI we are using. 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 which ABI we are using. 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 "$lt_cv_prog_gnu_ld" = yes; 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* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. 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 ;; ppc64-*linux*|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" ;; ppc*-*linux*|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 x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; *-*solaris*) # Find out which ABI we are using. 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*) 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 "x$lt_cv_path_mainfest_tool" != xyes; 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 $_lt_result -eq 0; 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 $_lt_result -eq 0 && $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 "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; 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 "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; 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=no enable_win32_dll=no # 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 --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=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 test -z "$pic_mode" && pic_mode=default # 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 # 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 "X${COLLECT_NAMES+set}" != Xset; 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 for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` # 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 "$GCC" = yes; 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" # 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 x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; 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 "$GCC" = yes; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi ;; 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' ;; 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 "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; 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' ;; 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' ;; 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 which 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" # 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 x"$lt_cv_prog_compiler_pic_works" = xyes; 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 x"$lt_cv_prog_compiler_static_works" = xyes; 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 "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; 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 "$hard_links" = no; 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 "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) link_all_deplibs=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 "$with_gnu_ld" = yes; 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 "$lt_use_gnu_ld_interface" = yes; 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 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 "$host_cpu" != ia64; 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 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 (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; 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 ;; 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 "$host_os" = linux-dietlibc; 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 "$tmp_diet" = no 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' ;; 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 "x$supports_anon_versioning" = xyes; 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 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 "x$supports_anon_versioning" = xyes; 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* | netbsdelf*-gnu) 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 can not *** 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 "$ld_shlibs" = no; 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 "$GCC" = yes && 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 "$host_cpu" = ia64; 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 AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". 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) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | 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 # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; 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,' if test "$GCC" = yes; 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 "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi link_all_deplibs=no else # not using gcc if test "$host_cpu" = ia64; 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 "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi 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_use_runtimelinking" = yes; 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 "${lt_cv_aix_libpath+set}" = 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 "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; 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 "${lt_cv_aix_libpath+set}" = 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 "$with_gnu_ld" = yes; 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 # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' 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~linknames=' archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $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 "$lt_cv_ld_force_load" = "yes"; 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*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; 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 "$GCC" = yes; 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 $output_objdir/$soname = $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 $output_objdir/$soname = $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 "$GCC" = yes && test "$with_gnu_ld" = no; 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 "$with_gnu_ld" = no; 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 "$GCC" = yes && test "$with_gnu_ld" = no; 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 x"$lt_cv_prog_compiler__b" = xyes; 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 "$with_gnu_ld" = no; 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 "$GCC" = yes; 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 "$lt_cv_irix_exported_symbol" = yes; 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 ;; netbsd* | netbsdelf*-gnu) 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*) 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__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; 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 case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' ;; *) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; 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 "$GCC" = yes; 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 "$GCC" = yes; 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 "$GCC" = yes; 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 "x$host_vendor" = xsequent; 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 "$GCC" = yes; 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 can NOT 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 "$GCC" = yes; 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 x$host_vendor = xsni; 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 "$ld_shlibs" = no && 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 "$enable_shared" = yes && test "$GCC" = yes; 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 "$GCC" = yes; 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` 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" else 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 "$host_cpu" = ia64; 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 # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.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}' else # 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' fi 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%'\''`; test $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} $libname${shared_ext}' 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=yes 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 "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; 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 "$lt_cv_prog_gnu_ld" = yes; 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 ;; # 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 # Append ld.so.conf contents 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="/lib /usr/lib $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' ;; netbsdelf*-gnu) version_type=linux 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='NetBSD ld.elf_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*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac 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 if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; 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 "$with_gnu_ld" = yes; 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=freebsd-elf 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 "$with_gnu_ld" = yes; 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 "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi { $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 "X$hardcode_automatic" = "Xyes" ; then # We can hardcode non-existent directories. if test "$hardcode_direct" != no && # 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 "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && test "$hardcode_minus_L" != no; 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 "$hardcode_action" = relink || test "$inherit_rpath" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi if test "x$enable_dlopen" != xyes; 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 ;; *) 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 "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && 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 "$cross_compiling" = yes; 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 #endif #include #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 -fvisbility=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 "x$lt_cv_dlopen_self" = xyes; 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 "$cross_compiling" = yes; 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 #endif #include #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 -fvisbility=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 which 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 "$can_build_shared" = "no" && 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 "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no 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 "$enable_shared" = yes || 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: # # Wall # { $as_echo "$as_me:${as_lineno-$LINENO}: checking for maximum warnings compiler flag" >&5 $as_echo_n "checking for maximum warnings compiler flag... " >&6; } if ${sac_cv_cwflag+:} false; then : $as_echo_n "(cached) " >&6 else case "${CC-cc}" in *gcc*) ssac_cv_cwflag=-Wall;; *) case "$host" in *irix*) sac_cv_cwflag=-fullwarn ;; *solaris*) sac_cv_cwflag="-erroff=%none,E_END_OF_LOOP_CODE_NOT_REACHED,E_BAD_PTR_INT_COMBINATION -errtags" ;; *) sac_cv_cwflag=;; esac ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $sac_cv_cwflag" >&5 $as_echo "$sac_cv_cwflag" >&6; } CWFLAG=$sac_cv_cwflag { $as_echo "$as_me:${as_lineno-$LINENO}: checking for compilation environment" >&5 $as_echo_n "checking for compilation environment... " >&6; } if ${sac_cv_cc_environment+:} false; then : $as_echo_n "(cached) " >&6 else machine=`$CC -dumpmachine` if test "$machine" = mingw32 ; then sac_cv_cc_environment=$machine fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $sac_cv_cc_environment" >&5 $as_echo "$sac_cv_cc_environment" >&6; } if test "$sac_cv_cc_environment" = mingw32 ; then CFLAGS="$CFLAGS -I\$(top_srcdir)/win32/pthread -DWINVER=0x0501 \ -D_WIN32_WINNT=0x0501 -DIN_LIBSOFIA_SIP_UA -DIN_LIBSOFIA_SRES \ -mms-bitfields \ -pipe -mno-cygwin -mwindows -mconsole -Wall -g -O0" LDFLAGS="$LDFLAGS -Wl,--enable-auto-image-base" LIBS="-L\$(top_srcdir)/win32/pthread -lpthreadVC2 -lws2_32 \ -lwsock32" MINGW_ENVIRONMENT=1 $as_echo "#define HAVE_MINGW 1" >>confdefs.h $as_echo "#define HAVE_WIN32 1" >>confdefs.h fi if test "x$sac_cv_cc_environment" != x; then HAVE_MINGW32_TRUE= HAVE_MINGW32_FALSE='#' else HAVE_MINGW32_TRUE='#' HAVE_MINGW32_FALSE= fi # # GCoverage # # Check whether --enable-coverage was given. if test "${enable_coverage+set}" = set; then : enableval=$enable_coverage; else enable_coverage=no fi if test X$enable_coverage = Xno ; then : elif test X$GCC != Xyes ; then as_fn_error $? "--enable-coverage requires gcc" "$LINENO" 5 else COVERAGE_FLAGS="-fprofile-arcs -ftest-coverage" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __gcov_init in -lgcov" >&5 $as_echo_n "checking for __gcov_init in -lgcov... " >&6; } if ${ac_cv_lib_gcov___gcov_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgcov $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 __gcov_init (); int main () { return __gcov_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_gcov___gcov_init=yes else ac_cv_lib_gcov___gcov_init=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_gcov___gcov_init" >&5 $as_echo "$ac_cv_lib_gcov___gcov_init" >&6; } if test "x$ac_cv_lib_gcov___gcov_init" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBGCOV 1 _ACEOF LIBS="-lgcov $LIBS" fi GCOV=`echo $CC | sed s/gcc/gcov/g` $as_echo "#define HAVE_COVERAGE 1" >>confdefs.h # Extract the first word of "lcov", so it can be a program name with args. set dummy lcov; 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_LCOV+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LCOV"; then ac_cv_prog_LCOV="$LCOV" # 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_LCOV="lcov" $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 test -z "$ac_cv_prog_LCOV" && ac_cv_prog_LCOV="false" fi fi LCOV=$ac_cv_prog_LCOV if test -n "$LCOV"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LCOV" >&5 $as_echo "$LCOV" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test X$LCOV != Xfalse ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $LCOV accepts --compat-libtool" >&5 $as_echo_n "checking whether $LCOV accepts --compat-libtool... " >&6; } if $LCOV --compat-libtool --help > /dev/null 2>&1 ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5 $as_echo "not supported" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: lcov option --compat-libtool is not supported" >&5 $as_echo "$as_me: WARNING: lcov option --compat-libtool is not supported" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Update lcov to version > 1.5" >&5 $as_echo "$as_me: WARNING: Update lcov to version > 1.5" >&2;} LCOV=false fi fi # Extract the first word of "genhtml", so it can be a program name with args. set dummy genhtml; 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_GENHTML+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$GENHTML"; then ac_cv_prog_GENHTML="$GENHTML" # 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_GENHTML="genhtml" $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 test -z "$ac_cv_prog_GENHTML" && ac_cv_prog_GENHTML="false" fi fi GENHTML=$ac_cv_prog_GENHTML if test -n "$GENHTML"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GENHTML" >&5 $as_echo "$GENHTML" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "genpng", so it can be a program name with args. set dummy genpng; 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_GENPNG+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$GENPNG"; then ac_cv_prog_GENPNG="$GENPNG" # 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_GENPNG="genpng" $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 test -z "$ac_cv_prog_GENPNG" && ac_cv_prog_GENPNG="false" fi fi GENPNG=$ac_cv_prog_GENPNG if test -n "$GENPNG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GENPNG" >&5 $as_echo "$GENPNG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test X$LCOV != Xfalse ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $GENPNG has all required modules" >&5 $as_echo_n "checking whether $GENPNG has all required modules... " >&6; } if $GENPNG --help > /dev/null 2>&1 ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5 $as_echo "not supported" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: GD.pm perl module is not installed" >&5 $as_echo "$as_me: WARNING: GD.pm perl module is not installed" >&2;} GENPNG=false fi fi fi if test X$enable_coverage != Xno; then ENABLE_COVERAGE_TRUE= ENABLE_COVERAGE_FALSE='#' else ENABLE_COVERAGE_TRUE='#' ENABLE_COVERAGE_FALSE= fi if test X$LCOV != Xfalse; then HAVE_LCOV_TRUE= HAVE_LCOV_FALSE='#' else HAVE_LCOV_TRUE='#' HAVE_LCOV_FALSE= fi if test X$GENPNG != Xfalse; then HAVE_GENPNG_TRUE= HAVE_GENPNG_FALSE='#' else HAVE_GENPNG_TRUE='#' HAVE_GENPNG_FALSE= fi MOSTLYCLEANFILES="*.bb *.bbg *.da *.gcov *.gcda *.gcno" # Check whether --enable-ndebug was given. if test "${enable_ndebug+set}" = set; then : enableval=$enable_ndebug; else enable_ndebug=no fi if test x$enable_ndebug = xyes; then NDEBUG_TRUE= NDEBUG_FALSE='#' else NDEBUG_TRUE='#' NDEBUG_FALSE= fi # Check whether --enable-expensive-checks was given. if test "${enable_expensive_checks+set}" = set; then : enableval=$enable_expensive_checks; else enable_expensive_checks=no fi if test x$enable_expensive_checks != xno; then TESTS_ENVIRONMENT=EXPENSIVE_CHECKS=1 fi if test x$enable_expensive_checks != xno; then EXPENSIVE_CHECKS_TRUE= EXPENSIVE_CHECKS_FALSE='#' else EXPENSIVE_CHECKS_TRUE='#' EXPENSIVE_CHECKS_FALSE= fi ACLOCAL_AMFLAGS="-I m4" # Check whether --with-doxygen was given. if test "${with_doxygen+set}" = set; then : withval=$with_doxygen; case $with_doxygen in yes ) doxygen=doxygen ;; no ) doxygen=echo ;; esac else doxygen=doxygen fi # Extract the first word of "doxygen", so it can be a program name with args. set dummy doxygen; 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_DOXYGEN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DOXYGEN"; then ac_cv_prog_DOXYGEN="$DOXYGEN" # 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_DOXYGEN="$doxygen" $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 test -z "$ac_cv_prog_DOXYGEN" && ac_cv_prog_DOXYGEN="echo" fi fi DOXYGEN=$ac_cv_prog_DOXYGEN if test -n "$DOXYGEN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DOXYGEN" >&5 $as_echo "$DOXYGEN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test $DOXYGEN != echo; then HAVE_DOXYGEN_TRUE= HAVE_DOXYGEN_FALSE='#' else HAVE_DOXYGEN_TRUE='#' HAVE_DOXYGEN_FALSE= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler vendor" >&5 $as_echo_n "checking for C compiler vendor... " >&6; } if ${ax_cv_c_compiler_vendor+:} false; then : $as_echo_n "(cached) " >&6 else ax_cv_c_compiler_vendor=unknown # note: don't check for gcc first since some other compilers define __GNUC__ for ventest in intel:__ICC,__ECC,__INTEL_COMPILER ibm:__xlc__,__xlC__,__IBMC__,__IBMCPP__ gnu:__GNUC__ sun:__SUNPRO_C,__SUNPRO_CC hp:__HP_cc,__HP_aCC dec:__DECC,__DECCXX,__DECC_VER,__DECCXX_VER borland:__BORLANDC__,__TURBOC__ comeau:__COMO__ cray:_CRAYC kai:__KCC lcc:__LCC__ metrowerks:__MWERKS__ sgi:__sgi,sgi microsoft:_MSC_VER watcom:__WATCOMC__ portland:__PGI; do vencpp="defined("`echo $ventest | cut -d: -f2 | sed 's/,/) || defined(/g'`")" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #if !($vencpp) thisisanerror; #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ax_cv_c_compiler_vendor=`echo $ventest | cut -d: -f1`; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_c_compiler_vendor" >&5 $as_echo "$ax_cv_c_compiler_vendor" >&6; } SOFIA_PLAT_CFLAGS= # openbsd seems to not define NULL as a void pointer, I blame standards by committee for this. # This is a dirty hack, but shuts up all the warnings case "$host" in *-openbsd*) SOFIA_PLAT_CFLAGS="-DNULL='((void *)0L)'";; *) ;; esac SOFIA_PLAT_CFLAGS=$SOFIA_PLAT_CFLAGS ### checks for libraries ### -------------------- # Enable 64 bit build # Check whether --enable-64 was given. if test "${enable_64+set}" = set; then : enableval=$enable_64; enable_64="$enable_64" else enable_64="no" fi if test "x${ax_cv_c_compiler_vendor}" = "xsun" ; then if test "${enable_64}" = "yes"; then SOFIA_CFLAGS="$SOFIA_CFLAGS -m64" LDFLAGS="-m64 -Wl,-64" export PKG_CONFIG_PATH=/usr/lib/64/pkgconfig fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 $as_echo_n "checking for an ANSI C-conforming const... " >&6; } if ${ac_cv_c_const+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __cplusplus /* Ultrix mips cc rejects this sort of thing. */ typedef int charset[2]; const charset cs = { 0, 0 }; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; { /* SCO 3.2v4 cc rejects this sort of thing. */ char tx; char *t = &tx; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; if (s) return 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; } bx; struct s *b = &bx; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; if (!foo) return 0; } return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_const=yes else ac_cv_c_const=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_const" >&5 $as_echo "$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then $as_echo "#define const /**/" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 $as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } if ${ac_cv_header_time+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { if ((struct tm *) 0) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_time=yes else ac_cv_header_time=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_time" >&5 $as_echo "$ac_cv_header_time" >&6; } if test $ac_cv_header_time = yes; then $as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h fi 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 : else cat >>confdefs.h <<_ACEOF #define size_t unsigned int _ACEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC recognizes __func__" >&5 $as_echo_n "checking whether $CC recognizes __func__... " >&6; } if ${ac_cv_c_var_func+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { char *s = __func__; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_var_func=yes else ac_cv_c_var_func=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_var_func" >&5 $as_echo "$ac_cv_c_var_func" >&6; } if test $ac_cv_c_var_func = "yes"; then $as_echo "#define HAVE_FUNC 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC recognizes __FUNCTION__" >&5 $as_echo_n "checking whether $CC recognizes __FUNCTION__... " >&6; } if ${ac_cv_c_macro_function+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { char *s = __FUNCTION__; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_macro_function=yes else ac_cv_c_macro_function=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_macro_function" >&5 $as_echo "$ac_cv_c_macro_function" >&6; } if test $ac_cv_c_macro_function = "yes"; then $as_echo "#define HAVE_FUNCTION 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 $as_echo_n "checking for inline... " >&6; } if ${ac_cv_c_inline+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo () {return 0; } $ac_kw foo_t foo () {return 0; } #endif _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_inline=$ac_kw fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_inline" != no && break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 $as_echo "$ac_cv_c_inline" >&6; } case $ac_cv_c_inline in inline | yes) ;; *) case $ac_cv_c_inline in no) ac_val=;; *) ac_val=$ac_cv_c_inline;; esac cat >>confdefs.h <<_ACEOF #ifndef __cplusplus #define inline $ac_val #endif _ACEOF ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sa_len" >&5 $as_echo_n "checking for sa_len... " >&6; } if ${ac_cv_sa_len+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { struct sockaddr t;t.sa_len = 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sa_len=yes else ac_cv_sa_len=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sa_len" >&5 $as_echo "$ac_cv_sa_len" >&6; } if test "$ac_cv_sa_len" = yes ;then $as_echo "#define HAVE_SA_LEN 1" >>confdefs.h fi # Beginning of SAC_SOFIA_SU # ====================================================================== # Check for features used by su case "$target" in *-*-solaris?.* ) cat >>confdefs.h <<\_AXEOF #define __EXTENSIONS__ 1 _AXEOF ;; esac # Check includes used by su includes ac_fn_c_check_header_mongrel "$LINENO" "sys/types.h" "ac_cv_header_sys_types_h" "$ac_includes_default" if test "x$ac_cv_header_sys_types_h" = xyes; then : cat >>confdefs.h <<\_AXEOF #define SU_HAVE_SYS_TYPES 1 _AXEOF fi ax_inttypes=false ac_fn_c_check_header_mongrel "$LINENO" "stdint.h" "ac_cv_header_stdint_h" "$ac_includes_default" if test "x$ac_cv_header_stdint_h" = xyes; then : ax_inttypes=true cat >>confdefs.h <<\_AXEOF #define SU_HAVE_STDINT 1 _AXEOF fi ac_fn_c_check_header_mongrel "$LINENO" "inttypes.h" "ac_cv_header_inttypes_h" "$ac_includes_default" if test "x$ac_cv_header_inttypes_h" = xyes; then : ax_inttypes=true cat >>confdefs.h <<\_AXEOF #define SU_HAVE_INTTYPES 1 _AXEOF fi if $ax_inttypes; then : ; else as_fn_error $? "\"No or found.\"" "$LINENO" 5 fi if test "x$MINGW_ENVIRONMENT" != x1 ; then ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default" if test "x$ac_cv_header_pthread_h" = xyes; then : HAVE_PTHREADS=1; cat >>confdefs.h <<\_AXEOF #define SU_HAVE_PTHREADS 1 _AXEOF fi else HAVE_PTHREADS=1; cat >>confdefs.h <<\_AXEOF #define SU_HAVE_PTHREADS 1 _AXEOF fi # Check whether --enable-experimental was given. if test "${enable_experimental+set}" = set; then : enableval=$enable_experimental; else enable_experimental=no fi if test $enable_experimental = yes ; then cat >>confdefs.h <<\_AXEOF #define SU_HAVE_EXPERIMENTAL 1 _AXEOF fi # Check whether --enable-tag-cast was given. if test "${enable_tag_cast+set}" = set; then : enableval=$enable_tag_cast; else enable_tag_cast=yes fi if test "$enable_tag_cast" = "yes"; then tag_cast=1 else tag_cast=0 fi case "$ac_cv_c_inline" in yes) cat >>confdefs.h <<\_AXEOF #define su_inline static inline _AXEOF cat >>confdefs.h <<\_AXEOF #define SU_INLINE inline _AXEOF cat >>confdefs.h <<\_AXEOF #define SU_HAVE_INLINE 1 _AXEOF cat >>confdefs.h <<_ACEOF #define SU_INLINE_TAG_CAST $tag_cast _ACEOF ;; no | "" ) cat >>confdefs.h <<\_AXEOF #define su_inline static _AXEOF cat >>confdefs.h <<\_AXEOF #define SU_INLINE /*inline*/ _AXEOF cat >>confdefs.h <<\_AXEOF #define SU_HAVE_INLINE 0 _AXEOF cat >>confdefs.h <<\_AXEOF #define SU_INLINE_TAG_CAST 0 _AXEOF ;; *) cat >>confdefs.h <<_ACEOF #define su_inline static $ac_cv_c_inline _ACEOF cat >>confdefs.h <<_ACEOF #define SU_INLINE $ac_cv_c_inline _ACEOF cat >>confdefs.h <<\_AXEOF #define SU_HAVE_INLINE 1 _AXEOF cat >>confdefs.h <<_ACEOF #define SU_INLINE_TAG_CAST $tag_cast _ACEOF ;; esac # Check whether --enable-size-compat was given. if test "${enable_size_compat+set}" = set; then : enableval=$enable_size_compat; else enable_size_compat=yes fi if test X$enable_size_compat != Xyes; then cat >>confdefs.h <<\_AXEOF #define SOFIA_ISIZE_T size_t _AXEOF cat >>confdefs.h <<\_AXEOF #define ISIZE_MAX SIZE_MAX _AXEOF cat >>confdefs.h <<\_AXEOF #define SOFIA_ISSIZE_T ssize_t _AXEOF cat >>confdefs.h <<\_AXEOF #define ISSIZE_MAX SSIZE_MAX _AXEOF cat >>confdefs.h <<\_AXEOF #define SOFIA_USIZE_T size_t _AXEOF cat >>confdefs.h <<\_AXEOF #define USIZE_MAX SIZE_MAX _AXEOF else cat >>confdefs.h <<\_AXEOF #define SOFIA_ISIZE_T int _AXEOF cat >>confdefs.h <<\_AXEOF #define ISIZE_MAX INT_MAX _AXEOF cat >>confdefs.h <<\_AXEOF #define SOFIA_ISSIZE_T int _AXEOF cat >>confdefs.h <<\_AXEOF #define ISSIZE_MAX INT_MAX _AXEOF cat >>confdefs.h <<\_AXEOF #define SOFIA_USIZE_T unsigned _AXEOF cat >>confdefs.h <<\_AXEOF #define USIZE_MAX UINT_MAX _AXEOF fi # Check whether --enable-corefoundation was given. if test "${enable_corefoundation+set}" = set; then : enableval=$enable_corefoundation; else enable_corefoundation=no fi if test $enable_corefoundation = yes; then COREFOUNDATION_TRUE= COREFOUNDATION_FALSE='#' else COREFOUNDATION_TRUE='#' COREFOUNDATION_FALSE= fi if test $enable_corefoundation = yes ; then cat >>confdefs.h <<\_AXEOF #define SU_HAVE_OSX_CF_API 1 _AXEOF LIBS="-framework CoreFoundation -framework SystemConfiguration $LIBS" fi ### ====================================================================== ### Test if we have stack suitable for handling tags directly ### { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stack suitable for tags" >&5 $as_echo_n "checking for stack suitable for tags... " >&6; } if ${ac_cv_tagstack+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_tagstack=no if test "$cross_compiling" = yes; then : case "$target" in i?86-*-* ) ac_cv_tagstack=yes ;; * ) ac_cv_tagstack=no ;; esac else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if HAVE_INTTYPES_H #include #endif #if HAVE_STDINT_H #include #endif #include typedef void *tp; typedef intptr_t tv; int test1(tv l, tv h, ...) { va_list ap; tv i, *p = &l; va_start(ap, h); if (*p++ != l || *p++ != h) return 1; for (i = l; i <= h; i++) { if (*p++ != i) return 1; } for (i = l; i <= h; i++) { if (va_arg(ap, tv) != i) return 1; } va_end(ap); return 0; } int main(int avc, char **av) { return test1((tv)1, (tv)10, (tv)1, (tv)2, (tv)3, (tv)4, (tv)5, (tv)6, (tv)7, (tv)8, (tv)9, (tv)10); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_tagstack=yes else ac_cv_tagstack=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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_tagstack" >&5 $as_echo "$ac_cv_tagstack" >&6; } if test $ac_cv_tagstack = yes ; then cat >>confdefs.h <<\_AXEOF #define SU_HAVE_TAGSTACK 1 _AXEOF fi ### ====================================================================== ### Test if free(0) fails ### { $as_echo "$as_me:${as_lineno-$LINENO}: checking for graceful free(0)" >&5 $as_echo_n "checking for graceful free(0)... " >&6; } if ${ac_cv_free_null+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_free_null=no if test "$cross_compiling" = yes; then : ac_cv_free_null=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main(int avc, char **av) { free(0); return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_free_null=yes else ac_cv_free_null=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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_free_null" >&5 $as_echo "$ac_cv_free_null" >&6; } if test $ac_cv_free_null = yes ; then $as_echo "#define HAVE_FREE_NULL 1" >>confdefs.h fi if test "$ac_cv_sa_len" = yes ;then cat >>confdefs.h <<\_AXEOF #define SU_HAVE_SOCKADDR_SA_LEN 1 _AXEOF fi # Check whether --enable-ip6 was given. if test "${enable_ip6+set}" = set; then : enableval=$enable_ip6; else enable_ip6=yes fi if ! test no$enable_ip6 = nono ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sockaddr_in6" >&5 $as_echo_n "checking for sockaddr_in6... " >&6; } if ${ac_cv_sin6+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "struct sockaddr_in6" >/dev/null 2>&1; then : ac_cv_sin6=yes else ac_cv_sin6=no fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sin6" >&5 $as_echo "$ac_cv_sin6" >&6; } if test $ac_cv_sin6 = yes ;then $as_echo "#define HAVE_SIN6 1" >>confdefs.h fi case $ac_cv_sin6 in yes) cat >>confdefs.h <<\_AXEOF #define SU_HAVE_IN6 1 _AXEOF ;; no) ;; *) as_fn_error $? "Inconsistent struct sockaddr_sin6 test" "$LINENO" 5 ;; esac fi for ac_header in unistd.h sys/time.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 fcntl.h dirent.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 winsock2.h do : ac_fn_c_check_header_mongrel "$LINENO" "winsock2.h" "ac_cv_header_winsock2_h" "$ac_includes_default" if test "x$ac_cv_header_winsock2_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_WINSOCK2_H 1 _ACEOF $as_echo "#define HAVE_WIN32 1" >>confdefs.h cat >>confdefs.h <<\_AXEOF #define SU_HAVE_WINSOCK 1 _AXEOF cat >>confdefs.h <<\_AXEOF #define SU_HAVE_WINSOCK2 1 _AXEOF cat >>confdefs.h <<\_AXEOF #define SU_HAVE_SOCKADDR_STORAGE 1 _AXEOF $as_echo "#define HAVE_ADDRINFO 1" >>confdefs.h $as_echo "#define HAVE_GETADDRINFO 1" >>confdefs.h $as_echo "#define HAVE_FREEADDRINFO 1" >>confdefs.h cat >>confdefs.h <<\_AXEOF #define SU_HAVE_ADDRINFO 1 _AXEOF for ac_header in windef.h ws2tcpip.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 iphlpapi.h do : ac_fn_c_check_header_compile "$LINENO" "iphlpapi.h" "ac_cv_header_iphlpapi_h" "#if HAVE_WINDEF_H #include #include #endif " if test "x$ac_cv_header_iphlpapi_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_IPHLPAPI_H 1 _ACEOF $as_echo "#define HAVE_INTERFACE_INFO_EX 1" >>confdefs.h $as_echo "#define HAVE_SIO_ADDRESS_LIST_QUERY 1" >>confdefs.h fi done $as_echo "#define HAVE_FILETIME 1" >>confdefs.h else cat >>confdefs.h <<\_AXEOF #define SU_HAVE_BSDSOCK 1 _AXEOF for ac_header in sys/socket.h sys/ioctl.h sys/filio.h sys/sockio.h \ sys/select.h sys/epoll.h sys/devpoll.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 netinet/in.h arpa/inet.h netdb.h \ net/if.h net/if_types.h ifaddr.h netpacket/packet.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" " #include #include " 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_decl "$LINENO" "MSG_TRUNC" "ac_cv_have_decl_MSG_TRUNC" " #include #include " if test "x$ac_cv_have_decl_MSG_TRUNC" = xyes; then : $as_echo "#define HAVE_MSG_TRUNC 1" >>confdefs.h fi ac_fn_c_check_decl "$LINENO" "SO_RCVBUFFORCE" "ac_cv_have_decl_SO_RCVBUFFORCE" " #include #include " if test "x$ac_cv_have_decl_SO_RCVBUFFORCE" = xyes; then : $as_echo "#define HAVE_SO_RCVBUFFORCE 1" >>confdefs.h fi ac_fn_c_check_decl "$LINENO" "SO_SNDBUFFORCE" "ac_cv_have_decl_SO_SNDBUFFORCE" " #include #include " if test "x$ac_cv_have_decl_SO_SNDBUFFORCE" = xyes; then : $as_echo "#define HAVE_SO_SNDBUFFORCE 1" >>confdefs.h fi ac_fn_c_check_decl "$LINENO" "IP_ADD_MEMBERSHIP" "ac_cv_have_decl_IP_ADD_MEMBERSHIP" " #include #include #include " if test "x$ac_cv_have_decl_IP_ADD_MEMBERSHIP" = xyes; then : $as_echo "#define HAVE_IP_ADD_MEMBERSHIP 1" >>confdefs.h fi ac_fn_c_check_decl "$LINENO" "IP_MULTICAST_LOOP" "ac_cv_have_decl_IP_MULTICAST_LOOP" " #include #include #include " if test "x$ac_cv_have_decl_IP_MULTICAST_LOOP" = xyes; then : $as_echo "#define HAVE_IP_MULTICAST_LOOP 1" >>confdefs.h fi ac_fn_c_check_decl "$LINENO" "IP_MTU_DISCOVER" "ac_cv_have_decl_IP_MTU_DISCOVER" " #include #include #include " if test "x$ac_cv_have_decl_IP_MTU_DISCOVER" = xyes; then : $as_echo "#define HAVE_IP_MTU_DISCOVER 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct addrinfo" >&5 $as_echo_n "checking for struct addrinfo... " >&6; } if ${ac_cv_struct_addrinfo+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_struct_addrinfo=no if test "$ac_cv_header_sys_socket_h" = yes; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "struct.+addrinfo" >/dev/null 2>&1; then : ac_cv_struct_addrinfo=yes fi rm -f conftest* else ac_cv_struct_addrinfo='sys/socket.h missing' fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_addrinfo" >&5 $as_echo "$ac_cv_struct_addrinfo" >&6; } if test "$ac_cv_struct_addrinfo" = yes; then cat >>confdefs.h <<\_AXEOF #define SU_HAVE_ADDRINFO 1 _AXEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct sockaddr_storage" >&5 $as_echo_n "checking for struct sockaddr_storage... " >&6; } if ${ac_cv_struct_sockaddr_storage+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_struct_sockaddr_storage=no if test "$ac_cv_header_sys_socket_h" = yes; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "struct.+sockaddr_storage" >/dev/null 2>&1; then : ac_cv_struct_sockaddr_storage=yes fi rm -f conftest* else ac_cv_struct_sockaddr_storage='sys/socket.h missing' fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_sockaddr_storage" >&5 $as_echo "$ac_cv_struct_sockaddr_storage" >&6; } if test "$ac_cv_struct_sockaddr_storage" = yes; then cat >>confdefs.h <<\_AXEOF #define SU_HAVE_SOCKADDR_STORAGE 1 _AXEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for field ifr_index in struct ifreq" >&5 $as_echo_n "checking for field ifr_index in struct ifreq... " >&6; } if ${ac_cv_struct_ifreq_ifr_index+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_struct_ifreq_ifr_index=no if test "1${ac_cv_header_arpa_inet_h}2${ac_cv_header_netdb_h}3${ac_cv_header_sys_socket_h}4${ac_cv_header_net_if_h}" = 1yes2yes3yes4yes; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include int main () { struct ifreq ifreq; int index; index = ifreq.ifr_index; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_struct_ifreq_ifr_index=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else ac_cv_struct_ifreq_ifr_index='net/if.h missing' fi # arpa/inet.h && netdb.h && sys/socket.h && net/if.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_ifreq_ifr_index" >&5 $as_echo "$ac_cv_struct_ifreq_ifr_index" >&6; } if test "$ac_cv_struct_ifreq_ifr_index" = yes ; then : $as_echo "#define HAVE_IFR_INDEX 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for field ifr_ifindex in struct ifreq" >&5 $as_echo_n "checking for field ifr_ifindex in struct ifreq... " >&6; } if ${ac_cv_struct_ifreq_ifr_ifindex+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_struct_ifreq_ifr_ifindex=no if test "1${ac_cv_header_arpa_inet_h}2${ac_cv_header_netdb_h}3${ac_cv_header_sys_socket_h}4${ac_cv_header_net_if_h}" = 1yes2yes3yes4yes; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include int main () { struct ifreq ifreq; int index; index = ifreq.ifr_ifindex; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_struct_ifreq_ifr_ifindex=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else ac_cv_struct_ifreq_ifr_ifindex='net/if.h missing' fi # arpa/inet.h && netdb.h && sys/socket.h && net/if.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_ifreq_ifr_ifindex" >&5 $as_echo "$ac_cv_struct_ifreq_ifr_ifindex" >&6; } if test "$ac_cv_struct_ifreq_ifr_ifindex" = yes; then : $as_echo "#define HAVE_IFR_IFINDEX 1" >>confdefs.h fi fi # ifr_index in struct ifreq { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct ifconf" >&5 $as_echo_n "checking for struct ifconf... " >&6; } if ${ac_cv_struct_ifconf+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_struct_ifconf=no if test "$ac_cv_header_net_if_h" = yes; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "struct.+ifconf" >/dev/null 2>&1; then : ac_cv_struct_ifconf=yes fi rm -f conftest* else ac_cv_struct_ifconf='net/if.h missing' fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_ifconf" >&5 $as_echo "$ac_cv_struct_ifconf" >&6; } if test "$ac_cv_struct_ifconf" = yes; then $as_echo "#define HAVE_IFCONF 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ioctl SIOCGIFNUM" >&5 $as_echo_n "checking for ioctl SIOCGIFNUM... " >&6; } if ${ac_cv_ioctl_siocgifnum+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_ioctl_siocgifnum=no if test "$ac_cv_header_sys_sockio_h" = yes; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifdef SIOCGIFNUM yes #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "yes" >/dev/null 2>&1; then : ac_cv_ioctl_siocgifnum=yes fi rm -f conftest* else ac_cv_ioctl_siocgifnum='sys/sockio.h missing' fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_ioctl_siocgifnum" >&5 $as_echo "$ac_cv_ioctl_siocgifnum" >&6; } if test "$ac_cv_ioctl_siocgifnum" = yes; then HAVE_IFNUM=1 $as_echo "#define HAVE_IFNUM 1" >>confdefs.h else HAVE_IFNUM=0 fi fi done # =========================================================================== # Checks for libraries # =========================================================================== { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5 $as_echo_n "checking for pthread_create in -lpthread... " >&6; } if ${ac_cv_lib_pthread_pthread_create+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $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 pthread_create (); int main () { return pthread_create (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pthread_pthread_create=yes else ac_cv_lib_pthread_pthread_create=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_pthread_pthread_create" >&5 $as_echo "$ac_cv_lib_pthread_pthread_create" >&6; } if test "x$ac_cv_lib_pthread_pthread_create" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBPTHREAD 1 _ACEOF LIBS="-lpthread $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socketpair in -lsocket" >&5 $as_echo_n "checking for socketpair in -lsocket... " >&6; } if ${ac_cv_lib_socket_socketpair+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket -lnsl $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 socketpair (); int main () { return socketpair (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_socket_socketpair=yes else ac_cv_lib_socket_socketpair=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_socket_socketpair" >&5 $as_echo "$ac_cv_lib_socket_socketpair" >&6; } if test "x$ac_cv_lib_socket_socketpair" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBSOCKET 1 _ACEOF LIBS="-lsocket $LIBS" fi # Check whether --with-rt was given. if test "${with_rt+set}" = set; then : withval=$with_rt; fi if test "${with_rt}" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5 $as_echo_n "checking for library containing clock_gettime... " >&6; } if ${ac_cv_search_clock_gettime+:} 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 clock_gettime (); int main () { return clock_gettime (); ; return 0; } _ACEOF for ac_lib in '' rt; 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_clock_gettime=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_clock_gettime+:} false; then : break fi done if ${ac_cv_search_clock_gettime+:} false; then : else ac_cv_search_clock_gettime=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5 $as_echo "$ac_cv_search_clock_gettime" >&6; } ac_res=$ac_cv_search_clock_gettime if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi for ac_func in clock_gettime clock_getcpuclockid do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done ac_fn_c_check_decl "$LINENO" "CLOCK_MONOTONIC" "ac_cv_have_decl_CLOCK_MONOTONIC" " #include " if test "x$ac_cv_have_decl_CLOCK_MONOTONIC" = xyes; then : $as_echo "#define HAVE_CLOCK_MONOTONIC 1" >>confdefs.h fi fi # No GLib path explicitly defined, use pkg-config # Check whether --with-glib was given. if test "${with_glib+set}" = set; then : withval=$with_glib; case "$with_glib" in yes | "" ) with_glib=2.0 ;; esac else with_glib=2.0 fi # Check whether --with-glib-dir was given. if test "${with_glib_dir+set}" = set; then : withval=$with_glib_dir; else with_glib_dir="pkg-config" fi if test "$with_glib" = no || test "$with_glib_dir" = "no" ; then : # No glib elif test "$with_glib_dir" = "pkg-config" ; then succeeded=no if test -z "$PKG_CONFIG"; then # 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_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 test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no" ;; 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 "$PKG_CONFIG" = "no" ; then echo "*** The pkg-config script could not be found. Make sure it is" echo "*** in your path, or set the PKG_CONFIG environment variable" echo "*** to the full path to pkg-config." echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config." else PKG_CONFIG_MIN_VERSION=0.9.0 if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for glib-$with_glib" >&5 $as_echo_n "checking for glib-$with_glib... " >&6; } if $PKG_CONFIG --exists "glib-$with_glib" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } succeeded=yes { $as_echo "$as_me:${as_lineno-$LINENO}: checking GLIB_CFLAGS" >&5 $as_echo_n "checking GLIB_CFLAGS... " >&6; } GLIB_CFLAGS=`$PKG_CONFIG --cflags "glib-$with_glib"` { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GLIB_CFLAGS" >&5 $as_echo "$GLIB_CFLAGS" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking GLIB_LIBS" >&5 $as_echo_n "checking GLIB_LIBS... " >&6; } GLIB_LIBS=`$PKG_CONFIG --libs "glib-$with_glib"` { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GLIB_LIBS" >&5 $as_echo "$GLIB_LIBS" >&6; } else GLIB_CFLAGS="" GLIB_LIBS="" ## If we have a custom action on failure, don't print errors, but ## do set a variable so people can do so. GLIB_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "glib-$with_glib"` fi else echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer." echo "*** See http://www.freedesktop.org/software/pkgconfig" fi fi if test $succeeded = yes; then HAVE_GLIB=yes else HAVE_GLIB=no fi else # GLib path is explicitly defined gprefix=$with_glib_dir GLIB_VERSION="$with_glib" GLIBXXX=glib-$with_glib if test "$gprefix" = "yes" ; then for gprefix in /usr /usr/local /opt/$GLIBXXX do test -d $gprefix/include/$GLIBXXX && break done fi if ! test -d $gprefix/include/$GLIBXXX ; then as_fn_error $? "\"No $GLIBXXX in --with-glib=$with_glib_dir\"" "$LINENO" 5 else exec_gprefix=${gprefix} glibdir=${exec_gprefix}/lib gincludedir=${gprefix}/include # glib_genmarshal=glib-genmarshal # glib_mkenums=glib-mkenums HAVE_GLIB=yes if test "x$MINGW_ENVIRONMENT" = x1 ; then GLIB_LIBS="${glibdir}/lib$GLIBXXX.dll.a ${glibdir}/libintl.a ${glibdir}/libiconv.a" else GLIB_LIBS="-L${glibdir} -l$GLIBXXX -lintl -liconv" fi GLIB_CFLAGS="-I${gincludedir}/$GLIBXXX -I${glibdir}/$GLIBXXX/include" fi fi # GLib path is explicitly defined if test "x$HAVE_GLIB" = xyes ; then SOFIA_GLIB_PKG_REQUIRES="`test -n "$SOFIA_GLIB_PKG_REQUIRES" && echo "$SOFIA_GLIB_PKG_REQUIRES, "`glib-2.0" fi if test "x$HAVE_GLIB" = xyes; then HAVE_GLIB_TRUE= HAVE_GLIB_FALSE='#' else HAVE_GLIB_TRUE='#' HAVE_GLIB_FALSE= fi # =========================================================================== # Checks for library functions. # =========================================================================== { $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 '' xnet socket; 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing inet_ntop" >&5 $as_echo_n "checking for library containing inet_ntop... " >&6; } if ${ac_cv_search_inet_ntop+:} 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_ntop (); int main () { return inet_ntop (); ; return 0; } _ACEOF for ac_lib in '' socket 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_ntop=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_inet_ntop+:} false; then : break fi done if ${ac_cv_search_inet_ntop+:} false; then : else ac_cv_search_inet_ntop=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_ntop" >&5 $as_echo "$ac_cv_search_inet_ntop" >&6; } ac_res=$ac_cv_search_inet_ntop 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 getipnodebyname" >&5 $as_echo_n "checking for library containing getipnodebyname... " >&6; } if ${ac_cv_search_getipnodebyname+:} 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 getipnodebyname (); int main () { return getipnodebyname (); ; return 0; } _ACEOF for ac_lib in '' xnet socket 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_getipnodebyname=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_getipnodebyname+:} false; then : break fi done if ${ac_cv_search_getipnodebyname+:} false; then : else ac_cv_search_getipnodebyname=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_getipnodebyname" >&5 $as_echo "$ac_cv_search_getipnodebyname" >&6; } ac_res=$ac_cv_search_getipnodebyname 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 gethostbyname" >&5 $as_echo_n "checking for library containing gethostbyname... " >&6; } if ${ac_cv_search_gethostbyname+:} 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 gethostbyname (); int main () { return gethostbyname (); ; return 0; } _ACEOF for ac_lib in '' xnet 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_gethostbyname=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_gethostbyname+:} false; then : break fi done if ${ac_cv_search_gethostbyname+:} false; then : else ac_cv_search_gethostbyname=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5 $as_echo "$ac_cv_search_gethostbyname" >&6; } ac_res=$ac_cv_search_gethostbyname 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 getaddrinfo" >&5 $as_echo_n "checking for library containing getaddrinfo... " >&6; } if ${ac_cv_search_getaddrinfo+:} 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 getaddrinfo (); int main () { return getaddrinfo (); ; return 0; } _ACEOF for ac_lib in '' xnet socket 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_getaddrinfo=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_getaddrinfo+:} false; then : break fi done if ${ac_cv_search_getaddrinfo+:} false; then : else ac_cv_search_getaddrinfo=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_getaddrinfo" >&5 $as_echo "$ac_cv_search_getaddrinfo" >&6; } ac_res=$ac_cv_search_getaddrinfo if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works # for constant arguments. Useless! { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working alloca.h" >&5 $as_echo_n "checking for working alloca.h... " >&6; } if ${ac_cv_working_alloca_h+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { char *p = (char *) alloca (2 * sizeof (int)); if (p) return 0; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_working_alloca_h=yes else ac_cv_working_alloca_h=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_working_alloca_h" >&5 $as_echo "$ac_cv_working_alloca_h" >&6; } if test $ac_cv_working_alloca_h = yes; then $as_echo "#define HAVE_ALLOCA_H 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for alloca" >&5 $as_echo_n "checking for alloca... " >&6; } if ${ac_cv_func_alloca_works+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __GNUC__ # define alloca __builtin_alloca #else # ifdef _MSC_VER # include # define alloca _alloca # else # ifdef HAVE_ALLOCA_H # include # else # ifdef _AIX #pragma alloca # else # ifndef alloca /* predefined by HP cc +Olibcalls */ void *alloca (size_t); # endif # endif # endif # endif #endif int main () { char *p = (char *) alloca (1); if (p) return 0; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_func_alloca_works=yes else ac_cv_func_alloca_works=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_alloca_works" >&5 $as_echo "$ac_cv_func_alloca_works" >&6; } if test $ac_cv_func_alloca_works = yes; then $as_echo "#define HAVE_ALLOCA 1" >>confdefs.h else # The SVR3 libPW and SVR4 libucb both contain incompatible functions # that cause trouble. Some versions do not even contain alloca or # contain a buggy version. If you still want to use their alloca, # use ar to extract alloca.o from them instead of compiling alloca.c. ALLOCA=\${LIBOBJDIR}alloca.$ac_objext $as_echo "#define C_ALLOCA 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether \`alloca.c' needs Cray hooks" >&5 $as_echo_n "checking whether \`alloca.c' needs Cray hooks... " >&6; } if ${ac_cv_os_cray+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined CRAY && ! defined CRAY2 webecray #else wenotbecray #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "webecray" >/dev/null 2>&1; then : ac_cv_os_cray=yes else ac_cv_os_cray=no fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_os_cray" >&5 $as_echo "$ac_cv_os_cray" >&6; } if test $ac_cv_os_cray = yes; then for ac_func in _getb67 GETB67 getb67; do as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define CRAY_STACKSEG_END $ac_func _ACEOF break fi done fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking stack direction for C alloca" >&5 $as_echo_n "checking stack direction for C alloca... " >&6; } if ${ac_cv_c_stack_direction+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_c_stack_direction=0 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int find_stack_direction (int *addr, int depth) { int dir, dummy = 0; if (! addr) addr = &dummy; *addr = addr < &dummy ? 1 : addr == &dummy ? 0 : -1; dir = depth ? find_stack_direction (addr, depth - 1) : 0; return dir + dummy; } int main (int argc, char **argv) { return find_stack_direction (0, argc + !argv + 20) < 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_c_stack_direction=1 else ac_cv_c_stack_direction=-1 fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_stack_direction" >&5 $as_echo "$ac_cv_c_stack_direction" >&6; } cat >>confdefs.h <<_ACEOF #define STACK_DIRECTION $ac_cv_c_stack_direction _ACEOF fi for ac_func in gettimeofday strerror random initstate tcsetattr flock \ socketpair gethostname gethostbyname getipnodebyname \ poll epoll_create kqueue select if_nameindex \ signal alarm \ strnlen \ memmem \ getaddrinfo getnameinfo freeaddrinfo gai_strerror getifaddrs \ getline getdelim getpass do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done # getline getdelim getpass are _GNU_SOURCE stuff if test $ac_cv_func_poll = yes ; then cat >>confdefs.h <<\_AXEOF #define SU_HAVE_POLL 1 _AXEOF fi if test $ac_cv_func_epoll_create = yes && test $ac_cv_header_sys_epoll_h = yes then $as_echo "#define HAVE_EPOLL 1" >>confdefs.h fi if test $ac_cv_func_if_nameindex = yes ; then cat >>confdefs.h <<\_AXEOF #define SU_HAVE_IF_NAMEINDEX 1 _AXEOF fi for ac_func in memccpy memspn memcspn strtoull \ inet_ntop inet_pton poll do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF : else case "$REPLACE_LIBADD" in "$ac_func.lo" | \ *" $ac_func.lo" | \ "$ac_func.lo "* | \ *" $ac_func.lo "* ) ;; *) REPLACE_LIBADD="$REPLACE_LIBADD $ac_func.lo" ;; esac fi done : if test $ac_cv_func_signal = yes ; then ac_fn_c_check_decl "$LINENO" "SIGPIPE" "ac_cv_have_decl_SIGPIPE" " #include " if test "x$ac_cv_have_decl_SIGPIPE" = xyes; then : $as_echo "#define HAVE_SIGPIPE 1" >>confdefs.h fi fi # =========================================================================== # Check how to implement su_port # =========================================================================== # Check whether --enable-poll-port was given. if test "${enable_poll_port+set}" = set; then : enableval=$enable_poll_port; else enable_poll_port=maybe fi if test $enable_poll_port = maybe ; then if test $ac_cv_func_poll = yes ; then $as_echo "#define HAVE_POLL_PORT 1" >>confdefs.h fi elif test $enable_poll_port = yes ; then $as_echo "#define HAVE_POLL_PORT 1" >>confdefs.h fi # =========================================================================== # Check pthread_rwlock_unlock() # =========================================================================== if test x$HAVE_PTHREADS = x1 ; then if test "$cross_compiling" = yes; then : $as_echo "#define HAVE_PTHREAD_RWLOCK 1" >>confdefs.h else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _XOPEN_SOURCE (500) #include pthread_rwlock_t rw; int main() { pthread_rwlock_init(&rw, NULL); pthread_rwlock_rdlock(&rw); pthread_rwlock_rdlock(&rw); pthread_rwlock_unlock(&rw); /* pthread_rwlock_trywrlock() should fail (not return 0) */ return pthread_rwlock_trywrlock(&rw) != 0 ? 0 : 1; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : $as_echo "#define HAVE_PTHREAD_RWLOCK 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Recursive pthread_rwlock_rdlock() does not work!!! " >&5 $as_echo "$as_me: WARNING: Recursive pthread_rwlock_rdlock() does not work!!! " >&2;} fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi # =========================================================================== # Check IPv6 addresss configuration # =========================================================================== case "$target" in *-*-linux*) $as_echo "#define HAVE_PROC_NET_IF_INET6 1" >>confdefs.h ;; esac ac_config_headers="$ac_config_headers libsofia-sip-ua/su/sofia-sip/su_configure.h" # End of SAC_SOFIA_SU # Check whether --with-openssl was given. if test "${with_openssl+set}" = set; then : withval=$with_openssl; else with_openssl=pkg-config fi if test "$with_openssl" = no ;then : # No openssl else if test "$with_openssl" = "pkg-config" ; then succeeded=no if test -z "$PKG_CONFIG"; then # 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_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 test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no" ;; 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 "$PKG_CONFIG" = "no" ; then echo "*** The pkg-config script could not be found. Make sure it is" echo "*** in your path, or set the PKG_CONFIG environment variable" echo "*** to the full path to pkg-config." echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config." else PKG_CONFIG_MIN_VERSION=0.9.0 if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for openssl" >&5 $as_echo_n "checking for openssl... " >&6; } if $PKG_CONFIG --exists "openssl" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } succeeded=yes { $as_echo "$as_me:${as_lineno-$LINENO}: checking openssl_CFLAGS" >&5 $as_echo_n "checking openssl_CFLAGS... " >&6; } openssl_CFLAGS=`$PKG_CONFIG --cflags "openssl"` { $as_echo "$as_me:${as_lineno-$LINENO}: result: $openssl_CFLAGS" >&5 $as_echo "$openssl_CFLAGS" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking openssl_LIBS" >&5 $as_echo_n "checking openssl_LIBS... " >&6; } openssl_LIBS=`$PKG_CONFIG --libs "openssl"` { $as_echo "$as_me:${as_lineno-$LINENO}: result: $openssl_LIBS" >&5 $as_echo "$openssl_LIBS" >&6; } else openssl_CFLAGS="" openssl_LIBS="" ## If we have a custom action on failure, don't print errors, but ## do set a variable so people can do so. openssl_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "openssl"` fi else echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer." echo "*** See http://www.freedesktop.org/software/pkgconfig" fi fi if test $succeeded = yes; then HAVE_TLS=1 HAVE_OPENSSL=1 else HAVE_OPENSSL=0 fi fi if test x$HAVE_OPENSSL = x1 ; then $as_echo "#define HAVE_LIBCRYPTO 1" >>confdefs.h $as_echo "#define HAVE_LIBSSL 1" >>confdefs.h else for ac_header in openssl/tls1.h do : ac_fn_c_check_header_mongrel "$LINENO" "openssl/tls1.h" "ac_cv_header_openssl_tls1_h" "$ac_includes_default" if test "x$ac_cv_header_openssl_tls1_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_OPENSSL_TLS1_H 1 _ACEOF HAVE_OPENSSL=1 HAVE_TLS=1 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BIO_new in -lcrypto" >&5 $as_echo_n "checking for BIO_new in -lcrypto... " >&6; } if ${ac_cv_lib_crypto_BIO_new+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lcrypto $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 BIO_new (); int main () { return BIO_new (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_crypto_BIO_new=yes else ac_cv_lib_crypto_BIO_new=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_crypto_BIO_new" >&5 $as_echo "$ac_cv_lib_crypto_BIO_new" >&6; } if test "x$ac_cv_lib_crypto_BIO_new" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBCRYPTO 1 _ACEOF LIBS="-lcrypto $LIBS" else HAVE_OPENSSL=0 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: OpenSSL crypto library was not found" >&5 $as_echo "$as_me: WARNING: OpenSSL crypto library was not found" >&2;} fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for TLSv1_method in -lssl" >&5 $as_echo_n "checking for TLSv1_method in -lssl... " >&6; } if ${ac_cv_lib_ssl_TLSv1_method+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lssl $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 TLSv1_method (); int main () { return TLSv1_method (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ssl_TLSv1_method=yes else ac_cv_lib_ssl_TLSv1_method=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_ssl_TLSv1_method" >&5 $as_echo "$ac_cv_lib_ssl_TLSv1_method" >&6; } if test "x$ac_cv_lib_ssl_TLSv1_method" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBSSL 1 _ACEOF LIBS="-lssl $LIBS" else HAVE_TLS=0 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: OpenSSL protocol library was not found" >&5 $as_echo "$as_me: WARNING: OpenSSL protocol library was not found" >&2;} fi else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: OpenSSL include files were not found" >&5 $as_echo "$as_me: WARNING: OpenSSL include files were not found" >&2;} fi done fi if test x$HAVE_OPENSSL = x1; then $as_echo "#define HAVE_OPENSSL 1" >>confdefs.h fi if test x$HAVE_TLS = x1; then $as_echo "#define HAVE_TLS 1" >>confdefs.h fi fi if test x$HAVE_TLS = x1; then HAVE_TLS_TRUE= HAVE_TLS_FALSE='#' else HAVE_TLS_TRUE='#' HAVE_TLS_FALSE= fi # Check whether --with-sigcomp was given. if test "${with_sigcomp+set}" = set; then : withval=$with_sigcomp; else with_sigcomp=no fi if test -n "${with_sigcomp}" && test "${with_sigcomp}" != no ; then if test "${with_sigcomp}" != yes ; then CPPFLAGS="-I${with_sigcomp}/include $CPPFLAGS" LIBS="-L${with_sigcomp}/lib -lsigcomp $LIBS" else LIBS="-lsigcomp $LIBS" fi for ac_header in sigcomp.h do : ac_fn_c_check_header_mongrel "$LINENO" "sigcomp.h" "ac_cv_header_sigcomp_h" "$ac_includes_default" if test "x$ac_cv_header_sigcomp_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SIGCOMP_H 1 _ACEOF else as_fn_error $? "cannot find Sofia SigComp includes" "$LINENO" 5 fi done ac_fn_c_check_func "$LINENO" "sigcomp_library_2_5" "ac_cv_func_sigcomp_library_2_5" if test "x$ac_cv_func_sigcomp_library_2_5" = xyes; then : $as_echo "#define HAVE_SIGCOMP 1" >>confdefs.h $as_echo "#define HAVE_SOFIA_SIGCOMP 1" >>confdefs.h else as_fn_error $? "Sofia SigComp API >= 2.5 was not found" "$LINENO" 5 fi fi # Check for features used by tport. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for IP_RECVERR" >&5 $as_echo_n "checking for IP_RECVERR... " >&6; } if ${ac_cv_sys_ip_recverr+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { int one = 1; int s = 0; setsockopt(s, SOL_IP, IP_RECVERR, &one, sizeof(one)); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_ip_recverr=yes else ac_cv_sys_ip_recverr=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_ip_recverr" >&5 $as_echo "$ac_cv_sys_ip_recverr" >&6; } if test "$ac_cv_sys_ip_recverr" = yes ; then $as_echo "#define HAVE_IP_RECVERR 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for IPV6_RECVERR" >&5 $as_echo_n "checking for IPV6_RECVERR... " >&6; } if ${ac_cv_sys_ipv6_recverr+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { int one = 1; int s = 0; setsockopt(s, SOL_IPV6, IPV6_RECVERR, &one, sizeof(one)); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_ipv6_recverr=yes else ac_cv_sys_ipv6_recverr=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_ipv6_recverr" >&5 $as_echo "$ac_cv_sys_ipv6_recverr" >&6; } if test "$ac_cv_sys_ipv6_recverr" = yes ; then $as_echo "#define HAVE_IPV6_RECVERR 1" >>confdefs.h fi for ac_header in netinet/tcp.h netinet/sctp.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" " #include #include " 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 # Check whether --enable-sctp was given. if test "${enable_sctp+set}" = set; then : enableval=$enable_sctp; else enable_sigcomp=no fi if test x$enable_sctp = xyes; then $as_echo "#define HAVE_SCTP 1" >>confdefs.h fi succeeded=no if test -z "$PKG_CONFIG"; then # 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_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 test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no" ;; 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 "$PKG_CONFIG" = "no" ; then echo "*** The pkg-config script could not be found. Make sure it is" echo "*** in your path, or set the PKG_CONFIG environment variable" echo "*** to the full path to pkg-config." echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config." else PKG_CONFIG_MIN_VERSION=0.9.0 if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for check >= 0.9.4" >&5 $as_echo_n "checking for check >= 0.9.4... " >&6; } if $PKG_CONFIG --exists "check >= 0.9.4" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } succeeded=yes { $as_echo "$as_me:${as_lineno-$LINENO}: checking CHECK_CFLAGS" >&5 $as_echo_n "checking CHECK_CFLAGS... " >&6; } CHECK_CFLAGS=`$PKG_CONFIG --cflags "check >= 0.9.4"` { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CHECK_CFLAGS" >&5 $as_echo "$CHECK_CFLAGS" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking CHECK_LIBS" >&5 $as_echo_n "checking CHECK_LIBS... " >&6; } CHECK_LIBS=`$PKG_CONFIG --libs "check >= 0.9.4"` { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CHECK_LIBS" >&5 $as_echo "$CHECK_LIBS" >&6; } else CHECK_CFLAGS="" CHECK_LIBS="" ## If we have a custom action on failure, don't print errors, but ## do set a variable so people can do so. CHECK_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "check >= 0.9.4"` fi else echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer." echo "*** See http://www.freedesktop.org/software/pkgconfig" fi fi if test $succeeded = yes; then have_check="yes" else have_check="no" fi if test x"$have_check" = "xyes"; then HAVE_CHECK_TRUE= HAVE_CHECK_FALSE='#' else HAVE_CHECK_TRUE='#' HAVE_CHECK_FALSE= fi if test x"$have_check" = "xyes"; then $as_echo "#define HAVE_CHECK 1" >>confdefs.h CFLAGS_save=$CFLAGS CFLAGS="$CFLAGS $CHECK_CFLAGS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include void tcase_add_ss1_test(TCase *tc, TFun tf, char const *name) { /* prototype with allowed_exit_value */ _tcase_add_test(tc, tf, name, 0, 0, 0, 1); } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : $as_echo "#define HAVE_NEW_TCASE_ADD_TEST 1" >>confdefs.h fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$CFLAGS_save fi for ac_header in fnmatch.h do : ac_fn_c_check_header_mongrel "$LINENO" "fnmatch.h" "ac_cv_header_fnmatch_h" "$ac_includes_default" if test "x$ac_cv_header_fnmatch_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_FNMATCH_H 1 _ACEOF fi done { $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 : $as_echo "#define HAVE_LIBDL 1" >>confdefs.h fi ### internal modules ### ---------------- $as_echo "#define HAVE_SOFIA_SIP 1" >>confdefs.h $as_echo "#define HAVE_SOFIA_SRESOLV 1" >>confdefs.h $as_echo "#define HAVE_SOFIA_SMIME 0" >>confdefs.h # Check whether --enable-stun was given. if test "${enable_stun+set}" = set; then : enableval=$enable_stun; else enable_stun=yes fi if test x$enable_stun = xno ; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ** STUN support disabled **" >&5 $as_echo "$as_me: WARNING: ** STUN support disabled **" >&2;} elif test x${HAVE_OPENSSL} != x1 ; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ** TLS support for STUN disabled as OpenSSL headers and/or libraries were not found **" >&5 $as_echo "$as_me: WARNING: ** TLS support for STUN disabled as OpenSSL headers and/or libraries were not found **" >&2;} $as_echo "#define HAVE_SOFIA_STUN 1" >>confdefs.h else $as_echo "#define HAVE_SOFIA_STUN 1" >>confdefs.h fi if test "x$enable_stun" = xyes; then HAVE_STUN_TRUE= HAVE_STUN_FALSE='#' else HAVE_STUN_TRUE='#' HAVE_STUN_FALSE= fi # Check whether --enable-nth was given. if test "${enable_nth+set}" = set; then : enableval=$enable_nth; else enable_nth=yes fi if test "x$enable_nth" = xyes; then HAVE_NTH_TRUE= HAVE_NTH_FALSE='#' else HAVE_NTH_TRUE='#' HAVE_NTH_FALSE= fi if test x$enable_nth = xyes ; then $as_echo "#define HAVE_SOFIA_NTH 1" >>confdefs.h $as_echo "#define HAVE_SOFIA_HTTP 1" >>confdefs.h fi # Check whether --enable-ntlm was given. if test "${enable_ntlm+set}" = set; then : enableval=$enable_ntlm; else enable_ntlm=no fi if test x$enable_ntlm = xyes ; then $as_echo "#define HAVE_SOFIA_NTLM 1" >>confdefs.h fi if test "x$enable_ntlm" = xyes; then HAVE_NTLM_TRUE= HAVE_NTLM_FALSE='#' else HAVE_NTLM_TRUE='#' HAVE_NTLM_FALSE= fi $as_echo "#define HAVE_SRTP 0" >>confdefs.h $as_echo "#define HAVE_UPNP 0" >>confdefs.h # Check whether --enable-memleak_log was given. if test "${enable_memleak_log+set}" = set; then : enableval=$enable_memleak_log; else enable_memleak_log=no fi if test x$enable_memleak_log = xyes ; then $as_echo "#define HAVE_MEMLEAK_LOG 1" >>confdefs.h fi ### checks for header files ### ----------------------- { $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 #include #include #include 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 _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 _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 #include #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 ### checks for declarations ### ----------------------- ### checks for types ### ---------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking return type of signal handlers" >&5 $as_echo_n "checking return type of signal handlers... " >&6; } if ${ac_cv_type_signal+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { return *(signal (0, 0)) (0) == 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_type_signal=int else ac_cv_type_signal=void fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_signal" >&5 $as_echo "$ac_cv_type_signal" >&6; } cat >>confdefs.h <<_ACEOF #define RETSIGTYPE $ac_cv_type_signal _ACEOF ac_fn_c_check_type "$LINENO" "long long" "ac_cv_type_long_long" "$ac_includes_default" if test "x$ac_cv_type_long_long" = xyes; then : $as_echo "#define longlong long long" >>confdefs.h : else : fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether IO functions support C99 size specifiers" >&5 $as_echo_n "checking whether IO functions support C99 size specifiers... " >&6; } if ${ac_cv_c_c99_format+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_c99_format=yes if test "$cross_compiling" = yes; then : ac_cv_c_c99_format=yes else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { char buf[64]; if (sprintf(buf, "%lld%hhd%jd%zd%td", (long long int)1, (char)2, (intmax_t)3, (size_t)4, (ptrdiff_t)5) != 5) exit(1); else if (strcmp(buf, "12345")) exit(2); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_c_c99_format=yes else ac_cv_c_c99_format=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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_c99_format" >&5 $as_echo "$ac_cv_c_c99_format" >&6; } if test $ac_cv_c_c99_format = yes; then $as_echo "#define HAVE_C99_FORMAT 1" >>confdefs.h $as_echo "#define LLU \"%llu\"" >>confdefs.h $as_echo "#define LLI \"%lli\"" >>confdefs.h $as_echo "#define LLX \"%llx\"" >>confdefs.h $as_echo "#define MOD_ZD \"%zd\"" >>confdefs.h $as_echo "#define MOD_ZU \"%zu\"" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether IO functions support size specifier for long long" >&5 $as_echo_n "checking whether IO functions support size specifier for long long... " >&6; } if ${ac_cv_c_ll_format+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_ll_format=yes if test "$cross_compiling" = yes; then : ac_cv_c_ll_format=yes else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { char buf[64]; if (sprintf(buf, "%lld", (long long int)1) != 1) exit(1); else if (strcmp(buf, "1")) exit(2); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_c_ll_format=yes else ac_cv_c_ll_format=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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_ll_format" >&5 $as_echo "$ac_cv_c_ll_format" >&6; } if test $ac_cv_c_ll_format = yes; then $as_echo "#define LLU \"%llu\"" >>confdefs.h $as_echo "#define LLI \"%lli\"" >>confdefs.h $as_echo "#define LLX \"%llx\"" >>confdefs.h else as_fn_error $? "\"printf cannot handle 64-bit integers\"" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether IO functions support size specifier for size_t" >&5 $as_echo_n "checking whether IO functions support size specifier for size_t... " >&6; } if ${ac_cv_c_z_format+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_z_format=yes if test "$cross_compiling" = yes; then : ac_cv_c_z_format=yes else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { char buf[64]; if (sprintf(buf, "%zd", (size_t)1) != 1) exit(1); else if (strcmp(buf, "1")) exit(2); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_c_z_format=yes else ac_cv_c_z_format=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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_z_format" >&5 $as_echo "$ac_cv_c_z_format" >&6; } if test $ac_cv_c_z_format = yes; then $as_echo "#define MOD_ZD \"%ld\"" >>confdefs.h $as_echo "#define MOD_ZU \"%lu\"" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \"printf cannot handle size_t" >&5 $as_echo "$as_me: WARNING: \"printf cannot handle size_t" >&2;} $as_echo "#define MOD_ZD \"%ld\"" >>confdefs.h $as_echo "#define MOD_ZU \"%lu\"" >>confdefs.h fi fi ### checks for structures ### --------------------- ### checks for typedefs, structures, and compiler characteristics. ### -------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 $as_echo_n "checking for an ANSI C-conforming const... " >&6; } if ${ac_cv_c_const+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __cplusplus /* Ultrix mips cc rejects this sort of thing. */ typedef int charset[2]; const charset cs = { 0, 0 }; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; { /* SCO 3.2v4 cc rejects this sort of thing. */ char tx; char *t = &tx; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; if (s) return 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; } bx; struct s *b = &bx; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; if (!foo) return 0; } return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_const=yes else ac_cv_c_const=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_const" >&5 $as_echo "$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then $as_echo "#define const /**/" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 $as_echo_n "checking for inline... " >&6; } if ${ac_cv_c_inline+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo () {return 0; } $ac_kw foo_t foo () {return 0; } #endif _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_inline=$ac_kw fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_inline" != no && break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 $as_echo "$ac_cv_c_inline" >&6; } case $ac_cv_c_inline in inline | yes) ;; *) case $ac_cv_c_inline in no) ac_val=;; *) ac_val=$ac_cv_c_inline;; esac cat >>confdefs.h <<_ACEOF #ifndef __cplusplus #define inline $ac_val #endif _ACEOF ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 $as_echo_n "checking for inline... " >&6; } if ${ac_cv_c_inline+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo () {return 0; } $ac_kw foo_t foo () {return 0; } #endif _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_inline=$ac_kw fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_inline" != no && break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 $as_echo "$ac_cv_c_inline" >&6; } case $ac_cv_c_inline in inline | yes) ;; *) case $ac_cv_c_inline in no) ac_val=;; *) ac_val=$ac_cv_c_inline;; esac cat >>confdefs.h <<_ACEOF #ifndef __cplusplus #define inline $ac_val #endif _ACEOF ;; esac case "$ac_cv_c_inline" in *inline* | yes) $as_echo "#define HAVE_INLINE 1" >>confdefs.h ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 $as_echo_n "checking whether byte ordering is bigendian... " >&6; } if ${ac_cv_c_bigendian+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_bigendian=unknown # See if we're dealing with a universal compiler. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __APPLE_CC__ not a universal capable compiler #endif typedef int dummy; _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # Check for potential -arch flags. It is not universal unless # there are at least two -arch flags with different values. ac_arch= ac_prev= for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do if test -n "$ac_prev"; then case $ac_word in i?86 | x86_64 | ppc | ppc64) if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then ac_arch=$ac_word else ac_cv_c_bigendian=universal break fi ;; esac ac_prev= elif test "x$ac_word" = "x-arch"; then ac_prev=arch fi done fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_c_bigendian = unknown; then # See if sys/param.h defines the BYTE_ORDER macro. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ && LITTLE_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no 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 if test $ac_cv_c_bigendian = unknown; then # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to _BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #ifndef _BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no 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 if test $ac_cv_c_bigendian = unknown; then # Compile a test program. if test "$cross_compiling" = yes; then : # Try to guess by grepping values from an object file. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; int use_ascii (int i) { return ascii_mm[i] + ascii_ii[i]; } short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; int use_ebcdic (int i) { return ebcdic_mm[i] + ebcdic_ii[i]; } extern int foo; int main () { return use_ascii (foo) == use_ebcdic (foo); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then ac_cv_c_bigendian=yes fi if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then if test "$ac_cv_c_bigendian" = unknown; then ac_cv_c_bigendian=no else # finding both strings is unlikely to happen, but who knows? ac_cv_c_bigendian=unknown fi fi fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* Are we little or big endian? From Harbison&Steele. */ union { long int l; char c[sizeof (long int)]; } u; u.l = 1; return u.c[sizeof (long int) - 1] == 1; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_c_bigendian=no else ac_cv_c_bigendian=yes 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_c_bigendian" >&5 $as_echo "$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in #( yes) $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h ;; #( no) ;; #( universal) $as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h ;; #( *) as_fn_error $? "unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC recognizes __func__" >&5 $as_echo_n "checking whether $CC recognizes __func__... " >&6; } if ${ac_cv_c_var_func+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { char *s = __func__; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_var_func=yes else ac_cv_c_var_func=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_var_func" >&5 $as_echo "$ac_cv_c_var_func" >&6; } if test $ac_cv_c_var_func = "yes"; then $as_echo "#define HAVE_FUNC 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC recognizes __FUNCTION__" >&5 $as_echo_n "checking whether $CC recognizes __FUNCTION__... " >&6; } if ${ac_cv_c_macro_function+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { char *s = __FUNCTION__; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_macro_function=yes else ac_cv_c_macro_function=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_macro_function" >&5 $as_echo "$ac_cv_c_macro_function" >&6; } if test $ac_cv_c_macro_function = "yes"; then $as_echo "#define HAVE_FUNCTION 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC recognizes field names in struct initialization" >&5 $as_echo_n "checking whether $CC recognizes field names in struct initialization... " >&6; } if ${ac_cv_c_keyword_struct+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { struct { int foo; char *bar; } test = { foo: 1, bar: "bar" }; return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_keyword_struct=yes else ac_cv_c_keyword_struct=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_keyword_struct" >&5 $as_echo "$ac_cv_c_keyword_struct" >&6; } if test $ac_cv_c_keyword_struct = "yes"; then $as_echo "#define HAVE_STRUCT_KEYWORDS 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 $as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } if ${ac_cv_header_time+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { if ((struct tm *) 0) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_time=yes else ac_cv_header_time=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_time" >&5 $as_echo "$ac_cv_header_time" >&6; } if test $ac_cv_header_time = yes; then $as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h fi 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 : else cat >>confdefs.h <<_ACEOF #define size_t unsigned int _ACEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sa_len" >&5 $as_echo_n "checking for sa_len... " >&6; } if ${ac_cv_sa_len+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { struct sockaddr t;t.sa_len = 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sa_len=yes else ac_cv_sa_len=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sa_len" >&5 $as_echo "$ac_cv_sa_len" >&6; } if test "$ac_cv_sa_len" = yes ;then $as_echo "#define HAVE_SA_LEN 1" >>confdefs.h fi ### checks for library functions ### ---------------------------- ### checks for system services ### -------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking /dev/urandom" >&5 $as_echo_n "checking /dev/urandom... " >&6; } if ${ac_cv_dev_urandom+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_dev_urandom=no if test -r /dev/urandom; then ac_cv_dev_urandom=yes; fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_dev_urandom" >&5 $as_echo "$ac_cv_dev_urandom" >&6; } if test $ac_cv_dev_urandom = yes; then $as_echo "#define HAVE_DEV_URANDOM 1" >>confdefs.h $as_echo "#define DEV_URANDOM 1" >>confdefs.h fi ### output ### ------ ac_config_files="$ac_config_files Makefile packages/Makefile packages/sofia-sip-ua.pc packages/sofia-sip-ua-glib.pc libsofia-sip-ua/Makefile libsofia-sip-ua/bnf/Makefile libsofia-sip-ua/bnf/Doxyfile libsofia-sip-ua/docs/Makefile libsofia-sip-ua/docs/Doxyfile libsofia-sip-ua/docs/Doxyfile.version libsofia-sip-ua/docs/sofia-footer.html libsofia-sip-ua/features/Doxyfile libsofia-sip-ua/features/Makefile libsofia-sip-ua/http/Doxyfile libsofia-sip-ua/http/Makefile libsofia-sip-ua/ipt/Doxyfile libsofia-sip-ua/ipt/Makefile libsofia-sip-ua/iptsec/Doxyfile libsofia-sip-ua/iptsec/Makefile libsofia-sip-ua/msg/Doxyfile libsofia-sip-ua/msg/Makefile libsofia-sip-ua/nea/Doxyfile libsofia-sip-ua/nea/Makefile libsofia-sip-ua/nta/Doxyfile libsofia-sip-ua/nta/Makefile libsofia-sip-ua/nth/Doxyfile libsofia-sip-ua/nth/Makefile libsofia-sip-ua/nua/Doxyfile libsofia-sip-ua/nua/Makefile libsofia-sip-ua/sdp/Doxyfile libsofia-sip-ua/sdp/Makefile libsofia-sip-ua/sip/Doxyfile libsofia-sip-ua/sip/Makefile libsofia-sip-ua/soa/Doxyfile libsofia-sip-ua/soa/Makefile libsofia-sip-ua/sresolv/Doxyfile libsofia-sip-ua/sresolv/Makefile libsofia-sip-ua/stun/Doxyfile libsofia-sip-ua/stun/Makefile libsofia-sip-ua/su/Doxyfile libsofia-sip-ua/su/Makefile libsofia-sip-ua/tport/Doxyfile libsofia-sip-ua/tport/Makefile libsofia-sip-ua/url/Doxyfile libsofia-sip-ua/url/Makefile libsofia-sip-ua/features/sofia-sip/sofia_features.h s2check/Makefile libsofia-sip-ua-glib/Makefile libsofia-sip-ua-glib/su-glib/Makefile libsofia-sip-ua-glib/su-glib/Doxyfile utils/Makefile utils/Doxyfile tests/Makefile win32/Makefile win32/config.h open_c/Makefile open_c/config.h" ac_config_commands="$ac_config_commands version" ac_config_files="$ac_config_files packages/sofia-sip-${PACKAGE_VERSION}.spec:packages/sofia-sip.spec.in" 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 "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 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 "${HAVE_MINGW32_TRUE}" && test -z "${HAVE_MINGW32_FALSE}"; then as_fn_error $? "conditional \"HAVE_MINGW32\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_COVERAGE_TRUE}" && test -z "${ENABLE_COVERAGE_FALSE}"; then as_fn_error $? "conditional \"ENABLE_COVERAGE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_LCOV_TRUE}" && test -z "${HAVE_LCOV_FALSE}"; then as_fn_error $? "conditional \"HAVE_LCOV\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_GENPNG_TRUE}" && test -z "${HAVE_GENPNG_FALSE}"; then as_fn_error $? "conditional \"HAVE_GENPNG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${NDEBUG_TRUE}" && test -z "${NDEBUG_FALSE}"; then as_fn_error $? "conditional \"NDEBUG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${EXPENSIVE_CHECKS_TRUE}" && test -z "${EXPENSIVE_CHECKS_FALSE}"; then as_fn_error $? "conditional \"EXPENSIVE_CHECKS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_DOXYGEN_TRUE}" && test -z "${HAVE_DOXYGEN_FALSE}"; then as_fn_error $? "conditional \"HAVE_DOXYGEN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${COREFOUNDATION_TRUE}" && test -z "${COREFOUNDATION_FALSE}"; then as_fn_error $? "conditional \"COREFOUNDATION\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_GLIB_TRUE}" && test -z "${HAVE_GLIB_FALSE}"; then as_fn_error $? "conditional \"HAVE_GLIB\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_TLS_TRUE}" && test -z "${HAVE_TLS_FALSE}"; then as_fn_error $? "conditional \"HAVE_TLS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_CHECK_TRUE}" && test -z "${HAVE_CHECK_FALSE}"; then as_fn_error $? "conditional \"HAVE_CHECK\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_STUN_TRUE}" && test -z "${HAVE_STUN_FALSE}"; then as_fn_error $? "conditional \"HAVE_STUN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_NTH_TRUE}" && test -z "${HAVE_NTH_FALSE}"; then as_fn_error $? "conditional \"HAVE_NTH\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_NTLM_TRUE}" && test -z "${HAVE_NTLM_FALSE}"; then as_fn_error $? "conditional \"HAVE_NTLM\" 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 sofia-sip $as_me 1.12.11devel, 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="\\ sofia-sip config.status 1.12.11devel 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" ac_aux_dir="$ac_aux_dir" # 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"`' enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $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"`' 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"`' OBJDUMP='`$ECHO "$OBJDUMP" | $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"`' DLLTOOL='`$ECHO "$DLLTOOL" | $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_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"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $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"`' sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $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 SHELL \ ECHO \ PATH_SEPARATOR \ SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ file_magic_glob \ want_nocaseglob \ DLLTOOL \ 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_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ nm_file_list_spec \ 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\\"\\\`\\\\\\"" ;; *) 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 \ sys_lib_dlsearch_path_spec; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done ac_aux_dir='$ac_aux_dir' xsi_shell='$xsi_shell' lt_shell_append='$lt_shell_append' # See if we are running on zsh, and set the options which 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' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile' PACKAGE_VERSION=${PACKAGE_VERSION} _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" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "libsofia-sip-ua/su/sofia-sip/su_configure.h") CONFIG_HEADERS="$CONFIG_HEADERS libsofia-sip-ua/su/sofia-sip/su_configure.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "packages/Makefile") CONFIG_FILES="$CONFIG_FILES packages/Makefile" ;; "packages/sofia-sip-ua.pc") CONFIG_FILES="$CONFIG_FILES packages/sofia-sip-ua.pc" ;; "packages/sofia-sip-ua-glib.pc") CONFIG_FILES="$CONFIG_FILES packages/sofia-sip-ua-glib.pc" ;; "libsofia-sip-ua/Makefile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/Makefile" ;; "libsofia-sip-ua/bnf/Makefile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/bnf/Makefile" ;; "libsofia-sip-ua/bnf/Doxyfile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/bnf/Doxyfile" ;; "libsofia-sip-ua/docs/Makefile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/docs/Makefile" ;; "libsofia-sip-ua/docs/Doxyfile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/docs/Doxyfile" ;; "libsofia-sip-ua/docs/Doxyfile.version") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/docs/Doxyfile.version" ;; "libsofia-sip-ua/docs/sofia-footer.html") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/docs/sofia-footer.html" ;; "libsofia-sip-ua/features/Doxyfile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/features/Doxyfile" ;; "libsofia-sip-ua/features/Makefile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/features/Makefile" ;; "libsofia-sip-ua/http/Doxyfile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/http/Doxyfile" ;; "libsofia-sip-ua/http/Makefile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/http/Makefile" ;; "libsofia-sip-ua/ipt/Doxyfile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/ipt/Doxyfile" ;; "libsofia-sip-ua/ipt/Makefile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/ipt/Makefile" ;; "libsofia-sip-ua/iptsec/Doxyfile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/iptsec/Doxyfile" ;; "libsofia-sip-ua/iptsec/Makefile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/iptsec/Makefile" ;; "libsofia-sip-ua/msg/Doxyfile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/msg/Doxyfile" ;; "libsofia-sip-ua/msg/Makefile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/msg/Makefile" ;; "libsofia-sip-ua/nea/Doxyfile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/nea/Doxyfile" ;; "libsofia-sip-ua/nea/Makefile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/nea/Makefile" ;; "libsofia-sip-ua/nta/Doxyfile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/nta/Doxyfile" ;; "libsofia-sip-ua/nta/Makefile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/nta/Makefile" ;; "libsofia-sip-ua/nth/Doxyfile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/nth/Doxyfile" ;; "libsofia-sip-ua/nth/Makefile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/nth/Makefile" ;; "libsofia-sip-ua/nua/Doxyfile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/nua/Doxyfile" ;; "libsofia-sip-ua/nua/Makefile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/nua/Makefile" ;; "libsofia-sip-ua/sdp/Doxyfile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/sdp/Doxyfile" ;; "libsofia-sip-ua/sdp/Makefile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/sdp/Makefile" ;; "libsofia-sip-ua/sip/Doxyfile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/sip/Doxyfile" ;; "libsofia-sip-ua/sip/Makefile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/sip/Makefile" ;; "libsofia-sip-ua/soa/Doxyfile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/soa/Doxyfile" ;; "libsofia-sip-ua/soa/Makefile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/soa/Makefile" ;; "libsofia-sip-ua/sresolv/Doxyfile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/sresolv/Doxyfile" ;; "libsofia-sip-ua/sresolv/Makefile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/sresolv/Makefile" ;; "libsofia-sip-ua/stun/Doxyfile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/stun/Doxyfile" ;; "libsofia-sip-ua/stun/Makefile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/stun/Makefile" ;; "libsofia-sip-ua/su/Doxyfile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/su/Doxyfile" ;; "libsofia-sip-ua/su/Makefile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/su/Makefile" ;; "libsofia-sip-ua/tport/Doxyfile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/tport/Doxyfile" ;; "libsofia-sip-ua/tport/Makefile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/tport/Makefile" ;; "libsofia-sip-ua/url/Doxyfile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/url/Doxyfile" ;; "libsofia-sip-ua/url/Makefile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/url/Makefile" ;; "libsofia-sip-ua/features/sofia-sip/sofia_features.h") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua/features/sofia-sip/sofia_features.h" ;; "s2check/Makefile") CONFIG_FILES="$CONFIG_FILES s2check/Makefile" ;; "libsofia-sip-ua-glib/Makefile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua-glib/Makefile" ;; "libsofia-sip-ua-glib/su-glib/Makefile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua-glib/su-glib/Makefile" ;; "libsofia-sip-ua-glib/su-glib/Doxyfile") CONFIG_FILES="$CONFIG_FILES libsofia-sip-ua-glib/su-glib/Doxyfile" ;; "utils/Makefile") CONFIG_FILES="$CONFIG_FILES utils/Makefile" ;; "utils/Doxyfile") CONFIG_FILES="$CONFIG_FILES utils/Doxyfile" ;; "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;; "win32/Makefile") CONFIG_FILES="$CONFIG_FILES win32/Makefile" ;; "win32/config.h") CONFIG_FILES="$CONFIG_FILES win32/config.h" ;; "open_c/Makefile") CONFIG_FILES="$CONFIG_FILES open_c/Makefile" ;; "open_c/config.h") CONFIG_FILES="$CONFIG_FILES open_c/config.h" ;; "version") CONFIG_COMMANDS="$CONFIG_COMMANDS version" ;; "packages/sofia-sip-${PACKAGE_VERSION}.spec") CONFIG_FILES="$CONFIG_FILES packages/sofia-sip-${PACKAGE_VERSION}.spec:packages/sofia-sip.spec.in" ;; *) 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` 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 ' >$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 = "" } { 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 ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\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. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; "libtool":C) # See if we are running on zsh, and set the options which 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 # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $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. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # 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 GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # The names of the tagged configurations supported by this script. available_tags="" # ### BEGIN LIBTOOL CONFIG # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # 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 # An object symbol dumper. OBJDUMP=$lt_OBJDUMP # 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 # DLL creation program. DLLTOOL=$lt_DLLTOOL # 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 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 # 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 in which our libraries should be installed. lt_sysroot=$lt_sysroot # 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 # Run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # 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 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 "X${COLLECT_NAMES+set}" != Xset; 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) if test x"$xsi_shell" = xyes; then sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ func_dirname ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ } # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_basename ()$/,/^} # func_basename /c\ func_basename ()\ {\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ func_dirname_and_basename ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ func_stripname ()\ {\ \ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ \ # positional parameters, so assign one to ordinary parameter first.\ \ func_stripname_result=${3}\ \ func_stripname_result=${func_stripname_result#"${1}"}\ \ func_stripname_result=${func_stripname_result%"${2}"}\ } # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ func_split_long_opt ()\ {\ \ func_split_long_opt_name=${1%%=*}\ \ func_split_long_opt_arg=${1#*=}\ } # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ func_split_short_opt ()\ {\ \ func_split_short_opt_arg=${1#??}\ \ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ } # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ func_lo2o ()\ {\ \ case ${1} in\ \ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ \ *) func_lo2o_result=${1} ;;\ \ esac\ } # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_xform ()$/,/^} # func_xform /c\ func_xform ()\ {\ func_xform_result=${1%.*}.lo\ } # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_arith ()$/,/^} # func_arith /c\ func_arith ()\ {\ func_arith_result=$(( $* ))\ } # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_len ()$/,/^} # func_len /c\ func_len ()\ {\ func_len_result=${#1}\ } # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$lt_shell_append" = xyes; then sed -e '/^func_append ()$/,/^} # func_append /c\ func_append ()\ {\ eval "${1}+=\\${2}"\ } # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ func_append_quoted ()\ {\ \ func_quote_for_eval "${2}"\ \ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ } # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: # Save a `func_append' function call where possible by direct use of '+=' sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: else # Save a `func_append' function call even when '+=' is not available sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$_lt_function_replace_fail" = x":"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 $as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} fi 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 sofia-sip-1.12.11+20110422.1/configure.ac000066400000000000000000000256441223300710500170670ustar00rootroot00000000000000dnl Copyright (C) 2005-2006 Nokia Corporation dnl Contact: Pekka Pessi dnl Licensed under LGPL. See file COPYING. dnl dnl ref: http://www.gnu.org/software/autoconf/manual/autoconf.info.gz dnl AC_PREREQ(2.57) dnl information on the package dnl --------------------------- dnl update both the version for AC_INIT and the LIBSOFIA_SIP_UA_MAJOR_MINOR AC_INIT([sofia-sip], [1.12.11devel]) AC_CONFIG_SRCDIR([libsofia-sip-ua/sip/sofia-sip/sip.h]) AC_CONFIG_MACRO_DIR([m4]) AC_SUBST(VER_LIBSOFIA_SIP_UA_MAJOR_MINOR, [1.12]) dnl Includedir specific to this sofia version AC_SUBST(include_sofiadir, '${includedir}/sofia-sip-1.12') AC_SUBST(LIBVER_SOFIA_SIP_UA_CUR, [6]) AC_SUBST(LIBVER_SOFIA_SIP_UA_REV, [0]) AC_SUBST(LIBVER_SOFIA_SIP_UA_AGE, [6]) AC_SUBST(LIBVER_SOFIA_SIP_UA_SOVER, [0]) # CUR-AGE AC_SUBST(LIBVER_SOFIA_SIP_UA_GLIB_CUR, [3]) AC_SUBST(LIBVER_SOFIA_SIP_UA_GLIB_REV, [0]) AC_SUBST(LIBVER_SOFIA_SIP_UA_GLIB_AGE, [0]) AC_SUBST(LIBVER_SOFIA_SIP_UA_GLIB_SOVER, [3]) # CUR-AGE ## calls AC_CANONICAL_ macros that are required by AM_INIT_AUTOMAKE SAC_CANONICAL_SYSTEM_CACHE_CHECK AM_INIT_AUTOMAKE AM_MAINTAINER_MODE AC_CONFIG_HEADERS([config.h]) ### checks for programs ### ------------------- AC_LANG([C]) SAC_TOOL_CC AC_GNU_SOURCE AC_PROG_INSTALL AC_PROG_CPP AC_CHECK_PROG(ETAGS, etags, etags, echo) AC_CHECK_TOOL(AR, ar, ar) AC_CHECK_TOOL(LD, ld, ld) AC_PROG_LIBTOOL AM_PROG_CC_C_O SAC_CFLAGS SAC_CHECK_COMPILATION_ENVIRONMENT SAC_COVERAGE SAC_ENABLE_NDEBUG SAC_ENABLE_EXPENSIVE_CHECKS dnl Add parameters for aclocal AC_SUBST(ACLOCAL_AMFLAGS, "-I m4") AC_ARG_WITH(doxygen, [ --with-doxygen[[=CMD]] use doxygen command CMD [[doxygen]]],[ case $with_doxygen in yes ) doxygen=doxygen ;; no ) doxygen=echo ;; esac], doxygen=doxygen) AC_CHECK_PROG([DOXYGEN], [doxygen], [$doxygen], [echo]) AM_CONDITIONAL([HAVE_DOXYGEN], [test $DOXYGEN != echo]) AC_DEFUN([AX_COMPILER_VENDOR], [ AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor, [ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=unknown # note: don't check for gcc first since some other compilers define __GNUC__ for ventest in intel:__ICC,__ECC,__INTEL_COMPILER ibm:__xlc__,__xlC__,__IBMC__,__IBMCPP__ gnu:__GNUC__ sun:__SUNPRO_C,__SUNPRO_CC hp:__HP_cc,__HP_aCC dec:__DECC,__DECCXX,__DECC_VER,__DECCXX_VER borland:__BORLANDC__,__TURBOC__ comeau:__COMO__ cray:_CRAYC kai:__KCC lcc:__LCC__ metrowerks:__MWERKS__ sgi:__sgi,sgi microsoft:_MSC_VER watcom:__WATCOMC__ portland:__PGI; do vencpp="defined("`echo $ventest | cut -d: -f2 | sed 's/,/) || defined(/g'`")" AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[ #if !($vencpp) thisisanerror; #endif ])], [ax_cv_]_AC_LANG_ABBREV[_compiler_vendor=`echo $ventest | cut -d: -f1`; break]) done ]) ]) AX_COMPILER_VENDOR SOFIA_PLAT_CFLAGS= # openbsd seems to not define NULL as a void pointer, I blame standards by committee for this. # This is a dirty hack, but shuts up all the warnings case "$host" in *-openbsd*) SOFIA_PLAT_CFLAGS="-DNULL='((void *)0L)'";; *) ;; esac AC_SUBST(SOFIA_PLAT_CFLAGS, $SOFIA_PLAT_CFLAGS) ### checks for libraries ### -------------------- # Enable 64 bit build AC_ARG_ENABLE(64, [AC_HELP_STRING([--enable-64],[build with 64 bit support])],[enable_64="$enable_64"],[enable_64="no"]) if test "x${ax_cv_c_compiler_vendor}" = "xsun" ; then if test "${enable_64}" = "yes"; then SOFIA_CFLAGS="$SOFIA_CFLAGS -m64" LDFLAGS="-m64 -Wl,-64" export PKG_CONFIG_PATH=/usr/lib/64/pkgconfig fi fi SAC_SOFIA_SU SAC_OPENSSL SAC_TPORT dnl Check is used for testing PKG_CHECK_MODULES(CHECK, check >= 0.9.4, have_check="yes", have_check="no") AM_CONDITIONAL(HAVE_CHECK, test x"$have_check" = "xyes") if test x"$have_check" = "xyes"; then AC_DEFINE([HAVE_CHECK], 1, [Define to 1 if check library is available]) SAC_NEW_TCASE_ADD_TEST fi AC_CHECK_HEADERS([fnmatch.h]) dnl dl is currently used only in testing AC_CHECK_LIB([dl], [dlopen], [ dnl Note: -ldl is not added to LIBS AC_DEFINE([HAVE_LIBDL], 1, [Define to 1 if dl library is available]) ]) ### internal modules ### ---------------- AC_DEFINE([HAVE_SOFIA_SIP], 1, [Define to 1 always]) AC_DEFINE([HAVE_SOFIA_SRESOLV], 1, [Define to 1 if we use DNS library]) AC_DEFINE([HAVE_SOFIA_SMIME], 0, [Define to 1 if we use S/MIME library]) AC_ARG_ENABLE(stun, [ --disable-stun disable stun module (enabled)], , enable_stun=yes) if test x$enable_stun = xno ; then AC_MSG_WARN([** STUN support disabled **]) elif test x${HAVE_OPENSSL} != x1 ; then dnl compile STUN only if OPENSSL is available AC_MSG_WARN([** TLS support for STUN disabled as OpenSSL headers and/or libraries were not found **]) AC_DEFINE([HAVE_SOFIA_STUN], 1, [Define to 1 if we use STUN library]) else AC_DEFINE([HAVE_SOFIA_STUN], 1, [Define to 1 if we use STUN library]) fi AM_CONDITIONAL([HAVE_STUN], [test "x$enable_stun" = xyes]) AC_ARG_ENABLE(nth, [ --disable-nth disable HTTP-related modules nth and http (enabled)], , enable_nth=yes) AM_CONDITIONAL([HAVE_NTH], [test "x$enable_nth" = xyes]) if test x$enable_nth = xyes ; then AC_DEFINE([HAVE_SOFIA_NTH], 1, [Define to 1 if we use NTH library]) AC_DEFINE([HAVE_SOFIA_HTTP], 1, [Define to 1 if we use HTTP parser library]) fi dnl Disable NTLM support by default AC_ARG_ENABLE(ntlm, [ --enable-ntlm enable NTLM support [[disabled]]], , enable_ntlm=no) if test x$enable_ntlm = xyes ; then AC_DEFINE([HAVE_SOFIA_NTLM], 1, [Define to 1 if we use NTLM library]) fi AM_CONDITIONAL([HAVE_NTLM], [test "x$enable_ntlm" = xyes]) AC_DEFINE([HAVE_SRTP], 0, [Define to 1 if we use SRTP]) AC_DEFINE([HAVE_UPNP], 0, [Define to 1 if we use UPnP]) AC_ARG_ENABLE(memleak_log, [ --enable-memleak-log enable logging of possible memory leaks [[disabled]]], , enable_memleak_log=no) if test x$enable_memleak_log = xyes ; then AC_DEFINE([HAVE_MEMLEAK_LOG], 1, [Define to 1 for memory-leak-related logging]) fi ### checks for header files ### ----------------------- AC_HEADER_STDC ### checks for declarations ### ----------------------- ### checks for types ### ---------------- AC_TYPE_SIGNAL AC_TYPE_LONGLONG dnl dnl Define HAVE_C99_FORMAT to 1 if the formatted IO functions (printf/scanf dnl et.al.) support the C99 'size specifiers', namely ll, hh, j, z, t dnl (representing long long int, char, intmax_t, size_t, ptrdiff_t). Some C dnl compilers supported these specifiers prior to C99 as an extension. dnl AC_CACHE_CHECK([whether IO functions support C99 size specifiers], [ac_cv_c_c99_format],[ ac_cv_c_c99_format=yes AC_RUN_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT], [[char buf[64]; if (sprintf(buf, "%lld%hhd%jd%zd%td", (long long int)1, (char)2, (intmax_t)3, (size_t)4, (ptrdiff_t)5) != 5) exit(1); else if (strcmp(buf, "12345")) exit(2);]])], [ac_cv_c_c99_format=yes], [ac_cv_c_c99_format=no], [ac_cv_c_c99_format=yes]) ]) if test $ac_cv_c_c99_format = yes; then AC_DEFINE([HAVE_C99_FORMAT], [1], [Define to 1 if printf supports C99 size specifiers])dnl AC_DEFINE([LLU], ["%llu"], [Format (%llu) for unsigned long long])dnl AC_DEFINE([LLI], ["%lli"], [Format (%lli) for long long])dnl AC_DEFINE([LLX], ["%llx"], [Format (%llx) for long long hex])dnl AC_DEFINE([MOD_ZD], ["%zd"], [Define printf() modifier for ssize_t])dnl AC_DEFINE([MOD_ZU], ["%zu"], [Define printf() modifier for size_t])dnl else AC_CACHE_CHECK([whether IO functions support size specifier for long long], [ac_cv_c_ll_format],[ ac_cv_c_ll_format=yes AC_RUN_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT], [[char buf[64]; if (sprintf(buf, "%lld", (long long int)1) != 1) exit(1); else if (strcmp(buf, "1")) exit(2);]])], [ac_cv_c_ll_format=yes], [ac_cv_c_ll_format=no], [ac_cv_c_ll_format=yes]) ]) if test $ac_cv_c_ll_format = yes; then AC_DEFINE([LLU], ["%llu"], [Format (%llu) for unsigned long long])dnl AC_DEFINE([LLI], ["%lli"], [Format (%lli) for long long])dnl AC_DEFINE([LLX], ["%llx"], [Format (%llx) for long long hex])dnl else AC_MSG_ERROR("printf cannot handle 64-bit integers") fi AC_CACHE_CHECK([whether IO functions support size specifier for size_t], [ac_cv_c_z_format],[ ac_cv_c_z_format=yes AC_RUN_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT], [[char buf[64]; if (sprintf(buf, "%zd", (size_t)1) != 1) exit(1); else if (strcmp(buf, "1")) exit(2);]])], [ac_cv_c_z_format=yes], [ac_cv_c_z_format=no], [ac_cv_c_z_format=yes]) ]) if test $ac_cv_c_z_format = yes; then AC_DEFINE([MOD_ZD], ["%ld"], [Define printf() modifier for ssize_t])dnl AC_DEFINE([MOD_ZU], ["%lu"], [Define printf() modifier for size_t])dnl else dnl Cross fingers AC_MSG_WARN("printf cannot handle size_t, using long instead") AC_DEFINE([MOD_ZD], ["%ld"], [Define printf() modifier for ssize_t])dnl AC_DEFINE([MOD_ZU], ["%lu"], [Define printf() modifier for size_t])dnl fi fi ### checks for structures ### --------------------- ### checks for typedefs, structures, and compiler characteristics. ### -------------------------------------------------------------- AC_C_CONST AC_C_INLINE AC_C_INLINE_DEFINE AC_C_BIGENDIAN AC_C_VAR_FUNC AC_C_MACRO_FUNCTION AC_C_KEYWORD_STRUCT AC_HEADER_TIME AC_TYPE_SIZE_T AC_SYS_SA_LEN ### checks for library functions ### ---------------------------- ### checks for system services ### -------------------------- AC_DEV_URANDOM ### output ### ------ AC_CONFIG_FILES([ Makefile packages/Makefile packages/sofia-sip-ua.pc packages/sofia-sip-ua-glib.pc libsofia-sip-ua/Makefile libsofia-sip-ua/bnf/Makefile libsofia-sip-ua/bnf/Doxyfile libsofia-sip-ua/docs/Makefile libsofia-sip-ua/docs/Doxyfile libsofia-sip-ua/docs/Doxyfile.version libsofia-sip-ua/docs/sofia-footer.html libsofia-sip-ua/features/Doxyfile libsofia-sip-ua/features/Makefile libsofia-sip-ua/http/Doxyfile libsofia-sip-ua/http/Makefile libsofia-sip-ua/ipt/Doxyfile libsofia-sip-ua/ipt/Makefile libsofia-sip-ua/iptsec/Doxyfile libsofia-sip-ua/iptsec/Makefile libsofia-sip-ua/msg/Doxyfile libsofia-sip-ua/msg/Makefile libsofia-sip-ua/nea/Doxyfile libsofia-sip-ua/nea/Makefile libsofia-sip-ua/nta/Doxyfile libsofia-sip-ua/nta/Makefile libsofia-sip-ua/nth/Doxyfile libsofia-sip-ua/nth/Makefile libsofia-sip-ua/nua/Doxyfile libsofia-sip-ua/nua/Makefile libsofia-sip-ua/sdp/Doxyfile libsofia-sip-ua/sdp/Makefile libsofia-sip-ua/sip/Doxyfile libsofia-sip-ua/sip/Makefile libsofia-sip-ua/soa/Doxyfile libsofia-sip-ua/soa/Makefile libsofia-sip-ua/sresolv/Doxyfile libsofia-sip-ua/sresolv/Makefile libsofia-sip-ua/stun/Doxyfile libsofia-sip-ua/stun/Makefile libsofia-sip-ua/su/Doxyfile libsofia-sip-ua/su/Makefile libsofia-sip-ua/tport/Doxyfile libsofia-sip-ua/tport/Makefile libsofia-sip-ua/url/Doxyfile libsofia-sip-ua/url/Makefile libsofia-sip-ua/features/sofia-sip/sofia_features.h s2check/Makefile libsofia-sip-ua-glib/Makefile libsofia-sip-ua-glib/su-glib/Makefile libsofia-sip-ua-glib/su-glib/Doxyfile utils/Makefile utils/Doxyfile tests/Makefile win32/Makefile win32/config.h open_c/Makefile open_c/config.h ]) AC_CONFIG_COMMANDS([version],,[PACKAGE_VERSION=${PACKAGE_VERSION}]) AC_CONFIG_FILES([packages/sofia-sip-${PACKAGE_VERSION}.spec:packages/sofia-sip.spec.in]) AC_OUTPUT sofia-sip-1.12.11+20110422.1/depcomp000077500000000000000000000560161223300710500161530ustar00rootroot00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2013-05-30.07; # UTC # Copyright (C) 1999-2013 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 . # 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 . 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 . 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 '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: sofia-sip-1.12.11+20110422.1/docs/000077500000000000000000000000001223300710500155165ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/docs/build_system.txt000066400000000000000000000062611223300710500207670ustar00rootroot00000000000000============================= Sofia-SIP build system README ============================= :Author: Kai Vehmanen :Author: Pekka Pessi :Version: 20051011-5 :Formatting: reStructuredText, http://docutils.sourceforge.net/rst.html Introduction ============ The Sofia-SIP build system practices are documented in this file. The instructions are aimed at developers. Quick start =========== To build Sofia-SIP:: sh> ``./autogen.sh`` (if building from a fresh Git checkout) sh> ``./configure`` sh> ``make`` Note that autogen.sh expects to have automake 1.9. If using a newer automake, generate the GNU autotool files using the command autoreconf. Autotool notes ============== Macros ------ Sofia-SIP specific macros are prefixed with "``SAC\_``" and are defined in files under the toplevel "m4/" directory. Makefile target notes --------------------- - all optionally compiled source files should be listed separately in ``DIST_SOURCES`` variable (otherwise ``make dist`` will fail) Makefile fragments ------------------ Some common makefile rules are in 'rules' subdirectory. Maintainer mode --------------- Sofia-SIP tree is by default configured with automake maintainer mode disabled. In other words, Makefiles do not contain rules for recreating or updating configure, Makefiles or other autotool-generated files. To update these files, you need to run top-level autogen.sh script. Those developers who need to often modify configure.ac, Makefile.am and macro files, can enable maintainer mode with configure option '--enable-maintainer-mode'. Running tests ============= Sofia-SIP has quite complete suite of test cases. It is prudent to run them while making changes and before committing them to revision control system. However, running certain tests takes quite a long time to execture. Therefore, they are run only if the environment variable EXPENSIVE_CHECKS has been set. EXPENSIVE_CHECKS is also set by the build system if configure option '--enable-expensive-checks' has been used. On selectes architectures, it is possible to run tests under valgrind. Use the make target 'valcheck' for that purpose. Code-tree layout ================ Most of the code resides in the libsofia-sip-ua directory. The main library, libsofia-sip-ua.so, is created by collecting object files (for example bnf/bnf_objs.o) from individual modules. There are some portability issues with the way the shared library is currently built, and we are looking for ways to improve the situation. Making releases =============== See sofia-sip/docs/release_management.txt Developer documentation ======================= Generating reference documentation from source code --------------------------------------------------- The libsofia-sip-ua library has a top-level make target "doxygen" for generating the HTML reference documentation. The pages will be created to libsofia-sip-ua/docs subdirectory. This special target is primarily meant for use by the Sofia-SIP website admins, but can be used by anyone with the proper set of tools: - Doxygen, http://www.stack.nl/~dimitri/doxygen/ - Dot graph tool, http://www.research.att.com/sw/tools/graphviz/ sofia-sip-1.12.11+20110422.1/docs/devel_platform_notes.txt000066400000000000000000000027171223300710500225010ustar00rootroot00000000000000====================================================== Notes on compiling Sofia-SIP in different environments ====================================================== Using GNU Autotools ------------------- If you modify autoconf or automake files (configure.ac or Makefile.am) or if you compile Sofia SIP that you pulled from darcs or CVS repo, you need up-to-date autotools. Autoconf should be at least 2.57 and automake should be at least 1.7. You can avoid running autoreconf explicitly if you use ./configure option --enable-maintainer-mode. Notes to distributors ---------------------- Build options such as "--disable-stun" (HAVE_SOFIA_STUN) and "--disable-nth" (HAVE_SOFIA_NTH) modify the public library API/ABI, by omitting certain interfaces from the resulting library and installed header files. Options such as '--disable-size-compat' modify the library ABI by changing the types used in public library function signatures. Generic POSIX (GNU/Linux, BSD, ...) ----------------------------------- Sofia-SIP should compile out-of-the-box on generic POSIX machines. Use the standard GNU autotool 'configure+make' procedure to build the software. See top-level README file for more information. The configure script accepts various options. See "./configure --help" for the full list. Mac OS X -------- TBD Win32 / Mingw ------------- TBD Win32 / Cygwin -------------- TBD Visual-C on win32 ----------------- See sofia-sip/win32/README.txt LocalWords: automake sofia-sip-1.12.11+20110422.1/docs/release_management.txt000066400000000000000000000102051223300710500220710ustar00rootroot00000000000000=================================== Sofia-SIP release management README =================================== :Author: Kai Vehmanen :Version: 20110311-01 :Formatting: reStructuredText, http://docutils.sourceforge.net/rst.html Introduction ============ This README contains instructions for making new Sofia-SIP releases. Links to other resources ======================== sofia-sip/README.developers The release notes ================= The release notes should contain the following sections: - about Sofia-SIP - copied verbatim from sofia-sip/README - list of changes since last release - maintained in sofia-sip/RELEASE - see diff between cvs/darcs between previous and this version - written in freshmeat.net "Changes:" style - notes on API/ABI interface changes - maintained in sofia-sip/RELEASE - all changes in public interfaces, plus other notes that developers should be aware of - contributors to this release - maintained in sofia-sip/RELEASE - also sofia-sip/AUTHORS should be updated (file should list all persons/companies who have code/scripts/etc copyrighted to them in the sofia-sip tree) See the RELEASE.template file for a full list of release note sections. Making the release tarball ========================== - basics: check system clock of the build host ;) - update the version number in sofia-sip/configure.ac - make sure the library versions are correct, and you've frozen all library interfaces (with correct entries in ChangeLog files), see README.developers for more information on library versioning in general - make sure everything that is supposed to be in the release is in the master darcs tree - run 'make distcheck' to verify everything is ready for release (requires automake-1.7 or newer) - tag repos (git and any slave trees) with release tag 'rel-sofia-sip-x_y_z', where x_y_z is the version number (see README.developers): sh> git tag "rel-sofia-sip-x_y_z" - take a fresh checkout of the release using the tag in separate clone: sh> git clone . ../release_x_y_z sh> cd ../release_x_y_z sh> git co rel-sofia-sip-x_y_z - create the release tarball with "make distcheck" (make sure depcomp et al libtool scripts are correctly created) - calculate md5 and sha1 hashes using md5sum and sha1sum utilities, and copy the values to the release-notes (see below) Creating the release notes and updating the website =================================================== - combine the sofia-sip/RELEASE contents with the template found from sfnet_www/templates/relnotes.txt - store the resulting release notes to sfnet_www/relnotes/relnotes-sofia-sip-x.y.z.txt - add explicit link to the release notes to sfnet_www/download.html (three most recent releases, see guidelines in the html comments) - update sfnet_www/index.html to mention the latest release - commit the change to sf.net website CVS, and run the sfnet_www/put_online.sh script Uploading the release to sourceforge.net ======================================== - use the the 'Admin' -> 'File releases' tool for creating a new release - to upload the file, you can use for example rsync: rsync -avP -e ssh sofia-sip-x.y.z.tar.gz USER@frs.sourceforge.net:uploads/ - attach the release notes (relnotes-sofia-sip-x.y.z.txt) to the file release Announcing releases =================== - send an announcement mail, containing the release notes, to sofia-sip-devel@lists.sourceforge.net - post a news item to freshmeat.net 'sofia-sip' project (current project owner: Kai Vehmanen) After release ============= - replace the RELEASE file with RELEASE.template, and commit it to master source repository (see sofia-sip/README.developers) - change version in configure.ac from "X.Y.Z" to "X.Y.Zdevel" (as it is in many cases unknown what the next version will be) - make a "tree open for development" commit Checking API/ABI compatibility ============================== - Use a unit test binary built against an old library, to verify a new library version (forwards-compatibility). - Use the 'icheck' tool (in Debian) to make comparison between two released versions. sofia-sip-1.12.11+20110422.1/install-sh000077500000000000000000000332551223300710500166020ustar00rootroot00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2011-11-20.07; # 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. nl=' ' IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} if test -z "$doit"; then doit_exec=exec else doit_exec=$doit fi # 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_glob='?' initialize_posix_glob=' test "$posix_glob" != "?" || { if (set -f) 2>/dev/null; then posix_glob= else posix_glob=: fi } ' 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 no_target_directory= 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 *' '* | *' '* | *' '* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done 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 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; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else # Prefer dirname, but fall back on a substitute if dirname fails. dstdir=` (dirname "$dst") 2>/dev/null || expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$dst" : 'X\(//\)[^/]' \| \ X"$dst" : 'X\(//\)$' \| \ X"$dst" : 'X\(/\)' \| . 2>/dev/null || echo X"$dst" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q' ` test -d "$dstdir" dstdir_status=$? fi fi 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. ;; *) tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/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. ls_ld_tmpdir=`ls -ld "$tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/d" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- 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 eval "$initialize_posix_glob" oIFS=$IFS IFS=/ $posix_glob set -f set fnord $dstdir shift $posix_glob 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=$dstdir/_inst.$$_ rmtmp=$dstdir/_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` && eval "$initialize_posix_glob" && $posix_glob set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && $posix_glob 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 '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: sofia-sip-1.12.11+20110422.1/libsofia-sip-ua-glib/000077500000000000000000000000001223300710500204655ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua-glib/.gitignore000066400000000000000000000000671223300710500224600ustar00rootroot00000000000000/su-glib/su_source_test /su-glib/torture_su_glib_timer sofia-sip-1.12.11+20110422.1/libsofia-sip-ua-glib/ChangeLog000066400000000000000000000015501223300710500222400ustar00rootroot000000000000002006-12-05 Kai Vehmanen * libsofia-sip-ua-glib interface v3 frozen, version to 3:0:0 (for 1.12.5 release). * nua-glib submodule has been moved from libsofia-sip-ua-glib, and sofia-sip, to a standalone sofia-nua-glib package. 2006-11-22 Kai Vehmanen * libsofia-sip-ua-glib interface v2 frozen, version to 2:0:2 (for 1.12.4 release). 2006-07-25 Kai Vehmanen * libsofia-sip-ua-glib interface v1 frozen, version to 1:0:1 (for 1.12.2 release). 2006-06-16 Kai Vehmanen * libsofia-sip-ua-glib interface v0 frozen, version to 0:0:0. 2006-04-12 Kai Vehmanen * Modified build system to require glib-2.4 or newer to compile libsofia-sip-ua-glib. 2006-03-09 Kai Vehmanen * libsofia-sip-ua-glib created. sofia-sip-1.12.11+20110422.1/libsofia-sip-ua-glib/Makefile.am000066400000000000000000000026401223300710500225230ustar00rootroot00000000000000# # Makefile.am for sofia-sip/libsofia-sip-ua-glib # # Copyright (C) 2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # AUTOMAKE_OPTIONS = foreign 1.7 SUBDIRS=su-glib GLIB_TARGETS=su-glib/libsu-glib.la lib_LTLIBRARIES = if HAVE_GLIB lib_LTLIBRARIES += libsofia-sip-ua-glib.la endif libsofia_sip_ua_glib_la_SOURCES = libsofia_sip_ua_glib_la_LIBADD = \ $(top_builddir)/libsofia-sip-ua/libsofia-sip-ua.la \ $(GLIB_TARGETS) $(GLIB_LIBS) # set the libtool version info version:revision:age for libsofia-sip-ua-glib # - soname to 'libsofia-sip-ua-glib.so.(CUR-AGE)' libsofia_sip_ua_glib_la_LDFLAGS = \ -version-info $(LIBVER_SOFIA_SIP_UA_GLIB_CUR):$(LIBVER_SOFIA_SIP_UA_GLIB_REV):$(LIBVER_SOFIA_SIP_UA_GLIB_AGE) DOXYGEN = doxygen EXTRA_DIST = docs/Doxyfile.aliases \ docs/Doxyfile.conf \ docs/Doxyfile.version doxygen: built-sources @mkdir -p docs docs/html &&\ for d in $(DIST_SUBDIRS) $(DIST_SUBDIRS); do \ test -r $$d/Doxyfile \ && pushd $$d > /dev/null \ && echo running ${DOXYGEN} in $$d \ && ${DOXYGEN} \ && popd > /dev/null ; \ done ${top_srcdir}/scripts/hide_emails.sh docs/html PHONY = doxygen include $(top_srcdir)/rules/recursive.am if HAVE_LCOV include $(top_srcdir)/rules/lcov.am endif include $(top_srcdir)/rules/silent.am .PHONY = $(PHONY) CLEANFILES = docs/*.doxytags distclean-local: -rm -rf docs/html sofia-sip-1.12.11+20110422.1/libsofia-sip-ua-glib/Makefile.in000066400000000000000000000755311223300710500225450ustar00rootroot00000000000000# Makefile.in generated by automake 1.14 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 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 sofia-sip/libsofia-sip-ua-glib # # Copyright (C) 2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # # Recursive Makefile targets # -------------------------- # # Generate lcov output # # # Copyright (C) 2007 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # # Silent compilation w/ Automake 1.9 or 1.10 # ---------------------------------------------------------- # Automake 1.9.6 is not clever enough to override suffix rules within if # if SOFIA_COMPILE_SILENT VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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@ @HAVE_GLIB_TRUE@am__append_1 = libsofia-sip-ua-glib.la DIST_COMMON = $(top_srcdir)/rules/recursive.am \ $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.am \ $(srcdir)/Makefile.in $(srcdir)/Makefile.am ChangeLog @HAVE_GENPNG_TRUE@@HAVE_LCOV_TRUE@am__append_2 = --frames @HAVE_LCOV_TRUE@am__append_3 = lcov lcov-report lcov-rerun clean-lcov covcheck uncovered subdir = libsofia-sip-ua-glib ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(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)/m4/sac-coverage.m4 \ $(top_srcdir)/m4/sac-general.m4 \ $(top_srcdir)/m4/sac-openssl.m4 \ $(top_srcdir)/m4/sac-pkg-config.m4 $(top_srcdir)/m4/sac-su2.m4 \ $(top_srcdir)/m4/sac-tport.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libsofia-sip-ua/su/sofia-sip/su_configure.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)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libsofia_sip_ua_glib_la_DEPENDENCIES = \ $(top_builddir)/libsofia-sip-ua/libsofia-sip-ua.la \ $(GLIB_TARGETS) $(am__DEPENDENCIES_1) am_libsofia_sip_ua_glib_la_OBJECTS = libsofia_sip_ua_glib_la_OBJECTS = \ $(am_libsofia_sip_ua_glib_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 = libsofia_sip_ua_glib_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsofia_sip_ua_glib_la_LDFLAGS) \ $(LDFLAGS) -o $@ @HAVE_GLIB_TRUE@am_libsofia_sip_ua_glib_la_rpath = -rpath $(libdir) 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) -I$(top_builddir)/libsofia-sip-ua/su/sofia-sip 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) 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 = $(libsofia_sip_ua_glib_la_SOURCES) DIST_SOURCES = $(libsofia_sip_ua_glib_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 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 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)` CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) 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@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CHECK_CFLAGS = @CHECK_CFLAGS@ CHECK_LIBS = @CHECK_LIBS@ COVERAGE_FLAGS = @COVERAGE_FLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CWFLAG = @CWFLAG@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = doxygen DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV = @GCOV@ GENHTML = @GENHTML@ GENPNG = @GENPNG@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GLIB_VERSION = @GLIB_VERSION@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVER_SOFIA_SIP_UA_AGE = @LIBVER_SOFIA_SIP_UA_AGE@ LIBVER_SOFIA_SIP_UA_CUR = @LIBVER_SOFIA_SIP_UA_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_AGE = @LIBVER_SOFIA_SIP_UA_GLIB_AGE@ LIBVER_SOFIA_SIP_UA_GLIB_CUR = @LIBVER_SOFIA_SIP_UA_GLIB_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_REV = @LIBVER_SOFIA_SIP_UA_GLIB_REV@ LIBVER_SOFIA_SIP_UA_GLIB_SOVER = @LIBVER_SOFIA_SIP_UA_GLIB_SOVER@ LIBVER_SOFIA_SIP_UA_REV = @LIBVER_SOFIA_SIP_UA_REV@ LIBVER_SOFIA_SIP_UA_SOVER = @LIBVER_SOFIA_SIP_UA_SOVER@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MINGW_ENVIRONMENT = @MINGW_ENVIRONMENT@ MKDIR_P = @MKDIR_P@ MOSTLYCLEANFILES = @MOSTLYCLEANFILES@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ RANLIB = @RANLIB@ REPLACE_LIBADD = @REPLACE_LIBADD@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ SOFIA_GLIB_CFLAGS = @SOFIA_GLIB_CFLAGS@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ SOFIA_PLAT_CFLAGS = @SOFIA_PLAT_CFLAGS@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ VERSION = @VERSION@ VER_LIBSOFIA_SIP_UA_MAJOR_MINOR = @VER_LIBSOFIA_SIP_UA_MAJOR_MINOR@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ include_sofiadir = @include_sofiadir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ openssl_CFLAGS = @openssl_CFLAGS@ openssl_LIBS = @openssl_LIBS@ 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@ AUTOMAKE_OPTIONS = foreign 1.7 SUBDIRS = su-glib GLIB_TARGETS = su-glib/libsu-glib.la lib_LTLIBRARIES = $(am__append_1) libsofia_sip_ua_glib_la_SOURCES = libsofia_sip_ua_glib_la_LIBADD = \ $(top_builddir)/libsofia-sip-ua/libsofia-sip-ua.la \ $(GLIB_TARGETS) $(GLIB_LIBS) # set the libtool version info version:revision:age for libsofia-sip-ua-glib # - soname to 'libsofia-sip-ua-glib.so.(CUR-AGE)' libsofia_sip_ua_glib_la_LDFLAGS = \ -version-info $(LIBVER_SOFIA_SIP_UA_GLIB_CUR):$(LIBVER_SOFIA_SIP_UA_GLIB_REV):$(LIBVER_SOFIA_SIP_UA_GLIB_AGE) EXTRA_DIST = docs/Doxyfile.aliases \ docs/Doxyfile.conf \ docs/Doxyfile.version PHONY = doxygen $(am__append_3) SOFIA_RECURSIVE = \ valcheck-recursive \ checklib-recursive SOFIA_DIST_RECURSIVE = \ built-sources-recursive \ clean-built-sources-recursive # Scripts @HAVE_LCOV_TRUE@LCOV_UNCOVERED = ${top_srcdir}/scripts/uncovered @HAVE_LCOV_TRUE@LCOV_REPORT = ${top_srcdir}/scripts/lcov-report # Report directory @HAVE_LCOV_TRUE@lcovdir = ${top_builddir}/lcov # Options @HAVE_LCOV_TRUE@GENHTML_OPTIONS = --show-details --legend \ @HAVE_LCOV_TRUE@ $(am__append_2) # Fancy shell command that expands to directory relative to top_builddir @HAVE_LCOV_TRUE@expand_subdir = `pwd|sed "s'\`cd ${top_builddir};pwd\`''"` SOFIA_SILENT = @ LIBTOOL_FLAGS = --silent # From Automake 1.9.6 - LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(LIBTOOL_FLAGS) \ $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) LINK = ${SOFIA_SILENT}test "${SOFIA_SILENT}" != @ || echo ' LINK $@'; \ $(LIBTOOL) --tag=CC --mode=link $(LIBTOOL_FLAGS) \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ .PHONY = $(PHONY) CLEANFILES = docs/*.doxytags all: all-recursive .SUFFIXES: .SUFFIXES: .c .lo .o $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/recursive.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.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) --foreign libsofia-sip-ua-glib/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign libsofia-sip-ua-glib/Makefile .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/rules/recursive.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.am: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): 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}; \ } libsofia-sip-ua-glib.la: $(libsofia_sip_ua_glib_la_OBJECTS) $(libsofia_sip_ua_glib_la_DEPENDENCIES) $(EXTRA_libsofia_sip_ua_glib_la_DEPENDENCIES) $(AM_V_CCLD)$(libsofia_sip_ua_glib_la_LINK) $(am_libsofia_sip_ua_glib_la_rpath) $(libsofia_sip_ua_glib_la_OBJECTS) $(libsofia_sip_ua_glib_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 # 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: $(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) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(libdir)"; 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: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) 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." @HAVE_LCOV_FALSE@clean-local: clean: clean-recursive clean-am: clean-generic clean-libLTLIBRARIES clean-libtool clean-local \ mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-local 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-libLTLIBRARIES 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-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-libLTLIBRARIES .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-libLTLIBRARIES \ clean-libtool clean-local cscopelist-am ctags ctags-am \ distclean distclean-compile distclean-generic \ distclean-libtool distclean-local 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-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-libLTLIBRARIES doxygen: built-sources @mkdir -p docs docs/html &&\ for d in $(DIST_SUBDIRS) $(DIST_SUBDIRS); do \ test -r $$d/Doxyfile \ && pushd $$d > /dev/null \ && echo running ${DOXYGEN} in $$d \ && ${DOXYGEN} \ && popd > /dev/null ; \ done ${top_srcdir}/scripts/hide_emails.sh docs/html all-recursive: built-sources-recursive built-sources: built-sources-recursive clean-built-sources: clean-built-sources-recursive valcheck: valcheck-recursive $(SOFIA_RECURSIVE): @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$target) \ || eval $$failcom; \ done; \ test -z "$$fail" $(SOFIA_DIST_RECURSIVE): @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ target=`echo $@ | sed s/-recursive//`; \ list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$target) \ || eval $$failcom; \ done; \ test -z "$$fail" # # Generate pretty coverage report (unless it has been already done) # @HAVE_LCOV_TRUE@lcov: @HAVE_LCOV_TRUE@ @-test -r ${lcovdir}${expand_subdir}/lcov.info \ @HAVE_LCOV_TRUE@ || make lcov-report # Generate pretty coverage report based on current coverage data @HAVE_LCOV_TRUE@lcov-report: @HAVE_LCOV_TRUE@ sub=${expand_subdir} odir=${lcovdir}$$sub ; \ @HAVE_LCOV_TRUE@ rm -rf $$odir ; mkdir -p $$odir && \ @HAVE_LCOV_TRUE@ ${LCOV_REPORT} ${GENHTML_OPTIONS} \ @HAVE_LCOV_TRUE@ --title "${PACKAGE_NAME}-${PACKAGE_VERSION}$$sub" \ @HAVE_LCOV_TRUE@ --srcdir=${srcdir} -o $$odir # Rerun checks before generating report @HAVE_LCOV_TRUE@lcov-rerun: clean-lcov @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) lcov-report # Show all uncovered lines as errors @HAVE_LCOV_TRUE@uncovered: @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} # Run check in current dir and show all uncovered lines as errors @HAVE_LCOV_TRUE@covcheck: @HAVE_LCOV_TRUE@ -find . -name "*.gcda" | xargs rm -rf @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} @HAVE_LCOV_TRUE@clean-local:: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true @HAVE_LCOV_TRUE@clean-lcov: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true # Rules from depend2.am (GENERIC = TRUE, SUBDIROBJ = FALSE, %FASTDEP% = am_fastdepCC) silenced. .c.o: @test "${SOFIA_SILENT}" != @ || echo ' COMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(COMPILE) -c -o $@ $< .c.lo: @test "${SOFIA_SILENT}" != @ || echo ' LTCOMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(LTCOMPILE) -c -o $@ $< # endif distclean-local: -rm -rf docs/html # 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: sofia-sip-1.12.11+20110422.1/libsofia-sip-ua-glib/docs/000077500000000000000000000000001223300710500214155ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua-glib/docs/.gitignore000066400000000000000000000000221223300710500233770ustar00rootroot00000000000000/html/ *.doxytags sofia-sip-1.12.11+20110422.1/libsofia-sip-ua-glib/docs/Doxyfile.aliases000066400000000000000000000000741223300710500245440ustar00rootroot00000000000000@INCLUDE = ../../libsofia-sip-ua/docs/Doxyfile.aliases sofia-sip-1.12.11+20110422.1/libsofia-sip-ua-glib/docs/Doxyfile.conf000066400000000000000000000020101223300710500240400ustar00rootroot00000000000000@INCLUDE = ../../libsofia-sip-ua/docs/Doxyfile.conf @INCLUDE = ../../libsofia-sip-ua/docs/Doxyfile.rfc HTML_FOOTER = ../../libsofia-sip-ua/docs/sofia-footer.html TAGFILES += ../../libsofia-sip-ua/docs/docs.doxytags=../docs TAGFILES += ../../libsofia-sip-ua/docs/su.doxytags=../su TAGFILES += ../../libsofia-sip-ua/docs/ipt.doxytags=../ipt TAGFILES += ../../libsofia-sip-ua/docs/bnf.doxytags=../bnf TAGFILES += ../../libsofia-sip-ua/docs/url.doxytags=../url TAGFILES += ../../libsofia-sip-ua/docs/msg.doxytags=../msg TAGFILES += ../../libsofia-sip-ua/docs/sip.doxytags=../sip TAGFILES += ../../libsofia-sip-ua/docs/sresolv.doxytags=../sresolv TAGFILES += ../../libsofia-sip-ua/docs/tport.doxytags=../tport TAGFILES += ../../libsofia-sip-ua/docs/nta.doxytags=../nta TAGFILES += ../../libsofia-sip-ua/docs/sdp.doxytags=../sdp TAGFILES += ../../libsofia-sip-ua/docs/nua.doxytags=../nua sofia-sip-1.12.11+20110422.1/libsofia-sip-ua-glib/docs/Doxyfile.version000066400000000000000000000000751223300710500246110ustar00rootroot00000000000000@INCLUDE = ../../libsofia-sip-ua/docs/Doxyfile.version sofia-sip-1.12.11+20110422.1/libsofia-sip-ua-glib/su-glib/000077500000000000000000000000001223300710500220275ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua-glib/su-glib/Doxyfile.in000066400000000000000000000004651223300710500241470ustar00rootroot00000000000000PROJECT_NAME = "sofia-sip/su-glib" OUTPUT_DIRECTORY = ../docs/html/su-glib INPUT = @srcdir@/su_glib.docs @srcdir@ . @srcdir@/sofia-sip @INCLUDE_PATH = @srcdir@ . @INCLUDE = ../docs/Doxyfile.conf GENERATE_TAGFILE = ../docs/su_glib.doxytags ALIASES += sofia-sip-1.12.11+20110422.1/libsofia-sip-ua-glib/su-glib/Makefile.am000066400000000000000000000030451223300710500240650ustar00rootroot00000000000000# # Makefile.am for su-glib module # # Copyright (C) 2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # # ---------------------------------------------------------------------- # Headers S_BASE = $(top_srcdir)/libsofia-sip-ua B_BASE = $(top_builddir)/libsofia-sip-ua INCLUDES = -I$(S_BASE)/su -I$(B_BASE)/su $(GLIB_CFLAGS) \ $(SOFIA_GLIB_CFLAGS) # ---------------------------------------------------------------------- # Build targets noinst_LTLIBRARIES = libsu-glib.la check_PROGRAMS = su_source_test torture_su_glib_timer # ---------------------------------------------------------------------- # Tests TESTS = su_source_test torture_su_glib_timer # ---------------------------------------------------------------------- # Rules for building the targets nobase_include_sofia_HEADERS = if HAVE_GLIB nobase_include_sofia_HEADERS += \ sofia-sip/su_source.h \ sofia-sip/su_glib.h endif libsu_glib_la_SOURCES = su_source.c libsu_glib_la_DEPENDENCIES = \ ../../libsofia-sip-ua/libsofia-sip-ua.la LDADD = libsu-glib.la \ ../../libsofia-sip-ua/libsofia-sip-ua.la \ $(GLIB_LIBS) # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST = Doxyfile su_glib.docs # ---------------------------------------------------------------------- # Automake options AUTOMAKE_OPTIONS = foreign # ---------------------------------------------------------------------- # Sofia specific rules include $(top_srcdir)/rules/sofia.am sofia-sip-1.12.11+20110422.1/libsofia-sip-ua-glib/su-glib/Makefile.in000066400000000000000000001346201223300710500241020ustar00rootroot00000000000000# Makefile.in generated by automake 1.14 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 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 su-glib module # # Copyright (C) 2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # # ---------------------------------------------------------------------- # Headers # common Makefile targets for libsofia-sip-ua(-glib) modules # ---------------------------------------------------------- # # run tests with valgrind # # Copyright (C) 2007 Nokia Corporation. # 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 file contains free software from Makefile.in by the Free Software # Foundation: # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 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. # # Generate lcov output # # # Copyright (C) 2007 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # # Silent compilation w/ Automake 1.9 or 1.10 # ---------------------------------------------------------- # Automake 1.9.6 is not clever enough to override suffix rules within if # if SOFIA_COMPILE_SILENT VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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@ check_PROGRAMS = su_source_test$(EXEEXT) \ torture_su_glib_timer$(EXEEXT) TESTS = su_source_test$(EXEEXT) torture_su_glib_timer$(EXEEXT) @HAVE_GLIB_TRUE@am__append_1 = \ @HAVE_GLIB_TRUE@ sofia-sip/su_source.h \ @HAVE_GLIB_TRUE@ sofia-sip/su_glib.h DIST_COMMON = $(top_srcdir)/rules/sofia.am \ $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am \ $(top_srcdir)/rules/silent.am $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(srcdir)/Doxyfile.in \ $(top_srcdir)/depcomp $(am__nobase_include_sofia_HEADERS_DIST) \ $(top_srcdir)/test-driver # Use with --enable-ndebug @NDEBUG_TRUE@am__append_2 = -DNDEBUG @HAVE_GENPNG_TRUE@@HAVE_LCOV_TRUE@am__append_3 = --frames @HAVE_LCOV_TRUE@am__append_4 = lcov lcov-report lcov-rerun clean-lcov covcheck uncovered subdir = libsofia-sip-ua-glib/su-glib ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(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)/m4/sac-coverage.m4 \ $(top_srcdir)/m4/sac-general.m4 \ $(top_srcdir)/m4/sac-openssl.m4 \ $(top_srcdir)/m4/sac-pkg-config.m4 $(top_srcdir)/m4/sac-su2.m4 \ $(top_srcdir)/m4/sac-tport.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libsofia-sip-ua/su/sofia-sip/su_configure.h CONFIG_CLEAN_FILES = Doxyfile CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libsu_glib_la_LIBADD = am_libsu_glib_la_OBJECTS = su_source.lo libsu_glib_la_OBJECTS = $(am_libsu_glib_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 = su_source_test_SOURCES = su_source_test.c su_source_test_OBJECTS = su_source_test.$(OBJEXT) su_source_test_LDADD = $(LDADD) am__DEPENDENCIES_1 = su_source_test_DEPENDENCIES = libsu-glib.la \ ../../libsofia-sip-ua/libsofia-sip-ua.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) torture_su_glib_timer_SOURCES = torture_su_glib_timer.c torture_su_glib_timer_OBJECTS = torture_su_glib_timer.$(OBJEXT) torture_su_glib_timer_LDADD = $(LDADD) torture_su_glib_timer_DEPENDENCIES = libsu-glib.la \ ../../libsofia-sip-ua/libsofia-sip-ua.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) -I$(top_builddir)/libsofia-sip-ua/su/sofia-sip depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f 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) 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 = $(libsu_glib_la_SOURCES) su_source_test.c \ torture_su_glib_timer.c DIST_SOURCES = $(libsu_glib_la_SOURCES) su_source_test.c \ torture_su_glib_timer.c am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__nobase_include_sofia_HEADERS_DIST = sofia-sip/su_source.h \ sofia-sip/su_glib.h 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)$(include_sofiadir)" HEADERS = $(nobase_include_sofia_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)` 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=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ 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_DRIVER = $(SHELL) $(top_srcdir)/test-driver 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) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CHECK_CFLAGS = @CHECK_CFLAGS@ CHECK_LIBS = @CHECK_LIBS@ COVERAGE_FLAGS = @COVERAGE_FLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CWFLAG = @CWFLAG@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV = @GCOV@ GENHTML = @GENHTML@ GENPNG = @GENPNG@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GLIB_VERSION = @GLIB_VERSION@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVER_SOFIA_SIP_UA_AGE = @LIBVER_SOFIA_SIP_UA_AGE@ LIBVER_SOFIA_SIP_UA_CUR = @LIBVER_SOFIA_SIP_UA_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_AGE = @LIBVER_SOFIA_SIP_UA_GLIB_AGE@ LIBVER_SOFIA_SIP_UA_GLIB_CUR = @LIBVER_SOFIA_SIP_UA_GLIB_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_REV = @LIBVER_SOFIA_SIP_UA_GLIB_REV@ LIBVER_SOFIA_SIP_UA_GLIB_SOVER = @LIBVER_SOFIA_SIP_UA_GLIB_SOVER@ LIBVER_SOFIA_SIP_UA_REV = @LIBVER_SOFIA_SIP_UA_REV@ LIBVER_SOFIA_SIP_UA_SOVER = @LIBVER_SOFIA_SIP_UA_SOVER@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MINGW_ENVIRONMENT = @MINGW_ENVIRONMENT@ MKDIR_P = @MKDIR_P@ MOSTLYCLEANFILES = @MOSTLYCLEANFILES@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ RANLIB = @RANLIB@ REPLACE_LIBADD = @REPLACE_LIBADD@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ SOFIA_GLIB_CFLAGS = @SOFIA_GLIB_CFLAGS@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ SOFIA_PLAT_CFLAGS = @SOFIA_PLAT_CFLAGS@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ VERSION = @VERSION@ VER_LIBSOFIA_SIP_UA_MAJOR_MINOR = @VER_LIBSOFIA_SIP_UA_MAJOR_MINOR@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ include_sofiadir = @include_sofiadir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ openssl_CFLAGS = @openssl_CFLAGS@ openssl_LIBS = @openssl_LIBS@ 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@ S_BASE = $(top_srcdir)/libsofia-sip-ua B_BASE = $(top_builddir)/libsofia-sip-ua INCLUDES = -I$(S_BASE)/su -I$(B_BASE)/su $(GLIB_CFLAGS) \ $(SOFIA_GLIB_CFLAGS) # ---------------------------------------------------------------------- # Build targets noinst_LTLIBRARIES = libsu-glib.la # ---------------------------------------------------------------------- # Rules for building the targets nobase_include_sofia_HEADERS = $(am__append_1) libsu_glib_la_SOURCES = su_source.c libsu_glib_la_DEPENDENCIES = \ ../../libsofia-sip-ua/libsofia-sip-ua.la LDADD = libsu-glib.la ../../libsofia-sip-ua/libsofia-sip-ua.la \ $(GLIB_LIBS) $(openssl_LIBS) # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST = Doxyfile su_glib.docs # ---------------------------------------------------------------------- # Automake options AUTOMAKE_OPTIONS = foreign sofiasrcdir = ${top_srcdir}/libsofia-sip-ua sofiabuilddir = ${top_builddir}/libsofia-sip-ua AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(SOFIA_CFLAGS) \ $(openssl_CFLAGS) $(SOFIA_PLAT_CFLAGS) $(am__append_2) SOFIA_COVERAGE = $(COVERAGE_FLAGS) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files TAG_AWK = ${sofiasrcdir}/su/tag_dll.awk SUFFIXES = _tag_ref.c _tag.c INTERNAL_INCLUDES = \ -I${sofiasrcdir}/features -I${sofiabuilddir}/features \ -I${sofiasrcdir}/ipt -I${sofiabuilddir}/ipt \ -I${sofiasrcdir}/iptsec -I${sofiabuilddir}/iptsec \ -I${sofiasrcdir}/bnf -I${sofiabuilddir}/bnf \ -I${sofiasrcdir}/http -I${sofiabuilddir}/http \ -I${sofiasrcdir}/msg -I${sofiabuilddir}/msg \ -I${sofiasrcdir}/nth -I${sofiabuilddir}/nth \ -I${sofiasrcdir}/nta -I${sofiabuilddir}/nta \ -I${sofiasrcdir}/nea -I${sofiabuilddir}/nea \ -I${sofiasrcdir}/nua -I${sofiabuilddir}/nua \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sdp -I${sofiabuilddir}/sdp \ -I${sofiasrcdir}/sip -I${sofiabuilddir}/sip \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sresolv -I${sofiabuilddir}/sresolv \ -I${sofiasrcdir}/tport -I${sofiabuilddir}/tport \ -I${sofiasrcdir}/stun -I${sofiabuilddir}/stun \ -I${sofiasrcdir}/url -I${sofiabuilddir}/url \ -I${sofiasrcdir}/su -I${sofiabuilddir}/su PHONY = built-sources clean-built-sources $(am__append_4) VALGRIND = valgrind VALGRINDFLAGS = --tool=memcheck # Scripts @HAVE_LCOV_TRUE@LCOV_UNCOVERED = ${top_srcdir}/scripts/uncovered @HAVE_LCOV_TRUE@LCOV_REPORT = ${top_srcdir}/scripts/lcov-report # Report directory @HAVE_LCOV_TRUE@lcovdir = ${top_builddir}/lcov # Options @HAVE_LCOV_TRUE@GENHTML_OPTIONS = --show-details --legend \ @HAVE_LCOV_TRUE@ $(am__append_3) # Fancy shell command that expands to directory relative to top_builddir @HAVE_LCOV_TRUE@expand_subdir = `pwd|sed "s'\`cd ${top_builddir};pwd\`''"` SOFIA_SILENT = @ LIBTOOL_FLAGS = --silent # From Automake 1.9.6 - LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(LIBTOOL_FLAGS) \ $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) LINK = ${SOFIA_SILENT}test "${SOFIA_SILENT}" != @ || echo ' LINK $@'; \ $(LIBTOOL) --tag=CC --mode=link $(LIBTOOL_FLAGS) \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ all: all-am .SUFFIXES: .SUFFIXES: _tag_ref.c _tag.c .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.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) --foreign libsofia-sip-ua-glib/su-glib/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign libsofia-sip-ua-glib/su-glib/Makefile .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.am: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): Doxyfile: $(top_builddir)/config.status $(srcdir)/Doxyfile.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ 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}; \ } libsu-glib.la: $(libsu_glib_la_OBJECTS) $(libsu_glib_la_DEPENDENCIES) $(EXTRA_libsu_glib_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libsu_glib_la_OBJECTS) $(libsu_glib_la_LIBADD) $(LIBS) 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 su_source_test$(EXEEXT): $(su_source_test_OBJECTS) $(su_source_test_DEPENDENCIES) $(EXTRA_su_source_test_DEPENDENCIES) @rm -f su_source_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(su_source_test_OBJECTS) $(su_source_test_LDADD) $(LIBS) torture_su_glib_timer$(EXEEXT): $(torture_su_glib_timer_OBJECTS) $(torture_su_glib_timer_DEPENDENCIES) $(EXTRA_torture_su_glib_timer_DEPENDENCIES) @rm -f torture_su_glib_timer$(EXEEXT) $(AM_V_CCLD)$(LINK) $(torture_su_glib_timer_OBJECTS) $(torture_su_glib_timer_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_source.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_source_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/torture_su_glib_timer.Po@am__quote@ .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.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) '$<'` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-nobase_include_sofiaHEADERS: $(nobase_include_sofia_HEADERS) @$(NORMAL_INSTALL) @list='$(nobase_include_sofia_HEADERS)'; test -n "$(include_sofiadir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(include_sofiadir)'"; \ $(MKDIR_P) "$(DESTDIR)$(include_sofiadir)" || exit 1; \ fi; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo " $(MKDIR_P) '$(DESTDIR)$(include_sofiadir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(include_sofiadir)/$$dir"; }; \ echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(include_sofiadir)/$$dir'"; \ $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(include_sofiadir)/$$dir" || exit $$?; }; \ done uninstall-nobase_include_sofiaHEADERS: @$(NORMAL_UNINSTALL) @list='$(nobase_include_sofia_HEADERS)'; test -n "$(include_sofiadir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ dir='$(DESTDIR)$(include_sofiadir)'; $(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; \ else \ 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 $(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 $$? su_source_test.log: su_source_test$(EXEEXT) @p='su_source_test$(EXEEXT)'; \ b='su_source_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) torture_su_glib_timer.log: torture_su_glib_timer$(EXEEXT) @p='torture_su_glib_timer$(EXEEXT)'; \ b='torture_su_glib_timer'; \ $(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: $(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) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(include_sofiadir)"; 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 "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) -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: 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) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." @HAVE_LCOV_FALSE@clean-local: clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libtool clean-local \ clean-noinstLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -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-nobase_include_sofiaHEADERS 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 -rf ./$(DEPDIR) -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-nobase_include_sofiaHEADERS .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libtool clean-local \ 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-nobase_include_sofiaHEADERS 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 \ uninstall-nobase_include_sofiaHEADERS built-sources: $(BUILT_SOURCES) clean-built-sources: -rm -rf $(BUILT_SOURCES) $(BUILT_SOURCES:%=$(srcdir)/%) *_tag_ref.c: $(TAG_AWK) _tag.c_tag_ref.c: $(AWK) -f $(TAG_AWK) NODLL=1 $(TAG_DLL_FLAGS) REF=$@ $< ../bnf/libbnf.la ../http/libhttp.la ../ipt/libipt.la ../iptsec/libiptsec.la \ ../msg/libmsg.la ../nea/libnea.la ../nta/libnta.la ../nth/libnth.la \ ../nua/libnua.la ../sdp/libsdp.la ../sip/libsip.la ../soa/libsoa.la \ ../sresolv/libsresolv.la ../stun/libstun.la ../su/libsu.la \ ../tport/libtport.la ../url/liburl.la: cd $(@D) && $(MAKE) $(@F) checklib: $(noinst_LTLIBRARIES) $(check_LTLIBRARIES) valcheck: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) valcheck-am valcheck-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS # Run tests with valgrind in valcheck-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ list='$(TESTS)'; \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ if case $$tst in \ run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ $${dir}$$tst ;; \ esac ; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ echo "XPASS: $$tst"; \ ;; \ *) \ echo "PASS: $$tst"; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xfail=`expr $$xfail + 1`; \ echo "XFAIL: $$tst"; \ ;; \ *) \ failed=`expr $$failed + 1`; \ echo "FAIL: $$tst"; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ echo "SKIP: $$tst"; \ fi; \ done; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="All $$all tests passed"; \ else \ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all tests failed"; \ else \ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ skipped="($$skip tests were not run)"; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ report=""; \ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ report="Please report to $(PACKAGE_BUGREPORT)"; \ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ echo "$$dashes"; \ echo "$$banner"; \ test -z "$$skipped" || echo "$$skipped"; \ test -z "$$report" || echo "$$report"; \ echo "$$dashes"; \ test "$$failed" -eq 0; \ else :; fi # # Generate pretty coverage report (unless it has been already done) # @HAVE_LCOV_TRUE@lcov: @HAVE_LCOV_TRUE@ @-test -r ${lcovdir}${expand_subdir}/lcov.info \ @HAVE_LCOV_TRUE@ || make lcov-report # Generate pretty coverage report based on current coverage data @HAVE_LCOV_TRUE@lcov-report: @HAVE_LCOV_TRUE@ sub=${expand_subdir} odir=${lcovdir}$$sub ; \ @HAVE_LCOV_TRUE@ rm -rf $$odir ; mkdir -p $$odir && \ @HAVE_LCOV_TRUE@ ${LCOV_REPORT} ${GENHTML_OPTIONS} \ @HAVE_LCOV_TRUE@ --title "${PACKAGE_NAME}-${PACKAGE_VERSION}$$sub" \ @HAVE_LCOV_TRUE@ --srcdir=${srcdir} -o $$odir # Rerun checks before generating report @HAVE_LCOV_TRUE@lcov-rerun: clean-lcov @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) lcov-report # Show all uncovered lines as errors @HAVE_LCOV_TRUE@uncovered: @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} # Run check in current dir and show all uncovered lines as errors @HAVE_LCOV_TRUE@covcheck: @HAVE_LCOV_TRUE@ -find . -name "*.gcda" | xargs rm -rf @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} @HAVE_LCOV_TRUE@clean-local:: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true @HAVE_LCOV_TRUE@clean-lcov: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true # Rules from depend2.am (GENERIC = TRUE, SUBDIROBJ = FALSE, %FASTDEP% = am_fastdepCC) silenced. .c.o: @test "${SOFIA_SILENT}" != @ || echo ' COMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(COMPILE) -c -o $@ $< .c.lo: @test "${SOFIA_SILENT}" != @ || echo ' LTCOMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(LTCOMPILE) -c -o $@ $< # endif # ---------------------------------------------------------------------- # Sofia specific rules # 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: sofia-sip-1.12.11+20110422.1/libsofia-sip-ua-glib/su-glib/sofia-sip/000077500000000000000000000000001223300710500237215ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua-glib/su-glib/sofia-sip/su_glib.h000066400000000000000000000026421223300710500255220ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2006 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef SU_GLIB_SOURCE_H #define SU_GLIB_SOURCE_H /** * @file su_glib.h * * @author Pekka Pessi * @author Kai Vehmanen */ #ifndef SU_WAIT_H #include #endif #ifndef __GLIB_H__ #include #endif SOFIA_BEGIN_DECLS SOFIAPUBFUN su_root_t *su_glib_root_create(su_root_magic_t *) __attribute__((__malloc__)); SOFIAPUBFUN GSource *su_glib_root_gsource(su_root_t *); SOFIAPUBFUN void su_glib_prefer_gsource(void); SOFIA_END_DECLS #endif /* !defined SU_GLIB_SOURCE_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua-glib/su-glib/sofia-sip/su_source.h000066400000000000000000000031061223300710500261010ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef SU_SOURCE_H /** Defined when su_source.h has been included. */ #define SU_SOURCE_H /** * @file su_source.h * @brief * * NOTE: This file (su_source.h) is DEPRECATED as of 1.12.2 release. * Please use su_glib.h instead. * * @author Pekka Pessi * @author Kai Vehmanen * * @date Created: Thu Mar 4 19:58:50 2004 ppessi * */ #ifndef SU_WAIT_H #include #endif #ifndef __GLIB_H__ #include #endif SOFIA_BEGIN_DECLS SOFIAPUBFUN su_root_t *su_root_source_create(su_root_magic_t *) __attribute__((__malloc__)); SOFIAPUBFUN GSource *su_root_source(su_root_t *); SOFIA_END_DECLS #endif /* !defined SU_SOURCE_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua-glib/su-glib/su_glib.docs000066400000000000000000000030761223300710500243330ustar00rootroot00000000000000/** @mainpage Sofia-SIP su-glib Module @section su_glib_meta Module Meta Information The su-glib module provides an interface to connect Sofia-SIP event loop to an existing glib main loop. Without this interface, a glib based application would have to create a separate thread for running the Sofia-SIP event loop. @CONTACT Pekka Pessi @STATUS Core library @LICENSE LGPL @section su_glib_contents Contents of su-glib Module The su-glib module contains the public header files as follows: - the public API of the module - deprecated API (1.12.1 and earlier) @section su_glib_examples Examples of use Below is a simple example of how to use su-glib: @code #include #include /* ... */ GMainLoop *ptr = g_main_loop_new(NULL, FALSE); GSource *gsource; su_root_t *sofia_event_loop; su_timer_t *timer; /* create a sofia event loop using su-glib function su_glib_root_source_create() */ sofia_event_loop = su_glib_root_create(NULL); /* attach the created GSource to glib event loop */ gsource = su_glib_root_gsource(sofia_event_loop); g_source_attach(gsource, g_main_loop_get_context(ptr)); /* use the sofia event loop with libsofia-sip-ua modules */ timer = su_timer_create(su_root_task(sofia_event_loop), 200L); /* ... initialize other Sofia-SIP modules/functrions */ /* run the glib mainloop */ g_main_loop_run(ptr); @endcode @section su_glib_todo Todo - see sourceforge.net issue tracker for sofia-sip (-> http://sofia-sip.sourceforge.net/development.html ) */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua-glib/su-glib/su_source.c000066400000000000000000000664611223300710500242170ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005-2009 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /** * @file su_source.c * @brief Wrapper for glib GSource. * * Refs: * - http://sofia-sip.sourceforge.net/refdocs/su/group__su__wait.html * - http://developer.gnome.org/doc/API/glib/glib-the-main-event-loop.html * * @author Pekka Pessi . * * @date Created: Thu Mar 4 15:15:15 2004 ppessi * */ #include "config.h" #ifdef SYMBIAN #include #endif #ifndef __GLIB_H__ #include #endif #if HAVE_OPEN_C #include #include #endif #define SU_PORT_IMPLEMENTATION 1 #define SU_MSG_ARG_T union { char anoymous[4]; } #define su_port_s su_source_s #include "sofia-sip/su_source.h" #include "sofia-sip/su_glib.h" #include "sofia-sip/su.h" #include "su_port.h" #include "sofia-sip/su_alloc.h" #include #include #include #include #include #if 1 #define PORT_LOCK_DEBUG(x) ((void)0) #else #define PORT_LOCK_DEBUG(x) printf x #endif static su_port_t *su_source_port_create(void) __attribute__((__malloc__)); static gboolean su_source_prepare(GSource *gs, gint *return_tout); static gboolean su_source_check(GSource *gs); static gboolean su_source_dispatch(GSource *gs, GSourceFunc callback, gpointer user_data); static void su_source_finalize(GSource *source); static GSourceFuncs su_source_funcs[1] = {{ su_source_prepare, su_source_check, su_source_dispatch, su_source_finalize, NULL, NULL }}; static int su_source_port_init(su_port_t *self, su_port_vtable_t const *vtable); static void su_source_port_deinit(su_port_t *self); static void su_source_lock(su_port_t *self, char const *who); static void su_source_unlock(su_port_t *self, char const *who); static void su_source_incref(su_port_t *self, char const *who); static void su_source_decref(su_port_t *self, int blocking, char const *who); static struct _GSource *su_source_gsource(su_port_t *port); static int su_source_register(su_port_t *self, su_root_t *root, su_wait_t *wait, su_wakeup_f callback, su_wakeup_arg_t *arg, int priority); static int su_source_unregister(su_port_t *port, su_root_t *root, su_wait_t *wait, su_wakeup_f callback, su_wakeup_arg_t *arg); static int su_source_deregister(su_port_t *self, int i); static int su_source_unregister_all(su_port_t *self, su_root_t *root); static int su_source_eventmask(su_port_t *self, int index, int socket, int events); static void su_source_run(su_port_t *self); static void su_source_break(su_port_t *self); static su_duration_t su_source_step(su_port_t *self, su_duration_t tout); static int su_source_thread(su_port_t *self, enum su_port_thread_op op); static int su_source_add_prepoll(su_port_t *port, su_root_t *root, su_prepoll_f *, su_prepoll_magic_t *); static int su_source_remove_prepoll(su_port_t *port, su_root_t *root); static int su_source_multishot(su_port_t *self, int multishot); static int su_source_wakeup(su_port_t *self); static int su_source_is_running(su_port_t const *self); static char const *su_source_name(su_port_t const *self); static su_port_vtable_t const su_source_port_vtable[1] = {{ /* su_vtable_size: */ sizeof su_source_port_vtable, su_source_lock, su_source_unlock, su_source_incref, su_source_decref, su_source_gsource, su_base_port_send, su_source_register, su_source_unregister, su_source_deregister, su_source_unregister_all, su_source_eventmask, su_source_run, su_source_break, su_source_step, su_source_thread, su_source_add_prepoll, su_source_remove_prepoll, su_base_port_timers, su_source_multishot, /*su_source_wait_events*/ NULL, su_base_port_getmsgs, su_base_port_getmsgs_from, su_source_name, su_base_port_start_shared, su_base_port_wait, NULL, su_base_port_deferrable, su_base_port_max_defer, su_source_wakeup, su_source_is_running, su_base_port_stamp64, su_base_port_stamp64_offset, }}; static char const *su_source_name(su_port_t const *self) { return "GSource"; } /** * Port is a per-thread reactor. * * Multiple root objects executed by single thread share a su_port_t object. */ struct su_source_s { su_base_port_t sup_base[1]; GThread *sup_tid; GStaticMutex sup_obtained[1]; GStaticMutex sup_mutex[1]; GSource *sup_source; /**< Backpointer to source */ GMainLoop *sup_main_loop; /**< Reference to mainloop while running */ /* Waits */ unsigned sup_registers; /** Counter incremented by su_port_register() or su_port_unregister() */ unsigned sup_n_waits; unsigned sup_size_waits; unsigned sup_max_index; unsigned *sup_indices; su_wait_t *sup_waits; su_wakeup_f *sup_wait_cbs; su_wakeup_arg_t**sup_wait_args; su_root_t **sup_wait_roots; }; typedef struct _SuSource { GSource ss_source[1]; su_port_t ss_port[1]; } SuSource; #define SU_SOURCE_OWN_THREAD(p) ((p)->sup_tid == g_thread_self()) #if 1 #define SU_SOURCE_INCREF(p, f) (g_source_ref(p->sup_source)) #define SU_SOURCE_DECREF(p, f) (g_source_unref(p->sup_source)) #else /* Debugging versions */ #define SU_SOURCE_INCREF(p, f) (g_source_ref(p->sup_source), printf("incref(%p) by %s\n", (p), f)) #define SU_SOURCE_DECREF(p, f) do { printf("decref(%p) by %s\n", (p), f), \ g_source_unref(p->sup_source); } while(0) #endif #if HAVE_FUNC #define enter (void)SU_DEBUG_9(("%s: entering\n", __func__)) #elif HAVE_FUNCTION #define enter (void)SU_DEBUG_9(("%s: entering\n", __FUNCTION__)) #else #define enter (void)0 #endif /*=============== Public function definitions ===============*/ /** Create a root that uses GSource as reactor */ su_root_t *su_glib_root_create(su_root_magic_t *magic) { return su_root_create_with_port(magic, su_source_port_create()); } /** Deprecated */ su_root_t *su_root_source_create(su_root_magic_t *magic) { return su_glib_root_create(magic); } /** * Returns a GSource object for the root * * Note that you need to unref the GSource with g_source_unref() * before destroying the root object. * * @return NULL on error (for instance if root was not created with * su_glib_root_create()) */ GSource *su_glib_root_gsource(su_root_t *root) { g_assert(root); return su_root_gsource(root); } /*=============== Private function definitions ===============*/ /** Initialize source port */ static int su_source_port_init(su_port_t *self, su_port_vtable_t const *vtable) { GSource *gs = (GSource *)((char *)self - offsetof(SuSource, ss_port)); self->sup_source = gs; g_static_mutex_init(self->sup_obtained); g_static_mutex_init(self->sup_mutex); return su_base_port_init(self, vtable); } static void su_source_port_deinit(su_port_t *self) { su_base_port_deinit(self); g_static_mutex_free(self->sup_mutex); g_static_mutex_free(self->sup_obtained); if (self->sup_indices) free (self->sup_indices), self->sup_indices = NULL; if (self->sup_waits) free (self->sup_waits), self->sup_waits = NULL; if (self->sup_wait_cbs) free (self->sup_wait_cbs), self->sup_wait_cbs = NULL; if (self->sup_wait_args) free (self->sup_wait_args), self->sup_wait_args = NULL; if (self->sup_wait_roots) free (self->sup_wait_roots), self->sup_wait_roots = NULL; su_home_deinit(self->sup_base->sup_home); } /** @internal Destroy a port. */ static void su_source_finalize(GSource *gs) { SuSource *ss = (SuSource *)gs; assert(gs); SU_DEBUG_9(("su_source_finalize() called\n")); su_source_port_deinit(ss->ss_port); } /** @internal Send a message to the port. */ int su_source_wakeup(su_port_t *self) { GMainContext *gmc = g_source_get_context(self->sup_source); if (gmc) g_main_context_wakeup(gmc); return 0; } /** @internal * * Change or query ownership of the port object. * * @param self pointer to a port object * @param op operation * * @ERRORS * @ERROR EALREADY port already has an owner (or has no owner) */ static int su_source_thread(su_port_t *self, enum su_port_thread_op op) { GThread *me = g_thread_self(); switch (op) { case su_port_thread_op_is_obtained: if (self->sup_tid == me) return 2; else if (self->sup_tid) return 1; else return 0; case su_port_thread_op_release: if (self->sup_tid != me) return errno = EALREADY, -1; self->sup_tid = NULL; g_static_mutex_unlock(self->sup_obtained); return 0; case su_port_thread_op_obtain: if (su_home_threadsafe(su_port_home(self)) == -1) return -1; g_static_mutex_lock(self->sup_obtained); self->sup_tid = me; return 0; default: return errno = ENOSYS, -1; } } /* -- Registering and unregistering ------------------------------------- */ /* Seconds from 1.1.1900 to 1.1.1970 */ #define NTP_EPOCH 2208988800UL /** Prepare to wait - calculate time to next timer */ static gboolean su_source_prepare(GSource *gs, gint *return_tout) { SuSource *ss = (SuSource *)gs; su_port_t *self = ss->ss_port; su_duration_t tout = SU_WAIT_FOREVER; enter; su_base_port_waiting(self); if (self->sup_base->sup_head) { *return_tout = 0; return TRUE; } if (self->sup_base->sup_timers || self->sup_base->sup_deferrable) { su_time_t now; GTimeVal gtimeval; g_source_get_current_time(gs, >imeval); now.tv_sec = gtimeval.tv_sec + 2208988800UL; now.tv_usec = gtimeval.tv_usec; tout = su_timer_next_expires(&self->sup_base->sup_timers, now); if (self->sup_base->sup_deferrable) { su_duration_t tout_defer; tout_defer = su_timer_next_expires(&self->sup_base->sup_deferrable, now); if (tout_defer < self->sup_base->sup_max_defer) tout_defer = self->sup_base->sup_max_defer; if (tout > tout_defer) tout = tout_defer; } } *return_tout = (tout >= 0 && tout <= (su_duration_t)G_MAXINT)? (gint)tout : -1; return (tout == 0); } static gboolean su_source_check(GSource *gs) { SuSource *ss = (SuSource *)gs; su_port_t *self = ss->ss_port; gint tout; #if SU_HAVE_POLL unsigned i, I; #endif enter; #if SU_HAVE_POLL I = self->sup_n_waits; for (i = 0; i < I; i++) { if (self->sup_waits[i].revents) return TRUE; } #endif return su_source_prepare(gs, &tout); } static gboolean su_source_dispatch(GSource *gs, GSourceFunc callback, gpointer user_data) { SuSource *ss = (SuSource *)gs; su_port_t *self = ss->ss_port; enter; su_base_port_waiting(self); if (self->sup_base->sup_head) su_base_port_getmsgs(self); if (self->sup_base->sup_timers || self->sup_base->sup_deferrable) { su_time_t now; GTimeVal gtimeval; su_duration_t tout; tout = SU_DURATION_MAX; g_source_get_current_time(gs, >imeval); now.tv_sec = gtimeval.tv_sec + 2208988800UL; now.tv_usec = gtimeval.tv_usec; su_timer_expire(&self->sup_base->sup_timers, &tout, now); su_timer_expire(&self->sup_base->sup_deferrable, &tout, now); } #if SU_HAVE_POLL { su_root_t *root; su_wait_t *waits = self->sup_waits; unsigned i, n = self->sup_n_waits; unsigned version = self->sup_registers; for (i = 0; i < n; i++) { if (waits[i].revents) { root = self->sup_wait_roots[i]; self->sup_wait_cbs[i](root ? su_root_magic(root) : NULL, &waits[i], self->sup_wait_args[i]); /* Callback used su_register()/su_unregister() */ if (version != self->sup_registers) break; } } } #endif if (!callback) return TRUE; return callback(user_data); } static void su_source_lock(su_port_t *self, char const *who) { PORT_LOCK_DEBUG(("%p at %s locking(%p)...", (void *)g_thread_self(), who, self)); g_static_mutex_lock(self->sup_mutex); PORT_LOCK_DEBUG((" ...%p at %s locked(%p)...", (void *)g_thread_self(), who, self)); } static void su_source_unlock(su_port_t *self, char const *who) { g_static_mutex_unlock(self->sup_mutex); PORT_LOCK_DEBUG((" ...%p at %s unlocked(%p)\n", (void *)g_thread_self(), who, self)); } static void su_source_incref(su_port_t *self, char const *who) { SU_SOURCE_INCREF(self, who); } static void su_source_decref(su_port_t *self, int blocking, char const *who) { /* XXX - blocking? */ SU_SOURCE_DECREF(self, who); } GSource *su_source_gsource(su_port_t *self) { return self->sup_source; } /** @internal * * Register a @c su_wait_t object. The wait object, a callback function and * a argument pointer is stored in the port object. The callback function * will be called when the wait object is signaled. * * Please note if identical wait objects are inserted, only first one is * ever signalled. * * @param self pointer to port * @param root pointer to root object * @param waits pointer to wait object * @param callback callback function pointer * @param arg argument given to callback function when it is invoked * @param priority relative priority of the wait object * (0 is normal, 1 important, 2 realtime) * * @return * The function @su_source_register returns nonzero index of the wait object, * or -1 upon an error. */ int su_source_register(su_port_t *self, su_root_t *root, su_wait_t *wait, su_wakeup_f callback, su_wakeup_arg_t *arg, int priority) { unsigned i, j, I; unsigned n; enter; assert(SU_SOURCE_OWN_THREAD(self)); n = self->sup_n_waits; if (n >= self->sup_size_waits) { /* Reallocate size arrays */ unsigned size; unsigned *indices; su_wait_t *waits; su_wakeup_f *wait_cbs; su_wakeup_arg_t **wait_args; su_root_t **wait_tasks; if (self->sup_size_waits == 0) size = SU_WAIT_MIN; else size = 2 * self->sup_size_waits; indices = realloc(self->sup_indices, size * sizeof(*indices)); if (indices) { self->sup_indices = indices; for (i = self->sup_size_waits; i < size; i++) indices[i] = UINT_MAX; } for (i = 0; i < self->sup_n_waits; i++) g_source_remove_poll(self->sup_source, (GPollFD*)&self->sup_waits[i]); waits = realloc(self->sup_waits, size * sizeof(*waits)); if (waits) self->sup_waits = waits; for (i = 0; i < self->sup_n_waits; i++) g_source_add_poll(self->sup_source, (GPollFD*)&waits[i]); wait_cbs = realloc(self->sup_wait_cbs, size * sizeof(*wait_cbs)); if (wait_cbs) self->sup_wait_cbs = wait_cbs; wait_args = realloc(self->sup_wait_args, size * sizeof(*wait_args)); if (wait_args) self->sup_wait_args = wait_args; /* Add sup_wait_roots array, if needed */ wait_tasks = realloc(self->sup_wait_roots, size * sizeof(*wait_tasks)); if (wait_tasks) self->sup_wait_roots = wait_tasks; if (!(indices && waits && wait_cbs && wait_args && wait_tasks)) { return -1; } self->sup_size_waits = size; } self->sup_n_waits++; if (priority > 0) { /* Insert */ for (; n > 0; n--) { g_source_remove_poll(self->sup_source, (GPollFD*)&self->sup_waits[n-1]); self->sup_waits[n] = self->sup_waits[n-1]; g_source_add_poll(self->sup_source, (GPollFD*)&self->sup_waits[n]); self->sup_wait_cbs[n] = self->sup_wait_cbs[n-1]; self->sup_wait_args[n] = self->sup_wait_args[n-1]; self->sup_wait_roots[n] = self->sup_wait_roots[n-1]; } } else { /* Append - no need to move anything */ } self->sup_waits[n] = *wait; g_source_add_poll(self->sup_source, (GPollFD*)&self->sup_waits[n]); self->sup_wait_cbs[n] = callback; self->sup_wait_args[n] = arg; self->sup_wait_roots[n] = root; I = self->sup_max_index; for (i = 0; i < I; i++) if (self->sup_indices[i] == UINT_MAX) break; else if (self->sup_indices[i] >= n) self->sup_indices[i]++; if (i == I) self->sup_max_index++; if (n + 1 < self->sup_n_waits) for (j = i; j < I; j++) if (self->sup_indices[j] != UINT_MAX && self->sup_indices[j] >= n) self->sup_indices[j]++; self->sup_indices[i] = n; self->sup_registers++; return i + 1; /* 0 is failure */ } /** Unregister a su_wait_t object. * * The function su_source_unregister() unregisters a su_wait_t object. The * wait object, a callback function and a argument are removed from the * port object. * * @param self - pointer to port object * @param root - pointer to root object * @param wait - pointer to wait object * @param callback - callback function pointer (may be NULL) * @param arg - argument given to callback function when it is invoked * (may be NULL) * * @return Nonzero index of the wait object, or -1 upon an error. */ int su_source_unregister(su_port_t *self, su_root_t *root, su_wait_t *wait, su_wakeup_f callback, /* XXX - ignored */ su_wakeup_arg_t *arg) { unsigned n, N; unsigned i, I, j, *indices; enter; assert(self); assert(SU_SOURCE_OWN_THREAD(self)); i = (unsigned)-1; N = self->sup_n_waits; I = self->sup_max_index; indices = self->sup_indices; for (n = 0; n < N; n++) { if (SU_WAIT_CMP(wait[0], self->sup_waits[n]) != 0) continue; /* Found - delete it */ if (indices[n] == n) i = n; else for (i = 0; i < I; i++) if (indices[i] == n) break; assert(i < I); indices[i] = UINT_MAX; g_source_remove_poll(self->sup_source, (GPollFD*)&self->sup_waits[n]); self->sup_n_waits = N = N - 1; if (n < N) for (j = 0; j < I; j++) if (self->sup_indices[j] != UINT_MAX && self->sup_indices[j] > n) self->sup_indices[j]--; for (; n < N; n++) { g_source_remove_poll(self->sup_source, (GPollFD*)&self->sup_waits[n+1]); self->sup_waits[n] = self->sup_waits[n+1]; g_source_add_poll(self->sup_source, (GPollFD*)&self->sup_waits[n]); self->sup_wait_cbs[n] = self->sup_wait_cbs[n+1]; self->sup_wait_args[n] = self->sup_wait_args[n+1]; self->sup_wait_roots[n] = self->sup_wait_roots[n+1]; } i += 1; /* 0 is failure */ if (i == I) self->sup_max_index--; break; } self->sup_registers++; return (int)i; } /** Deregister a su_wait_t object. * * The function su_source_deregister() deregisters a su_wait_t registrattion. * The wait object, a callback function and a argument are removed from the * port object. * * @param self - pointer to port object * @param i - registration index * * @return Index of the wait object, or -1 upon an error. */ int su_source_deregister(su_port_t *self, int i) { unsigned j, n, N; unsigned I, *indices; su_wait_t wait[1]; enter; assert(self); assert(SU_SOURCE_OWN_THREAD(self)); if (i <= 0) return -1; N = self->sup_n_waits; I = self->sup_max_index; indices = self->sup_indices; assert((unsigned)i < I + 1); n = indices[i - 1]; if (n == UINT_MAX) return -1; self->sup_n_waits = N = N - 1; wait[0] = self->sup_waits[n]; g_source_remove_poll(self->sup_source, (GPollFD*)&self->sup_waits[n]); if (n < N) for (j = 0; j < I; j++) if (self->sup_indices[j] != UINT_MAX && self->sup_indices[j] > n) self->sup_indices[j]--; for (; n < N; n++) { g_source_remove_poll(self->sup_source, (GPollFD*)&self->sup_waits[n + 1]); self->sup_waits[n] = self->sup_waits[n+1]; g_source_add_poll(self->sup_source, (GPollFD*)&self->sup_waits[n]); self->sup_wait_cbs[n] = self->sup_wait_cbs[n+1]; self->sup_wait_args[n] = self->sup_wait_args[n+1]; self->sup_wait_roots[n] = self->sup_wait_roots[n+1]; } indices[i - 1] = UINT_MAX; if ((unsigned)i == I) self->sup_max_index--; su_wait_destroy(wait); self->sup_registers++; return (int)i; } /** @internal * Unregister all su_wait_t objects. * * The function su_source_unregister_all() unregisters all su_wait_t objects * associated with given root object destroys all queued timers. * * @param self - pointer to port object * @param root - pointer to root object * * @return Number of wait objects removed. */ int su_source_unregister_all(su_port_t *self, su_root_t *root) { unsigned i, j; unsigned n_waits; su_wait_t *waits; su_wakeup_f *wait_cbs; su_wakeup_arg_t**wait_args; su_root_t **wait_roots; enter; assert(SU_SOURCE_OWN_THREAD(self)); n_waits = self->sup_n_waits; waits = self->sup_waits; wait_cbs = self->sup_wait_cbs; wait_args = self->sup_wait_args; wait_roots = self->sup_wait_roots; for (i = j = 0; (unsigned)i < n_waits; i++) { if (wait_roots[i] == root) { /* XXX - we should free all resources associated with this */ g_source_remove_poll(self->sup_source, (GPollFD*)&waits[i]); continue; } if (i != j) { g_source_remove_poll(self->sup_source, (GPollFD*)&waits[i]); waits[j] = waits[i]; wait_cbs[j] = wait_cbs[i]; wait_args[j] = wait_args[i]; wait_roots[j] = wait_roots[i]; g_source_add_poll(self->sup_source, (GPollFD*)&waits[i]); } j++; } self->sup_n_waits = j; self->sup_registers++; return n_waits - j; } /**Set mask for a registered event. @internal * * Sets the mask describing events that can signal the registered callback. * * @param port pointer to port object * @param index registration index * @param socket socket * @param events new event mask * * @retval 0 when successful, * @retval -1 upon an error. */ static int su_source_eventmask(su_port_t *self, int index, int socket, int events) { unsigned n; int retval; enter; assert(self); assert(SU_SOURCE_OWN_THREAD(self)); assert(0 < index && (unsigned)index <= self->sup_max_index); if (index <= 0 || (unsigned)index > self->sup_max_index) return -1; n = self->sup_indices[index - 1]; if (n == UINT_MAX) return -1; g_source_remove_poll(self->sup_source, (GPollFD*)&self->sup_waits[n]); retval = su_wait_mask(&self->sup_waits[n], socket, events); g_source_add_poll(self->sup_source, (GPollFD*)&self->sup_waits[n]); return retval; } static int su_source_multishot(su_port_t *self, int multishot) { if (multishot == -1) return 1; else if (multishot == 0 || multishot == 1) return 1; /* Always enabled */ else return (errno = EINVAL), -1; } /** @internal Run the main loop. * * The main loop runs until su_source_break() is called from a callback. * * @param self pointer to port object * */ static void su_source_run(su_port_t *self) { GMainContext *gmc; GMainLoop *gml; enter; gmc = g_source_get_context(self->sup_source); if (gmc && g_main_context_acquire(gmc)) { gml = g_main_loop_new(gmc, TRUE); self->sup_main_loop = gml; g_main_loop_run(gml); g_main_loop_unref(gml); self->sup_main_loop = NULL; g_main_context_release(gmc); } } static int su_source_is_running(su_port_t const *self) { return self->sup_main_loop && g_main_loop_is_running(self->sup_main_loop); } /** @internal * The function @c su_source_break() is used to terminate execution of @c * su_source_run(). It can be called from a callback function. * * @param self pointer to port * */ static void su_source_break(su_port_t *self) { enter; if (self->sup_main_loop) g_main_loop_quit(self->sup_main_loop); } /** @internal Block until wait object is signaled or timeout. * * This function waits for wait objects and the timers associated with * the root object. When any wait object is signaled or timer is * expired, it invokes the callbacks. * * This function returns when a callback has been invoked or @c tout * milliseconds is elapsed. * * @param self pointer to port * @param tout timeout in milliseconds * * @Return * Milliseconds to the next invocation of timer, or @c SU_WAIT_FOREVER if * there are no active timers. */ su_duration_t su_source_step(su_port_t *self, su_duration_t tout) { GMainContext *gmc; enter; gmc = g_source_get_context(self->sup_source); if (gmc && g_main_context_acquire(gmc)) { GPollFD *fds = NULL; gint fds_size = 0; gint fds_wait; gint priority = G_MAXINT; gint src_tout = -1; g_main_context_prepare(gmc, &priority); fds_wait = g_main_context_query(gmc, priority, &src_tout, NULL, 0); while (fds_wait > fds_size) { fds = g_alloca(fds_wait * sizeof(fds[0])); fds_size = fds_wait; fds_wait = g_main_context_query(gmc, priority, &src_tout, fds, fds_size); } if (src_tout >= 0 && tout > (su_duration_t)src_tout) tout = src_tout; su_base_port_waiting(self); su_wait((su_wait_t *)fds, fds_wait, tout); g_main_context_check(gmc, priority, fds, fds_wait); g_main_context_dispatch(gmc); g_main_context_release(gmc); } return 0; } static int su_source_add_prepoll(su_port_t *port, su_root_t *root, su_prepoll_f *prepoll, su_prepoll_magic_t *magic) { /* We could call prepoll in su_source_prepare()?? */ return -1; } static int su_source_remove_prepoll(su_port_t *port, su_root_t *root) { return -1; } #if 0 /** @internal * Prints out the contents of the port. * * @param self pointer to a port * @param f pointer to a file (if @c NULL, uses @c stdout). */ void su_source_dump(su_port_t const *self, FILE *f) { int i; #define IS_WAIT_IN(x) (((x)->events & SU_WAIT_IN) ? "IN" : "") #define IS_WAIT_OUT(x) (((x)->events & SU_WAIT_OUT) ? "OUT" : "") #define IS_WAIT_ACCEPT(x) (((x)->events & SU_WAIT_ACCEPT) ? "ACCEPT" : "") if (f == NULL) f = stdout; fprintf(f, "su_port_t at %p:\n", self); fprintf(f, "\tport is%s running\n", self->sup_running ? "" : "not "); fprintf(f, "\tport tid %p\n", (void *)self->sup_tid); fprintf(f, "\t%d wait objects\n", self->sup_n_waits); for (i = 0; i < self->sup_n_waits; i++) { } } #endif /**@internal * * Allocates and initializes a reactor and message port object. * * @return * If successful a pointer to the new message port is returned, otherwise * NULL is returned. */ static su_port_t *su_source_port_create(void) { SuSource *ss; su_port_t *self = NULL; SU_DEBUG_9(("su_source_port_create() called\n")); ss = (SuSource *)g_source_new(su_source_funcs, (sizeof *ss)); if (ss) { self = ss->ss_port; if (su_source_port_init(self, su_source_port_vtable) < 0) g_source_unref(ss->ss_source), self = NULL; } else { su_perror("su_source_port_create(): g_source_new"); } SU_DEBUG_1(("su_source_port_create() returns %p\n", (void *)self)); return self; } /* No su_source_port_start */ /** Use su_source implementation when su_root_create() is called. * * @NEW_1_12_5 */ void su_glib_prefer_gsource(void) { su_port_prefer(su_source_port_create, NULL); } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua-glib/su-glib/su_source_test.c000066400000000000000000000264501223300710500252500ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005-2006 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@ingroup su_root_ex * @CFILE su_source_test.c * * @brief Test program for glib and su root event loop integration. * * @author Pekka Pessi * * @date Created: Thu Mar 18 19:40:51 1999 pessi */ #include "config.h" #include #include #include #include #include struct pinger; #define SU_ROOT_MAGIC_T struct pinger #define SU_INTERNAL_P su_root_t * #define SU_MSG_ARG_T su_sockaddr_t #include "sofia-sip/su.h" #include "sofia-sip/su_wait.h" #include "sofia-sip/su_log.h" #include #include "sofia-sip/su_glib.h" struct pinger { enum { PINGER = 1, PONGER = 2 } const sort; char const * name; unsigned running : 1; unsigned : 0; su_root_t *root; su_socket_t s; su_timer_t *t; int id; int rindex; su_time_t when; su_sockaddr_t addr; double rtt_total; int rtt_n; }; short opt_family = AF_INET; short opt_verbatim = 0; short opt_singlethread = 0; GMainLoop *global_gmainloop = NULL; static su_socket_t udpsocket(void) { su_socket_t s; su_sockaddr_t su = { 0 }; socklen_t sulen = sizeof(su); char nbuf[64]; su.su_family = opt_family; su_getlocalip(&su); s = su_socket(su.su_family, SOCK_DGRAM, 0); if (s == INVALID_SOCKET) { su_perror("udpsocket: socket"); exit(1); } if (bind(s, &su.su_sa, su_sockaddr_size(&su)) == SOCKET_ERROR) { su_perror("udpsocket: bind"); exit(1); } if (getsockname(s, &su.su_sa, &sulen) == SOCKET_ERROR) { su_perror("udpsocket: getsockname"); exit(1); } if (opt_verbatim) printf("udpsocket: using address [%s]:%u\n", inet_ntop(su.su_family, SU_ADDR(&su), nbuf, sizeof(nbuf)), ntohs(su.su_sin.sin_port)); return s; } static char *snow(su_time_t now) { static char buf[24]; su_time_print(buf, sizeof(buf), &now); return buf; } void do_ping(struct pinger *p, su_timer_t *t, void *p0) { char buf[1024]; assert(p == su_root_magic(su_timer_root(t))); assert(p->sort == PINGER); p->when = su_now(); snprintf(buf, sizeof(buf), "Ping %d at %s", p->id++, snow(p->when)); if (sendto(p->s, buf, strlen(buf), 0, &p->addr.su_sa, su_sockaddr_size(&p->addr)) == -1) { su_perror("do_ping: send"); } if (opt_verbatim) { puts(buf); fflush(stdout); } } int do_rtt(struct pinger *p, su_wait_t *w, void *p0) { su_sockaddr_t su; struct sockaddr * const susa = &su.su_sa; socklen_t susize[] = { sizeof(su)}; char buf[1024]; char nbuf[1024]; int n; su_time_t now = su_now(); double rtt; assert(p0 == p); assert(p->sort == PINGER); rtt = su_time_diff(now, p->when); p->rtt_total += rtt, p->rtt_n++; su_wait_events(w, p->s); n = recvfrom(p->s, buf, sizeof(buf) - 1, 0, susa, susize); if (n < 0) { su_perror("do_rtt: recvfrom"); return 0; } buf[n] = 0; if (opt_verbatim) printf("do_rtt: %d bytes from [%s]:%u: \"%s\", rtt = %lg ms\n", n, inet_ntop(su.su_family, SU_ADDR(&su), nbuf, sizeof(nbuf)), ntohs(su.su_sin.sin_port), buf, rtt / 1000); do_ping(p, p->t, NULL); return 0; } void do_pong(struct pinger *p, su_timer_t *t, void *p0) { char buf[1024]; assert(p == su_root_magic(su_timer_root(t))); assert(p->sort == PONGER); p->id = 0; snprintf(buf, sizeof(buf), "Pong at %s", snow(su_now())); if (sendto(p->s, buf, strlen(buf), 0, &p->addr.su_sa, su_sockaddr_size(&p->addr)) == -1) { su_perror("do_pong: send"); } if (opt_verbatim) { puts(buf); fflush(stdout); } } int do_recv(struct pinger *p, su_wait_t *w, void *p0) { su_sockaddr_t su; socklen_t susize[] = { sizeof(su)}; char buf[1024]; char nbuf[1024]; int n; su_time_t now = su_now(); assert(p0 == p); assert(p->sort == PONGER); su_wait_events(w, p->s); n = recvfrom(p->s, buf, sizeof(buf) - 1, 0, &su.su_sa, susize); if (n < 0) { su_perror("do_recv: recvfrom"); return 0; } buf[n] = 0; if (opt_verbatim) printf("do_recv: %d bytes from [%s]:%u: \"%s\" at %s\n", n, inet_ntop(su.su_family, SU_ADDR(&su), nbuf, sizeof(nbuf)), ntohs(su.su_sin.sin_port), buf, snow(now)); fflush(stdout); #if 0 if (p->id) puts("do_recv: already a pending reply"); if (su_timer_set(p->t, do_pong, p) < 0) { fprintf(stderr, "do_recv: su_timer_set() error\n"); return 0; } p->id = 1; #else do_pong(p, p->t, NULL); #endif return 0; } void do_exit(struct pinger *x, su_timer_t *t, void *x0) { g_assert(global_gmainloop); if (opt_verbatim) printf("do_exit at %s\n", snow(su_now())); g_main_loop_quit(global_gmainloop); } int do_init(su_root_t *root, struct pinger *p) { su_wait_t w; su_socket_t s; long interval; su_timer_t *t; su_wakeup_f f; int index, index0; switch (p->sort) { case PINGER: f = do_rtt; interval = 200; break; case PONGER: f = do_recv; interval = 40; break; default: return SU_FAILURE; } /* Create a sockets, */ s = udpsocket(); if (su_wait_create(&w, s, SU_WAIT_IN) == SOCKET_ERROR) su_perror("su_wait_create"), exit(1); p->s = s; p->t = t = su_timer_create(su_root_task(root), interval); if (t == NULL) { su_perror("su_timer_create"); return SU_FAILURE; } index0 = su_root_register(root, &w, f, p, 0); if (index0 == SOCKET_ERROR) { su_perror("su_root_register"); return SU_FAILURE; } index = su_root_register(root, &w, f, p, 0); if (index == SOCKET_ERROR) { su_perror("su_root_register"); return SU_FAILURE; } su_root_deregister(root, index0); p->rindex = index; return 0; } void do_destroy(su_root_t *root, struct pinger *p) { if (opt_verbatim) printf("do_destroy %s at %s\n", p->name, snow(su_now())); su_root_deregister(root, p->rindex); su_timer_destroy(p->t), p->t = NULL; p->running = 0; } void start_ping(struct pinger *p, su_msg_r msg, su_sockaddr_t *arg) { if (!p->running) return; if (opt_verbatim) printf("start_ping: %s\n", p->name); p->addr = *arg; p->id = 1; su_timer_set_at(p->t, do_ping, p, su_now()); } void start_pong(struct pinger *p, su_msg_r msg, su_sockaddr_t *arg) { su_msg_r reply; if (!p->running) return; if (opt_verbatim) printf("start_pong: %s\n", p->name); p->addr = *arg; if (su_msg_reply(reply, msg, start_ping, sizeof(p->addr)) == 0) { socklen_t sinsize[1] = { sizeof(p->addr) }; if (getsockname(p->s, (struct sockaddr*)su_msg_data(reply), sinsize) == SOCKET_ERROR) su_perror("start_pong: getsockname()"), exit(1); su_msg_send(reply); } else { fprintf(stderr, "su_msg_create failed!\n"); } } void init_ping(struct pinger *p, su_msg_r msg, su_sockaddr_t *arg) { su_msg_r reply; if (opt_verbatim) printf("init_ping: %s\n", p->name); if (su_msg_reply(reply, msg, start_pong, sizeof(p->addr)) == 0) { socklen_t sinsize[1] = { sizeof(p->addr) }; if (getsockname(p->s, (struct sockaddr*)su_msg_data(reply), sinsize) == SOCKET_ERROR) su_perror("start_pong: getsockname()"), exit(1); su_msg_send(reply); } else { fprintf(stderr, "su_msg_reply failed!\n"); } } #if HAVE_SIGNAL static RETSIGTYPE term(int n) { exit(1); } #endif void time_test(void) { su_time_t now = su_now(), then = now; su_duration_t t1, t2; su_duration_t us; for (us = 0; us < 1000000; us += 300) { then.tv_sec = now.tv_sec; if ((then.tv_usec = now.tv_usec + us) >= 1000000) then.tv_usec -= 1000000, then.tv_sec++; t1 = su_duration(now, then); t2 = su_duration(then, now); assert(t1 == -t2); } if (opt_verbatim) printf("time_test: passed\n"); } char const name[] = "su_test"; void usage(int exitcode) { fprintf(stderr, "usage: %s [-6vs] [pid]\n", name); exit(exitcode); } /* * test su_wait functionality: * * Create a ponger, waking up do_recv() when data arrives, * then scheduling do_pong() by timer * * Create a pinger, executed from timer, scheduling do_ping(), * waking up do_rtt() when data arrives * * Create a timer, executing do_exit() after 10 seconds */ int main(int argc, char *argv[]) { su_root_t *root; su_clone_r ping = SU_CLONE_R_INIT, pong = SU_CLONE_R_INIT; su_msg_r start_msg = SU_MSG_R_INIT; su_timer_t *t; unsigned long sleeppid = 0; struct pinger pinger = { PINGER, "ping", 1 }, ponger = { PONGER, "pong", 1 }; char *argv0 = argv[0]; #if HAVE_OPEN_C dup2(1, 2); #endif while (argv[1]) { if (strcmp(argv[1], "-v") == 0) { opt_verbatim = 1; argv++; } #if SU_HAVE_IN6 else if (strcmp(argv[1], "-6") == 0) { opt_family = AF_INET6; argv++; } #endif else if (strcmp(argv[1], "-s") == 0) { opt_singlethread = 1; argv++; } else if (strlen(argv[1]) == strspn(argv[1], "0123456789")) { sleeppid = strtoul(argv[1], NULL, 10); argv++; } else { usage(1); } } #if HAVE_OPEN_C opt_verbatim = 1; opt_singlethread = 1; su_log_soft_set_level(su_log_default, 9); #endif #if HAVE_SIGNAL signal(SIGTERM, term); #endif su_init(); atexit(su_deinit); time_test(); global_gmainloop = g_main_loop_new(NULL, FALSE); g_assert(global_gmainloop); root = su_glib_root_create(NULL); if (!root) perror("su_root_glib_create"), exit(1); if (!g_source_attach(su_glib_root_gsource(root), g_main_loop_get_context(global_gmainloop))) perror("g_source_attach"), exit(1); su_root_threading(root, 0 && !opt_singlethread); if (su_clone_start(root, ping, &pinger, do_init, do_destroy) != 0) perror("su_clone_start"), exit(1); if (su_clone_start(root, pong, &ponger, do_init, do_destroy) != 0) perror("su_clone_start"), exit(1); /* Test timer, exiting after 200 milliseconds */ t = su_timer_create(su_root_task(root), 200L); if (t == NULL) su_perror("su_timer_create"), exit(1); su_timer_set(t, (su_timer_f)do_exit, NULL); su_msg_create(start_msg, su_clone_task(ping), su_clone_task(pong), init_ping, 0); su_msg_send(start_msg); g_main_loop_run(global_gmainloop); su_clone_wait(root, ping); su_clone_wait(root, pong); su_timer_destroy(t); if (pinger.rtt_n) { printf("%s executed %u pings in %g, mean rtt=%g sec\n", name, pinger.rtt_n, pinger.rtt_total, pinger.rtt_total / pinger.rtt_n); } su_root_destroy(root); g_main_loop_unref(global_gmainloop), global_gmainloop = NULL; if (opt_verbatim) printf("%s exiting\n", argv0); #ifndef HAVE_WIN32 #if HAVE_SIGNAL if (sleeppid) kill(sleeppid, SIGTERM); #endif #endif #if HAVE_OPEN_C sleep(7); #endif return 0; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua-glib/su-glib/torture_su_glib_timer.c000066400000000000000000000132021223300710500266010ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005,2006 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /** * @brief Test program for su-glib timers * * Based on torture_su_timer.c of libsofia-sip-ua. * * @author Pekka Pessi * @author Kai Vehmanen * * @internal * * @date Created: Fri Oct 19 08:53:55 2001 pessi */ #include "config.h" #include #include #include #include #include struct tester; #define SU_ROOT_MAGIC_T struct tester #define SU_INTERNAL_P su_root_t * #define SU_TIMER_ARG_T struct timing #include "sofia-sip/su.h" #include "sofia-sip/su_wait.h" #include "sofia-sip/su_log.h" #include struct timing { int t_run; int t_times; su_time_t t_prev; }; struct tester { su_root_t *root; su_timer_t *t, *t1; unsigned times; void *sentinel; }; void print_stamp(struct tester *x, su_timer_t *t, struct timing *ti) { su_time_t now = su_now(), prev = ti->t_prev; ti->t_prev = now; printf("timer interval %f\n", 1000 * su_time_diff(now, prev)); if (!ti->t_run) su_timer_set(t, print_stamp, ti); if (++ti->t_times >= 10) su_timer_reset(t); } void print_X(struct tester *x, su_timer_t *t1, struct timing *ti) { su_timer_set(t1, print_X, ti); putchar('X'); fflush(stdout); } su_msg_r intr_msg = SU_MSG_R_INIT; static RETSIGTYPE intr_handler(int signum) { su_msg_send(intr_msg); } static void test_break(struct tester *tester, su_msg_r msg, su_msg_arg_t *arg) { su_root_break(tester->root); } void end_test(struct tester *tester, su_timer_t *t, struct timing *ti) { printf("ending test\n"); su_timer_destroy(t); su_timer_reset(tester->t); su_timer_reset(tester->t1); su_root_break(tester->root); } void increment(struct tester *tester, su_timer_t *t, struct timing *ti) { tester->times++; if ((void *)ti == (void*)tester->sentinel) su_root_break(tester->root); } void usage(char const *name) { fprintf(stderr, "usage: %s [-1r] [-Nnum] [interval]\n", name); exit(1); } /* * test su_timer functionality: * * Create a timer, executing print_stamp() in every 20 ms */ int main(int argc, char *argv[]) { su_root_t *root; su_timer_t *t, *t1, *t_end; su_timer_t **timers; su_duration_t interval = 60; char *argv0 = argv[0]; char *s; int use_t1 = 0; su_time_t now, started; intptr_t i, N = 500; GSource *source; struct timing timing[1] = {{ 0 }}; struct tester tester[1] = {{ 0 }}; while (argv[1] && argv[1][0] == '-') { char *o = argv[1] + 1; while (*o) { if (*o == '1') o++, use_t1 = 1; else if (*o == 'r') o++, timing->t_run = 1; else if (*o == 'N') { if (o[1]) N = strtoul(o + 1, &o, 0); else if (argv[2]) N = strtoul(argv++[2], &o, 0); break; } else break; } if (*o) usage(argv0); argv++; } if (argv[1]) { interval = strtoul(argv[1], &s, 10); if (interval == 0 || s == argv[1]) usage(argv0); } su_init(); atexit(su_deinit); tester->root = root = su_glib_root_create(tester); source = su_root_gsource(tester->root); g_source_attach(source, NULL /*g_main_context_default ()*/); su_msg_create(intr_msg, su_root_task(root), su_root_task(root), test_break, 0); signal(SIGINT, intr_handler); #if HAVE_SIGPIPE signal(SIGPIPE, intr_handler); signal(SIGQUIT, intr_handler); signal(SIGHUP, intr_handler); #endif t = su_timer_create(su_root_task(root), interval); t1 = su_timer_create(su_root_task(root), 1); t_end = su_timer_create(su_root_task(root), 20 * interval); if (t == NULL || t1 == NULL || t_end == NULL) su_perror("su_timer_create"), exit(1); tester->t = t, tester->t1 = t1; timing->t_prev = su_now(); if (timing->t_run) su_timer_run(t, print_stamp, timing); else su_timer_set(t, print_stamp, timing); if (use_t1) su_timer_set(t1, print_X, NULL); su_timer_set(t_end, end_test, NULL); su_root_run(root); su_msg_destroy(intr_msg); su_timer_destroy(t); su_timer_destroy(t1); if (timing->t_times != 10) { fprintf(stderr, "%s: t expired %d times (expecting 10)\n", argv0, timing->t_times); return 1; } /* Insert timers in order */ timers = calloc(N, sizeof *timers); if (!timers) { perror("calloc"); exit(1); } now = started = su_now(); for (i = 0; i < N; i++) { t = su_timer_create(su_root_task(root), 1000); if (!t) { perror("su_timer_create"); exit(1); } if (++now.tv_usec == 0) ++now.tv_sec; su_timer_set_at(t, increment, (void *)i, now); timers[i] = t; } tester->sentinel = (void*)(i - 1); su_root_run(root); printf("Processing %u timers took %f millisec (%f expected)\n", (unsigned)i, su_time_diff(su_now(), started) * 1000, (double)i / 1000); for (i = 0; i < N; i++) { su_timer_destroy(timers[i]); } su_root_destroy(root); su_deinit(); return 0; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/000077500000000000000000000000001223300710500175525ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/.gitignore000066400000000000000000000024131223300710500215420ustar00rootroot00000000000000/bnf/torture_bnf /features/sofia-sip/sofia_features.h /http/http_parser_table.c /http/http_tag.c /http/sofia-sip/http_protos.h /http/sofia-sip/http_tag.h /http/test_http /ipt/torture_base64 /iptsec/test_auth_digest /msg/msg_mime_table.c /msg/msg_name_hash /msg/sofia-sip/msg_mime_protos.h /msg/sofia-sip/msg_protos.h /msg/test_msg /msg/test_protos.h /msg/test_table.c /nta/check_nta /nta/portbind /nta/test_nta /nta/test_nta_api /nth/http-client /nth/http-server /nth/test_nth /nth/tmp_sippasswd.* /nua/check_nua /sdp/test_sdp /sdp/torture_sdp /sip/sip_parser_table.c /sip/sip_tag.c /sip/sofia-sip/sip_extra.h /sip/sofia-sip/sip_hclasses.h /sip/sofia-sip/sip_protos.h /sip/sofia-sip/sip_tag.h /sip/test_date /sip/test_sip_msg /sip/torture_sip /sip/validator /soa/test_soa /sresolv/check_sres_sip /sresolv/named.run /sresolv/test_sresolv /sresolv/torture_sresolv /stun/lookup_stun_server /stun/stunc /su/addrinfo /su/localinfo /su/sofia-sip/stamp-h2 /su/sofia-sip/su_configure.h /su/su_proxy /su/test_htable /su/test_htable2 /su/test_memmem /su/test_poll /su/test_su /su/torture_heap /su/torture_rbtree /su/torture_su /su/torture_su_alloc /su/torture_su_bm /su/torture_su_port /su/torture_su_root /su/torture_su_tag /su/torture_su_time /su/torture_su_timer /tport/test_tport /url/torture_url sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/ChangeLog000066400000000000000000000265601223300710500213350ustar00rootroot000000000000002007-04-25 Kai Vehmanen * libsofia-sip-ua interface v4 frozen (5:0:5) for the 1.12.6 release 2007-02-09 Kai Vehmanen * libsofia-sip-ua interface v4 frozen (4:0:4) for the 1.12.5 release 2006-10-12 Kai Vehmanen * libsofia-sip-ua interface v3 frozen (3:0:3) for the 1.12.3 release 2006-09-26 Kai Vehmanen * libsofia-sip-ua interface v2 frozen (2:0:2) for the 1.12.2 release 2006-08-30 Pekka Pessi * nua: added tag nutag_refer_with_id. 2006-08-28 Kai Vehmanen * libsofia-sip-ua interface v2 opened to development, version to 2:0:2. 2006-08-25 Pekka Pessi * Added urltag_scan(). 2006-08-23 Pekka Pessi * nta.c, nta.h: added nta_leg_make_replaces(), nta_leg_by_replaces(). * nua: event watcher (nua_subscribe, nua_watcher) now tries to re-establish subscription if the subscription was terminated with reason "deactivated" or "probation". Likewise, if SUBSCRIBE was returned a suitable error response with Retry-After header, nua tries to re-establish subscription after given interval. 2006-07-27 Kai Vehmanen * libsofia-sip-ua interface v1 frozen (1.12.1), version to 1:0:1. 2006-06-16 Kai Vehmanen * libsofia-sip-ua interface v0 frozen (1.12.0), version to 0:0:0. 2005-11-28 Kai Vehmanen * /Doxyfile: Fixed the use of doxytags. Now a separate 'doxytags_MODNAME' file is created for each module. 2005-11-15 Kai Vehmanen * /Makefile.am: Changed to use the 'include_sofia_HEADERS' variable for listing public library headers. The variable is defined in the top-level configure.ac. 2005-10-27 Pekka Pessi * Always including stun library. M ./libsofia-sip-ua/Makefile.am -6 +3 * Added rule to make missing module libraries in libsofia-sip-ua/sofia.am M ./libsofia-sip-ua/sofia.am -1 +6 * Added LDFLAG -static to all test programs in their Makefile.am M ./libsofia-sip-ua/bnf/Makefile.am -1 +1 M ./libsofia-sip-ua/http/Makefile.am -2 +2 M ./libsofia-sip-ua/ipt/Makefile.am -1 +2 M ./libsofia-sip-ua/iptsec/Makefile.am +2 M ./libsofia-sip-ua/msg/Makefile.am -2 +2 M ./libsofia-sip-ua/nta/Makefile.am -1 +1 M ./libsofia-sip-ua/nth/Makefile.am +2 M ./libsofia-sip-ua/nua/Makefile.am +2 M ./libsofia-sip-ua/sdp/Makefile.am +3 M ./libsofia-sip-ua/sip/Makefile.am +4 M ./libsofia-sip-ua/soa/Makefile.am +2 M ./libsofia-sip-ua/sresolv/Makefile.am -2 +2 M ./libsofia-sip-ua/stun/Makefile.am -6 +1 2005-10-14 Pekka Pessi * Shell syntax exercise. M ./autogen.sh -4 +4 2005-10-13 Pekka Pessi * /Makefile.am: fixed COVERAGE_INPUT. 2005-10-13 Kai Vehmanen * /Makefile.am: Build all submodules as proper shared libraries (noinst_LTLIBRARIES). Fixes sf.net:#1264030. 2005-09-09 Pekka Pessi * darcs changes --from-tag pessi-darcs-1: Thu Sep 8 21:50:24 EEST 2005 Pekka.Pessi@nokia.com * There is no separate TLS test anymore. M ./tport/Makefile.am -1 +1 Thu Sep 8 21:36:46 EEST 2005 Pekka.Pessi@nokia.com * Logging. M ./nua/nua_stack.c -4 +2 Thu Sep 8 21:36:39 EEST 2005 Pekka.Pessi@nokia.com * Added tests for tport_convert_addr. M ./tport/tport_test.c +22 Thu Sep 8 21:36:27 EEST 2005 Pekka.Pessi@nokia.com * Fixed receiving empty SigComp message. M ./tport/tport.c +7 Thu Sep 8 21:32:48 EEST 2005 Pekka.Pessi@nokia.com * Updated ChangeLogs. M ./nta/ChangeLog -2 +10 Thu Sep 8 21:32:37 EEST 2005 Pekka.Pessi@nokia.com * Updated ChangeLog. M ./iptsec/ChangeLog +11 Thu Sep 8 21:31:16 EEST 2005 Pekka.Pessi@nokia.com * Added more tests. M ./nta/nta.c -2 +2 M ./nta/nta_test.c -2 +44 Thu Sep 8 21:30:19 EEST 2005 Pekka.Pessi@nokia.com * Handling changes in alias list. M ./nta/nta.c -9 +22 M ./nta/nta_test.c +1 Thu Sep 8 21:18:47 EEST 2005 Pekka.Pessi@nokia.com * Gcc4 fixes. M ./ipt/base64.c -1 +1 M ./iptsec/auth_module.c -1 +1 M ./iptsec/auth_plugin_delayed.c +4 M ./nua/nua_stack.c -1 +1 M ./nua/nua_tag.c -1 +1 M ./nua/nua_tag.h -5 +5 M ./su/htable2.h -1 +1 M ./su/su.c -1 +1 M ./tport/tport.c -7 +7 Thu Sep 8 21:16:39 EEST 2005 Pekka.Pessi@nokia.com * Added tests for tport_shutdown(). Do not assert() on invalid input. M ./tport/tport.c -2 M ./tport/tport_test.c +5 Thu Sep 8 21:13:18 EEST 2005 Pekka.Pessi@nokia.com * Log when password file is read. M ./iptsec/auth_module.c +3 Thu Sep 8 21:12:49 EEST 2005 Pekka.Pessi@nokia.com * Allow empty allow list. M ./iptsec/auth_module.c -1 +1 Thu Sep 8 21:12:26 EEST 2005 Pekka.Pessi@nokia.com * Use unsigned as auth_htable_t hash type. M ./iptsec/auth_module.c -5 +5 Thu Sep 8 21:10:23 EEST 2005 Pekka.Pessi@nokia.com * Added auth_digest_credentials(). Use opaque to match Authorization header. M ./iptsec/auth_digest_test.c -2 +3 M ./iptsec/auth_module.c -1 +78 M ./iptsec/auth_plugin.h +4 Thu Sep 8 21:07:57 EEST 2005 Pekka.Pessi@nokia.com * Fixed gcc4 problems with tag classes. M ./http/http_tag.h.in +3 M ./msg/msg_mime_protos.h.in +3 M ./sdp/sdp_tag.h +3 M ./su/su_tag_class.h +12 M ./su/su_tag_inline.h -1 +1 M ./url/url_tag_class.h +3 Thu Sep 8 21:06:22 EEST 2005 Pekka.Pessi@nokia.com * Added sip_security_client_select(). M ./sip/sip_util.c -37 +14 M ./sip/sip_util.h +4 Thu Sep 8 19:32:19 EEST 2005 Pekka.Pessi@nokia.com * Not using su_home_deinit() to destroy homes that are not initialized. M ./nth/nth_server.c -3 +2 M ./nua/nua.c -2 +1 M ./su/su_vector.c -2 +1 Thu Sep 8 19:06:31 EEST 2005 Pekka.Pessi@nokia.com * Moved function types to msg_types.h. M ./msg/msg_header.h -7 M ./msg/msg_types.h +9 Thu Sep 8 18:35:12 EEST 2005 Pekka.Pessi@nokia.com * Fixed su_clone_start() return value. M ./su/su_root.c -1 +1 Thu Sep 8 18:34:26 EEST 2005 Pekka.Pessi@nokia.com * Removed SIP_DLL_VAR. M ./sip/sip_dll.h -7 Thu Sep 8 18:29:27 EEST 2005 Pekka.Pessi@nokia.com * Avoid __func__. M ./sresolv/sresolv.c -3 +4 Thu Sep 8 18:29:09 EEST 2005 Pekka.Pessi@nokia.com * Fix includes. M ./nta/nta.c -2 +1 M ./sresolv/sresolv.c -4 +7 M ./sresolv/sresolv.h -1 +1 Thu Sep 8 18:26:35 EEST 2005 Pekka.Pessi@nokia.com * Using autoconf to figure out 64-bit types. Avoid off_t and 64-bit constants. M ../configure.ac +6 M ./nta/sl_read_payload.c -1 +1 M ./nua/nua_stack.c -6 +5 M ./sdp/sdp_parse.c -3 +2 M ./sdp/sdp_print.c -5 +5 M ./sip/validator.c -18 +18 M ./soa/soa.c -3 +4 M ./su/su_time.c -1 +1 M ./su/tstdef.h -3 +3 Thu Sep 8 18:17:58 EEST 2005 Pekka.Pessi@nokia.com * Using RETSIGTYPE. M ../configure.ac -3 +4 M ./nth/http-server.c -2 +2 M ./soa/test_soa.c -1 +3 M ./su/su_test.c -1 +1 M ./su/su_timer_test.c -1 +1 Thu Sep 8 18:13:35 EEST 2005 Pekka.Pessi@nokia.com * Fixed macro expansion problem with VC6 M ./nta/nta_test.c -2 +2 Thu Sep 8 18:12:45 EEST 2005 Pekka.Pessi@nokia.com * Compile without sresolv, too. M ./nta/nta.c -3 +5 Thu Sep 8 18:12:16 EEST 2005 Pekka.Pessi@nokia.com * Fixed const/non-const problems with gcc4/vc6. M ./msg/msg_mime.c -6 +6 M ./msg/msg_parser.c -1 +1 M ./nta/nta.c -4 +4 M ./sip/sip_basic.c -1 +1 M ./sip/sip_security.c -1 +1 M ./sip/sip_util.c -2 +2 M ./su/htable.h -10 +10 Thu Sep 8 18:06:04 EEST 2005 Pekka.Pessi@nokia.com * Moved msg_hclass_t definition into msg_types.h M ./msg/msg_header.h -37 M ./msg/msg_types.h +40 Thu Sep 8 18:05:32 EEST 2005 Pekka.Pessi@nokia.com * Silenced vc6 warning. M ./iptsec/auth_module.c -1 +1 Thu Sep 8 18:05:07 EEST 2005 Pekka.Pessi@nokia.com * Not using __func__. M ./iptsec/auth_digest.c -2 +2 Thu Sep 8 18:04:38 EEST 2005 Pekka.Pessi@nokia.com * Silenced gcc4 warning. M ./tport/tport.c -1 +1 Thu Sep 8 18:04:16 EEST 2005 Pekka.Pessi@nokia.com * Better following autoconf macros M ./tport/tport.c +9 Thu Sep 8 18:02:53 EEST 2005 Pekka.Pessi@nokia.com * Using TPORT_DLL. M ./tport/tport.h -10 +19 Thu Sep 8 18:01:58 EEST 2005 Pekka.Pessi@nokia.com * Not using IS_EXCLUDED_MASK. M ./url/url.c -1 +6 Thu Sep 8 18:01:17 EEST 2005 Pekka.Pessi@nokia.com * Explicitly using M ./msg/msg.c +2 M ./msg/msg_mclass.c +1 M ./msg/msg_mime.c +1 M ./msg/msg_parser.c +1 M ./nta/nta.c +3 M ./nth/nth_client.c +2 M ./nth/nth_server.c +2 M ./su/su_port.c +1 M ./su/su_proxy.c +1 M ./su/su_root.c +1 Thu Sep 8 17:54:28 EEST 2005 Pekka.Pessi@nokia.com * Using http_off_t instead of off_t. M ./http/http_basic.c -5 +5 Thu Sep 8 18:56:58 EEST 2005 Pekka.Pessi@nokia.com * Not using su_home_deinit(). M ./nua/nua.c -3 +2 Thu Sep 8 16:40:30 EEST 2005 Pekka.Pessi@nokia.com * Adding soa_asynch.c A ./soa/soa_asynch.c Thu Sep 8 03:23:00 EEST 2005 Pekka.Pessi@nokia.com * stab 2 at soa Added more functionality to soa. Stab at asynchronous API, too. M ./soa/Makefile.am -1 +2 M ./soa/soa.c -146 +564 M ./soa/soa.h -5 +24 M ./soa/soa_add.h -2 +5 M ./soa/soa_session.h -21 +48 M ./soa/soa_static.c -30 +89 M ./soa/soa_tag.c +64 M ./soa/test_soa.c -7 +224 M ./m4/sac-su2.m4 -1 +1 Thu Sep 8 03:12:28 EEST 2005 Pekka.Pessi@nokia.com * really run sdp tests Now really running SDP tests. M ./sdp/run-tests -1 +1 Thu Sep 8 03:11:35 EEST 2005 Pekka.Pessi@nokia.com * su_home_new and su_home_unref Added su_home_new() and su_home_unref(). Fixed su_home_mutex_lock() and su_home_mutex_unlock(). Slightly changed semantics of su_home_clone() versus su_home_threadsafe(). M ./http/http_test.c -6 +6 M ./msg/msg_test.c -2 +2 M ./su/htable_test.c +3 M ./su/su_alloc.c -173 +337 M ./su/su_alloc.h -10 +18 M ./su/su_alloc_lock.c -8 +31 M ./su/su_alloc_test.c -5 +12 Thu Sep 8 03:07:17 EEST 2005 Pekka.Pessi@nokia.com * More liberal sdp parsing for config files. Be more liberal when parsing config files (do not require v=, accept -1 as len argument). M ./sdp/sdp_parse.c -9 +25 Thu Sep 8 01:05:02 EEST 2005 Pekka.Pessi@nokia.com * su_msg_is_non_null Added su_msg_is_non_null(). M ./su/su_wait.h +11 Thu Sep 8 01:03:31 EEST 2005 Pekka.Pessi@nokia.com * sdp_parser_home Added sdp_parser_home() M ./sdp/sdp.h +2 M ./sdp/sdp_parse.c +10 2005-09-08 Kai Vehmanen * Makefile.am: Workaround for automake bug related to adding custom targets to RECURSIVE_TARGETS. 2005-08-25 Kai Vehmanen * Makefile.am: soa depends on ipt and sip, so has to be after them in SUBDIRS. 2005-08-17 Pekka Pessi * Fixed BEGIN()/END() pairs in test programs. 2005-08-04 Pekka Pessi * Added soa module. 2005-07-18 Kai Vehmanen * libsofia-sip-ua created. sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/Makefile.am000066400000000000000000000064311223300710500216120ustar00rootroot00000000000000# # Makefile.am for sofia-sip/libsofia-sip-ua # # Copyright (C) 2005,2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # # ref: http://www.gnu.org/software/automake/manual/automake.html AUTOMAKE_OPTIONS = foreign # select which optional sofia-sip modules have been enabled # in the build OPT_LIBADD = $(openssl_LIBS) OPT_SUBDIRS_STUN = OPT_SUBDIRS_HTTP = OPT_SUBDIRS_NTH = if HAVE_STUN OPT_LIBADD += stun/libstun.la OPT_SUBDIRS_STUN += stun endif if HAVE_NTH OPT_LIBADD += http/libhttp.la nth/libnth.la OPT_SUBDIRS_HTTP += http OPT_SUBDIRS_NTH += nth endif # note: order does matter in the subdir list SUBDIRS = su features bnf sresolv ipt sdp url msg sip $(OPT_SUBDIRS_HTTP) \ $(OPT_SUBDIRS_STUN) soa tport nta $(OPT_SUBDIRS_NTH) \ nea iptsec nua DIST_SUBDIRS = su features bnf sresolv ipt sdp url msg sip http \ stun soa tport nta nth \ nea iptsec nua docs DOXYGEN = doxygen lib_LTLIBRARIES = libsofia-sip-ua.la libsofia_sip_ua_la_SOURCES = libsofia_sip_ua_la_LIBADD = bnf/libbnf.la \ features/libfeatures.la \ ipt/libipt.la \ iptsec/libiptsec.la \ msg/libmsg.la \ nea/libnea.la \ nta/libnta.la \ nua/libnua.la \ sdp/libsdp.la \ sip/libsip.la \ soa/libsoa.la \ sresolv/libsresolv.la \ su/libsu.la \ tport/libtport.la \ url/liburl.la \ $(OPT_LIBADD) # set the libtool version info version:revision:age for libsofia-sip-ua # - soname to 'libsofia-sip-ua.so.(CUR-AGE)' libsofia_sip_ua_la_LDFLAGS = \ -version-info $(LIBVER_SOFIA_SIP_UA_CUR):$(LIBVER_SOFIA_SIP_UA_REV):$(LIBVER_SOFIA_SIP_UA_AGE) PHONY = doxygen built-sources include $(top_srcdir)/rules/recursive.am checklib: checklib-recursive $(lib_LTLIBRARIES) doxygen: built-sources @echo Generating empty doxytags @mkdir -p docs/html ; \ for d in $(DIST_SUBDIRS); do \ test -r $$d/Doxyfile || continue ; \ if ! test -r docs/$$d.doxytags ; then \ echo '' > docs/$$d.doxytags ; \ else \ sed '2,10s!index!'$$d'_index!' \ docs/$$d.doxytags > docs/$$d.doxytags.tmp && \ mv -f docs/$$d.doxytags.tmp docs/$$d.doxytags ; \ fi ; \ done @for d in $(DIST_SUBDIRS); do \ ( test -r $$d/Doxyfile && \ cd $$d > /dev/null && \ echo running ${DOXYGEN} first time in $$d && \ ${DOXYGEN} 2>&1 ) | \ egrep -v -i -e 'Warning: (unsupported (xml/)?html tag|unable to resolve reference|explicit link.*could not be resolved)' ; \ test -r docs/$$d.doxytags && \ sed '2,10s!index!'$$d'_index!' \ docs/$$d.doxytags > docs/$$d.doxytags.tmp && \ mv -f docs/$$d.doxytags.tmp docs/$$d.doxytags ; \ done @for d in $(DIST_SUBDIRS); do \ ( test -r $$d/Doxyfile && \ cd $$d > /dev/null && \ echo running ${DOXYGEN} second time in $$d && \ ${DOXYGEN} 2>&1 ) | \ egrep -v -i -e 'Warning: Unsupported (xml/)?html tag' ; \ test -r docs/$$d.doxytags && \ sed '2,10s!index!'$$d'_index!' \ docs/$$d.doxytags > docs/$$d.doxytags.tmp && \ mv -f docs/$$d.doxytags.tmp docs/$$d.doxytags ; \ done ${top_srcdir}/scripts/hide_emails.sh docs/html if HAVE_LCOV include $(top_srcdir)/rules/lcov.am endif include $(top_srcdir)/rules/silent.am .PHONY: $(PHONY) sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/Makefile.in000066400000000000000000001014251223300710500216220ustar00rootroot00000000000000# Makefile.in generated by automake 1.14 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 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 sofia-sip/libsofia-sip-ua # # Copyright (C) 2005,2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # # ref: http://www.gnu.org/software/automake/manual/automake.html # Recursive Makefile targets # -------------------------- # # Generate lcov output # # # Copyright (C) 2007 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # # Silent compilation w/ Automake 1.9 or 1.10 # ---------------------------------------------------------- # Automake 1.9.6 is not clever enough to override suffix rules within if # if SOFIA_COMPILE_SILENT VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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@ @HAVE_STUN_TRUE@am__append_1 = stun/libstun.la @HAVE_STUN_TRUE@am__append_2 = stun @HAVE_NTH_TRUE@am__append_3 = http/libhttp.la nth/libnth.la @HAVE_NTH_TRUE@am__append_4 = http @HAVE_NTH_TRUE@am__append_5 = nth DIST_COMMON = $(top_srcdir)/rules/recursive.am \ $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.am \ $(srcdir)/Makefile.in $(srcdir)/Makefile.am ChangeLog @HAVE_GENPNG_TRUE@@HAVE_LCOV_TRUE@am__append_6 = --frames @HAVE_LCOV_TRUE@am__append_7 = lcov lcov-report lcov-rerun clean-lcov covcheck uncovered subdir = libsofia-sip-ua ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(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)/m4/sac-coverage.m4 \ $(top_srcdir)/m4/sac-general.m4 \ $(top_srcdir)/m4/sac-openssl.m4 \ $(top_srcdir)/m4/sac-pkg-config.m4 $(top_srcdir)/m4/sac-su2.m4 \ $(top_srcdir)/m4/sac-tport.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libsofia-sip-ua/su/sofia-sip/su_configure.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)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) $(am__append_1) \ $(am__append_3) libsofia_sip_ua_la_DEPENDENCIES = bnf/libbnf.la \ features/libfeatures.la ipt/libipt.la iptsec/libiptsec.la \ msg/libmsg.la nea/libnea.la nta/libnta.la nua/libnua.la \ sdp/libsdp.la sip/libsip.la soa/libsoa.la \ sresolv/libsresolv.la su/libsu.la tport/libtport.la \ url/liburl.la $(am__DEPENDENCIES_2) am_libsofia_sip_ua_la_OBJECTS = libsofia_sip_ua_la_OBJECTS = $(am_libsofia_sip_ua_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 = libsofia_sip_ua_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsofia_sip_ua_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) -I$(top_builddir)/libsofia-sip-ua/su/sofia-sip 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) 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 = $(libsofia_sip_ua_la_SOURCES) DIST_SOURCES = $(libsofia_sip_ua_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 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 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)` CTAGS = ctags 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@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CHECK_CFLAGS = @CHECK_CFLAGS@ CHECK_LIBS = @CHECK_LIBS@ COVERAGE_FLAGS = @COVERAGE_FLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CWFLAG = @CWFLAG@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = doxygen DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV = @GCOV@ GENHTML = @GENHTML@ GENPNG = @GENPNG@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GLIB_VERSION = @GLIB_VERSION@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVER_SOFIA_SIP_UA_AGE = @LIBVER_SOFIA_SIP_UA_AGE@ LIBVER_SOFIA_SIP_UA_CUR = @LIBVER_SOFIA_SIP_UA_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_AGE = @LIBVER_SOFIA_SIP_UA_GLIB_AGE@ LIBVER_SOFIA_SIP_UA_GLIB_CUR = @LIBVER_SOFIA_SIP_UA_GLIB_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_REV = @LIBVER_SOFIA_SIP_UA_GLIB_REV@ LIBVER_SOFIA_SIP_UA_GLIB_SOVER = @LIBVER_SOFIA_SIP_UA_GLIB_SOVER@ LIBVER_SOFIA_SIP_UA_REV = @LIBVER_SOFIA_SIP_UA_REV@ LIBVER_SOFIA_SIP_UA_SOVER = @LIBVER_SOFIA_SIP_UA_SOVER@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MINGW_ENVIRONMENT = @MINGW_ENVIRONMENT@ MKDIR_P = @MKDIR_P@ MOSTLYCLEANFILES = @MOSTLYCLEANFILES@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ RANLIB = @RANLIB@ REPLACE_LIBADD = @REPLACE_LIBADD@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ SOFIA_GLIB_CFLAGS = @SOFIA_GLIB_CFLAGS@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ SOFIA_PLAT_CFLAGS = @SOFIA_PLAT_CFLAGS@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ VERSION = @VERSION@ VER_LIBSOFIA_SIP_UA_MAJOR_MINOR = @VER_LIBSOFIA_SIP_UA_MAJOR_MINOR@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ include_sofiadir = @include_sofiadir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ openssl_CFLAGS = @openssl_CFLAGS@ openssl_LIBS = @openssl_LIBS@ 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@ AUTOMAKE_OPTIONS = foreign # select which optional sofia-sip modules have been enabled # in the build OPT_LIBADD = $(openssl_LIBS) $(am__append_1) $(am__append_3) OPT_SUBDIRS_STUN = $(am__append_2) OPT_SUBDIRS_HTTP = $(am__append_4) OPT_SUBDIRS_NTH = $(am__append_5) # note: order does matter in the subdir list SUBDIRS = su features bnf sresolv ipt sdp url msg sip $(OPT_SUBDIRS_HTTP) \ $(OPT_SUBDIRS_STUN) soa tport nta $(OPT_SUBDIRS_NTH) \ nea iptsec nua DIST_SUBDIRS = su features bnf sresolv ipt sdp url msg sip http \ stun soa tport nta nth \ nea iptsec nua docs lib_LTLIBRARIES = libsofia-sip-ua.la libsofia_sip_ua_la_SOURCES = libsofia_sip_ua_la_LIBADD = bnf/libbnf.la \ features/libfeatures.la \ ipt/libipt.la \ iptsec/libiptsec.la \ msg/libmsg.la \ nea/libnea.la \ nta/libnta.la \ nua/libnua.la \ sdp/libsdp.la \ sip/libsip.la \ soa/libsoa.la \ sresolv/libsresolv.la \ su/libsu.la \ tport/libtport.la \ url/liburl.la \ $(OPT_LIBADD) # set the libtool version info version:revision:age for libsofia-sip-ua # - soname to 'libsofia-sip-ua.so.(CUR-AGE)' libsofia_sip_ua_la_LDFLAGS = \ -version-info $(LIBVER_SOFIA_SIP_UA_CUR):$(LIBVER_SOFIA_SIP_UA_REV):$(LIBVER_SOFIA_SIP_UA_AGE) PHONY = doxygen built-sources $(am__append_7) SOFIA_RECURSIVE = \ valcheck-recursive \ checklib-recursive SOFIA_DIST_RECURSIVE = \ built-sources-recursive \ clean-built-sources-recursive # Scripts @HAVE_LCOV_TRUE@LCOV_UNCOVERED = ${top_srcdir}/scripts/uncovered @HAVE_LCOV_TRUE@LCOV_REPORT = ${top_srcdir}/scripts/lcov-report # Report directory @HAVE_LCOV_TRUE@lcovdir = ${top_builddir}/lcov # Options @HAVE_LCOV_TRUE@GENHTML_OPTIONS = --show-details --legend \ @HAVE_LCOV_TRUE@ $(am__append_6) # Fancy shell command that expands to directory relative to top_builddir @HAVE_LCOV_TRUE@expand_subdir = `pwd|sed "s'\`cd ${top_builddir};pwd\`''"` SOFIA_SILENT = @ LIBTOOL_FLAGS = --silent # From Automake 1.9.6 - LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(LIBTOOL_FLAGS) \ $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) LINK = ${SOFIA_SILENT}test "${SOFIA_SILENT}" != @ || echo ' LINK $@'; \ $(LIBTOOL) --tag=CC --mode=link $(LIBTOOL_FLAGS) \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ all: all-recursive .SUFFIXES: .SUFFIXES: .c .lo .o $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/recursive.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.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) --foreign libsofia-sip-ua/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign libsofia-sip-ua/Makefile .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/rules/recursive.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.am: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): 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}; \ } libsofia-sip-ua.la: $(libsofia_sip_ua_la_OBJECTS) $(libsofia_sip_ua_la_DEPENDENCIES) $(EXTRA_libsofia_sip_ua_la_DEPENDENCIES) $(AM_V_CCLD)$(libsofia_sip_ua_la_LINK) -rpath $(libdir) $(libsofia_sip_ua_la_OBJECTS) $(libsofia_sip_ua_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 # 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: $(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) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(libdir)"; 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: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) 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." @HAVE_LCOV_FALSE@clean-local: clean: clean-recursive clean-am: clean-generic clean-libLTLIBRARIES clean-libtool clean-local \ mostlyclean-am distclean: distclean-recursive -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-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-libLTLIBRARIES 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-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-libLTLIBRARIES .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-libLTLIBRARIES \ clean-libtool clean-local 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-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-libLTLIBRARIES all-recursive: built-sources-recursive built-sources: built-sources-recursive clean-built-sources: clean-built-sources-recursive valcheck: valcheck-recursive $(SOFIA_RECURSIVE): @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$target) \ || eval $$failcom; \ done; \ test -z "$$fail" $(SOFIA_DIST_RECURSIVE): @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ target=`echo $@ | sed s/-recursive//`; \ list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$target) \ || eval $$failcom; \ done; \ test -z "$$fail" checklib: checklib-recursive $(lib_LTLIBRARIES) doxygen: built-sources @echo Generating empty doxytags @mkdir -p docs/html ; \ for d in $(DIST_SUBDIRS); do \ test -r $$d/Doxyfile || continue ; \ if ! test -r docs/$$d.doxytags ; then \ echo '' > docs/$$d.doxytags ; \ else \ sed '2,10s!index!'$$d'_index!' \ docs/$$d.doxytags > docs/$$d.doxytags.tmp && \ mv -f docs/$$d.doxytags.tmp docs/$$d.doxytags ; \ fi ; \ done @for d in $(DIST_SUBDIRS); do \ ( test -r $$d/Doxyfile && \ cd $$d > /dev/null && \ echo running ${DOXYGEN} first time in $$d && \ ${DOXYGEN} 2>&1 ) | \ egrep -v -i -e 'Warning: (unsupported (xml/)?html tag|unable to resolve reference|explicit link.*could not be resolved)' ; \ test -r docs/$$d.doxytags && \ sed '2,10s!index!'$$d'_index!' \ docs/$$d.doxytags > docs/$$d.doxytags.tmp && \ mv -f docs/$$d.doxytags.tmp docs/$$d.doxytags ; \ done @for d in $(DIST_SUBDIRS); do \ ( test -r $$d/Doxyfile && \ cd $$d > /dev/null && \ echo running ${DOXYGEN} second time in $$d && \ ${DOXYGEN} 2>&1 ) | \ egrep -v -i -e 'Warning: Unsupported (xml/)?html tag' ; \ test -r docs/$$d.doxytags && \ sed '2,10s!index!'$$d'_index!' \ docs/$$d.doxytags > docs/$$d.doxytags.tmp && \ mv -f docs/$$d.doxytags.tmp docs/$$d.doxytags ; \ done ${top_srcdir}/scripts/hide_emails.sh docs/html # # Generate pretty coverage report (unless it has been already done) # @HAVE_LCOV_TRUE@lcov: @HAVE_LCOV_TRUE@ @-test -r ${lcovdir}${expand_subdir}/lcov.info \ @HAVE_LCOV_TRUE@ || make lcov-report # Generate pretty coverage report based on current coverage data @HAVE_LCOV_TRUE@lcov-report: @HAVE_LCOV_TRUE@ sub=${expand_subdir} odir=${lcovdir}$$sub ; \ @HAVE_LCOV_TRUE@ rm -rf $$odir ; mkdir -p $$odir && \ @HAVE_LCOV_TRUE@ ${LCOV_REPORT} ${GENHTML_OPTIONS} \ @HAVE_LCOV_TRUE@ --title "${PACKAGE_NAME}-${PACKAGE_VERSION}$$sub" \ @HAVE_LCOV_TRUE@ --srcdir=${srcdir} -o $$odir # Rerun checks before generating report @HAVE_LCOV_TRUE@lcov-rerun: clean-lcov @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) lcov-report # Show all uncovered lines as errors @HAVE_LCOV_TRUE@uncovered: @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} # Run check in current dir and show all uncovered lines as errors @HAVE_LCOV_TRUE@covcheck: @HAVE_LCOV_TRUE@ -find . -name "*.gcda" | xargs rm -rf @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} @HAVE_LCOV_TRUE@clean-local:: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true @HAVE_LCOV_TRUE@clean-lcov: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true # Rules from depend2.am (GENERIC = TRUE, SUBDIROBJ = FALSE, %FASTDEP% = am_fastdepCC) silenced. .c.o: @test "${SOFIA_SILENT}" != @ || echo ' COMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(COMPILE) -c -o $@ $< .c.lo: @test "${SOFIA_SILENT}" != @ || echo ' LTCOMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(LTCOMPILE) -c -o $@ $< # endif .PHONY: $(PHONY) # 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: sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/bnf/000077500000000000000000000000001223300710500203175ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/bnf/ChangeLog000066400000000000000000000003271223300710500220730ustar00rootroot000000000000002006-06-15 Kai Vehmanen * sofia-sip/hostdomain.h (host_is_local): Function added. 2005-07-18 Kai Vehmanen * Initial import of the module to Sofia-SIP tree. sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/bnf/Doxyfile.in000066400000000000000000000005251223300710500224340ustar00rootroot00000000000000PROJECT_NAME = "bnf" OUTPUT_DIRECTORY = ../docs/html/bnf INPUT = @srcdir@/bnf.docs @srcdir@/sofia-sip @srcdir@ . @INCLUDE_PATH = . @srcdir@ @INCLUDE = ../docs/Doxyfile.conf TAGFILES += ../docs/su.doxytags=../su GENERATE_TAGFILE = ../docs/bnf.doxytags PREDEFINED += "static=" MAX_INITIALIZER_LINES = 2 sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/bnf/Makefile.am000066400000000000000000000022051223300710500223520ustar00rootroot00000000000000# # Makefile.am for bnf module # # Copyright (C) 2005,2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # ---------------------------------------------------------------------- # Header paths INCLUDES = -I$(srcdir)/../su -I../su # ---------------------------------------------------------------------- # Build targets noinst_LTLIBRARIES = libbnf.la check_PROGRAMS = torture_bnf # ---------------------------------------------------------------------- # Rules for building the targets nobase_include_sofia_HEADERS = sofia-sip/bnf.h sofia-sip/hostdomain.h libbnf_la_SOURCES = bnf.c COVERAGE_INPUT = $(libbnf_la_SOURCES) $(include_sofia_HEADERS) LDADD = libbnf.la ../su/libsu.la torture_bnf_LDFLAGS = -static # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST = bnf.docs # ---------------------------------------------------------------------- # Tests TESTS = torture_bnf # ---------------------------------------------------------------------- # Sofia specific rules include $(top_srcdir)/rules/sofia.am sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/bnf/Makefile.in000066400000000000000000001314541223300710500223740ustar00rootroot00000000000000# Makefile.in generated by automake 1.14 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 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 bnf module # # Copyright (C) 2005,2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # ---------------------------------------------------------------------- # Header paths # common Makefile targets for libsofia-sip-ua(-glib) modules # ---------------------------------------------------------- # # run tests with valgrind # # Copyright (C) 2007 Nokia Corporation. # 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 file contains free software from Makefile.in by the Free Software # Foundation: # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 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. # # Generate lcov output # # # Copyright (C) 2007 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # # Silent compilation w/ Automake 1.9 or 1.10 # ---------------------------------------------------------- # Automake 1.9.6 is not clever enough to override suffix rules within if # if SOFIA_COMPILE_SILENT VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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@ check_PROGRAMS = torture_bnf$(EXEEXT) TESTS = torture_bnf$(EXEEXT) DIST_COMMON = $(top_srcdir)/rules/sofia.am \ $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am \ $(top_srcdir)/rules/silent.am $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(srcdir)/Doxyfile.in \ $(top_srcdir)/depcomp $(nobase_include_sofia_HEADERS) \ $(top_srcdir)/test-driver ChangeLog # Use with --enable-ndebug @NDEBUG_TRUE@am__append_1 = -DNDEBUG @HAVE_GENPNG_TRUE@@HAVE_LCOV_TRUE@am__append_2 = --frames @HAVE_LCOV_TRUE@am__append_3 = lcov lcov-report lcov-rerun clean-lcov covcheck uncovered subdir = libsofia-sip-ua/bnf ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(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)/m4/sac-coverage.m4 \ $(top_srcdir)/m4/sac-general.m4 \ $(top_srcdir)/m4/sac-openssl.m4 \ $(top_srcdir)/m4/sac-pkg-config.m4 $(top_srcdir)/m4/sac-su2.m4 \ $(top_srcdir)/m4/sac-tport.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libsofia-sip-ua/su/sofia-sip/su_configure.h CONFIG_CLEAN_FILES = Doxyfile CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libbnf_la_LIBADD = am_libbnf_la_OBJECTS = bnf.lo libbnf_la_OBJECTS = $(am_libbnf_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 = torture_bnf_SOURCES = torture_bnf.c torture_bnf_OBJECTS = torture_bnf.$(OBJEXT) torture_bnf_LDADD = $(LDADD) am__DEPENDENCIES_1 = torture_bnf_DEPENDENCIES = libbnf.la ../su/libsu.la \ $(am__DEPENDENCIES_1) torture_bnf_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(torture_bnf_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) -I$(top_builddir)/libsofia-sip-ua/su/sofia-sip depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f 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) 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 = $(libbnf_la_SOURCES) torture_bnf.c DIST_SOURCES = $(libbnf_la_SOURCES) torture_bnf.c 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)$(include_sofiadir)" HEADERS = $(nobase_include_sofia_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)` 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=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ 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_DRIVER = $(SHELL) $(top_srcdir)/test-driver 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) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CHECK_CFLAGS = @CHECK_CFLAGS@ CHECK_LIBS = @CHECK_LIBS@ COVERAGE_FLAGS = @COVERAGE_FLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CWFLAG = @CWFLAG@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV = @GCOV@ GENHTML = @GENHTML@ GENPNG = @GENPNG@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GLIB_VERSION = @GLIB_VERSION@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVER_SOFIA_SIP_UA_AGE = @LIBVER_SOFIA_SIP_UA_AGE@ LIBVER_SOFIA_SIP_UA_CUR = @LIBVER_SOFIA_SIP_UA_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_AGE = @LIBVER_SOFIA_SIP_UA_GLIB_AGE@ LIBVER_SOFIA_SIP_UA_GLIB_CUR = @LIBVER_SOFIA_SIP_UA_GLIB_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_REV = @LIBVER_SOFIA_SIP_UA_GLIB_REV@ LIBVER_SOFIA_SIP_UA_GLIB_SOVER = @LIBVER_SOFIA_SIP_UA_GLIB_SOVER@ LIBVER_SOFIA_SIP_UA_REV = @LIBVER_SOFIA_SIP_UA_REV@ LIBVER_SOFIA_SIP_UA_SOVER = @LIBVER_SOFIA_SIP_UA_SOVER@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MINGW_ENVIRONMENT = @MINGW_ENVIRONMENT@ MKDIR_P = @MKDIR_P@ MOSTLYCLEANFILES = @MOSTLYCLEANFILES@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ RANLIB = @RANLIB@ REPLACE_LIBADD = @REPLACE_LIBADD@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ SOFIA_GLIB_CFLAGS = @SOFIA_GLIB_CFLAGS@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ SOFIA_PLAT_CFLAGS = @SOFIA_PLAT_CFLAGS@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ VERSION = @VERSION@ VER_LIBSOFIA_SIP_UA_MAJOR_MINOR = @VER_LIBSOFIA_SIP_UA_MAJOR_MINOR@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ include_sofiadir = @include_sofiadir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ openssl_CFLAGS = @openssl_CFLAGS@ openssl_LIBS = @openssl_LIBS@ 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@ INCLUDES = -I$(srcdir)/../su -I../su # ---------------------------------------------------------------------- # Build targets noinst_LTLIBRARIES = libbnf.la # ---------------------------------------------------------------------- # Rules for building the targets nobase_include_sofia_HEADERS = sofia-sip/bnf.h sofia-sip/hostdomain.h libbnf_la_SOURCES = bnf.c COVERAGE_INPUT = $(libbnf_la_SOURCES) $(include_sofia_HEADERS) LDADD = libbnf.la ../su/libsu.la $(openssl_LIBS) torture_bnf_LDFLAGS = -static # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST = bnf.docs sofiasrcdir = ${top_srcdir}/libsofia-sip-ua sofiabuilddir = ${top_builddir}/libsofia-sip-ua AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(SOFIA_CFLAGS) \ $(openssl_CFLAGS) $(SOFIA_PLAT_CFLAGS) $(am__append_1) SOFIA_COVERAGE = $(COVERAGE_FLAGS) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files TAG_AWK = ${sofiasrcdir}/su/tag_dll.awk SUFFIXES = _tag_ref.c _tag.c INTERNAL_INCLUDES = \ -I${sofiasrcdir}/features -I${sofiabuilddir}/features \ -I${sofiasrcdir}/ipt -I${sofiabuilddir}/ipt \ -I${sofiasrcdir}/iptsec -I${sofiabuilddir}/iptsec \ -I${sofiasrcdir}/bnf -I${sofiabuilddir}/bnf \ -I${sofiasrcdir}/http -I${sofiabuilddir}/http \ -I${sofiasrcdir}/msg -I${sofiabuilddir}/msg \ -I${sofiasrcdir}/nth -I${sofiabuilddir}/nth \ -I${sofiasrcdir}/nta -I${sofiabuilddir}/nta \ -I${sofiasrcdir}/nea -I${sofiabuilddir}/nea \ -I${sofiasrcdir}/nua -I${sofiabuilddir}/nua \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sdp -I${sofiabuilddir}/sdp \ -I${sofiasrcdir}/sip -I${sofiabuilddir}/sip \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sresolv -I${sofiabuilddir}/sresolv \ -I${sofiasrcdir}/tport -I${sofiabuilddir}/tport \ -I${sofiasrcdir}/stun -I${sofiabuilddir}/stun \ -I${sofiasrcdir}/url -I${sofiabuilddir}/url \ -I${sofiasrcdir}/su -I${sofiabuilddir}/su PHONY = built-sources clean-built-sources $(am__append_3) VALGRIND = valgrind VALGRINDFLAGS = --tool=memcheck # Scripts @HAVE_LCOV_TRUE@LCOV_UNCOVERED = ${top_srcdir}/scripts/uncovered @HAVE_LCOV_TRUE@LCOV_REPORT = ${top_srcdir}/scripts/lcov-report # Report directory @HAVE_LCOV_TRUE@lcovdir = ${top_builddir}/lcov # Options @HAVE_LCOV_TRUE@GENHTML_OPTIONS = --show-details --legend \ @HAVE_LCOV_TRUE@ $(am__append_2) # Fancy shell command that expands to directory relative to top_builddir @HAVE_LCOV_TRUE@expand_subdir = `pwd|sed "s'\`cd ${top_builddir};pwd\`''"` SOFIA_SILENT = @ LIBTOOL_FLAGS = --silent # From Automake 1.9.6 - LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(LIBTOOL_FLAGS) \ $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) LINK = ${SOFIA_SILENT}test "${SOFIA_SILENT}" != @ || echo ' LINK $@'; \ $(LIBTOOL) --tag=CC --mode=link $(LIBTOOL_FLAGS) \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ all: all-am .SUFFIXES: .SUFFIXES: _tag_ref.c _tag.c .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.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 libsofia-sip-ua/bnf/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu libsofia-sip-ua/bnf/Makefile .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.am: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): Doxyfile: $(top_builddir)/config.status $(srcdir)/Doxyfile.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ 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}; \ } libbnf.la: $(libbnf_la_OBJECTS) $(libbnf_la_DEPENDENCIES) $(EXTRA_libbnf_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libbnf_la_OBJECTS) $(libbnf_la_LIBADD) $(LIBS) 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 torture_bnf$(EXEEXT): $(torture_bnf_OBJECTS) $(torture_bnf_DEPENDENCIES) $(EXTRA_torture_bnf_DEPENDENCIES) @rm -f torture_bnf$(EXEEXT) $(AM_V_CCLD)$(torture_bnf_LINK) $(torture_bnf_OBJECTS) $(torture_bnf_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bnf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/torture_bnf.Po@am__quote@ .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.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) '$<'` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-nobase_include_sofiaHEADERS: $(nobase_include_sofia_HEADERS) @$(NORMAL_INSTALL) @list='$(nobase_include_sofia_HEADERS)'; test -n "$(include_sofiadir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(include_sofiadir)'"; \ $(MKDIR_P) "$(DESTDIR)$(include_sofiadir)" || exit 1; \ fi; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo " $(MKDIR_P) '$(DESTDIR)$(include_sofiadir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(include_sofiadir)/$$dir"; }; \ echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(include_sofiadir)/$$dir'"; \ $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(include_sofiadir)/$$dir" || exit $$?; }; \ done uninstall-nobase_include_sofiaHEADERS: @$(NORMAL_UNINSTALL) @list='$(nobase_include_sofia_HEADERS)'; test -n "$(include_sofiadir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ dir='$(DESTDIR)$(include_sofiadir)'; $(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; \ else \ 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 $(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 $$? torture_bnf.log: torture_bnf$(EXEEXT) @p='torture_bnf$(EXEEXT)'; \ b='torture_bnf'; \ $(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: $(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) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(include_sofiadir)"; 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 "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) -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: 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) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." @HAVE_LCOV_FALSE@clean-local: clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libtool clean-local \ clean-noinstLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -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-nobase_include_sofiaHEADERS 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 -rf ./$(DEPDIR) -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-nobase_include_sofiaHEADERS .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libtool clean-local \ 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-nobase_include_sofiaHEADERS 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 \ uninstall-nobase_include_sofiaHEADERS built-sources: $(BUILT_SOURCES) clean-built-sources: -rm -rf $(BUILT_SOURCES) $(BUILT_SOURCES:%=$(srcdir)/%) *_tag_ref.c: $(TAG_AWK) _tag.c_tag_ref.c: $(AWK) -f $(TAG_AWK) NODLL=1 $(TAG_DLL_FLAGS) REF=$@ $< ../bnf/libbnf.la ../http/libhttp.la ../ipt/libipt.la ../iptsec/libiptsec.la \ ../msg/libmsg.la ../nea/libnea.la ../nta/libnta.la ../nth/libnth.la \ ../nua/libnua.la ../sdp/libsdp.la ../sip/libsip.la ../soa/libsoa.la \ ../sresolv/libsresolv.la ../stun/libstun.la ../su/libsu.la \ ../tport/libtport.la ../url/liburl.la: cd $(@D) && $(MAKE) $(@F) checklib: $(noinst_LTLIBRARIES) $(check_LTLIBRARIES) valcheck: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) valcheck-am valcheck-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS # Run tests with valgrind in valcheck-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ list='$(TESTS)'; \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ if case $$tst in \ run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ $${dir}$$tst ;; \ esac ; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ echo "XPASS: $$tst"; \ ;; \ *) \ echo "PASS: $$tst"; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xfail=`expr $$xfail + 1`; \ echo "XFAIL: $$tst"; \ ;; \ *) \ failed=`expr $$failed + 1`; \ echo "FAIL: $$tst"; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ echo "SKIP: $$tst"; \ fi; \ done; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="All $$all tests passed"; \ else \ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all tests failed"; \ else \ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ skipped="($$skip tests were not run)"; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ report=""; \ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ report="Please report to $(PACKAGE_BUGREPORT)"; \ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ echo "$$dashes"; \ echo "$$banner"; \ test -z "$$skipped" || echo "$$skipped"; \ test -z "$$report" || echo "$$report"; \ echo "$$dashes"; \ test "$$failed" -eq 0; \ else :; fi # # Generate pretty coverage report (unless it has been already done) # @HAVE_LCOV_TRUE@lcov: @HAVE_LCOV_TRUE@ @-test -r ${lcovdir}${expand_subdir}/lcov.info \ @HAVE_LCOV_TRUE@ || make lcov-report # Generate pretty coverage report based on current coverage data @HAVE_LCOV_TRUE@lcov-report: @HAVE_LCOV_TRUE@ sub=${expand_subdir} odir=${lcovdir}$$sub ; \ @HAVE_LCOV_TRUE@ rm -rf $$odir ; mkdir -p $$odir && \ @HAVE_LCOV_TRUE@ ${LCOV_REPORT} ${GENHTML_OPTIONS} \ @HAVE_LCOV_TRUE@ --title "${PACKAGE_NAME}-${PACKAGE_VERSION}$$sub" \ @HAVE_LCOV_TRUE@ --srcdir=${srcdir} -o $$odir # Rerun checks before generating report @HAVE_LCOV_TRUE@lcov-rerun: clean-lcov @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) lcov-report # Show all uncovered lines as errors @HAVE_LCOV_TRUE@uncovered: @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} # Run check in current dir and show all uncovered lines as errors @HAVE_LCOV_TRUE@covcheck: @HAVE_LCOV_TRUE@ -find . -name "*.gcda" | xargs rm -rf @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} @HAVE_LCOV_TRUE@clean-local:: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true @HAVE_LCOV_TRUE@clean-lcov: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true # Rules from depend2.am (GENERIC = TRUE, SUBDIROBJ = FALSE, %FASTDEP% = am_fastdepCC) silenced. .c.o: @test "${SOFIA_SILENT}" != @ || echo ' COMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(COMPILE) -c -o $@ $< .c.lo: @test "${SOFIA_SILENT}" != @ || echo ' LTCOMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(LTCOMPILE) -c -o $@ $< # endif # ---------------------------------------------------------------------- # Sofia specific rules # 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: sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/bnf/bnf.c000066400000000000000000000521451223300710500212370ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005,2006 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE bnf.c * @brief Character syntax table for HTTP-like protocols. * * @author Pekka Pessi * @author Kai Vehmanen * * @date Created: Thu Jun 8 19:28:55 2000 ppessi */ #include "config.h" #include "sofia-sip/bnf.h" #include "sofia-sip/su_string.h" #include #include #define ws bnf_ws #define crlf bnf_crlf #define alpha bnf_alpha #define digit bnf_mark|bnf_token0|bnf_safe #define sep bnf_separator #define msep bnf_mark|bnf_separator #define psep bnf_param0|bnf_separator #define tok bnf_token0 #define mtok bnf_mark|bnf_token0 #define smtok bnf_mark|bnf_token0|bnf_safe #define safe bnf_safe /** Table for determining class of a character */ unsigned char const _bnf_table[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, ws, crlf, 0, 0, crlf, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ws, mtok, sep, 0, safe, mtok, 0, mtok, /* !"#$%&' */ msep, msep, mtok, tok, sep, smtok, smtok, psep, /* ()*+,-./ */ digit, digit, digit, digit, digit, digit, digit, digit, /* 01234567 */ digit, digit, psep, sep, sep, sep, sep, sep, /* 89:;<=>? */ sep, alpha, alpha, alpha, alpha, alpha, alpha, alpha, /* @ABCDEFG */ alpha, alpha, alpha, alpha, alpha, alpha, alpha, alpha, /* HIJKLMNO */ alpha, alpha, alpha, alpha, alpha, alpha, alpha, alpha, /* PQRSTUVW */ alpha, alpha, alpha, psep, sep, psep, 0, smtok, /* XYZ[\]^_ */ tok, alpha, alpha, alpha, alpha, alpha, alpha, alpha, /* `abcdefg */ alpha, alpha, alpha, alpha, alpha, alpha, alpha, alpha, /* hijklmno */ alpha, alpha, alpha, alpha, alpha, alpha, alpha, alpha, /* pqrstuvw */ alpha, alpha, alpha, sep, 0, sep, mtok, 0, /* xyz{|}~ */ }; #if 0 /* This escaped lab */ #define BM(c, m00, m32, m64, m96) \ ((c < 64) \ ? ((c < 32) \ ? (m00 & (1 << (31 - c))) \ : (m32 & (1 << (63 - c)))) \ : ((c < 96) \ ? (m64 & (1 << (95 - c))) \ : (m96 & (1 << (127 - c))))) /** Span of a token */ size_t bnf_span_token(char const *s) { char const *e = s; unsigned const m32 = 0x4536FFC0U, m64 = 0x7FFFFFE1U, m96 = 0xFFFFFFE2U; while (BM(*e, 0, m32, m64, m96)) e++; return e - s; } /** Span of a token */ size_t bnf_span_token4(char const *s) { char const *e = s; while (_bnf_table[(unsigned char)(*e)] & bnf_token) e++; return e - s; } char * bnf_span_token_end(char const *s) { return (char *)s; } #endif /** Return length of decimal-octet */ su_inline int span_ip4_octet(char const *host) { /* decimal-octet = DIGIT / DIGIT DIGIT / (("0"/"1") 2*(DIGIT)) / ("2" ("0"/"1"/"2"/"3"/"4") DIGIT) / ("2" "5" ("0"/"1"/"2"/"3"/"4"/"5")) */ if (!IS_DIGIT(host[0])) return 0; /* DIGIT */ if (!IS_DIGIT(host[1])) return 1; if (host[0] == '2') { /* ("2" "5" ("0"/"1"/"2"/"3"/"4"/"5")) */ if (host[1] == '5' && host[2] >= '0' && host[2] <= '5') return 3; /* ("2" ("0"/"1"/"2"/"3"/"4") DIGIT) */ if (host[1] >= '0' && host[1] <= '4' && host[2] >= '0' && host[2] <= '9') return 3; } else if (host[0] == '0' || host[0] == '1') { if (IS_DIGIT(host[2])) /* ("1" 2*(DIGIT)) ... or "0" 2*(DIGIT) */ return 3; } /* POS-DIGIT DIGIT */ return 2; } /** Return length of valid IP4 address */ static int span_canonic_ip4_address(char const *host, int *return_canonize) { int n, len, canonize = 0; if (host == NULL) return 0; /* IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet */ len = span_ip4_octet(host); if (len == 0 || host[len] != '.') return 0; if (len > 1 && host[0] == '0') canonize = 1; n = len + 1; len = span_ip4_octet(host + n); if (len == 0 || host[n + len] != '.') return 0; if (len > 1 && host[n] == '0') canonize = 1; n += len + 1; len = span_ip4_octet(host + n); if (len == 0 || host[n + len] != '.') return 0; if (len > 1 && host[n] == '0') canonize = 1; n += len + 1; len = span_ip4_octet(host + n); if (len == 0 || IS_DIGIT(host[n + len]) || host[n + len] == '.') return 0; if (len > 1 && host[n] == '0') canonize = 1; n += len; if (canonize && return_canonize) *return_canonize = 1; return n; } /** Return length of valid IP4 address. * * Note that we accept here up to two leading zeroes * which makes "dotted decimal" notation ambiguous: * 127.000.000.001 is interpreted same as 127.0.0.1 * * Note that traditionally IP address octets starting * with zero have been interpreted as octal: * 172.055.055.001 has been same as 172.45.45.1 * * @b However, we interpret them as @b decimal, * 172.055.055.001 is same as 172.55.55.1. */ int span_ip4_address(char const *host) { return span_canonic_ip4_address(host, NULL); } /** Scan and canonize a valid IP4 address. */ int scan_ip4_address(char **inout_host) { char *src = *inout_host, *dst = src; issize_t n; int canonize = 0; if (src == NULL) return -1; n = span_canonic_ip4_address(src, &canonize); if (n == 0) return -1; *inout_host += n; if (!canonize) return n; for (;;) { char c = *dst++ = *src++; if (IS_DIGIT(*src)) { if (canonize && c == '0') dst--; else if (c == '.') canonize = 1; else canonize = 0; } else if (*src != '.') { break; } } *dst = '\0'; return n; } /** Return length of hex4 */ su_inline int span_hex4(char const *host) { if (!IS_HEX(host[0])) return 0; if (!IS_HEX(host[1])) return 1; if (!IS_HEX(host[2])) return 2; if (!IS_HEX(host[3])) return 3; return 4; } /** Return length of valid IP6 address */ su_inline int span_canonic_ip6_address(char const *host, int *return_canonize, char *hexparts[9]) { int n = 0, len, hex4, doublecolon = 0, canonize = 0; /* IPv6address = hexpart [ ":" IPv4address ] hexpart = hexseq / hexseq "::" [ hexseq ] / "::" [ hexseq ] hexseq = hex4 *( ":" hex4) hex4 = 1*4HEXDIG There is at most 8 hex4, 6 hex4 if IPv4address is included. */ if (host == NULL) return 0; for (hex4 = 0; hex4 < 8; ) { len = span_hex4(host + n); if (return_canonize) { if ((len > 1 && host[n + 1] == '0') || host[n] == '0') canonize = 1; if (hexparts) hexparts[hex4 + doublecolon] = (char *)(host + n); } if (host[n + len] == ':') { if (len != 0) { hex4++; n += len + 1; if (!doublecolon && host[n] == ':') { if (return_canonize && hexparts) { hexparts[hex4] = (char *)(host + n - 1); } doublecolon++, n++; } } else if (n == 0 && host[1] == ':') { doublecolon++, n = 2; } else break; } else if (host[n + len] == '.') { len = span_canonic_ip4_address(host + n, return_canonize); if (len == 0 || hex4 > 6 || !(doublecolon || hex4 == 6)) return 0; if (canonize && return_canonize) *return_canonize = 1; return n + len; } else { if (len != 0) hex4++; n += len; break; } } if (hex4 != 8 && !doublecolon) return 0; if (IS_HEX(host[n]) || host[n] == ':') return 0; if (canonize && return_canonize) *return_canonize = canonize; return n; } /** Canonize scanned IP6 address. * * @retval Length of canonized IP6 address. */ su_inline int canonize_ip6_address(char *host, char *hexparts[9]) { char *dst, *hex, *ip4 = NULL; int i, doublecolon, j, maxparts, maxspan, span, len; char buf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; /* Canonic representation has fewest chars - except for mapped/compatible IP4 addresses, like ::15.21.117.42 or ::ffff:15.21.117.42 which have non-canonic forms of ::f15:752a or ::ffff:f15:752a => we just canonize hexparts and ip4part separately and select optimal place for doublecolon (with expection of ::1 and ::, which are canonized) */ for (i = 0, doublecolon = -1; i < 9; i++) { hex = hexparts[i]; if (!hex) break; if (hex[0] == ':') doublecolon = i; while (hex[0] == '0' && IS_HEX(hex[1])) hex++; hexparts[i] = hex; } assert(i > 0); if (hexparts[i - 1][span_hex4(hexparts[i - 1])] == '.') ip4 = hexparts[--i]; maxparts = ip4 ? 6 : 8; if (doublecolon >= 0) { /* Order at most 8 (or 6) hexparts */ assert(i <= maxparts + 1); if (i == maxparts + 1) { /* There is an extra doublecolon */ for (j = doublecolon; j + 1 < i; j++) hexparts[j] = hexparts[j + 1]; i--; } else { for (j = maxparts; i > doublecolon + 1; ) hexparts[--j] = hexparts[--i]; for (;j > doublecolon;) hexparts[--j] = "0:"; i = maxparts; } } assert(i == maxparts); /* Scan for optimal place for "::" */ for (i = 0, maxspan = 0, span = 0, doublecolon = 0; i < maxparts; i++) { if (hexparts[i][0] == '0') span++; else if (span > maxspan) doublecolon = i - span, maxspan = span, span = 0; else span = 0; } if (span > maxspan) doublecolon = i - span, maxspan = span; dst = buf; for (i = 0; i < maxparts; i++) { if (i == doublecolon) hex = i == 0 ? "::" : ":", len = 1; else if (i > doublecolon && i < doublecolon + maxspan) continue; else hex = hexparts[i], len = span_hex4(hex); if (hex[len] == ':') len++; memcpy(dst, hex, len); dst += len; } if (ip4) { hex = ip4; len = scan_ip4_address(&hex); assert(len > 0); /* Canonize :: and ::1 */ if (doublecolon == 0 && maxspan == 6) { if (len == 7 && strncmp(ip4, "0.0.0.0", len) == 0) ip4 = "", len = 0; else if (len == 7 && strncmp(ip4, "0.0.0.1", len) == 0) ip4 = "1", len = 1; } memcpy(dst, ip4, len); dst += len; } len = dst - buf; memcpy(host, buf, len); return len; } /** Return length of valid IP6 address */ int span_ip6_address(char const *host) { return span_canonic_ip6_address(host, NULL, NULL); } /** Scan and canonize valid IP6 address. * * @param inout_host input pointer to string to scan * output pointer to first character after valid IP6 address * * @retval Length of valid IP6 address or -1 upon an error. * * @note Scanned IP6 is not always NUL-terminated. */ int scan_ip6_address(char **inout_host) { int n, canonize = 0; char *host = *inout_host; char *hexparts[9] = { NULL }; n = span_canonic_ip6_address(host, &canonize, hexparts); if (n == 0) return -1; *inout_host += n; if (canonize) { int len = canonize_ip6_address(host, hexparts); assert(len <= n); if (len < n) host[len] = '\0'; } return n; } /** Return length of valid IP6 reference. */ int span_ip6_reference(char const *host) { /* IPv6reference = "[" IPv6address "]" */ if (host && host[0] == '[') { int n = span_ip6_address(host + 1); if (n > 0 && host[n + 1] == ']') return n + 2; } return 0; } /** Scan valid IP6 reference. */ int scan_ip6_reference(char **inout_host) { int n, canonize = 0; char *host = *inout_host; char *hexparts[9] = { NULL }; /* IPv6reference = "[" IPv6address "]" */ if (host == NULL || host[0] != '[' || (n = span_canonic_ip6_address(host + 1, &canonize, hexparts)) == 0 || host[n + 1] != ']') return -1; *inout_host += n + 2; if (canonize) { int len = canonize_ip6_address(host + 1, hexparts); assert(len <= n); host[len + 1] = ']'; if (len + 2 < n + 2) host[len + 2] = '\0'; } return n + 2; } /** Return length of valid IP4 or IP6 address. */ int span_ip_address(char const *host) { if (!host || !host[0]) return 0; /* IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet */ if (IS_DIGIT(host[0])) { int n = span_ip4_address(host); if (n) return n; } if (host[0] == '[') return span_ip6_reference(host); else return span_ip6_address(host); } /** Scan valid IP4/IP6 address. */ int scan_ip_address(char **inout_host) { char *host = *inout_host; if (host == NULL) return -1; /* IPv6reference = "[" IPv6address "]" */ if (host[0] == '[') return scan_ip6_reference(inout_host); if (IS_DIGIT(host[0])) { int n = scan_ip4_address(inout_host); if (n > 0) return n; } return scan_ip6_address(inout_host); } /** Return length of a valid domain label */ su_inline size_t span_domain_label(char const *label) { /* domainlabel = alphanum / alphanum *( alphanum / "-" ) alphanum */ if (IS_ALPHANUM(*label)) { size_t n; for (n = 1; IS_ALPHANUM(label[n]) || label[n] == '-'; n++) ; if (IS_ALPHANUM(label[n - 1])) return n; } return 0; } /** Scan valid domain name and count number of labels in it. */ su_inline size_t span_domain_labels(char const *host, size_t *return_labels) { size_t len, n, labels; int c; if (!host || !host[0]) return 0; for (n = 0, labels = 0; ; n += len) { len = span_domain_label(host + n); if (len == 0) return 0; labels++; if (host[n + len] != '.') break; len++; if (!IS_ALPHANUM(host[n + len])) break; } /* Check that last label does not start with number */ if (!IS_ALPHA(host[n])) return 0; c = host[n + len]; if (IS_ALPHANUM(c) || c == '-' || c == '.') return 0; if (return_labels) *return_labels = labels; return n + len; } /** Return length of a valid domain name. * * @code * hostname = *( domainlabel "." ) toplabel [ "." ] * domainlabel = alphanum * / alphanum *( alphanum / "-" ) alphanum * toplabel = ALPHA / ALPHA *( alphanum / "-" ) alphanum * @endcode */ isize_t span_domain(char const *host) { return span_domain_labels(host, NULL); } /** Scan valid domain name. */ issize_t scan_domain(char **inout_host) { char *host; size_t n, labels; n = span_domain_labels(host = *inout_host, &labels); if (n == 0) return -1; /* Remove extra dot at the end of hostname */ if (labels > 1 && host[n - 1] == '.') host[n - 1] = '\0'; *inout_host += n; return n; } /** Return length of a valid domain name or IP address. */ isize_t span_host(char const *host) { if (!host || !host[0]) return 0; if (host[0] == '[') return span_ip6_reference(host); if (IS_DIGIT(host[0])) { int n = span_ip4_address(host); if (n) return (isize_t)n; } return span_domain(host); } /** Scan valid domain name or IP address. */ issize_t scan_host(char **inout_host) { char *host = *inout_host; if (host == NULL) return -1; /* IPv6reference = "[" IPv6address "]" */ if (host[0] == '[') return scan_ip6_reference(inout_host); if (IS_DIGIT(host[0])) { int n = scan_ip4_address(inout_host); if (n > 0) return (issize_t)n; } return scan_domain(inout_host); } #include /** Return true if @a string is valid IP4 address in dot-notation. * * @note Only 4-octet form is accepted, e.g., @c 127.1 is not considered * valid IP4 address. */ int host_is_ip4_address(char const *string) { int n = span_ip4_address(string); return n > 0 && string[n] == '\0'; } /** Return true if @a string is valid IP6 address in hex notation. * * E.g., fe80::1 is a valid IP6 address. */ int host_is_ip6_address(char const *string) { int n = span_ip6_address(string); return n > 0 && string[n] == '\0'; } int host_ip6_reference(char const *string) { return host_is_ip6_reference(string); } /** Return true if @a string is valid IP6 reference, * i.e. hex notation in square brackets. * * E.g., [::1] is a valid IP6 reference. */ int host_is_ip6_reference(char const *string) { int n = span_ip6_reference(string); return n > 0 && string[n] == '\0'; } /** Return true if @a string is valid IP address. * * Valid IP address is either a IP4 adddress in quad-octet notation, * IP6 hex address or IP6 reference in square brackets ([]). */ int host_is_ip_address(char const *string) { int n = span_ip_address(string); return n > 0 && string[n] == '\0'; } /** Return true if @a string is valid a domain name. * * Valid domain name consists of alphanumeric labels separated with * dot ("."). There can be a "-" in the middle of label. * The last label must start with a letter. * * @code * hostname = *( domainlabel "." ) toplabel [ "." ] * domainlabel = alphanum * / alphanum *( alphanum / "-" ) alphanum * toplabel = ALPHA / ALPHA *( alphanum / "-" ) alphanum * @endcode */ int host_is_domain(char const *string) { size_t n = string ? span_domain(string) : 0; return string && n > 0 && string[n] == '\0'; } /** Return true if @a string is valid a host name. * * Check if the @a string is a domain name, IP address or IP6 reference. */ int host_is_valid(char const *string) { size_t n = span_host(string); return n > 0 && string[n] == '\0'; } /** Returns true if @a string is describing a local address. * * Uses the definitions of local addresses found in RFC1700 and * RFC4291. */ int host_is_local(char const *host) { size_t n; if (host_is_ip6_reference(host)) return (strcmp(host, "[::1]") == 0); else if (host_is_ip6_address(host)) return (strcmp(host, "::1") == 0); else if (host_is_ip4_address(host)) return (strncmp(host, "127.", 4) == 0); n = span_domain(host); return n >= 9 /* strlen("localhost") */ && su_casenmatch(host, "localhost", 9) && (n == 9 || ((n == 10 || /* localhost. */ n == 21 || /* strlen("localhost.localdomain") */ n == 22) && /* strlen("localhost.localdomain.") */ su_casenmatch(host + 9, ".localdomain.", n - 9))); } /** Return true if @a string has domain name in "invalid." domain. * */ int host_has_domain_invalid(char const *string) { size_t n = span_domain(string); if (n >= 7 && string[n] == '\0') { static char const invalid[] = ".invalid"; if (string[n - 1] == '.') /* .invalid. perhaps? */ n--; if (n == 7 /* strlen("invalid") */) return su_casenmatch(string, invalid + 1, 7); else return su_casenmatch(string + n - 8, invalid, 8); } return 0; } #include static size_t convert_ip_address(char const *s, uint8_t addr[16], size_t *return_addrlen) { size_t len; int canonize = 0; char buf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; #if SU_HAVE_IN6 len = span_ip6_reference(s); if (len) { assert(len - 2 < sizeof buf); assert(len > 2); if (s[len]) return 0; len = len - 2; s = memcpy(buf, s + 1, len), buf[len] = '\0'; } else len = span_ip6_address(s); if (len) { if (s[len] == '\0' && su_inet_pton(AF_INET6, s, addr) == 1) { if (SU_IN6_IS_ADDR_V4MAPPED(addr) || SU_IN6_IS_ADDR_V4COMPAT(addr)) { memcpy(addr, addr + 12, 4); return (void)(*return_addrlen = 4), len; } return (void)(*return_addrlen = 16), len; } } else #endif len = span_canonic_ip4_address(s, &canonize); if (len) { if (canonize) { char *tmp = buf; s = memcpy(tmp, s, len + 1); scan_ip4_address(&tmp); } if (s[len] == '\0' && su_inet_pton(AF_INET, s, addr) == 1) return (void)(*return_addrlen = 4), len; } return 0; } /** Compare two host names or IP addresses * * Converts valid IP addresses to the binary format before comparing them. * Note that IP6-mapped IP4 addresses and IP6-compatible IP4 addresses are * compared as IP4 addresses; that is, ::%ffff:127.0.0.1, ::127.0.0.1 and * 127.0.0.1 all are all equal. * * @param a IP address or domain name * @param b IP address or domain name * * @retval -1 if a < b * @retval 0 if a == b * @retval 1 if a > b * * @since New in @VERSION_1_12_4. */ int host_cmp(char const *a, char const *b) { uint8_t a6[16], b6[16]; size_t alen, blen, asize = 0, bsize = 0; int retval; if (a == NULL || b == NULL) { retval = (a != NULL) - (b != NULL); } else { alen = convert_ip_address(a, a6, &asize); blen = convert_ip_address(b, b6, &bsize); if (alen > 0 && blen > 0) { if (asize < bsize) retval = -1; else if (asize > bsize) retval = 1; else retval = memcmp(a6, b6, asize); } else { retval = su_strcasecmp(a, b); } } return retval; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/bnf/bnf.docs000066400000000000000000000007541223300710500217440ustar00rootroot00000000000000/* -*- C -*- */ /**@MODULEPAGE "bnf" - String Parser Module * * @section bnf_meta Module Meta Information * * The Sofia @b bnf module contains macros and functions for parsing * text-based formats, for example, for SIP. The interface is described in * . * * The interface used for validating hostnames and IP addresses is in * . * * @CONTACT Pekka Pessi * * @STATUS @SofiaSIP Core library * * @LICENSE LGPL */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/bnf/sofia-sip/000077500000000000000000000000001223300710500222115ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/bnf/sofia-sip/bnf.h000066400000000000000000000227161223300710500231370ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef BNF_H /** Defined when has been included. */ #define BNF_H /**@file sofia-sip/bnf.h * * Parsing macros and prototypes for HTTP-like protocols. * * @author Pekka Pessi * * @date Created: Tue Jun 06 10:59:34 2000 ppessi * */ #include #include SOFIA_BEGIN_DECLS /* Parsing tokens */ /** Control characters. */ #define CTL "\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" "\177" "\0" /** Space */ #define SP " " /** Horizontal tab */ #define HT "\t" /** Carriage return */ #define CR "\r" /** Line feed */ #define LF "\n" /** Line-ending characters */ #define CRLF CR LF /** Whitespace */ #define WS SP HT /** Linear whitespace */ #define LWS SP HT CR LF /** Lower-case alphabetic characters */ #define LOALPHA "abcdefghijklmnopqrstuvwxyz" /** Upper-case alphabetic characters */ #define UPALPHA "ABCDEFGHIJKLMNOPQRSTUVWXYZ" /** Alphabetic characters */ #define ALPHA LOALPHA UPALPHA /** Digits */ #define DIGIT "0123456789" /** RTSP safe characters */ #define SAFE "$-_." /* RTSP stuff */ #define ALPHANUM DIGIT ALPHA #define HEX DIGIT "ABCDEF" "abcdef" /** SIP token characters. * @note $|&^# were token chars in RFC 2543, but no more in RFC 3261. */ #define SIP_TOKEN ALPHANUM "-.!%*_+`'~" /** SIP separator characters */ #define SIP_SEPARATOR "()<>@,;:\\\"/[]?={}" SP HT /** SIP Word characters (that are not token characters) */ #define SIP_WORD "()<>:\\\"/[]?{}" /** Skip whitespace (SP HT) */ #define skip_ws(ss) (*(ss) += span_ws(*(ss))) /** Skip linear whitespace (SP HT CR LF) */ #define skip_lws(ss) (*(ss) += span_lws(*(ss))) /** Skip [a-zA-Z] */ #define skip_alpha(ss) (*(ss) += span_alpha(*(ss))) /** Skip digits */ #define skip_digit(ss) (*(ss) += span_digit(*(ss))) /** Skip characters belonging to an RTSP token. */ #define skip_alpha_digit_safe(ss) (*(ss) += span_alpha_digit_safe(*(ss))) /** Skip characters belonging to a SIP token. */ #define skip_token(ss) (*(ss) += span_token(*(ss))) /** Skip characters belonging to a SIP parameter value. */ #define skip_param(ss) (*(ss) += span_param(*(ss))) /** Skip characters belonging to a SIP word. */ #define skip_word(ss) (*(ss) += span_word(*(ss))) /** Test if @c is CR or LF */ #define IS_CRLF(c) ((c) == '\r' || (c) == '\n') /** Test if @c is linear whitespace */ #define IS_LWS(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n') /*#define IS_LWS(c) ((_bnf_table[(unsigned char)(c)] & bnf_lws))*/ /** Test if @c is normal whitespace */ #define IS_WS(c) ((c) == ' ' || (c) == '\t') /** Test if @c is not whitespace (and not NUL). */ #define IS_NON_WS(c) (c && !IS_WS(c)) /*#define IS_NON_WS(c) (c && !(_bnf_table[(unsigned char)c] & bnf_ws))*/ /** Test if @c is not linear whitespace (and not NUL). */ #define IS_NON_LWS(c) (c && !IS_LWS(c)) /*#define IS_NON_LWS(c) (c && !(_bnf_table[(unsigned char)c] & bnf_lws))*/ /** Test if @c is a digit. */ #define IS_DIGIT(c) ((c) >= '0' && (c) <= '9') /** Test if @c is alphabetic. */ #define IS_ALPHA(c) (c && ((_bnf_table[(unsigned char)c] & bnf_alpha))) /** Test if @c is alphanumeric. */ #define IS_ALPHANUM(c) (c && (IS_DIGIT(c) || IS_ALPHA(c))) /** Test if @c is URL-unreserved. */ #define IS_UNRESERVED(c) ((_bnf_table[(unsigned char)c] & bnf_unreserved)) /** Test if @c is URL-reserved. */ #define IS_RESERVED(c) (c && !(_bnf_table[(unsigned char)c] & bnf_unreserved)) /** Test if @c is valid in tokens. */ #define IS_TOKEN(c) ((_bnf_table[(unsigned char)c] & bnf_token)) /** Test if @c is valid for SIP parameter value. */ #define IS_PARAM(c) ((_bnf_table[(unsigned char)c] & (bnf_token|bnf_param))) /** Test if @c is a hex digit. */ #define IS_HEX(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'A' && (c) <= 'F') || ((c) >= 'a' && (c) <= 'f')) /** Test if @c is a linear whitespace or valid in tokens. */ #define IS_TOKENLWS(c) ((_bnf_table[(unsigned char)c] & (bnf_token|bn_lws))) enum { bnf_ws = 1, /**< Whitespace character */ bnf_crlf = 2, /**< Line end character */ bnf_lws = 3, /**< Linear whitespace */ bnf_alpha = 4, /**< Alphabetic */ bnf_safe = 8, /**< RTSP safe */ bnf_mark = 16, /**< URL mark */ bnf_unreserved = bnf_alpha | bnf_mark, /**< URL unreserved */ bnf_separator = 32, /**< SIP separator */ /** SIP token, not alphabetic (0123456789-.!%*_+`'~) */ bnf_token0 = 64 | bnf_safe, bnf_token = bnf_token0 | bnf_alpha, /**< SIP token */ bnf_param0 = 128, /**< SIP parameter, not token */ bnf_param = bnf_token | bnf_param0 /**< SIP/HTTP parameter */ }; /** Table for determining class of a character. */ SOFIAPUBVAR unsigned char const _bnf_table[256]; /** Get number of characters before CRLF */ #define span_non_crlf(s) strcspn(s, CR LF) /** Get number of characters before whitespace */ #define span_non_ws(s) strcspn(s, WS) /** Get number of whitespace characters */ #define span_ws(s) strspn(s, WS) /** Get number of characters before linear whitespace */ #define span_non_lws(s) strcspn(s, LWS) /** Calculate span of a linear whitespace. * LWS = [*WSP CRLF] 1*WSP */ su_inline isize_t span_lws(char const *s) { char const *e = s; int i = 0; e += strspn(s, WS); if (e[i] == '\r') i++; if (e[i] == '\n') i++; if (IS_WS(e[i])) e += i + strspn(e + i, WS); return e - s; } /** Calculate span of a token or linear whitespace characters. */ su_inline isize_t span_token_lws(char const *s) { char const *e = s; while (_bnf_table[(unsigned char)(*e)] & (bnf_token | bnf_lws)) e++; return e - s; } /** Calculate span of a token characters. */ su_inline isize_t span_token(char const *s) { char const *e = s; while (_bnf_table[(unsigned char)(*e)] & bnf_token) e++; return e - s; } /** Calculate span of a alphabetic characters. */ su_inline isize_t span_alpha(char const *s) { char const *e = s; while (_bnf_table[(unsigned char)(*e)] & bnf_alpha) e++; return e - s; } /** Calculate span of a digits. */ su_inline isize_t span_digit(char const *s) { char const *e = s; while (*e >= '0' && *e <= '9') e++; return e - s; } /** Calculate span of a hex. */ su_inline isize_t span_hexdigit(char const *s) { char const *e = s; while (IS_HEX(*e)) e++; return e - s; } /** Calculate span of characters belonging to an RTSP token */ su_inline isize_t span_alpha_digit_safe(char const *s) { char const *e = s; while (_bnf_table[(unsigned char)(*e)] & (bnf_alpha | bnf_safe)) e++; return e - s; } /** Calculate span of a characters valid in parameters. */ su_inline isize_t span_param(char const *s) { char const *e = s; while (IS_PARAM(*e)) e++; return e - s; } /** Calculate span of a SIP word. */ su_inline isize_t span_word(char const *s) { char const *e = s; while (*e && (IS_TOKEN(*e) || strchr(SIP_WORD, *e))) e++; return e - s; } /** Calculate span of a unreserved characters. */ su_inline isize_t span_unreserved(char const *s) { char const *e = s; while (IS_UNRESERVED(*e)) e++; return e - s; } /** Calculate span of a double quoted string (with escaped chars inside) */ su_inline isize_t span_quoted(char const *s) { char const *b = s; if (*s++ != '"') return 0; for (;;) { s += strcspn(s, "\\\""); if (!*s) return 0; if (*s++ == '"') return s - b; if (!*s++) return 0; } } /* RFC 2396 defines URL chars */ /** Reserved in URLs */ #define URL_RESERVED ";/?:=+$," /** Non-alphanumeric characters without syntactical meaning. */ #define URL_MARK "-_.!~*'()" /** Unreserved characters. */ #define URL_UNRESERVED ALPHANUM URL_MARK /** URL hex escape. */ #define URL_ESCAPED "%" #define URL_DELIMS "<>#%\"" #define URL_UNWISE "{}|\\^[]`" #define URL_SCHEME ALPHANUM "+-." /** Get number of characters belonging to url scheme */ #define span_url_scheme(s) strspn(s, URL_SCHEME) SOFIAPUBFUN int span_ip4_address(char const *host); SOFIAPUBFUN int span_ip6_address(char const *host); SOFIAPUBFUN int span_ip6_reference(char const *host); SOFIAPUBFUN int span_ip_address(char const *host); SOFIAPUBFUN isize_t span_domain(char const *host); SOFIAPUBFUN isize_t span_host(char const *host); SOFIAPUBFUN int scan_ip4_address(char **inout_host); SOFIAPUBFUN int scan_ip6_address(char **inout_host); SOFIAPUBFUN int scan_ip6_reference(char **inout_host); SOFIAPUBFUN int scan_ip_address(char **inout_host); SOFIAPUBFUN issize_t scan_domain(char **inout_host); SOFIAPUBFUN issize_t scan_host(char **inout_host); SOFIA_END_DECLS #endif /* !defined BNF_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/bnf/sofia-sip/hostdomain.h000066400000000000000000000037271223300710500245400ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2006 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef SOFIA_SIP_HOSTDOMAIN_H /** Defined when has been included. */ #define SOFIA_SIP_HOSTDOMAIN_H /**@file sofia-sip/hostdomain.h * * Predicates for handling host names: IP addresses or domain names. * * @author Pekka Pessi * * @date Created: Thu Mar 9 16:15:22 EET 2006 ppessi */ #ifndef SU_CONFIG_H #include #endif SOFIA_BEGIN_DECLS SOFIAPUBFUN int host_is_ip4_address(char const *string); SOFIAPUBFUN int host_is_ip6_address(char const *string); SOFIAPUBFUN int host_is_ip6_reference(char const *string); SOFIAPUBFUN int host_is_ip_address(char const *string); SOFIAPUBFUN int host_is_domain(char const *string); SOFIAPUBFUN int host_is_valid(char const *string); SOFIAPUBFUN int host_is_local(char const *string); SOFIAPUBFUN int host_has_domain_invalid(char const *string); SOFIAPUBFUN int host_cmp(char const *a, char const *b); /** This is typo. @deprecated Use host_is_ip6_reference() instead. */ SOFIAPUBFUN int host_ip6_reference(char const *string); SOFIA_END_DECLS #endif /* !defined(SOFIA_SIP_HOSTDOMAIN_H) */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/bnf/torture_bnf.c000066400000000000000000000310051223300710500230130ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE torture_bnf.c * * Torture tests for BNF functions. * * @author Pekka Pessi * * @date Created: Tue Aug 21 15:18:26 2001 ppessi */ #include "config.h" #include #include #include #include #include #include #include "sofia-sip/bnf.h" static int test_flags = 0; #define TSTFLAGS test_flags #include char const name[] = "torture_bnf"; static int count_bnf(int bnf_flags) { int i, n; for (i = 0, n = 0; i < 128; i++) if (_bnf_table[i] & bnf_flags) n++; return n; } static int bnf_test(void) { BEGIN(); TEST_1(IS_TOKEN('a')); TEST_1(IS_TOKEN('b')); /* Fixed for 1.12.2: lws = [*wsp crlf] 1*wsp */ TEST_SIZE(span_lws(" \r\n \r\nLoppuu"), 5); TEST_SIZE(span_lws(" \r\r \nLoppuu"), 2); TEST_SIZE(span_lws(" \n\r \nLoppuu"), 2); TEST_SIZE(span_lws(" \r \nLoppuu"), 4); TEST_SIZE(span_lws(" \n\t \nLoppuu"), 5); TEST_SIZE(span_lws(" \r\n\t \nLoppuu"), 6); TEST_SIZE(span_token(SIP_TOKEN), strlen(SIP_TOKEN)); TEST_SIZE(count_bnf(bnf_token), strlen(SIP_TOKEN "$")); #define SIP_PARAM SIP_TOKEN "[:]/" TEST_SIZE(span_param(SIP_PARAM), strlen(SIP_PARAM)); TEST_SIZE(count_bnf(bnf_param), strlen(SIP_PARAM "$")); TEST_SIZE(span_unreserved(URL_UNRESERVED URL_ESCAPED), strlen(URL_UNRESERVED URL_ESCAPED)); TEST_SIZE(count_bnf(bnf_unreserved), strlen(URL_UNRESERVED URL_ESCAPED)); { char word[] = ALPHA DIGIT "-.!%*_+`'~()<>:\\\"/[]?{}"; TEST_SIZE(span_word(word), strlen(word)); } END(); } static int ip_test(void) { BEGIN(); char *s; TEST(span_ip4_address("127.255.249.000,"), 15); TEST(span_ip4_address("0.00.000.000:,"), 12); /* Test error detection */ TEST(span_ip4_address("256.00.000.000:,"), 0); TEST(span_ip4_address("255.00.000.0000,"), 0); TEST(span_ip4_address("255.00.000.199."), 0); { char ip0[] = "010.250.020.000,"; char ip1[] = "0.00.000.000:,"; char ip2[] = "256.00.000.000:,"; char ip3[] = "255.00.000.0000,"; char ip4[] = "255.00.000.199."; s = ip0; TEST(scan_ip4_address(&s), 15); TEST_S(s, ","); TEST_S(ip0, "10.250.20.0"); s = ip1; TEST(scan_ip4_address(&s), 12); TEST_S(s, ":,"); TEST_S(ip1, "0.0.0.0"); /* Test error detection */ s = ip2; TEST(scan_ip4_address(&s), -1); s = ip3; TEST(scan_ip4_address(&s), -1); s = ip4; TEST(scan_ip4_address(&s), -1); } TEST(span_ip6_address("dead:beef:feed:ded:0:1:2:3"), 26); TEST(span_ip6_address("::beef:feed:ded:0:1:2:3"), 23); TEST(span_ip6_address("::255.0.0.0,"), 11); TEST(span_ip6_address("::,"), 2); TEST(span_ip_address("[dead:beef:feed:ded:0:1:2:3]"), 28); TEST(span_ip_address("::255.0.0.0,"), 11); TEST(span_ip_address("[::255.0.0.0]:"), 13); TEST(span_ip6_address("dead:beef:feed::0ded:0:1:2:3"), 28); TEST(span_ip6_address("dead:beef:feed::0ded:0000:0001:0002:0003"), 40); TEST(span_ip6_address("dead:beef:feed::0ded::0000:0001:0002:0003"), 0); TEST(span_ip6_address("::dead:beef:feed::0ded:0000:0001:0002:0003"), 0); TEST(span_ip6_address("dead:beef:feed:ded:0:1:2:3:4"), 0); TEST(span_ip6_address("dead:beef:feed:00ded:0:1:2:3"), 0); TEST(span_ip6_address("dead:beef:feed:ded:0:1:2:127.0.0.1"), 0); TEST(span_ip6_address(":255.0.0.0,"), 0); TEST(span_ip6_address("255.0.0.0,"), 0); /* Accept colon after IP4-quad */ TEST(span_ip_address("::255.0.0.0:5060"), 11); /* This is a reference */ TEST(span_ip6_address("[dead:beef:feed:ded:0:1:2:3]"), 0); TEST(span_ip6_reference("[dead:beef:feed:ded:0:1:2:3]:1"), 28); TEST(span_ip_address("[dead:beef:feed:ded:0:1:2:3]:1"), 28); TEST(span_ip_address("[127.0.0.1]:1"), 0); { char ip0[] = "dead:beef:feed:ded:0:1:2:3,"; char ip1[] = "::beef:feed:ded:0:1:2:3;"; char ip1b[] = "::beef:feed:ded:0:0:2:3;"; char ip2[] = "::255.00.0.0,"; char ip3[] = "::,"; char ip4[] = "0:0:0:0:0:0:0:0,"; char ip4b[] = "0:0:0:0:0:0:0.0.0.0,"; char ip4c[] = "0:0:0:0:0:0:0.0.0.1,"; char ip5[] = "dead:beef:feed::0ded:0:1:2:3"; char ip6[] = "dead:beef:feed::0ded:0000:0001:0002:0003+"; char ip7[] = "1:0:0:2:0:0:0:3,"; char ip8[] = "1:0:0:2:0:0:3:4,"; char ip9[] = "1::2:0:0:0:3,"; s = ip0; TEST(scan_ip6_address(&s), 26); TEST_S(s, ","); TEST_S(ip0, "dead:beef:feed:ded::1:2:3"); s = ip1; TEST(scan_ip6_address(&s), 23); TEST_S(s, ";"); TEST_S(ip1, "::beef:feed:ded:0:1:2:3;"); s = ip1b; TEST(scan_ip6_address(&s), 23); TEST_S(s, ";"); TEST_S(ip1b, "0:beef:feed:ded::2:3"); s = ip2; TEST(scan_ip6_address(&s), 12); TEST_S(s, ","); TEST_S(ip2, "::255.0.0.0"); s = ip3; TEST(scan_ip6_address(&s), 2); TEST_S(s, ","); TEST_S(ip3, "::,"); s = ip4; TEST(scan_ip6_address(&s), 15); TEST_S(s, ","); TEST_S(ip4, "::"); s = ip4b; TEST(scan_ip6_address(&s), 19); TEST_S(s, ","); TEST_S(ip4b, "::"); s = ip4c; TEST(scan_ip6_address(&s), 19); TEST_S(s, ","); TEST_S(ip4c, "::1"); TEST_S(ip5, "dead:beef:feed::0ded:0:1:2:3"); s = ip5; TEST(scan_ip6_address(&s), 28); TEST_S(s, ""); TEST_S(ip5, "dead:beef:feed:ded::1:2:3"); s = ip6; TEST(scan_ip6_address(&s), 40); TEST_S(s, "+"); TEST_S(ip6, "dead:beef:feed:ded::1:2:3"); s = ip7; TEST(scan_ip6_address(&s), 15); TEST_S(s, ","); TEST_S(ip7, "1:0:0:2::3"); s = ip8; TEST(scan_ip6_address(&s), 15); TEST_S(s, ","); TEST_S(ip8, "1::2:0:0:3:4"); s = ip9; TEST(scan_ip6_address(&s), 12); TEST_S(s, ","); TEST_S(ip9, "1:0:0:2::3"); } { char err0[] = "dead:beef:feed::0ded::0000:0001:0002:0003"; char err1[] = "::dead:beef:feed::0ded:0000:0001:0002:0003"; char err2[] = "dead:beef:feed:ded:0:1:2:3:4"; char err3[] = "dead:beef:feed:00ded:0:1:2:3"; char err4[] = "dead:beef:feed:ded:0:1:2:127.0.0.1"; char err5[] = ":255.0.0.0,"; char err6[] = "255.0.0.0,"; char err7[] = "dead:beef:feed:ded:0:1:2:3:4:5,"; TEST(scan_ip6_address((s = err0, &s)), -1); TEST(scan_ip6_address((s = err1, &s)), -1); TEST(scan_ip6_address((s = err2, &s)), -1); TEST(scan_ip6_address((s = err3, &s)), -1); TEST(scan_ip6_address((s = err4, &s)), -1); TEST(scan_ip6_address((s = err5, &s)), -1); TEST(scan_ip6_address((s = err6, &s)), -1); TEST(scan_ip6_address((s = err7, &s)), -1); } { char err0[] = "[dead:beef:feed::0ded::0000:0001:0002:0003]:"; char err1[] = "[::dead:beef:feed::0ded:0000:0001:0002:0003]+"; char err2[] = "[dead:beef:feed:ded:0:1:2:3:4]+"; char err3[] = "[dead:beef:feed:00ded:0:1:2:3]+"; char err4[] = "[dead:beef:feed:ded:0:1:2:127.0.0.1]"; char err5[] = "[:255.0.0.0],"; char err6[] = "[255.0.0.0],"; char err7[] = "[dead:beef:feed:ded:0:1:2:]"; TEST(scan_ip6_reference((s = err0, &s)), -1); TEST(scan_ip6_reference((s = err1, &s)), -1); TEST(scan_ip6_reference((s = err2, &s)), -1); TEST(scan_ip6_reference((s = err3, &s)), -1); TEST(scan_ip6_reference((s = err4, &s)), -1); TEST(scan_ip6_reference((s = err5, &s)), -1); TEST(scan_ip6_reference((s = err6, &s)), -1); TEST(scan_ip6_reference((s = err7, &s)), -1); } END(); } #define TEST_SCAN(scanner, input, canonic, output) \ do { char s0[] = input; char *s = s0; \ size_t n = sizeof(input) - sizeof(output); \ TEST_SIZE(scanner(&s), n); \ TEST_S(s, output); \ TEST_S(s0, canonic); } while(0) #include static int host_test(void) { BEGIN(); TEST(host_is_ip4_address(NULL), 0); TEST(host_is_ip6_address(NULL), 0); TEST(host_ip6_reference(NULL), 0); TEST(host_is_ip_address(NULL), 0); TEST(host_is_domain(NULL), 0); TEST(host_is_valid(NULL), 0); TEST(host_has_domain_invalid(NULL), 0); TEST_SIZE(span_host("rama"), 4); TEST_SIZE(span_host("ra-ma.1-2.3-4.a4-9."), 19); TEST_SIZE(span_host("a.1.b"), 5); TEST_SIZE(span_host("127.255.249.000.a,"), 17); TEST_SIZE(span_host("127.255.249.000,"), 15); TEST_SIZE(span_host("0.00.000.000:,"), 12); TEST_SIZE(span_host("127.255.249.000,"), 15); TEST_SIZE(span_host("[dead:beef:feed:ded:0:1:2:3]:1"), 28); TEST_SIZE(span_host("[dead:beef:feed:ded::1:2:3]:1"), 27); TEST_SIZE(span_host("[::127.0.0.1]:1"), 13); TEST_SCAN(scan_host, "rama", "rama", ""); TEST_SCAN(scan_host, "rama.", "rama.", ""); TEST_SCAN(scan_ip4_address, "127.255.249.000,", "127.255.249.0", ","); TEST_SCAN(scan_host, "127.255.249.000,", "127.255.249.0", ","); TEST_SCAN(scan_host, "a.1.b.", "a.1.b", ""); TEST_SCAN(scan_host, "ra-ma.1-2.3-4.a4-9.", "ra-ma.1-2.3-4.a4-9", ""); TEST_SCAN(scan_host, "127.255.249.000.a,", "127.255.249.000.a,", ","); TEST_SCAN(scan_host, "0.00.000.000:,", "0.0.0.0", ":,"); TEST_SCAN(scan_host, "127.255.249.000,", "127.255.249.0", ","); TEST_SCAN(scan_host, "[dead:beef:feed:ded:0:1:2:3]:1", "[dead:beef:feed:ded::1:2:3]", ":1"); TEST_SCAN(scan_host, "[::127.0.0.1]:1", "[::127.0.0.1]:1", ":1"); /* Test error detection */ TEST_SIZE(span_host("256.00.000.000:,"), 0); TEST_SIZE(span_host("255.00.000.0000,"), 0); TEST_SIZE(span_host("255.00.000.199."), 0); TEST_SIZE(span_host("[127.0.0.1]:1"), 0); TEST_SIZE(span_domain("rama.1"), 0); TEST_SIZE(span_domain("-ma.1-2.3-4.a4-9."), 0); TEST_SIZE(span_domain("a..b"), 0); TEST_SIZE(span_domain("a.b.-"), 0); TEST_SIZE(span_domain("a.b-"), 0); TEST(host_is_local("126.0.0.0"), 0); TEST(host_is_local("127.0.0.0"), 1); TEST(host_is_local("127.0.0.2"), 1); TEST(host_is_local("0.0.0.0"), 0); TEST(host_is_local("::1"), 1); TEST(host_is_local("::1"), 1); TEST(host_is_local("::1:3fff"), 0); TEST(host_is_local("[::1]"), 1); TEST(host_is_local("localdomain.domain.org"), 0); TEST(host_is_local("localhost.domain.org"), 0); TEST(host_is_local("localhost"), 1); TEST(host_is_local("localhost.localdomain"), 1); TEST(host_is_local("localhost."), 1); TEST(host_is_local("localhost.localdomain."), 1); TEST(host_is_local("localhost.localdomain.org"), 0); TEST(host_has_domain_invalid("invalid"), 1); TEST(host_has_domain_invalid("invalid."), 1); TEST(host_has_domain_invalid("1.invalid"), 1); TEST(host_has_domain_invalid("1.invalid."), 1); TEST(host_has_domain_invalid("1invalid"), 0); TEST(host_has_domain_invalid("valid."), 0); TEST(host_has_domain_invalid("1-.invalid."), 0); TEST(host_is_domain("127.0.0.1"), 0); TEST(host_is_domain("3.com"), 1); TEST(host_is_domain("127.0.0.com"), 1); TEST(host_is_domain("actra.0.1"), 0); /* Invalid IP4 address (extra leading zeros) */ TEST_1(!host_cmp("127.0.0.1", "127.0.0.01")); /* Invalid reference (extra leading zeros) */ TEST_1(host_cmp("[0ffff:0ffff:0ffff:0ffff:0ffff:0ffff:255.255.255.255]", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")); #if SU_HAVE_IN6 TEST_1(!host_cmp("[ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255]", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")); TEST_1(!host_cmp("::1", "::001")); TEST_1(!host_cmp("[::1]", "::1")); TEST_1(!host_cmp("[::1]", "::0.0.0.1")); TEST_1(!host_cmp("::ffff:127.0.0.1", "127.0.0.1")); TEST_1(!host_cmp("::ffff:127.0.0.1", "::ffff:7f00:1")); TEST_1(!host_cmp("::ffff:127.0.0.1", "::ffff:7f00:1")); TEST_1(!host_cmp("[::ffff:127.0.0.1]", "[::7f00:1]")); #endif TEST_1(host_cmp("::", "0.0.0.0")); TEST_1(host_cmp("::1", "0.0.0.1")); END(); } static void usage(int exitcode) { fprintf(stderr, "usage: %s [-v] [-a]\n", name); exit(exitcode); } int main(int argc, char *argv[]) { int retval = 0; int i; for (i = 1; argv[i]; i++) { if (strcmp(argv[i], "-v") == 0) test_flags |= tst_verbatim; else if (strcmp(argv[i], "-a") == 0) test_flags |= tst_abort; else usage(1); } retval |= bnf_test(); fflush(stdout); retval |= ip_test(); fflush(stdout); retval |= host_test(); fflush(stdout); return retval; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/docs/000077500000000000000000000000001223300710500205025ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/docs/.gitignore000066400000000000000000000001051223300710500224660ustar00rootroot00000000000000/Doxyfile.rfc /Doxyfile.version /html/ /sofia-footer.html *.doxytags sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/docs/ChangeLog000066400000000000000000000007501223300710500222560ustar00rootroot000000000000002005-10-27 Pekka Pessi * Added aliases for RFC links in libsofia-sip-ua/docs/Doxyfile.aliases. M ./libsofia-sip-ua/docs/Doxyfile.aliases -7 +2208 2005-10-12 Pekka Pessi * Fixed aliases for Doxygen 1.4. M ./libsofia-sip-ua/docs/Doxyfile.aliases -6 +6 2005-09-08 Kai Vehmanen * hide_emails.sh: Fixed bug in hiding addresses of form foo.bar-bar@something.org. Fixed sf.net bug #1277167. sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/docs/Doxyfile.aliases000066400000000000000000000074721223300710500236420ustar00rootroot00000000000000# Doxyfile 1.0.0 format # PREDEFINED = DOX \ DOXYGEN_ONLY=1 \ DOCUMENTATION_ONLY=1 \ SU_HAVE_INLINE=1 su_inline=inline \ SOFIA_BEGIN_DECLS SOFIA_END_DECLS SOFIAPUBFUN SOFIACALL \ SOFIAPUBVAR=extern \ SU_DLL SIP_DLL RTSP_DLL SU_DLL NTA_DLL NUA_DLL MSG_DLL AUTH_DLL \ NTH_DLL HTTP_DLL \ __attribute__()= ALIASES = \ "MODULEPAGE=\mainpage Sofia SIP User Agent Library - " \ "CONTACT=\par Contact:\n" \ "STATUS=\par Status:\n" \ "LICENSE=\par License:\n" \ "SofiaSIP=Sofia SIP" \ "SU=@ref su_index \"SU\"" "su=@ref su_index \"su\"" \ "msg=@ref msg_index \"msg\"" \ "sip=@ref sip_index \"sip\"" \ "nua=@ref nua_index \"nua\"" \ "nta=@ref nta_index \"nta\"" \ "soa=@ref soa_index \"soa\"" \ "DEF=\def" \ "TAGS=\par Related Tags:" \ "TAG=\par \n" \ "EVENTS=\par Events:\n" \ "RESPONSES=\par Related Response Codes:\n" \ "CFILE=\internal \file" \ "IFILE=\file" \ "HI=\hideinitializer " \ "HIDE=\hideinitializer " \ "SHOW=\showinitializer " \ "LGPL2=\par Lesser GNU Public License Version 2:\n \ref lgpl2\n \if 0\n" \ "ENDLGPL2=\endif \n" \ "GPL2=\par GNU Public License Version 2:\n \ref gpl2\n \if 0\n" \ "ENDGPL2=\endif \n" \ "ERRORS=\par Errors: " \ "ERROR=\par \n \b " \ "NEW_1_12_2=@since New in 1.12.2" \ "VERSION_1_12_2=1.12.2" \ "NEW_1_12_4=@since New in 1.12.4" \ "VERSION_1_12_4=1.12.4" \ "VERSION_1_12_5=1.12.5" \ "NEW_1_12_5=@since New in 1.12.5" \ "EXP_1_12_5=@since Experimental in 1.12.5, available if --enable-experimental configuration option is given" \ "VERSION_1_12_6=1.12.6" \ "NEW_1_12_6=@since New in 1.12.6" \ "EXP_1_12_6=@since Experimental in 1.12.6, available if --enable-experimental configuration option is given" \ "VERSION_1_12_7=1.12.7" \ "NEW_1_12_7=@since New in 1.12.7" \ "EXP_1_12_7=@since Experimental in 1.12.7, available if --enable-experimental configuration option is given" \ "VERSION_1_12_8=1.12.8" \ "NEW_1_12_8=@since New in 1.12.8" \ "VERSION_1_12_9=1.12.9" \ "NEW_1_12_9=@since New in 1.12.9" \ "VERSION_1_12_10=1.12.10" \ "NEW_1_12_10=@since New in 1.12.10" \ "VERSION_1_12_11=1.12.11" \ "NEW_1_12_11=@since New in 1.12.11" \ "VERSION_UNRELEASED=UNRELEASED" \ "NEW_UNRELEASED=@since Not yet released" \ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/docs/Doxyfile.conf000066400000000000000000000027711223300710500231430ustar00rootroot00000000000000# Doxyfile 1.0.0 format # @INCLUDE = "../../libsofia-sip-ua/docs/Doxyfile.version" @INCLUDE = "../../libsofia-sip-ua/docs/Doxyfile.aliases" @INCLUDE = "../../libsofia-sip-ua/docs/Doxyfile.rfc" OUTPUT_LANGUAGE = English OPTIMIZE_OUTPUT_FOR_C = YES SHOW_USED_FILES = NO QUIET = YES WARNINGS = YES DISABLE_INDEX = NO HAVE_DOT = YES CLASS_GRAPH = NO INCLUDE_GRAPH = YES INCLUDED_BY_GRAPH = NO COLLABORATION_GRAPH = YES GROUP_GRAPHS = NO EXTRACT_ALL = NO EXTRACT_PRIVATE = NO VERBATIM_HEADERS = YES HIDE_UNDOC_RELATIONS = YES HIDE_UNDOC_MEMBERS = YES HIDE_UNDOC_CLASSES = YES HIDE_SCOPE_NAMES = YES BRIEF_MEMBER_DESC = YES REPEAT_BRIEF = YES JAVADOC_AUTOBRIEF = YES MAX_INITIALIZER_LINES = 0 ENUM_VALUES_PER_LINE = 1 ENABLE_PREPROCESSING = YES MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = YES # HTML GENERATE_HTML = YES HTML_OUTPUT = . HTML_ALIGN_MEMBERS = YES HTML_FOOTER = ../../libsofia-sip-ua/docs/sofia-footer.html ALLEXTERNALS = NO EXTERNAL_GROUPS = NO # LATEX GENERATE_LATEX = NO LATEX_OUTPUT = latex LATEX_CMD_NAME = pdflatex USE_PDFLATEX = YES PDF_HYPERLINKS = YES COMPACT_LATEX = YES PAPER_TYPE = a4wide EXTRA_PACKAGES = LATEX_BATCHMODE = YES FILE_PATTERNS = *.h *.c EXCLUDE_PATTERNS = acconfig.h config.h confdefs.h \ test*.h test*.c torture*.c *test.c *torture.c \ *_tag_dll.c *_tag_ref.c sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/docs/Doxyfile.in000066400000000000000000000020201223300710500226070ustar00rootroot00000000000000PROJECT_NAME = "libsofia-sip-ua" OUTPUT_DIRECTORY = ../docs/html INPUT = @srcdir@/mainpage.docs @srcdir@/docguide.docs @srcdir@/conformance.docs # release.docs @INCLUDE_PATH = . @srcdir@ @INCLUDE = ../docs/Doxyfile.conf @INCLUDE = ../sip/sip.doxyaliases GENERATE_TAGFILE = docs.doxytags TAGFILES = TAGFILES += su.doxytags=su TAGFILES += ipt.doxytags=ipt TAGFILES += bnf.doxytags=bnf TAGFILES += url.doxytags=url TAGFILES += msg.doxytags=msg TAGFILES += sip.doxytags=sip TAGFILES += sresolv.doxytags=sresolv TAGFILES += stun.doxytags=stun TAGFILES += tport.doxytags=tport TAGFILES += nta.doxytags=nta TAGFILES += iptsec.doxytags=iptsec TAGFILES += sdp.doxytags=sdp TAGFILES += soa.doxytags=soa TAGFILES += nea.doxytags=nea TAGFILES += nua.doxytags=nua TAGFILES += features.doxytags=features EXAMPLE_PATH = @srcdir@/../sip sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/docs/Doxyfile.version.in000066400000000000000000000001241223300710500242760ustar00rootroot00000000000000PROJECT_NUMBER = @VERSION@ IMAGE_PATH = @top_srcdir@/libsofia-sip-ua/docs/pictures sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/docs/Makefile.am000066400000000000000000000027611223300710500225440ustar00rootroot00000000000000EXTRA_DIST = Doxyfile.aliases Doxyfile.conf \ docguide.docs \ mainpage.docs \ conformance.docs \ ChangeLog \ pictures/SIP_basic_incoming_operation.eps \ pictures/SIP_basic_incoming_operation.gif \ pictures/SIP_basic_incoming_operation.vsd \ pictures/SIP_basic_outgoing_operation.eps \ pictures/SIP_basic_outgoing_operation.gif \ pictures/SIP_basic_outgoing_operation.vsd \ pictures/SIP_incoming_call.eps \ pictures/SIP_incoming_call.gif \ pictures/SIP_incoming_call.vsd \ pictures/SIP_outgoing_call.eps \ pictures/SIP_outgoing_call.gif \ pictures/SIP_outgoing_call.vsd \ pictures/SIP_outgoing_operation_with_auth.eps \ pictures/SIP_outgoing_operation_with_auth.gif \ pictures/SIP_outgoing_operation_with_auth.vsd \ pictures/autotools.eps \ pictures/autotools.gif \ pictures/autotools.vsd \ pictures/nta-receiving-message.eps \ pictures/nta-receiving-message.gif BUILT_SOURCES = Doxyfile.rfc # Including Doxyfile.rfc in dist breaks make manpages Doxyfile.rfc: Makefile.am $(AWK) 'END { b="\\"; q="\\\""; \ print "# Autogenerated aliases for RFCs "from" .. "to ; \ print "ALIASES += " b; \ for (i=from; i < to; i++) { \ print "RFC"i"=\"RFC "i"\" "b; \ }}' \ site=http://tools.ietf.org/html type= \ from=700 to=6500 \ /dev/null > $@ CLEANFILES = Doxyfile.rfc *.doxytags distclean-local: -rm -rf html # ---------------------------------------------------------------------- # Sofia specific rules LDADD = include $(top_srcdir)/rules/sofia.am sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/docs/Makefile.in000066400000000000000000000634351223300710500225620ustar00rootroot00000000000000# Makefile.in generated by automake 1.14 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 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@ # common Makefile targets for libsofia-sip-ua(-glib) modules # ---------------------------------------------------------- # # run tests with valgrind # # Copyright (C) 2007 Nokia Corporation. # 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 file contains free software from Makefile.in by the Free Software # Foundation: # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 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. # # Generate lcov output # # # Copyright (C) 2007 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # # Silent compilation w/ Automake 1.9 or 1.10 # ---------------------------------------------------------- # Automake 1.9.6 is not clever enough to override suffix rules within if # if SOFIA_COMPILE_SILENT VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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@ DIST_COMMON = $(top_srcdir)/rules/sofia.am \ $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am \ $(top_srcdir)/rules/silent.am $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(srcdir)/Doxyfile.in \ $(srcdir)/Doxyfile.version.in $(srcdir)/sofia-footer.html.in \ ChangeLog # Use with --enable-ndebug @NDEBUG_TRUE@am__append_1 = -DNDEBUG @HAVE_GENPNG_TRUE@@HAVE_LCOV_TRUE@am__append_2 = --frames @HAVE_LCOV_TRUE@am__append_3 = lcov lcov-report lcov-rerun clean-lcov covcheck uncovered subdir = libsofia-sip-ua/docs ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(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)/m4/sac-coverage.m4 \ $(top_srcdir)/m4/sac-general.m4 \ $(top_srcdir)/m4/sac-openssl.m4 \ $(top_srcdir)/m4/sac-pkg-config.m4 $(top_srcdir)/m4/sac-su2.m4 \ $(top_srcdir)/m4/sac-tport.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libsofia-sip-ua/su/sofia-sip/su_configure.h CONFIG_CLEAN_FILES = Doxyfile Doxyfile.version sofia-footer.html 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) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CHECK_CFLAGS = @CHECK_CFLAGS@ CHECK_LIBS = @CHECK_LIBS@ COVERAGE_FLAGS = @COVERAGE_FLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CWFLAG = @CWFLAG@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV = @GCOV@ GENHTML = @GENHTML@ GENPNG = @GENPNG@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GLIB_VERSION = @GLIB_VERSION@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVER_SOFIA_SIP_UA_AGE = @LIBVER_SOFIA_SIP_UA_AGE@ LIBVER_SOFIA_SIP_UA_CUR = @LIBVER_SOFIA_SIP_UA_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_AGE = @LIBVER_SOFIA_SIP_UA_GLIB_AGE@ LIBVER_SOFIA_SIP_UA_GLIB_CUR = @LIBVER_SOFIA_SIP_UA_GLIB_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_REV = @LIBVER_SOFIA_SIP_UA_GLIB_REV@ LIBVER_SOFIA_SIP_UA_GLIB_SOVER = @LIBVER_SOFIA_SIP_UA_GLIB_SOVER@ LIBVER_SOFIA_SIP_UA_REV = @LIBVER_SOFIA_SIP_UA_REV@ LIBVER_SOFIA_SIP_UA_SOVER = @LIBVER_SOFIA_SIP_UA_SOVER@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MINGW_ENVIRONMENT = @MINGW_ENVIRONMENT@ MKDIR_P = @MKDIR_P@ MOSTLYCLEANFILES = @MOSTLYCLEANFILES@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ RANLIB = @RANLIB@ REPLACE_LIBADD = @REPLACE_LIBADD@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ SOFIA_GLIB_CFLAGS = @SOFIA_GLIB_CFLAGS@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ SOFIA_PLAT_CFLAGS = @SOFIA_PLAT_CFLAGS@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ VERSION = @VERSION@ VER_LIBSOFIA_SIP_UA_MAJOR_MINOR = @VER_LIBSOFIA_SIP_UA_MAJOR_MINOR@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ include_sofiadir = @include_sofiadir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ openssl_CFLAGS = @openssl_CFLAGS@ openssl_LIBS = @openssl_LIBS@ 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@ EXTRA_DIST = Doxyfile.aliases Doxyfile.conf \ docguide.docs \ mainpage.docs \ conformance.docs \ ChangeLog \ pictures/SIP_basic_incoming_operation.eps \ pictures/SIP_basic_incoming_operation.gif \ pictures/SIP_basic_incoming_operation.vsd \ pictures/SIP_basic_outgoing_operation.eps \ pictures/SIP_basic_outgoing_operation.gif \ pictures/SIP_basic_outgoing_operation.vsd \ pictures/SIP_incoming_call.eps \ pictures/SIP_incoming_call.gif \ pictures/SIP_incoming_call.vsd \ pictures/SIP_outgoing_call.eps \ pictures/SIP_outgoing_call.gif \ pictures/SIP_outgoing_call.vsd \ pictures/SIP_outgoing_operation_with_auth.eps \ pictures/SIP_outgoing_operation_with_auth.gif \ pictures/SIP_outgoing_operation_with_auth.vsd \ pictures/autotools.eps \ pictures/autotools.gif \ pictures/autotools.vsd \ pictures/nta-receiving-message.eps \ pictures/nta-receiving-message.gif BUILT_SOURCES = Doxyfile.rfc CLEANFILES = Doxyfile.rfc *.doxytags # ---------------------------------------------------------------------- # Sofia specific rules LDADD = $(openssl_LIBS) sofiasrcdir = ${top_srcdir}/libsofia-sip-ua sofiabuilddir = ${top_builddir}/libsofia-sip-ua AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(SOFIA_CFLAGS) \ $(openssl_CFLAGS) $(SOFIA_PLAT_CFLAGS) $(am__append_1) SOFIA_COVERAGE = $(COVERAGE_FLAGS) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files TAG_AWK = ${sofiasrcdir}/su/tag_dll.awk SUFFIXES = _tag_ref.c _tag.c INTERNAL_INCLUDES = \ -I${sofiasrcdir}/features -I${sofiabuilddir}/features \ -I${sofiasrcdir}/ipt -I${sofiabuilddir}/ipt \ -I${sofiasrcdir}/iptsec -I${sofiabuilddir}/iptsec \ -I${sofiasrcdir}/bnf -I${sofiabuilddir}/bnf \ -I${sofiasrcdir}/http -I${sofiabuilddir}/http \ -I${sofiasrcdir}/msg -I${sofiabuilddir}/msg \ -I${sofiasrcdir}/nth -I${sofiabuilddir}/nth \ -I${sofiasrcdir}/nta -I${sofiabuilddir}/nta \ -I${sofiasrcdir}/nea -I${sofiabuilddir}/nea \ -I${sofiasrcdir}/nua -I${sofiabuilddir}/nua \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sdp -I${sofiabuilddir}/sdp \ -I${sofiasrcdir}/sip -I${sofiabuilddir}/sip \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sresolv -I${sofiabuilddir}/sresolv \ -I${sofiasrcdir}/tport -I${sofiabuilddir}/tport \ -I${sofiasrcdir}/stun -I${sofiabuilddir}/stun \ -I${sofiasrcdir}/url -I${sofiabuilddir}/url \ -I${sofiasrcdir}/su -I${sofiabuilddir}/su PHONY = built-sources clean-built-sources $(am__append_3) VALGRIND = valgrind VALGRINDFLAGS = --tool=memcheck # Scripts @HAVE_LCOV_TRUE@LCOV_UNCOVERED = ${top_srcdir}/scripts/uncovered @HAVE_LCOV_TRUE@LCOV_REPORT = ${top_srcdir}/scripts/lcov-report # Report directory @HAVE_LCOV_TRUE@lcovdir = ${top_builddir}/lcov # Options @HAVE_LCOV_TRUE@GENHTML_OPTIONS = --show-details --legend \ @HAVE_LCOV_TRUE@ $(am__append_2) # Fancy shell command that expands to directory relative to top_builddir @HAVE_LCOV_TRUE@expand_subdir = `pwd|sed "s'\`cd ${top_builddir};pwd\`''"` SOFIA_SILENT = @ LIBTOOL_FLAGS = --silent # From Automake 1.9.6 - LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(LIBTOOL_FLAGS) \ $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) LINK = ${SOFIA_SILENT}test "${SOFIA_SILENT}" != @ || echo ' LINK $@'; \ $(LIBTOOL) --tag=CC --mode=link $(LIBTOOL_FLAGS) \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: _tag_ref.c _tag.c .c .lo .o $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.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 libsofia-sip-ua/docs/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu libsofia-sip-ua/docs/Makefile .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.am: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): Doxyfile: $(top_builddir)/config.status $(srcdir)/Doxyfile.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ Doxyfile.version: $(top_builddir)/config.status $(srcdir)/Doxyfile.version.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ sofia-footer.html: $(top_builddir)/config.status $(srcdir)/sofia-footer.html.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(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 installdirs: 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: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) 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) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) 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) @HAVE_LCOV_FALSE@clean-local: 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-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 mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: all check install install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am 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-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-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am # Including Doxyfile.rfc in dist breaks make manpages Doxyfile.rfc: Makefile.am $(AWK) 'END { b="\\"; q="\\\""; \ print "# Autogenerated aliases for RFCs "from" .. "to ; \ print "ALIASES += " b; \ for (i=from; i < to; i++) { \ print "RFC"i"=\"RFC "i"\" "b; \ }}' \ site=http://tools.ietf.org/html type= \ from=700 to=6500 \ /dev/null > $@ distclean-local: -rm -rf html built-sources: $(BUILT_SOURCES) clean-built-sources: -rm -rf $(BUILT_SOURCES) $(BUILT_SOURCES:%=$(srcdir)/%) *_tag_ref.c: $(TAG_AWK) _tag.c_tag_ref.c: $(AWK) -f $(TAG_AWK) NODLL=1 $(TAG_DLL_FLAGS) REF=$@ $< ../bnf/libbnf.la ../http/libhttp.la ../ipt/libipt.la ../iptsec/libiptsec.la \ ../msg/libmsg.la ../nea/libnea.la ../nta/libnta.la ../nth/libnth.la \ ../nua/libnua.la ../sdp/libsdp.la ../sip/libsip.la ../soa/libsoa.la \ ../sresolv/libsresolv.la ../stun/libstun.la ../su/libsu.la \ ../tport/libtport.la ../url/liburl.la: cd $(@D) && $(MAKE) $(@F) checklib: $(noinst_LTLIBRARIES) $(check_LTLIBRARIES) valcheck: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) valcheck-am valcheck-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS # Run tests with valgrind in valcheck-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ list='$(TESTS)'; \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ if case $$tst in \ run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ $${dir}$$tst ;; \ esac ; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ echo "XPASS: $$tst"; \ ;; \ *) \ echo "PASS: $$tst"; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xfail=`expr $$xfail + 1`; \ echo "XFAIL: $$tst"; \ ;; \ *) \ failed=`expr $$failed + 1`; \ echo "FAIL: $$tst"; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ echo "SKIP: $$tst"; \ fi; \ done; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="All $$all tests passed"; \ else \ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all tests failed"; \ else \ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ skipped="($$skip tests were not run)"; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ report=""; \ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ report="Please report to $(PACKAGE_BUGREPORT)"; \ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ echo "$$dashes"; \ echo "$$banner"; \ test -z "$$skipped" || echo "$$skipped"; \ test -z "$$report" || echo "$$report"; \ echo "$$dashes"; \ test "$$failed" -eq 0; \ else :; fi # # Generate pretty coverage report (unless it has been already done) # @HAVE_LCOV_TRUE@lcov: @HAVE_LCOV_TRUE@ @-test -r ${lcovdir}${expand_subdir}/lcov.info \ @HAVE_LCOV_TRUE@ || make lcov-report # Generate pretty coverage report based on current coverage data @HAVE_LCOV_TRUE@lcov-report: @HAVE_LCOV_TRUE@ sub=${expand_subdir} odir=${lcovdir}$$sub ; \ @HAVE_LCOV_TRUE@ rm -rf $$odir ; mkdir -p $$odir && \ @HAVE_LCOV_TRUE@ ${LCOV_REPORT} ${GENHTML_OPTIONS} \ @HAVE_LCOV_TRUE@ --title "${PACKAGE_NAME}-${PACKAGE_VERSION}$$sub" \ @HAVE_LCOV_TRUE@ --srcdir=${srcdir} -o $$odir # Rerun checks before generating report @HAVE_LCOV_TRUE@lcov-rerun: clean-lcov @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) lcov-report # Show all uncovered lines as errors @HAVE_LCOV_TRUE@uncovered: @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} # Run check in current dir and show all uncovered lines as errors @HAVE_LCOV_TRUE@covcheck: @HAVE_LCOV_TRUE@ -find . -name "*.gcda" | xargs rm -rf @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} @HAVE_LCOV_TRUE@clean-local:: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true @HAVE_LCOV_TRUE@clean-lcov: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true # Rules from depend2.am (GENERIC = TRUE, SUBDIROBJ = FALSE, %FASTDEP% = am_fastdepCC) silenced. .c.o: @test "${SOFIA_SILENT}" != @ || echo ' COMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(COMPILE) -c -o $@ $< .c.lo: @test "${SOFIA_SILENT}" != @ || echo ' LTCOMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(LTCOMPILE) -c -o $@ $< # endif # 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: sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/docs/conformance.docs000066400000000000000000001036751223300710500236620ustar00rootroot00000000000000/* -*- html -*- */ /** @page sofia_sip_conformance SIP and SDP Protocol Features in Sofia-SIP This document describes how Sofia-SIP stack supports specifications listed below.
RFC 3261
RFC 2617
RFC 3262
RFC 3263
RFC 3265
RFC 2806
RFC 2976
RFC 3311
RFC 3313
RFC 3323
RFC 3326
RFC 3325
RFC 3327
RFC 3329
RFC 3361
RFC 3420
RFC 3428
RFC 3486
RFC 3515
RFC 3581
RFC 3608
RFC 3680
RFC 3824
RFC 3840
RFC 3841
RFC 3842
RFC 3856
RFC 3857
RFC 3858
RFC 3859
RFC 3860
RFC 3891
RFC 3892
RFC 3903
RFC 4028
RFC 4168
RFC 4320
RFC 4488
RFC 5057
RFC 4566
RFC 2327
RFC 3264
RFC 3266
RFC 3312
RFC 3388
RFC 3407
RFC 3524
RFC 3551
RFC 3556
RFC 3605
RFC 3890
Feature Supported Notes
@RFC3261: Basic SIP Protocol The SIP registration and dialog level implementation enables the application to operate as a SIP UA, SIP proxy or a redirect server according to the @RFC3261. The @RFC3261 functionality is divided into five layers: -# message syntax and encoding -# transport -# transaction -# transaction user (UAS and UAC cores, proxy core) -# SIP elements: user agent client and server, proxies, registrars  
@RFC3261 Sections 19 and 20:
Syntax and encoding
The supported @RFC3261 methods are: @b REGISTER, @b OPTIONS, @b INVITE, @b ACK, @b CANCEL, @b BYE, as well as extension methods INFO, PRACK, SUBSCRIBE, NOTIFY, UPDATE, MESSAGE, REFER, and PUBLISH. Sofia-SIP supports the following SIP headers as specified in @RFC3261 or its extensions (generating, parsing and syntax checking): @ref sip_accept "Accept", @ref sip_accept_encoding "Accept-Encoding", @ref sip_accept_language "Accept-Language", @ref sip_alert_info "Alert-Info" (extension in @VERSION_1_12_7), @ref sip_allow "Allow", @ref sip_authentication_info "Authentication-Info", @ref sip_authorization "Authorization", @ref sip_call_id "Call-ID" ("i"), @ref sip_call_info "Call-Info", @ref sip_contact "Contact" ("m"), @ref sip_content_disposition "Content-Disposition", @ref sip_content_encoding "Content-Encoding" ("e"), @ref sip_content_language "Content-Language", @ref sip_content_length "Content-Length" ("l"), @ref sip_content_type "Content-Type" ("c"), @ref sip_cseq "CSeq", @ref sip_date "Date", @ref sip_error_info "Error-Info", @ref sip_expires "Expires", @ref sip_from "From" ("f"), @ref sip_in_reply_to "In-Reply-To", @ref sip_max_forwards "Max-Forwards", @ref sip_min_expires "Min-Expires", @ref sip_mime_version "MIME-Version", @ref sip_organization "Organization", @ref sip_p_asserted_identity "P-Asserted-Identity" (extension in @VERSION_1_12_7), @ref sip_p_preferred_identity "P-Preferred-Identity" (extension in @VERSION_1_12_7), @ref sip_priority "Priority", @ref sip_proxy_authenticate "Proxy-Authenticate", @ref sip_proxy_authorization "Proxy-Authorization", @ref sip_proxy_require "Proxy-Require", @ref sip_record_route "Record-Route", @ref sip_refer_sub "Refer-Sub" (@VERSION_1_12_5), @ref sip_remote_party_id "Remote-Party-ID" (extension in @VERSION_1_12_7), @ref sip_reply_to "Reply-To" (extension in @VERSION_1_12_7), @ref sip_require "Require", @ref sip_retry_after "Retry-After", @ref sip_route "Route", @ref sip_server "Server", @ref sip_subject "Subject" ("s"), @ref sip_supported "Supported" ("k"), @ref sip_timestamp "Timestamp", @ref sip_to "To" ("t"), @ref sip_unsupported "Unsupported", @ref sip_user_agent "User-Agent", @ref sip_via "Via" ("v"), @ref sip_warning "Warning", and @ref sip_www_authenticate "WWW-Authenticate". Unknown headers (extension headers) are supported and can be passed to/received from application as name-value pairs. It is possible to extend SIP parser in run-time with header-specific parsers. - Automatic escaping of reserved characters has not been implemented. - Using NUL (zero byte) in double-quoted strings has not been implemented
@RFC3261 Section 18:
UDP and TCP transports
UDP and TCP on both IP4 and IP6 are supported. The UDP size limit of 1300 bytes is enforced by default. If limit is exceeded, TCP is tried instead. If TCP connection is refused, UDP is tried if message size is less than 64 kilobytes. Limit is adjustable via parameter NTATAG_UDP_MTU(). TCP connections are reused by client. However, server closes connections after idle time of 30 minutes (by default). The idle time limit is adjustable with TPTAG_IDLE() (given as argument to nta_agent_add_tport() or nta_agent_create()). Server tries to use same TCP connection to return response as the request was received. Only one SIP message is accepted per UDP message, as per @RFC3261. There is experimental support for SCTP, too.
@RFC3261 Section 17:
Transactions
Transaction state engines function as specified in @RFC3261 section 17. There is special handling of methods @b INVITE, @b ACK, and @b CANCEL. There are two modes for transaction state engines, User-Agent and Proxy modes. Default values for SIP timers are those specified by @RFC3261. The values for T1, T1x64, T2 and T4 can be changed via configuration tags defined in . The SIP timer C is implemented from @VERSION_1_12_7. Also, its value can be changed via configuration tag NTATAG_TIMER_C() defined in .  
@RFC3261 Section 26:
Security
TLS and SIPS URIs has been implemented. Currently, TLS does not require certificate from client nor it does check it if one is provided. Missing: - Authorizing connections with TLS certificates - S/MIME
@RFC2617: HTTP Digest Authentication Sofia-SIP includes authentication client and server modules implementing HTTP Digest authentication. HTTP Digest is a simple challenge-response authentication scheme defined in @RFC2617 based on the UA sending a checksum calculated over specific values in response to a challenge sent by the server (proxy or UA). Checksum calculation supports MD5 (@RFC1321). The algorithm for calculating MD5 digest hash can be MD5, MD5sess or be @RFC2069-compatible algorithm. The quality-of-protection (qop) parameters "auth", "auth-int" and none (missing) are supported. The "opaque" parameter is supported. The SIP authentication headers supported (generating, parsing and syntax checking) are: @ref sip_authorization "Authorization", @ref sip_authentication_info "Authentication-Info", @ref sip_proxy_authenticate "Proxy-Authenticate", @ref sip_proxy_authentication_info "Proxy-Authentication-Info", @ref sip_proxy_authorization "Proxy-Authorization", and @ref sip_www_authenticate "WWW-Authenticate". SIP interface to the modules is implemented as defined in @RFC3261 (sections 8.1.3.5, 22.2, 22.3, 22.4). An @RFC2617 header @ref sip_proxy_authentication_info "Proxy-Authentication-Info" is not listed in @RFC3261 but it is nevertheless supported by Sofia-SIP. Missing: - Using nextnonce - Mutual authentication
@RFC3262: PRACK and 100rel PRACK method is supported within dialog as defined in RFC3262. Semantics of reliable provisional responses are supported: - including 100rel Required header in provisional responses if request had 100rel - generation of PRACK based on 100rel option tag in Require header of a provisional response, and - automatic re-transmission of provisional responses. The SIP headers supported (generating, parsing and syntax checking) are @ref sip_rseq "RSeq" and @ref sip_rack "RAck".  
@RFC3263: Locating SIP Servers Support for SIP server address resolution from SIP or SIPS URI using NAPTR, SRV, A or AAAA records in DNS as defined in @RFC3263. - Resolving any other types of URIs than SIP or SIPS URIs, e.g., IM: or PRES: URIs.
@RFC3265: SIP Event Notifications SIP extensions for subscribing and processing asynchronous event notifications as defined in @RFC3265. Includes dialog level support for sending and refreshing SUBSCRIBE and receiving NOTIFY messages. The SIP headers explicitly supported (generating, parsing and syntax checking) are @ref sip_event "Event" ("o"), @ref sip_allow_events "Allow-Events", and @ref sip_subscription_state "Subscription-State" Note: currently there is no support for forked SUBSCRIBE requests. Application must take care of: - Subscribing, generating or processing specific event types and interpreting the content of event data is up to application
@RFC2806: tel URI Sofia-SIP supports handling of any URI type. Sofia-SIP parses tel: URIs. Missing: - Resolving the tel: URIs
@RFC2976: INFO INFO method is supported within a dialog natively. Not implemented: - Generating or processing contents of INFO requests
@RFC3311: UPDATE UPDATE method as defined in RFC3311. UPDATE allows a client to update parameters of a session (such as the set of media streams and their codecs) even within early dialogs. Offer-Answer negotiation with UPDATE is implemented in nua. Application must take care of: - Initiating UPDATE requests
@RFC3313: Media Authentication Sofia-SIP provides generic support for extension headers and parameters. P-Media-Authorization header is supported as an @ref sip_unknown "extension header". Application must take care of: - Passing the authorization token to QoS reservation request
@RFC3323: Privacy @ref sip_privacy "Privacy" header is supported (generating, parsing and syntax checking). Call-Id header is generated from cryptographically random id without host name or IP address. By default, @ref sip_contact "Contact" and @ref sip_via "Via" headers contain only IP address that can be dynamically allocated. Application can enter any SIP URI and display name to From header, e.g., @code Anonymous @endcode. Application must take care of: - Properly populating the URIs and display names within SIP headers - Not including any optional headers that could reveal identity - Generating of Privacy header with appropriate values - Generating of Proxy-Require: privacy - Using anonymous callback URIs etc.
@RFC3326: Reason Sofia-SIP supports @ref sip_reason "Reason" header (generating, parsing and syntax checking). Application must take care of: - Generating or processing Reason headers
@RFC3325: Asserted Identity Sofia-SIP supports @ref sip_p_asserted_identity "P-Asserted-Identity" and @ref sip_p_preferred_identity "P-Preferred-Identity" headers (generating, parsing and syntax checking). Also the non-standard header @ref sip_remote_party_id "Remote-Party-ID" is supported. @NEW_1_12_7. Not implemented: - id privacy - Recognizing trust domains and enforcing handling of headers based on those
@RFC3327: Path User-agent engine can add "path" option tag to Supported header of REGISTER requests. Sofia-SIP explicitly supports @ref sip_path "Path" header (generating, parsing and syntax checking).  
@RFC3329: Security Agreement Some support of the SIP Security Mechanism Agreement procedures. The client is able to insert Security-Client and Security-Verify header with fake @e d-ver value. Sofia-SIP explicitly supports (generating, parsing and syntax checking) @ref sip_security_client "Security-Client", @ref sip_security_server "Security-Server", and @ref sip_security_verify "Security-Verify" headers. Security-mechanism supported is "digest". Correct @e d-ver value is not calculated.
@RFC3361: DHCPv4 option for locating SIP servers. Sofia-SIP supports outbound proxy. Application must take care of: - passing outbound proxy name or address from DHCP client to Sofia-SIP stack.
@RFC3420: message/sipfrag Sofia-SIP passes the received SIP message headers to application which can create a message/sipfrag payload. Application must take care of: - processing the SIP message fragments
@RFC3428: MESSAGE MESSAGE method is supported natively.  
@RFC3486: Compressing SIP Sofia-SIP provides support for using comp=sigcomp parameters in @ref sip_via "Via" header and @ref url_t "SIP URIs", indicating support for compression. SigComp itself is not supported.
@RFC3515: REFER REFER method is supported natively. Sofia-SIP processes incoming REFER requests and generates NOTIFY with correct @ref sip_event "Event" header automatically. Further notifications can be automatically generated actions when nua_invite() is given referrer's nua handle in NUTAG_NOTIFY_REFER(). Sofia-SIP explicitly supports (generating, parsing and syntax checking) @ref sip_refer_to "Refer-To" ("r") SIP header. See also support for RFC 3891 and RFC 3892.  
@RFC3608: Service-Route Sofia-SIP supports @ref sip_service_route "Service-Route" that can be used to provide a mechanism by which a registrar may inform a registering UA of a service route. User-Agent will optionally use the route provided in @ref sip_service_route "Service-Route" header. The SIP header explicitly supported (generating, parsing and syntax checking) is @ref sip_service_route "Service-Route".  
@RFC3680: "reg" event Sofia-SIP supports generic SIP event support for subscribing SIP event packages and receiving notifications for them. Subscriptions are refreshed before expiration when needed and subscriptions are terminated on request. Sofia-SIP takes care of notified subscription states. UA can SUBSCRIBE to a registration state event package after sending initial REGISTER to, e.g., 3GPP network and use it to follow its registration status. Application must take care of: - Generating subscriptions for "reg" event - Processing notifications for "reg" event - Handling of XML document in notifications
@RFC3824: ENUM Tel URIs are supported in any headers including URI parameters, e.g., To, From, Contact headers, and Request-URI of the outgoing SIP request provided that the next hop is given as SIP or SIPS URI. Stack can not resolve E.164 number to address of next hop. A proxy in the network must resolve E.164 numbers with ENUM.
@RFC3840: Callee Capabilities Feature parameters can be added to SIP profiles and sent within Contact header of REGISTER request as header parameters. UAC can optionally generate media tags for Contact header using local media profile. Feature parameters can also be sent within any other SIP request as extension parameters of Contact header. Application must take care of: - Processing the feature parameters received in the Contact header
@RFC3841: Caller Preferences Built-in support for user-agent behavior. UAC can optionally generate Accept-Contact header using local media profile. SIP parser parses the Accept-Contact and Reject-Contact headers. ACK and CANCEL request messages sent have same values for Accept-Contact/Reject-Contact or Request-Disposition headers as the original request had. There are functions for calculating score for contacts. The SIP headers explicitly supported (generating, parsing and syntax checking) are: @ref sip_request_disposition "Request-Disposition" ("d"), @ref sip_accept_contact "Accept-Contact" ("a"), @ref sip_reject_contact "Reject-Contact" ("j"), Application must take care of: - UAS processing incoming Accept-Contact or Reject-Contact headers
@RFC3842: Message waiting event Sofia-SIP supports generic SIP event support for subscribing SIP event packages and receiving notifications for them. Subscriptions are refreshed before expiration when needed and subscriptions are terminated on request. Sofia-SIP takes care of notified subscription states. Application must take care of: - Generating subscriptions for "message-summary" event - Including correct @ref sip_event "Event" and @ref sip_accept "Accept" headers in the request (if needed) - Processing notifications for "message-summary" event - Handling of summary information in notifications
@RFC3856: Presence
@RFC3859: Common Profile for Presence
Sofia-SIP supports generic SIP event support for subscribing SIP event packages and receiving notifications for them. Subscriptions are refreshed before expiration when needed and subscriptions are terminated on request. Sofia-SIP takes care of notified subscription states. Note: Usage of pres: URI is supported only if the next hop URI to where to send SUBSCRIBE is a SIP URI (e.g. of outbound proxy). Resolving of pres: URIs by DNS is not supported. Application must take care of: - Generating subscriptions for "presence" event - Including correct @ref sip_event "Event" and @ref sip_accept "Accept" headers in the request (if needed) - Processing notifications for "presence" event - Handling of presence information in notifications
@RFC3857: "winfo" event template package
@RFC3858: winfo format
Sofia-SIP supports generic SIP event support for subscribing SIP event packages and receiving notifications for them. Subscriptions are refreshed before expiration when needed and subscriptions are terminated on request. Sofia-SIP takes care of notified subscription states. Application must take care of: - Generating subscriptions for winfo events - Including correct @ref sip_event "Event" and @ref sip_accept "Accept" headers in the request (if needed) - Processing notifications for winfo events: - Processing watcherinfo XML documents
@RFC3860: Common Profile for IM Sofia-SIP supports handling of any URI type. Sofia-SIP parses "im:" URIs. Application must take care of: - resolving the "im:" URI
@RFC3891: Replaces @ref sip_replaces "Replaces" header is explicitly supported (generating, parsing and syntax checking). Application must take care of: - generating @ref sip_replaces "Replaces" header from a dialog and matching a dialog with a Replaces header received
@RFC3892: Referred-By @ref sip_referred_by "Referred-By" header is explicitly supported (generating, parsing and syntax checking). Referred-by token can be sent and received in text-based SIP message body. Application must take care of: - Generating or processing @ref sip_referred_by "Referred-By" headers - Generating (and encrypting) or verifying (and decrypting) of Referred-by tokens
@RFC3903: PUBLISH PUBLISH method is supported natively. The SIP headers explicitly supported (generating, parsing and syntax checking) are @ref sip_etag "SIP-ETag" and @ref sip_if_match "SIP-If-Match". The user-agent engine keep published data refreshed until nua_unpublish() is called. Application must take care of: - Including correct @ref sip_event "Event" in the request - Permanently storing @SIPETag
@RFC4028: Session Timers The SIP session-timer ("timer") extension is supported. The session-expires value and refreshing party is negotiated in user-agent engine. When user-agent engine is responsible for refreshes, it will initiate re-INVITE or UPDATE transaction at regular intervals. If there has been no SIP activity in session during the refresh period, it will try to automatically terminate the call by sending a @b BYE request. The SIP headers explicitly supported (generating, parsing and syntax checking) are @ref sip_session_expires "Session-Expires" ("x") and @ref sip_min_se "Min-SE".  
@RFC4168: SCTP as Transport for SIP The transport=sctp URI parameter is supported. The SCTP transport protocol is supported as experimental. It is enabled with configure script argument --enable-sctp. The framing of SIP messages over SCTP is not specified clearly in @RFC4168. It is possible to send SIP messages smaller than 64K over SCTP.  
@RFC4320: Actions Addressing Identified Issues with SIP's Non-INVITE Transaction The action 1 (make the best use of provisional responses) is supported when NTATAG_EXTRA_100(1) is used with nua_create() or nta_agent_create(). The 100 Trying provisional response is sent after T2 is expired or when a retransmission is received after T2/2 after the initial request. The action 2 (remove the useless late-response storm) is supported by default. The 408 timeout response is not forwarded by default (it's forwarding can be enabled with NTATAG_PASS_408(1), however). Application must include NTATAG_EXTRA_100(1) with nua_create() or nta_agent_create() tags.
@RFC4488: Suppression of REFER Implicit Subscription Sofia-SIP supports @ref sip_refer_sub "Refer-Sub" header (generating, parsing and syntax checking). The implicit subscription is suppressed by @nua, if the @ReferSub: true header is included in the REFER request (@ref nua_refer "on server side") or response (@ref nua_i_refer "on client side"). @NEW_1_12_5 The REFER client application must include SIPTAG_REFER_SUB_STR("true") in the nua_refer() tags.
@RFC5057: Multiple Dialog Usages in SIP Sofia-SIP provides function sip_response_terminates_dialog() that can be used to determine the effect of error response with dialog. The nua UA engine uses sip_response_terminates_dialog(). The client application must either use NUA or sip_response_terminates_dialog().
Feature Supported Notes
@RFC4566: SDP: Session Description Protocol Generic support (generating, parsing and syntax checking) for SDP. The SDP @ref sdp_version_t "v=", @ref sdp_origin_t "o=", @ref sdp_connection_t "c=", @ref sdp_bandwidth_t "b=", @ref sdp_time_t "t=", @ref sdp_repeat_t "r=", @ref sdp_zone_t "z=", @ref sdp_key_t "k=", @ref sdp_attribute_t "a=", and @ref sdp_media_t "m=" lines are separated and parsed. The "e=", "p=", "s=", and "i=" lines are separated. The attributes "a=sendrecv", "a=sendonly", "a=recvonly", "a=inactive", @ref sdp_rtpmap_s "a=rtpmap", and "a=fmtp" are parsed. The implementation partially implements @RFC4566. Note that definition of 'token' was updated in @RFC4566 and the parser has not been updated yet. @RFC4566 obsoletes - @RFC2327: SDP (Session Description Protocol) - @RFC3266: IP6 in SDP
@RFC3264: SDP Offer/Answer Negotiation Generating and processing offers or answers. - "a=fmtp" parameters are not taken into account when generating or processing answer
@RFC3312: Preconditions Sofia-SIP provides generic support for attribute lines that conform to SDP syntax. Sofia-SIP supports handling SIP feature tags in @ref sip_proxy_require "Proxy-Require", @ref sip_require "Require", @ref sip_supported "Supported" ("k"), and @ref sip_unsupported "Unsupported" header. Application must take care of: - Semantics and handling of preconditions - Reservation of resources
@RFC3388: Grouping of Media Lines Sofia-SIP provides generic support for attribute lines that conform to SDP syntax. @RFC3388 defines mid, group, LS and FID are predefined strings to be used within attribute line Application must take care of: - Generating or processing the attribute lines - Grouping the media for transport accordingly
@RFC3407: Capability Declaration Sofia-SIP provides generic support for attribute lines that conform to SDP syntax. Application must take care of: - Defining sqn, cdsc, cpar etc. strings needed in a= line - Generating or processing the attribute lines - Capability negotiation itself
@RFC3524: SRF Sofia-SIP provides generic support for attribute lines that conform to SDP syntax. Application must take care of: - Defining SRF string needed in a= line - Generating or processing the attribute lines
@RFC3551: RTP/AVP Sofia-SIP recognizes the RTP payload types for well-known audio and video codecs defined in @RFC3551. Application must take care of: - Audio or video processing - Generating a=rtpmap or a=fmtp lines when needed
@RFC3556: Bandwidth Sofia-SIP provides generic support for attribute lines that conform to SDP syntax. Application must take care of: - Generating or processing RS and RR bandwidth modifiers - Semantics of bandwidth allocation
@RFC3605: RTCP attribute Sofia-SIP provides generic support for attribute lines that conform to SDP syntax. Application must take care of: - Discovering port numbers - Generating or processing the RTCP attribute lines
@RFC3890: TIAS Sofia-SIP provides generic support for attribute lines that conform to SDP syntax. Application must take care of: - Generating or processing TIAS bandwidth modifiers - Generating or processing the maxprate attribute lines
*/ /* Overflow: @RFC4566: SDP: Session Description Protocol Obsoletes RFC2327 and RFC3266.   @RFC3320: SigComp Support for using SigComp for compression and decompression of SIP/SDP messages. By default, dynamic compression is used. Decompression using UDVM   @RFC3321: SigComp Extended operations Support for SigComp extended operations. - Explicit Acknowledgment Scheme - Shared Compression - Checkpoint State - Implicit Deletion for Dictionary Update @RFC3325: Asserted Identity Explicit support (generating, parsing and syntax checking) for the following SIP headers: P-Asserted-Identity, P-Preferred-Identity - Recognizing trust domains and enforcing handling of headers based on those @RFC3485: SIP/SDP Dictionary Support for SigComp static compression using SIP/SDP dictionary.   - Implicitly registered user identities @RFC3959: early-session Early-session value can be used within Content-Disposition, Supported and Require headers. - Generating of Content-Disposition, Supported and Require - Handling of multipart bodies with early and session SDP */sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/docs/docguide.docs000066400000000000000000000177251223300710500231530ustar00rootroot00000000000000/*! @page docguide Documentation Guidelines @section doxygen Using Doxygen Doxygen is a document generation program, used by many C/C++ projects. Its home page is at http://www.doxygen.org. The Sofia documentation is written using Doxygen. Doxygen works by extracting the documentation data both from the actual C/C++ source code and from the specially formatted comments. The comments can contain some Javadoc-like @ref doxycommands "special commands". In general the the style of the comments and documentation should follow the javadoc style guide. A Doxygen comment must either contain reference about the entity it is describing, e.g., command \@file when describing files: @verbatim /** * @file foo.c * * Implementation of foo. The foo takes care of grokking xyzzy. * * @author Jaska Jokunen \n * * @date Created: Wed Oct 20 15:06:51 EEST 2004 jasjoku */ @endverbatim Usually the entity that is documented comes straight after the documentation comment. For example, documenting a function happens like this: @anchor orch @verbatim /** * Orches a candometer. If orching candometer is not possible, it * tries to schadule hearping. * * @param[in] k pointer to a candometer * @param[in] level orching level * @param[out] return_hearping return value for schaduled hearping * * @return * The function orch() returns the candometer value, or #ERROR upon an error. * If the returned value is 0, the newly schaduled hearping is returned in * @a return_hearping. */ int orch(cando_t *k, int level, hearping_t *return_hearping) { ... } @endverbatim @subsection doxyfile Doxyfile and Doxyfile.conf The doxygen options are specified through a configuration file, Doxyfile. As a convention, a module-specific Doxyfile includes a common file libsofia-sip-ua/docs/Doxyfile.conf. This makes it possible to keep the module-specific Doxyfiles as clean as possible: @code PROJECT_NAME = "ipt" OUTPUT_DIRECTORY = ../docs/ipt INPUT = ipt.docs . @INCLUDE = ../Doxyfile.conf TAGFILES += ../docs/docs/doxytags=../docs TAGFILES += ../docs/su/doxytags=../su GENERATE_TAGFILE = ../docs/ipt/doxytags @endcode From the file above, you can observe some conventions. The Doxygen-generated HTML documentation is collected in @b docs subdirectory at top level. A separate output directory is created for each submodule under it. Doxytags for the module are generated in the @e doxytags file in the output directory. @subsection module_docs Module documentation in \.docs Each module contains a documentation file containing at least the module mainpage called @e \.docs. There should be the module boilerplate information, for instance the following example is excerpt contents of file @e ipt.docs: @verbatim /** @MODULEPAGE "ipt" - Utility Module @section ipt_meta Module Meta Information Utility library for IP Telephony applications. @CONTACT Pekka Pessi @STATUS @SofiaSIP Core library @LICENSE LGPL @section ipt_overview Overview This module contain some routines useful for IPT applications, like - ... - ... */ @endverbatim @section doxycommands Common Doxygen Commands In this section we go through the most common Doxygen commands. All the commands are explained in the manual. The commands include - @ref doxystyle "style commands (@@a, @@b, @@c, @@e, @@em, @@p)" - @ref doxyfuncs "function parameters and return values (@@param, @@return, @@retval)" @subsection doxystyle Style Commands - @a, @b, @c, @e The text style can be changed with @@b @b (bold), @@c @c (code), or @@e @e (italic) commands. Function argument names use style command @@a. For example, a sentence "The @b Content-Type header @a ct specifies the @e media-type of the message body, e.g., @c audio/amr would be AMR-encoded audio." is produced with commands like @code The @b Content-Type header @a ct specifies the @e media-type of the message body, e.g., @c audio/amr would be AMR-encoded audio. @endcode The style commands have synonyms, e.g., @@em and @@e mean same, as well as @@c and @@p. @subsection doxyfuncs Function Parameters and Return Values - @param, @return, @retval Parameters to a function are documented with @@param commands. (See the @ref orch "orch()" function above.) As a convention, the data flow direction [in], [out] or [in,out] is indicated in the brackets after the @@param command keyword. Return values can be documented in two alternative manners, either using @@return command (see @ref orch "orch()") or @@retval command. The latter is used if the function returns a small number of possible values, e.g., enumeration or success/failure indication. @verbatim /**Schadule hearping. * * The function schadule() schadules a hearping. * * @param[in] h pointer to hearping * * @retval 0 hearping was successful * @retval -1 an error occurred */ int schadule(hearping_t *h) { ... } @endverbatim @subsection doxyexamples Example Blocks - @code, @endcode An example code fragment can be included using @@code and @@endcode commands. @verbatim /**Destroy a hearping. * * The function hearping_destroy() deinitializes a hearping and * reclaims the memory allocated for it. * * @param[in,out] h pointer to pointer to hearping * * The function clears the pointer to hearping, so it must be called * with a pointer to pointer: * @code * hearping_destroy(&x->hearping); * @endcode */ void hearping_destroy(hearping_t **h) { @endverbatim @subsection docpar Paragraphs The command @@par can be used to divide text into paragraphs. The text on the same line with @@par is used as a subtitle for the paragraph. The commands @@date, @@note, @@bug, @@todo, @@sa (See Also) and @@deprecated can be used to add common paragraphs to documentation entries. @subsection docfiles Documenting Files In most files there is documentation entry for the file itself. It is usually at top after the LGPL reference, containing @@file command or alias @@CFILE/@@IFILE. There are Emacs macros for creating the boilerplate entry. @subsection docgrouping Grouping Entries When the structure of the documentation does not follow directory or file structure, it is possible to use grouping commands @@defgroup and @@ingroup. The command @@defgroup creates a group, and @@ingroup adds an entry to an group. @subsection doclinking Creating Links Normally, Doxygen creates links to classes (and C structs) when it encounters the struct/class name. It is also possible to add links to functions, type names and variables. If the function name is followed by pair of parenthesis (), Doxygen creates a link to it. If a type name or variable is prefixed with hash @#, Doxygen creates a link to it. It is also possible to create links with freely selected link to documentation entries with @@link and @@endlink commands. When the link target is a named page, section, or subsection, it is possible to use the @@ref command. @subsection doctext Writing Body Text The main body of the documentation is specified with @@mainpage command. The contents of the @@mainpage entry become the HTML home page of the documentation set. In each documentation set generated with Doxygen there can be only one @@mainpage command. Commands @@section, @@subsection, and @@subsubsection can be used to structure the body text. It is also possible to add individual HTML pages to the documentation. It happens with @@page command. These individual pages are like the home page added with @@mainpage, they can be accessed with the Related Pages link from the navigation bar. @subsection docimages Adding Images Images are added with @@image command. As the different documentation formats support different image formats, the @@image has list the image file name for each supported documentation format. The following example uses bitmap image for HTML documentation and Encapsulate PostScript for print documents: @code @image html sip-parser.gif @image latex sip-parser.eps @endcode */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/docs/mainpage.docs000066400000000000000000000627711223300710500231520ustar00rootroot00000000000000/* -*- text -*- */ /**@mainpage Sofia SIP User Agent Library - sofia-sip-ua @section Introduction This document contains automatically generated reference documentation for Sofia-SIP components. Some introductory material and pointers to the example code are also included. For a list of module specific pages, see @ref subdirs "source tree structure" or direct links to submodules:
nua su features soa sdp nta tport sresolv sip msg url stun iptsec nea nth http bnf ipt @section who Contact Information You can download latest Sofia SIP from the project home page at Sourceforge.net. Please contact us if you have questions regarding this software:
  • Pekka Pessi
  • Kai Vehmanen
Or post to the Sofia-SIP mailing list:
  • mailto:sofia-sip-devel@lists.sourceforge.net
  • http://lists.sourceforge.net/lists/listinfo/sofia-sip-devel
*/ /**@page building Source Tree Structure @section subdirs Directory Structure In libsofia-sip-ua, there are subdirectories for different modules listed below. Terminal and high-level libraries used for both signaling and media: Common runtime library: - "su" - sockets, memory management, threads - "sresolv" - Asynchronous DNS resolver - "ipt" - IPT utility library SIP Signaling: - "nua" - SIP User Agent library - "nea" - SIP Event API - "iptsec" - Digest authentication for HTTP and SIP - "nta" - SIP transaction engine - "tport" - Message transport - "sip" - SIP messages and headers - "msg" - Message handling - "url" - URL handling - "url" - low level parsing HTTP subsystem: - "nth" - HTTP protocol engine - "http" - HTTP messages and headers SDP processing: - "soa" - SDP Offer/Answer engine for SIP - "sdp" - SDP parser Other: - "stun" - STUN library Features provided by Sofia-SIP library: - "features" - Features provided by Sofia SIP Documentation: - "docs" - Doxygen reference documentation */ /** @page styleguide C Style Guide This document gives general guidelines on generic C style and code formatting within Sofia-SIP. The guidelines include identifier naming conventions, indenting convention, and tool usage directions. Please note that C style is always a matter of taste. @section naming Naming Conventions Generally, identifiers within each module are prefixed with the name of that module. For instance, the functions within http parser module @b http have prefix @c http_. Identifiers composed of multiple words have an underscore "_" between the words, the words themselves are in lower case. For instance, http_request_create(). Macros should be in upper case. File names should be in lower case using underscore as delimiter if needed. Normal typedefs have suffix @c _t, however, function types have suffix @c _f. The enum names also sometimes have @c _e, struct names have @c _s and union names @c _u. It is recommended that type itself is typedef'ed, not a pointer to the type. It should be clear from variable declaration if the variable is a pointer or not. @code typedef struct foo_s foo_t; typedef int f_fun(foo_t *f, char const *s); @endcode Struct and union members should have common prefix. For instance, @code struct foo_s { int f_len; char *f_name; fun_f *f_fun; }; @endcode This prefix makes it easier to find where members are used. @section formatting Indenting and Formatting code Indentation in Sofia-SIP C code generally follows the @e K&R style with indent of 2 characters (so you can use the default "GNU" c-style in Emacs). The maximum line length should be 80 characters. For example, @code void kluge(int foo) { if (foo) { bar(); } else { switch (baz()) { case a: eeny(); break; case b: meeny(); break; default: moe(); break; } } } @endcode The default indentation can be achieved with GNU indent with options @code -nbad -bap -bbo -nbc -br -brs -c33 -cd33 -ncdb -ce -ci2 -cli0 -cp33 -cs -d0 -di1 -nfc1 -nfca -hnl -i2 -ip0 -l79 -lp -npcs -nprs -npsl -saf -sai -saw -nsc -nsob -nss @endcode Loops without condition use @c for @c (;;) instead of @c while @c (1). @code for (;;) { foo(); if (bar()) break; baz(); } @endcode There should be whitespace on both sides of infix operators, except . or ->, which require no space, or , (comma) which requires space only after). There should be whitespace between a keyword and parenthesis following it, but no whitespace between an identifier and parenthesis following it. E.g., @code while (i++ < n) baz(); for (;;) { x->x_foo(); if (bar()) break; z.z_baz++; } return (13 * i); @endcode */ /** @page programming Programming Guide @section porting Writing Portable Code Most of Sofia-SIP software is written as portable. All core modules are (or at least should be) written in ANSI C 89 with some ANSI C 99 features. If there are platform specific parts, they are collected to separate C files and isolated from the rest of the software with a wrapper interface. SU module handles abstraction to OS specific functionality such as memory management, sockets, threads and time functions. @subsection ansi_99 ANSI C 99 features The following ANSI C 99 features are to be used in Sofia-SIP software: - Integer types - functions va_copy() and snprintf() The following ANSI C 99 features shall not be used in Sofia-SIP software: - definition of a variable in the middle of function code. (so always define your variables in the beginning of the block) @subsection port_ints Integer Types As you should know, the length of native storage size depends on hardware, OS and compiler. This means in practice that the length of int or long is not necessarily 32 bits. As a consequence, you need to make sure that the value you intend to store in the int, can actually fit in int on different platforms. As a rule of thumb, if the integer value can exceed 8 bits, you should use types that have a defined length. Nevertheless its OK to use native integer types if you bear in mind what was said above. The original reason for having only native data type was performance. The int type is always stored in the fastest (and usually biggest size) possible. Never assume anything on the length of the type. Alway use sizeof() operator to find out the length. C 99 standard defines the following fixed length data types: - int64_t - uint64_t - int32_t - uint32_t - int16_t - uint16_t - int8_t - uint8_t To use these data types you must include the header, which takes care of including correct file. If @b su includes are not available, you must include the following code segment to each file where you plan to use them: @code #if HAVE_STDINT_H #include #elif HAVE_INTTYPES_H #include #else #error Define HAVE_STDINT_H as 1 if you have , \ or HAVE_INTTYPES_H if you have #endif @endcode @subsection port_byte_sex Byte order The host byte order on different platforms vary. When you do only local processing, need not to worry about the byte order. But as soon as you start writing code that send or receives anything to the network, you need to start worrying. If you wish to convert the byte order, it is simply done by calling one the following functions: The htonl() function converts the unsigned integer hostlong from host byte order to network byte order. The htons() function converts the unsigned short integer hostshort from host byte order to network byte order. The ntohl() function converts the unsigned integer netlong from network byte order to host byte order. The ntohs() function converts the unsigned short integer netshort from network byte order to host byte order. You need to include or to use these functions. @subsection port_struct Packing structures By default, compilers usually arrange structures so that they are quick to access. This means that most fields in the structure start at the 32 bit boundary. If you need to conserve memory, you may use structure packing. To tell the compiler that you only need certain amount of bits to store a variable, you can use bit-fields. Compiler may or may not pack the bit-fields. @code struct foo { unsigned bar:5; unsigned foo:2; unsigned :0; int something; } @endcode If compiler decides to pack this structure, this code generates a structure that has @a bar and @a foo in the first seven bits, and then @a something beginning from the next 32 bit boundary. One problem arises when using packed bit-fields: on ARM it is generally not possible to access a 32 bit field that does not start from the 32-bit boundary. Hence the example has the :0 padding member in the structure. Seems handy but beware: initialization of this structure fails on some ARM gcc compilers. (Ask Kai Vehmanen for details). A way to force packing of a structure is to use preprocessor directive @c @#pragma(pack). This directive is compiler specific, so if you plan to write truly portable code, you cannot use it. We have used it in some parts of the Sofia-SIP though. Only alternative is to write functions that fetch the desired bits from a 32 bit field with bit operations; not very handy and error prone. The same aligment problem also arises if you cast for example char buffer to a int32_t. You can only read int32_t from the 32bit boundary on ARM platform. So be careful. As a conclusion, when using bit-fields and stucture packing, beware of the pitfalls. If you don't really need to use them (as in parsing binary protocols), don't use them. @section file_organization File and Directory Structure A Sofia-SIP library module can be defined as a subdirectory under the libsofia-sip-ua directory hierarchy that contains a file \.docs (where the \ of course referes to the actual name of the module). In case you like to start developing a new module, please contact Sofia-SIP development team so that they can help you to set up the basic module for you. An overview of the contents of a module directory: - file \.docs \n Main documentation file for the module. See @ref module_docs for more information - subdirectory pictures \n Contains any pictures/images that are needed by the module documentation. The file formats to use are GIF (for html pages) and EPS (for latex). If some program (e.g. MS Visio) is used to create the pictures, also the original files must be stored here.\n (Note that old modules may have "images" subdirectory instead of "pictures") - files Makefile.am \n See section @ref build "dealing with GNU Autotools" below. - (optionally) source code file(s) of the module and module tests. The source code file(s) can also be located in subdirectories if necesary. @section oo_with_c Writing Object-Oriented Code While C does not provide any special object-oriented features on its own, it is possible to program in object-oriented way using C, too. Sofia code make use of many object-oriented features while being written entirely in C. @subsection oo_hiding Data Hiding Data hiding is a practice that makes separation between two modules very clear. Outside code cannot directly access the data within a module, but it has to use functions provided for that purpose. Data hiding also makes it easier to define a protocol between two objects - all communication happens using function calls. How to implement data hiding in C? Easiest answer is to only declare data structures in the header files, not to define them. We have a typedef #msg_t for @link msg_s struct msg_s @endlink in , but the actual structure is defined in "msg_internal.h". Programs outside @b msg module does not have access to the @link msg_s struct msg_s @endlink, but they have to to access the #msg_t object through method functions provided in . The @b msg implementation is also free to change the internal layout of the structure, only keeping the function interface unmodified. @subsection oo_interface Interfaces Abstract interface is another object-oriented practice used in Sofia. Parser headers, defined in , is a good example of abstract interface. The type for message headers, #msg_header_t, is defined using two C structures @link msg_common_s struct msg_common_s @endlink (#msg_common_t), and @link msg_hclass_s struct msg_hclass_s @endlink (#msg_hclass_t). Abstract interface is achieved using virtual function table in #msg_hclass_t structure, bit like C++ typically implements abstract classes and virtual functions. For implemenation of each header, the function table is initialized with functions responsible for decoding, encoding and manipulating the header structure. Unlike C++, the class of the object (#msg_hclass_t) is represented by a real data structure which also contains header-specific data, like header name. @dontinclude sip_basic.c @skipline msg_hclass_t sip_contact_class @skip {{ @until }}; @subsection oo_derived Inheritance and Derived Objects Inheritance is a object-oriented practice that has limited use in Sofia. Most common example of inheritance is use of #su_home_t. Many objects are derived from #su_home_t, which means that they can use the various home-based memory management functions from . In this sence, inheritance means that a pointer to a derived object can be casted as a pointer to a base object. In other words, the derived object must have the base object at the beginning of its memory area: @code struct derived { struct base base[1]; int extra; char *data; }; @endcode There are three alternatives to cast a pointer to derived to a pointer to base: @code struct base *base1 = (struct base *)derived; struct base *base2 = &derived->base; struct base *base3 = derived->base; @endcode The third alternative works because base was used as a 1-element array. @subsection oo_templates Templates There are a few template types implemented as macros in Sofia libraries. They include hash table, defined in , which can be used to define hash tables types and accessor functions for different object, and red-black tree, defined in . @section memory Memory Management The home-based memory management is useful when a lot of memory blocks are allocated for given task. The allocations are done via the memory home, which keeps a reference to each allocated memory block. When the memory home is then freed, it will free all memory blocks to which it has reference. This simplifies application logic because application code does not need to keep track of the allocated memory and free every allocated block separately. See documentation of and @ref su_alloc "memory managment tutorial" for more information of memory management services. @subsection contextdata Memory management of context data A typical example of use of a memory home is to have a memory home structure (#su_home_t) as part of operation context information structure. @code /* context info structure */ struct context { su_home_t ctx_home[1]; /* memory home */ other_t *ctx_other_stuff; /* example of memory areas */ ... }; /* context pointer */ struct context *ctx; /* Allocate memory for context structure and initialize memory home */ ctx = su_home_clone(NULL, sizeof (struct context)); /* Allocate memory and register it with memory home */ ctx->ctx_other_stuff = su_zalloc(ctx->ctx_home, sizeof(other_t)); ... processing and allocating more memory ... /* Release registered memory areas, home, and context structure */ su_home_zap(ctx->ctx_home); @endcode @subsection combining Combining allocations Another place where home-based memory management makes programmers life easier is case where a sub-procedure makes multiple memory allocations and, in case the sub-procedure fails, all the allocations must be released and, in case the sub-procedure is succesfull, all allocations must be controlled by upper level memory management. @code /* example sub-procedure. top_home is upper-level memory home */ int sub_procedure( su_home_t *top_home, ... ) { su_home_t temphome[1] = { SU_HOME_INIT(temphome) }; ... allocations and other processing ... /* was processing successfull ? */ if (success) { /* ok -> move registered allocated memory to upper level memory home */ su_home_move( top_home, temphome ); } /* destroy temporary memory home (and registered allocations) */ /* Note than in case processing was succesfull the memory */ /* registrations were already moved to upper level home. */ su_home_deinit(temphome); /* return ok/not-ok */ return success; } @endcode @section testing Testing Your Code See for example of how to write module tests with macros provided by Sofia. Here are some ideas of what you should test: - "Smoke test" \n See that the module compiles, links and executes. - Module API functions should be tested with\n - valid args - not valid args - Aim for 100% line coverage\n (If there is a line of code that you have not tested, you don't know if its working.) \n For selected part of code you should also aim for 100% branch/path coverage.\n But be anyway reasonable with these because in practise complete coverage is next to impossible to achive (so 80% is ok in practise). - Create test to check assumptions and/or tricks used in code.\n For example if you rely on some compiler feature, create a test that will fail with a compiler that does not have that feature. @subsection check Running Module Tests Automake, which is used to build Sofia SIP, has builtin support for unit tests. To add an automatically run test to your module, you just have to add the following few lines to your module's Makefile.am (of course, you have to write the test programs, too): @code TESTS = test_foo test_bar check_PROGRAMS = test_foo test_bar test_foo_SOURCES = foo.c foo.h test_foo_LDADD = -L. -lmy test_bar_SOURCES = bar.c bar.h test_foo_LDADD = -L. -lmy @endcode Each test program should either return zero for success or a non-zero error code in its main function. Now when you run "make check", @b my_test_foo and @b my_test_bar will be built and then run. Make will print a summary of how the tests went. As these tests are run from the build system, the tests must be non-interactive (no questions asked) and not rely on any files that are not in version control system. Sofia SIP's top-level makefile contains a recursive check target, so you can use "cd sofia-sip ; make check" to run all the existing tests with a single command. @section build Dealing with GNU Autotools Sofia-SIP build system is based on the GNU tools automake, autoconf and libtool. This toolset has become the de-facto way of building Linux software. Because of this there is a lot of publicly available documentation about these tools, and of course, lots and lots of examples. A good introduction to these tools is available at developer.gnome.org. Autobook provides more detailed documentation for autoconf and automake. The GNU make manual is also a good source of information. @subsection autogen_sh autogen.sh At top-level there is a shell script called @b autogen.sh. It calls a convenient tool called @b autoreconf which will generate configure script for you. It also fixes the mode bits: the mode bits are not stored in darcs version control system. @code $ sh autogen.sh $ ./configure ... with your configure options ... @endcode @subsection configure_ac configure.ac The @b configure.ac file (older autoconf versions used also @b configure.in) contains the primary configuration for autoconf. configure.ac contains checks for all external libraries, non-standard language and compiler features that are needed to build the target module. This file is created by the developer of the module. @subsection sofia_m4 m4 files Sofia-SIP's own autoconf macros are stored in the top-level direcry called @b m4. These macros, along with all other macros used by @b configure.ac, are copied into the module-specific @b aclocal.m4 file by an utility called aclocal. Contact Sofia-SIP development team, if you need changes to these files. @subsection aclocal_m4 aclocal.m4 The aclocal.m4 contains the definitions of the autoconf macros used in @b configure.ac. This file is generated by aclocal command. @subsection Makefile_am Makefile.am Makefile.am is where you define what programs and libraries should be built, and also what source files are needed to create them. When you run automake, it creates the file Makefile.in. This file is created by the developer of the module. @subsection configure configure When you run configure script, it performs all the checks defined in @b configure.ac and then replaces all @b xxx.in files with equivalent @b xxx files. All @c @@FOO@@ variables in the source @b *.in files are replaced with values found during the configuration process. For instance the variable @c @@srcdir@@ in @b Makefile.in is replaced in @b Makefile with the source directory path (useful when compiling outside the main source tree). This file is generated by autoconf command. @subsection config_status config.status This script stores the last parameters given to configre command. If necessary you can rerun the last given configure script (with given parameters) by using command "./config.status -r" or "./config.status --recheck". This file is generated by configure script. @subsection config_cache config.cache This file contains results of the various checks that configure script performed. In case the configure script failed, you might try to delete this file and run the configure script again. This file is generated by configure script. @subsection Makefile Makefile The @b Makefile contains the actual rules how to build the target libraries and program. It is used by the @c make program. @b Makefile is generated from @b Makefile.in when you run @c autoconf command. Ensure that "make dist" and "make install" targets work. This file is generated by config.status and configure scripts. @subsection config_h config.h This file contains C language defines of various confurable issues. This file is generated by config.status and configure script. @subsection sofia_sip_configure_h sofia-sip/su_configure.h This file contains C language defines describing how the Sofia SIP UA library is configured. This file is generated by config.status and configure script. */ /** @page debug_logs Debugging Logs The Sofia-SIP components can output various debugging information. The detail of the debugging output is determined by the debugging level. The level is usually module-specific and it can be modified by module-specific environment variable. There is also a default level for all modules, controlled by environment variable #SOFIA_DEBUG. The environment variables controlling the logging and other debug output are as follows: - #SOFIA_DEBUG Default debug level (0..9) - #NUA_DEBUG User Agent engine (nua) debug level (0..9) - #SOA_DEBUG SDP Offer/Answer engine (soa) debug level (0..9) - #NEA_DEBUG Event engine (nea) debug level (0..9) - #IPTSEC_DEBUG HTTP/SIP autentication module debug level (0..9) - #NTA_DEBUG Transaction engine debug level (0..9) - #TPORT_DEBUG Transport event debug level (0..9) - #TPORT_LOG If set, print out all parsed SIP messages on transport layer - #TPORT_DUMP Filename for dumping unparsed messages from transport - #SU_DEBUG su module debug level (0..9) The defined debug output levels are: - 0 SU_DEBUG_0() - fatal errors, panic - 1 SU_DEBUG_1() - critical errors, minimal progress at subsystem level - 2 SU_DEBUG_2() - non-critical errors - 3 SU_DEBUG_3() - warnings, progress messages - 5 SU_DEBUG_5() - signaling protocol actions (incoming packets, ...) - 7 SU_DEBUG_7() - media protocol actions (incoming packets, ...) - 9 SU_DEBUG_9() - entering/exiting functions, very verbatim progress In addition to the macros mentioned above, there is also functions for printing logging messages: - su_llog(), su_vllog() - su_perror(), su_perror2() The log level can be set (to a level defined in a configuration file, for instance) with following functions - su_log_set_level(), su_log_soft_set_level() The log output can be redirected to, e.g., system log or loggin server, with su_log_redirect(). */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/docs/pictures/000077500000000000000000000000001223300710500223405ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/docs/pictures/SIP_basic_incoming_operation.eps000066400000000000000000007534551223300710500306330ustar00rootroot00000000000000Gg%!PS-Adobe-3.0 EPSF-3.0 %%Creator: ImageMark Software Labs %%For: () () %%Title: V:\work\rinnerah\sofia\SIP basic incoming operation.eps %%CreationDate: () () %%BoundingBox: 0 0 372 193 %%DocumentProcessColors: Black %%ColorUsage:Color %%DocumentFonts: Helvetica %%+Helvetica-Bold %%+Helvetica-Oblique %%+Helvetica-BoldOblique %%+Times-Roman %%+Times-Bold %%+Times-Italic %%+Times-BoldItalic %%+Courier %%+Courier-Bold %%+Courier-Oblique %%+Courier-BoldOblique %%+Symbol %%DocumentSuppliedResources: procset Adobe_level2_AI5 1.2 0 %%+ procset Adobe_screens_AI5 1.0 0 %%+ procset Adobe_typography_AI5 1.0 0 %%+ procset Adobe_ColorImage_AI6 1.1 0 %%+ procset Adobe_blend_AI5 1.0 0 %%+ procset Adobe_pattern_AI5 1.0 0 %%+ procset Adobe_Illustrator_AI5 1.0 0 %AI5_FileFormat 3.0 %AI3_ColorUsage: Color %AI3_TemplateBox: 0 0 372 193 %AI3_TileBox: 0 0 372 193 %AI3_DocumentPreview: None %%Template: %%PageOrigin:0.0000 0.0000 %AI7_GridSettings: 72 8 72 8 1 0 0.8 0.8 0.8 0.9 0.9 0.9 %%EndComments %%BeginProlog %%BeginResource: procset Adobe_level2_AI5 1.2 0 %%Title: (Adobe Illustrator (R) Version 5.0 Level 2 Emulation) %%Version: 1.2 0 %%CreationDate: (04/10/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /Adobe_level2_AI5 25 dict dup begin put /packedarray where not { userdict begin /packedarray { array astore readonly } bind def /setpacking /pop load def /currentpacking false def end 0 } if pop userdict /defaultpacking currentpacking put true setpacking /initialize { Adobe_level2_AI5 begin } bind def /terminate { currentdict Adobe_level2_AI5 eq { end } if } bind def mark /setcustomcolor where not { /findcmykcustomcolor { 0 6 packedarray } bind def /findrgbcustomcolor { 1 5 packedarray } bind def /setcustomcolor { exch aload pop 0 eq { pop 4 { 4 index mul 4 1 roll } repeat 5 -1 roll pop setcmykcolor } { pop 3 { 1 exch sub 3 index mul 1 exch sub 3 1 roll } repeat 4 -1 roll pop setrgbcolor } ifelse } def } if /gt38? mark {version cvr cvx exec} stopped {cleartomark true} {38 gt exch pop} ifelse def userdict /deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt put userdict /level2? systemdict /languagelevel known dup { pop systemdict /languagelevel get 2 ge } if put /level2ScreenFreq { begin 60 HalftoneType 1 eq { pop Frequency } if HalftoneType 2 eq { pop GrayFrequency } if HalftoneType 5 eq { pop Default level2ScreenFreq } if end } bind def userdict /currentScreenFreq level2? {currenthalftone level2ScreenFreq} {currentscreen pop pop} ifelse put level2? not { /setcmykcolor where not { /setcmykcolor { exch .11 mul add exch .59 mul add exch .3 mul add 1 exch sub setgray } def } if /currentcmykcolor where not { /currentcmykcolor { 0 0 0 1 currentgray sub } def } if /setoverprint where not { /setoverprint /pop load def } if /selectfont where not { /selectfont { exch findfont exch dup type /arraytype eq { makefont } { scalefont } ifelse setfont } bind def } if /cshow where not { /cshow { [ 0 0 5 -1 roll aload pop ] cvx bind forall } bind def } if } if cleartomark /anyColor? { add add add 0 ne } bind def /testColor { gsave setcmykcolor currentcmykcolor grestore } bind def /testCMYKColorThrough { testColor anyColor? } bind def userdict /composite? level2? { gsave 1 1 1 1 setcmykcolor currentcmykcolor grestore add add add 4 eq } { 1 0 0 0 testCMYKColorThrough 0 1 0 0 testCMYKColorThrough 0 0 1 0 testCMYKColorThrough 0 0 0 1 testCMYKColorThrough and and and } ifelse put composite? not { userdict begin gsave /cyan? 1 0 0 0 testCMYKColorThrough def /magenta? 0 1 0 0 testCMYKColorThrough def /yellow? 0 0 1 0 testCMYKColorThrough def /black? 0 0 0 1 testCMYKColorThrough def grestore /isCMYKSep? cyan? magenta? yellow? black? or or or def /customColor? isCMYKSep? not def end } if end defaultpacking setpacking %%EndResource %%BeginResource: procset Adobe_typography_AI5 1.0 1 %%Title: (Typography Operators) %%Version: 1.0 %%CreationDate:(03/26/93) () %%Copyright: ((C) 1987-1993 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_typography_AI5 54 dict dup begin put /initialize { begin begin Adobe_typography_AI5 begin Adobe_typography_AI5 { dup xcheck { bind } if pop pop } forall end end end Adobe_typography_AI5 begin } def /terminate { currentdict Adobe_typography_AI5 eq { end } if } def /modifyEncoding { /_tempEncode exch ddef /_pntr 0 ddef { counttomark -1 roll dup type dup /marktype eq { pop pop exit } { /nametype eq { _tempEncode /_pntr dup load dup 3 1 roll 1 add ddef 3 -1 roll put } { /_pntr exch ddef } ifelse } ifelse } loop _tempEncode } def /TE { StandardEncoding 256 array copy modifyEncoding /_nativeEncoding exch def } def % /TZ { dup type /arraytype eq { /_wv exch def } { /_wv 0 def } ifelse /_useNativeEncoding exch def pop pop findfont _wv type /arraytype eq { _wv makeblendedfont } if dup length 2 add dict begin mark exch { 1 index /FID ne { def } if cleartomark mark } forall pop /FontName exch def counttomark 0 eq { 1 _useNativeEncoding eq { /Encoding _nativeEncoding def } if cleartomark } { /Encoding load 256 array copy modifyEncoding /Encoding exch def } ifelse FontName currentdict end definefont pop } def /tr { _ax _ay 3 2 roll } def /trj { _cx _cy _sp _ax _ay 6 5 roll } def /a0 { /Tx { dup currentpoint 3 2 roll tr _psf newpath moveto tr _ctm _pss } ddef /Tj { dup currentpoint 3 2 roll trj _pjsf newpath moveto trj _ctm _pjss } ddef } def /a1 { /Tx { dup currentpoint 4 2 roll gsave dup currentpoint 3 2 roll tr _psf newpath moveto tr _ctm _pss grestore 3 1 roll moveto tr sp } ddef /Tj { dup currentpoint 4 2 roll gsave dup currentpoint 3 2 roll trj _pjsf newpath moveto trj _ctm _pjss grestore 3 1 roll moveto tr jsp } ddef } def /e0 { /Tx { tr _psf } ddef /Tj { trj _pjsf } ddef } def /e1 { /Tx { dup currentpoint 4 2 roll gsave tr _psf grestore 3 1 roll moveto tr sp } ddef /Tj { dup currentpoint 4 2 roll gsave trj _pjsf grestore 3 1 roll moveto tr jsp } ddef } def /i0 { /Tx { tr sp } ddef /Tj { trj jsp } ddef } def /i1 { W N } def /o0 { /Tx { tr sw rmoveto } ddef /Tj { trj swj rmoveto } ddef } def /r0 { /Tx { tr _ctm _pss } ddef /Tj { trj _ctm _pjss } ddef } def /r1 { /Tx { dup currentpoint 4 2 roll currentpoint gsave newpath moveto tr _ctm _pss grestore 3 1 roll moveto tr sp } ddef /Tj { dup currentpoint 4 2 roll currentpoint gsave newpath moveto trj _ctm _pjss grestore 3 1 roll moveto tr jsp } ddef } def /To { pop _ctm currentmatrix pop } def /TO { iTe _ctm setmatrix newpath } def /Tp { pop _tm astore pop _ctm setmatrix _tDict begin /W { } def /h { } def } def /TP { end iTm 0 0 moveto } def /Tr { _render 3 le { currentpoint newpath moveto } if dup 8 eq { pop 0 } { dup 9 eq { pop 1 } if } ifelse dup /_render exch ddef _renderStart exch get load exec } def /iTm { _ctm setmatrix _tm concat 0 _rise translate _hs 1 scale } def /Tm { _tm astore pop iTm 0 0 moveto } def /Td { _mtx translate _tm _tm concatmatrix pop iTm 0 0 moveto } def /iTe { _render -1 eq { } { _renderEnd _render get dup null ne { load exec } { pop } ifelse } ifelse /_render -1 ddef } def /Ta { pop } def /Tf { dup 1000 div /_fScl exch ddef % selectfont } def /Tl { pop 0 exch _leading astore pop } def /Tt { pop } def /TW { 3 npop } def /Tw { /_cx exch ddef } def /TC { 3 npop } def /Tc { /_ax exch ddef } def /Ts { /_rise exch ddef currentpoint iTm moveto } def /Ti { 3 npop } def /Tz { 100 div /_hs exch ddef iTm } def /TA { pop } def /Tq { pop } def /Th { pop pop pop pop pop } def /TX { pop } def /Tk { exch pop _fScl mul neg 0 rmoveto } def /TK { 2 npop } def /T* { _leading aload pop neg Td } def /T*- { _leading aload pop Td } def /T- { _hyphen Tx } def /T+ { } def /TR { _ctm currentmatrix pop _tm astore pop iTm 0 0 moveto } def /TS { currentfont 3 1 roll /_Symbol_ _fScl 1000 mul selectfont 0 eq { Tx } { Tj } ifelse setfont } def /Xb { pop pop } def /Tb /Xb load def /Xe { pop pop pop pop } def /Te /Xe load def /XB { } def /TB /XB load def currentdict readonly pop end setpacking %%EndResource %%BeginResource: procset Adobe_screens_AI5 1.2 0 %%Title: (Adobe Illustrator (R) Version 5.0 Custom Halftone Screens ProcSet) %%Version: 1.2 0 %%CreationDate: (03/24/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking systemdict begin userdict /Adobe_screens_AI5 15 dict dup begin put /initialize { Adobe_screens_AI5 begin /screenid deviceDPI 600 gt composite? not or { -1 } { deviceDPI currentScreenFreq dup dup 60 ge exch 150 le and deviceDPI 300 le and { pop 60 } if div 1.41421 div 0.5 add cvi } ifelse def 2 screenid eq { /customsize 16 def /customdata /customdata2 def setcustomscreen } if 3 screenid eq { /customsize 24 def /customdata /customdata3 def setcustomscreen } if 4 screenid eq { /customsize 16 def /customdata /customdata4 def setcustomscreen } if 5 screenid eq { /customsize 20 def /customdata /customdata5 def setcustomscreen } if 6 screenid eq { /customsize 24 def /customdata /customdata6 def setcustomscreen } if 7 screenid eq { /customsize 28 def /customdata /customdata7 def setcustomscreen } if 8 screenid eq { /customsize 16 def /customdata /customdata8 def setcustomscreen } if } def /terminate { currentdict Adobe_screens_AI5 eq { end } if } def /setcustomscreen { deviceDPI customsize div 0 { 1 add 2 div customsize mul cvi exch 1 add 2 div customsize mul cvi exch customsize mul add customdata load exch get 256 div } setscreen } def /customdata2 28 28 mul string def currentfile customdata2 readhexstring 4180E8694988E2634382EA6B4B8AE061A01939C8A81737C2A21B3BCAAA1636C0 F8795998F6775796FA7B5B9AF57656952ED8B80727D6B60F2FDABA0626D5B50E 4E8DE6674786EE6F4F8EE5664685ED6EAD1434C6A61F3FCEAE1232C5A51E3ECD F3745493FE7F5F9EF1725291FD7E5E9D24D3B30C2CDEBE0222D1B10A2ADDBD04 4483EB6C4C8BE1624281E96A4A89E364A31C3CCBAB1535C1A11A3AC9A91838C3 FB7C5C9BF4755594F97A5A99F778589730DBBB0525D4B40D2DD9B90828D7B710 508FE4654584EC6D4D8CE7684887EF70AF1131C4A41D3DCCAC1333C7A72040CF F0715190FC7D5D9CF2735392FF80609F21D0B00929DCBC0323D2B20B2BDFBF01 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata3 28 28 mul string def currentfile customdata3 readhexstring 011DC7F5E73D0421CBF3E43A021EC8F6E83E0522CCF2E43A2B648BC4A0762F68 8AC39E732C658CC5A177306989C29D72D5B6521A6192D9B55219608FD6B6531B 6193DAB451185F8FFCEE440C28D2FCED430B27D1FDEF450C29D3FBEC420A26D0 BEA77D366F83BCA77C356E87BFA87E377082BBA67B346D86145B99E0AE4A1259 98DFB14E155C9AE1AD4A115897DEB04D0623CDF4E63C0420CAF8EA400723CDF4 E53B031FC9F7E93F316988C19F752E678EC6A378326A88C09F742D668DC6A278 DBB350175E91D8B8551C6395DCB24F165D90D7B7541C6294FAEC420925CFFFF1 470E2BD5F9EB410824CEFEF0460D2AD4BAA57A336C85BEAA80397180B9A47933 6B84BDA97F387181105797DDAF4C145A9CE3AB480F5696DDAE4B13599BE2AC49 021EC8F6E83E0522CCF2E43A011DC7F5E73D0421CBF3E43A2C658CC5A1773069 89C29D722B648BC4A0762F688AC39E73D6B6531B6193DAB451185F8FD5B6521A 6192D9B55219608FFDEF450C29D3FBEC420A26D0FCEE440C28D2FCED430B27D1 BFA87E377082BBA67B346D86BEA77D366F83BCA77C356E87155C9AE1AD4A1158 97DEB04D145B99E0AE4A125998DFB14E0723CDF4E53B031FC9F7E93F0623CDF4 E63C0420CAF8EA40326A88C09F742D668DC6A278316988C19F752E678EC6A378 DCB24F165D90D7B7541C6294DBB350175E91D8B8551C6395F9EB410824CEFEF0 460D2AD4FAEC420925CFFFF1470E2BD5B9A479336B84BDA97F387181BAA57A33 6C85BEAA803971800F5696DDAE4B13599BE2AC49105797DDAF4C145A9CE3AB48 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata4 28 28 mul string def currentfile customdata4 readhexstring 1139B8E0FAD2531B133BBAE2F8D05119417180A6AE9A7B4B437382A5AD987949 C08867272F6F92CAC28A66262E6E90C8E8DE5F070F37B6F2EADD5E060E36B5F0 FED6571F173FBEE6FDD5561E163EBDE5AB9E7F4F477786A1A99D7E4E467685A3 2C6C96CEC68E62222A6A95CDC58D64240C34B3F6EED95A020A32B1F5EDDB5C04 143CBBE3F9D1521A123AB9E1FBD3541C447483A4AC997A4A427281A7AF9B7C4C C38B65252D6D91C9C1896828307093CBEBDC5D050D35B4F1E9DF60081038B7F3 FCD4551D153DBCE4FFD758201840BFE7A89C7D4D457584A2AA9F8050487887A0 296994CCC48C63232B6B97CFC78F61210931B0F4ECDA5B030B33B2F7EFD85901 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata5 28 28 mul string def currentfile customdata5 readhexstring 010B34C3EBFCF7CE3F16020C35C4EDFBF6CD3E15102552A4D6EADDB5632B1126 54A5D5EADCB3622A3958768499C19E8C7C5E3A59778498C19D8B7B5DC8A99370 47334C7587AFC9AA936F46324B7485AEF1E5BC6B1E0A2351A3D8F2E4BC6A1E09 2351A2D7FFF9D14219050F38C6EFFEF9D04118040E37C6EFE8E0B7662D142856 A8D3E7DFB7652D132856A7D4BF9C8E7F603D5B7A8195BE9A8E7E603C5B798297 314A7389B2CCAD906D442F497289B1CBAC926E4508214FA1DBF4E2B9671B0720 4EA0DAF4E3BA691C030D36C5EDFBF6CD3F16010C34C3ECFDF8CF4017122654A6 D4E9DDB4622A112553A5D6EBDEB5642C3B59788397C09C8B7C5D3A58778599C2 9E8C7D5FCAAB926E46314B7486AFC8AA947048334D7587B0F2E4BB691D082250 A1D8F1E6BD6B1F0A2452A3D9FDF8CF4118030E36C5EEFFFAD1421A050F38C7F0 E6DFB6642C132755A7D3E8E1B8662E152957A8D2BE9A8D7E5F3B5A798296BF9B 8F80613D5C7B80952F487188B1CAAC916D443049728AB3CCAE906C43061F4D9F DAF3E2BA681C07214FA0DBF5E1B8671A00000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata6 28 28 mul string def currentfile customdata6 readhexstring 081A44B6E0F2FDECC150250C091B45B6E1F3FCEBC04F240C1D336199C7D8DCD3 A56C37221E33619AC8D7DBD2A46B36214864798091AEB1958C7E694C49657A81 90ADB0948B7D684BB99D8475593C405C7888A1BEBA9E8574583B3F5B7888A0BD E4CBAA712E1215326098CFE8E4CCA9712D1114315F97CEE7F5F1C6552B040719 43B5DFFAF6F0C6542A03061842B4DEF9FFEDC352270E0B1C47B8E3F4FEECC251 260D0A1C46B7E2F4DAD5A76E39232035639CCAD5D9D4A66D38231F34629BC9D6 AF938E806A4E4A677C838FABAE928D7F694D4A667B828FAC3E5A778AA3BFBC9F 8772563A3D597689A2BEBB9F8673573A14305E97D1EAE6CDA76F2B0F132F5D96 D0E9E5CDA8702C10051742B3DDFCF8EEC4522801041641B2DDFBF7EFC5532902 091B45B6E1F3FCEBC04F240C081A44B6E0F2FDECC150250C1E33619AC8D7DBD2 A46B36211D336199C7D8DCD3A56C372249657A8190ADB0948B7D684B48647980 91AEB1958C7E694CBA9E8574583B3F5B7888A0BDB99D8475593C405C7888A1BE E4CCA9712D1114315F97CEE7E4CBAA712E1215326098CFE8F6F0C6542A030618 42B4DEF9F5F1C6552B04071943B5DFFAFEECC251260D0A1C46B7E2F4FFEDC352 270E0B1C47B8E3F4D9D4A66D38231F34629BC9D6DAD5A76E39232035639CCAD5 AE928D7F694D4A667B828FACAF938E806A4E4A677C838FAB3D597689A2BEBB9F 8673573A3E5A778AA3BFBC9F8772563A132F5D96D0E9E5CDA8702C1014305E97 D1EAE6CDA76F2B0F041641B2DDFBF7EFC5532902051742B3DDFCF8EEC4522801 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata7 28 28 mul string def currentfile customdata7 readhexstring 01061B44B7E1F5FEFBE6BD4A210C01071B45B8E1F6FDFBE6BC4A200B09132A54 A7D1EAF5EED9B05D331609142B55A8D2EAF4EED9AF5C32161D2D3D6993C1CBE0 CEC59B7140301E2E3D6A93C0CADFCDC49A713F3047576C7B828DA2B6A48F867E 6F5A48576C7C828CA1B6A38F867E6E59BAAA958A78634E4451667A8498ADBAAB 968977624E4350657A8398ADE3D4C99F7539251A273C6892C2D7E4D4C89E7539 241A273B6891C1D6F8F2DDB460371005122A53A7D0ECF9F2DDB360360F051229 53A6D0EBFFFDE8BE4C220D03081D46B9E3F7FFFCE7BD4B210D02071C46B8E2F7 F3F0DBB15E34180B152C56A9D3E8F3EFDAB05D34170A142C55A9D2E9DFCCC69C 7341321F2F3F6B94BFC9DECCC59C7241311F2E3E6A94BFCAB5A38E8780705B49 596D7D808BA0B4A28D877F6F5B48586D7C818BA043506479859AAFBCAC978876 614C424F64798499AEBBAB968977624D19263B6791C3D8E5D6C79D7337231825 3A6690C3D7E5D5C79E74382304112952A5CFEDFAF0DBB25E350E03102851A5CE ECF9F1DCB25F360E01071B45B8E1F6FDFBE6BC4A200B01061B44B7E1F5FEFBE6 BD4A210C09142B55A8D2EAF4EED9AF5C321609132A54A7D1EAF5EED9B05D3316 1E2E3D6A93C0CADFCDC49A713F301D2D3D6993C1CBE0CEC59B71403048576C7C 828CA1B6A38F867E6E5947576C7B828DA2B6A48F867E6F5ABAAB968977624E43 50657A8398ADBAAA958A78634E4451667A8498ADE4D4C89E7539241A273B6891 C1D6E3D4C99F7539251A273C6892C2D7F9F2DDB360360F05122953A6D0EBF8F2 DDB460371005122A53A7D0ECFFFCE7BD4B210D02071C46B8E2F7FFFDE8BE4C22 0D03081D46B9E3F7F3EFDAB05D34170A142C55A9D2E9F3F0DBB15E34180B152C 56A9D3E8DECCC59C7241311F2E3E6A94BFCADFCCC69C7341321F2F3F6B94BFC9 B4A28D877F6F5B48586D7C818BA0B5A38E8780705B49596D7D808BA0424F6479 8499AEBBAB968977624D43506479859AAFBCAC978876614C18253A6690C3D7E5 D5C79E74382319263B6791C3D8E5D6C79D73372303102851A5CEECF9F1DCB25F 360E04112952A5CFEDFAF0DBB25E350E pop pop /customdata8 28 28 mul string def currentfile customdata8 readhexstring 050F2747B6D6EEF8FEF4DCBC4D2D1507111D375F9EC6E0E9EBE6CCA4653D1F13 2939556F8EA8C1D1D3C3AE9475573B2B4961717D808999B1B39B8B867F73634B B8A090827A6A5A42445C6C7C8492A2BAD8C8AA97785232222434546E8DACCADA F0E2CFA768401A0A0C1C365E9DC5E4F2FAF7DFBF50301802040E2646B5D5EDFC FFF5DDBD4E2E160806102848B7D7EFF9EAE7CDA5663E2014121E38609FC7E1E8 D2C2AF9576583C2C2A3A56708FA9C0D0B29A8A878074644C4A62727E818898B0 435B6B7B8593A3BBB9A19183796959412333536D8CADCBDBD9C9AB9677513121 0B1B355D9CC4E5F3F1E3CEA6673F1909030D2545B4D4ECFDFBF6DEBE4F2F1701 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop end end defaultpacking setpacking %%EndResource %%BeginResource: procset AGM_Gradient_Sep 1.0 0 %%Title: (AGM Gradient Procset) %%Version: 1.0 0 %%CreationDate: (4/26/96) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /AGM_Gradient_Sep 5 dict dup begin put /AGM_Gradient_Sep_private 100 dict def /initialize{ AGM_Gradient_Sep begin AGM_Gradient_Sep_private begin _compositeJob{ initializeSinglePassSeps }{ initializeMultiPassSeps }ifelse initializeSeps AGM_Gradient_private begin /_fillSD newSpotDict def /_rampSD newSpotDict def /_nCustomColorSD nd end AGM_Gradient_Sep_private { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall AGM_Gradient_Sep { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall end currentdict readonly pop end }def /terminate{ currentdict AGM_Gradient_Sep eq{ end }if }def AGM_Gradient_Sep_private begin /initializeSeps{ _noImage not _level2PS not and{ /_whiteBytes 1 makeByte8 pt /knockOut{ 8 setImageParms _whiteBytes /_image load 5 execImage }def /linealFill{ mySave 8 setImageParms _color{ _nCustomColorSD begin cyan magenta yellow black _spotColor{ spot1 begin /tintImage tintValue 1 exch sub makeByte8 def end spot2 begin /tintImage tintValue 1 exch sub makeByte8 def end }if end 4{ makeByte8 4 1 roll }repeat true 4 _nCustomColorSD ncolorimage }{ _nCustomColorSD/black get 1 exch sub makeByte8 _nCustomColorSD bwImage }ifelse myRestore }def }{ /knockOut{ gsave false setoverprint 1 setgray 0 0 1 1 rectfill grestore }def }ifelse /newSpotDict{ 11 dict dup begin /nSpots 2 def /spot1 7 dict def /spot2 7 dict def end }def /initSpotData { begin /name nd /tintImage nd /tintValue nd /spot_C nd /spot_M nd /spot_Y nd /spot_K nd end }def /initSpotDict{ begin /cyanInk false def /magentaInk false def /yellowInk false def /blackInk false def /cyan nd /magenta nd /yellow nd /black nd spot1 initSpotData spot2 initSpotData end }def /copySpotDict{ /_dst xp begin cyanInk magentaInk yellowInk blackInk cyan magenta yellow black spot1 spot2 end _dst begin /spot1 spot1 maxlength dict def /spot2 spot2 maxlength dict def spot2 copy pop spot1 copy pop /black xd /yellow xd /magenta xd /cyan xd /blackInk xd /yellowInk xd /magentaInk xd /cyanInk xd end }def /setCustomColor { 1 index /Black eq{ 6 1 roll 5 npop 1 exch sub setgray }{ 6 1 roll _ccAry1 astore exch dup null eq{ pop 0 }if setcustomcolor }ifelse }def /setCStop{ /_colorStyle exch pt _colorStyle 0 eq{ 0 0 0 4 -1 roll 1 exch sub _spotColor{ /_colorStyle 3 pt /Black 1 index 1 exch sub }if }if _colorStyle 2 eq{ 3 npop }if _rampSD _fillSD copySpotDict _colorStyle 4 eq{ pop 9 2 roll 3 npop 6 -2 roll } if _colorStyle 3 eq _colorStyle 4 eq or{ _fillSD begin exch dup spot1/name get eq{ spot1 spot2 }{ spot2 spot1 }ifelse begin begin /name xd 1 exch sub /tintValue xd 4{ tintValue mul 4 1 roll }repeat _spotColor not{ /tintValue null def }if end /tintValue 0 def end end }if _fillSD nsetcustomcolor }def /renderCMYK{ spot1/name get null eq spot2/name get null eq and dup not{ pop spot1 spotConverted }if dup not{ pop spot2 spotConverted }if }def /fill_ /fill load def /fillOvp{ currentoverprint{ _inRipSep{ currentcolorspace 0 get dup /DeviceGray eq 1 index /DeviceCMYK eq or{ pop currentcmykcolor add add add 0 eq{ newpath }if }{ /Separation eq{ currentcolor 0 eq{ newpath }if }if }ifelse }{ currentgray 1 eq{ newpath }if }ifelse }if fill_ }def /fill{ _nCustomColorSD begin renderCMYK { fillOvp }{ spot1 begin gsave name null ne{ spot_C spot_M spot_Y spot_K name tintValue setCustomColor }{ 1 setgray }ifelse fillOvp grestore end spot2 begin name null ne{ gsave true setoverprint spot_C spot_M spot_Y spot_K name tintValue setCustomColor fillOvp grestore }if end newpath }ifelse end }def /expandSpot{ _spotColor{ /_len xp _rampSD begin spot1 begin tintImage null ne{ tintImage _len expandOne /tintImage xd }if end spot2 begin tintImage null ne{ tintImage _len expandOne /tintImage xd }if end end }{ pop }ifelse }def /rampImage{ _rampSD begin _color{ /cyanInk _cyanData 0 ne def /magentaInk _magentaData 0 ne def /yellowInk _yellowData 0 ne def /blackInk _blackData 0 ne def _nSamples setImageParms _nSamples expandSpot _cyanData _magentaData _yellowData _blackData _nSamples 4 expandColor true 4 _rampSD ncolorimage }{ /cyanInk false def /magentaInk false def /yellowInk false def /blackInk true def _nSamples setImageParms _blackData _rampSD bwImage }ifelse end }def /nsetcustomcolor where{ pop }{ /nsetcustomcolor { /_nCustomColorSD xp _nCustomColorSD begin 4 copy /black xd /yellow xd /magenta xd /cyan xd 4 copy 0 ne /blackInk xd 0 ne /yellowInk xd 0 ne /magentaInk xd 0 ne /cyanInk xd end setcmykcolor }def }ifelse /nsetcustomcolorend where{ pop }{ /nsetcustomcolorend { /_nCustomColorSD null pt }def }ifelse }def /initializeSinglePassSeps{ /_decodeNorm [0 1] pt /_decodeInvert [1 0] pt /spotConverted { begin name null eq{ false }{ tintValue null eq tintImage null eq and{ true }{ false currentpagedevice/SeparationOrder get{name eq or}forall not }ifelse }ifelse end }def /dictImage { 20 dict dup begin /Dict xd /Decode xd /DataSource xd /ImageMatrix xd /BitsPerComponent xd /Height xd /Width xd /ImageType 1 def Dict end /_image load 1 execImage }def /bwImage{ begin gsave currentoverprint{ blackInk{ [/Separation /Black /DeviceGray{}] setcolorspace _decodeInvert dictImage }{ 5 npop }ifelse }{ /DeviceGray setcolorspace _decodeNorm dictImage }ifelse grestore end }def /ncolorimage where{ pop }{ /ncolorimage{ begin renderCMYK { cyanInk magentaInk and yellowInk and blackInk and not currentoverprint and { pop pop gsave cyanInk{ 8 copy [/Separation /Cyan /DeviceGray{}] setcolorspace 3 npop _decodeNorm dictImage }if magentaInk{ 8 copy [/Separation /Magenta /DeviceGray{}] setcolorspace 4 -1 roll 3 npop _decodeNorm dictImage }if yellowInk{ 8 copy [/Separation /Yellow /DeviceGray{}] setcolorspace 4 -2 roll 3 npop _decodeNorm dictImage }if blackInk{ 4 -3 roll [/Separation /Black /DeviceGray{}] setcolorspace 3 npop _decodeNorm dictImage }{ 8 npop }ifelse grestore }{ /_colorimage load 10 execImage }ifelse }{ 6 npop gsave spot1 begin name null ne tintImage null ne and{ [/Separation name /DeviceGray{}] setcolorspace 4 copy tintImage name /Black eq{ _decodeNorm }{ _decodeInvert }ifelse dictImage }{ 1 setgray fill }ifelse end spot2 begin true setoverprint name null ne tintImage null ne and{ [/Separation name /DeviceGray{}] setcolorspace tintImage name /Black eq{ _decodeNorm }{ _decodeInvert }ifelse dictImage }{ 4 npop 1 setgray fill }ifelse end grestore }ifelse end }def }ifelse }def /initializeMultiPassSeps{ /_isCMYKSep _cyanPlate _magentaPlate or _yellowPlate or _blackPlate or pt /invertXfer{ [ { 1 exch sub }/exec load systemdict /currenttransfer get exec /exec load ] cvx systemdict /settransfer get exec }def /ccThrough{ gsave 1 setCustomColor currentcmykcolor grestore add add add 0 ne }def /spotConverted { begin _isCMYKSep not{ false }{ name null eq{ false }{ tintValue null eq tintImage null eq and{ true }{ spot_C spot_M spot_Y spot_K name ccThrough }ifelse }ifelse }ifelse end }def /spotChannel { _isCMYKSep{ pop false }{ begin name null eq{ false }{ spot_C spot_M spot_Y spot_K name ccThrough }ifelse end }ifelse }def /getChannelData { _isCMYKSep dup{ pop renderCMYK }if { _blackPlate{ 4 1 roll 3 npop blackInk }{ _yellowPlate{ 4 2 roll 3 npop yellowInk }{ _magentaPlate{ 4 3 roll 3 npop magentaInk }{ 3 npop cyanInk }ifelse }ifelse }ifelse { true /nonZeroData }{ true /zeroData }ifelse }{ 4 npop spot1/name get null ne spot1 spotChannel and{ spot1/tintImage get dup null ne{ false /nonZeroData }{ pop false /noData }ifelse }{ spot2/name get null ne spot2 spotChannel and{ spot2/tintImage get dup null ne{ false /nonZeroData }{ pop false /noData }ifelse }{ false /noData }ifelse }ifelse }ifelse }def /renderChannelData { /_tmp xp _tmp /nonZeroData ne currentoverprint and{ pop _tmp /zeroData eq{pop}if 4 npop }{ _tmp /nonZeroData eq{ { invertXfer }if systemdict/image get 5 execImage }{ pop _tmp /zeroData eq{pop}if 4 npop knockOut }ifelse }ifelse }def /bwImage{ begin gsave dup dup dup getChannelData exch pop false exch renderChannelData grestore end }def /ncolorimage{ begin pop pop gsave spot2/name get null ne spot2 spotChannel and{ true setoverprint }if getChannelData renderChannelData grestore end }def }def end end defaultpacking setpacking %%EndResource %%BeginResource: procset AGM_Gradient 1.0 0 %%Title: (AGM Gradient Procset) %%Version: 1.0 0 %%CreationDate: (4/26/96) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /AGM_Gradient 20 dict dup begin put /AGM_Gradient_private 200 dict def /initialize { AGM_Gradient begin AGM_Gradient_private begin initializeVars /bd systemdict/mark get def /ed _level2PS { (>>) }{ (counttomark 2 idiv dup dict begin {def} repeat pop currentdict end) } ifelse cvx def _level2PS{ initializeLev2 }{ initializeLev1 }ifelse queryDevice initializeShading initializeOps _producingSeps{ AGM_Gradient_Sep/initialize get exec }{ initializeComposite }ifelse _illustrator{ /f{}def /F{}def /s{}def /S{}def /b{}def /B{}def }if /image where{ /image get /_image xd }if /colorimage where{ /colorimage get /_colorimage xd }if /rectfill where dup{ exch pop not _producingSeps or }{ not }ifelse { /rectfill{ gsave newpath 4 2 roll moveto 1 index 0 rlineto 0 1 index rlineto 1 index neg 0 rlineto pop pop closepath fill grestore }def }if /linealImage _noImage{ /rectImage load }{ _producingSeps{ AGM_Gradient_Sep/AGM_Gradient_Sep_private get begin /rampImage load end }{ /rampImage load }ifelse }ifelse def AGM_Gradient_private { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall AGM_Gradient { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall end currentdict readonly pop end }def /initializeAI { pop pop AGM_Gradient/AGM_Gradient_private get /_illustrator true put AGM_Gradient/initialize get exec AGM_Gradient begin }def /unload{ systemdict/languagelevel known{ systemdict/languagelevel get 2 ge{ userdict/AGM_Gradient_Sep 2 copy known{ undef }{ pop pop }ifelse userdict/AGM_Gradient 2 copy known{ undef }{ pop pop }ifelse }if }if }def /terminate{ currentdict AGM_Gradient eq{ end }if }def AGM_Gradient_private begin /initializeVars{ /_d255 256 array def 0 1 255{ _d255 exch dup 255 div put }bind for /_d255- 256 array def 0 1 255{ _d255- exch 1 _d255 2 index get sub put }bind for /_sSave nd /_dUserSpace matrix defaultmatrix def /_bUMatrix matrix def /_imageMatrix matrix def /_saveMatrix matrix def /_xm matrix def /_ccAry1 5 array def /_level2PS systemdict/languagelevel known dup{ pop systemdict/languagelevel get 2 ge }if def /_level3PS _level2PS systemdict/shfill known and def currentdict /_illustrator known not{ /_illustrator false def }if }def /initializeOps { AGM_Gradient begin currentdict/Bc known not{ /Bc{ _renderFlag 2 eq{ 6 npop }{ pushBSpace _rampIndex 0 eq{ pop pop setCStop }if linealFill popBSpace }ifelse }def }if currentdict/Bg known not{ /Bg{ 10 npop /_gradName xp /_renderFlag xp _renderFlag 2 ne{ _illustrator{ _of setoverprint }if _illustrator _eo and _renderFlag 3 eq or{ eoclip }{ clip }ifelse _gradNames _gradName 2 copy known{ get mark exch aload pop /_gradType xp 1 sub dup /_rampIndex xp /_maxRampIndex xp mark exch aload pop 0 0 }if pop pop getRampData }{ mark mark }ifelse }def }if currentdict/Bm known not{ /Bm{ _renderFlag 2 ne{ _gradType 0 eq{ linealRamp }{ radialGrad }ifelse }{ 6 npop }ifelse }def }if currentdict/Bh known not{ /Bh{ 2 npop /_yHi xp /_xHi xp /_radHilite _xHi 0 ne _yHi 0 ne or pt }def }if currentdict/Bn known not{ /Bn{ AGM_Gradient_private begin dict /_gradNames xp end }def }if currentdict/Bd known not{ /Bd{ AGM_Gradient begin AGM_Gradient_private begin /_nColorsBd xp /_gradType xp /_gradName xp }def }if currentdict/BD known not{ /BD{ currentdict/_gradNames known not{ /_gradNames 20 dict def }if ] _nColorsBd _gradType ] _gradName exch /_gradNames xput end end }def }if currentdict/Bb known not{ /Bb{ AGM_Gradient begin AGM_Gradient_private begin _producingSeps{ AGM_Gradient_Sep/AGM_Gradient_Sep_private get begin }if mySave }def }if currentdict/BB known not{ /BB{ /_tmp xp cleartomark cleartomark _tmp dup _renderFlag myRestore _producingSeps{ end }if _illustrator end end { 2 ne exch 0 gt and{ 2 eq{ s }{ S }ifelse }{ pop newpath }ifelse }{ pop newpath }ifelse }def }if currentdict/Xm known not{ /Xm{ _xm astore pop }def }if end }def /queryDevice{ /_inRipSep _level2PS{ currentpagedevice/Separations 2 copy known{ get }{ pop pop false }ifelse }{ false }ifelse def /_noImage /lv1Fix where{ pop lv1Fix }{ false }ifelse def /_useShells where{ pop }{ /_useShells true def }ifelse /_useSmoothShade where{ pop }{ /_useSmoothShade false def }ifelse /_cyanPlate 1 0 0 0 testCMYKColorThrough def /_magentaPlate 0 1 0 0 testCMYKColorThrough def /_yellowPlate 0 0 1 0 testCMYKColorThrough def /_blackPlate 0 0 0 1 testCMYKColorThrough def /_compositeJob _cyanPlate _magentaPlate and _yellowPlate and _blackPlate and def /_compositeSpotDevice where{ pop }{ /_compositeSpotDevice _compositeJob not _inRipSep or{ 1 }{ 0 }ifelse def }ifelse /_producingSeps _compositeSpotDevice 0 ne def /_deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt def /_dpiThreshold where{ pop }{ /_dpiThreshold 600 def }ifelse /_screenFreqThreshold where{ pop }{ /_screenFreqThreshold 150 def }ifelse /_contoneDevice where{ pop }{ /_contoneDevice false def }ifelse /_subSampleOK _deviceDPI _dpiThreshold le currentScreenFreq _screenFreqThreshold le and _contoneDevice not and _producingSeps not and def }def /initializeLev1{ /makeByte8{ /_tmp 0 pt 255 mul cvi 8 string 8{ dup _tmp 3 index put /_tmp _tmp 1 add pt }repeat exch pop }def /currentScreenFreq{ currentscreen pop pop }def /_byte 1 string def /colorimage where{ pop }{ /colorimage{ pop pop /_blackTmp xp /_yellowTmp xp /_magentaTmp xp /_cyanTmp xp /_cnt 0 pt [ _byte dup 0 _cyanTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .3 /mul cvx _magentaTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .59 /mul cvx _yellowTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .11 /mul cvx _blackTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx /add cvx /add cvx /add cvx 1 /exch cvx /sub cvx /dup cvx 0 /lt cvx{ pop 0 }/if cvx /dup cvx 1 /gt cvx{ pop 1 }/if cvx 255 /mul cvx /cvi cvx 256 /mod cvx /dup cvx 0 /lt cvx{ pop 0 }/if cvx /put cvx /_cnt dup cvx 1 /add cvx /pt cvx ] cvx bind /_image load 5 execImage }def }ifelse }def /initializeLev2{ /level2ScreenFreq{ begin 60 HalftoneType 1 eq{ pop Frequency }if HalftoneType 2 eq{ pop GrayFrequency }if HalftoneType 5 eq{ pop Default level2ScreenFreq }if end }def /currentScreenFreq{ currenthalftone level2ScreenFreq }def }def /initializeShading{ _useSmoothShade _level3PS and{ /_usingSmoothShade true pt initializeLev3_Ops }{ /_usingSmoothShade false pt }ifelse }def /initializeLev3_Ops { /initShFill{ /_index _gradType 0 eq {0}{_maxRampIndex 1 sub} ifelse pt /_rampFuncsArray _maxRampIndex array pt /_boundsArray _maxRampIndex 1 sub array pt /_encodeArray _maxRampIndex 2 mul array pt /_beginCoord _rampPoint pt /_colorSpace null pt /_firstFill _rampIndex _maxRampIndex eq pt /_lastFill false pt }def /getRampColorSpace{ _nSamples 1 gt{ /_ndx 0 pt [blendColor] cvx exec }if /_C0 [currentcolor] pt /_C0_Space currentcolorspace pt _nSamples 1 gt{ /_ndx _nSamples 1 sub pt [blendColor] cvx exec }if /_C1 [currentcolor] pt /_C1_Space currentcolorspace pt _C0_Space _C1_Space eq{ /_rampColorSpace _C0_Space pt }{ (colorspace conflict!) == showpage stop }ifelse _spotColor{ nsetcustomcolorend }if }def /linealShFill{ popBSpace _xm aload pop pushBSpace /_size _index 1 add pt _size _maxRampIndex lt { /_rampFuncsArray _rampFuncsArray 0 _size getinterval pt /_boundsArray _boundsArray 0 _size 1 sub getinterval pt /_encodeArray _encodeArray 0 _size 2 mul getinterval pt }if bd /ShadingType 2 /ColorSpace _colorSpace /Function bd /FunctionType 3 /Domain [0 1] /Functions _rampFuncsArray /Bounds _boundsArray /Encode _encodeArray ed /Extend [_firstFill _lastFill] /Domain [0 1] /Coords [_beginCoord 0 _endCoord 0] ed shfill }def /radialShFill{ /_size _maxRampIndex _index sub pt _size _maxRampIndex lt { /_rampFuncsArray _rampFuncsArray _index _size getinterval pt /_boundsArray _boundsArray _index _size 1 sub getinterval pt /_encodeArray _encodeArray _index 2 mul _size 2 mul getinterval pt }if /_rampLen _beginCoord _endCoord sub pt bd /ShadingType 3 /ColorSpace _colorSpace /Function bd /FunctionType 3 /Domain [0 1] /Functions _rampFuncsArray /Bounds _boundsArray /Encode _encodeArray ed /Extend [_lastFill _firstFill] /Domain [0 1] /Coords [_xHi _rampLen mul _yHi _rampLen mul _endCoord 0 0 _beginCoord] ed shfill _radHilite{ _xHi _rampLen mul _yHi _rampLen mul translate }if }def /fillRamp{ /_invert _midPoint 0.5 lt pt _rampIndex _maxRampIndex eq { initShFill }if getRampColorSpace _colorSpace null eq{ /_colorSpace _rampColorSpace pt }{ _colorSpace _rampColorSpace ne{ /_index _index 1 _gradType 0 eq{ sub pt linealShFill }{ add pt radialShFill }ifelse initShFill /_colorSpace _rampColorSpace pt } if }ifelse /_endCoord _endPoint pt _rampFuncsArray _index bd /FunctionType 2 /Domain [0 1] /N 0.5 log _invert{1 _midPoint sub}{_midPoint}ifelse log div _gradType 0 eq{ _invert{/C1}{/C0}ifelse _C0 _invert{/C0}{/C1}ifelse _C1 }{ _invert{/C0}{/C1}ifelse _C1 _invert{/C1}{/C0}ifelse _C0 }ifelse ed put _rampIndex 1 ne{ _boundsArray _index _gradType 1 eq{1 sub}if _endCoord put } if 0 1 _invert {exch}if _encodeArray _index 2 mul 1 add 3 -1 roll put _encodeArray _index 2 mul 3 -1 roll put _rampIndex 1 eq { /_lastFill true pt _gradType 0 eq{ linealShFill }{ radialShFill }ifelse }if /_index _index 1 _gradType 0 eq{ add pt }{ sub pt }ifelse }def /radialRamp /fillRamp load def /rampImage /fillRamp load def AGM_Gradient begin /Bc{ 6 npop }def end }def /initializeComposite{ /bwImage{ pop /_image load 5 execImage }def currentdict/rampImage known not{ /rampImage{ _color{ _nSamples setImageParms _rgbRamp{ _redData _greenData _blueData _nSamples 3 expandColor true 3 null ncolorimage }{ _cyanData _magentaData _yellowData _blackData _nSamples 4 expandColor true 4 null ncolorimage }ifelse }{ _nSamples setImageParms _blackData null bwImage }ifelse }def }if /setCStop{ /_colorStyle exch pt _colorStyle 0 eq{ 1 exch sub 0 0 0 4 -1 roll }if _colorStyle 2 eq{ setrgbcolor 4 npop }if _colorStyle 3 eq{ 1 exch sub /_tmp xp pop 4{ _tmp mul 4 1 roll }repeat }if _colorStyle 4 eq{ 3 -1 roll pop pop 1 exch sub /_tmp xp 3{ 1 exch sub _tmp mul 1 exch sub 3 1 roll }repeat setrgbcolor 4 npop }if _colorStyle 2 ne _colorStyle 4 ne and{ null nsetcustomcolor }if }def /nsetcustomcolor { pop setcmykcolor }def /nsetcustomcolorend { }def /ncolorimage{ pop /_colorimage load 10 execImage }def _noImage not _level2PS not and{ /linealFill{ 8 setImageParms _color{ currentcmykcolor 4{ makeByte8 4 1 roll }repeat true 4 null ncolorimage }{ currentgray makeByte8 null bwImage }ifelse }def }if }def /npop{ {pop}repeat }def /xd{ exch def }def /nd{ null def }def /pt{ AGM_Gradient_private 3 1 roll put }def /xp{ exch pt }def /xput{ dup load dup length exch maxlength eq{ dup dup load dup length 2 mul dict copy def }if load begin def end }def /mySave{ save /_sSave xp }def /myRestore{ _sSave type /savetype eq{ _sSave restore }if }def /gMark{ counttomark 2 add -1 roll }def /execImage{ /_tmp xp { exec }stopped{ $error /errorname get /undefinedresult ne{ stop }{ _tmp npop }ifelse }if }def /pushBSpace{ newpath gsave _bUMatrix astore concat }def /popBSpace{ grestore }def /setImageParms{ 1 8 2 index 0 0 1 0 0 _imageMatrix astore }def /linealFill{ 0 0 1 1 rectfill }def /testCMYKColorThrough{ gsave setcmykcolor currentcmykcolor grestore add add add 0 ne }def /expandOne { /_tmp xp dup type /stringtype ne{ _tmp string exch dup 0 ne{ 255 mul cvi 0 1 _tmp 1 sub{ 3 copy exch put pop }for }if pop }if }def /expandColor{ /_channels xp /_len xp _channels{ _len expandOne _channels 1 roll }repeat }def /blendColor{ _color{ _rgbRamp _producingSeps not and{ _redData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _greenData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _blueData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if /setrgbcolor cvx }{ _cyanData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _magentaData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _yellowData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _blackData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _spotColor{ _rampSD begin /_rampSD cvx /begin cvx spot1 begin tintImage dup type /stringtype eq{ /_ndx cvx /get cvx _d255- /exch cvx /get cvx }{ dup null ne{ name type /nametype ne{ 1 exch sub }if }if }ifelse end /spot1 cvx /tintValue 3 -1 /roll cvx /put cvx spot2 begin tintImage dup type /stringtype eq{ /_ndx cvx /get cvx _d255- /exch cvx /get cvx }{ dup null ne{ name type /nametype ne{ 1 exch sub }if }if }ifelse end /spot2 cvx /tintValue 3 -1 /roll cvx /put cvx /end cvx end /_rampSD cvx /nsetcustomcolor cvx }{ /setcmykcolor cvx }ifelse }ifelse }{ _blackData /_ndx cvx /get cvx _d255 /exch cvx /get cvx _usingSmoothShade{ 1 /exch cvx /sub cvx 0 0 0 4 -1 /roll cvx /setcmykcolor cvx }{ /setgray cvx }ifelse }ifelse }def /linealRamp{ pushBSpace _ramp{ linealImage }{ linealFill }ifelse popBSpace /_rampIndex _rampIndex 1 sub pt _rampIndex 0 gt{ getRampData }if }def /radialGrad{ /_firstShell true pt _usingSmoothShade not{ fill }if pushBSpace _radHilite{ _xHi _yHi _bUMatrix idtransform /_yHi xp /_xHi xp _rampPoint 1 lt{ 1 _rampPoint sub dup _xHi mul exch _yHi mul translate }if }if _rampIndex{ radialRamp /_rampIndex _rampIndex 1 sub pt _rampIndex 0 gt{ getRampData }if }repeat popBSpace }def /getNSamples{ 0 exch { dup type /stringtype eq{ length exch pop exit }if pop }forall dup 0 eq{ pop 1 }if }def /getRampData{ /_rampType gMark pt /_color _rampType 0 gt pt /_ccRGB _rampType 5 eq _rampType 6 eq or pt /_rgbRamp _rampType 4 eq _ccRGB or pt /_ccProcess _rampType 2 eq _rampType 3 eq or pt _producingSeps{ _rampSD initSpotDict /_spotColor _ccProcess _ccRGB or pt }{ /_spotColor false pt }ifelse /_ramp true pt 100 div /_rampPoint xp 100 div /_midPoint xp dup /_colorStyle xp _colorStyle 0 eq{ 2 }{ _colorStyle 1 eq{ 5 }{ _colorStyle 2 eq{ 8 }{ _colorStyle 3 eq{ _producingSeps{ _rampSD begin spot1 begin /name 3 index def /spot_K 4 index def /spot_Y 5 index def /spot_M 6 index def /spot_C 7 index def end end }if 7 }{ _producingSeps{ _rampSD begin spot1 begin /name 4 index def /spot_K 8 index def /spot_Y 9 index def /spot_M 10 index def /spot_C 11 index def end end }if 11 } ifelse }ifelse }ifelse }ifelse /_tmp xp _tmp index 100 div /_endPoint xp _gradType 1 eq{ _tmp 1 add index 100 div /_midPoint xp }if _producingSeps{ _tmp 2 add index /_nextColorStyle xp _nextColorStyle 3 eq{ /_tmp _tmp 4 add pt _tmp index dup _rampSD begin spot1 /name get ne{ spot2 begin /name xd /spot_K _tmp 2 add index def /spot_Y _tmp 3 add index def /spot_M _tmp 4 add index def /spot_C _tmp 5 add index def end }{ pop }ifelse end }if _nextColorStyle 4 eq{ /_tmp _tmp 5 add pt _tmp index dup _rampSD begin spot1 /name get ne{ spot2 begin /name xd /spot_K _tmp 5 add index def /spot_Y _tmp 6 add index def /spot_M _tmp 7 add index def /spot_C _tmp 8 add index def end }{ pop }ifelse end }if }if _rampType 3 eq _rampType 6 eq or{ /_tint2Data gMark pt }if _ccProcess _ccRGB or{ /_tint1Data gMark pt }if _rgbRamp{ /_blueData gMark pt /_greenData gMark pt /_redData gMark pt }if _producingSeps{ _rampSD begin _ccProcess _ccRGB or{ _rampType 3 eq _rampType 6 eq or{ spot2 begin /tintImage _gradType 0 eq{ _tint2Data }{ _tint1Data }ifelse def name null eq{ /name /Black def }if end }if spot1 begin /tintImage _gradType 0 eq _rampType 2 eq or _rampType 5 eq or{ _tint1Data }{ _tint2Data }ifelse def _rampType 2 eq _rampType 5 eq or{ name null eq{ /name spot2 /name get def spot2 /name null put }if }{ name null eq{ /name /Black def }if }ifelse end }if end }if /_blackData gMark pt _rampType 0 gt{ counttomark 4 add -3 roll /_yellowData xp /_magentaData xp /_cyanData xp }if _ramp{ /_nSamples [ _rampType 0 eq {_blackData}if _rampType 1 eq {_cyanData _magentaData _yellowData _blackData}if _rampType 2 eq {_cyanData _magentaData _yellowData _blackData _tint1Data}if _rampType 3 eq {_cyanData _magentaData _yellowData _blackData _tint1Data _tint2Data}if _rampType 4 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData}if _rampType 5 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData _tint1Data}if _rampType 6 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData _tint1Data _tint2Data}if ] getNSamples pt _usingSmoothShade not {/_ramp _nSamples 1 gt pt} if } if setCStop }def /rectImage{ gsave /_sInc 1 pt /_bInc 1 _nSamples div pt /_uRampLen 1 0 dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt pt /_pChange _uRampLen 0 eq{0}{_nSamples _uRampLen div}ifelse pt 0 _nSamples [ /dup cvx /_ndx /exch cvx /pt cvx blendColor 0 0 _bInc 1 /rectfill cvx _bInc 0 /translate cvx _sInc /add cvx ] cvx bind repeat pop _spotColor{ nsetcustomcolorend }if grestore }def /radialInit{ /_nRadSamples _nSamples dup 0 eq{pop 1}if pt /_sInc -1 pt /_rampLen _rampPoint _endPoint sub pt /_bInc _rampLen _nSamples div neg pt /_optimize false pt _subSampleOK{ /_uRampLen _rampLen 0 dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt 0 _rampLen dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt 2 copy lt{ exch }if pop pt /_pChange _uRampLen 0 eq{ 0 }{ _nSamples _uRampLen div }ifelse pt _pChange .5 gt dup /_optimize xp{ /_nRadSamples _uRampLen 2 div round cvi dup 1 le{pop 2}if pt /_bInc _rampLen _nRadSamples div neg pt /_sInc _nSamples 1 sub _nRadSamples 1 sub div neg pt }if }if _radHilite{ /_xBCInc _xHi _rampLen mul _nRadSamples div pt /_yBCInc _yHi _rampLen mul _nRadSamples div pt }if }def currentdict/radialRamp known not{ /radialRamp{ /_saveMatrix _saveMatrix currentmatrix def radialInit _rampPoint _nSamples 1 sub _nRadSamples [ /dup cvx _optimize{ /round cvx /cvi cvx }if /_ndx /exch cvx /pt cvx _useShells{ /_firstShell cvx{ /_firstShell false pt }{ 0 0 3 index 360 0 arcn fill }/ifelse cvx }if blendColor _useShells{ 0 0 3 /index cvx 0 360 /arc cvx }{ 0 0 3 /index cvx 0 360 /arc cvx /fill cvx }ifelse /exch cvx _bInc /add cvx /exch cvx _sInc /add cvx _radHilite{ _xBCInc _yBCInc /translate cvx }if ] cvx bind repeat pop pop _saveMatrix setmatrix _radHilite{ _xHi _rampLen mul _yHi _rampLen mul translate }if _useShells _rampIndex 1 eq and{ fill }if _spotColor{ nsetcustomcolorend }if }def }if end end defaultpacking setpacking %%EndResource %%BeginProcSet: Adobe_ColorImage_AI6 1.1 0 userdict /Adobe_ColorImage_AI6 known not { userdict /Adobe_ColorImage_AI6 24 dict put } if userdict /Adobe_ColorImage_AI6 get begin /initialize { Adobe_ColorImage_AI6 begin Adobe_ColorImage_AI6 { dup type /arraytype eq { dup xcheck { bind } if } if pop pop } forall } def /terminate { end } def currentdict /Adobe_ColorImage_AI6_Vars known not { /Adobe_ColorImage_AI6_Vars 15 dict def } if Adobe_ColorImage_AI6_Vars begin /channelcount 0 def /sourcecount 0 def /sourcearray 4 array def /plateindex -1 def /XIMask 0 def /XIBinary 0 def /XIChannelCount 0 def /XIBitsPerPixel 0 def /XIImageHeight 0 def /XIImageWidth 0 def /XIImageMatrix null def /XIBuffer null def /XIDataProc null def /XIVersion 6 def end /WalkRGBString null def /WalkCMYKString null def /StuffRGBIntoGrayString null def /RGBToGrayImageProc null def /StuffCMYKIntoGrayString null def /CMYKToGrayImageProc null def /ColorImageCompositeEmulator null def /SeparateCMYKImageProc null def /FourEqual null def /TestPlateIndex null def currentdict /_colorimage known not { /colorimage where { /colorimage get /_colorimage exch def } { /_colorimage null def } ifelse } if /_currenttransfer systemdict /currenttransfer get def /colorimage null def /XI null def /WalkRGBString { 0 3 index dup length 1 sub 0 3 3 -1 roll { 3 getinterval { } forall 5 index exec 3 index } for 5 { pop } repeat } def /WalkCMYKString { 0 3 index dup length 1 sub 0 4 3 -1 roll { 4 getinterval { } forall 6 index exec 3 index } for 5 { pop } repeat } def /StuffRGBIntoGrayString { .11 mul exch .59 mul add exch .3 mul add cvi 3 copy put pop 1 add } def /RGBToGrayImageProc { Adobe_ColorImage_AI6_Vars begin sourcearray 0 get exec dup length 3 idiv string dup 3 1 roll /StuffRGBIntoGrayString load exch WalkRGBString end } def /StuffCMYKIntoGrayString { exch .11 mul add exch .59 mul add exch .3 mul add dup 255 gt { pop 255 } if 255 exch sub cvi 3 copy put pop 1 add } def /CMYKToGrayImageProc { Adobe_ColorImage_AI6_Vars begin sourcearray 0 get exec dup length 4 idiv string dup 3 1 roll /StuffCMYKIntoGrayString load exch WalkCMYKString end } def /ColorImageCompositeEmulator { pop true eq { Adobe_ColorImage_AI6_Vars /sourcecount get 5 add { pop } repeat } { Adobe_ColorImage_AI6_Vars /channelcount get 1 ne { Adobe_ColorImage_AI6_Vars begin sourcearray 0 3 -1 roll put channelcount 3 eq { /RGBToGrayImageProc } { /CMYKToGrayImageProc } ifelse load end } if image } ifelse } def /SeparateCMYKImageProc { Adobe_ColorImage_AI6_Vars begin sourcecount 0 ne { sourcearray plateindex get exec } { sourcearray 0 get exec dup length 4 idiv string 0 2 index plateindex 4 2 index length 1 sub { get 255 exch sub 3 copy put pop 1 add 2 index } for pop pop exch pop } ifelse end } def /FourEqual { 4 index ne { pop pop pop false } { 4 index ne { pop pop false } { 4 index ne { pop false } { 4 index eq } ifelse } ifelse } ifelse } def /TestPlateIndex { Adobe_ColorImage_AI6_Vars begin /plateindex -1 def /setcmykcolor where { pop gsave 1 0 0 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 1 0 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 0 1 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 0 0 1 setcmykcolor systemdict /currentgray get exec 1 exch sub grestore 1 0 0 0 FourEqual { /plateindex 0 def } { 0 1 0 0 FourEqual { /plateindex 1 def } { 0 0 1 0 FourEqual { /plateindex 2 def } { 0 0 0 1 FourEqual { /plateindex 3 def } { 0 0 0 0 FourEqual { /plateindex 5 def } if } ifelse } ifelse } ifelse } ifelse pop pop pop pop } if plateindex end } def /colorimage { Adobe_ColorImage_AI6_Vars begin /channelcount 1 index def /sourcecount 2 index 1 eq { channelcount 1 sub } { 0 } ifelse def 4 sourcecount add index dup 8 eq exch 1 eq or not end { /_colorimage load null ne { _colorimage } { Adobe_ColorImage_AI6_Vars /sourcecount get 7 add { pop } repeat } ifelse } { dup 3 eq TestPlateIndex dup -1 eq exch 5 eq or or { /_colorimage load null eq { ColorImageCompositeEmulator } { dup 1 eq { pop pop image } { Adobe_ColorImage_AI6_Vars /plateindex get 5 eq { gsave 0 _currenttransfer exec 1 _currenttransfer exec eq { 0 _currenttransfer exec 0.5 lt } { 0 _currenttransfer exec 1 _currenttransfer exec gt } ifelse { { pop 0 } } { { pop 1 } } ifelse systemdict /settransfer get exec } if _colorimage Adobe_ColorImage_AI6_Vars /plateindex get 5 eq { grestore } if } ifelse } ifelse } { dup 1 eq { pop pop image } { pop pop Adobe_ColorImage_AI6_Vars begin sourcecount -1 0 { exch sourcearray 3 1 roll put } for /SeparateCMYKImageProc load end systemdict /image get exec } ifelse } ifelse } ifelse } def /XG { pop pop } def /XF { 13 {pop} repeat } def /Xh { Adobe_ColorImage_AI6_Vars begin gsave /XIMask exch 0 ne def /XIImageHeight exch def /XIImageWidth exch def /XIImageMatrix exch def 0 0 moveto XIImageMatrix concat XIImageWidth XIImageHeight scale XIMask { /_lp /null ddef _fc /_lp /imagemask ddef } if /XIVersion 7 def end } def /XH { Adobe_ColorImage_AI6_Vars begin /XIVersion 6 def grestore end } def /XI { Adobe_ColorImage_AI6_Vars begin gsave /XIMask exch 0 ne def /XIBinary exch 0 ne def pop pop /XIChannelCount exch def /XIBitsPerPixel exch def /XIImageHeight exch def /XIImageWidth exch def pop pop pop pop /XIImageMatrix exch def XIBitsPerPixel 1 eq { XIImageWidth 8 div ceiling cvi } { XIImageWidth XIChannelCount mul } ifelse /XIBuffer exch string def XIBinary { /XIDataProc { currentfile XIBuffer readstring pop } def XIVersion 6 le { currentfile 128 string readline pop pop } if } { /XIDataProc { currentfile XIBuffer readhexstring pop } def } ifelse XIVersion 6 le { 0 0 moveto XIImageMatrix concat XIImageWidth XIImageHeight scale XIMask { /_lp /null ddef _fc /_lp /imagemask ddef } if } if XIMask { XIImageWidth XIImageHeight false [ XIImageWidth 0 0 XIImageHeight neg 0 0 ] /XIDataProc load imagemask } { XIImageWidth XIImageHeight XIBitsPerPixel [ XIImageWidth 0 0 XIImageHeight neg 0 0 ] /XIDataProc load XIChannelCount 1 eq { gsave 0 setgray image grestore } { false XIChannelCount colorimage } ifelse } ifelse grestore end } def end %%EndProcSet %%BeginResource: procset Adobe_Illustrator_AI5 1.1 0 %%Title: (Adobe Illustrator (R) Version 5.0 Full Prolog) %%Version: 1.1 0 %%CreationDate: (3/7/1994) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_Illustrator_AI5_vars 81 dict dup begin put /_eo false def /_lp /none def /_pf { } def /_ps { } def /_psf { } def /_pss { } def /_pjsf { } def /_pjss { } def /_pola 0 def /_doClip 0 def /cf currentflat def /_tm matrix def /_renderStart [ /e0 /r0 /a0 /o0 /e1 /r1 /a1 /i0 ] def /_renderEnd [ null null null null /i1 /i1 /i1 /i1 ] def /_render -1 def /_rise 0 def /_ax 0 def /_ay 0 def /_cx 0 def /_cy 0 def /_leading [ 0 0 ] def /_ctm matrix def /_mtx matrix def /_sp 16#020 def /_hyphen (-) def /_fScl 0 def /_cnt 0 def /_hs 1 def /_nativeEncoding 0 def /_useNativeEncoding 0 def /_tempEncode 0 def /_pntr 0 def /_tDict 2 dict def /_wv 0 def /Tx { } def /Tj { } def /CRender { } def /_AI3_savepage { } def /_gf null def /_cf 4 array def /_if null def /_of false def /_fc { } def /_gs null def /_cs 4 array def /_is null def /_os false def /_sc { } def /_pd 1 dict def /_ed 15 dict def /_pm matrix def /_fm null def /_fd null def /_fdd null def /_sm null def /_sd null def /_sdd null def /_i null def /discardSave null def /buffer 256 string def /beginString null def /endString null def /endStringLength null def /layerCnt 1 def /layerCount 1 def /perCent (%) 0 get def /perCentSeen? false def /newBuff null def /newBuffButFirst null def /newBuffLast null def /clipForward? false def end userdict /Adobe_Illustrator_AI5 known not { userdict /Adobe_Illustrator_AI5 91 dict put } if userdict /Adobe_Illustrator_AI5 get begin /initialize { Adobe_Illustrator_AI5 dup begin Adobe_Illustrator_AI5_vars begin discardDict { bind pop pop } forall dup /nc get begin { dup xcheck 1 index type /operatortype ne and { bind } if pop pop } forall end newpath } def /terminate { end end } def /_ null def /ddef { Adobe_Illustrator_AI5_vars 3 1 roll put } def /xput { dup load dup length exch maxlength eq { dup dup load dup length 2 mul dict copy def } if load begin def end } def /npop { { pop } repeat } def /sw { dup length exch stringwidth exch 5 -1 roll 3 index mul add 4 1 roll 3 1 roll mul add } def /swj { dup 4 1 roll dup length exch stringwidth exch 5 -1 roll 3 index mul add 4 1 roll 3 1 roll mul add 6 2 roll /_cnt 0 ddef { 1 index eq { /_cnt _cnt 1 add ddef } if } forall pop exch _cnt mul exch _cnt mul 2 index add 4 1 roll 2 index add 4 1 roll pop pop } def /ss { 4 1 roll { 2 npop (0) exch 2 copy 0 exch put pop gsave false charpath currentpoint 4 index setmatrix stroke grestore moveto 2 copy rmoveto } exch cshow 3 npop } def /jss { 4 1 roll { 2 npop (0) exch 2 copy 0 exch put gsave _sp eq { exch 6 index 6 index 6 index 5 -1 roll widthshow currentpoint } { false charpath currentpoint 4 index setmatrix stroke } ifelse grestore moveto 2 copy rmoveto } exch cshow 6 npop } def /sp { { 2 npop (0) exch 2 copy 0 exch put pop false charpath 2 copy rmoveto } exch cshow 2 npop } def /jsp { { 2 npop (0) exch 2 copy 0 exch put _sp eq { exch 5 index 5 index 5 index 5 -1 roll widthshow } { false charpath } ifelse 2 copy rmoveto } exch cshow 5 npop } def /pl { transform 0.25 sub round 0.25 add exch 0.25 sub round 0.25 add exch itransform } def /setstrokeadjust where { pop true setstrokeadjust /c { curveto } def /C /c load def /v { currentpoint 6 2 roll curveto } def /V /v load def /y { 2 copy curveto } def /Y /y load def /l { lineto } def /L /l load def /m { moveto } def } { /c { pl curveto } def /C /c load def /v { currentpoint 6 2 roll pl curveto } def /V /v load def /y { pl 2 copy curveto } def /Y /y load def /l { pl lineto } def /L /l load def /m { pl moveto } def } ifelse /d { setdash } def /cf { } def /i { dup 0 eq { pop cf } if setflat } def /j { setlinejoin } def /J { setlinecap } def /M { setmiterlimit } def /w { setlinewidth } def /XR { 0 ne /_eo exch ddef } def /H { } def /h { closepath } def /N { _pola 0 eq { _doClip 1 eq { _eo {eoclip} {clip} ifelse /_doClip 0 ddef } if newpath } { /CRender { N } ddef } ifelse } def /n { N } def /F { _pola 0 eq { _doClip 1 eq { gsave _pf grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _fc /_doClip 0 ddef } { _pf } ifelse } { /CRender { F } ddef } ifelse } def /f { closepath F } def /S { _pola 0 eq { _doClip 1 eq { gsave _ps grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _sc /_doClip 0 ddef } { _ps } ifelse } { /CRender { S } ddef } ifelse } def /s { closepath S } def /B { _pola 0 eq { _doClip 1 eq gsave F grestore { gsave S grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _sc /_doClip 0 ddef } { S } ifelse } { /CRender { B } ddef } ifelse } def /b { closepath B } def /W { /_doClip 1 ddef } def /* { count 0 ne { dup type /stringtype eq { pop } if } if newpath } def /u { } def /U { } def /q { _pola 0 eq { gsave } if } def /Q { _pola 0 eq { grestore } if } def /*u { _pola 1 add /_pola exch ddef } def /*U { _pola 1 sub /_pola exch ddef _pola 0 eq { CRender } if } def /D { pop } def /*w { } def /*W { } def /` { /_i save ddef clipForward? { nulldevice } if 6 1 roll 4 npop concat pop userdict begin /showpage { } def 0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit [] 0 setdash /setstrokeadjust where {pop false setstrokeadjust} if newpath 0 setgray false setoverprint } def /~ { end _i restore } def /O { 0 ne /_of exch ddef /_lp /none ddef } def /R { 0 ne /_os exch ddef /_lp /none ddef } def /g { /_gf exch ddef /_fc { _lp /fill ne { _of setoverprint _gf setgray /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /G { /_gs exch ddef /_sc { _lp /stroke ne { _os setoverprint _gs setgray /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /k { _cf astore pop /_fc { _lp /fill ne { _of setoverprint _cf aload pop setcmykcolor /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /K { _cs astore pop /_sc { _lp /stroke ne { _os setoverprint _cs aload pop setcmykcolor /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /x { /_gf exch ddef findcmykcustomcolor /_if exch ddef /_fc { _lp /fill ne { _of setoverprint _if _gf 1 exch sub setcustomcolor /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /X { /_gs exch ddef findcmykcustomcolor /_is exch ddef /_sc { _lp /stroke ne { _os setoverprint _is _gs 1 exch sub setcustomcolor /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /A { pop } def /annotatepage { userdict /annotatepage 2 copy known {get exec} {pop pop} ifelse } def /XT { pop pop } def /discard { save /discardSave exch store discardDict begin /endString exch store gt38? { 2 add } if load stopped pop end discardSave restore } bind def userdict /discardDict 7 dict dup begin put /pre38Initialize { /endStringLength endString length store /newBuff buffer 0 endStringLength getinterval store /newBuffButFirst newBuff 1 endStringLength 1 sub getinterval store /newBuffLast newBuff endStringLength 1 sub 1 getinterval store } def /shiftBuffer { newBuff 0 newBuffButFirst putinterval newBuffLast 0 currentfile read not { stop } if put } def 0 { pre38Initialize mark currentfile newBuff readstring exch pop { { newBuff endString eq { cleartomark stop } if shiftBuffer } loop } { stop } ifelse } def 1 { pre38Initialize /beginString exch store mark currentfile newBuff readstring exch pop { { newBuff beginString eq { /layerCount dup load 1 add store } { newBuff endString eq { /layerCount dup load 1 sub store layerCount 0 eq { cleartomark stop } if } if } ifelse shiftBuffer } loop } if } def 2 { mark { currentfile buffer readline not { stop } if endString eq { cleartomark stop } if } loop } def 3 { /beginString exch store /layerCnt 1 store mark { currentfile buffer readline not { stop } if dup beginString eq { pop /layerCnt dup load 1 add store } { endString eq { layerCnt 1 eq { cleartomark stop } { /layerCnt dup load 1 sub store } ifelse } if } ifelse } loop } def end userdict /clipRenderOff 15 dict dup begin put { /n /N /s /S /f /F /b /B } { { _doClip 1 eq { /_doClip 0 ddef _eo {eoclip} {clip} ifelse } if newpath } def } forall /Tr /pop load def /Bb {} def /BB /pop load def /Bg {12 npop} def /Bm {6 npop} def /Bc /Bm load def /Bh {4 npop} def end /Lb { 4 npop 6 1 roll pop 4 1 roll pop pop pop 0 eq { 0 eq { (%AI5_BeginLayer) 1 (%AI5_EndLayer--) discard } { /clipForward? true def /Tx /pop load def /Tj /pop load def currentdict end clipRenderOff begin begin } ifelse } { 0 eq { save /discardSave exch store } if } ifelse } bind def /LB { discardSave dup null ne { restore } { pop clipForward? { currentdict end end begin /clipForward? false ddef } if } ifelse } bind def /Pb { pop pop 0 (%AI5_EndPalette) discard } bind def /Np { 0 (%AI5_End_NonPrinting--) discard } bind def /Ln /pop load def /Ap /pop load def /Ar { 72 exch div 0 dtransform dup mul exch dup mul add sqrt dup 1 lt { pop 1 } if setflat } def /Mb { q } def /Md { } def /MB { Q } def /nc 3 dict def nc begin /setgray { pop } bind def /setcmykcolor { 4 npop } bind def /setcustomcolor { 2 npop } bind def currentdict readonly pop end end setpacking %%EndResource %%BeginResource: procset Adobe_blend_AI5 1.4 0 %%Title: (Adobe Illustrator (R) Version 5.0 Blend ProcSet) %%Version: 1.4 0 %%CreationDate: (11/19/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /Adobe_blend_AI5 70 dict dup begin put /bd { bind def } bind def /xs { exch store } bd /nullProc { { } } def /initialize { pop pop Adobe_blend_AI5 begin Adobe_blend_AI5_vars begin /_contoneDevice where { pop } { /_contoneDevice false def } ifelse /_dpiThreshold where { pop } { /_dpiThreshold 600 def } ifelse /_screenFreqThreshold where { pop } { /_screenFreqThreshold 150 def } ifelse /tRectOK? deviceDPI _dpiThreshold le currentScreenFreq _screenFreqThreshold le and _contoneDevice not and def /invertXfer { [ { 1 exch sub } /exec load systemdict/currenttransfer get exec /exec load ] cvx systemdict/settransfer get exec } bd /spotDict 3 dict dup begin /nSpots 2 def /spot1 7 dict def /spot2 7 dict def end def composite? { /_setgray_ /setgray load def /_fill_ /fill load def /_image_ /image load def } { /_setgray_ systemdict/setgray get def /_fill_ systemdict/fill get def /_image_ systemdict/image get def } ifelse } bd /terminate { currentdict Adobe_blend_AI5_vars eq { end currentdict Adobe_blend_AI5 eq { end } if } if } bd /_compositeSpotDevice where { begin _compositeSpotDevice 0 ne {userdict /composite? true put} if end } { /_compositeSpotDevice 0 def } ifelse /nullString () def /d255 256 array def 0 1 255 { d255 exch dup 255 div put } bind for /d255- 256 array def 0 1 255 { d255- exch 1 d255 2 index get sub put } bind for /dUserSpace matrix defaultmatrix def currentdict /Adobe_blend_AI5_vars 89 dict dup begin put { /f /F /s /S /b /B } { null def } bind forall /byte 1 string def /sSave null def /setSSave { save /sSave exch store } bind def /Bm null def /doBlend null def /startC? false def /endC? false def /fCMYK? null def /startTint 0 def /endTint 0 def /bSMatrix matrix def /bUMatrix matrix def /dMatrix matrix def /inLine? true def /pTState? false def /bHi? false def /yHi 0 def /xHi 0 def /noImg /lv1Fix where { pop lv1Fix } { false } ifelse def /ccAry1 5 array def /ccTint 0 def /spotColor? false def /colorimage? true def [ /tint1Data /tint2Data /spotDict /bAxis /ubAxis /pChange /optimize? /nSamples /sInc /blendProc /_bn /xBCInc /yBCInc /bInc /bRender /cBName /cBType /nColors /color? /blend? /colorType /cData /cDataLen /bDataLen /rampPoint /midPoint /endPoint /blendLength /blackData /yeData /mgData /cyData /cnt1 /ndx /_fill /tmp counttomark { null def } bind repeat pop currentdict end currentdict end exch begin begin /unitSq { 0 0 moveto 0 1 lineto 1 1 lineto 1 0 lineto closepath } bd /gMark { counttomark 2 add -1 roll } bd /setCustomColor { dup /ccTint exch store 1 exch sub 6 1 roll ccAry1 astore exch setcustomcolor } bd /currentCustomColor { ccAry1 aload pop ccTint } bd /nsetcustomcolor where { pop } { /nsetcustomcolor { pop setcmykcolor } bd } ifelse /nsetcustomcolorend where { pop } { /nsetcustomcolorend { } bd } ifelse /setBSpace { newpath bUMatrix astore concat unitSq } bd /setCStop { dup 0 eq { pop spotColor? { dup 1 exch sub /ccTint exch def ccAry1 4 /Black put } if setgray } { 1 eq { setcmykcolor } { composite? not colorType 2 lt and { forceCMYK } { setCustomColor } ifelse } ifelse } ifelse } bd /makeByte { /tmp 0 store 255 mul cvi 8 string 8 { dup tmp 3 index put /tmp tmp 1 add store } repeat exch pop } bd /setImgSpace { cDataLen 1 8 2 index 0 0 1 0 0 dMatrix astore } bd /bwImage { setImgSpace cData /_image_ load { exec } stopped { $error /errorname get /undefinedresult ne { stop } { pop pop pop pop pop } ifelse } if } bd level2? { /bFill { _fill } def /bCImg { /cDataLen bDataLen store setImgSpace setSSave expandSpot cyData mgData yeData cData expandCMYK true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd } if /expandOne { dup type /stringtype ne { cDataLen string exch dup 0 ne { 255 mul cvi 0 1 cDataLen 1 sub { 3 copy exch put pop } for } if pop } if } bd /expandSpot { spotColor? { spotDict begin spot1 begin tintImage type /nulltype ne { tintImage expandOne /tintImage exch def } if end spot2 begin tintImage type /nulltype ne { tintImage expandOne /tintImage exch def } if end end } if } bd /expandCMYK { 4 { expandOne 4 1 roll } repeat } bd /colorimage where dup { exch pop /ncolorimage where { pop } { /ncolorimage {pop colorimage} bd } ifelse } if not { /ncolorimage where { pop } { /colorimage? false store /ncolorimage { pop pop pop setSSave /blackData xs /yeData xs /mgData xs /cyData xs /cnt1 0 store [ byte dup 0 cyData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .3 /mul cvx } { .3 mul } ifelse mgData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .59 /mul cvx } { .59 mul } ifelse yeData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .11 /mul cvx } { .11 mul } ifelse blackData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx } if /add cvx /add cvx /add cvx 1 /exch cvx /sub cvx /dup cvx 0 /lt cvx { pop 0 } /if cvx /dup cvx 1 /gt cvx { pop 1 } /if cvx 255 /mul cvx /cvi cvx 256 /mod cvx /dup cvx 0 /lt cvx { pop 0 } /if cvx /put cvx /cnt1 dup cvx 1 /add cvx /store cvx ] cvx bind _image_ sSave restore } bd } ifelse } if level2? not { /bCImg { /cDataLen bDataLen store setImgSpace setSSave expandSpot cyData mgData yeData cData colorimage? { expandCMYK } if true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd /bwFill { setSSave /cDataLen 8 store /cData currentgray makeByte store bwImage sSave restore } bd /c1ImgFill { setSSave /cDataLen 8 store setImgSpace spotColor? { spotDict begin spot1 begin currentCustomColor makeByte /tintImage exch def /name exch def /spot_K exch def /spot_Y exch def /spot_M exch def /spot_C exch def end spot2 initSpotData end } if currentcmykcolor 4 { makeByte 4 1 roll } repeat true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd /bFill noImg { { _fill } } { { color? { c1ImgFill } { bwFill } ifelse } } ifelse bd } if composite? { /bCFun { color? { cyData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if mgData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if yeData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if cData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if spotColor? { spotDict begin /spotDict cvx /begin cvx spot1 begin tintImage dup type /stringtype eq { /ndx cvx /get cvx d255- /exch cvx /get cvx } { dup type /nulltype ne { name type /nametype ne {1 exch sub} if } if } ifelse end /spot1 cvx /tintValue 3 -1 /roll cvx /put cvx spot2 begin tintImage dup type /stringtype eq { /ndx cvx /get cvx d255- /exch cvx /get cvx } { dup type /nulltype ne { name type /nametype ne {1 exch sub} if } if } ifelse end /spot2 cvx /tintValue 3 -1 /roll cvx /put cvx /end cvx end /spotDict cvx /nsetcustomcolor cvx } { /setcmykcolor cvx } ifelse } { cData /ndx cvx /get cvx d255 /exch cvx /get cvx /setgray cvx } ifelse } bd /Bc { newpath gsave setBSpace nColors 1 eq { pop pop setCStop } if bFill grestore } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { linImg } { bFill } ifelse grestore nColors 1 gt { getRData } if } bd /rdBm { /nColors dup load 1 sub store _fill gsave bUMatrix astore concat bHi? { xHi yHi bUMatrix idtransform /yHi exch store /xHi exch store rampPoint 1 lt { 1 rampPoint sub dup xHi mul exch yHi mul translate } if } if nColors { 0 0 rampPoint 0 360 arc _fill blend? bHi? or { rdBlend } if nColors 1 gt { getRData } if /nColors dup load 1 sub store } repeat /nColors 1 store grestore } bd /cGetRData { setCStop /blend? cData type /stringtype eq dup not color? and { pop cyData type /stringtype eq mgData type /stringtype eq yeData type /stringtype eq or or } if store } def /cGetRData } if /eCStop { mark 1 index 3 mul 3 add dup 8 gt { pop 8 } if 1 roll cleartomark } bd composite? not { /knockOut level2? { { 0 0 0 0 setcmykcolor _fill } } { /bFill noImg { { _fill } } { { _of true eq { currentgray 1 ne { bwFill } if } { bwFill } ifelse } } ifelse def /whiteByte 1 makeByte def noImg { { 0 0 0 0 setcmykcolor _fill } } { { cBType 0 eq { setSSave /cData whiteByte store /cDataLen 8 store bwImage sSave restore } { _fill } ifelse } } ifelse } ifelse bd /bCFun { cData dup type /stringtype ne { color? { 1 exch sub } if } { /ndx cvx /get cvx color? customColor? not and { d255- } { d255 } ifelse /exch cvx /get cvx } ifelse /_setgray_ cvx } bd /eCCBlend { dup 3 eq { pop mark 7 1 roll 6 copy ccThrough? dup /blend? xs { /startC? true store setCustomColor customColor? { /cData tint1Data store setCDataLen } if /endC? 3 index 3 eq { 4 index 1 ne } { false } ifelse store } if cleartomark stop } if 1 eq { pop pop pop } if pop /startC? false store 6 { 8 index } repeat ccThrough? dup /blend? xs { /endC? true store blend? not { stop } if customColor? { /cData tint1Data store setCDataLen } if } if } bd /handleOP { _of not { knockOut } if } bd /handleROP { _of not { 0 0 0 0 setcmykcolor _fill } { newpath } ifelse } bd /rdBm { /nColors dup load 1 sub store blend? { _fill } { handleROP } ifelse gsave bUMatrix astore concat bHi? { xHi yHi bUMatrix idtransform /yHi exch store /xHi exch store rampPoint 1 lt { 1 rampPoint sub dup xHi mul exch yHi mul translate } if } if nColors { 0 0 rampPoint 0 360 arc blend? { cData type /stringtype ne bHi? not and { cData color? { 1 exch sub } if _setgray_ _fill_ } { cData type /stringtype ne { /cDataLen 1 store /bDataLen 1 store } if rdBlend } ifelse } { handleROP pTState? { /bAxis rampPoint endPoint sub store xHi bAxis mul yHi bAxis mul translate } if } ifelse nColors 1 gt { getRData } if /nColors dup load 1 sub store } repeat /nColors 1 store grestore } bd /ccThrough? { gsave pop 0 setCustomColor currentcmykcolor grestore anyColor? } bd /forceCMYK { exch pop 1 exch sub 5 1 roll 4 { 4 index mul 4 1 roll } repeat 0 cCMYKData dup /cData ne { dup /yeData eq { pop 1 add } { /mgData eq { 2 } { 3 } ifelse add } ifelse 0 } if pop index 0 eq { pop pop pop pop 0 0 0 0 } if setcmykcolor pop /fCMYK? true store } bd /endCapSepBc { pop pop dup 0 eq { pop setgray } { 1 eq { setcmykcolor } { colorType 1 eq { forceCMYK } { fCMYK? { forceCMYK } { setCustomColor } ifelse } ifelse } ifelse } ifelse currentcmykcolor anyColor? blend? and { bFill } { handleOP } ifelse } bd } if /cCMYKData 0 def composite? dup not { pop customColor? } if not { /cCMYKData /cyData /mgData /yeData /cData black? not { yellow? { exch } { magenta? { 3 } { 4 } ifelse -1 roll } ifelse } if 4 1 roll pop pop pop store /Bc { gsave setBSpace nColors 1 gt { blend? currentcmykcolor anyColor? and { bFill } { handleOP } ifelse } { endCapSepBc } ifelse grestore newpath } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { cCMYKData load dup type /stringtype eq { dup length /cDataLen xs /cData xs gsave colorType 0 ne noImg not and { invertXfer } if linImg grestore } { pop bFill } ifelse } { handleOP } ifelse grestore nColors 1 gt { getRData } if } bd /cmykGetRData { /fCMYK? false store blend? { { cmykDataProcs colorType get exec } stopped pop blend? { /cData cCMYKData load store setCDataLen } if } if } def /cmykDataProcs [ { pop black? dup /blend? xs { setgray 0 } if pop } { cCMYKData load dup type /stringtype ne { 0 0 0 cyan? not { 4 magenta? { 1 } { yellow? { 2 } { 3 } ifelse } ifelse roll } if 4 copy add add add 0 eq { /blend? false store } if setcmykcolor /startC? true store /endC? true store eCStop stop } if pop dup 0 eq { pop setgray } { 1 eq { setcmykcolor } { forceCMYK } ifelse } ifelse } bind /eCCBlend load { cBType 1 eq { tint1Data tint2Data /tint1Data xs /tint2Data xs } if 0 eq { black? { setgray } { 0 0 0 4 -1 roll 1 exch sub setcmykcolor } ifelse black? { /blend? true store } if 6 { 8 index } repeat ccThrough? { /blend? true store } { black? { /cData tint1Data store setCDataLen } { /blend? false store } ifelse } ifelse } { mark 7 1 roll 6 copy ccThrough? { forceCMYK pop stop } if 9 index 0 eq { black? dup /blend? xs { pop 1 setgray /cData tint2Data store setCDataLen 0 } if pop } { /blend? 6 { 16 index } repeat ccThrough? store blend? { forceCMYK } if } ifelse cleartomark } ifelse } bind ] def /cmykGetRData } if composite? dup not { pop isCMYKSep? } if not { /endCapSepBc { /white? false store pop pop dup 0 eq { pop /white? 1 index 1 eq store setgray } { 1 eq { setcmykcolor } { setCustomColor } ifelse } ifelse % currentcmykcolor anyColor? endC? or blend? and { bFill } { handleOP } ifelse } bd /Bc { gsave setBSpace nColors 1 gt { blend? startC? and { bFill } { handleOP } ifelse } { endCapSepBc } ifelse grestore newpath } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { cData type /stringtype eq { linImg } { bFill } ifelse } { handleOP } ifelse grestore nColors 1 gt { getRData } if } bd /discardCMY { counttomark 4 add -3 roll pop pop pop } bd /testTopCC { 6 copy ccThrough? } bd /getCRamp { { ccDataProcs colorType 2 sub get exec } stopped pop blend? cDataLen 0 eq and { /cDataLen bDataLen store } if } bd /ccGetRData { /fCMYK? false store /startC? false store /endC? false store colorType 2 lt { /blend? false def } if blend? { getCRamp } { setCStop } ifelse blend? { /blend? cData 1 ne store blend? { cData dup type /stringtype ne { 1 exch sub /cData xs 0 } if pop } if } if } def /ccDataProcs [ /eCCBlend load { cBType 1 eq { tint1Data tint2Data /tint1Data xs /tint2Data xs } if 0 eq { /blend? false store pop } { mark 7 1 roll testTopCC { /blend? 1 index 1 ne store /startC? blend? store /endC? false store blend? not { cleartomark stop } if /cData tint1Data store setCDataLen setCustomColor pop stop } if cleartomark } ifelse 2 index 0 eq { /blend? false store } { mark 6 { 9 index } repeat testTopCC dup /blend? xs { /blend? 1 index 1 ne store /endC? blend? store /startC? false store blend? not { cleartomark stop } if /cData tint2Data store setCDataLen } if cleartomark } ifelse } bind ] def /ccGetRData } if load Adobe_blend_AI5_vars /getData 3 -1 roll put /setCDataLen { /cDataLen 0 cData dup type /stringtype eq { length exch } if pop store } bd /initSpotData { begin /name null def /tintImage null def /tintValue null def /spot_C null def /spot_M null def /spot_Y null def /spot_K null def end } bd /getRData { /colorType gMark store _compositeSpotDevice 0 ne { spotDict begin spot1 initSpotData spot2 initSpotData end /spotColor? colorType 2 eq colorType 3 eq or def } { /spotColor? false store } ifelse /blend? true store 0 0 0 0 setcmykcolor 100 div /rampPoint xs % (between 13 and 87%) 100 div /midPoint xs dup 0 eq { 2 } { dup 1 eq { 5 } { _compositeSpotDevice 0 ne { spotDict begin spot1 begin /name 3 index def /spot_K 4 index def /spot_Y 5 index def /spot_M 6 index def /spot_C 7 index def end end } if 7 } ifelse } ifelse /tmp exch def tmp index 100 div /endPoint xs _compositeSpotDevice 0 ne { tmp 2 add index 3 eq { /tmp tmp 4 add def tmp index dup spotDict begin spot1/name get ne { spot2 begin /name exch def /spot_K tmp 2 add index def /spot_Y tmp 3 add index def /spot_M tmp 4 add index def /spot_C tmp 5 add index def end } { pop } ifelse end } if } if /color? colorType 0 gt store colorType 3 eq { /tint2Data gMark store } if colorType 2 ge { /tint1Data gMark store } if _compositeSpotDevice 0 ne { spotDict begin colorType 2 ge { colorType 3 eq { spot2 begin /tintImage cBType 0 eq {tint2Data} {tint1Data} ifelse def name null eq {/name /Black def} if end } if spot1 begin /tintImage cBType 0 eq colorType 2 eq or {tint1Data} {tint2Data} ifelse def colorType 2 eq { name null eq { /name spot2/name get def spot2/name null put } if } { name null eq {/name /Black def} if } ifelse end } if end } if /cData gMark store setCDataLen colorType 0 gt { counttomark 4 add -3 roll /yeData xs /mgData xs /cyData xs } if blend? { /bDataLen cDataLen dup 0 eq color? and { [ cyData mgData yeData ] { dup type /stringtype eq { length exch pop exit } if pop } forall } if store bDataLen 0 eq { /bDataLen 1 store } if getData blend? { composite? cDataLen 0 eq and { /cDataLen bDataLen store } if } if } { setCStop } ifelse } bd /Bg { 0 0 0 0 setcmykcolor 6 { pop } repeat /blendLength xs pop pop pop /cBName xs /bRender xs bRender 2 ne { composite? not { _of setoverprint } if _eo {eoclip} {clip} ifelse _bn cBName 2 copy known { get mark exch aload pop /cBType xs /nColors xs mark exch aload pop 0 0 } if pop pop getRData cBType 0 eq { /linealBm } { bHi? { /pTState? nColors 2 gt store } if /doBlend /rdBlend load store /rdBm } ifelse } { inLine? not { mark mark } if /Bc dup { cleartomark mark } bd /nullProc } ifelse load /Bm xs } bd /linImg noImg { { newpath doRctBlend } } { { /doBlend color? composite? and { /bCImg } { /bwImage } ifelse load store 0 0 moveto tRectOK? composite? and { { mark 0 1 dtransform atan cvi 90 mod 0 eq 1 0 dtransform atan cvi 90 mod 0 eq } stopped { cleartomark } { and exch pop { newpath doRctBlend } { doBlend } ifelse } ifelse } { doBlend } ifelse } } ifelse bd /doRctBlend { gsave /sInc 1 store /nSamples bDataLen store /bInc 1 bDataLen div store /ubAxis 1 0 dtransform dUserSpace idtransform dup mul exch dup mul add sqrt store /pChange ubAxis 0 eq { 0 } { bDataLen ubAxis div } ifelse store pChange .5 gt noImg not and dup /optimize? xs { /nSamples ubAxis 2 div round cvi dup 1 le { pop 2 } if store /bInc 1 nSamples div store /sInc bDataLen 1 sub nSamples 1 sub div store } if 0 nSamples [ /dup cvx optimize? { /round cvx /cvi cvx } if /ndx /exch cvx /store cvx bCFun /rectfill where dup { exch pop _compositeSpotDevice 1 ne and } if { 0 0 bInc 1 /rectfill cvx } { 0 0 /moveto cvx bInc 0 /lineto cvx bInc 1 /lineto cvx 0 1 /lineto cvx /closepath cvx /_fill_ cvx } ifelse bInc 0 /translate cvx sInc /add cvx ] cvx bind repeat pop spotColor? {nsetcustomcolorend} if grestore } bd /rdPrep { /nSamples bDataLen dup 0 eq { pop 1 } if store /sInc -1 store /bAxis rampPoint endPoint sub store /bInc bAxis bDataLen div neg store /optimize? false store tRectOK? { /ubAxis bAxis 0 dtransform dUserSpace idtransform dup mul exch dup mul add sqrt 0 bAxis dtransform dUserSpace idtransform dup mul exch dup mul add sqrt 2 copy lt { exch } if pop store /pChange ubAxis 0 eq { 0 } { bDataLen ubAxis div } ifelse store pChange .5 gt noImg not and dup /optimize? xs { /nSamples ubAxis 2 div round cvi dup 1 le { pop 2 } if store /bInc bAxis nSamples div neg store /sInc bDataLen 1 sub nSamples 1 sub div neg store } if } if bHi? { /xBCInc xHi bAxis mul nSamples div store /yBCInc yHi bAxis mul nSamples div store } if } bd /rdBlend { newpath gsave rdPrep rampPoint bDataLen 1 sub nSamples [ /dup cvx optimize? { /round cvx /cvi cvx } if /ndx /exch cvx /store cvx bCFun 0 0 3 /index cvx 0 360 /arc cvx /_fill_ cvx /exch cvx bInc /add cvx /exch cvx sInc /add cvx bHi? { xBCInc yBCInc /translate cvx } if ] cvx bind repeat pop pop spotColor? {nsetcustomcolorend} if grestore pTState? { xHi bAxis mul yHi bAxis mul translate } if } bd /Bh { pop pop /pTState? false store 2 copy 0 ne exch 0 ne or dup /bHi? xs { /yHi xs /xHi xs 0 0 } if pop pop } bd /BD { inLine? not { ] nColors cBType ] _bn cBName 3 -1 roll put end } if } bd /Bn { 1 add dict dup nullString null put /_bn xs } bd /Bd { Adobe_blend_AI5_vars begin 3 -1 roll dup nullString eq dup { setSSave } if /inLine? exch def /cBName exch def /nColors exch def /cBType exch def } bd /Bb { sSave null eq { Adobe_blend_AI5_vars begin setSSave } if composite? { /_fill /fill load store } { /__fill /fill load store /_fill { _of true eq { currentgray 1 ne { __fill } if } { __fill } ifelse } def } ifelse /fill { } def } bd /BB { /cBType xs cleartomark cleartomark cBType dup bRender sSave dup type /savetype eq { restore 0 } if pop currentdict Adobe_blend_AI5_vars eq { end } if 2 ne exch 0 gt and { 2 eq { s } { S } ifelse } { pop newpath } ifelse } bd currentdict readonly pop end end defaultpacking setpacking %%EndResource %%BeginResource: procset Adobe_pattern_AI5 1.1 0 %%Title: (Adobe Illustrator (R) Version 5.0 Pattern Operators) %%Version: 1.1 0 %%CreationDate: (03/26/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_Illustrator_AI5 known not { userdict /Adobe_Illustrator_AI5 95 dict put } if userdict /Adobe_Illustrator_AI5 get begin /@ { } def /& { } def /dp { dup null eq { pop _dp 0 ne { 0 1 _dp 1 sub _dl mod { _da exch get 3 get } for _dp 1 sub _dl mod 1 add packedarray _da 0 get aload pop 8 -1 roll 5 -1 roll pop 4 1 roll definepattern pop } if } { _dp 0 ne _dp _dl mod 0 eq and { null dp } if 7 packedarray _da exch _dp _dl mod exch put _dp _dl mod _da 0 get 4 get 2 packedarray /_dp _dp 1 add def } ifelse } def /E { _ed begin dup 0 get type /arraytype ne { 0 { dup 1 add index type /arraytype eq { 1 add } { exit } ifelse } loop array astore } if /_dd exch def /_ury exch def /_urx exch def /_lly exch def /_llx exch def /_n exch def /_y 0 def /_dl 4 def /_dp 0 def /_da _dl array def 0 1 _dd length 1 sub { /_d exch _dd exch get def 0 2 _d length 2 sub { /_x exch def /_c _d _x get _ ne def /_r _d _x 1 add get cvlit def _r _ ne { _urx _llx sub _ury _lly sub [ 1 0 0 1 0 0 ] [ /save cvx _llx neg _lly neg /translate cvx _c { nc /begin cvx } if _r dup type /stringtype eq { cvx } { { exec } /forall cvx } ifelse _c { /end cvx } if /restore cvx ] cvx /_fn 12 _n length add string def _y _fn cvs pop /_y _y 1 add def _fn 12 _n putinterval _fn _c false dp _d exch _x 1 add exch put } if } for } for null dp _n _dd /_pd end xput } def /fc { _fm dup concatmatrix pop } def /p { /_fm exch ddef 9 -2 roll _pm translate fc 7 -2 roll _pm scale fc 5 -1 roll _pm rotate fc 4 -2 roll exch 0 ne { dup _pm rotate fc 1 -1 _pm scale fc neg _pm rotate fc } { pop } ifelse dup _pm rotate fc exch dup sin exch cos div 1 0 0 1 0 6 2 roll _pm astore fc neg _pm rotate fc _pd exch get /_fdd exch ddef /_pf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm patternfill } { pop fill } ifelse grestore pop } for pop } for restore newpath } ddef /_psf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm 9 copy 6 npop patternashow } { pop 6 copy 3 npop hvashow } ifelse grestore pop } for pop } for restore sw rmoveto } ddef /_pjsf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm 12 copy 6 npop patternawidthshow } { pop 9 copy 3 npop hvawidthshow } ifelse grestore pop } for pop } for restore swj rmoveto } ddef /_lp /none ddef } def /sc { _sm dup concatmatrix pop } def /P { /_sm exch ddef 9 -2 roll _pm translate sc 7 -2 roll _pm scale sc 5 -1 roll _pm rotate sc 4 -2 roll exch 0 ne { dup _pm rotate sc 1 -1 _pm scale sc neg _pm rotate sc } { pop } ifelse dup _pm rotate sc exch dup sin exch cos div 1 0 0 1 0 6 2 roll _pm astore sc neg _pm rotate sc _pd exch get /_sdd exch ddef /_ps { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm patternstroke } { pop stroke } ifelse grestore pop } for pop } for restore newpath } ddef /_pss { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm 10 copy 6 npop patternashowstroke } { pop 7 copy 3 npop ss } ifelse grestore pop } for pop } for restore pop sw rmoveto } ddef /_pjss { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm 13 copy 6 npop patternawidthshowstroke } { pop 10 copy 3 npop jss } ifelse grestore pop } for pop } for restore pop swj rmoveto } ddef /_lp /none ddef } def end userdict /Adobe_pattern_AI5 18 dict dup begin put /initialize { /definepattern where { pop } { begin begin Adobe_pattern_AI5 begin Adobe_pattern_AI5 { dup xcheck { bind } if pop pop } forall mark cachestatus 7 1 roll pop pop pop pop exch pop exch { { 10000 add dup 2 index gt { exit } if dup setcachelimit } loop } stopped cleartomark end end end Adobe_pattern_AI5 begin } ifelse } def /terminate { currentdict Adobe_pattern_AI5 eq { end } if } def errordict /nocurrentpoint { pop stop } put errordict /invalidaccess { pop stop } put /patternencoding 256 array def 0 1 255 { patternencoding exch ( ) 2 copy exch 0 exch put cvn put } for /definepattern { 17 dict begin /uniform exch def /cache exch def /key exch def /procarray exch def /mtx exch matrix invertmatrix def /height exch def /width exch def /ctm matrix currentmatrix def /ptm matrix def /str 32 string def /slice 9 dict def slice /s 1 put slice /q 256 procarray length div sqrt floor cvi put slice /b 0 put /FontBBox [ 0 0 0 0 ] def /FontMatrix mtx matrix copy def /Encoding patternencoding def /FontType 3 def /BuildChar { exch begin /setstrokeadjust where {pop true setstrokeadjust} if slice begin dup q dup mul mod s idiv /i exch def dup q dup mul mod s mod /j exch def q dup mul idiv procarray exch get /xl j width s div mul def /xg j 1 add width s div mul def /yl i height s div mul def /yg i 1 add height s div mul def uniform { 1 1 } { width 0 dtransform dup mul exch dup mul add sqrt dup 1 add exch div 0 height dtransform dup mul exch dup mul add sqrt dup 1 add exch div } ifelse width 0 cache { xl 4 index mul yl 4 index mul xg 6 index mul yg 6 index mul setcachedevice } { setcharwidth } ifelse gsave scale newpath xl yl moveto xg yl lineto xg yg lineto xl yg lineto closepath clip newpath end end exec grestore } def key currentdict definefont end } def /patterncachesize { gsave newpath 0 0 moveto width 0 lineto width height lineto 0 height lineto closepath patternmatrix setmatrix pathbbox exch ceiling 4 -1 roll floor sub 3 1 roll ceiling exch floor sub mul 1 add grestore } def /patterncachelimit { cachestatus 7 1 roll 6 npop 8 mul } def /patternpath { exch dup begin setfont ctm setmatrix concat slice exch /b exch slice /q get dup mul mul put FontMatrix concat uniform { width 0 dtransform round width div exch round width div exch 0 height dtransform round height div exch height div exch 0 0 transform round exch round exch ptm astore setmatrix } { ptm currentmatrix pop } ifelse { currentpoint } stopped not { 2 npop pathbbox true 4 index 3 index eq 4 index 3 index eq and { pop false { { 2 npop } { 3 npop true } { 7 npop true } { pop true } pathforall } stopped { 5 npop true } if } if { height div ceiling height mul 4 1 roll width div ceiling width mul 4 1 roll height div floor height mul 4 1 roll width div floor width mul 4 1 roll 2 index sub height div ceiling cvi exch 3 index sub width div ceiling cvi exch 4 2 roll moveto FontMatrix mtx invertmatrix dup dup 4 get exch 5 get rmoveto ptm ptm concatmatrix pop slice /s patterncachesize patterncachelimit div ceiling sqrt ceiling cvi dup slice /q get gt { pop slice /q get } if put 0 1 slice /s get dup mul 1 sub { slice /b get add gsave 0 1 str length 1 sub { str exch 2 index put } for pop dup { gsave ptm setmatrix 1 index str length idiv { str show } repeat 1 index str length mod str exch 0 exch getinterval show grestore 0 height rmoveto } repeat grestore } for 2 npop } { 4 npop } ifelse } if end } def /patternclip { _eo {eoclip} {clip} ifelse } def /patternstrokepath { strokepath } def /patternmatrix matrix def /patternfill { dup type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get } if gsave patternclip Adobe_pattern_AI5 /patternpath get exec grestore newpath } def /patternstroke { dup type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get } if gsave patternstrokepath true { { { newpath moveto } { lineto } { curveto } { closepath 3 copy Adobe_pattern_AI5 /patternfill get exec } pathforall 3 npop } stopped { 5 npop patternclip Adobe_pattern_AI5 /patternfill get exec } if } { patternclip Adobe_pattern_AI5 /patternfill get exec } ifelse grestore newpath } def /vpatternawidthshow { 6 1 roll /_hvay exch ddef /_hvax exch ddef /_hvwb exch ddef /_hvcy exch ddef /_hvcx exch ddef { dup cstring dup length 1 eq _charorientation 1 eq and { -90 rotate currentpoint _fontRotateAdjust add moveto gsave false charpath currentpoint 5 index 5 index 5 index Adobe_pattern_AI5 /patternfill get exec grestore _fontRotateAdjust sub moveto _hvwb eq { _hvcx _hvcy rmoveto } if _hvax _hvay rmoveto 90 rotate } { currentpoint _fontHeight sub _hvax sub 3 index _hvwb eq { _hvcx sub } if currentpoint exch 4 index stringwidth pop 2 div sub exch _fontAscent sub moveto gsave 2 index false charpath 6 index 6 index 6 index Adobe_pattern_AI5 /patternfill get exec grestore newpath moveto pop pop } ifelse } cforall 3 npop } def /hpatternawidthshow { { dup cstring exch gsave 3 index eq { 5 index 5 index rmoveto } if false charpath currentpoint 9 index 9 index 9 index Adobe_pattern_AI5 /patternfill get exec grestore newpath moveto 2 copy rmoveto } cforall 8 npop } def /patternashow { 0 0 0 6 3 roll patternawidthshow } def /patternawidthshow { 6 index type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get 7 1 roll } if _lineorientation 0 eq { hpatternawidthshow } { vpatternawidthshow } ifelse } def /vpatternawidthshowstroke { 7 1 roll 6 1 roll /_hvay exch ddef /_hvax exch ddef /_hvwb exch ddef /_hvcy exch ddef /_hvcx exch ddef { dup cstring dup length 1 eq _charorientation 1 eq and { -90 rotate currentpoint _fontRotateAdjust add moveto gsave false charpath currentpoint 3 index setmatrix 6 index 6 index 6 index Adobe_pattern_AI5 /patternstroke get exec grestore _fontRotateAdjust sub moveto _hvwb eq { _hvcx _hvcy rmoveto } if _hvax _hvay rmoveto 90 rotate } { currentpoint _fontHeight sub _hvax sub 3 index _hvwb eq { _hvcx sub } if currentpoint exch 4 index stringwidth pop 2 div sub exch _fontAscent sub moveto gsave 2 index false charpath 4 index setmatrix 7 index 7 index 7 index Adobe_pattern_AI5 /patternstroke get exec grestore newpath moveto pop pop } ifelse } cforall 4 npop } def /hpatternawidthshowstroke { 7 1 roll { dup cstring exch gsave 3 index eq { 5 index 5 index rmoveto } if false charpath currentpoint 7 index setmatrix 10 index 10 index 10 index Adobe_pattern_AI5 /patternstroke get exec grestore newpath moveto 2 copy rmoveto } cforall 9 npop } def /patternashowstroke { 0 0 0 7 3 roll patternawidthshowstroke } def /patternawidthshowstroke { 7 index type /dicttype eq { patternmatrix /patternmatrix get 8 1 roll } if _lineorientation 0 eq { hpatternawidthshowstroke } { vpatternawidthshowstroke } ifelse } def end setpacking %%EndResource %%EndProlog %%BeginSetup Adobe_level2_AI5 /initialize get exec Adobe_screens_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_typography_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_blend_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_pattern_AI5 /initialize get exec Adobe_ColorImage_AI6 /initialize get exec Adobe_Illustrator_AI5 /initialize get exec [ 39/quotesingle 96/grave 130/quotesinglbase 131/florin 132/quotedblbase 133/ellipsis 134/dagger 135/daggerdbl 136/circumflex 137/perthousand 138/Scaron 139/guilsinglleft 140/OE 145/quoteleft 146/quoteright 147/quotedblleft 148/quotedblright 149/bullet 150/endash 151/emdash 152/tilde 153/trademark 154/scaron 155/guilsinglright 156/oe 157/dotlessi 159/Ydieresis 164/currency 166/brokenbar 168/dieresis 169/copyright 170/ordfeminine 172/logicalnot 174/registered 175/macron 176/ring 177/plusminus 178/twosuperior 179/threesuperior 180/acute 181/mu 183/periodcentered 184/cedilla 185/onesuperior 186/ordmasculine 188/onequarter 189/onehalf 190/threequarters 192/Agrave 193/Aacute 194/Acircumflex 195/Atilde 196/Adieresis 197/Aring 198/AE 199/Ccedilla 200/Egrave 201/Eacute 202/Ecircumflex 203/Edieresis 204/Igrave 205/Iacute 206/Icircumflex 207/Idieresis 208/Eth 209/Ntilde 210/Ograve 211/Oacute 212/Ocircumflex 213/Otilde 214/Odieresis 215/multiply 216/Oslash 217/Ugrave 218/Uacute 219/Ucircumflex 220/Udieresis 221/Yacute 222/Thorn 223/germandbls 224/agrave 225/aacute 226/acircumflex 227/atilde 228/adieresis 229/aring 230/ae 231/ccedilla 232/egrave 233/eacute 234/ecircumflex 235/edieresis 236/igrave 237/iacute 238/icircumflex 239/idieresis 240/eth 241/ntilde 242/ograve 243/oacute 244/ocircumflex 245/otilde 246/odieresis 247/divide 248/oslash 249/ugrave 250/uacute 251/ucircumflex 252/udieresis 253/yacute 254/thorn 255/ydieresis TE %AI3_BeginEncoding: _Helvetica Helvetica [ /_Helvetica/Helvetica 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-Bold Helvetica-Bold [ /_Helvetica-Bold/Helvetica-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-Oblique Helvetica-Oblique [ /_Helvetica-Oblique/Helvetica-Oblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-BoldOblique Helvetica-BoldOblique [ /_Helvetica-BoldOblique/Helvetica-BoldOblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Roman Times-Roman [ /_Times-Roman/Times-Roman 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Bold Times-Bold [ /_Times-Bold/Times-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Italic Times-Italic [ /_Times-Italic/Times-Italic 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-BoldItalic Times-BoldItalic [ /_Times-BoldItalic/Times-BoldItalic 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier Courier [ /_Courier/Courier 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-Bold Courier-Bold [ /_Courier-Bold/Courier-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-Oblique Courier-Oblique [ /_Courier-Oblique/Courier-Oblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-BoldOblique Courier-BoldOblique [ /_Courier-BoldOblique/Courier-BoldOblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Symbol Symbol [ /_Symbol/Symbol 0 0 1 TZ %AI3_EndEncoding AdobeType %%EndSetup 1 XR u 0.000 0.000 0.000 0.000 k [] 0 d 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 140.0315 154.2047 m 211.4646 154.2047 L 211.4646 189.9213 L 140.0315 189.9213 L 140.0315 154.2047 L B U 0 To 1.0000 0.0000 0.0000 1.0000 162.1417 175.7480 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (NUA/\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 146.8346 161.5748 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0.000 0.000 0.000 1.000 k (Sofia stack\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 J 1 j 175.7480 154.2047 m 175.7480 2.2677 L S U u 0.000 0.000 0.000 0.000 k 166.6772 28.9134 m 184.8189 28.9134 L 184.8189 109.9843 L 166.6772 109.9843 L 166.6772 28.9134 L B U u 0.000 0.000 0.000 1.000 K 363.9685 108.2835 m 188.2205 108.2835 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 188.7874 106.0157 m 184.8189 108.2835 L 188.7874 110.5512 L 188.7874 106.0157 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 254.5512 111.6850 m 294.2362 111.6850 L 294.2362 123.0236 L 254.5512 123.0236 L 254.5512 111.6850 L F U 0 To 1.0000 0.0000 0.0000 1.0000 255.1181 114.5197 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (MESSAGE\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 184.8189 82.2047 m 360.5669 82.2047 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 360.0000 84.4724 m 363.9685 82.2047 L 360.0000 80.5039 L 360.0000 84.4724 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 260.2205 85.6063 m 287.4331 85.6063 L 287.4331 97.5118 L 260.2205 97.5118 L 260.2205 85.6063 L F U 0 To 1.0000 0.0000 0.0000 1.0000 261.3543 89.0079 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (200 Ok\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 166.6772 72.5669 m 9.0709 72.5669 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 9.6378 70.8661 m 5.6693 72.5669 L 9.6378 74.8346 L 9.6378 70.8661 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 56.6929 75.9685 m 115.6535 75.9685 L 115.6535 87.3071 L 56.6929 87.3071 L 56.6929 75.9685 L F U 0 To 1.0000 0.0000 0.0000 1.0000 57.8268 79.3701 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (nua_i_message\r) Tx TO 0.000 0.000 0.000 1.000 K %%PageTrailer gsave annotatepage grestore showpage %%Trailer Adobe_Illustrator_AI5 /terminate get exec Adobe_pattern_AI5 /terminate get exec Adobe_blend_AI5 /terminate get exec Adobe_ColorImage_AI6 /terminate get exec Adobe_typography_AI5 /terminate get exec Adobe_screens_AI5 /terminate get exec Adobe_level2_AI5 /terminate get exec %%EOF II*(@33JJ``ww33JJ``ww33GG\\pp""11@@OO^^nn}}""++33<>FFMMUUll""11@@OO^^nn}}33GG\\pp33JJ``ww33MMff33PPmm33MMff33JJ``ww33MMff((77EETTbbqq--DD[[qq::WWuu::WWuu::WWuu::WWuu""DDff""DDff))RRzz""DDff::WWuu33MMff""++33<FMUl"Dfƪ3"J1`@wO^n}Ҍ"Df׈33GG\\pp)Rz"31J@`Ow^n}"Df3M"f+3<DMUh|:Wu3Pm33MMff3Mf"+3<DMUh:|Wu3"J1`@wO^n}Ҍ"Df̈ת33MMff:Wu3(P7mETbq3Mf3Uw--DD[[qq3&M3f@MYfs:WuȒׯ33MMff:Wu3M&f3@MYfs:Wu! ,@H*\ȰÇ#JHŋ3jȱǏ CIb('Lɲ˗0cʜpF8$s'}JѣHK Mr)ӧPJOVf̚+BTÊK,h})'Z|[p*[߿wÈC-ǐ3LG'c̹盟CMZeӨSlYmݴma+޵U07=.ȓ+_μУKN³3$^[%}r'=AZ՟)Jq߿뾽fFwf^ :_-~&afمv`~(aH(fF`,8.(H0hJ(DvW$j8`A&TaC!F1D12cGA9dI'/n@@-]S ͔(qԹgO?uH%A-mzhSOF:UR$^պkWQ܈fL,La~;n]}Wo_(paÇ䛘qcǏ /P&qjNԁ)(UxAvRR !-xasj!K_y!5!ga)(w+8c'x#6"8"8I`XdMɤO~6$/bHe`f։!y&i&m&q9g.J UY{r敟(Y((-(=)MZ)])m) *Z**}*=p+dZ+ޚ+|+Q,> [,7,85|Jզnz[@$XA .dC%NXE5nG!E$ 1I)UdK1e,YM9u1@O~%ZQIqUZiSQNiUWnW8l±ӂe[k)lAF _[]x*cȀ ]%d˾٫{}] ~lk3@(o(P;A¹o33S/>jC\B ST>P\E]JFkFpqGtGHfRrI&\I( H)R+R-Һ/3**4LTsMdM1݄s-*s#OtP%P Ete!!TMG'J/tL74N?PG5SS t:c, ÊDU,r}DNj])e5-_ዯ4ame2v=ͦ 3v[2o-h5<=wev/^zs^|s7_~"_7`qݷ`u8VĄS\8 ]P1Z#$CXxF1WEo'fy-f]dxTV{ge6^+4:1-F"USalUZiR鮯EdN4kĽrrp 7pW%;`;r٦/g7s_=G'=bOG8u fu_ggYv=wxw]?7x%oG[Ƕy煅>zUT5{?M|FQ?}??OwVNM x~. \FPR@;sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/docs/pictures/SIP_basic_incoming_operation.vsd000066400000000000000000000420001223300710500306110ustar00rootroot00000000000000ࡱ>   Root EntryFp5B@VisioDocumentSummaryInformation(DocumentSummaryInformation8Visio (TM) Drawing l URd !fffMMM333$ $ U8@ TD Arial@NMonotype Sorts@m Wingd NtSymbol5T?? Y@-1U J:DT1EW-hPT8*  .U_b a酸0zGz?@3CfRbU|||%U P } |KpG/Y&4Y$? v AfY&,,' /Dq&z&} | |y  }{})} ?2  | | ||||*|||E-?k4'-'CECE,'*CECECE-?H>?:`}'CEUCECECECEUCECE- O4F2AJY;; AnVnVAbGTfY R_R__ `#f:/lb6p`fW /l /l  Y?5?(\ #!+ | tFf-|J-|-|-wG QUo "OM`EtoA _3=OOOaOsO@O??O?7ܻuR? sU/-O%7I[mRf J+ K5   . ||i| d' 0/UKiR?d?v4Gzt2#&Us s s s) -0jӯY/ƛ!3)󿵶1D///Q+p)?HdYc4AkǿٿYfU|%1I߀O]-(fp ɻ %-=Y[:!#:4)A/q//YkϹ/p?2 Sπ'9}Fɇ7%õ8@\n1$u  (:L^p)BH>ZՔU \ n4!'4#U2q ?/%&k/%&`,`,`',ѓ4?|QԞQyٓA G $z Z$bp6q /#3=/Uq@T0'vr@1N!T0;UOauADV=煤{2r H+"P)Ҳ$2@1@1B,$1//cAm/ߙ߫BVVj /Q?c?u4D?U0O贁 NkRC6$SfMea5t(O"?2RO}q19!S _2_D_"3Htr+*a__//5o2DV õoa`oo1 I+< g4`\\esprn002\HER1F5B1S odWX+'?LetterO_b PRIV0|'r\KhC]>w!tuy //-/?/Q/c/u////////??)?;?M1E%winspool\\esprn002\HER1F5B1IP_172.21?.36.10UFDfP h-RTUUUA@ ?I?a 3h AeqYk Hu_ Q? #,BDrag between shapes to indicate a flow offormation or control.mb?sߛ⿻xw?t? 8HD    3h <>T$  ;MBRAU@?N ?AP6 Ju `u buU  -J ">ۀJuM` Zue"JD4WAQ @%UI>J[@hK'F"U/g%'_-/g JQ#5 L"V &6 霑c ?@IW0?@q`0U>U5Q?!9[a2f`rd}b0@3&/0`A.=@2M @J2uF.3B B$fH2&M+3Q(-DT! @6[Dн8P$?J 3tNsWB Ld!%6 MB##0O贁Nk?<$2%@@PR%|#xQ}T5 B`7Copyright 1999 Visio Corporation. All Rs reserved.J`P_SCPchm!#22776G#2r5ofP"JSfunq&^(E9 Yr[xQ4 0UChange Arrow?head..PVcthe ae siz`n`tyle for`is connectorP1`Bb)WlJhUd>5 yG|(AJ*C<4bZw"M (3,rx srA iVohot'd1dxB3d+=-C2U낥@6f 32`_D/@>W4C)rp -3TqC@@JQ\^E? v!3?|@ 2Pa@0pqB;uK`u`WE @ǗHXC1 aVHl'-d! !Oya HE_9bFt w~# . B W ]MaLku]@+Tk]/aTo fPUl4,"H$ @Y,b'@ d OA-4 U7U2@ [7ERH<( U2E 7 R(n S >@?4 =RDtKOi{ UP?V]U$5@*P8FDTey  ahm qTP^UI"H$ @IY,b'@? ?I*M_q2?p^qu2`"ua )e 0QPC$ d" !!H!@$'y!(*e!(*!(!'P!(F!#q!Pa!F!F!! h1F!w??????!a3ky!|aM % @*#DN?tE/A%F'/Ble!J#UQ/c#%ay!! "`B-Ba.-!  V*W__#QoD!o3ogQ%[kro_m!2oRqr r"s/NUA/ Sofia stack"cU?OO,O>OKO !ҨEEP-DT!f-quF `u `buh0`u k]@"qrbchbmwrqOM߆_B›OFEO@$ڋއ߆^rhz ^(Ua^8Ti){WU_s_U[*oKe O0hc:y G{"!%v~`OD EUO!MնBQ(_:_L_^_*__oo=oS!Y_ƣτoCoߡ8Jߘonߴoo 1v!!%3!!D{R#5GY %O%I 2DVhz63Lv200 Ods1kRE/%/7/I/[/m///b^@@Ia#.:L+GhC?Hf#;!`2?111 I?0[5Bs 1?Q?t0 tN&dqzs?TRMO_Qdq;OMO_OqOOOOORnOO__$_nua_i_messageU  Ul4,"H$ @Y,b'@  C-37"AU2@w IRH<( U2Edw \7 RUlL I @?' >wRD_<( i;?U$ < w?VU5@@g( "*^p=*4 -l #5GYk}C:\Program Files\Microsoft Visio\Solutions\Block Dia\Basic Shapes.vss*7l"4FXj|  C:\Program Files\Microsoft Visio\Solutions\ Extras\Connectors.vss]l 2DV`hzՌ(X<C* KC! 4/ =/$ C6/*U1(5 O"D&U=Q Jf )h"/Tyj+U-| Ʌ&Q- H*9(TYgEQ/,GuideTheDocPage-1Gesture FormatConnectorVisio 90Directed line 1Directed lin?e 1.7Directed line 1.11Directed line 1.12_v3 v E, <- LTGdU| UUUAUU   U ) ,E 4I <MXJ 0 xfUl4,"H$ @Y,bK'@  2UA-3@7;Ul4, |  AJ-37A_*<N@D F KRVg q6uH<( H<( _*<NE  RVg &q {th * g"4pFX(?@(~fϫ@ , :TR q&^ !B< 2b>#O}HpB| U$@' XN )D yY1^ =`2^ QfV?lO xFDW 3C=v՜.+,D՜.+,@HP\h t   PagesMastersPage-1Directed line 18_VPID_PREVIEWS@_VPID_ALTERNATENAMES?_PID_LINKBASE A Oh+'0HPdp| rinnerahSIP outgoing callGEWRSt EMFl@@VISIODrawing% %   &%   '% V0999% ( % (  Rp ArialxxxxxxwZwxdv% Rp ArialHUw@*wwFhtUw*wFFUw%wxFx|HUw(%w\xFFx#` xdv% %  %   TdAALTNUA/   T,AA LdSofia stacki     % &%  W$% ( % Rp  Arialxxxxxxdv% %  %  % &%   '% V0U   UU% ( % (  &%  W$XEXEXX% ( %  '% % V, U\\ XU\% % (   '% % V0>RRR>>R% % (  Rp Arialnxxxxxxdv% %  %   Tx@OAAML\MESSAGEV  % &%  W$ ? ?% ( %  '% % V,>E>E>>% % (   '% % V0kkk% % (  Rp ArialHUw@*wwpFpFFUw%wxFx|HUw(%w\xpFpFx#` xdv% %  %   Tpm|AAzLX200 Ok  % &%  W$% ( %  '% % V,% % (   '% % V0)|)|)|)% % (  Rp ArialHUw@*wwpFpFFUw%wxFx|HUw(%w\xpFpFx#` xdv% %  %   T*~AA* Lhnua_i_message  % VisioInformation"sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/docs/pictures/SIP_basic_outgoing_operation.eps000066400000000000000000011073771223300710500306600ustar00rootroot00000000000000&%!PS-Adobe-3.0 EPSF-3.0 %%Creator: ImageMark Software Labs %%For: () () %%Title: V:\work\rinnerah\sofia\SIP basic outgoing operation.eps %%CreationDate: () () %%BoundingBox: 0 0 379 256 %%DocumentProcessColors: Black %%ColorUsage:Color %%DocumentFonts: Helvetica %%+Helvetica-Bold %%+Helvetica-Oblique %%+Helvetica-BoldOblique %%+Times-Roman %%+Times-Bold %%+Times-Italic %%+Times-BoldItalic %%+Courier %%+Courier-Bold %%+Courier-Oblique %%+Courier-BoldOblique %%+Symbol %%DocumentSuppliedResources: procset Adobe_level2_AI5 1.2 0 %%+ procset Adobe_screens_AI5 1.0 0 %%+ procset Adobe_typography_AI5 1.0 0 %%+ procset Adobe_ColorImage_AI6 1.1 0 %%+ procset Adobe_blend_AI5 1.0 0 %%+ procset Adobe_pattern_AI5 1.0 0 %%+ procset Adobe_Illustrator_AI5 1.0 0 %AI5_FileFormat 3.0 %AI3_ColorUsage: Color %AI3_TemplateBox: 0 0 379 256 %AI3_TileBox: 0 0 379 256 %AI3_DocumentPreview: None %%Template: %%PageOrigin:0.0000 0.0000 %AI7_GridSettings: 72 8 72 8 1 0 0.8 0.8 0.8 0.9 0.9 0.9 %%EndComments %%BeginProlog %%BeginResource: procset Adobe_level2_AI5 1.2 0 %%Title: (Adobe Illustrator (R) Version 5.0 Level 2 Emulation) %%Version: 1.2 0 %%CreationDate: (04/10/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /Adobe_level2_AI5 25 dict dup begin put /packedarray where not { userdict begin /packedarray { array astore readonly } bind def /setpacking /pop load def /currentpacking false def end 0 } if pop userdict /defaultpacking currentpacking put true setpacking /initialize { Adobe_level2_AI5 begin } bind def /terminate { currentdict Adobe_level2_AI5 eq { end } if } bind def mark /setcustomcolor where not { /findcmykcustomcolor { 0 6 packedarray } bind def /findrgbcustomcolor { 1 5 packedarray } bind def /setcustomcolor { exch aload pop 0 eq { pop 4 { 4 index mul 4 1 roll } repeat 5 -1 roll pop setcmykcolor } { pop 3 { 1 exch sub 3 index mul 1 exch sub 3 1 roll } repeat 4 -1 roll pop setrgbcolor } ifelse } def } if /gt38? mark {version cvr cvx exec} stopped {cleartomark true} {38 gt exch pop} ifelse def userdict /deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt put userdict /level2? systemdict /languagelevel known dup { pop systemdict /languagelevel get 2 ge } if put /level2ScreenFreq { begin 60 HalftoneType 1 eq { pop Frequency } if HalftoneType 2 eq { pop GrayFrequency } if HalftoneType 5 eq { pop Default level2ScreenFreq } if end } bind def userdict /currentScreenFreq level2? {currenthalftone level2ScreenFreq} {currentscreen pop pop} ifelse put level2? not { /setcmykcolor where not { /setcmykcolor { exch .11 mul add exch .59 mul add exch .3 mul add 1 exch sub setgray } def } if /currentcmykcolor where not { /currentcmykcolor { 0 0 0 1 currentgray sub } def } if /setoverprint where not { /setoverprint /pop load def } if /selectfont where not { /selectfont { exch findfont exch dup type /arraytype eq { makefont } { scalefont } ifelse setfont } bind def } if /cshow where not { /cshow { [ 0 0 5 -1 roll aload pop ] cvx bind forall } bind def } if } if cleartomark /anyColor? { add add add 0 ne } bind def /testColor { gsave setcmykcolor currentcmykcolor grestore } bind def /testCMYKColorThrough { testColor anyColor? } bind def userdict /composite? level2? { gsave 1 1 1 1 setcmykcolor currentcmykcolor grestore add add add 4 eq } { 1 0 0 0 testCMYKColorThrough 0 1 0 0 testCMYKColorThrough 0 0 1 0 testCMYKColorThrough 0 0 0 1 testCMYKColorThrough and and and } ifelse put composite? not { userdict begin gsave /cyan? 1 0 0 0 testCMYKColorThrough def /magenta? 0 1 0 0 testCMYKColorThrough def /yellow? 0 0 1 0 testCMYKColorThrough def /black? 0 0 0 1 testCMYKColorThrough def grestore /isCMYKSep? cyan? magenta? yellow? black? or or or def /customColor? isCMYKSep? not def end } if end defaultpacking setpacking %%EndResource %%BeginResource: procset Adobe_typography_AI5 1.0 1 %%Title: (Typography Operators) %%Version: 1.0 %%CreationDate:(03/26/93) () %%Copyright: ((C) 1987-1993 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_typography_AI5 54 dict dup begin put /initialize { begin begin Adobe_typography_AI5 begin Adobe_typography_AI5 { dup xcheck { bind } if pop pop } forall end end end Adobe_typography_AI5 begin } def /terminate { currentdict Adobe_typography_AI5 eq { end } if } def /modifyEncoding { /_tempEncode exch ddef /_pntr 0 ddef { counttomark -1 roll dup type dup /marktype eq { pop pop exit } { /nametype eq { _tempEncode /_pntr dup load dup 3 1 roll 1 add ddef 3 -1 roll put } { /_pntr exch ddef } ifelse } ifelse } loop _tempEncode } def /TE { StandardEncoding 256 array copy modifyEncoding /_nativeEncoding exch def } def % /TZ { dup type /arraytype eq { /_wv exch def } { /_wv 0 def } ifelse /_useNativeEncoding exch def pop pop findfont _wv type /arraytype eq { _wv makeblendedfont } if dup length 2 add dict begin mark exch { 1 index /FID ne { def } if cleartomark mark } forall pop /FontName exch def counttomark 0 eq { 1 _useNativeEncoding eq { /Encoding _nativeEncoding def } if cleartomark } { /Encoding load 256 array copy modifyEncoding /Encoding exch def } ifelse FontName currentdict end definefont pop } def /tr { _ax _ay 3 2 roll } def /trj { _cx _cy _sp _ax _ay 6 5 roll } def /a0 { /Tx { dup currentpoint 3 2 roll tr _psf newpath moveto tr _ctm _pss } ddef /Tj { dup currentpoint 3 2 roll trj _pjsf newpath moveto trj _ctm _pjss } ddef } def /a1 { /Tx { dup currentpoint 4 2 roll gsave dup currentpoint 3 2 roll tr _psf newpath moveto tr _ctm _pss grestore 3 1 roll moveto tr sp } ddef /Tj { dup currentpoint 4 2 roll gsave dup currentpoint 3 2 roll trj _pjsf newpath moveto trj _ctm _pjss grestore 3 1 roll moveto tr jsp } ddef } def /e0 { /Tx { tr _psf } ddef /Tj { trj _pjsf } ddef } def /e1 { /Tx { dup currentpoint 4 2 roll gsave tr _psf grestore 3 1 roll moveto tr sp } ddef /Tj { dup currentpoint 4 2 roll gsave trj _pjsf grestore 3 1 roll moveto tr jsp } ddef } def /i0 { /Tx { tr sp } ddef /Tj { trj jsp } ddef } def /i1 { W N } def /o0 { /Tx { tr sw rmoveto } ddef /Tj { trj swj rmoveto } ddef } def /r0 { /Tx { tr _ctm _pss } ddef /Tj { trj _ctm _pjss } ddef } def /r1 { /Tx { dup currentpoint 4 2 roll currentpoint gsave newpath moveto tr _ctm _pss grestore 3 1 roll moveto tr sp } ddef /Tj { dup currentpoint 4 2 roll currentpoint gsave newpath moveto trj _ctm _pjss grestore 3 1 roll moveto tr jsp } ddef } def /To { pop _ctm currentmatrix pop } def /TO { iTe _ctm setmatrix newpath } def /Tp { pop _tm astore pop _ctm setmatrix _tDict begin /W { } def /h { } def } def /TP { end iTm 0 0 moveto } def /Tr { _render 3 le { currentpoint newpath moveto } if dup 8 eq { pop 0 } { dup 9 eq { pop 1 } if } ifelse dup /_render exch ddef _renderStart exch get load exec } def /iTm { _ctm setmatrix _tm concat 0 _rise translate _hs 1 scale } def /Tm { _tm astore pop iTm 0 0 moveto } def /Td { _mtx translate _tm _tm concatmatrix pop iTm 0 0 moveto } def /iTe { _render -1 eq { } { _renderEnd _render get dup null ne { load exec } { pop } ifelse } ifelse /_render -1 ddef } def /Ta { pop } def /Tf { dup 1000 div /_fScl exch ddef % selectfont } def /Tl { pop 0 exch _leading astore pop } def /Tt { pop } def /TW { 3 npop } def /Tw { /_cx exch ddef } def /TC { 3 npop } def /Tc { /_ax exch ddef } def /Ts { /_rise exch ddef currentpoint iTm moveto } def /Ti { 3 npop } def /Tz { 100 div /_hs exch ddef iTm } def /TA { pop } def /Tq { pop } def /Th { pop pop pop pop pop } def /TX { pop } def /Tk { exch pop _fScl mul neg 0 rmoveto } def /TK { 2 npop } def /T* { _leading aload pop neg Td } def /T*- { _leading aload pop Td } def /T- { _hyphen Tx } def /T+ { } def /TR { _ctm currentmatrix pop _tm astore pop iTm 0 0 moveto } def /TS { currentfont 3 1 roll /_Symbol_ _fScl 1000 mul selectfont 0 eq { Tx } { Tj } ifelse setfont } def /Xb { pop pop } def /Tb /Xb load def /Xe { pop pop pop pop } def /Te /Xe load def /XB { } def /TB /XB load def currentdict readonly pop end setpacking %%EndResource %%BeginResource: procset Adobe_screens_AI5 1.2 0 %%Title: (Adobe Illustrator (R) Version 5.0 Custom Halftone Screens ProcSet) %%Version: 1.2 0 %%CreationDate: (03/24/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking systemdict begin userdict /Adobe_screens_AI5 15 dict dup begin put /initialize { Adobe_screens_AI5 begin /screenid deviceDPI 600 gt composite? not or { -1 } { deviceDPI currentScreenFreq dup dup 60 ge exch 150 le and deviceDPI 300 le and { pop 60 } if div 1.41421 div 0.5 add cvi } ifelse def 2 screenid eq { /customsize 16 def /customdata /customdata2 def setcustomscreen } if 3 screenid eq { /customsize 24 def /customdata /customdata3 def setcustomscreen } if 4 screenid eq { /customsize 16 def /customdata /customdata4 def setcustomscreen } if 5 screenid eq { /customsize 20 def /customdata /customdata5 def setcustomscreen } if 6 screenid eq { /customsize 24 def /customdata /customdata6 def setcustomscreen } if 7 screenid eq { /customsize 28 def /customdata /customdata7 def setcustomscreen } if 8 screenid eq { /customsize 16 def /customdata /customdata8 def setcustomscreen } if } def /terminate { currentdict Adobe_screens_AI5 eq { end } if } def /setcustomscreen { deviceDPI customsize div 0 { 1 add 2 div customsize mul cvi exch 1 add 2 div customsize mul cvi exch customsize mul add customdata load exch get 256 div } setscreen } def /customdata2 28 28 mul string def currentfile customdata2 readhexstring 4180E8694988E2634382EA6B4B8AE061A01939C8A81737C2A21B3BCAAA1636C0 F8795998F6775796FA7B5B9AF57656952ED8B80727D6B60F2FDABA0626D5B50E 4E8DE6674786EE6F4F8EE5664685ED6EAD1434C6A61F3FCEAE1232C5A51E3ECD F3745493FE7F5F9EF1725291FD7E5E9D24D3B30C2CDEBE0222D1B10A2ADDBD04 4483EB6C4C8BE1624281E96A4A89E364A31C3CCBAB1535C1A11A3AC9A91838C3 FB7C5C9BF4755594F97A5A99F778589730DBBB0525D4B40D2DD9B90828D7B710 508FE4654584EC6D4D8CE7684887EF70AF1131C4A41D3DCCAC1333C7A72040CF F0715190FC7D5D9CF2735392FF80609F21D0B00929DCBC0323D2B20B2BDFBF01 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata3 28 28 mul string def currentfile customdata3 readhexstring 011DC7F5E73D0421CBF3E43A021EC8F6E83E0522CCF2E43A2B648BC4A0762F68 8AC39E732C658CC5A177306989C29D72D5B6521A6192D9B55219608FD6B6531B 6193DAB451185F8FFCEE440C28D2FCED430B27D1FDEF450C29D3FBEC420A26D0 BEA77D366F83BCA77C356E87BFA87E377082BBA67B346D86145B99E0AE4A1259 98DFB14E155C9AE1AD4A115897DEB04D0623CDF4E63C0420CAF8EA400723CDF4 E53B031FC9F7E93F316988C19F752E678EC6A378326A88C09F742D668DC6A278 DBB350175E91D8B8551C6395DCB24F165D90D7B7541C6294FAEC420925CFFFF1 470E2BD5F9EB410824CEFEF0460D2AD4BAA57A336C85BEAA80397180B9A47933 6B84BDA97F387181105797DDAF4C145A9CE3AB480F5696DDAE4B13599BE2AC49 021EC8F6E83E0522CCF2E43A011DC7F5E73D0421CBF3E43A2C658CC5A1773069 89C29D722B648BC4A0762F688AC39E73D6B6531B6193DAB451185F8FD5B6521A 6192D9B55219608FFDEF450C29D3FBEC420A26D0FCEE440C28D2FCED430B27D1 BFA87E377082BBA67B346D86BEA77D366F83BCA77C356E87155C9AE1AD4A1158 97DEB04D145B99E0AE4A125998DFB14E0723CDF4E53B031FC9F7E93F0623CDF4 E63C0420CAF8EA40326A88C09F742D668DC6A278316988C19F752E678EC6A378 DCB24F165D90D7B7541C6294DBB350175E91D8B8551C6395F9EB410824CEFEF0 460D2AD4FAEC420925CFFFF1470E2BD5B9A479336B84BDA97F387181BAA57A33 6C85BEAA803971800F5696DDAE4B13599BE2AC49105797DDAF4C145A9CE3AB48 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata4 28 28 mul string def currentfile customdata4 readhexstring 1139B8E0FAD2531B133BBAE2F8D05119417180A6AE9A7B4B437382A5AD987949 C08867272F6F92CAC28A66262E6E90C8E8DE5F070F37B6F2EADD5E060E36B5F0 FED6571F173FBEE6FDD5561E163EBDE5AB9E7F4F477786A1A99D7E4E467685A3 2C6C96CEC68E62222A6A95CDC58D64240C34B3F6EED95A020A32B1F5EDDB5C04 143CBBE3F9D1521A123AB9E1FBD3541C447483A4AC997A4A427281A7AF9B7C4C C38B65252D6D91C9C1896828307093CBEBDC5D050D35B4F1E9DF60081038B7F3 FCD4551D153DBCE4FFD758201840BFE7A89C7D4D457584A2AA9F8050487887A0 296994CCC48C63232B6B97CFC78F61210931B0F4ECDA5B030B33B2F7EFD85901 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata5 28 28 mul string def currentfile customdata5 readhexstring 010B34C3EBFCF7CE3F16020C35C4EDFBF6CD3E15102552A4D6EADDB5632B1126 54A5D5EADCB3622A3958768499C19E8C7C5E3A59778498C19D8B7B5DC8A99370 47334C7587AFC9AA936F46324B7485AEF1E5BC6B1E0A2351A3D8F2E4BC6A1E09 2351A2D7FFF9D14219050F38C6EFFEF9D04118040E37C6EFE8E0B7662D142856 A8D3E7DFB7652D132856A7D4BF9C8E7F603D5B7A8195BE9A8E7E603C5B798297 314A7389B2CCAD906D442F497289B1CBAC926E4508214FA1DBF4E2B9671B0720 4EA0DAF4E3BA691C030D36C5EDFBF6CD3F16010C34C3ECFDF8CF4017122654A6 D4E9DDB4622A112553A5D6EBDEB5642C3B59788397C09C8B7C5D3A58778599C2 9E8C7D5FCAAB926E46314B7486AFC8AA947048334D7587B0F2E4BB691D082250 A1D8F1E6BD6B1F0A2452A3D9FDF8CF4118030E36C5EEFFFAD1421A050F38C7F0 E6DFB6642C132755A7D3E8E1B8662E152957A8D2BE9A8D7E5F3B5A798296BF9B 8F80613D5C7B80952F487188B1CAAC916D443049728AB3CCAE906C43061F4D9F DAF3E2BA681C07214FA0DBF5E1B8671A00000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata6 28 28 mul string def currentfile customdata6 readhexstring 081A44B6E0F2FDECC150250C091B45B6E1F3FCEBC04F240C1D336199C7D8DCD3 A56C37221E33619AC8D7DBD2A46B36214864798091AEB1958C7E694C49657A81 90ADB0948B7D684BB99D8475593C405C7888A1BEBA9E8574583B3F5B7888A0BD E4CBAA712E1215326098CFE8E4CCA9712D1114315F97CEE7F5F1C6552B040719 43B5DFFAF6F0C6542A03061842B4DEF9FFEDC352270E0B1C47B8E3F4FEECC251 260D0A1C46B7E2F4DAD5A76E39232035639CCAD5D9D4A66D38231F34629BC9D6 AF938E806A4E4A677C838FABAE928D7F694D4A667B828FAC3E5A778AA3BFBC9F 8772563A3D597689A2BEBB9F8673573A14305E97D1EAE6CDA76F2B0F132F5D96 D0E9E5CDA8702C10051742B3DDFCF8EEC4522801041641B2DDFBF7EFC5532902 091B45B6E1F3FCEBC04F240C081A44B6E0F2FDECC150250C1E33619AC8D7DBD2 A46B36211D336199C7D8DCD3A56C372249657A8190ADB0948B7D684B48647980 91AEB1958C7E694CBA9E8574583B3F5B7888A0BDB99D8475593C405C7888A1BE E4CCA9712D1114315F97CEE7E4CBAA712E1215326098CFE8F6F0C6542A030618 42B4DEF9F5F1C6552B04071943B5DFFAFEECC251260D0A1C46B7E2F4FFEDC352 270E0B1C47B8E3F4D9D4A66D38231F34629BC9D6DAD5A76E39232035639CCAD5 AE928D7F694D4A667B828FACAF938E806A4E4A677C838FAB3D597689A2BEBB9F 8673573A3E5A778AA3BFBC9F8772563A132F5D96D0E9E5CDA8702C1014305E97 D1EAE6CDA76F2B0F041641B2DDFBF7EFC5532902051742B3DDFCF8EEC4522801 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata7 28 28 mul string def currentfile customdata7 readhexstring 01061B44B7E1F5FEFBE6BD4A210C01071B45B8E1F6FDFBE6BC4A200B09132A54 A7D1EAF5EED9B05D331609142B55A8D2EAF4EED9AF5C32161D2D3D6993C1CBE0 CEC59B7140301E2E3D6A93C0CADFCDC49A713F3047576C7B828DA2B6A48F867E 6F5A48576C7C828CA1B6A38F867E6E59BAAA958A78634E4451667A8498ADBAAB 968977624E4350657A8398ADE3D4C99F7539251A273C6892C2D7E4D4C89E7539 241A273B6891C1D6F8F2DDB460371005122A53A7D0ECF9F2DDB360360F051229 53A6D0EBFFFDE8BE4C220D03081D46B9E3F7FFFCE7BD4B210D02071C46B8E2F7 F3F0DBB15E34180B152C56A9D3E8F3EFDAB05D34170A142C55A9D2E9DFCCC69C 7341321F2F3F6B94BFC9DECCC59C7241311F2E3E6A94BFCAB5A38E8780705B49 596D7D808BA0B4A28D877F6F5B48586D7C818BA043506479859AAFBCAC978876 614C424F64798499AEBBAB968977624D19263B6791C3D8E5D6C79D7337231825 3A6690C3D7E5D5C79E74382304112952A5CFEDFAF0DBB25E350E03102851A5CE ECF9F1DCB25F360E01071B45B8E1F6FDFBE6BC4A200B01061B44B7E1F5FEFBE6 BD4A210C09142B55A8D2EAF4EED9AF5C321609132A54A7D1EAF5EED9B05D3316 1E2E3D6A93C0CADFCDC49A713F301D2D3D6993C1CBE0CEC59B71403048576C7C 828CA1B6A38F867E6E5947576C7B828DA2B6A48F867E6F5ABAAB968977624E43 50657A8398ADBAAA958A78634E4451667A8498ADE4D4C89E7539241A273B6891 C1D6E3D4C99F7539251A273C6892C2D7F9F2DDB360360F05122953A6D0EBF8F2 DDB460371005122A53A7D0ECFFFCE7BD4B210D02071C46B8E2F7FFFDE8BE4C22 0D03081D46B9E3F7F3EFDAB05D34170A142C55A9D2E9F3F0DBB15E34180B152C 56A9D3E8DECCC59C7241311F2E3E6A94BFCADFCCC69C7341321F2F3F6B94BFC9 B4A28D877F6F5B48586D7C818BA0B5A38E8780705B49596D7D808BA0424F6479 8499AEBBAB968977624D43506479859AAFBCAC978876614C18253A6690C3D7E5 D5C79E74382319263B6791C3D8E5D6C79D73372303102851A5CEECF9F1DCB25F 360E04112952A5CFEDFAF0DBB25E350E pop pop /customdata8 28 28 mul string def currentfile customdata8 readhexstring 050F2747B6D6EEF8FEF4DCBC4D2D1507111D375F9EC6E0E9EBE6CCA4653D1F13 2939556F8EA8C1D1D3C3AE9475573B2B4961717D808999B1B39B8B867F73634B B8A090827A6A5A42445C6C7C8492A2BAD8C8AA97785232222434546E8DACCADA F0E2CFA768401A0A0C1C365E9DC5E4F2FAF7DFBF50301802040E2646B5D5EDFC FFF5DDBD4E2E160806102848B7D7EFF9EAE7CDA5663E2014121E38609FC7E1E8 D2C2AF9576583C2C2A3A56708FA9C0D0B29A8A878074644C4A62727E818898B0 435B6B7B8593A3BBB9A19183796959412333536D8CADCBDBD9C9AB9677513121 0B1B355D9CC4E5F3F1E3CEA6673F1909030D2545B4D4ECFDFBF6DEBE4F2F1701 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop end end defaultpacking setpacking %%EndResource %%BeginResource: procset AGM_Gradient_Sep 1.0 0 %%Title: (AGM Gradient Procset) %%Version: 1.0 0 %%CreationDate: (4/26/96) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /AGM_Gradient_Sep 5 dict dup begin put /AGM_Gradient_Sep_private 100 dict def /initialize{ AGM_Gradient_Sep begin AGM_Gradient_Sep_private begin _compositeJob{ initializeSinglePassSeps }{ initializeMultiPassSeps }ifelse initializeSeps AGM_Gradient_private begin /_fillSD newSpotDict def /_rampSD newSpotDict def /_nCustomColorSD nd end AGM_Gradient_Sep_private { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall AGM_Gradient_Sep { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall end currentdict readonly pop end }def /terminate{ currentdict AGM_Gradient_Sep eq{ end }if }def AGM_Gradient_Sep_private begin /initializeSeps{ _noImage not _level2PS not and{ /_whiteBytes 1 makeByte8 pt /knockOut{ 8 setImageParms _whiteBytes /_image load 5 execImage }def /linealFill{ mySave 8 setImageParms _color{ _nCustomColorSD begin cyan magenta yellow black _spotColor{ spot1 begin /tintImage tintValue 1 exch sub makeByte8 def end spot2 begin /tintImage tintValue 1 exch sub makeByte8 def end }if end 4{ makeByte8 4 1 roll }repeat true 4 _nCustomColorSD ncolorimage }{ _nCustomColorSD/black get 1 exch sub makeByte8 _nCustomColorSD bwImage }ifelse myRestore }def }{ /knockOut{ gsave false setoverprint 1 setgray 0 0 1 1 rectfill grestore }def }ifelse /newSpotDict{ 11 dict dup begin /nSpots 2 def /spot1 7 dict def /spot2 7 dict def end }def /initSpotData { begin /name nd /tintImage nd /tintValue nd /spot_C nd /spot_M nd /spot_Y nd /spot_K nd end }def /initSpotDict{ begin /cyanInk false def /magentaInk false def /yellowInk false def /blackInk false def /cyan nd /magenta nd /yellow nd /black nd spot1 initSpotData spot2 initSpotData end }def /copySpotDict{ /_dst xp begin cyanInk magentaInk yellowInk blackInk cyan magenta yellow black spot1 spot2 end _dst begin /spot1 spot1 maxlength dict def /spot2 spot2 maxlength dict def spot2 copy pop spot1 copy pop /black xd /yellow xd /magenta xd /cyan xd /blackInk xd /yellowInk xd /magentaInk xd /cyanInk xd end }def /setCustomColor { 1 index /Black eq{ 6 1 roll 5 npop 1 exch sub setgray }{ 6 1 roll _ccAry1 astore exch dup null eq{ pop 0 }if setcustomcolor }ifelse }def /setCStop{ /_colorStyle exch pt _colorStyle 0 eq{ 0 0 0 4 -1 roll 1 exch sub _spotColor{ /_colorStyle 3 pt /Black 1 index 1 exch sub }if }if _colorStyle 2 eq{ 3 npop }if _rampSD _fillSD copySpotDict _colorStyle 4 eq{ pop 9 2 roll 3 npop 6 -2 roll } if _colorStyle 3 eq _colorStyle 4 eq or{ _fillSD begin exch dup spot1/name get eq{ spot1 spot2 }{ spot2 spot1 }ifelse begin begin /name xd 1 exch sub /tintValue xd 4{ tintValue mul 4 1 roll }repeat _spotColor not{ /tintValue null def }if end /tintValue 0 def end end }if _fillSD nsetcustomcolor }def /renderCMYK{ spot1/name get null eq spot2/name get null eq and dup not{ pop spot1 spotConverted }if dup not{ pop spot2 spotConverted }if }def /fill_ /fill load def /fillOvp{ currentoverprint{ _inRipSep{ currentcolorspace 0 get dup /DeviceGray eq 1 index /DeviceCMYK eq or{ pop currentcmykcolor add add add 0 eq{ newpath }if }{ /Separation eq{ currentcolor 0 eq{ newpath }if }if }ifelse }{ currentgray 1 eq{ newpath }if }ifelse }if fill_ }def /fill{ _nCustomColorSD begin renderCMYK { fillOvp }{ spot1 begin gsave name null ne{ spot_C spot_M spot_Y spot_K name tintValue setCustomColor }{ 1 setgray }ifelse fillOvp grestore end spot2 begin name null ne{ gsave true setoverprint spot_C spot_M spot_Y spot_K name tintValue setCustomColor fillOvp grestore }if end newpath }ifelse end }def /expandSpot{ _spotColor{ /_len xp _rampSD begin spot1 begin tintImage null ne{ tintImage _len expandOne /tintImage xd }if end spot2 begin tintImage null ne{ tintImage _len expandOne /tintImage xd }if end end }{ pop }ifelse }def /rampImage{ _rampSD begin _color{ /cyanInk _cyanData 0 ne def /magentaInk _magentaData 0 ne def /yellowInk _yellowData 0 ne def /blackInk _blackData 0 ne def _nSamples setImageParms _nSamples expandSpot _cyanData _magentaData _yellowData _blackData _nSamples 4 expandColor true 4 _rampSD ncolorimage }{ /cyanInk false def /magentaInk false def /yellowInk false def /blackInk true def _nSamples setImageParms _blackData _rampSD bwImage }ifelse end }def /nsetcustomcolor where{ pop }{ /nsetcustomcolor { /_nCustomColorSD xp _nCustomColorSD begin 4 copy /black xd /yellow xd /magenta xd /cyan xd 4 copy 0 ne /blackInk xd 0 ne /yellowInk xd 0 ne /magentaInk xd 0 ne /cyanInk xd end setcmykcolor }def }ifelse /nsetcustomcolorend where{ pop }{ /nsetcustomcolorend { /_nCustomColorSD null pt }def }ifelse }def /initializeSinglePassSeps{ /_decodeNorm [0 1] pt /_decodeInvert [1 0] pt /spotConverted { begin name null eq{ false }{ tintValue null eq tintImage null eq and{ true }{ false currentpagedevice/SeparationOrder get{name eq or}forall not }ifelse }ifelse end }def /dictImage { 20 dict dup begin /Dict xd /Decode xd /DataSource xd /ImageMatrix xd /BitsPerComponent xd /Height xd /Width xd /ImageType 1 def Dict end /_image load 1 execImage }def /bwImage{ begin gsave currentoverprint{ blackInk{ [/Separation /Black /DeviceGray{}] setcolorspace _decodeInvert dictImage }{ 5 npop }ifelse }{ /DeviceGray setcolorspace _decodeNorm dictImage }ifelse grestore end }def /ncolorimage where{ pop }{ /ncolorimage{ begin renderCMYK { cyanInk magentaInk and yellowInk and blackInk and not currentoverprint and { pop pop gsave cyanInk{ 8 copy [/Separation /Cyan /DeviceGray{}] setcolorspace 3 npop _decodeNorm dictImage }if magentaInk{ 8 copy [/Separation /Magenta /DeviceGray{}] setcolorspace 4 -1 roll 3 npop _decodeNorm dictImage }if yellowInk{ 8 copy [/Separation /Yellow /DeviceGray{}] setcolorspace 4 -2 roll 3 npop _decodeNorm dictImage }if blackInk{ 4 -3 roll [/Separation /Black /DeviceGray{}] setcolorspace 3 npop _decodeNorm dictImage }{ 8 npop }ifelse grestore }{ /_colorimage load 10 execImage }ifelse }{ 6 npop gsave spot1 begin name null ne tintImage null ne and{ [/Separation name /DeviceGray{}] setcolorspace 4 copy tintImage name /Black eq{ _decodeNorm }{ _decodeInvert }ifelse dictImage }{ 1 setgray fill }ifelse end spot2 begin true setoverprint name null ne tintImage null ne and{ [/Separation name /DeviceGray{}] setcolorspace tintImage name /Black eq{ _decodeNorm }{ _decodeInvert }ifelse dictImage }{ 4 npop 1 setgray fill }ifelse end grestore }ifelse end }def }ifelse }def /initializeMultiPassSeps{ /_isCMYKSep _cyanPlate _magentaPlate or _yellowPlate or _blackPlate or pt /invertXfer{ [ { 1 exch sub }/exec load systemdict /currenttransfer get exec /exec load ] cvx systemdict /settransfer get exec }def /ccThrough{ gsave 1 setCustomColor currentcmykcolor grestore add add add 0 ne }def /spotConverted { begin _isCMYKSep not{ false }{ name null eq{ false }{ tintValue null eq tintImage null eq and{ true }{ spot_C spot_M spot_Y spot_K name ccThrough }ifelse }ifelse }ifelse end }def /spotChannel { _isCMYKSep{ pop false }{ begin name null eq{ false }{ spot_C spot_M spot_Y spot_K name ccThrough }ifelse end }ifelse }def /getChannelData { _isCMYKSep dup{ pop renderCMYK }if { _blackPlate{ 4 1 roll 3 npop blackInk }{ _yellowPlate{ 4 2 roll 3 npop yellowInk }{ _magentaPlate{ 4 3 roll 3 npop magentaInk }{ 3 npop cyanInk }ifelse }ifelse }ifelse { true /nonZeroData }{ true /zeroData }ifelse }{ 4 npop spot1/name get null ne spot1 spotChannel and{ spot1/tintImage get dup null ne{ false /nonZeroData }{ pop false /noData }ifelse }{ spot2/name get null ne spot2 spotChannel and{ spot2/tintImage get dup null ne{ false /nonZeroData }{ pop false /noData }ifelse }{ false /noData }ifelse }ifelse }ifelse }def /renderChannelData { /_tmp xp _tmp /nonZeroData ne currentoverprint and{ pop _tmp /zeroData eq{pop}if 4 npop }{ _tmp /nonZeroData eq{ { invertXfer }if systemdict/image get 5 execImage }{ pop _tmp /zeroData eq{pop}if 4 npop knockOut }ifelse }ifelse }def /bwImage{ begin gsave dup dup dup getChannelData exch pop false exch renderChannelData grestore end }def /ncolorimage{ begin pop pop gsave spot2/name get null ne spot2 spotChannel and{ true setoverprint }if getChannelData renderChannelData grestore end }def }def end end defaultpacking setpacking %%EndResource %%BeginResource: procset AGM_Gradient 1.0 0 %%Title: (AGM Gradient Procset) %%Version: 1.0 0 %%CreationDate: (4/26/96) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /AGM_Gradient 20 dict dup begin put /AGM_Gradient_private 200 dict def /initialize { AGM_Gradient begin AGM_Gradient_private begin initializeVars /bd systemdict/mark get def /ed _level2PS { (>>) }{ (counttomark 2 idiv dup dict begin {def} repeat pop currentdict end) } ifelse cvx def _level2PS{ initializeLev2 }{ initializeLev1 }ifelse queryDevice initializeShading initializeOps _producingSeps{ AGM_Gradient_Sep/initialize get exec }{ initializeComposite }ifelse _illustrator{ /f{}def /F{}def /s{}def /S{}def /b{}def /B{}def }if /image where{ /image get /_image xd }if /colorimage where{ /colorimage get /_colorimage xd }if /rectfill where dup{ exch pop not _producingSeps or }{ not }ifelse { /rectfill{ gsave newpath 4 2 roll moveto 1 index 0 rlineto 0 1 index rlineto 1 index neg 0 rlineto pop pop closepath fill grestore }def }if /linealImage _noImage{ /rectImage load }{ _producingSeps{ AGM_Gradient_Sep/AGM_Gradient_Sep_private get begin /rampImage load end }{ /rampImage load }ifelse }ifelse def AGM_Gradient_private { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall AGM_Gradient { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall end currentdict readonly pop end }def /initializeAI { pop pop AGM_Gradient/AGM_Gradient_private get /_illustrator true put AGM_Gradient/initialize get exec AGM_Gradient begin }def /unload{ systemdict/languagelevel known{ systemdict/languagelevel get 2 ge{ userdict/AGM_Gradient_Sep 2 copy known{ undef }{ pop pop }ifelse userdict/AGM_Gradient 2 copy known{ undef }{ pop pop }ifelse }if }if }def /terminate{ currentdict AGM_Gradient eq{ end }if }def AGM_Gradient_private begin /initializeVars{ /_d255 256 array def 0 1 255{ _d255 exch dup 255 div put }bind for /_d255- 256 array def 0 1 255{ _d255- exch 1 _d255 2 index get sub put }bind for /_sSave nd /_dUserSpace matrix defaultmatrix def /_bUMatrix matrix def /_imageMatrix matrix def /_saveMatrix matrix def /_xm matrix def /_ccAry1 5 array def /_level2PS systemdict/languagelevel known dup{ pop systemdict/languagelevel get 2 ge }if def /_level3PS _level2PS systemdict/shfill known and def currentdict /_illustrator known not{ /_illustrator false def }if }def /initializeOps { AGM_Gradient begin currentdict/Bc known not{ /Bc{ _renderFlag 2 eq{ 6 npop }{ pushBSpace _rampIndex 0 eq{ pop pop setCStop }if linealFill popBSpace }ifelse }def }if currentdict/Bg known not{ /Bg{ 10 npop /_gradName xp /_renderFlag xp _renderFlag 2 ne{ _illustrator{ _of setoverprint }if _illustrator _eo and _renderFlag 3 eq or{ eoclip }{ clip }ifelse _gradNames _gradName 2 copy known{ get mark exch aload pop /_gradType xp 1 sub dup /_rampIndex xp /_maxRampIndex xp mark exch aload pop 0 0 }if pop pop getRampData }{ mark mark }ifelse }def }if currentdict/Bm known not{ /Bm{ _renderFlag 2 ne{ _gradType 0 eq{ linealRamp }{ radialGrad }ifelse }{ 6 npop }ifelse }def }if currentdict/Bh known not{ /Bh{ 2 npop /_yHi xp /_xHi xp /_radHilite _xHi 0 ne _yHi 0 ne or pt }def }if currentdict/Bn known not{ /Bn{ AGM_Gradient_private begin dict /_gradNames xp end }def }if currentdict/Bd known not{ /Bd{ AGM_Gradient begin AGM_Gradient_private begin /_nColorsBd xp /_gradType xp /_gradName xp }def }if currentdict/BD known not{ /BD{ currentdict/_gradNames known not{ /_gradNames 20 dict def }if ] _nColorsBd _gradType ] _gradName exch /_gradNames xput end end }def }if currentdict/Bb known not{ /Bb{ AGM_Gradient begin AGM_Gradient_private begin _producingSeps{ AGM_Gradient_Sep/AGM_Gradient_Sep_private get begin }if mySave }def }if currentdict/BB known not{ /BB{ /_tmp xp cleartomark cleartomark _tmp dup _renderFlag myRestore _producingSeps{ end }if _illustrator end end { 2 ne exch 0 gt and{ 2 eq{ s }{ S }ifelse }{ pop newpath }ifelse }{ pop newpath }ifelse }def }if currentdict/Xm known not{ /Xm{ _xm astore pop }def }if end }def /queryDevice{ /_inRipSep _level2PS{ currentpagedevice/Separations 2 copy known{ get }{ pop pop false }ifelse }{ false }ifelse def /_noImage /lv1Fix where{ pop lv1Fix }{ false }ifelse def /_useShells where{ pop }{ /_useShells true def }ifelse /_useSmoothShade where{ pop }{ /_useSmoothShade false def }ifelse /_cyanPlate 1 0 0 0 testCMYKColorThrough def /_magentaPlate 0 1 0 0 testCMYKColorThrough def /_yellowPlate 0 0 1 0 testCMYKColorThrough def /_blackPlate 0 0 0 1 testCMYKColorThrough def /_compositeJob _cyanPlate _magentaPlate and _yellowPlate and _blackPlate and def /_compositeSpotDevice where{ pop }{ /_compositeSpotDevice _compositeJob not _inRipSep or{ 1 }{ 0 }ifelse def }ifelse /_producingSeps _compositeSpotDevice 0 ne def /_deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt def /_dpiThreshold where{ pop }{ /_dpiThreshold 600 def }ifelse /_screenFreqThreshold where{ pop }{ /_screenFreqThreshold 150 def }ifelse /_contoneDevice where{ pop }{ /_contoneDevice false def }ifelse /_subSampleOK _deviceDPI _dpiThreshold le currentScreenFreq _screenFreqThreshold le and _contoneDevice not and _producingSeps not and def }def /initializeLev1{ /makeByte8{ /_tmp 0 pt 255 mul cvi 8 string 8{ dup _tmp 3 index put /_tmp _tmp 1 add pt }repeat exch pop }def /currentScreenFreq{ currentscreen pop pop }def /_byte 1 string def /colorimage where{ pop }{ /colorimage{ pop pop /_blackTmp xp /_yellowTmp xp /_magentaTmp xp /_cyanTmp xp /_cnt 0 pt [ _byte dup 0 _cyanTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .3 /mul cvx _magentaTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .59 /mul cvx _yellowTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .11 /mul cvx _blackTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx /add cvx /add cvx /add cvx 1 /exch cvx /sub cvx /dup cvx 0 /lt cvx{ pop 0 }/if cvx /dup cvx 1 /gt cvx{ pop 1 }/if cvx 255 /mul cvx /cvi cvx 256 /mod cvx /dup cvx 0 /lt cvx{ pop 0 }/if cvx /put cvx /_cnt dup cvx 1 /add cvx /pt cvx ] cvx bind /_image load 5 execImage }def }ifelse }def /initializeLev2{ /level2ScreenFreq{ begin 60 HalftoneType 1 eq{ pop Frequency }if HalftoneType 2 eq{ pop GrayFrequency }if HalftoneType 5 eq{ pop Default level2ScreenFreq }if end }def /currentScreenFreq{ currenthalftone level2ScreenFreq }def }def /initializeShading{ _useSmoothShade _level3PS and{ /_usingSmoothShade true pt initializeLev3_Ops }{ /_usingSmoothShade false pt }ifelse }def /initializeLev3_Ops { /initShFill{ /_index _gradType 0 eq {0}{_maxRampIndex 1 sub} ifelse pt /_rampFuncsArray _maxRampIndex array pt /_boundsArray _maxRampIndex 1 sub array pt /_encodeArray _maxRampIndex 2 mul array pt /_beginCoord _rampPoint pt /_colorSpace null pt /_firstFill _rampIndex _maxRampIndex eq pt /_lastFill false pt }def /getRampColorSpace{ _nSamples 1 gt{ /_ndx 0 pt [blendColor] cvx exec }if /_C0 [currentcolor] pt /_C0_Space currentcolorspace pt _nSamples 1 gt{ /_ndx _nSamples 1 sub pt [blendColor] cvx exec }if /_C1 [currentcolor] pt /_C1_Space currentcolorspace pt _C0_Space _C1_Space eq{ /_rampColorSpace _C0_Space pt }{ (colorspace conflict!) == showpage stop }ifelse _spotColor{ nsetcustomcolorend }if }def /linealShFill{ popBSpace _xm aload pop pushBSpace /_size _index 1 add pt _size _maxRampIndex lt { /_rampFuncsArray _rampFuncsArray 0 _size getinterval pt /_boundsArray _boundsArray 0 _size 1 sub getinterval pt /_encodeArray _encodeArray 0 _size 2 mul getinterval pt }if bd /ShadingType 2 /ColorSpace _colorSpace /Function bd /FunctionType 3 /Domain [0 1] /Functions _rampFuncsArray /Bounds _boundsArray /Encode _encodeArray ed /Extend [_firstFill _lastFill] /Domain [0 1] /Coords [_beginCoord 0 _endCoord 0] ed shfill }def /radialShFill{ /_size _maxRampIndex _index sub pt _size _maxRampIndex lt { /_rampFuncsArray _rampFuncsArray _index _size getinterval pt /_boundsArray _boundsArray _index _size 1 sub getinterval pt /_encodeArray _encodeArray _index 2 mul _size 2 mul getinterval pt }if /_rampLen _beginCoord _endCoord sub pt bd /ShadingType 3 /ColorSpace _colorSpace /Function bd /FunctionType 3 /Domain [0 1] /Functions _rampFuncsArray /Bounds _boundsArray /Encode _encodeArray ed /Extend [_lastFill _firstFill] /Domain [0 1] /Coords [_xHi _rampLen mul _yHi _rampLen mul _endCoord 0 0 _beginCoord] ed shfill _radHilite{ _xHi _rampLen mul _yHi _rampLen mul translate }if }def /fillRamp{ /_invert _midPoint 0.5 lt pt _rampIndex _maxRampIndex eq { initShFill }if getRampColorSpace _colorSpace null eq{ /_colorSpace _rampColorSpace pt }{ _colorSpace _rampColorSpace ne{ /_index _index 1 _gradType 0 eq{ sub pt linealShFill }{ add pt radialShFill }ifelse initShFill /_colorSpace _rampColorSpace pt } if }ifelse /_endCoord _endPoint pt _rampFuncsArray _index bd /FunctionType 2 /Domain [0 1] /N 0.5 log _invert{1 _midPoint sub}{_midPoint}ifelse log div _gradType 0 eq{ _invert{/C1}{/C0}ifelse _C0 _invert{/C0}{/C1}ifelse _C1 }{ _invert{/C0}{/C1}ifelse _C1 _invert{/C1}{/C0}ifelse _C0 }ifelse ed put _rampIndex 1 ne{ _boundsArray _index _gradType 1 eq{1 sub}if _endCoord put } if 0 1 _invert {exch}if _encodeArray _index 2 mul 1 add 3 -1 roll put _encodeArray _index 2 mul 3 -1 roll put _rampIndex 1 eq { /_lastFill true pt _gradType 0 eq{ linealShFill }{ radialShFill }ifelse }if /_index _index 1 _gradType 0 eq{ add pt }{ sub pt }ifelse }def /radialRamp /fillRamp load def /rampImage /fillRamp load def AGM_Gradient begin /Bc{ 6 npop }def end }def /initializeComposite{ /bwImage{ pop /_image load 5 execImage }def currentdict/rampImage known not{ /rampImage{ _color{ _nSamples setImageParms _rgbRamp{ _redData _greenData _blueData _nSamples 3 expandColor true 3 null ncolorimage }{ _cyanData _magentaData _yellowData _blackData _nSamples 4 expandColor true 4 null ncolorimage }ifelse }{ _nSamples setImageParms _blackData null bwImage }ifelse }def }if /setCStop{ /_colorStyle exch pt _colorStyle 0 eq{ 1 exch sub 0 0 0 4 -1 roll }if _colorStyle 2 eq{ setrgbcolor 4 npop }if _colorStyle 3 eq{ 1 exch sub /_tmp xp pop 4{ _tmp mul 4 1 roll }repeat }if _colorStyle 4 eq{ 3 -1 roll pop pop 1 exch sub /_tmp xp 3{ 1 exch sub _tmp mul 1 exch sub 3 1 roll }repeat setrgbcolor 4 npop }if _colorStyle 2 ne _colorStyle 4 ne and{ null nsetcustomcolor }if }def /nsetcustomcolor { pop setcmykcolor }def /nsetcustomcolorend { }def /ncolorimage{ pop /_colorimage load 10 execImage }def _noImage not _level2PS not and{ /linealFill{ 8 setImageParms _color{ currentcmykcolor 4{ makeByte8 4 1 roll }repeat true 4 null ncolorimage }{ currentgray makeByte8 null bwImage }ifelse }def }if }def /npop{ {pop}repeat }def /xd{ exch def }def /nd{ null def }def /pt{ AGM_Gradient_private 3 1 roll put }def /xp{ exch pt }def /xput{ dup load dup length exch maxlength eq{ dup dup load dup length 2 mul dict copy def }if load begin def end }def /mySave{ save /_sSave xp }def /myRestore{ _sSave type /savetype eq{ _sSave restore }if }def /gMark{ counttomark 2 add -1 roll }def /execImage{ /_tmp xp { exec }stopped{ $error /errorname get /undefinedresult ne{ stop }{ _tmp npop }ifelse }if }def /pushBSpace{ newpath gsave _bUMatrix astore concat }def /popBSpace{ grestore }def /setImageParms{ 1 8 2 index 0 0 1 0 0 _imageMatrix astore }def /linealFill{ 0 0 1 1 rectfill }def /testCMYKColorThrough{ gsave setcmykcolor currentcmykcolor grestore add add add 0 ne }def /expandOne { /_tmp xp dup type /stringtype ne{ _tmp string exch dup 0 ne{ 255 mul cvi 0 1 _tmp 1 sub{ 3 copy exch put pop }for }if pop }if }def /expandColor{ /_channels xp /_len xp _channels{ _len expandOne _channels 1 roll }repeat }def /blendColor{ _color{ _rgbRamp _producingSeps not and{ _redData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _greenData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _blueData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if /setrgbcolor cvx }{ _cyanData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _magentaData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _yellowData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _blackData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _spotColor{ _rampSD begin /_rampSD cvx /begin cvx spot1 begin tintImage dup type /stringtype eq{ /_ndx cvx /get cvx _d255- /exch cvx /get cvx }{ dup null ne{ name type /nametype ne{ 1 exch sub }if }if }ifelse end /spot1 cvx /tintValue 3 -1 /roll cvx /put cvx spot2 begin tintImage dup type /stringtype eq{ /_ndx cvx /get cvx _d255- /exch cvx /get cvx }{ dup null ne{ name type /nametype ne{ 1 exch sub }if }if }ifelse end /spot2 cvx /tintValue 3 -1 /roll cvx /put cvx /end cvx end /_rampSD cvx /nsetcustomcolor cvx }{ /setcmykcolor cvx }ifelse }ifelse }{ _blackData /_ndx cvx /get cvx _d255 /exch cvx /get cvx _usingSmoothShade{ 1 /exch cvx /sub cvx 0 0 0 4 -1 /roll cvx /setcmykcolor cvx }{ /setgray cvx }ifelse }ifelse }def /linealRamp{ pushBSpace _ramp{ linealImage }{ linealFill }ifelse popBSpace /_rampIndex _rampIndex 1 sub pt _rampIndex 0 gt{ getRampData }if }def /radialGrad{ /_firstShell true pt _usingSmoothShade not{ fill }if pushBSpace _radHilite{ _xHi _yHi _bUMatrix idtransform /_yHi xp /_xHi xp _rampPoint 1 lt{ 1 _rampPoint sub dup _xHi mul exch _yHi mul translate }if }if _rampIndex{ radialRamp /_rampIndex _rampIndex 1 sub pt _rampIndex 0 gt{ getRampData }if }repeat popBSpace }def /getNSamples{ 0 exch { dup type /stringtype eq{ length exch pop exit }if pop }forall dup 0 eq{ pop 1 }if }def /getRampData{ /_rampType gMark pt /_color _rampType 0 gt pt /_ccRGB _rampType 5 eq _rampType 6 eq or pt /_rgbRamp _rampType 4 eq _ccRGB or pt /_ccProcess _rampType 2 eq _rampType 3 eq or pt _producingSeps{ _rampSD initSpotDict /_spotColor _ccProcess _ccRGB or pt }{ /_spotColor false pt }ifelse /_ramp true pt 100 div /_rampPoint xp 100 div /_midPoint xp dup /_colorStyle xp _colorStyle 0 eq{ 2 }{ _colorStyle 1 eq{ 5 }{ _colorStyle 2 eq{ 8 }{ _colorStyle 3 eq{ _producingSeps{ _rampSD begin spot1 begin /name 3 index def /spot_K 4 index def /spot_Y 5 index def /spot_M 6 index def /spot_C 7 index def end end }if 7 }{ _producingSeps{ _rampSD begin spot1 begin /name 4 index def /spot_K 8 index def /spot_Y 9 index def /spot_M 10 index def /spot_C 11 index def end end }if 11 } ifelse }ifelse }ifelse }ifelse /_tmp xp _tmp index 100 div /_endPoint xp _gradType 1 eq{ _tmp 1 add index 100 div /_midPoint xp }if _producingSeps{ _tmp 2 add index /_nextColorStyle xp _nextColorStyle 3 eq{ /_tmp _tmp 4 add pt _tmp index dup _rampSD begin spot1 /name get ne{ spot2 begin /name xd /spot_K _tmp 2 add index def /spot_Y _tmp 3 add index def /spot_M _tmp 4 add index def /spot_C _tmp 5 add index def end }{ pop }ifelse end }if _nextColorStyle 4 eq{ /_tmp _tmp 5 add pt _tmp index dup _rampSD begin spot1 /name get ne{ spot2 begin /name xd /spot_K _tmp 5 add index def /spot_Y _tmp 6 add index def /spot_M _tmp 7 add index def /spot_C _tmp 8 add index def end }{ pop }ifelse end }if }if _rampType 3 eq _rampType 6 eq or{ /_tint2Data gMark pt }if _ccProcess _ccRGB or{ /_tint1Data gMark pt }if _rgbRamp{ /_blueData gMark pt /_greenData gMark pt /_redData gMark pt }if _producingSeps{ _rampSD begin _ccProcess _ccRGB or{ _rampType 3 eq _rampType 6 eq or{ spot2 begin /tintImage _gradType 0 eq{ _tint2Data }{ _tint1Data }ifelse def name null eq{ /name /Black def }if end }if spot1 begin /tintImage _gradType 0 eq _rampType 2 eq or _rampType 5 eq or{ _tint1Data }{ _tint2Data }ifelse def _rampType 2 eq _rampType 5 eq or{ name null eq{ /name spot2 /name get def spot2 /name null put }if }{ name null eq{ /name /Black def }if }ifelse end }if end }if /_blackData gMark pt _rampType 0 gt{ counttomark 4 add -3 roll /_yellowData xp /_magentaData xp /_cyanData xp }if _ramp{ /_nSamples [ _rampType 0 eq {_blackData}if _rampType 1 eq {_cyanData _magentaData _yellowData _blackData}if _rampType 2 eq {_cyanData _magentaData _yellowData _blackData _tint1Data}if _rampType 3 eq {_cyanData _magentaData _yellowData _blackData _tint1Data _tint2Data}if _rampType 4 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData}if _rampType 5 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData _tint1Data}if _rampType 6 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData _tint1Data _tint2Data}if ] getNSamples pt _usingSmoothShade not {/_ramp _nSamples 1 gt pt} if } if setCStop }def /rectImage{ gsave /_sInc 1 pt /_bInc 1 _nSamples div pt /_uRampLen 1 0 dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt pt /_pChange _uRampLen 0 eq{0}{_nSamples _uRampLen div}ifelse pt 0 _nSamples [ /dup cvx /_ndx /exch cvx /pt cvx blendColor 0 0 _bInc 1 /rectfill cvx _bInc 0 /translate cvx _sInc /add cvx ] cvx bind repeat pop _spotColor{ nsetcustomcolorend }if grestore }def /radialInit{ /_nRadSamples _nSamples dup 0 eq{pop 1}if pt /_sInc -1 pt /_rampLen _rampPoint _endPoint sub pt /_bInc _rampLen _nSamples div neg pt /_optimize false pt _subSampleOK{ /_uRampLen _rampLen 0 dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt 0 _rampLen dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt 2 copy lt{ exch }if pop pt /_pChange _uRampLen 0 eq{ 0 }{ _nSamples _uRampLen div }ifelse pt _pChange .5 gt dup /_optimize xp{ /_nRadSamples _uRampLen 2 div round cvi dup 1 le{pop 2}if pt /_bInc _rampLen _nRadSamples div neg pt /_sInc _nSamples 1 sub _nRadSamples 1 sub div neg pt }if }if _radHilite{ /_xBCInc _xHi _rampLen mul _nRadSamples div pt /_yBCInc _yHi _rampLen mul _nRadSamples div pt }if }def currentdict/radialRamp known not{ /radialRamp{ /_saveMatrix _saveMatrix currentmatrix def radialInit _rampPoint _nSamples 1 sub _nRadSamples [ /dup cvx _optimize{ /round cvx /cvi cvx }if /_ndx /exch cvx /pt cvx _useShells{ /_firstShell cvx{ /_firstShell false pt }{ 0 0 3 index 360 0 arcn fill }/ifelse cvx }if blendColor _useShells{ 0 0 3 /index cvx 0 360 /arc cvx }{ 0 0 3 /index cvx 0 360 /arc cvx /fill cvx }ifelse /exch cvx _bInc /add cvx /exch cvx _sInc /add cvx _radHilite{ _xBCInc _yBCInc /translate cvx }if ] cvx bind repeat pop pop _saveMatrix setmatrix _radHilite{ _xHi _rampLen mul _yHi _rampLen mul translate }if _useShells _rampIndex 1 eq and{ fill }if _spotColor{ nsetcustomcolorend }if }def }if end end defaultpacking setpacking %%EndResource %%BeginProcSet: Adobe_ColorImage_AI6 1.1 0 userdict /Adobe_ColorImage_AI6 known not { userdict /Adobe_ColorImage_AI6 24 dict put } if userdict /Adobe_ColorImage_AI6 get begin /initialize { Adobe_ColorImage_AI6 begin Adobe_ColorImage_AI6 { dup type /arraytype eq { dup xcheck { bind } if } if pop pop } forall } def /terminate { end } def currentdict /Adobe_ColorImage_AI6_Vars known not { /Adobe_ColorImage_AI6_Vars 15 dict def } if Adobe_ColorImage_AI6_Vars begin /channelcount 0 def /sourcecount 0 def /sourcearray 4 array def /plateindex -1 def /XIMask 0 def /XIBinary 0 def /XIChannelCount 0 def /XIBitsPerPixel 0 def /XIImageHeight 0 def /XIImageWidth 0 def /XIImageMatrix null def /XIBuffer null def /XIDataProc null def /XIVersion 6 def end /WalkRGBString null def /WalkCMYKString null def /StuffRGBIntoGrayString null def /RGBToGrayImageProc null def /StuffCMYKIntoGrayString null def /CMYKToGrayImageProc null def /ColorImageCompositeEmulator null def /SeparateCMYKImageProc null def /FourEqual null def /TestPlateIndex null def currentdict /_colorimage known not { /colorimage where { /colorimage get /_colorimage exch def } { /_colorimage null def } ifelse } if /_currenttransfer systemdict /currenttransfer get def /colorimage null def /XI null def /WalkRGBString { 0 3 index dup length 1 sub 0 3 3 -1 roll { 3 getinterval { } forall 5 index exec 3 index } for 5 { pop } repeat } def /WalkCMYKString { 0 3 index dup length 1 sub 0 4 3 -1 roll { 4 getinterval { } forall 6 index exec 3 index } for 5 { pop } repeat } def /StuffRGBIntoGrayString { .11 mul exch .59 mul add exch .3 mul add cvi 3 copy put pop 1 add } def /RGBToGrayImageProc { Adobe_ColorImage_AI6_Vars begin sourcearray 0 get exec dup length 3 idiv string dup 3 1 roll /StuffRGBIntoGrayString load exch WalkRGBString end } def /StuffCMYKIntoGrayString { exch .11 mul add exch .59 mul add exch .3 mul add dup 255 gt { pop 255 } if 255 exch sub cvi 3 copy put pop 1 add } def /CMYKToGrayImageProc { Adobe_ColorImage_AI6_Vars begin sourcearray 0 get exec dup length 4 idiv string dup 3 1 roll /StuffCMYKIntoGrayString load exch WalkCMYKString end } def /ColorImageCompositeEmulator { pop true eq { Adobe_ColorImage_AI6_Vars /sourcecount get 5 add { pop } repeat } { Adobe_ColorImage_AI6_Vars /channelcount get 1 ne { Adobe_ColorImage_AI6_Vars begin sourcearray 0 3 -1 roll put channelcount 3 eq { /RGBToGrayImageProc } { /CMYKToGrayImageProc } ifelse load end } if image } ifelse } def /SeparateCMYKImageProc { Adobe_ColorImage_AI6_Vars begin sourcecount 0 ne { sourcearray plateindex get exec } { sourcearray 0 get exec dup length 4 idiv string 0 2 index plateindex 4 2 index length 1 sub { get 255 exch sub 3 copy put pop 1 add 2 index } for pop pop exch pop } ifelse end } def /FourEqual { 4 index ne { pop pop pop false } { 4 index ne { pop pop false } { 4 index ne { pop false } { 4 index eq } ifelse } ifelse } ifelse } def /TestPlateIndex { Adobe_ColorImage_AI6_Vars begin /plateindex -1 def /setcmykcolor where { pop gsave 1 0 0 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 1 0 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 0 1 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 0 0 1 setcmykcolor systemdict /currentgray get exec 1 exch sub grestore 1 0 0 0 FourEqual { /plateindex 0 def } { 0 1 0 0 FourEqual { /plateindex 1 def } { 0 0 1 0 FourEqual { /plateindex 2 def } { 0 0 0 1 FourEqual { /plateindex 3 def } { 0 0 0 0 FourEqual { /plateindex 5 def } if } ifelse } ifelse } ifelse } ifelse pop pop pop pop } if plateindex end } def /colorimage { Adobe_ColorImage_AI6_Vars begin /channelcount 1 index def /sourcecount 2 index 1 eq { channelcount 1 sub } { 0 } ifelse def 4 sourcecount add index dup 8 eq exch 1 eq or not end { /_colorimage load null ne { _colorimage } { Adobe_ColorImage_AI6_Vars /sourcecount get 7 add { pop } repeat } ifelse } { dup 3 eq TestPlateIndex dup -1 eq exch 5 eq or or { /_colorimage load null eq { ColorImageCompositeEmulator } { dup 1 eq { pop pop image } { Adobe_ColorImage_AI6_Vars /plateindex get 5 eq { gsave 0 _currenttransfer exec 1 _currenttransfer exec eq { 0 _currenttransfer exec 0.5 lt } { 0 _currenttransfer exec 1 _currenttransfer exec gt } ifelse { { pop 0 } } { { pop 1 } } ifelse systemdict /settransfer get exec } if _colorimage Adobe_ColorImage_AI6_Vars /plateindex get 5 eq { grestore } if } ifelse } ifelse } { dup 1 eq { pop pop image } { pop pop Adobe_ColorImage_AI6_Vars begin sourcecount -1 0 { exch sourcearray 3 1 roll put } for /SeparateCMYKImageProc load end systemdict /image get exec } ifelse } ifelse } ifelse } def /XG { pop pop } def /XF { 13 {pop} repeat } def /Xh { Adobe_ColorImage_AI6_Vars begin gsave /XIMask exch 0 ne def /XIImageHeight exch def /XIImageWidth exch def /XIImageMatrix exch def 0 0 moveto XIImageMatrix concat XIImageWidth XIImageHeight scale XIMask { /_lp /null ddef _fc /_lp /imagemask ddef } if /XIVersion 7 def end } def /XH { Adobe_ColorImage_AI6_Vars begin /XIVersion 6 def grestore end } def /XI { Adobe_ColorImage_AI6_Vars begin gsave /XIMask exch 0 ne def /XIBinary exch 0 ne def pop pop /XIChannelCount exch def /XIBitsPerPixel exch def /XIImageHeight exch def /XIImageWidth exch def pop pop pop pop /XIImageMatrix exch def XIBitsPerPixel 1 eq { XIImageWidth 8 div ceiling cvi } { XIImageWidth XIChannelCount mul } ifelse /XIBuffer exch string def XIBinary { /XIDataProc { currentfile XIBuffer readstring pop } def XIVersion 6 le { currentfile 128 string readline pop pop } if } { /XIDataProc { currentfile XIBuffer readhexstring pop } def } ifelse XIVersion 6 le { 0 0 moveto XIImageMatrix concat XIImageWidth XIImageHeight scale XIMask { /_lp /null ddef _fc /_lp /imagemask ddef } if } if XIMask { XIImageWidth XIImageHeight false [ XIImageWidth 0 0 XIImageHeight neg 0 0 ] /XIDataProc load imagemask } { XIImageWidth XIImageHeight XIBitsPerPixel [ XIImageWidth 0 0 XIImageHeight neg 0 0 ] /XIDataProc load XIChannelCount 1 eq { gsave 0 setgray image grestore } { false XIChannelCount colorimage } ifelse } ifelse grestore end } def end %%EndProcSet %%BeginResource: procset Adobe_Illustrator_AI5 1.1 0 %%Title: (Adobe Illustrator (R) Version 5.0 Full Prolog) %%Version: 1.1 0 %%CreationDate: (3/7/1994) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_Illustrator_AI5_vars 81 dict dup begin put /_eo false def /_lp /none def /_pf { } def /_ps { } def /_psf { } def /_pss { } def /_pjsf { } def /_pjss { } def /_pola 0 def /_doClip 0 def /cf currentflat def /_tm matrix def /_renderStart [ /e0 /r0 /a0 /o0 /e1 /r1 /a1 /i0 ] def /_renderEnd [ null null null null /i1 /i1 /i1 /i1 ] def /_render -1 def /_rise 0 def /_ax 0 def /_ay 0 def /_cx 0 def /_cy 0 def /_leading [ 0 0 ] def /_ctm matrix def /_mtx matrix def /_sp 16#020 def /_hyphen (-) def /_fScl 0 def /_cnt 0 def /_hs 1 def /_nativeEncoding 0 def /_useNativeEncoding 0 def /_tempEncode 0 def /_pntr 0 def /_tDict 2 dict def /_wv 0 def /Tx { } def /Tj { } def /CRender { } def /_AI3_savepage { } def /_gf null def /_cf 4 array def /_if null def /_of false def /_fc { } def /_gs null def /_cs 4 array def /_is null def /_os false def /_sc { } def /_pd 1 dict def /_ed 15 dict def /_pm matrix def /_fm null def /_fd null def /_fdd null def /_sm null def /_sd null def /_sdd null def /_i null def /discardSave null def /buffer 256 string def /beginString null def /endString null def /endStringLength null def /layerCnt 1 def /layerCount 1 def /perCent (%) 0 get def /perCentSeen? false def /newBuff null def /newBuffButFirst null def /newBuffLast null def /clipForward? false def end userdict /Adobe_Illustrator_AI5 known not { userdict /Adobe_Illustrator_AI5 91 dict put } if userdict /Adobe_Illustrator_AI5 get begin /initialize { Adobe_Illustrator_AI5 dup begin Adobe_Illustrator_AI5_vars begin discardDict { bind pop pop } forall dup /nc get begin { dup xcheck 1 index type /operatortype ne and { bind } if pop pop } forall end newpath } def /terminate { end end } def /_ null def /ddef { Adobe_Illustrator_AI5_vars 3 1 roll put } def /xput { dup load dup length exch maxlength eq { dup dup load dup length 2 mul dict copy def } if load begin def end } def /npop { { pop } repeat } def /sw { dup length exch stringwidth exch 5 -1 roll 3 index mul add 4 1 roll 3 1 roll mul add } def /swj { dup 4 1 roll dup length exch stringwidth exch 5 -1 roll 3 index mul add 4 1 roll 3 1 roll mul add 6 2 roll /_cnt 0 ddef { 1 index eq { /_cnt _cnt 1 add ddef } if } forall pop exch _cnt mul exch _cnt mul 2 index add 4 1 roll 2 index add 4 1 roll pop pop } def /ss { 4 1 roll { 2 npop (0) exch 2 copy 0 exch put pop gsave false charpath currentpoint 4 index setmatrix stroke grestore moveto 2 copy rmoveto } exch cshow 3 npop } def /jss { 4 1 roll { 2 npop (0) exch 2 copy 0 exch put gsave _sp eq { exch 6 index 6 index 6 index 5 -1 roll widthshow currentpoint } { false charpath currentpoint 4 index setmatrix stroke } ifelse grestore moveto 2 copy rmoveto } exch cshow 6 npop } def /sp { { 2 npop (0) exch 2 copy 0 exch put pop false charpath 2 copy rmoveto } exch cshow 2 npop } def /jsp { { 2 npop (0) exch 2 copy 0 exch put _sp eq { exch 5 index 5 index 5 index 5 -1 roll widthshow } { false charpath } ifelse 2 copy rmoveto } exch cshow 5 npop } def /pl { transform 0.25 sub round 0.25 add exch 0.25 sub round 0.25 add exch itransform } def /setstrokeadjust where { pop true setstrokeadjust /c { curveto } def /C /c load def /v { currentpoint 6 2 roll curveto } def /V /v load def /y { 2 copy curveto } def /Y /y load def /l { lineto } def /L /l load def /m { moveto } def } { /c { pl curveto } def /C /c load def /v { currentpoint 6 2 roll pl curveto } def /V /v load def /y { pl 2 copy curveto } def /Y /y load def /l { pl lineto } def /L /l load def /m { pl moveto } def } ifelse /d { setdash } def /cf { } def /i { dup 0 eq { pop cf } if setflat } def /j { setlinejoin } def /J { setlinecap } def /M { setmiterlimit } def /w { setlinewidth } def /XR { 0 ne /_eo exch ddef } def /H { } def /h { closepath } def /N { _pola 0 eq { _doClip 1 eq { _eo {eoclip} {clip} ifelse /_doClip 0 ddef } if newpath } { /CRender { N } ddef } ifelse } def /n { N } def /F { _pola 0 eq { _doClip 1 eq { gsave _pf grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _fc /_doClip 0 ddef } { _pf } ifelse } { /CRender { F } ddef } ifelse } def /f { closepath F } def /S { _pola 0 eq { _doClip 1 eq { gsave _ps grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _sc /_doClip 0 ddef } { _ps } ifelse } { /CRender { S } ddef } ifelse } def /s { closepath S } def /B { _pola 0 eq { _doClip 1 eq gsave F grestore { gsave S grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _sc /_doClip 0 ddef } { S } ifelse } { /CRender { B } ddef } ifelse } def /b { closepath B } def /W { /_doClip 1 ddef } def /* { count 0 ne { dup type /stringtype eq { pop } if } if newpath } def /u { } def /U { } def /q { _pola 0 eq { gsave } if } def /Q { _pola 0 eq { grestore } if } def /*u { _pola 1 add /_pola exch ddef } def /*U { _pola 1 sub /_pola exch ddef _pola 0 eq { CRender } if } def /D { pop } def /*w { } def /*W { } def /` { /_i save ddef clipForward? { nulldevice } if 6 1 roll 4 npop concat pop userdict begin /showpage { } def 0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit [] 0 setdash /setstrokeadjust where {pop false setstrokeadjust} if newpath 0 setgray false setoverprint } def /~ { end _i restore } def /O { 0 ne /_of exch ddef /_lp /none ddef } def /R { 0 ne /_os exch ddef /_lp /none ddef } def /g { /_gf exch ddef /_fc { _lp /fill ne { _of setoverprint _gf setgray /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /G { /_gs exch ddef /_sc { _lp /stroke ne { _os setoverprint _gs setgray /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /k { _cf astore pop /_fc { _lp /fill ne { _of setoverprint _cf aload pop setcmykcolor /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /K { _cs astore pop /_sc { _lp /stroke ne { _os setoverprint _cs aload pop setcmykcolor /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /x { /_gf exch ddef findcmykcustomcolor /_if exch ddef /_fc { _lp /fill ne { _of setoverprint _if _gf 1 exch sub setcustomcolor /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /X { /_gs exch ddef findcmykcustomcolor /_is exch ddef /_sc { _lp /stroke ne { _os setoverprint _is _gs 1 exch sub setcustomcolor /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /A { pop } def /annotatepage { userdict /annotatepage 2 copy known {get exec} {pop pop} ifelse } def /XT { pop pop } def /discard { save /discardSave exch store discardDict begin /endString exch store gt38? { 2 add } if load stopped pop end discardSave restore } bind def userdict /discardDict 7 dict dup begin put /pre38Initialize { /endStringLength endString length store /newBuff buffer 0 endStringLength getinterval store /newBuffButFirst newBuff 1 endStringLength 1 sub getinterval store /newBuffLast newBuff endStringLength 1 sub 1 getinterval store } def /shiftBuffer { newBuff 0 newBuffButFirst putinterval newBuffLast 0 currentfile read not { stop } if put } def 0 { pre38Initialize mark currentfile newBuff readstring exch pop { { newBuff endString eq { cleartomark stop } if shiftBuffer } loop } { stop } ifelse } def 1 { pre38Initialize /beginString exch store mark currentfile newBuff readstring exch pop { { newBuff beginString eq { /layerCount dup load 1 add store } { newBuff endString eq { /layerCount dup load 1 sub store layerCount 0 eq { cleartomark stop } if } if } ifelse shiftBuffer } loop } if } def 2 { mark { currentfile buffer readline not { stop } if endString eq { cleartomark stop } if } loop } def 3 { /beginString exch store /layerCnt 1 store mark { currentfile buffer readline not { stop } if dup beginString eq { pop /layerCnt dup load 1 add store } { endString eq { layerCnt 1 eq { cleartomark stop } { /layerCnt dup load 1 sub store } ifelse } if } ifelse } loop } def end userdict /clipRenderOff 15 dict dup begin put { /n /N /s /S /f /F /b /B } { { _doClip 1 eq { /_doClip 0 ddef _eo {eoclip} {clip} ifelse } if newpath } def } forall /Tr /pop load def /Bb {} def /BB /pop load def /Bg {12 npop} def /Bm {6 npop} def /Bc /Bm load def /Bh {4 npop} def end /Lb { 4 npop 6 1 roll pop 4 1 roll pop pop pop 0 eq { 0 eq { (%AI5_BeginLayer) 1 (%AI5_EndLayer--) discard } { /clipForward? true def /Tx /pop load def /Tj /pop load def currentdict end clipRenderOff begin begin } ifelse } { 0 eq { save /discardSave exch store } if } ifelse } bind def /LB { discardSave dup null ne { restore } { pop clipForward? { currentdict end end begin /clipForward? false ddef } if } ifelse } bind def /Pb { pop pop 0 (%AI5_EndPalette) discard } bind def /Np { 0 (%AI5_End_NonPrinting--) discard } bind def /Ln /pop load def /Ap /pop load def /Ar { 72 exch div 0 dtransform dup mul exch dup mul add sqrt dup 1 lt { pop 1 } if setflat } def /Mb { q } def /Md { } def /MB { Q } def /nc 3 dict def nc begin /setgray { pop } bind def /setcmykcolor { 4 npop } bind def /setcustomcolor { 2 npop } bind def currentdict readonly pop end end setpacking %%EndResource %%BeginResource: procset Adobe_blend_AI5 1.4 0 %%Title: (Adobe Illustrator (R) Version 5.0 Blend ProcSet) %%Version: 1.4 0 %%CreationDate: (11/19/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /Adobe_blend_AI5 70 dict dup begin put /bd { bind def } bind def /xs { exch store } bd /nullProc { { } } def /initialize { pop pop Adobe_blend_AI5 begin Adobe_blend_AI5_vars begin /_contoneDevice where { pop } { /_contoneDevice false def } ifelse /_dpiThreshold where { pop } { /_dpiThreshold 600 def } ifelse /_screenFreqThreshold where { pop } { /_screenFreqThreshold 150 def } ifelse /tRectOK? deviceDPI _dpiThreshold le currentScreenFreq _screenFreqThreshold le and _contoneDevice not and def /invertXfer { [ { 1 exch sub } /exec load systemdict/currenttransfer get exec /exec load ] cvx systemdict/settransfer get exec } bd /spotDict 3 dict dup begin /nSpots 2 def /spot1 7 dict def /spot2 7 dict def end def composite? { /_setgray_ /setgray load def /_fill_ /fill load def /_image_ /image load def } { /_setgray_ systemdict/setgray get def /_fill_ systemdict/fill get def /_image_ systemdict/image get def } ifelse } bd /terminate { currentdict Adobe_blend_AI5_vars eq { end currentdict Adobe_blend_AI5 eq { end } if } if } bd /_compositeSpotDevice where { begin _compositeSpotDevice 0 ne {userdict /composite? true put} if end } { /_compositeSpotDevice 0 def } ifelse /nullString () def /d255 256 array def 0 1 255 { d255 exch dup 255 div put } bind for /d255- 256 array def 0 1 255 { d255- exch 1 d255 2 index get sub put } bind for /dUserSpace matrix defaultmatrix def currentdict /Adobe_blend_AI5_vars 89 dict dup begin put { /f /F /s /S /b /B } { null def } bind forall /byte 1 string def /sSave null def /setSSave { save /sSave exch store } bind def /Bm null def /doBlend null def /startC? false def /endC? false def /fCMYK? null def /startTint 0 def /endTint 0 def /bSMatrix matrix def /bUMatrix matrix def /dMatrix matrix def /inLine? true def /pTState? false def /bHi? false def /yHi 0 def /xHi 0 def /noImg /lv1Fix where { pop lv1Fix } { false } ifelse def /ccAry1 5 array def /ccTint 0 def /spotColor? false def /colorimage? true def [ /tint1Data /tint2Data /spotDict /bAxis /ubAxis /pChange /optimize? /nSamples /sInc /blendProc /_bn /xBCInc /yBCInc /bInc /bRender /cBName /cBType /nColors /color? /blend? /colorType /cData /cDataLen /bDataLen /rampPoint /midPoint /endPoint /blendLength /blackData /yeData /mgData /cyData /cnt1 /ndx /_fill /tmp counttomark { null def } bind repeat pop currentdict end currentdict end exch begin begin /unitSq { 0 0 moveto 0 1 lineto 1 1 lineto 1 0 lineto closepath } bd /gMark { counttomark 2 add -1 roll } bd /setCustomColor { dup /ccTint exch store 1 exch sub 6 1 roll ccAry1 astore exch setcustomcolor } bd /currentCustomColor { ccAry1 aload pop ccTint } bd /nsetcustomcolor where { pop } { /nsetcustomcolor { pop setcmykcolor } bd } ifelse /nsetcustomcolorend where { pop } { /nsetcustomcolorend { } bd } ifelse /setBSpace { newpath bUMatrix astore concat unitSq } bd /setCStop { dup 0 eq { pop spotColor? { dup 1 exch sub /ccTint exch def ccAry1 4 /Black put } if setgray } { 1 eq { setcmykcolor } { composite? not colorType 2 lt and { forceCMYK } { setCustomColor } ifelse } ifelse } ifelse } bd /makeByte { /tmp 0 store 255 mul cvi 8 string 8 { dup tmp 3 index put /tmp tmp 1 add store } repeat exch pop } bd /setImgSpace { cDataLen 1 8 2 index 0 0 1 0 0 dMatrix astore } bd /bwImage { setImgSpace cData /_image_ load { exec } stopped { $error /errorname get /undefinedresult ne { stop } { pop pop pop pop pop } ifelse } if } bd level2? { /bFill { _fill } def /bCImg { /cDataLen bDataLen store setImgSpace setSSave expandSpot cyData mgData yeData cData expandCMYK true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd } if /expandOne { dup type /stringtype ne { cDataLen string exch dup 0 ne { 255 mul cvi 0 1 cDataLen 1 sub { 3 copy exch put pop } for } if pop } if } bd /expandSpot { spotColor? { spotDict begin spot1 begin tintImage type /nulltype ne { tintImage expandOne /tintImage exch def } if end spot2 begin tintImage type /nulltype ne { tintImage expandOne /tintImage exch def } if end end } if } bd /expandCMYK { 4 { expandOne 4 1 roll } repeat } bd /colorimage where dup { exch pop /ncolorimage where { pop } { /ncolorimage {pop colorimage} bd } ifelse } if not { /ncolorimage where { pop } { /colorimage? false store /ncolorimage { pop pop pop setSSave /blackData xs /yeData xs /mgData xs /cyData xs /cnt1 0 store [ byte dup 0 cyData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .3 /mul cvx } { .3 mul } ifelse mgData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .59 /mul cvx } { .59 mul } ifelse yeData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .11 /mul cvx } { .11 mul } ifelse blackData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx } if /add cvx /add cvx /add cvx 1 /exch cvx /sub cvx /dup cvx 0 /lt cvx { pop 0 } /if cvx /dup cvx 1 /gt cvx { pop 1 } /if cvx 255 /mul cvx /cvi cvx 256 /mod cvx /dup cvx 0 /lt cvx { pop 0 } /if cvx /put cvx /cnt1 dup cvx 1 /add cvx /store cvx ] cvx bind _image_ sSave restore } bd } ifelse } if level2? not { /bCImg { /cDataLen bDataLen store setImgSpace setSSave expandSpot cyData mgData yeData cData colorimage? { expandCMYK } if true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd /bwFill { setSSave /cDataLen 8 store /cData currentgray makeByte store bwImage sSave restore } bd /c1ImgFill { setSSave /cDataLen 8 store setImgSpace spotColor? { spotDict begin spot1 begin currentCustomColor makeByte /tintImage exch def /name exch def /spot_K exch def /spot_Y exch def /spot_M exch def /spot_C exch def end spot2 initSpotData end } if currentcmykcolor 4 { makeByte 4 1 roll } repeat true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd /bFill noImg { { _fill } } { { color? { c1ImgFill } { bwFill } ifelse } } ifelse bd } if composite? { /bCFun { color? { cyData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if mgData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if yeData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if cData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if spotColor? { spotDict begin /spotDict cvx /begin cvx spot1 begin tintImage dup type /stringtype eq { /ndx cvx /get cvx d255- /exch cvx /get cvx } { dup type /nulltype ne { name type /nametype ne {1 exch sub} if } if } ifelse end /spot1 cvx /tintValue 3 -1 /roll cvx /put cvx spot2 begin tintImage dup type /stringtype eq { /ndx cvx /get cvx d255- /exch cvx /get cvx } { dup type /nulltype ne { name type /nametype ne {1 exch sub} if } if } ifelse end /spot2 cvx /tintValue 3 -1 /roll cvx /put cvx /end cvx end /spotDict cvx /nsetcustomcolor cvx } { /setcmykcolor cvx } ifelse } { cData /ndx cvx /get cvx d255 /exch cvx /get cvx /setgray cvx } ifelse } bd /Bc { newpath gsave setBSpace nColors 1 eq { pop pop setCStop } if bFill grestore } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { linImg } { bFill } ifelse grestore nColors 1 gt { getRData } if } bd /rdBm { /nColors dup load 1 sub store _fill gsave bUMatrix astore concat bHi? { xHi yHi bUMatrix idtransform /yHi exch store /xHi exch store rampPoint 1 lt { 1 rampPoint sub dup xHi mul exch yHi mul translate } if } if nColors { 0 0 rampPoint 0 360 arc _fill blend? bHi? or { rdBlend } if nColors 1 gt { getRData } if /nColors dup load 1 sub store } repeat /nColors 1 store grestore } bd /cGetRData { setCStop /blend? cData type /stringtype eq dup not color? and { pop cyData type /stringtype eq mgData type /stringtype eq yeData type /stringtype eq or or } if store } def /cGetRData } if /eCStop { mark 1 index 3 mul 3 add dup 8 gt { pop 8 } if 1 roll cleartomark } bd composite? not { /knockOut level2? { { 0 0 0 0 setcmykcolor _fill } } { /bFill noImg { { _fill } } { { _of true eq { currentgray 1 ne { bwFill } if } { bwFill } ifelse } } ifelse def /whiteByte 1 makeByte def noImg { { 0 0 0 0 setcmykcolor _fill } } { { cBType 0 eq { setSSave /cData whiteByte store /cDataLen 8 store bwImage sSave restore } { _fill } ifelse } } ifelse } ifelse bd /bCFun { cData dup type /stringtype ne { color? { 1 exch sub } if } { /ndx cvx /get cvx color? customColor? not and { d255- } { d255 } ifelse /exch cvx /get cvx } ifelse /_setgray_ cvx } bd /eCCBlend { dup 3 eq { pop mark 7 1 roll 6 copy ccThrough? dup /blend? xs { /startC? true store setCustomColor customColor? { /cData tint1Data store setCDataLen } if /endC? 3 index 3 eq { 4 index 1 ne } { false } ifelse store } if cleartomark stop } if 1 eq { pop pop pop } if pop /startC? false store 6 { 8 index } repeat ccThrough? dup /blend? xs { /endC? true store blend? not { stop } if customColor? { /cData tint1Data store setCDataLen } if } if } bd /handleOP { _of not { knockOut } if } bd /handleROP { _of not { 0 0 0 0 setcmykcolor _fill } { newpath } ifelse } bd /rdBm { /nColors dup load 1 sub store blend? { _fill } { handleROP } ifelse gsave bUMatrix astore concat bHi? { xHi yHi bUMatrix idtransform /yHi exch store /xHi exch store rampPoint 1 lt { 1 rampPoint sub dup xHi mul exch yHi mul translate } if } if nColors { 0 0 rampPoint 0 360 arc blend? { cData type /stringtype ne bHi? not and { cData color? { 1 exch sub } if _setgray_ _fill_ } { cData type /stringtype ne { /cDataLen 1 store /bDataLen 1 store } if rdBlend } ifelse } { handleROP pTState? { /bAxis rampPoint endPoint sub store xHi bAxis mul yHi bAxis mul translate } if } ifelse nColors 1 gt { getRData } if /nColors dup load 1 sub store } repeat /nColors 1 store grestore } bd /ccThrough? { gsave pop 0 setCustomColor currentcmykcolor grestore anyColor? } bd /forceCMYK { exch pop 1 exch sub 5 1 roll 4 { 4 index mul 4 1 roll } repeat 0 cCMYKData dup /cData ne { dup /yeData eq { pop 1 add } { /mgData eq { 2 } { 3 } ifelse add } ifelse 0 } if pop index 0 eq { pop pop pop pop 0 0 0 0 } if setcmykcolor pop /fCMYK? true store } bd /endCapSepBc { pop pop dup 0 eq { pop setgray } { 1 eq { setcmykcolor } { colorType 1 eq { forceCMYK } { fCMYK? { forceCMYK } { setCustomColor } ifelse } ifelse } ifelse } ifelse currentcmykcolor anyColor? blend? and { bFill } { handleOP } ifelse } bd } if /cCMYKData 0 def composite? dup not { pop customColor? } if not { /cCMYKData /cyData /mgData /yeData /cData black? not { yellow? { exch } { magenta? { 3 } { 4 } ifelse -1 roll } ifelse } if 4 1 roll pop pop pop store /Bc { gsave setBSpace nColors 1 gt { blend? currentcmykcolor anyColor? and { bFill } { handleOP } ifelse } { endCapSepBc } ifelse grestore newpath } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { cCMYKData load dup type /stringtype eq { dup length /cDataLen xs /cData xs gsave colorType 0 ne noImg not and { invertXfer } if linImg grestore } { pop bFill } ifelse } { handleOP } ifelse grestore nColors 1 gt { getRData } if } bd /cmykGetRData { /fCMYK? false store blend? { { cmykDataProcs colorType get exec } stopped pop blend? { /cData cCMYKData load store setCDataLen } if } if } def /cmykDataProcs [ { pop black? dup /blend? xs { setgray 0 } if pop } { cCMYKData load dup type /stringtype ne { 0 0 0 cyan? not { 4 magenta? { 1 } { yellow? { 2 } { 3 } ifelse } ifelse roll } if 4 copy add add add 0 eq { /blend? false store } if setcmykcolor /startC? true store /endC? true store eCStop stop } if pop dup 0 eq { pop setgray } { 1 eq { setcmykcolor } { forceCMYK } ifelse } ifelse } bind /eCCBlend load { cBType 1 eq { tint1Data tint2Data /tint1Data xs /tint2Data xs } if 0 eq { black? { setgray } { 0 0 0 4 -1 roll 1 exch sub setcmykcolor } ifelse black? { /blend? true store } if 6 { 8 index } repeat ccThrough? { /blend? true store } { black? { /cData tint1Data store setCDataLen } { /blend? false store } ifelse } ifelse } { mark 7 1 roll 6 copy ccThrough? { forceCMYK pop stop } if 9 index 0 eq { black? dup /blend? xs { pop 1 setgray /cData tint2Data store setCDataLen 0 } if pop } { /blend? 6 { 16 index } repeat ccThrough? store blend? { forceCMYK } if } ifelse cleartomark } ifelse } bind ] def /cmykGetRData } if composite? dup not { pop isCMYKSep? } if not { /endCapSepBc { /white? false store pop pop dup 0 eq { pop /white? 1 index 1 eq store setgray } { 1 eq { setcmykcolor } { setCustomColor } ifelse } ifelse % currentcmykcolor anyColor? endC? or blend? and { bFill } { handleOP } ifelse } bd /Bc { gsave setBSpace nColors 1 gt { blend? startC? and { bFill } { handleOP } ifelse } { endCapSepBc } ifelse grestore newpath } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { cData type /stringtype eq { linImg } { bFill } ifelse } { handleOP } ifelse grestore nColors 1 gt { getRData } if } bd /discardCMY { counttomark 4 add -3 roll pop pop pop } bd /testTopCC { 6 copy ccThrough? } bd /getCRamp { { ccDataProcs colorType 2 sub get exec } stopped pop blend? cDataLen 0 eq and { /cDataLen bDataLen store } if } bd /ccGetRData { /fCMYK? false store /startC? false store /endC? false store colorType 2 lt { /blend? false def } if blend? { getCRamp } { setCStop } ifelse blend? { /blend? cData 1 ne store blend? { cData dup type /stringtype ne { 1 exch sub /cData xs 0 } if pop } if } if } def /ccDataProcs [ /eCCBlend load { cBType 1 eq { tint1Data tint2Data /tint1Data xs /tint2Data xs } if 0 eq { /blend? false store pop } { mark 7 1 roll testTopCC { /blend? 1 index 1 ne store /startC? blend? store /endC? false store blend? not { cleartomark stop } if /cData tint1Data store setCDataLen setCustomColor pop stop } if cleartomark } ifelse 2 index 0 eq { /blend? false store } { mark 6 { 9 index } repeat testTopCC dup /blend? xs { /blend? 1 index 1 ne store /endC? blend? store /startC? false store blend? not { cleartomark stop } if /cData tint2Data store setCDataLen } if cleartomark } ifelse } bind ] def /ccGetRData } if load Adobe_blend_AI5_vars /getData 3 -1 roll put /setCDataLen { /cDataLen 0 cData dup type /stringtype eq { length exch } if pop store } bd /initSpotData { begin /name null def /tintImage null def /tintValue null def /spot_C null def /spot_M null def /spot_Y null def /spot_K null def end } bd /getRData { /colorType gMark store _compositeSpotDevice 0 ne { spotDict begin spot1 initSpotData spot2 initSpotData end /spotColor? colorType 2 eq colorType 3 eq or def } { /spotColor? false store } ifelse /blend? true store 0 0 0 0 setcmykcolor 100 div /rampPoint xs % (between 13 and 87%) 100 div /midPoint xs dup 0 eq { 2 } { dup 1 eq { 5 } { _compositeSpotDevice 0 ne { spotDict begin spot1 begin /name 3 index def /spot_K 4 index def /spot_Y 5 index def /spot_M 6 index def /spot_C 7 index def end end } if 7 } ifelse } ifelse /tmp exch def tmp index 100 div /endPoint xs _compositeSpotDevice 0 ne { tmp 2 add index 3 eq { /tmp tmp 4 add def tmp index dup spotDict begin spot1/name get ne { spot2 begin /name exch def /spot_K tmp 2 add index def /spot_Y tmp 3 add index def /spot_M tmp 4 add index def /spot_C tmp 5 add index def end } { pop } ifelse end } if } if /color? colorType 0 gt store colorType 3 eq { /tint2Data gMark store } if colorType 2 ge { /tint1Data gMark store } if _compositeSpotDevice 0 ne { spotDict begin colorType 2 ge { colorType 3 eq { spot2 begin /tintImage cBType 0 eq {tint2Data} {tint1Data} ifelse def name null eq {/name /Black def} if end } if spot1 begin /tintImage cBType 0 eq colorType 2 eq or {tint1Data} {tint2Data} ifelse def colorType 2 eq { name null eq { /name spot2/name get def spot2/name null put } if } { name null eq {/name /Black def} if } ifelse end } if end } if /cData gMark store setCDataLen colorType 0 gt { counttomark 4 add -3 roll /yeData xs /mgData xs /cyData xs } if blend? { /bDataLen cDataLen dup 0 eq color? and { [ cyData mgData yeData ] { dup type /stringtype eq { length exch pop exit } if pop } forall } if store bDataLen 0 eq { /bDataLen 1 store } if getData blend? { composite? cDataLen 0 eq and { /cDataLen bDataLen store } if } if } { setCStop } ifelse } bd /Bg { 0 0 0 0 setcmykcolor 6 { pop } repeat /blendLength xs pop pop pop /cBName xs /bRender xs bRender 2 ne { composite? not { _of setoverprint } if _eo {eoclip} {clip} ifelse _bn cBName 2 copy known { get mark exch aload pop /cBType xs /nColors xs mark exch aload pop 0 0 } if pop pop getRData cBType 0 eq { /linealBm } { bHi? { /pTState? nColors 2 gt store } if /doBlend /rdBlend load store /rdBm } ifelse } { inLine? not { mark mark } if /Bc dup { cleartomark mark } bd /nullProc } ifelse load /Bm xs } bd /linImg noImg { { newpath doRctBlend } } { { /doBlend color? composite? and { /bCImg } { /bwImage } ifelse load store 0 0 moveto tRectOK? composite? and { { mark 0 1 dtransform atan cvi 90 mod 0 eq 1 0 dtransform atan cvi 90 mod 0 eq } stopped { cleartomark } { and exch pop { newpath doRctBlend } { doBlend } ifelse } ifelse } { doBlend } ifelse } } ifelse bd /doRctBlend { gsave /sInc 1 store /nSamples bDataLen store /bInc 1 bDataLen div store /ubAxis 1 0 dtransform dUserSpace idtransform dup mul exch dup mul add sqrt store /pChange ubAxis 0 eq { 0 } { bDataLen ubAxis div } ifelse store pChange .5 gt noImg not and dup /optimize? xs { /nSamples ubAxis 2 div round cvi dup 1 le { pop 2 } if store /bInc 1 nSamples div store /sInc bDataLen 1 sub nSamples 1 sub div store } if 0 nSamples [ /dup cvx optimize? { /round cvx /cvi cvx } if /ndx /exch cvx /store cvx bCFun /rectfill where dup { exch pop _compositeSpotDevice 1 ne and } if { 0 0 bInc 1 /rectfill cvx } { 0 0 /moveto cvx bInc 0 /lineto cvx bInc 1 /lineto cvx 0 1 /lineto cvx /closepath cvx /_fill_ cvx } ifelse bInc 0 /translate cvx sInc /add cvx ] cvx bind repeat pop spotColor? {nsetcustomcolorend} if grestore } bd /rdPrep { /nSamples bDataLen dup 0 eq { pop 1 } if store /sInc -1 store /bAxis rampPoint endPoint sub store /bInc bAxis bDataLen div neg store /optimize? false store tRectOK? { /ubAxis bAxis 0 dtransform dUserSpace idtransform dup mul exch dup mul add sqrt 0 bAxis dtransform dUserSpace idtransform dup mul exch dup mul add sqrt 2 copy lt { exch } if pop store /pChange ubAxis 0 eq { 0 } { bDataLen ubAxis div } ifelse store pChange .5 gt noImg not and dup /optimize? xs { /nSamples ubAxis 2 div round cvi dup 1 le { pop 2 } if store /bInc bAxis nSamples div neg store /sInc bDataLen 1 sub nSamples 1 sub div neg store } if } if bHi? { /xBCInc xHi bAxis mul nSamples div store /yBCInc yHi bAxis mul nSamples div store } if } bd /rdBlend { newpath gsave rdPrep rampPoint bDataLen 1 sub nSamples [ /dup cvx optimize? { /round cvx /cvi cvx } if /ndx /exch cvx /store cvx bCFun 0 0 3 /index cvx 0 360 /arc cvx /_fill_ cvx /exch cvx bInc /add cvx /exch cvx sInc /add cvx bHi? { xBCInc yBCInc /translate cvx } if ] cvx bind repeat pop pop spotColor? {nsetcustomcolorend} if grestore pTState? { xHi bAxis mul yHi bAxis mul translate } if } bd /Bh { pop pop /pTState? false store 2 copy 0 ne exch 0 ne or dup /bHi? xs { /yHi xs /xHi xs 0 0 } if pop pop } bd /BD { inLine? not { ] nColors cBType ] _bn cBName 3 -1 roll put end } if } bd /Bn { 1 add dict dup nullString null put /_bn xs } bd /Bd { Adobe_blend_AI5_vars begin 3 -1 roll dup nullString eq dup { setSSave } if /inLine? exch def /cBName exch def /nColors exch def /cBType exch def } bd /Bb { sSave null eq { Adobe_blend_AI5_vars begin setSSave } if composite? { /_fill /fill load store } { /__fill /fill load store /_fill { _of true eq { currentgray 1 ne { __fill } if } { __fill } ifelse } def } ifelse /fill { } def } bd /BB { /cBType xs cleartomark cleartomark cBType dup bRender sSave dup type /savetype eq { restore 0 } if pop currentdict Adobe_blend_AI5_vars eq { end } if 2 ne exch 0 gt and { 2 eq { s } { S } ifelse } { pop newpath } ifelse } bd currentdict readonly pop end end defaultpacking setpacking %%EndResource %%BeginResource: procset Adobe_pattern_AI5 1.1 0 %%Title: (Adobe Illustrator (R) Version 5.0 Pattern Operators) %%Version: 1.1 0 %%CreationDate: (03/26/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_Illustrator_AI5 known not { userdict /Adobe_Illustrator_AI5 95 dict put } if userdict /Adobe_Illustrator_AI5 get begin /@ { } def /& { } def /dp { dup null eq { pop _dp 0 ne { 0 1 _dp 1 sub _dl mod { _da exch get 3 get } for _dp 1 sub _dl mod 1 add packedarray _da 0 get aload pop 8 -1 roll 5 -1 roll pop 4 1 roll definepattern pop } if } { _dp 0 ne _dp _dl mod 0 eq and { null dp } if 7 packedarray _da exch _dp _dl mod exch put _dp _dl mod _da 0 get 4 get 2 packedarray /_dp _dp 1 add def } ifelse } def /E { _ed begin dup 0 get type /arraytype ne { 0 { dup 1 add index type /arraytype eq { 1 add } { exit } ifelse } loop array astore } if /_dd exch def /_ury exch def /_urx exch def /_lly exch def /_llx exch def /_n exch def /_y 0 def /_dl 4 def /_dp 0 def /_da _dl array def 0 1 _dd length 1 sub { /_d exch _dd exch get def 0 2 _d length 2 sub { /_x exch def /_c _d _x get _ ne def /_r _d _x 1 add get cvlit def _r _ ne { _urx _llx sub _ury _lly sub [ 1 0 0 1 0 0 ] [ /save cvx _llx neg _lly neg /translate cvx _c { nc /begin cvx } if _r dup type /stringtype eq { cvx } { { exec } /forall cvx } ifelse _c { /end cvx } if /restore cvx ] cvx /_fn 12 _n length add string def _y _fn cvs pop /_y _y 1 add def _fn 12 _n putinterval _fn _c false dp _d exch _x 1 add exch put } if } for } for null dp _n _dd /_pd end xput } def /fc { _fm dup concatmatrix pop } def /p { /_fm exch ddef 9 -2 roll _pm translate fc 7 -2 roll _pm scale fc 5 -1 roll _pm rotate fc 4 -2 roll exch 0 ne { dup _pm rotate fc 1 -1 _pm scale fc neg _pm rotate fc } { pop } ifelse dup _pm rotate fc exch dup sin exch cos div 1 0 0 1 0 6 2 roll _pm astore fc neg _pm rotate fc _pd exch get /_fdd exch ddef /_pf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm patternfill } { pop fill } ifelse grestore pop } for pop } for restore newpath } ddef /_psf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm 9 copy 6 npop patternashow } { pop 6 copy 3 npop hvashow } ifelse grestore pop } for pop } for restore sw rmoveto } ddef /_pjsf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm 12 copy 6 npop patternawidthshow } { pop 9 copy 3 npop hvawidthshow } ifelse grestore pop } for pop } for restore swj rmoveto } ddef /_lp /none ddef } def /sc { _sm dup concatmatrix pop } def /P { /_sm exch ddef 9 -2 roll _pm translate sc 7 -2 roll _pm scale sc 5 -1 roll _pm rotate sc 4 -2 roll exch 0 ne { dup _pm rotate sc 1 -1 _pm scale sc neg _pm rotate sc } { pop } ifelse dup _pm rotate sc exch dup sin exch cos div 1 0 0 1 0 6 2 roll _pm astore sc neg _pm rotate sc _pd exch get /_sdd exch ddef /_ps { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm patternstroke } { pop stroke } ifelse grestore pop } for pop } for restore newpath } ddef /_pss { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm 10 copy 6 npop patternashowstroke } { pop 7 copy 3 npop ss } ifelse grestore pop } for pop } for restore pop sw rmoveto } ddef /_pjss { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm 13 copy 6 npop patternawidthshowstroke } { pop 10 copy 3 npop jss } ifelse grestore pop } for pop } for restore pop swj rmoveto } ddef /_lp /none ddef } def end userdict /Adobe_pattern_AI5 18 dict dup begin put /initialize { /definepattern where { pop } { begin begin Adobe_pattern_AI5 begin Adobe_pattern_AI5 { dup xcheck { bind } if pop pop } forall mark cachestatus 7 1 roll pop pop pop pop exch pop exch { { 10000 add dup 2 index gt { exit } if dup setcachelimit } loop } stopped cleartomark end end end Adobe_pattern_AI5 begin } ifelse } def /terminate { currentdict Adobe_pattern_AI5 eq { end } if } def errordict /nocurrentpoint { pop stop } put errordict /invalidaccess { pop stop } put /patternencoding 256 array def 0 1 255 { patternencoding exch ( ) 2 copy exch 0 exch put cvn put } for /definepattern { 17 dict begin /uniform exch def /cache exch def /key exch def /procarray exch def /mtx exch matrix invertmatrix def /height exch def /width exch def /ctm matrix currentmatrix def /ptm matrix def /str 32 string def /slice 9 dict def slice /s 1 put slice /q 256 procarray length div sqrt floor cvi put slice /b 0 put /FontBBox [ 0 0 0 0 ] def /FontMatrix mtx matrix copy def /Encoding patternencoding def /FontType 3 def /BuildChar { exch begin /setstrokeadjust where {pop true setstrokeadjust} if slice begin dup q dup mul mod s idiv /i exch def dup q dup mul mod s mod /j exch def q dup mul idiv procarray exch get /xl j width s div mul def /xg j 1 add width s div mul def /yl i height s div mul def /yg i 1 add height s div mul def uniform { 1 1 } { width 0 dtransform dup mul exch dup mul add sqrt dup 1 add exch div 0 height dtransform dup mul exch dup mul add sqrt dup 1 add exch div } ifelse width 0 cache { xl 4 index mul yl 4 index mul xg 6 index mul yg 6 index mul setcachedevice } { setcharwidth } ifelse gsave scale newpath xl yl moveto xg yl lineto xg yg lineto xl yg lineto closepath clip newpath end end exec grestore } def key currentdict definefont end } def /patterncachesize { gsave newpath 0 0 moveto width 0 lineto width height lineto 0 height lineto closepath patternmatrix setmatrix pathbbox exch ceiling 4 -1 roll floor sub 3 1 roll ceiling exch floor sub mul 1 add grestore } def /patterncachelimit { cachestatus 7 1 roll 6 npop 8 mul } def /patternpath { exch dup begin setfont ctm setmatrix concat slice exch /b exch slice /q get dup mul mul put FontMatrix concat uniform { width 0 dtransform round width div exch round width div exch 0 height dtransform round height div exch height div exch 0 0 transform round exch round exch ptm astore setmatrix } { ptm currentmatrix pop } ifelse { currentpoint } stopped not { 2 npop pathbbox true 4 index 3 index eq 4 index 3 index eq and { pop false { { 2 npop } { 3 npop true } { 7 npop true } { pop true } pathforall } stopped { 5 npop true } if } if { height div ceiling height mul 4 1 roll width div ceiling width mul 4 1 roll height div floor height mul 4 1 roll width div floor width mul 4 1 roll 2 index sub height div ceiling cvi exch 3 index sub width div ceiling cvi exch 4 2 roll moveto FontMatrix mtx invertmatrix dup dup 4 get exch 5 get rmoveto ptm ptm concatmatrix pop slice /s patterncachesize patterncachelimit div ceiling sqrt ceiling cvi dup slice /q get gt { pop slice /q get } if put 0 1 slice /s get dup mul 1 sub { slice /b get add gsave 0 1 str length 1 sub { str exch 2 index put } for pop dup { gsave ptm setmatrix 1 index str length idiv { str show } repeat 1 index str length mod str exch 0 exch getinterval show grestore 0 height rmoveto } repeat grestore } for 2 npop } { 4 npop } ifelse } if end } def /patternclip { _eo {eoclip} {clip} ifelse } def /patternstrokepath { strokepath } def /patternmatrix matrix def /patternfill { dup type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get } if gsave patternclip Adobe_pattern_AI5 /patternpath get exec grestore newpath } def /patternstroke { dup type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get } if gsave patternstrokepath true { { { newpath moveto } { lineto } { curveto } { closepath 3 copy Adobe_pattern_AI5 /patternfill get exec } pathforall 3 npop } stopped { 5 npop patternclip Adobe_pattern_AI5 /patternfill get exec } if } { patternclip Adobe_pattern_AI5 /patternfill get exec } ifelse grestore newpath } def /vpatternawidthshow { 6 1 roll /_hvay exch ddef /_hvax exch ddef /_hvwb exch ddef /_hvcy exch ddef /_hvcx exch ddef { dup cstring dup length 1 eq _charorientation 1 eq and { -90 rotate currentpoint _fontRotateAdjust add moveto gsave false charpath currentpoint 5 index 5 index 5 index Adobe_pattern_AI5 /patternfill get exec grestore _fontRotateAdjust sub moveto _hvwb eq { _hvcx _hvcy rmoveto } if _hvax _hvay rmoveto 90 rotate } { currentpoint _fontHeight sub _hvax sub 3 index _hvwb eq { _hvcx sub } if currentpoint exch 4 index stringwidth pop 2 div sub exch _fontAscent sub moveto gsave 2 index false charpath 6 index 6 index 6 index Adobe_pattern_AI5 /patternfill get exec grestore newpath moveto pop pop } ifelse } cforall 3 npop } def /hpatternawidthshow { { dup cstring exch gsave 3 index eq { 5 index 5 index rmoveto } if false charpath currentpoint 9 index 9 index 9 index Adobe_pattern_AI5 /patternfill get exec grestore newpath moveto 2 copy rmoveto } cforall 8 npop } def /patternashow { 0 0 0 6 3 roll patternawidthshow } def /patternawidthshow { 6 index type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get 7 1 roll } if _lineorientation 0 eq { hpatternawidthshow } { vpatternawidthshow } ifelse } def /vpatternawidthshowstroke { 7 1 roll 6 1 roll /_hvay exch ddef /_hvax exch ddef /_hvwb exch ddef /_hvcy exch ddef /_hvcx exch ddef { dup cstring dup length 1 eq _charorientation 1 eq and { -90 rotate currentpoint _fontRotateAdjust add moveto gsave false charpath currentpoint 3 index setmatrix 6 index 6 index 6 index Adobe_pattern_AI5 /patternstroke get exec grestore _fontRotateAdjust sub moveto _hvwb eq { _hvcx _hvcy rmoveto } if _hvax _hvay rmoveto 90 rotate } { currentpoint _fontHeight sub _hvax sub 3 index _hvwb eq { _hvcx sub } if currentpoint exch 4 index stringwidth pop 2 div sub exch _fontAscent sub moveto gsave 2 index false charpath 4 index setmatrix 7 index 7 index 7 index Adobe_pattern_AI5 /patternstroke get exec grestore newpath moveto pop pop } ifelse } cforall 4 npop } def /hpatternawidthshowstroke { 7 1 roll { dup cstring exch gsave 3 index eq { 5 index 5 index rmoveto } if false charpath currentpoint 7 index setmatrix 10 index 10 index 10 index Adobe_pattern_AI5 /patternstroke get exec grestore newpath moveto 2 copy rmoveto } cforall 9 npop } def /patternashowstroke { 0 0 0 7 3 roll patternawidthshowstroke } def /patternawidthshowstroke { 7 index type /dicttype eq { patternmatrix /patternmatrix get 8 1 roll } if _lineorientation 0 eq { hpatternawidthshowstroke } { vpatternawidthshowstroke } ifelse } def end setpacking %%EndResource %%EndProlog %%BeginSetup Adobe_level2_AI5 /initialize get exec Adobe_screens_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_typography_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_blend_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_pattern_AI5 /initialize get exec Adobe_ColorImage_AI6 /initialize get exec Adobe_Illustrator_AI5 /initialize get exec [ 39/quotesingle 96/grave 130/quotesinglbase 131/florin 132/quotedblbase 133/ellipsis 134/dagger 135/daggerdbl 136/circumflex 137/perthousand 138/Scaron 139/guilsinglleft 140/OE 145/quoteleft 146/quoteright 147/quotedblleft 148/quotedblright 149/bullet 150/endash 151/emdash 152/tilde 153/trademark 154/scaron 155/guilsinglright 156/oe 157/dotlessi 159/Ydieresis 164/currency 166/brokenbar 168/dieresis 169/copyright 170/ordfeminine 172/logicalnot 174/registered 175/macron 176/ring 177/plusminus 178/twosuperior 179/threesuperior 180/acute 181/mu 183/periodcentered 184/cedilla 185/onesuperior 186/ordmasculine 188/onequarter 189/onehalf 190/threequarters 192/Agrave 193/Aacute 194/Acircumflex 195/Atilde 196/Adieresis 197/Aring 198/AE 199/Ccedilla 200/Egrave 201/Eacute 202/Ecircumflex 203/Edieresis 204/Igrave 205/Iacute 206/Icircumflex 207/Idieresis 208/Eth 209/Ntilde 210/Ograve 211/Oacute 212/Ocircumflex 213/Otilde 214/Odieresis 215/multiply 216/Oslash 217/Ugrave 218/Uacute 219/Ucircumflex 220/Udieresis 221/Yacute 222/Thorn 223/germandbls 224/agrave 225/aacute 226/acircumflex 227/atilde 228/adieresis 229/aring 230/ae 231/ccedilla 232/egrave 233/eacute 234/ecircumflex 235/edieresis 236/igrave 237/iacute 238/icircumflex 239/idieresis 240/eth 241/ntilde 242/ograve 243/oacute 244/ocircumflex 245/otilde 246/odieresis 247/divide 248/oslash 249/ugrave 250/uacute 251/ucircumflex 252/udieresis 253/yacute 254/thorn 255/ydieresis TE %AI3_BeginEncoding: _Helvetica Helvetica [ /_Helvetica/Helvetica 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-Bold Helvetica-Bold [ /_Helvetica-Bold/Helvetica-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-Oblique Helvetica-Oblique [ /_Helvetica-Oblique/Helvetica-Oblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-BoldOblique Helvetica-BoldOblique [ /_Helvetica-BoldOblique/Helvetica-BoldOblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Roman Times-Roman [ /_Times-Roman/Times-Roman 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Bold Times-Bold [ /_Times-Bold/Times-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Italic Times-Italic [ /_Times-Italic/Times-Italic 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-BoldItalic Times-BoldItalic [ /_Times-BoldItalic/Times-BoldItalic 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier Courier [ /_Courier/Courier 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-Bold Courier-Bold [ /_Courier-Bold/Courier-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-Oblique Courier-Oblique [ /_Courier-Oblique/Courier-Oblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-BoldOblique Courier-BoldOblique [ /_Courier-BoldOblique/Courier-BoldOblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Symbol Symbol [ /_Symbol/Symbol 0 0 1 TZ %AI3_EndEncoding AdobeType %%EndSetup 1 XR u 0.000 0.000 0.000 0.000 k [] 0 d 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 140.0315 218.2677 m 212.5984 218.2677 L 212.5984 253.9843 L 140.0315 253.9843 L 140.0315 218.2677 L B U 0 To 1.0000 0.0000 0.0000 1.0000 162.7087 239.8110 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (NUA/\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 147.4016 225.0709 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0.000 0.000 0.000 1.000 k (Sofia stack\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 J 1 j 176.8819 218.2677 m 176.8819 42.5197 L S U u 5.6693 185.9528 m 172.9134 185.9528 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 172.3465 188.2205 m 176.8819 185.9528 L 172.3465 184.2520 L 172.3465 188.2205 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 66.3307 189.3543 m 115.6535 189.3543 L 115.6535 200.6929 L 66.3307 200.6929 L 66.3307 189.3543 L F U 0 To 1.0000 0.0000 0.0000 1.0000 66.8976 192.7559 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (nua_handle\(\)\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 5.6693 150.2362 m 164.4094 150.2362 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 163.8425 152.5039 m 167.8110 150.2362 L 163.8425 148.5354 L 163.8425 152.5039 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 57.2598 153.6378 m 115.6535 153.6378 L 115.6535 164.9764 L 57.2598 164.9764 L 57.2598 153.6378 L F U 0 To 1.0000 0.0000 0.0000 1.0000 58.3937 157.0394 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (nua_message\(\)\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.000 k 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 167.8110 69.7323 m 185.3858 69.7323 L 185.3858 150.2362 L 167.8110 150.2362 L 167.8110 69.7323 L B U u 0.000 0.000 0.000 1.000 K 185.3858 141.7323 m 361.7008 141.7323 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 361.7008 143.4331 m 365.6693 141.7323 L 361.7008 139.4646 L 361.7008 143.4331 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 255.6850 145.1339 m 294.8031 145.1339 L 294.8031 156.4724 L 255.6850 156.4724 L 255.6850 145.1339 L F U 0 To 1.0000 0.0000 0.0000 1.0000 256.8189 147.9685 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (MESSAGE\r) Tx TO 0.000 0.000 0.000 1.000 K u [8 4 ] 0 d 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 365.6693 114.5197 m 189.3543 114.5197 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 189.3543 112.2520 m 185.3858 114.5197 L 189.3543 116.7874 L 189.3543 112.2520 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 255.6850 117.9213 m 295.3701 117.9213 L 295.3701 129.2598 L 255.6850 129.2598 L 255.6850 117.9213 L F U 0 To 1.0000 0.0000 0.0000 1.0000 256.2520 121.3228 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr [] 0 d 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (100 Trying\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 365.6693 77.6693 m 189.3543 77.6693 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 189.3543 75.4016 m 185.3858 77.6693 L 189.3543 79.9370 L 189.3543 75.4016 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 261.9213 81.0709 m 289.1339 81.0709 L 289.1339 92.4094 L 261.9213 92.4094 L 261.9213 81.0709 L F U 0 To 1.0000 0.0000 0.0000 1.0000 262.4882 83.9055 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (200 Ok\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 167.8110 69.7323 m 9.0709 69.7323 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 9.6378 67.4646 m 5.6693 69.7323 L 9.6378 71.4331 L 9.6378 67.4646 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 56.6929 72.5669 m 116.7874 72.5669 L 116.7874 83.9055 L 56.6929 83.9055 L 56.6929 72.5669 L F U 0 To 1.0000 0.0000 0.0000 1.0000 57.2598 75.9685 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (nua_r_message\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 358.2992 120.1890 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0.000 0.000 0.000 1.000 k (\(1\)\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 9.6378 9.6378 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k (\(1\) optional\r) Tx TO 0.000 0.000 0.000 1.000 K %%PageTrailer gsave annotatepage grestore showpage %%Trailer Adobe_Illustrator_AI5 /terminate get exec Adobe_pattern_AI5 /terminate get exec Adobe_blend_AI5 /terminate get exec Adobe_ColorImage_AI6 /terminate get exec Adobe_typography_AI5 /terminate get exec Adobe_screens_AI5 /terminate get exec Adobe_level2_AI5 /terminate get exec %%EOF II*TT`(@ww33JJ``ww33GG\\pp""11@@OO^^nn}}""++33<>FFMMUUll""11@@OO^^nn}}33GG\\pp33JJ``ww33MMff33PPmm33MMff33JJ``ww33MMff((77EETTbbqq--DD[[qq::WWuu::WWuu::WWuu""DDff""DDff))RRzz""DDff::WWuu33MMff""++33<FMUl"Dfƪ3"J1`@wO^n}Ҍ"Df׈33GG\\pp)Rz"31J@`Ow^n}"Df3M"f+3<DMUh|:Wu3Pm33MMff3Mf"+3<DMUh:|Wu3"J1`@wO^n}Ҍ"Df̈ת33MMff:Wu3(P7mETbq3Mf3Uw--DD[[qq3&M3f@MYfs:WuȒׯ33MMff:Wu3M&f3@MYfs:Wu!,T@H*\ȰÇ#JHŋ3jȱǏ CIc(+Lɲ˗0cʜ)qeGV9'OyJѣHa M:r)ӧPJJө@Vsj̚kW`ÊKvh*Z|\p>Z߿wÈ-ǐ#3LP'cμ:m+rQLuװc;۸ͻoϿ x7ȓ4yۮ֫O^'|jw؋W1^ӵsW/]O~eϿ(hhs-5b&kzanYVva(h؉*X,(IH8dc<ؔE%^HVdLwTa;6hVd\vЖ^)f^cifD`fip)tix)hqHy3E6F@@ DPB >Q-^bF=~RH%M1dEU˃2/DSN=}gF0=JphҕA>UTV5yV]~Ɩdc*EZhAfδ V\u{7^}3o`… Fspbƍ?dʕބdɖ=-lХMFԭ]9lڵ=w[nyN%ō[lTꄛ>hrխ_Ǟ]vݽ^xiW(,Х'|g_Jsn:@ɹz+@5ʰC CG+DOD,SdEVL_R]+s1d-štB#  kI';I)lJ+T K-K/ L1$L3D3M5dM # tĊ2ʢ-"NA%Ќ p "Lp!ÆB(a/b̨q#ǎ?8q$ɒ&OLr%˖._„ &M3k̩s'Ϟ>R(ADiʥ@B*u*ժ I\ju,ٲfϢ-(W_25uhںvrމ|,xԿNx1 /6趧a/cάrBp~Y)ҥEO6y3֮M:4M^v޾SY8Ə$~Y9Ο+ )}:ԡcϮ},޿=< O~Ï/S>_sh]gNi~ nƕL:]L r(kXYdۉ+-Y/XQx;#?VC E"mJ2IiԄObX%WJ5eSMInERBfmؑ^ q`m7y% Xgw7]MgIhBZ(()h)iݹi`zjZ~*}X}s}"j{%zma+Xsi뭣i+.XUY,-+mDjiZߊ,j*g.(.-.&f/~nڨ/p]eh je [ ee0&#eI!ʂa/0y3i;cV3?3C$4Gۄx5xN]Vc[sݵ_c]gMhʛt6 V xL\&z އ#3n*@$XA .dC%NXE5nG!E$1@IOdK1eΔL7uϔ9:QI,tcSQNZEm6 ӪaŎ%ŕ9وpΥ[Cz[y%\a oVȐwe:+CԺ_Y\陛 FYæ]캸m}Y߽;8qɣ+^Y쒽Jު=Ȍo <կgлƠ?f{|Z 1:?T,3 ʃо[pCcsMCG4Č@JE[܏E`tqdTFsQ{5rԈ4ȲDrI&9RI(NJ*J,DI-K/<L1L3M5DM7-: N9\kO? >WPNB 4жH, OD},QJ,RS直RRLFGTV[UXw{5VZKspZM;uW^{W`vXb5XdU\Yh׌vgZv[=o5wrUtuwM^zK^[׷}Mհv+Nū~LaAA/` G7/A uc /R'PNoӂxeB1MmvekfJN58az"p-:suPjK~Z=ѲVmmk[:λ!zo|& UB|qIdq?, * + !"#$%&'()Root EntryF(B@VisioDocument"SummaryInformation($'DocumentSummaryInformation8Visio (TM) Drawing "l k!SRd !fffMMM333$ $ U8@ TD Arial@NMonotype Sorts@m Wingd NtSymbol5T?? Y@-1U J:DT1EW-hPT8*  .U_b a酸0zGz?@3CfRbU|||%U P } |KpG/Y&4Y$? v AfY&,,' /Dq&z&} | |y  }{})} ?2  | | ||||*|||E-?k4'-'CECE,'*CECECE-?H>?:`}'CEUCECECECEUCECE- O4F2AJY;; AnVnVAbGTfY R_R__ `#f:/lb6p`fW /l /l  Y?5?(\ #!+ | tFf-|J-|-|-wG QUo "OM`EtoA _3=OOOaOsO@O??O?7ܻuR? sU/-O%7I[mRf J+ K5   . ||i| d' 0/UKiR?d?v4Gzt2#&Us s s s) -0jӯY/ƛ!3)󿵶1D///Q+p)?HdYc4AkǿٿYfU|%1I߀O]-(fp ɻ %-=Y[:!#:4)A/q//YkϹ/p?2 Sπ'9}Fɇ7%õ8@\n1$u  (:L^p)BH>ZՔU \ n4!'4#U2q ?/%&k/%&`,`,`',ѓ4?|QԞQyٓA G $z Z$bp6q /#3=/Uq@T0'vr@1N!T0;UOauADV=煤{2r H+"P)Ҳ$2@1@1B,$1//cAm/ߙ߫BVVj /Q?c?u4D?U0O贁 NkRC6$SfMea5t(O"?2RO}q19!S _2_D_"3Htr+*a__//5o2DV õoa`oo1 I+< g4`\\esprn002\HER1F5B1S odWX+'?LetterO_b PRIV0|'r\KhC]>w!tuy //-/?/Q/c/u////////??)?;?M1E%winspool\\esprn002\HER1F5B1IP_172.21?.36.10UFDfP h-RTUUUA@ ?I?a 3h AeqYk Hu_ Q? #,BDrag between shapes to indicate a flow offormation or control.mb?sߛ⿻xw?t? 8HD    3h <>T$  ;MBRAU@?N ?AP6 Ju `u buU  -J ">ۀJuM` Zue"JD4WAQ @%UI>J[@hK'F"U/g%'_-/g JQ#5 L"V &6 霑c ?@IW0?@q`0U>U5Q?!9[a2f`rd}b0@3&/0`A.=@2M @J2uF.3B B$fH2&M+3Q(-DT! @6[Dн8P$?J 3tNsWB Ld!%6 MB##0O贁Nk?<$2%@@PR%|#xQ}T5 B`7Copyright 1999 Visio Corporation. All Rs reserved.J`P_SCPchm!#22776G#2r5ofP"JSfunq&^(E9 Yr[xQ4 0UChange Arrow?head..PVcthe ae siz`n`tyle for`is connectorP1`Bb)WlJhUd>5 yG|(AJ*C<4bZw"M (3,rx srA iVohot'd1dxB3d+=-C2U낥@6f 32`_D/@>W4C)rp -3TqC@@JQ\^E? v!3?|@ 2Pa@0pqB;uK`u`WE @ǗHXC1 aVHl'-d! !Oya HE_9bFt w~#O . B 4W ]Ma|ku]@+k]/ao fPUl4,"H$ @Y,b'@ d OA-4 U7U2@ [7ERH<( U2E 7 R(n S >@?4 =RDtKOi{ UP?V]U$5@*P8FDTey  ahm qTP^UI"H$ @IY,b'@? ?I*M_q2?p^qu2`"ua )ePe, aR b$!H!$'$a'$!'!(*!(!'!('!(e!'e!( *(@'!(#EqP!5a!ĉ!!! A11e! 4A1COUOgOyOOO!%i!|aM 5 `@*`$kT}^?@U/Q%V'/RRl!0qU@Q5m/#$1 ^`$R-R.-$1 "f*egzoo#aoTooNwa5'{>ob}$1R2{qr rsNUA/ Sofia stack"y%OOOO _N[`_p!kTtUP-DT!f-qu0`u `bu4@`ue 7.@"q>.Qs4. 9vC>@_]_Rɶ]_Q#tUjUO@$*4FЗ] *xUa*d1 wu%?oU%Sk*u4RsA"a$5B3$1Uu$1U!@5&x'oN[EYqtUܳ@Afܳ?}ƙZ&rjOa f@I~!?@q*Q #a1u`}@8w[2TP(<w ܿeQy%ƯدUi!}iWud^!_3_8:2$UUVM & &ڀ8nua_handle()"7e8ο(:L*i"s|Ϡ@!"ϨCߍl#!f}ߏ߳԰r,>Pbts-messag?$1>ybt@_E/W/K_Q tUQ}U!}U_]6ڟ_oo7oIo[omo9heFoF6OPO:_+_dO_)j_Ov!H6ahho@NOZ4A:0|s,>ˀaibg|u ,q~6a'9SeNrm6a//~5/U?g?k/}////AMES/SAGE"7oϑWo{om(Gb7OIO[Momo#p-DT! 14_vH{k}IϿE@+qyTy(ĩ@ ϑ(X#0O贁+NkbX͡a4T!a@ϑˏݏ%7I[måQåVV++100 Trying"^ӟ]^ooo^oDӯZvhHvh,>P88&mѡ(Kս4VhzϞϰ .@Rdvc& 2Ok"s $6H"Cn*(1?{4 I[,I[ss: hN 1(:L^p .Snua_r_messageD#C Ct? _ U93C%5A1Q=D͎1 EX`pB~[[p[)Q?TģUar!TBBu0`ND?4VBCu0Yt!?5/b(1)D4E#O __DE7_I_[_m_^U%`uľ_Qm_]eoo'o9oKo]oooooo'@o,_E1ƯDVq;T_qEmZ optionalj.O@OROIi6Q!3m Bu.71UU Ul4,"H$ @Y,b'@ ſ 7C-37"AU2@ 7IRH<( U2E  7 RUlL IB ߋ@?d wRD -;U$ < w?VU5@@g( "*^p=*4 -l #5GYk}C:\Program Files\Microsoft Visio\Solutions\Block Dia\Basic Shapes.vss*7l"4FXj|  C:\Program Files\Microsoft Visio\Solutions\ Extras\Connectors.vss]l 2DV`hzՌ(X<C*| KC!t +/ }/? 6/U1(5 O"D&U=Q Jf )h"/Tyj+U-| Ʌ&Q- H*9(TYgEQ/,GuideTheDocPage-1Gesture FormatConnectorVisio 90Directed line 1Directed lin?e 1.4Directed lin?e 1.7Directed lin?e 1.8Directed line 1.11Directed line 1.12_v 3_ 5EU,? <J- LUGdm|{ UU ׾ A U< \2d*6l: 0 xfUl4,"H$ @Y,bK'@   UA-3,7;Ul4, < } AJ-437A_*<N@D 2 KRVgt q6uH<( H<( _*<NE ! RVg q {th * g"4pFX(?@(ϫ@Ȝ , :TR q& !B< [ 2b>?O@p܇B| U$@'Cɇ LfNf)D 9X1 =`2 >V?C FD UNC=bN՜.+,D՜.+,@HP\h t   PagesMastersPage-1Directed line 18_VPID_PREVIEWS@_VPID_ALTERNATENAMES?_PID_LINKBASE A Oh+'0&HPdp| rinnerahSIP outgoing callG<&NPWRSt EMF4&) l@@VISIODrawing% %   &%   '% V0999% ( % (  Rp Arialdv% Rp Arial>t,Uw@*w<wP>>/Uw*wX#` @xdv% %  %   TdAALTNUA/   T,AA LdSofia stack     % &%  W$% ( % Rp  Arialdv% %  %  % &%  W$% ( %  '% % V,% % (   '% % V08888% % (  Rp Arialpudv% %  %   T: AA:  Ldnua_handle() % &%  W$UUUU% ( %  '% % V,RYRUYR% % (   '% % V0)<O)OO<)<)O% % (  Rp Arial>t,Uw@*w<w>X(:>tUw(%w\x>#` @xdv% %  %   T*=LAA*J Lhnua_message()  % &%   '% V0U   UU% ( % (  &%  W$ e?e e?e% ( %  '% % V,>bEi>bEe>i>b% % (   '% % V0K___KK_% % (  Rp Arial>t,Uw@*w<w>XD>tUw(%w\x>#` @xdv% %  %   TxM\AAZL\MESSAGE  % &%  W$EE% ( %  '% % V,  % % (   '% % V0{{{% % (  Rp Arial>t,Uw@*w<w>Xp>tUw(%w\x>#` @xdv% %  %   T|AA L`100 Trying  % &%  W$EE% ( %  '% % V,  % % (  ( (  '% % V0% % (  Rp Arial>t,Uw@*w<w>X(:>tUw(%w\x>#` @xdv% % (  %   TpAALX200 Ok  % &%  W$% ( %  '% % V,% % (   '% % V0''''% % (  Rp Arial>t,Uw@*w<w>X/>tUw(%w\x>#` @xdv% % (  %   T)AA) Lhnua_r_message  % % Rp Arial>t,Uw@*w<wP>X#` @xdv% % (  %   T`8wNAA8LT(1)  % % Rp Arial>t,Uw@*w<wP>XtUw(%w\xP>#` @xdv% % (  %   T9:PAAL Ld(1) optional    % VisioInformation"sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/docs/pictures/SIP_incoming_call.eps000066400000000000000000014006601223300710500263710ustar00rootroot00000000000000CcM%!PS-Adobe-3.0 EPSF-3.0 %%Creator: ImageMark Software Labs %%For: () () %%Title: V:\work\rinnerah\sofia\SIP_incoming_call.eps %%CreationDate: () () %%BoundingBox: 0 0 377 393 %%DocumentProcessColors: Black %%ColorUsage:Color %%DocumentFonts: Helvetica %%+Helvetica-Bold %%+Helvetica-Oblique %%+Helvetica-BoldOblique %%+Times-Roman %%+Times-Bold %%+Times-Italic %%+Times-BoldItalic %%+Courier %%+Courier-Bold %%+Courier-Oblique %%+Courier-BoldOblique %%+Symbol %%DocumentSuppliedResources: procset Adobe_level2_AI5 1.2 0 %%+ procset Adobe_screens_AI5 1.0 0 %%+ procset Adobe_typography_AI5 1.0 0 %%+ procset Adobe_ColorImage_AI6 1.1 0 %%+ procset Adobe_blend_AI5 1.0 0 %%+ procset Adobe_pattern_AI5 1.0 0 %%+ procset Adobe_Illustrator_AI5 1.0 0 %AI5_FileFormat 3.0 %AI3_ColorUsage: Color %AI3_TemplateBox: 0 0 377 393 %AI3_TileBox: 0 0 377 393 %AI3_DocumentPreview: None %%Template: %%PageOrigin:0.0000 0.0000 %AI7_GridSettings: 72 8 72 8 1 0 0.8 0.8 0.8 0.9 0.9 0.9 %%EndComments %%BeginProlog %%BeginResource: procset Adobe_level2_AI5 1.2 0 %%Title: (Adobe Illustrator (R) Version 5.0 Level 2 Emulation) %%Version: 1.2 0 %%CreationDate: (04/10/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /Adobe_level2_AI5 25 dict dup begin put /packedarray where not { userdict begin /packedarray { array astore readonly } bind def /setpacking /pop load def /currentpacking false def end 0 } if pop userdict /defaultpacking currentpacking put true setpacking /initialize { Adobe_level2_AI5 begin } bind def /terminate { currentdict Adobe_level2_AI5 eq { end } if } bind def mark /setcustomcolor where not { /findcmykcustomcolor { 0 6 packedarray } bind def /findrgbcustomcolor { 1 5 packedarray } bind def /setcustomcolor { exch aload pop 0 eq { pop 4 { 4 index mul 4 1 roll } repeat 5 -1 roll pop setcmykcolor } { pop 3 { 1 exch sub 3 index mul 1 exch sub 3 1 roll } repeat 4 -1 roll pop setrgbcolor } ifelse } def } if /gt38? mark {version cvr cvx exec} stopped {cleartomark true} {38 gt exch pop} ifelse def userdict /deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt put userdict /level2? systemdict /languagelevel known dup { pop systemdict /languagelevel get 2 ge } if put /level2ScreenFreq { begin 60 HalftoneType 1 eq { pop Frequency } if HalftoneType 2 eq { pop GrayFrequency } if HalftoneType 5 eq { pop Default level2ScreenFreq } if end } bind def userdict /currentScreenFreq level2? {currenthalftone level2ScreenFreq} {currentscreen pop pop} ifelse put level2? not { /setcmykcolor where not { /setcmykcolor { exch .11 mul add exch .59 mul add exch .3 mul add 1 exch sub setgray } def } if /currentcmykcolor where not { /currentcmykcolor { 0 0 0 1 currentgray sub } def } if /setoverprint where not { /setoverprint /pop load def } if /selectfont where not { /selectfont { exch findfont exch dup type /arraytype eq { makefont } { scalefont } ifelse setfont } bind def } if /cshow where not { /cshow { [ 0 0 5 -1 roll aload pop ] cvx bind forall } bind def } if } if cleartomark /anyColor? { add add add 0 ne } bind def /testColor { gsave setcmykcolor currentcmykcolor grestore } bind def /testCMYKColorThrough { testColor anyColor? } bind def userdict /composite? level2? { gsave 1 1 1 1 setcmykcolor currentcmykcolor grestore add add add 4 eq } { 1 0 0 0 testCMYKColorThrough 0 1 0 0 testCMYKColorThrough 0 0 1 0 testCMYKColorThrough 0 0 0 1 testCMYKColorThrough and and and } ifelse put composite? not { userdict begin gsave /cyan? 1 0 0 0 testCMYKColorThrough def /magenta? 0 1 0 0 testCMYKColorThrough def /yellow? 0 0 1 0 testCMYKColorThrough def /black? 0 0 0 1 testCMYKColorThrough def grestore /isCMYKSep? cyan? magenta? yellow? black? or or or def /customColor? isCMYKSep? not def end } if end defaultpacking setpacking %%EndResource %%BeginResource: procset Adobe_typography_AI5 1.0 1 %%Title: (Typography Operators) %%Version: 1.0 %%CreationDate:(03/26/93) () %%Copyright: ((C) 1987-1993 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_typography_AI5 54 dict dup begin put /initialize { begin begin Adobe_typography_AI5 begin Adobe_typography_AI5 { dup xcheck { bind } if pop pop } forall end end end Adobe_typography_AI5 begin } def /terminate { currentdict Adobe_typography_AI5 eq { end } if } def /modifyEncoding { /_tempEncode exch ddef /_pntr 0 ddef { counttomark -1 roll dup type dup /marktype eq { pop pop exit } { /nametype eq { _tempEncode /_pntr dup load dup 3 1 roll 1 add ddef 3 -1 roll put } { /_pntr exch ddef } ifelse } ifelse } loop _tempEncode } def /TE { StandardEncoding 256 array copy modifyEncoding /_nativeEncoding exch def } def % /TZ { dup type /arraytype eq { /_wv exch def } { /_wv 0 def } ifelse /_useNativeEncoding exch def pop pop findfont _wv type /arraytype eq { _wv makeblendedfont } if dup length 2 add dict begin mark exch { 1 index /FID ne { def } if cleartomark mark } forall pop /FontName exch def counttomark 0 eq { 1 _useNativeEncoding eq { /Encoding _nativeEncoding def } if cleartomark } { /Encoding load 256 array copy modifyEncoding /Encoding exch def } ifelse FontName currentdict end definefont pop } def /tr { _ax _ay 3 2 roll } def /trj { _cx _cy _sp _ax _ay 6 5 roll } def /a0 { /Tx { dup currentpoint 3 2 roll tr _psf newpath moveto tr _ctm _pss } ddef /Tj { dup currentpoint 3 2 roll trj _pjsf newpath moveto trj _ctm _pjss } ddef } def /a1 { /Tx { dup currentpoint 4 2 roll gsave dup currentpoint 3 2 roll tr _psf newpath moveto tr _ctm _pss grestore 3 1 roll moveto tr sp } ddef /Tj { dup currentpoint 4 2 roll gsave dup currentpoint 3 2 roll trj _pjsf newpath moveto trj _ctm _pjss grestore 3 1 roll moveto tr jsp } ddef } def /e0 { /Tx { tr _psf } ddef /Tj { trj _pjsf } ddef } def /e1 { /Tx { dup currentpoint 4 2 roll gsave tr _psf grestore 3 1 roll moveto tr sp } ddef /Tj { dup currentpoint 4 2 roll gsave trj _pjsf grestore 3 1 roll moveto tr jsp } ddef } def /i0 { /Tx { tr sp } ddef /Tj { trj jsp } ddef } def /i1 { W N } def /o0 { /Tx { tr sw rmoveto } ddef /Tj { trj swj rmoveto } ddef } def /r0 { /Tx { tr _ctm _pss } ddef /Tj { trj _ctm _pjss } ddef } def /r1 { /Tx { dup currentpoint 4 2 roll currentpoint gsave newpath moveto tr _ctm _pss grestore 3 1 roll moveto tr sp } ddef /Tj { dup currentpoint 4 2 roll currentpoint gsave newpath moveto trj _ctm _pjss grestore 3 1 roll moveto tr jsp } ddef } def /To { pop _ctm currentmatrix pop } def /TO { iTe _ctm setmatrix newpath } def /Tp { pop _tm astore pop _ctm setmatrix _tDict begin /W { } def /h { } def } def /TP { end iTm 0 0 moveto } def /Tr { _render 3 le { currentpoint newpath moveto } if dup 8 eq { pop 0 } { dup 9 eq { pop 1 } if } ifelse dup /_render exch ddef _renderStart exch get load exec } def /iTm { _ctm setmatrix _tm concat 0 _rise translate _hs 1 scale } def /Tm { _tm astore pop iTm 0 0 moveto } def /Td { _mtx translate _tm _tm concatmatrix pop iTm 0 0 moveto } def /iTe { _render -1 eq { } { _renderEnd _render get dup null ne { load exec } { pop } ifelse } ifelse /_render -1 ddef } def /Ta { pop } def /Tf { dup 1000 div /_fScl exch ddef % selectfont } def /Tl { pop 0 exch _leading astore pop } def /Tt { pop } def /TW { 3 npop } def /Tw { /_cx exch ddef } def /TC { 3 npop } def /Tc { /_ax exch ddef } def /Ts { /_rise exch ddef currentpoint iTm moveto } def /Ti { 3 npop } def /Tz { 100 div /_hs exch ddef iTm } def /TA { pop } def /Tq { pop } def /Th { pop pop pop pop pop } def /TX { pop } def /Tk { exch pop _fScl mul neg 0 rmoveto } def /TK { 2 npop } def /T* { _leading aload pop neg Td } def /T*- { _leading aload pop Td } def /T- { _hyphen Tx } def /T+ { } def /TR { _ctm currentmatrix pop _tm astore pop iTm 0 0 moveto } def /TS { currentfont 3 1 roll /_Symbol_ _fScl 1000 mul selectfont 0 eq { Tx } { Tj } ifelse setfont } def /Xb { pop pop } def /Tb /Xb load def /Xe { pop pop pop pop } def /Te /Xe load def /XB { } def /TB /XB load def currentdict readonly pop end setpacking %%EndResource %%BeginResource: procset Adobe_screens_AI5 1.2 0 %%Title: (Adobe Illustrator (R) Version 5.0 Custom Halftone Screens ProcSet) %%Version: 1.2 0 %%CreationDate: (03/24/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking systemdict begin userdict /Adobe_screens_AI5 15 dict dup begin put /initialize { Adobe_screens_AI5 begin /screenid deviceDPI 600 gt composite? not or { -1 } { deviceDPI currentScreenFreq dup dup 60 ge exch 150 le and deviceDPI 300 le and { pop 60 } if div 1.41421 div 0.5 add cvi } ifelse def 2 screenid eq { /customsize 16 def /customdata /customdata2 def setcustomscreen } if 3 screenid eq { /customsize 24 def /customdata /customdata3 def setcustomscreen } if 4 screenid eq { /customsize 16 def /customdata /customdata4 def setcustomscreen } if 5 screenid eq { /customsize 20 def /customdata /customdata5 def setcustomscreen } if 6 screenid eq { /customsize 24 def /customdata /customdata6 def setcustomscreen } if 7 screenid eq { /customsize 28 def /customdata /customdata7 def setcustomscreen } if 8 screenid eq { /customsize 16 def /customdata /customdata8 def setcustomscreen } if } def /terminate { currentdict Adobe_screens_AI5 eq { end } if } def /setcustomscreen { deviceDPI customsize div 0 { 1 add 2 div customsize mul cvi exch 1 add 2 div customsize mul cvi exch customsize mul add customdata load exch get 256 div } setscreen } def /customdata2 28 28 mul string def currentfile customdata2 readhexstring 4180E8694988E2634382EA6B4B8AE061A01939C8A81737C2A21B3BCAAA1636C0 F8795998F6775796FA7B5B9AF57656952ED8B80727D6B60F2FDABA0626D5B50E 4E8DE6674786EE6F4F8EE5664685ED6EAD1434C6A61F3FCEAE1232C5A51E3ECD F3745493FE7F5F9EF1725291FD7E5E9D24D3B30C2CDEBE0222D1B10A2ADDBD04 4483EB6C4C8BE1624281E96A4A89E364A31C3CCBAB1535C1A11A3AC9A91838C3 FB7C5C9BF4755594F97A5A99F778589730DBBB0525D4B40D2DD9B90828D7B710 508FE4654584EC6D4D8CE7684887EF70AF1131C4A41D3DCCAC1333C7A72040CF F0715190FC7D5D9CF2735392FF80609F21D0B00929DCBC0323D2B20B2BDFBF01 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata3 28 28 mul string def currentfile customdata3 readhexstring 011DC7F5E73D0421CBF3E43A021EC8F6E83E0522CCF2E43A2B648BC4A0762F68 8AC39E732C658CC5A177306989C29D72D5B6521A6192D9B55219608FD6B6531B 6193DAB451185F8FFCEE440C28D2FCED430B27D1FDEF450C29D3FBEC420A26D0 BEA77D366F83BCA77C356E87BFA87E377082BBA67B346D86145B99E0AE4A1259 98DFB14E155C9AE1AD4A115897DEB04D0623CDF4E63C0420CAF8EA400723CDF4 E53B031FC9F7E93F316988C19F752E678EC6A378326A88C09F742D668DC6A278 DBB350175E91D8B8551C6395DCB24F165D90D7B7541C6294FAEC420925CFFFF1 470E2BD5F9EB410824CEFEF0460D2AD4BAA57A336C85BEAA80397180B9A47933 6B84BDA97F387181105797DDAF4C145A9CE3AB480F5696DDAE4B13599BE2AC49 021EC8F6E83E0522CCF2E43A011DC7F5E73D0421CBF3E43A2C658CC5A1773069 89C29D722B648BC4A0762F688AC39E73D6B6531B6193DAB451185F8FD5B6521A 6192D9B55219608FFDEF450C29D3FBEC420A26D0FCEE440C28D2FCED430B27D1 BFA87E377082BBA67B346D86BEA77D366F83BCA77C356E87155C9AE1AD4A1158 97DEB04D145B99E0AE4A125998DFB14E0723CDF4E53B031FC9F7E93F0623CDF4 E63C0420CAF8EA40326A88C09F742D668DC6A278316988C19F752E678EC6A378 DCB24F165D90D7B7541C6294DBB350175E91D8B8551C6395F9EB410824CEFEF0 460D2AD4FAEC420925CFFFF1470E2BD5B9A479336B84BDA97F387181BAA57A33 6C85BEAA803971800F5696DDAE4B13599BE2AC49105797DDAF4C145A9CE3AB48 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata4 28 28 mul string def currentfile customdata4 readhexstring 1139B8E0FAD2531B133BBAE2F8D05119417180A6AE9A7B4B437382A5AD987949 C08867272F6F92CAC28A66262E6E90C8E8DE5F070F37B6F2EADD5E060E36B5F0 FED6571F173FBEE6FDD5561E163EBDE5AB9E7F4F477786A1A99D7E4E467685A3 2C6C96CEC68E62222A6A95CDC58D64240C34B3F6EED95A020A32B1F5EDDB5C04 143CBBE3F9D1521A123AB9E1FBD3541C447483A4AC997A4A427281A7AF9B7C4C C38B65252D6D91C9C1896828307093CBEBDC5D050D35B4F1E9DF60081038B7F3 FCD4551D153DBCE4FFD758201840BFE7A89C7D4D457584A2AA9F8050487887A0 296994CCC48C63232B6B97CFC78F61210931B0F4ECDA5B030B33B2F7EFD85901 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata5 28 28 mul string def currentfile customdata5 readhexstring 010B34C3EBFCF7CE3F16020C35C4EDFBF6CD3E15102552A4D6EADDB5632B1126 54A5D5EADCB3622A3958768499C19E8C7C5E3A59778498C19D8B7B5DC8A99370 47334C7587AFC9AA936F46324B7485AEF1E5BC6B1E0A2351A3D8F2E4BC6A1E09 2351A2D7FFF9D14219050F38C6EFFEF9D04118040E37C6EFE8E0B7662D142856 A8D3E7DFB7652D132856A7D4BF9C8E7F603D5B7A8195BE9A8E7E603C5B798297 314A7389B2CCAD906D442F497289B1CBAC926E4508214FA1DBF4E2B9671B0720 4EA0DAF4E3BA691C030D36C5EDFBF6CD3F16010C34C3ECFDF8CF4017122654A6 D4E9DDB4622A112553A5D6EBDEB5642C3B59788397C09C8B7C5D3A58778599C2 9E8C7D5FCAAB926E46314B7486AFC8AA947048334D7587B0F2E4BB691D082250 A1D8F1E6BD6B1F0A2452A3D9FDF8CF4118030E36C5EEFFFAD1421A050F38C7F0 E6DFB6642C132755A7D3E8E1B8662E152957A8D2BE9A8D7E5F3B5A798296BF9B 8F80613D5C7B80952F487188B1CAAC916D443049728AB3CCAE906C43061F4D9F DAF3E2BA681C07214FA0DBF5E1B8671A00000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata6 28 28 mul string def currentfile customdata6 readhexstring 081A44B6E0F2FDECC150250C091B45B6E1F3FCEBC04F240C1D336199C7D8DCD3 A56C37221E33619AC8D7DBD2A46B36214864798091AEB1958C7E694C49657A81 90ADB0948B7D684BB99D8475593C405C7888A1BEBA9E8574583B3F5B7888A0BD E4CBAA712E1215326098CFE8E4CCA9712D1114315F97CEE7F5F1C6552B040719 43B5DFFAF6F0C6542A03061842B4DEF9FFEDC352270E0B1C47B8E3F4FEECC251 260D0A1C46B7E2F4DAD5A76E39232035639CCAD5D9D4A66D38231F34629BC9D6 AF938E806A4E4A677C838FABAE928D7F694D4A667B828FAC3E5A778AA3BFBC9F 8772563A3D597689A2BEBB9F8673573A14305E97D1EAE6CDA76F2B0F132F5D96 D0E9E5CDA8702C10051742B3DDFCF8EEC4522801041641B2DDFBF7EFC5532902 091B45B6E1F3FCEBC04F240C081A44B6E0F2FDECC150250C1E33619AC8D7DBD2 A46B36211D336199C7D8DCD3A56C372249657A8190ADB0948B7D684B48647980 91AEB1958C7E694CBA9E8574583B3F5B7888A0BDB99D8475593C405C7888A1BE E4CCA9712D1114315F97CEE7E4CBAA712E1215326098CFE8F6F0C6542A030618 42B4DEF9F5F1C6552B04071943B5DFFAFEECC251260D0A1C46B7E2F4FFEDC352 270E0B1C47B8E3F4D9D4A66D38231F34629BC9D6DAD5A76E39232035639CCAD5 AE928D7F694D4A667B828FACAF938E806A4E4A677C838FAB3D597689A2BEBB9F 8673573A3E5A778AA3BFBC9F8772563A132F5D96D0E9E5CDA8702C1014305E97 D1EAE6CDA76F2B0F041641B2DDFBF7EFC5532902051742B3DDFCF8EEC4522801 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata7 28 28 mul string def currentfile customdata7 readhexstring 01061B44B7E1F5FEFBE6BD4A210C01071B45B8E1F6FDFBE6BC4A200B09132A54 A7D1EAF5EED9B05D331609142B55A8D2EAF4EED9AF5C32161D2D3D6993C1CBE0 CEC59B7140301E2E3D6A93C0CADFCDC49A713F3047576C7B828DA2B6A48F867E 6F5A48576C7C828CA1B6A38F867E6E59BAAA958A78634E4451667A8498ADBAAB 968977624E4350657A8398ADE3D4C99F7539251A273C6892C2D7E4D4C89E7539 241A273B6891C1D6F8F2DDB460371005122A53A7D0ECF9F2DDB360360F051229 53A6D0EBFFFDE8BE4C220D03081D46B9E3F7FFFCE7BD4B210D02071C46B8E2F7 F3F0DBB15E34180B152C56A9D3E8F3EFDAB05D34170A142C55A9D2E9DFCCC69C 7341321F2F3F6B94BFC9DECCC59C7241311F2E3E6A94BFCAB5A38E8780705B49 596D7D808BA0B4A28D877F6F5B48586D7C818BA043506479859AAFBCAC978876 614C424F64798499AEBBAB968977624D19263B6791C3D8E5D6C79D7337231825 3A6690C3D7E5D5C79E74382304112952A5CFEDFAF0DBB25E350E03102851A5CE ECF9F1DCB25F360E01071B45B8E1F6FDFBE6BC4A200B01061B44B7E1F5FEFBE6 BD4A210C09142B55A8D2EAF4EED9AF5C321609132A54A7D1EAF5EED9B05D3316 1E2E3D6A93C0CADFCDC49A713F301D2D3D6993C1CBE0CEC59B71403048576C7C 828CA1B6A38F867E6E5947576C7B828DA2B6A48F867E6F5ABAAB968977624E43 50657A8398ADBAAA958A78634E4451667A8498ADE4D4C89E7539241A273B6891 C1D6E3D4C99F7539251A273C6892C2D7F9F2DDB360360F05122953A6D0EBF8F2 DDB460371005122A53A7D0ECFFFCE7BD4B210D02071C46B8E2F7FFFDE8BE4C22 0D03081D46B9E3F7F3EFDAB05D34170A142C55A9D2E9F3F0DBB15E34180B152C 56A9D3E8DECCC59C7241311F2E3E6A94BFCADFCCC69C7341321F2F3F6B94BFC9 B4A28D877F6F5B48586D7C818BA0B5A38E8780705B49596D7D808BA0424F6479 8499AEBBAB968977624D43506479859AAFBCAC978876614C18253A6690C3D7E5 D5C79E74382319263B6791C3D8E5D6C79D73372303102851A5CEECF9F1DCB25F 360E04112952A5CFEDFAF0DBB25E350E pop pop /customdata8 28 28 mul string def currentfile customdata8 readhexstring 050F2747B6D6EEF8FEF4DCBC4D2D1507111D375F9EC6E0E9EBE6CCA4653D1F13 2939556F8EA8C1D1D3C3AE9475573B2B4961717D808999B1B39B8B867F73634B B8A090827A6A5A42445C6C7C8492A2BAD8C8AA97785232222434546E8DACCADA F0E2CFA768401A0A0C1C365E9DC5E4F2FAF7DFBF50301802040E2646B5D5EDFC FFF5DDBD4E2E160806102848B7D7EFF9EAE7CDA5663E2014121E38609FC7E1E8 D2C2AF9576583C2C2A3A56708FA9C0D0B29A8A878074644C4A62727E818898B0 435B6B7B8593A3BBB9A19183796959412333536D8CADCBDBD9C9AB9677513121 0B1B355D9CC4E5F3F1E3CEA6673F1909030D2545B4D4ECFDFBF6DEBE4F2F1701 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop end end defaultpacking setpacking %%EndResource %%BeginResource: procset AGM_Gradient_Sep 1.0 0 %%Title: (AGM Gradient Procset) %%Version: 1.0 0 %%CreationDate: (4/26/96) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /AGM_Gradient_Sep 5 dict dup begin put /AGM_Gradient_Sep_private 100 dict def /initialize{ AGM_Gradient_Sep begin AGM_Gradient_Sep_private begin _compositeJob{ initializeSinglePassSeps }{ initializeMultiPassSeps }ifelse initializeSeps AGM_Gradient_private begin /_fillSD newSpotDict def /_rampSD newSpotDict def /_nCustomColorSD nd end AGM_Gradient_Sep_private { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall AGM_Gradient_Sep { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall end currentdict readonly pop end }def /terminate{ currentdict AGM_Gradient_Sep eq{ end }if }def AGM_Gradient_Sep_private begin /initializeSeps{ _noImage not _level2PS not and{ /_whiteBytes 1 makeByte8 pt /knockOut{ 8 setImageParms _whiteBytes /_image load 5 execImage }def /linealFill{ mySave 8 setImageParms _color{ _nCustomColorSD begin cyan magenta yellow black _spotColor{ spot1 begin /tintImage tintValue 1 exch sub makeByte8 def end spot2 begin /tintImage tintValue 1 exch sub makeByte8 def end }if end 4{ makeByte8 4 1 roll }repeat true 4 _nCustomColorSD ncolorimage }{ _nCustomColorSD/black get 1 exch sub makeByte8 _nCustomColorSD bwImage }ifelse myRestore }def }{ /knockOut{ gsave false setoverprint 1 setgray 0 0 1 1 rectfill grestore }def }ifelse /newSpotDict{ 11 dict dup begin /nSpots 2 def /spot1 7 dict def /spot2 7 dict def end }def /initSpotData { begin /name nd /tintImage nd /tintValue nd /spot_C nd /spot_M nd /spot_Y nd /spot_K nd end }def /initSpotDict{ begin /cyanInk false def /magentaInk false def /yellowInk false def /blackInk false def /cyan nd /magenta nd /yellow nd /black nd spot1 initSpotData spot2 initSpotData end }def /copySpotDict{ /_dst xp begin cyanInk magentaInk yellowInk blackInk cyan magenta yellow black spot1 spot2 end _dst begin /spot1 spot1 maxlength dict def /spot2 spot2 maxlength dict def spot2 copy pop spot1 copy pop /black xd /yellow xd /magenta xd /cyan xd /blackInk xd /yellowInk xd /magentaInk xd /cyanInk xd end }def /setCustomColor { 1 index /Black eq{ 6 1 roll 5 npop 1 exch sub setgray }{ 6 1 roll _ccAry1 astore exch dup null eq{ pop 0 }if setcustomcolor }ifelse }def /setCStop{ /_colorStyle exch pt _colorStyle 0 eq{ 0 0 0 4 -1 roll 1 exch sub _spotColor{ /_colorStyle 3 pt /Black 1 index 1 exch sub }if }if _colorStyle 2 eq{ 3 npop }if _rampSD _fillSD copySpotDict _colorStyle 4 eq{ pop 9 2 roll 3 npop 6 -2 roll } if _colorStyle 3 eq _colorStyle 4 eq or{ _fillSD begin exch dup spot1/name get eq{ spot1 spot2 }{ spot2 spot1 }ifelse begin begin /name xd 1 exch sub /tintValue xd 4{ tintValue mul 4 1 roll }repeat _spotColor not{ /tintValue null def }if end /tintValue 0 def end end }if _fillSD nsetcustomcolor }def /renderCMYK{ spot1/name get null eq spot2/name get null eq and dup not{ pop spot1 spotConverted }if dup not{ pop spot2 spotConverted }if }def /fill_ /fill load def /fillOvp{ currentoverprint{ _inRipSep{ currentcolorspace 0 get dup /DeviceGray eq 1 index /DeviceCMYK eq or{ pop currentcmykcolor add add add 0 eq{ newpath }if }{ /Separation eq{ currentcolor 0 eq{ newpath }if }if }ifelse }{ currentgray 1 eq{ newpath }if }ifelse }if fill_ }def /fill{ _nCustomColorSD begin renderCMYK { fillOvp }{ spot1 begin gsave name null ne{ spot_C spot_M spot_Y spot_K name tintValue setCustomColor }{ 1 setgray }ifelse fillOvp grestore end spot2 begin name null ne{ gsave true setoverprint spot_C spot_M spot_Y spot_K name tintValue setCustomColor fillOvp grestore }if end newpath }ifelse end }def /expandSpot{ _spotColor{ /_len xp _rampSD begin spot1 begin tintImage null ne{ tintImage _len expandOne /tintImage xd }if end spot2 begin tintImage null ne{ tintImage _len expandOne /tintImage xd }if end end }{ pop }ifelse }def /rampImage{ _rampSD begin _color{ /cyanInk _cyanData 0 ne def /magentaInk _magentaData 0 ne def /yellowInk _yellowData 0 ne def /blackInk _blackData 0 ne def _nSamples setImageParms _nSamples expandSpot _cyanData _magentaData _yellowData _blackData _nSamples 4 expandColor true 4 _rampSD ncolorimage }{ /cyanInk false def /magentaInk false def /yellowInk false def /blackInk true def _nSamples setImageParms _blackData _rampSD bwImage }ifelse end }def /nsetcustomcolor where{ pop }{ /nsetcustomcolor { /_nCustomColorSD xp _nCustomColorSD begin 4 copy /black xd /yellow xd /magenta xd /cyan xd 4 copy 0 ne /blackInk xd 0 ne /yellowInk xd 0 ne /magentaInk xd 0 ne /cyanInk xd end setcmykcolor }def }ifelse /nsetcustomcolorend where{ pop }{ /nsetcustomcolorend { /_nCustomColorSD null pt }def }ifelse }def /initializeSinglePassSeps{ /_decodeNorm [0 1] pt /_decodeInvert [1 0] pt /spotConverted { begin name null eq{ false }{ tintValue null eq tintImage null eq and{ true }{ false currentpagedevice/SeparationOrder get{name eq or}forall not }ifelse }ifelse end }def /dictImage { 20 dict dup begin /Dict xd /Decode xd /DataSource xd /ImageMatrix xd /BitsPerComponent xd /Height xd /Width xd /ImageType 1 def Dict end /_image load 1 execImage }def /bwImage{ begin gsave currentoverprint{ blackInk{ [/Separation /Black /DeviceGray{}] setcolorspace _decodeInvert dictImage }{ 5 npop }ifelse }{ /DeviceGray setcolorspace _decodeNorm dictImage }ifelse grestore end }def /ncolorimage where{ pop }{ /ncolorimage{ begin renderCMYK { cyanInk magentaInk and yellowInk and blackInk and not currentoverprint and { pop pop gsave cyanInk{ 8 copy [/Separation /Cyan /DeviceGray{}] setcolorspace 3 npop _decodeNorm dictImage }if magentaInk{ 8 copy [/Separation /Magenta /DeviceGray{}] setcolorspace 4 -1 roll 3 npop _decodeNorm dictImage }if yellowInk{ 8 copy [/Separation /Yellow /DeviceGray{}] setcolorspace 4 -2 roll 3 npop _decodeNorm dictImage }if blackInk{ 4 -3 roll [/Separation /Black /DeviceGray{}] setcolorspace 3 npop _decodeNorm dictImage }{ 8 npop }ifelse grestore }{ /_colorimage load 10 execImage }ifelse }{ 6 npop gsave spot1 begin name null ne tintImage null ne and{ [/Separation name /DeviceGray{}] setcolorspace 4 copy tintImage name /Black eq{ _decodeNorm }{ _decodeInvert }ifelse dictImage }{ 1 setgray fill }ifelse end spot2 begin true setoverprint name null ne tintImage null ne and{ [/Separation name /DeviceGray{}] setcolorspace tintImage name /Black eq{ _decodeNorm }{ _decodeInvert }ifelse dictImage }{ 4 npop 1 setgray fill }ifelse end grestore }ifelse end }def }ifelse }def /initializeMultiPassSeps{ /_isCMYKSep _cyanPlate _magentaPlate or _yellowPlate or _blackPlate or pt /invertXfer{ [ { 1 exch sub }/exec load systemdict /currenttransfer get exec /exec load ] cvx systemdict /settransfer get exec }def /ccThrough{ gsave 1 setCustomColor currentcmykcolor grestore add add add 0 ne }def /spotConverted { begin _isCMYKSep not{ false }{ name null eq{ false }{ tintValue null eq tintImage null eq and{ true }{ spot_C spot_M spot_Y spot_K name ccThrough }ifelse }ifelse }ifelse end }def /spotChannel { _isCMYKSep{ pop false }{ begin name null eq{ false }{ spot_C spot_M spot_Y spot_K name ccThrough }ifelse end }ifelse }def /getChannelData { _isCMYKSep dup{ pop renderCMYK }if { _blackPlate{ 4 1 roll 3 npop blackInk }{ _yellowPlate{ 4 2 roll 3 npop yellowInk }{ _magentaPlate{ 4 3 roll 3 npop magentaInk }{ 3 npop cyanInk }ifelse }ifelse }ifelse { true /nonZeroData }{ true /zeroData }ifelse }{ 4 npop spot1/name get null ne spot1 spotChannel and{ spot1/tintImage get dup null ne{ false /nonZeroData }{ pop false /noData }ifelse }{ spot2/name get null ne spot2 spotChannel and{ spot2/tintImage get dup null ne{ false /nonZeroData }{ pop false /noData }ifelse }{ false /noData }ifelse }ifelse }ifelse }def /renderChannelData { /_tmp xp _tmp /nonZeroData ne currentoverprint and{ pop _tmp /zeroData eq{pop}if 4 npop }{ _tmp /nonZeroData eq{ { invertXfer }if systemdict/image get 5 execImage }{ pop _tmp /zeroData eq{pop}if 4 npop knockOut }ifelse }ifelse }def /bwImage{ begin gsave dup dup dup getChannelData exch pop false exch renderChannelData grestore end }def /ncolorimage{ begin pop pop gsave spot2/name get null ne spot2 spotChannel and{ true setoverprint }if getChannelData renderChannelData grestore end }def }def end end defaultpacking setpacking %%EndResource %%BeginResource: procset AGM_Gradient 1.0 0 %%Title: (AGM Gradient Procset) %%Version: 1.0 0 %%CreationDate: (4/26/96) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /AGM_Gradient 20 dict dup begin put /AGM_Gradient_private 200 dict def /initialize { AGM_Gradient begin AGM_Gradient_private begin initializeVars /bd systemdict/mark get def /ed _level2PS { (>>) }{ (counttomark 2 idiv dup dict begin {def} repeat pop currentdict end) } ifelse cvx def _level2PS{ initializeLev2 }{ initializeLev1 }ifelse queryDevice initializeShading initializeOps _producingSeps{ AGM_Gradient_Sep/initialize get exec }{ initializeComposite }ifelse _illustrator{ /f{}def /F{}def /s{}def /S{}def /b{}def /B{}def }if /image where{ /image get /_image xd }if /colorimage where{ /colorimage get /_colorimage xd }if /rectfill where dup{ exch pop not _producingSeps or }{ not }ifelse { /rectfill{ gsave newpath 4 2 roll moveto 1 index 0 rlineto 0 1 index rlineto 1 index neg 0 rlineto pop pop closepath fill grestore }def }if /linealImage _noImage{ /rectImage load }{ _producingSeps{ AGM_Gradient_Sep/AGM_Gradient_Sep_private get begin /rampImage load end }{ /rampImage load }ifelse }ifelse def AGM_Gradient_private { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall AGM_Gradient { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall end currentdict readonly pop end }def /initializeAI { pop pop AGM_Gradient/AGM_Gradient_private get /_illustrator true put AGM_Gradient/initialize get exec AGM_Gradient begin }def /unload{ systemdict/languagelevel known{ systemdict/languagelevel get 2 ge{ userdict/AGM_Gradient_Sep 2 copy known{ undef }{ pop pop }ifelse userdict/AGM_Gradient 2 copy known{ undef }{ pop pop }ifelse }if }if }def /terminate{ currentdict AGM_Gradient eq{ end }if }def AGM_Gradient_private begin /initializeVars{ /_d255 256 array def 0 1 255{ _d255 exch dup 255 div put }bind for /_d255- 256 array def 0 1 255{ _d255- exch 1 _d255 2 index get sub put }bind for /_sSave nd /_dUserSpace matrix defaultmatrix def /_bUMatrix matrix def /_imageMatrix matrix def /_saveMatrix matrix def /_xm matrix def /_ccAry1 5 array def /_level2PS systemdict/languagelevel known dup{ pop systemdict/languagelevel get 2 ge }if def /_level3PS _level2PS systemdict/shfill known and def currentdict /_illustrator known not{ /_illustrator false def }if }def /initializeOps { AGM_Gradient begin currentdict/Bc known not{ /Bc{ _renderFlag 2 eq{ 6 npop }{ pushBSpace _rampIndex 0 eq{ pop pop setCStop }if linealFill popBSpace }ifelse }def }if currentdict/Bg known not{ /Bg{ 10 npop /_gradName xp /_renderFlag xp _renderFlag 2 ne{ _illustrator{ _of setoverprint }if _illustrator _eo and _renderFlag 3 eq or{ eoclip }{ clip }ifelse _gradNames _gradName 2 copy known{ get mark exch aload pop /_gradType xp 1 sub dup /_rampIndex xp /_maxRampIndex xp mark exch aload pop 0 0 }if pop pop getRampData }{ mark mark }ifelse }def }if currentdict/Bm known not{ /Bm{ _renderFlag 2 ne{ _gradType 0 eq{ linealRamp }{ radialGrad }ifelse }{ 6 npop }ifelse }def }if currentdict/Bh known not{ /Bh{ 2 npop /_yHi xp /_xHi xp /_radHilite _xHi 0 ne _yHi 0 ne or pt }def }if currentdict/Bn known not{ /Bn{ AGM_Gradient_private begin dict /_gradNames xp end }def }if currentdict/Bd known not{ /Bd{ AGM_Gradient begin AGM_Gradient_private begin /_nColorsBd xp /_gradType xp /_gradName xp }def }if currentdict/BD known not{ /BD{ currentdict/_gradNames known not{ /_gradNames 20 dict def }if ] _nColorsBd _gradType ] _gradName exch /_gradNames xput end end }def }if currentdict/Bb known not{ /Bb{ AGM_Gradient begin AGM_Gradient_private begin _producingSeps{ AGM_Gradient_Sep/AGM_Gradient_Sep_private get begin }if mySave }def }if currentdict/BB known not{ /BB{ /_tmp xp cleartomark cleartomark _tmp dup _renderFlag myRestore _producingSeps{ end }if _illustrator end end { 2 ne exch 0 gt and{ 2 eq{ s }{ S }ifelse }{ pop newpath }ifelse }{ pop newpath }ifelse }def }if currentdict/Xm known not{ /Xm{ _xm astore pop }def }if end }def /queryDevice{ /_inRipSep _level2PS{ currentpagedevice/Separations 2 copy known{ get }{ pop pop false }ifelse }{ false }ifelse def /_noImage /lv1Fix where{ pop lv1Fix }{ false }ifelse def /_useShells where{ pop }{ /_useShells true def }ifelse /_useSmoothShade where{ pop }{ /_useSmoothShade false def }ifelse /_cyanPlate 1 0 0 0 testCMYKColorThrough def /_magentaPlate 0 1 0 0 testCMYKColorThrough def /_yellowPlate 0 0 1 0 testCMYKColorThrough def /_blackPlate 0 0 0 1 testCMYKColorThrough def /_compositeJob _cyanPlate _magentaPlate and _yellowPlate and _blackPlate and def /_compositeSpotDevice where{ pop }{ /_compositeSpotDevice _compositeJob not _inRipSep or{ 1 }{ 0 }ifelse def }ifelse /_producingSeps _compositeSpotDevice 0 ne def /_deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt def /_dpiThreshold where{ pop }{ /_dpiThreshold 600 def }ifelse /_screenFreqThreshold where{ pop }{ /_screenFreqThreshold 150 def }ifelse /_contoneDevice where{ pop }{ /_contoneDevice false def }ifelse /_subSampleOK _deviceDPI _dpiThreshold le currentScreenFreq _screenFreqThreshold le and _contoneDevice not and _producingSeps not and def }def /initializeLev1{ /makeByte8{ /_tmp 0 pt 255 mul cvi 8 string 8{ dup _tmp 3 index put /_tmp _tmp 1 add pt }repeat exch pop }def /currentScreenFreq{ currentscreen pop pop }def /_byte 1 string def /colorimage where{ pop }{ /colorimage{ pop pop /_blackTmp xp /_yellowTmp xp /_magentaTmp xp /_cyanTmp xp /_cnt 0 pt [ _byte dup 0 _cyanTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .3 /mul cvx _magentaTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .59 /mul cvx _yellowTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .11 /mul cvx _blackTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx /add cvx /add cvx /add cvx 1 /exch cvx /sub cvx /dup cvx 0 /lt cvx{ pop 0 }/if cvx /dup cvx 1 /gt cvx{ pop 1 }/if cvx 255 /mul cvx /cvi cvx 256 /mod cvx /dup cvx 0 /lt cvx{ pop 0 }/if cvx /put cvx /_cnt dup cvx 1 /add cvx /pt cvx ] cvx bind /_image load 5 execImage }def }ifelse }def /initializeLev2{ /level2ScreenFreq{ begin 60 HalftoneType 1 eq{ pop Frequency }if HalftoneType 2 eq{ pop GrayFrequency }if HalftoneType 5 eq{ pop Default level2ScreenFreq }if end }def /currentScreenFreq{ currenthalftone level2ScreenFreq }def }def /initializeShading{ _useSmoothShade _level3PS and{ /_usingSmoothShade true pt initializeLev3_Ops }{ /_usingSmoothShade false pt }ifelse }def /initializeLev3_Ops { /initShFill{ /_index _gradType 0 eq {0}{_maxRampIndex 1 sub} ifelse pt /_rampFuncsArray _maxRampIndex array pt /_boundsArray _maxRampIndex 1 sub array pt /_encodeArray _maxRampIndex 2 mul array pt /_beginCoord _rampPoint pt /_colorSpace null pt /_firstFill _rampIndex _maxRampIndex eq pt /_lastFill false pt }def /getRampColorSpace{ _nSamples 1 gt{ /_ndx 0 pt [blendColor] cvx exec }if /_C0 [currentcolor] pt /_C0_Space currentcolorspace pt _nSamples 1 gt{ /_ndx _nSamples 1 sub pt [blendColor] cvx exec }if /_C1 [currentcolor] pt /_C1_Space currentcolorspace pt _C0_Space _C1_Space eq{ /_rampColorSpace _C0_Space pt }{ (colorspace conflict!) == showpage stop }ifelse _spotColor{ nsetcustomcolorend }if }def /linealShFill{ popBSpace _xm aload pop pushBSpace /_size _index 1 add pt _size _maxRampIndex lt { /_rampFuncsArray _rampFuncsArray 0 _size getinterval pt /_boundsArray _boundsArray 0 _size 1 sub getinterval pt /_encodeArray _encodeArray 0 _size 2 mul getinterval pt }if bd /ShadingType 2 /ColorSpace _colorSpace /Function bd /FunctionType 3 /Domain [0 1] /Functions _rampFuncsArray /Bounds _boundsArray /Encode _encodeArray ed /Extend [_firstFill _lastFill] /Domain [0 1] /Coords [_beginCoord 0 _endCoord 0] ed shfill }def /radialShFill{ /_size _maxRampIndex _index sub pt _size _maxRampIndex lt { /_rampFuncsArray _rampFuncsArray _index _size getinterval pt /_boundsArray _boundsArray _index _size 1 sub getinterval pt /_encodeArray _encodeArray _index 2 mul _size 2 mul getinterval pt }if /_rampLen _beginCoord _endCoord sub pt bd /ShadingType 3 /ColorSpace _colorSpace /Function bd /FunctionType 3 /Domain [0 1] /Functions _rampFuncsArray /Bounds _boundsArray /Encode _encodeArray ed /Extend [_lastFill _firstFill] /Domain [0 1] /Coords [_xHi _rampLen mul _yHi _rampLen mul _endCoord 0 0 _beginCoord] ed shfill _radHilite{ _xHi _rampLen mul _yHi _rampLen mul translate }if }def /fillRamp{ /_invert _midPoint 0.5 lt pt _rampIndex _maxRampIndex eq { initShFill }if getRampColorSpace _colorSpace null eq{ /_colorSpace _rampColorSpace pt }{ _colorSpace _rampColorSpace ne{ /_index _index 1 _gradType 0 eq{ sub pt linealShFill }{ add pt radialShFill }ifelse initShFill /_colorSpace _rampColorSpace pt } if }ifelse /_endCoord _endPoint pt _rampFuncsArray _index bd /FunctionType 2 /Domain [0 1] /N 0.5 log _invert{1 _midPoint sub}{_midPoint}ifelse log div _gradType 0 eq{ _invert{/C1}{/C0}ifelse _C0 _invert{/C0}{/C1}ifelse _C1 }{ _invert{/C0}{/C1}ifelse _C1 _invert{/C1}{/C0}ifelse _C0 }ifelse ed put _rampIndex 1 ne{ _boundsArray _index _gradType 1 eq{1 sub}if _endCoord put } if 0 1 _invert {exch}if _encodeArray _index 2 mul 1 add 3 -1 roll put _encodeArray _index 2 mul 3 -1 roll put _rampIndex 1 eq { /_lastFill true pt _gradType 0 eq{ linealShFill }{ radialShFill }ifelse }if /_index _index 1 _gradType 0 eq{ add pt }{ sub pt }ifelse }def /radialRamp /fillRamp load def /rampImage /fillRamp load def AGM_Gradient begin /Bc{ 6 npop }def end }def /initializeComposite{ /bwImage{ pop /_image load 5 execImage }def currentdict/rampImage known not{ /rampImage{ _color{ _nSamples setImageParms _rgbRamp{ _redData _greenData _blueData _nSamples 3 expandColor true 3 null ncolorimage }{ _cyanData _magentaData _yellowData _blackData _nSamples 4 expandColor true 4 null ncolorimage }ifelse }{ _nSamples setImageParms _blackData null bwImage }ifelse }def }if /setCStop{ /_colorStyle exch pt _colorStyle 0 eq{ 1 exch sub 0 0 0 4 -1 roll }if _colorStyle 2 eq{ setrgbcolor 4 npop }if _colorStyle 3 eq{ 1 exch sub /_tmp xp pop 4{ _tmp mul 4 1 roll }repeat }if _colorStyle 4 eq{ 3 -1 roll pop pop 1 exch sub /_tmp xp 3{ 1 exch sub _tmp mul 1 exch sub 3 1 roll }repeat setrgbcolor 4 npop }if _colorStyle 2 ne _colorStyle 4 ne and{ null nsetcustomcolor }if }def /nsetcustomcolor { pop setcmykcolor }def /nsetcustomcolorend { }def /ncolorimage{ pop /_colorimage load 10 execImage }def _noImage not _level2PS not and{ /linealFill{ 8 setImageParms _color{ currentcmykcolor 4{ makeByte8 4 1 roll }repeat true 4 null ncolorimage }{ currentgray makeByte8 null bwImage }ifelse }def }if }def /npop{ {pop}repeat }def /xd{ exch def }def /nd{ null def }def /pt{ AGM_Gradient_private 3 1 roll put }def /xp{ exch pt }def /xput{ dup load dup length exch maxlength eq{ dup dup load dup length 2 mul dict copy def }if load begin def end }def /mySave{ save /_sSave xp }def /myRestore{ _sSave type /savetype eq{ _sSave restore }if }def /gMark{ counttomark 2 add -1 roll }def /execImage{ /_tmp xp { exec }stopped{ $error /errorname get /undefinedresult ne{ stop }{ _tmp npop }ifelse }if }def /pushBSpace{ newpath gsave _bUMatrix astore concat }def /popBSpace{ grestore }def /setImageParms{ 1 8 2 index 0 0 1 0 0 _imageMatrix astore }def /linealFill{ 0 0 1 1 rectfill }def /testCMYKColorThrough{ gsave setcmykcolor currentcmykcolor grestore add add add 0 ne }def /expandOne { /_tmp xp dup type /stringtype ne{ _tmp string exch dup 0 ne{ 255 mul cvi 0 1 _tmp 1 sub{ 3 copy exch put pop }for }if pop }if }def /expandColor{ /_channels xp /_len xp _channels{ _len expandOne _channels 1 roll }repeat }def /blendColor{ _color{ _rgbRamp _producingSeps not and{ _redData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _greenData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _blueData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if /setrgbcolor cvx }{ _cyanData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _magentaData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _yellowData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _blackData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _spotColor{ _rampSD begin /_rampSD cvx /begin cvx spot1 begin tintImage dup type /stringtype eq{ /_ndx cvx /get cvx _d255- /exch cvx /get cvx }{ dup null ne{ name type /nametype ne{ 1 exch sub }if }if }ifelse end /spot1 cvx /tintValue 3 -1 /roll cvx /put cvx spot2 begin tintImage dup type /stringtype eq{ /_ndx cvx /get cvx _d255- /exch cvx /get cvx }{ dup null ne{ name type /nametype ne{ 1 exch sub }if }if }ifelse end /spot2 cvx /tintValue 3 -1 /roll cvx /put cvx /end cvx end /_rampSD cvx /nsetcustomcolor cvx }{ /setcmykcolor cvx }ifelse }ifelse }{ _blackData /_ndx cvx /get cvx _d255 /exch cvx /get cvx _usingSmoothShade{ 1 /exch cvx /sub cvx 0 0 0 4 -1 /roll cvx /setcmykcolor cvx }{ /setgray cvx }ifelse }ifelse }def /linealRamp{ pushBSpace _ramp{ linealImage }{ linealFill }ifelse popBSpace /_rampIndex _rampIndex 1 sub pt _rampIndex 0 gt{ getRampData }if }def /radialGrad{ /_firstShell true pt _usingSmoothShade not{ fill }if pushBSpace _radHilite{ _xHi _yHi _bUMatrix idtransform /_yHi xp /_xHi xp _rampPoint 1 lt{ 1 _rampPoint sub dup _xHi mul exch _yHi mul translate }if }if _rampIndex{ radialRamp /_rampIndex _rampIndex 1 sub pt _rampIndex 0 gt{ getRampData }if }repeat popBSpace }def /getNSamples{ 0 exch { dup type /stringtype eq{ length exch pop exit }if pop }forall dup 0 eq{ pop 1 }if }def /getRampData{ /_rampType gMark pt /_color _rampType 0 gt pt /_ccRGB _rampType 5 eq _rampType 6 eq or pt /_rgbRamp _rampType 4 eq _ccRGB or pt /_ccProcess _rampType 2 eq _rampType 3 eq or pt _producingSeps{ _rampSD initSpotDict /_spotColor _ccProcess _ccRGB or pt }{ /_spotColor false pt }ifelse /_ramp true pt 100 div /_rampPoint xp 100 div /_midPoint xp dup /_colorStyle xp _colorStyle 0 eq{ 2 }{ _colorStyle 1 eq{ 5 }{ _colorStyle 2 eq{ 8 }{ _colorStyle 3 eq{ _producingSeps{ _rampSD begin spot1 begin /name 3 index def /spot_K 4 index def /spot_Y 5 index def /spot_M 6 index def /spot_C 7 index def end end }if 7 }{ _producingSeps{ _rampSD begin spot1 begin /name 4 index def /spot_K 8 index def /spot_Y 9 index def /spot_M 10 index def /spot_C 11 index def end end }if 11 } ifelse }ifelse }ifelse }ifelse /_tmp xp _tmp index 100 div /_endPoint xp _gradType 1 eq{ _tmp 1 add index 100 div /_midPoint xp }if _producingSeps{ _tmp 2 add index /_nextColorStyle xp _nextColorStyle 3 eq{ /_tmp _tmp 4 add pt _tmp index dup _rampSD begin spot1 /name get ne{ spot2 begin /name xd /spot_K _tmp 2 add index def /spot_Y _tmp 3 add index def /spot_M _tmp 4 add index def /spot_C _tmp 5 add index def end }{ pop }ifelse end }if _nextColorStyle 4 eq{ /_tmp _tmp 5 add pt _tmp index dup _rampSD begin spot1 /name get ne{ spot2 begin /name xd /spot_K _tmp 5 add index def /spot_Y _tmp 6 add index def /spot_M _tmp 7 add index def /spot_C _tmp 8 add index def end }{ pop }ifelse end }if }if _rampType 3 eq _rampType 6 eq or{ /_tint2Data gMark pt }if _ccProcess _ccRGB or{ /_tint1Data gMark pt }if _rgbRamp{ /_blueData gMark pt /_greenData gMark pt /_redData gMark pt }if _producingSeps{ _rampSD begin _ccProcess _ccRGB or{ _rampType 3 eq _rampType 6 eq or{ spot2 begin /tintImage _gradType 0 eq{ _tint2Data }{ _tint1Data }ifelse def name null eq{ /name /Black def }if end }if spot1 begin /tintImage _gradType 0 eq _rampType 2 eq or _rampType 5 eq or{ _tint1Data }{ _tint2Data }ifelse def _rampType 2 eq _rampType 5 eq or{ name null eq{ /name spot2 /name get def spot2 /name null put }if }{ name null eq{ /name /Black def }if }ifelse end }if end }if /_blackData gMark pt _rampType 0 gt{ counttomark 4 add -3 roll /_yellowData xp /_magentaData xp /_cyanData xp }if _ramp{ /_nSamples [ _rampType 0 eq {_blackData}if _rampType 1 eq {_cyanData _magentaData _yellowData _blackData}if _rampType 2 eq {_cyanData _magentaData _yellowData _blackData _tint1Data}if _rampType 3 eq {_cyanData _magentaData _yellowData _blackData _tint1Data _tint2Data}if _rampType 4 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData}if _rampType 5 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData _tint1Data}if _rampType 6 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData _tint1Data _tint2Data}if ] getNSamples pt _usingSmoothShade not {/_ramp _nSamples 1 gt pt} if } if setCStop }def /rectImage{ gsave /_sInc 1 pt /_bInc 1 _nSamples div pt /_uRampLen 1 0 dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt pt /_pChange _uRampLen 0 eq{0}{_nSamples _uRampLen div}ifelse pt 0 _nSamples [ /dup cvx /_ndx /exch cvx /pt cvx blendColor 0 0 _bInc 1 /rectfill cvx _bInc 0 /translate cvx _sInc /add cvx ] cvx bind repeat pop _spotColor{ nsetcustomcolorend }if grestore }def /radialInit{ /_nRadSamples _nSamples dup 0 eq{pop 1}if pt /_sInc -1 pt /_rampLen _rampPoint _endPoint sub pt /_bInc _rampLen _nSamples div neg pt /_optimize false pt _subSampleOK{ /_uRampLen _rampLen 0 dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt 0 _rampLen dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt 2 copy lt{ exch }if pop pt /_pChange _uRampLen 0 eq{ 0 }{ _nSamples _uRampLen div }ifelse pt _pChange .5 gt dup /_optimize xp{ /_nRadSamples _uRampLen 2 div round cvi dup 1 le{pop 2}if pt /_bInc _rampLen _nRadSamples div neg pt /_sInc _nSamples 1 sub _nRadSamples 1 sub div neg pt }if }if _radHilite{ /_xBCInc _xHi _rampLen mul _nRadSamples div pt /_yBCInc _yHi _rampLen mul _nRadSamples div pt }if }def currentdict/radialRamp known not{ /radialRamp{ /_saveMatrix _saveMatrix currentmatrix def radialInit _rampPoint _nSamples 1 sub _nRadSamples [ /dup cvx _optimize{ /round cvx /cvi cvx }if /_ndx /exch cvx /pt cvx _useShells{ /_firstShell cvx{ /_firstShell false pt }{ 0 0 3 index 360 0 arcn fill }/ifelse cvx }if blendColor _useShells{ 0 0 3 /index cvx 0 360 /arc cvx }{ 0 0 3 /index cvx 0 360 /arc cvx /fill cvx }ifelse /exch cvx _bInc /add cvx /exch cvx _sInc /add cvx _radHilite{ _xBCInc _yBCInc /translate cvx }if ] cvx bind repeat pop pop _saveMatrix setmatrix _radHilite{ _xHi _rampLen mul _yHi _rampLen mul translate }if _useShells _rampIndex 1 eq and{ fill }if _spotColor{ nsetcustomcolorend }if }def }if end end defaultpacking setpacking %%EndResource %%BeginProcSet: Adobe_ColorImage_AI6 1.1 0 userdict /Adobe_ColorImage_AI6 known not { userdict /Adobe_ColorImage_AI6 24 dict put } if userdict /Adobe_ColorImage_AI6 get begin /initialize { Adobe_ColorImage_AI6 begin Adobe_ColorImage_AI6 { dup type /arraytype eq { dup xcheck { bind } if } if pop pop } forall } def /terminate { end } def currentdict /Adobe_ColorImage_AI6_Vars known not { /Adobe_ColorImage_AI6_Vars 15 dict def } if Adobe_ColorImage_AI6_Vars begin /channelcount 0 def /sourcecount 0 def /sourcearray 4 array def /plateindex -1 def /XIMask 0 def /XIBinary 0 def /XIChannelCount 0 def /XIBitsPerPixel 0 def /XIImageHeight 0 def /XIImageWidth 0 def /XIImageMatrix null def /XIBuffer null def /XIDataProc null def /XIVersion 6 def end /WalkRGBString null def /WalkCMYKString null def /StuffRGBIntoGrayString null def /RGBToGrayImageProc null def /StuffCMYKIntoGrayString null def /CMYKToGrayImageProc null def /ColorImageCompositeEmulator null def /SeparateCMYKImageProc null def /FourEqual null def /TestPlateIndex null def currentdict /_colorimage known not { /colorimage where { /colorimage get /_colorimage exch def } { /_colorimage null def } ifelse } if /_currenttransfer systemdict /currenttransfer get def /colorimage null def /XI null def /WalkRGBString { 0 3 index dup length 1 sub 0 3 3 -1 roll { 3 getinterval { } forall 5 index exec 3 index } for 5 { pop } repeat } def /WalkCMYKString { 0 3 index dup length 1 sub 0 4 3 -1 roll { 4 getinterval { } forall 6 index exec 3 index } for 5 { pop } repeat } def /StuffRGBIntoGrayString { .11 mul exch .59 mul add exch .3 mul add cvi 3 copy put pop 1 add } def /RGBToGrayImageProc { Adobe_ColorImage_AI6_Vars begin sourcearray 0 get exec dup length 3 idiv string dup 3 1 roll /StuffRGBIntoGrayString load exch WalkRGBString end } def /StuffCMYKIntoGrayString { exch .11 mul add exch .59 mul add exch .3 mul add dup 255 gt { pop 255 } if 255 exch sub cvi 3 copy put pop 1 add } def /CMYKToGrayImageProc { Adobe_ColorImage_AI6_Vars begin sourcearray 0 get exec dup length 4 idiv string dup 3 1 roll /StuffCMYKIntoGrayString load exch WalkCMYKString end } def /ColorImageCompositeEmulator { pop true eq { Adobe_ColorImage_AI6_Vars /sourcecount get 5 add { pop } repeat } { Adobe_ColorImage_AI6_Vars /channelcount get 1 ne { Adobe_ColorImage_AI6_Vars begin sourcearray 0 3 -1 roll put channelcount 3 eq { /RGBToGrayImageProc } { /CMYKToGrayImageProc } ifelse load end } if image } ifelse } def /SeparateCMYKImageProc { Adobe_ColorImage_AI6_Vars begin sourcecount 0 ne { sourcearray plateindex get exec } { sourcearray 0 get exec dup length 4 idiv string 0 2 index plateindex 4 2 index length 1 sub { get 255 exch sub 3 copy put pop 1 add 2 index } for pop pop exch pop } ifelse end } def /FourEqual { 4 index ne { pop pop pop false } { 4 index ne { pop pop false } { 4 index ne { pop false } { 4 index eq } ifelse } ifelse } ifelse } def /TestPlateIndex { Adobe_ColorImage_AI6_Vars begin /plateindex -1 def /setcmykcolor where { pop gsave 1 0 0 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 1 0 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 0 1 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 0 0 1 setcmykcolor systemdict /currentgray get exec 1 exch sub grestore 1 0 0 0 FourEqual { /plateindex 0 def } { 0 1 0 0 FourEqual { /plateindex 1 def } { 0 0 1 0 FourEqual { /plateindex 2 def } { 0 0 0 1 FourEqual { /plateindex 3 def } { 0 0 0 0 FourEqual { /plateindex 5 def } if } ifelse } ifelse } ifelse } ifelse pop pop pop pop } if plateindex end } def /colorimage { Adobe_ColorImage_AI6_Vars begin /channelcount 1 index def /sourcecount 2 index 1 eq { channelcount 1 sub } { 0 } ifelse def 4 sourcecount add index dup 8 eq exch 1 eq or not end { /_colorimage load null ne { _colorimage } { Adobe_ColorImage_AI6_Vars /sourcecount get 7 add { pop } repeat } ifelse } { dup 3 eq TestPlateIndex dup -1 eq exch 5 eq or or { /_colorimage load null eq { ColorImageCompositeEmulator } { dup 1 eq { pop pop image } { Adobe_ColorImage_AI6_Vars /plateindex get 5 eq { gsave 0 _currenttransfer exec 1 _currenttransfer exec eq { 0 _currenttransfer exec 0.5 lt } { 0 _currenttransfer exec 1 _currenttransfer exec gt } ifelse { { pop 0 } } { { pop 1 } } ifelse systemdict /settransfer get exec } if _colorimage Adobe_ColorImage_AI6_Vars /plateindex get 5 eq { grestore } if } ifelse } ifelse } { dup 1 eq { pop pop image } { pop pop Adobe_ColorImage_AI6_Vars begin sourcecount -1 0 { exch sourcearray 3 1 roll put } for /SeparateCMYKImageProc load end systemdict /image get exec } ifelse } ifelse } ifelse } def /XG { pop pop } def /XF { 13 {pop} repeat } def /Xh { Adobe_ColorImage_AI6_Vars begin gsave /XIMask exch 0 ne def /XIImageHeight exch def /XIImageWidth exch def /XIImageMatrix exch def 0 0 moveto XIImageMatrix concat XIImageWidth XIImageHeight scale XIMask { /_lp /null ddef _fc /_lp /imagemask ddef } if /XIVersion 7 def end } def /XH { Adobe_ColorImage_AI6_Vars begin /XIVersion 6 def grestore end } def /XI { Adobe_ColorImage_AI6_Vars begin gsave /XIMask exch 0 ne def /XIBinary exch 0 ne def pop pop /XIChannelCount exch def /XIBitsPerPixel exch def /XIImageHeight exch def /XIImageWidth exch def pop pop pop pop /XIImageMatrix exch def XIBitsPerPixel 1 eq { XIImageWidth 8 div ceiling cvi } { XIImageWidth XIChannelCount mul } ifelse /XIBuffer exch string def XIBinary { /XIDataProc { currentfile XIBuffer readstring pop } def XIVersion 6 le { currentfile 128 string readline pop pop } if } { /XIDataProc { currentfile XIBuffer readhexstring pop } def } ifelse XIVersion 6 le { 0 0 moveto XIImageMatrix concat XIImageWidth XIImageHeight scale XIMask { /_lp /null ddef _fc /_lp /imagemask ddef } if } if XIMask { XIImageWidth XIImageHeight false [ XIImageWidth 0 0 XIImageHeight neg 0 0 ] /XIDataProc load imagemask } { XIImageWidth XIImageHeight XIBitsPerPixel [ XIImageWidth 0 0 XIImageHeight neg 0 0 ] /XIDataProc load XIChannelCount 1 eq { gsave 0 setgray image grestore } { false XIChannelCount colorimage } ifelse } ifelse grestore end } def end %%EndProcSet %%BeginResource: procset Adobe_Illustrator_AI5 1.1 0 %%Title: (Adobe Illustrator (R) Version 5.0 Full Prolog) %%Version: 1.1 0 %%CreationDate: (3/7/1994) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_Illustrator_AI5_vars 81 dict dup begin put /_eo false def /_lp /none def /_pf { } def /_ps { } def /_psf { } def /_pss { } def /_pjsf { } def /_pjss { } def /_pola 0 def /_doClip 0 def /cf currentflat def /_tm matrix def /_renderStart [ /e0 /r0 /a0 /o0 /e1 /r1 /a1 /i0 ] def /_renderEnd [ null null null null /i1 /i1 /i1 /i1 ] def /_render -1 def /_rise 0 def /_ax 0 def /_ay 0 def /_cx 0 def /_cy 0 def /_leading [ 0 0 ] def /_ctm matrix def /_mtx matrix def /_sp 16#020 def /_hyphen (-) def /_fScl 0 def /_cnt 0 def /_hs 1 def /_nativeEncoding 0 def /_useNativeEncoding 0 def /_tempEncode 0 def /_pntr 0 def /_tDict 2 dict def /_wv 0 def /Tx { } def /Tj { } def /CRender { } def /_AI3_savepage { } def /_gf null def /_cf 4 array def /_if null def /_of false def /_fc { } def /_gs null def /_cs 4 array def /_is null def /_os false def /_sc { } def /_pd 1 dict def /_ed 15 dict def /_pm matrix def /_fm null def /_fd null def /_fdd null def /_sm null def /_sd null def /_sdd null def /_i null def /discardSave null def /buffer 256 string def /beginString null def /endString null def /endStringLength null def /layerCnt 1 def /layerCount 1 def /perCent (%) 0 get def /perCentSeen? false def /newBuff null def /newBuffButFirst null def /newBuffLast null def /clipForward? false def end userdict /Adobe_Illustrator_AI5 known not { userdict /Adobe_Illustrator_AI5 91 dict put } if userdict /Adobe_Illustrator_AI5 get begin /initialize { Adobe_Illustrator_AI5 dup begin Adobe_Illustrator_AI5_vars begin discardDict { bind pop pop } forall dup /nc get begin { dup xcheck 1 index type /operatortype ne and { bind } if pop pop } forall end newpath } def /terminate { end end } def /_ null def /ddef { Adobe_Illustrator_AI5_vars 3 1 roll put } def /xput { dup load dup length exch maxlength eq { dup dup load dup length 2 mul dict copy def } if load begin def end } def /npop { { pop } repeat } def /sw { dup length exch stringwidth exch 5 -1 roll 3 index mul add 4 1 roll 3 1 roll mul add } def /swj { dup 4 1 roll dup length exch stringwidth exch 5 -1 roll 3 index mul add 4 1 roll 3 1 roll mul add 6 2 roll /_cnt 0 ddef { 1 index eq { /_cnt _cnt 1 add ddef } if } forall pop exch _cnt mul exch _cnt mul 2 index add 4 1 roll 2 index add 4 1 roll pop pop } def /ss { 4 1 roll { 2 npop (0) exch 2 copy 0 exch put pop gsave false charpath currentpoint 4 index setmatrix stroke grestore moveto 2 copy rmoveto } exch cshow 3 npop } def /jss { 4 1 roll { 2 npop (0) exch 2 copy 0 exch put gsave _sp eq { exch 6 index 6 index 6 index 5 -1 roll widthshow currentpoint } { false charpath currentpoint 4 index setmatrix stroke } ifelse grestore moveto 2 copy rmoveto } exch cshow 6 npop } def /sp { { 2 npop (0) exch 2 copy 0 exch put pop false charpath 2 copy rmoveto } exch cshow 2 npop } def /jsp { { 2 npop (0) exch 2 copy 0 exch put _sp eq { exch 5 index 5 index 5 index 5 -1 roll widthshow } { false charpath } ifelse 2 copy rmoveto } exch cshow 5 npop } def /pl { transform 0.25 sub round 0.25 add exch 0.25 sub round 0.25 add exch itransform } def /setstrokeadjust where { pop true setstrokeadjust /c { curveto } def /C /c load def /v { currentpoint 6 2 roll curveto } def /V /v load def /y { 2 copy curveto } def /Y /y load def /l { lineto } def /L /l load def /m { moveto } def } { /c { pl curveto } def /C /c load def /v { currentpoint 6 2 roll pl curveto } def /V /v load def /y { pl 2 copy curveto } def /Y /y load def /l { pl lineto } def /L /l load def /m { pl moveto } def } ifelse /d { setdash } def /cf { } def /i { dup 0 eq { pop cf } if setflat } def /j { setlinejoin } def /J { setlinecap } def /M { setmiterlimit } def /w { setlinewidth } def /XR { 0 ne /_eo exch ddef } def /H { } def /h { closepath } def /N { _pola 0 eq { _doClip 1 eq { _eo {eoclip} {clip} ifelse /_doClip 0 ddef } if newpath } { /CRender { N } ddef } ifelse } def /n { N } def /F { _pola 0 eq { _doClip 1 eq { gsave _pf grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _fc /_doClip 0 ddef } { _pf } ifelse } { /CRender { F } ddef } ifelse } def /f { closepath F } def /S { _pola 0 eq { _doClip 1 eq { gsave _ps grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _sc /_doClip 0 ddef } { _ps } ifelse } { /CRender { S } ddef } ifelse } def /s { closepath S } def /B { _pola 0 eq { _doClip 1 eq gsave F grestore { gsave S grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _sc /_doClip 0 ddef } { S } ifelse } { /CRender { B } ddef } ifelse } def /b { closepath B } def /W { /_doClip 1 ddef } def /* { count 0 ne { dup type /stringtype eq { pop } if } if newpath } def /u { } def /U { } def /q { _pola 0 eq { gsave } if } def /Q { _pola 0 eq { grestore } if } def /*u { _pola 1 add /_pola exch ddef } def /*U { _pola 1 sub /_pola exch ddef _pola 0 eq { CRender } if } def /D { pop } def /*w { } def /*W { } def /` { /_i save ddef clipForward? { nulldevice } if 6 1 roll 4 npop concat pop userdict begin /showpage { } def 0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit [] 0 setdash /setstrokeadjust where {pop false setstrokeadjust} if newpath 0 setgray false setoverprint } def /~ { end _i restore } def /O { 0 ne /_of exch ddef /_lp /none ddef } def /R { 0 ne /_os exch ddef /_lp /none ddef } def /g { /_gf exch ddef /_fc { _lp /fill ne { _of setoverprint _gf setgray /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /G { /_gs exch ddef /_sc { _lp /stroke ne { _os setoverprint _gs setgray /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /k { _cf astore pop /_fc { _lp /fill ne { _of setoverprint _cf aload pop setcmykcolor /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /K { _cs astore pop /_sc { _lp /stroke ne { _os setoverprint _cs aload pop setcmykcolor /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /x { /_gf exch ddef findcmykcustomcolor /_if exch ddef /_fc { _lp /fill ne { _of setoverprint _if _gf 1 exch sub setcustomcolor /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /X { /_gs exch ddef findcmykcustomcolor /_is exch ddef /_sc { _lp /stroke ne { _os setoverprint _is _gs 1 exch sub setcustomcolor /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /A { pop } def /annotatepage { userdict /annotatepage 2 copy known {get exec} {pop pop} ifelse } def /XT { pop pop } def /discard { save /discardSave exch store discardDict begin /endString exch store gt38? { 2 add } if load stopped pop end discardSave restore } bind def userdict /discardDict 7 dict dup begin put /pre38Initialize { /endStringLength endString length store /newBuff buffer 0 endStringLength getinterval store /newBuffButFirst newBuff 1 endStringLength 1 sub getinterval store /newBuffLast newBuff endStringLength 1 sub 1 getinterval store } def /shiftBuffer { newBuff 0 newBuffButFirst putinterval newBuffLast 0 currentfile read not { stop } if put } def 0 { pre38Initialize mark currentfile newBuff readstring exch pop { { newBuff endString eq { cleartomark stop } if shiftBuffer } loop } { stop } ifelse } def 1 { pre38Initialize /beginString exch store mark currentfile newBuff readstring exch pop { { newBuff beginString eq { /layerCount dup load 1 add store } { newBuff endString eq { /layerCount dup load 1 sub store layerCount 0 eq { cleartomark stop } if } if } ifelse shiftBuffer } loop } if } def 2 { mark { currentfile buffer readline not { stop } if endString eq { cleartomark stop } if } loop } def 3 { /beginString exch store /layerCnt 1 store mark { currentfile buffer readline not { stop } if dup beginString eq { pop /layerCnt dup load 1 add store } { endString eq { layerCnt 1 eq { cleartomark stop } { /layerCnt dup load 1 sub store } ifelse } if } ifelse } loop } def end userdict /clipRenderOff 15 dict dup begin put { /n /N /s /S /f /F /b /B } { { _doClip 1 eq { /_doClip 0 ddef _eo {eoclip} {clip} ifelse } if newpath } def } forall /Tr /pop load def /Bb {} def /BB /pop load def /Bg {12 npop} def /Bm {6 npop} def /Bc /Bm load def /Bh {4 npop} def end /Lb { 4 npop 6 1 roll pop 4 1 roll pop pop pop 0 eq { 0 eq { (%AI5_BeginLayer) 1 (%AI5_EndLayer--) discard } { /clipForward? true def /Tx /pop load def /Tj /pop load def currentdict end clipRenderOff begin begin } ifelse } { 0 eq { save /discardSave exch store } if } ifelse } bind def /LB { discardSave dup null ne { restore } { pop clipForward? { currentdict end end begin /clipForward? false ddef } if } ifelse } bind def /Pb { pop pop 0 (%AI5_EndPalette) discard } bind def /Np { 0 (%AI5_End_NonPrinting--) discard } bind def /Ln /pop load def /Ap /pop load def /Ar { 72 exch div 0 dtransform dup mul exch dup mul add sqrt dup 1 lt { pop 1 } if setflat } def /Mb { q } def /Md { } def /MB { Q } def /nc 3 dict def nc begin /setgray { pop } bind def /setcmykcolor { 4 npop } bind def /setcustomcolor { 2 npop } bind def currentdict readonly pop end end setpacking %%EndResource %%BeginResource: procset Adobe_blend_AI5 1.4 0 %%Title: (Adobe Illustrator (R) Version 5.0 Blend ProcSet) %%Version: 1.4 0 %%CreationDate: (11/19/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /Adobe_blend_AI5 70 dict dup begin put /bd { bind def } bind def /xs { exch store } bd /nullProc { { } } def /initialize { pop pop Adobe_blend_AI5 begin Adobe_blend_AI5_vars begin /_contoneDevice where { pop } { /_contoneDevice false def } ifelse /_dpiThreshold where { pop } { /_dpiThreshold 600 def } ifelse /_screenFreqThreshold where { pop } { /_screenFreqThreshold 150 def } ifelse /tRectOK? deviceDPI _dpiThreshold le currentScreenFreq _screenFreqThreshold le and _contoneDevice not and def /invertXfer { [ { 1 exch sub } /exec load systemdict/currenttransfer get exec /exec load ] cvx systemdict/settransfer get exec } bd /spotDict 3 dict dup begin /nSpots 2 def /spot1 7 dict def /spot2 7 dict def end def composite? { /_setgray_ /setgray load def /_fill_ /fill load def /_image_ /image load def } { /_setgray_ systemdict/setgray get def /_fill_ systemdict/fill get def /_image_ systemdict/image get def } ifelse } bd /terminate { currentdict Adobe_blend_AI5_vars eq { end currentdict Adobe_blend_AI5 eq { end } if } if } bd /_compositeSpotDevice where { begin _compositeSpotDevice 0 ne {userdict /composite? true put} if end } { /_compositeSpotDevice 0 def } ifelse /nullString () def /d255 256 array def 0 1 255 { d255 exch dup 255 div put } bind for /d255- 256 array def 0 1 255 { d255- exch 1 d255 2 index get sub put } bind for /dUserSpace matrix defaultmatrix def currentdict /Adobe_blend_AI5_vars 89 dict dup begin put { /f /F /s /S /b /B } { null def } bind forall /byte 1 string def /sSave null def /setSSave { save /sSave exch store } bind def /Bm null def /doBlend null def /startC? false def /endC? false def /fCMYK? null def /startTint 0 def /endTint 0 def /bSMatrix matrix def /bUMatrix matrix def /dMatrix matrix def /inLine? true def /pTState? false def /bHi? false def /yHi 0 def /xHi 0 def /noImg /lv1Fix where { pop lv1Fix } { false } ifelse def /ccAry1 5 array def /ccTint 0 def /spotColor? false def /colorimage? true def [ /tint1Data /tint2Data /spotDict /bAxis /ubAxis /pChange /optimize? /nSamples /sInc /blendProc /_bn /xBCInc /yBCInc /bInc /bRender /cBName /cBType /nColors /color? /blend? /colorType /cData /cDataLen /bDataLen /rampPoint /midPoint /endPoint /blendLength /blackData /yeData /mgData /cyData /cnt1 /ndx /_fill /tmp counttomark { null def } bind repeat pop currentdict end currentdict end exch begin begin /unitSq { 0 0 moveto 0 1 lineto 1 1 lineto 1 0 lineto closepath } bd /gMark { counttomark 2 add -1 roll } bd /setCustomColor { dup /ccTint exch store 1 exch sub 6 1 roll ccAry1 astore exch setcustomcolor } bd /currentCustomColor { ccAry1 aload pop ccTint } bd /nsetcustomcolor where { pop } { /nsetcustomcolor { pop setcmykcolor } bd } ifelse /nsetcustomcolorend where { pop } { /nsetcustomcolorend { } bd } ifelse /setBSpace { newpath bUMatrix astore concat unitSq } bd /setCStop { dup 0 eq { pop spotColor? { dup 1 exch sub /ccTint exch def ccAry1 4 /Black put } if setgray } { 1 eq { setcmykcolor } { composite? not colorType 2 lt and { forceCMYK } { setCustomColor } ifelse } ifelse } ifelse } bd /makeByte { /tmp 0 store 255 mul cvi 8 string 8 { dup tmp 3 index put /tmp tmp 1 add store } repeat exch pop } bd /setImgSpace { cDataLen 1 8 2 index 0 0 1 0 0 dMatrix astore } bd /bwImage { setImgSpace cData /_image_ load { exec } stopped { $error /errorname get /undefinedresult ne { stop } { pop pop pop pop pop } ifelse } if } bd level2? { /bFill { _fill } def /bCImg { /cDataLen bDataLen store setImgSpace setSSave expandSpot cyData mgData yeData cData expandCMYK true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd } if /expandOne { dup type /stringtype ne { cDataLen string exch dup 0 ne { 255 mul cvi 0 1 cDataLen 1 sub { 3 copy exch put pop } for } if pop } if } bd /expandSpot { spotColor? { spotDict begin spot1 begin tintImage type /nulltype ne { tintImage expandOne /tintImage exch def } if end spot2 begin tintImage type /nulltype ne { tintImage expandOne /tintImage exch def } if end end } if } bd /expandCMYK { 4 { expandOne 4 1 roll } repeat } bd /colorimage where dup { exch pop /ncolorimage where { pop } { /ncolorimage {pop colorimage} bd } ifelse } if not { /ncolorimage where { pop } { /colorimage? false store /ncolorimage { pop pop pop setSSave /blackData xs /yeData xs /mgData xs /cyData xs /cnt1 0 store [ byte dup 0 cyData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .3 /mul cvx } { .3 mul } ifelse mgData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .59 /mul cvx } { .59 mul } ifelse yeData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .11 /mul cvx } { .11 mul } ifelse blackData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx } if /add cvx /add cvx /add cvx 1 /exch cvx /sub cvx /dup cvx 0 /lt cvx { pop 0 } /if cvx /dup cvx 1 /gt cvx { pop 1 } /if cvx 255 /mul cvx /cvi cvx 256 /mod cvx /dup cvx 0 /lt cvx { pop 0 } /if cvx /put cvx /cnt1 dup cvx 1 /add cvx /store cvx ] cvx bind _image_ sSave restore } bd } ifelse } if level2? not { /bCImg { /cDataLen bDataLen store setImgSpace setSSave expandSpot cyData mgData yeData cData colorimage? { expandCMYK } if true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd /bwFill { setSSave /cDataLen 8 store /cData currentgray makeByte store bwImage sSave restore } bd /c1ImgFill { setSSave /cDataLen 8 store setImgSpace spotColor? { spotDict begin spot1 begin currentCustomColor makeByte /tintImage exch def /name exch def /spot_K exch def /spot_Y exch def /spot_M exch def /spot_C exch def end spot2 initSpotData end } if currentcmykcolor 4 { makeByte 4 1 roll } repeat true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd /bFill noImg { { _fill } } { { color? { c1ImgFill } { bwFill } ifelse } } ifelse bd } if composite? { /bCFun { color? { cyData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if mgData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if yeData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if cData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if spotColor? { spotDict begin /spotDict cvx /begin cvx spot1 begin tintImage dup type /stringtype eq { /ndx cvx /get cvx d255- /exch cvx /get cvx } { dup type /nulltype ne { name type /nametype ne {1 exch sub} if } if } ifelse end /spot1 cvx /tintValue 3 -1 /roll cvx /put cvx spot2 begin tintImage dup type /stringtype eq { /ndx cvx /get cvx d255- /exch cvx /get cvx } { dup type /nulltype ne { name type /nametype ne {1 exch sub} if } if } ifelse end /spot2 cvx /tintValue 3 -1 /roll cvx /put cvx /end cvx end /spotDict cvx /nsetcustomcolor cvx } { /setcmykcolor cvx } ifelse } { cData /ndx cvx /get cvx d255 /exch cvx /get cvx /setgray cvx } ifelse } bd /Bc { newpath gsave setBSpace nColors 1 eq { pop pop setCStop } if bFill grestore } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { linImg } { bFill } ifelse grestore nColors 1 gt { getRData } if } bd /rdBm { /nColors dup load 1 sub store _fill gsave bUMatrix astore concat bHi? { xHi yHi bUMatrix idtransform /yHi exch store /xHi exch store rampPoint 1 lt { 1 rampPoint sub dup xHi mul exch yHi mul translate } if } if nColors { 0 0 rampPoint 0 360 arc _fill blend? bHi? or { rdBlend } if nColors 1 gt { getRData } if /nColors dup load 1 sub store } repeat /nColors 1 store grestore } bd /cGetRData { setCStop /blend? cData type /stringtype eq dup not color? and { pop cyData type /stringtype eq mgData type /stringtype eq yeData type /stringtype eq or or } if store } def /cGetRData } if /eCStop { mark 1 index 3 mul 3 add dup 8 gt { pop 8 } if 1 roll cleartomark } bd composite? not { /knockOut level2? { { 0 0 0 0 setcmykcolor _fill } } { /bFill noImg { { _fill } } { { _of true eq { currentgray 1 ne { bwFill } if } { bwFill } ifelse } } ifelse def /whiteByte 1 makeByte def noImg { { 0 0 0 0 setcmykcolor _fill } } { { cBType 0 eq { setSSave /cData whiteByte store /cDataLen 8 store bwImage sSave restore } { _fill } ifelse } } ifelse } ifelse bd /bCFun { cData dup type /stringtype ne { color? { 1 exch sub } if } { /ndx cvx /get cvx color? customColor? not and { d255- } { d255 } ifelse /exch cvx /get cvx } ifelse /_setgray_ cvx } bd /eCCBlend { dup 3 eq { pop mark 7 1 roll 6 copy ccThrough? dup /blend? xs { /startC? true store setCustomColor customColor? { /cData tint1Data store setCDataLen } if /endC? 3 index 3 eq { 4 index 1 ne } { false } ifelse store } if cleartomark stop } if 1 eq { pop pop pop } if pop /startC? false store 6 { 8 index } repeat ccThrough? dup /blend? xs { /endC? true store blend? not { stop } if customColor? { /cData tint1Data store setCDataLen } if } if } bd /handleOP { _of not { knockOut } if } bd /handleROP { _of not { 0 0 0 0 setcmykcolor _fill } { newpath } ifelse } bd /rdBm { /nColors dup load 1 sub store blend? { _fill } { handleROP } ifelse gsave bUMatrix astore concat bHi? { xHi yHi bUMatrix idtransform /yHi exch store /xHi exch store rampPoint 1 lt { 1 rampPoint sub dup xHi mul exch yHi mul translate } if } if nColors { 0 0 rampPoint 0 360 arc blend? { cData type /stringtype ne bHi? not and { cData color? { 1 exch sub } if _setgray_ _fill_ } { cData type /stringtype ne { /cDataLen 1 store /bDataLen 1 store } if rdBlend } ifelse } { handleROP pTState? { /bAxis rampPoint endPoint sub store xHi bAxis mul yHi bAxis mul translate } if } ifelse nColors 1 gt { getRData } if /nColors dup load 1 sub store } repeat /nColors 1 store grestore } bd /ccThrough? { gsave pop 0 setCustomColor currentcmykcolor grestore anyColor? } bd /forceCMYK { exch pop 1 exch sub 5 1 roll 4 { 4 index mul 4 1 roll } repeat 0 cCMYKData dup /cData ne { dup /yeData eq { pop 1 add } { /mgData eq { 2 } { 3 } ifelse add } ifelse 0 } if pop index 0 eq { pop pop pop pop 0 0 0 0 } if setcmykcolor pop /fCMYK? true store } bd /endCapSepBc { pop pop dup 0 eq { pop setgray } { 1 eq { setcmykcolor } { colorType 1 eq { forceCMYK } { fCMYK? { forceCMYK } { setCustomColor } ifelse } ifelse } ifelse } ifelse currentcmykcolor anyColor? blend? and { bFill } { handleOP } ifelse } bd } if /cCMYKData 0 def composite? dup not { pop customColor? } if not { /cCMYKData /cyData /mgData /yeData /cData black? not { yellow? { exch } { magenta? { 3 } { 4 } ifelse -1 roll } ifelse } if 4 1 roll pop pop pop store /Bc { gsave setBSpace nColors 1 gt { blend? currentcmykcolor anyColor? and { bFill } { handleOP } ifelse } { endCapSepBc } ifelse grestore newpath } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { cCMYKData load dup type /stringtype eq { dup length /cDataLen xs /cData xs gsave colorType 0 ne noImg not and { invertXfer } if linImg grestore } { pop bFill } ifelse } { handleOP } ifelse grestore nColors 1 gt { getRData } if } bd /cmykGetRData { /fCMYK? false store blend? { { cmykDataProcs colorType get exec } stopped pop blend? { /cData cCMYKData load store setCDataLen } if } if } def /cmykDataProcs [ { pop black? dup /blend? xs { setgray 0 } if pop } { cCMYKData load dup type /stringtype ne { 0 0 0 cyan? not { 4 magenta? { 1 } { yellow? { 2 } { 3 } ifelse } ifelse roll } if 4 copy add add add 0 eq { /blend? false store } if setcmykcolor /startC? true store /endC? true store eCStop stop } if pop dup 0 eq { pop setgray } { 1 eq { setcmykcolor } { forceCMYK } ifelse } ifelse } bind /eCCBlend load { cBType 1 eq { tint1Data tint2Data /tint1Data xs /tint2Data xs } if 0 eq { black? { setgray } { 0 0 0 4 -1 roll 1 exch sub setcmykcolor } ifelse black? { /blend? true store } if 6 { 8 index } repeat ccThrough? { /blend? true store } { black? { /cData tint1Data store setCDataLen } { /blend? false store } ifelse } ifelse } { mark 7 1 roll 6 copy ccThrough? { forceCMYK pop stop } if 9 index 0 eq { black? dup /blend? xs { pop 1 setgray /cData tint2Data store setCDataLen 0 } if pop } { /blend? 6 { 16 index } repeat ccThrough? store blend? { forceCMYK } if } ifelse cleartomark } ifelse } bind ] def /cmykGetRData } if composite? dup not { pop isCMYKSep? } if not { /endCapSepBc { /white? false store pop pop dup 0 eq { pop /white? 1 index 1 eq store setgray } { 1 eq { setcmykcolor } { setCustomColor } ifelse } ifelse % currentcmykcolor anyColor? endC? or blend? and { bFill } { handleOP } ifelse } bd /Bc { gsave setBSpace nColors 1 gt { blend? startC? and { bFill } { handleOP } ifelse } { endCapSepBc } ifelse grestore newpath } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { cData type /stringtype eq { linImg } { bFill } ifelse } { handleOP } ifelse grestore nColors 1 gt { getRData } if } bd /discardCMY { counttomark 4 add -3 roll pop pop pop } bd /testTopCC { 6 copy ccThrough? } bd /getCRamp { { ccDataProcs colorType 2 sub get exec } stopped pop blend? cDataLen 0 eq and { /cDataLen bDataLen store } if } bd /ccGetRData { /fCMYK? false store /startC? false store /endC? false store colorType 2 lt { /blend? false def } if blend? { getCRamp } { setCStop } ifelse blend? { /blend? cData 1 ne store blend? { cData dup type /stringtype ne { 1 exch sub /cData xs 0 } if pop } if } if } def /ccDataProcs [ /eCCBlend load { cBType 1 eq { tint1Data tint2Data /tint1Data xs /tint2Data xs } if 0 eq { /blend? false store pop } { mark 7 1 roll testTopCC { /blend? 1 index 1 ne store /startC? blend? store /endC? false store blend? not { cleartomark stop } if /cData tint1Data store setCDataLen setCustomColor pop stop } if cleartomark } ifelse 2 index 0 eq { /blend? false store } { mark 6 { 9 index } repeat testTopCC dup /blend? xs { /blend? 1 index 1 ne store /endC? blend? store /startC? false store blend? not { cleartomark stop } if /cData tint2Data store setCDataLen } if cleartomark } ifelse } bind ] def /ccGetRData } if load Adobe_blend_AI5_vars /getData 3 -1 roll put /setCDataLen { /cDataLen 0 cData dup type /stringtype eq { length exch } if pop store } bd /initSpotData { begin /name null def /tintImage null def /tintValue null def /spot_C null def /spot_M null def /spot_Y null def /spot_K null def end } bd /getRData { /colorType gMark store _compositeSpotDevice 0 ne { spotDict begin spot1 initSpotData spot2 initSpotData end /spotColor? colorType 2 eq colorType 3 eq or def } { /spotColor? false store } ifelse /blend? true store 0 0 0 0 setcmykcolor 100 div /rampPoint xs % (between 13 and 87%) 100 div /midPoint xs dup 0 eq { 2 } { dup 1 eq { 5 } { _compositeSpotDevice 0 ne { spotDict begin spot1 begin /name 3 index def /spot_K 4 index def /spot_Y 5 index def /spot_M 6 index def /spot_C 7 index def end end } if 7 } ifelse } ifelse /tmp exch def tmp index 100 div /endPoint xs _compositeSpotDevice 0 ne { tmp 2 add index 3 eq { /tmp tmp 4 add def tmp index dup spotDict begin spot1/name get ne { spot2 begin /name exch def /spot_K tmp 2 add index def /spot_Y tmp 3 add index def /spot_M tmp 4 add index def /spot_C tmp 5 add index def end } { pop } ifelse end } if } if /color? colorType 0 gt store colorType 3 eq { /tint2Data gMark store } if colorType 2 ge { /tint1Data gMark store } if _compositeSpotDevice 0 ne { spotDict begin colorType 2 ge { colorType 3 eq { spot2 begin /tintImage cBType 0 eq {tint2Data} {tint1Data} ifelse def name null eq {/name /Black def} if end } if spot1 begin /tintImage cBType 0 eq colorType 2 eq or {tint1Data} {tint2Data} ifelse def colorType 2 eq { name null eq { /name spot2/name get def spot2/name null put } if } { name null eq {/name /Black def} if } ifelse end } if end } if /cData gMark store setCDataLen colorType 0 gt { counttomark 4 add -3 roll /yeData xs /mgData xs /cyData xs } if blend? { /bDataLen cDataLen dup 0 eq color? and { [ cyData mgData yeData ] { dup type /stringtype eq { length exch pop exit } if pop } forall } if store bDataLen 0 eq { /bDataLen 1 store } if getData blend? { composite? cDataLen 0 eq and { /cDataLen bDataLen store } if } if } { setCStop } ifelse } bd /Bg { 0 0 0 0 setcmykcolor 6 { pop } repeat /blendLength xs pop pop pop /cBName xs /bRender xs bRender 2 ne { composite? not { _of setoverprint } if _eo {eoclip} {clip} ifelse _bn cBName 2 copy known { get mark exch aload pop /cBType xs /nColors xs mark exch aload pop 0 0 } if pop pop getRData cBType 0 eq { /linealBm } { bHi? { /pTState? nColors 2 gt store } if /doBlend /rdBlend load store /rdBm } ifelse } { inLine? not { mark mark } if /Bc dup { cleartomark mark } bd /nullProc } ifelse load /Bm xs } bd /linImg noImg { { newpath doRctBlend } } { { /doBlend color? composite? and { /bCImg } { /bwImage } ifelse load store 0 0 moveto tRectOK? composite? and { { mark 0 1 dtransform atan cvi 90 mod 0 eq 1 0 dtransform atan cvi 90 mod 0 eq } stopped { cleartomark } { and exch pop { newpath doRctBlend } { doBlend } ifelse } ifelse } { doBlend } ifelse } } ifelse bd /doRctBlend { gsave /sInc 1 store /nSamples bDataLen store /bInc 1 bDataLen div store /ubAxis 1 0 dtransform dUserSpace idtransform dup mul exch dup mul add sqrt store /pChange ubAxis 0 eq { 0 } { bDataLen ubAxis div } ifelse store pChange .5 gt noImg not and dup /optimize? xs { /nSamples ubAxis 2 div round cvi dup 1 le { pop 2 } if store /bInc 1 nSamples div store /sInc bDataLen 1 sub nSamples 1 sub div store } if 0 nSamples [ /dup cvx optimize? { /round cvx /cvi cvx } if /ndx /exch cvx /store cvx bCFun /rectfill where dup { exch pop _compositeSpotDevice 1 ne and } if { 0 0 bInc 1 /rectfill cvx } { 0 0 /moveto cvx bInc 0 /lineto cvx bInc 1 /lineto cvx 0 1 /lineto cvx /closepath cvx /_fill_ cvx } ifelse bInc 0 /translate cvx sInc /add cvx ] cvx bind repeat pop spotColor? {nsetcustomcolorend} if grestore } bd /rdPrep { /nSamples bDataLen dup 0 eq { pop 1 } if store /sInc -1 store /bAxis rampPoint endPoint sub store /bInc bAxis bDataLen div neg store /optimize? false store tRectOK? { /ubAxis bAxis 0 dtransform dUserSpace idtransform dup mul exch dup mul add sqrt 0 bAxis dtransform dUserSpace idtransform dup mul exch dup mul add sqrt 2 copy lt { exch } if pop store /pChange ubAxis 0 eq { 0 } { bDataLen ubAxis div } ifelse store pChange .5 gt noImg not and dup /optimize? xs { /nSamples ubAxis 2 div round cvi dup 1 le { pop 2 } if store /bInc bAxis nSamples div neg store /sInc bDataLen 1 sub nSamples 1 sub div neg store } if } if bHi? { /xBCInc xHi bAxis mul nSamples div store /yBCInc yHi bAxis mul nSamples div store } if } bd /rdBlend { newpath gsave rdPrep rampPoint bDataLen 1 sub nSamples [ /dup cvx optimize? { /round cvx /cvi cvx } if /ndx /exch cvx /store cvx bCFun 0 0 3 /index cvx 0 360 /arc cvx /_fill_ cvx /exch cvx bInc /add cvx /exch cvx sInc /add cvx bHi? { xBCInc yBCInc /translate cvx } if ] cvx bind repeat pop pop spotColor? {nsetcustomcolorend} if grestore pTState? { xHi bAxis mul yHi bAxis mul translate } if } bd /Bh { pop pop /pTState? false store 2 copy 0 ne exch 0 ne or dup /bHi? xs { /yHi xs /xHi xs 0 0 } if pop pop } bd /BD { inLine? not { ] nColors cBType ] _bn cBName 3 -1 roll put end } if } bd /Bn { 1 add dict dup nullString null put /_bn xs } bd /Bd { Adobe_blend_AI5_vars begin 3 -1 roll dup nullString eq dup { setSSave } if /inLine? exch def /cBName exch def /nColors exch def /cBType exch def } bd /Bb { sSave null eq { Adobe_blend_AI5_vars begin setSSave } if composite? { /_fill /fill load store } { /__fill /fill load store /_fill { _of true eq { currentgray 1 ne { __fill } if } { __fill } ifelse } def } ifelse /fill { } def } bd /BB { /cBType xs cleartomark cleartomark cBType dup bRender sSave dup type /savetype eq { restore 0 } if pop currentdict Adobe_blend_AI5_vars eq { end } if 2 ne exch 0 gt and { 2 eq { s } { S } ifelse } { pop newpath } ifelse } bd currentdict readonly pop end end defaultpacking setpacking %%EndResource %%BeginResource: procset Adobe_pattern_AI5 1.1 0 %%Title: (Adobe Illustrator (R) Version 5.0 Pattern Operators) %%Version: 1.1 0 %%CreationDate: (03/26/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_Illustrator_AI5 known not { userdict /Adobe_Illustrator_AI5 95 dict put } if userdict /Adobe_Illustrator_AI5 get begin /@ { } def /& { } def /dp { dup null eq { pop _dp 0 ne { 0 1 _dp 1 sub _dl mod { _da exch get 3 get } for _dp 1 sub _dl mod 1 add packedarray _da 0 get aload pop 8 -1 roll 5 -1 roll pop 4 1 roll definepattern pop } if } { _dp 0 ne _dp _dl mod 0 eq and { null dp } if 7 packedarray _da exch _dp _dl mod exch put _dp _dl mod _da 0 get 4 get 2 packedarray /_dp _dp 1 add def } ifelse } def /E { _ed begin dup 0 get type /arraytype ne { 0 { dup 1 add index type /arraytype eq { 1 add } { exit } ifelse } loop array astore } if /_dd exch def /_ury exch def /_urx exch def /_lly exch def /_llx exch def /_n exch def /_y 0 def /_dl 4 def /_dp 0 def /_da _dl array def 0 1 _dd length 1 sub { /_d exch _dd exch get def 0 2 _d length 2 sub { /_x exch def /_c _d _x get _ ne def /_r _d _x 1 add get cvlit def _r _ ne { _urx _llx sub _ury _lly sub [ 1 0 0 1 0 0 ] [ /save cvx _llx neg _lly neg /translate cvx _c { nc /begin cvx } if _r dup type /stringtype eq { cvx } { { exec } /forall cvx } ifelse _c { /end cvx } if /restore cvx ] cvx /_fn 12 _n length add string def _y _fn cvs pop /_y _y 1 add def _fn 12 _n putinterval _fn _c false dp _d exch _x 1 add exch put } if } for } for null dp _n _dd /_pd end xput } def /fc { _fm dup concatmatrix pop } def /p { /_fm exch ddef 9 -2 roll _pm translate fc 7 -2 roll _pm scale fc 5 -1 roll _pm rotate fc 4 -2 roll exch 0 ne { dup _pm rotate fc 1 -1 _pm scale fc neg _pm rotate fc } { pop } ifelse dup _pm rotate fc exch dup sin exch cos div 1 0 0 1 0 6 2 roll _pm astore fc neg _pm rotate fc _pd exch get /_fdd exch ddef /_pf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm patternfill } { pop fill } ifelse grestore pop } for pop } for restore newpath } ddef /_psf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm 9 copy 6 npop patternashow } { pop 6 copy 3 npop hvashow } ifelse grestore pop } for pop } for restore sw rmoveto } ddef /_pjsf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm 12 copy 6 npop patternawidthshow } { pop 9 copy 3 npop hvawidthshow } ifelse grestore pop } for pop } for restore swj rmoveto } ddef /_lp /none ddef } def /sc { _sm dup concatmatrix pop } def /P { /_sm exch ddef 9 -2 roll _pm translate sc 7 -2 roll _pm scale sc 5 -1 roll _pm rotate sc 4 -2 roll exch 0 ne { dup _pm rotate sc 1 -1 _pm scale sc neg _pm rotate sc } { pop } ifelse dup _pm rotate sc exch dup sin exch cos div 1 0 0 1 0 6 2 roll _pm astore sc neg _pm rotate sc _pd exch get /_sdd exch ddef /_ps { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm patternstroke } { pop stroke } ifelse grestore pop } for pop } for restore newpath } ddef /_pss { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm 10 copy 6 npop patternashowstroke } { pop 7 copy 3 npop ss } ifelse grestore pop } for pop } for restore pop sw rmoveto } ddef /_pjss { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm 13 copy 6 npop patternawidthshowstroke } { pop 10 copy 3 npop jss } ifelse grestore pop } for pop } for restore pop swj rmoveto } ddef /_lp /none ddef } def end userdict /Adobe_pattern_AI5 18 dict dup begin put /initialize { /definepattern where { pop } { begin begin Adobe_pattern_AI5 begin Adobe_pattern_AI5 { dup xcheck { bind } if pop pop } forall mark cachestatus 7 1 roll pop pop pop pop exch pop exch { { 10000 add dup 2 index gt { exit } if dup setcachelimit } loop } stopped cleartomark end end end Adobe_pattern_AI5 begin } ifelse } def /terminate { currentdict Adobe_pattern_AI5 eq { end } if } def errordict /nocurrentpoint { pop stop } put errordict /invalidaccess { pop stop } put /patternencoding 256 array def 0 1 255 { patternencoding exch ( ) 2 copy exch 0 exch put cvn put } for /definepattern { 17 dict begin /uniform exch def /cache exch def /key exch def /procarray exch def /mtx exch matrix invertmatrix def /height exch def /width exch def /ctm matrix currentmatrix def /ptm matrix def /str 32 string def /slice 9 dict def slice /s 1 put slice /q 256 procarray length div sqrt floor cvi put slice /b 0 put /FontBBox [ 0 0 0 0 ] def /FontMatrix mtx matrix copy def /Encoding patternencoding def /FontType 3 def /BuildChar { exch begin /setstrokeadjust where {pop true setstrokeadjust} if slice begin dup q dup mul mod s idiv /i exch def dup q dup mul mod s mod /j exch def q dup mul idiv procarray exch get /xl j width s div mul def /xg j 1 add width s div mul def /yl i height s div mul def /yg i 1 add height s div mul def uniform { 1 1 } { width 0 dtransform dup mul exch dup mul add sqrt dup 1 add exch div 0 height dtransform dup mul exch dup mul add sqrt dup 1 add exch div } ifelse width 0 cache { xl 4 index mul yl 4 index mul xg 6 index mul yg 6 index mul setcachedevice } { setcharwidth } ifelse gsave scale newpath xl yl moveto xg yl lineto xg yg lineto xl yg lineto closepath clip newpath end end exec grestore } def key currentdict definefont end } def /patterncachesize { gsave newpath 0 0 moveto width 0 lineto width height lineto 0 height lineto closepath patternmatrix setmatrix pathbbox exch ceiling 4 -1 roll floor sub 3 1 roll ceiling exch floor sub mul 1 add grestore } def /patterncachelimit { cachestatus 7 1 roll 6 npop 8 mul } def /patternpath { exch dup begin setfont ctm setmatrix concat slice exch /b exch slice /q get dup mul mul put FontMatrix concat uniform { width 0 dtransform round width div exch round width div exch 0 height dtransform round height div exch height div exch 0 0 transform round exch round exch ptm astore setmatrix } { ptm currentmatrix pop } ifelse { currentpoint } stopped not { 2 npop pathbbox true 4 index 3 index eq 4 index 3 index eq and { pop false { { 2 npop } { 3 npop true } { 7 npop true } { pop true } pathforall } stopped { 5 npop true } if } if { height div ceiling height mul 4 1 roll width div ceiling width mul 4 1 roll height div floor height mul 4 1 roll width div floor width mul 4 1 roll 2 index sub height div ceiling cvi exch 3 index sub width div ceiling cvi exch 4 2 roll moveto FontMatrix mtx invertmatrix dup dup 4 get exch 5 get rmoveto ptm ptm concatmatrix pop slice /s patterncachesize patterncachelimit div ceiling sqrt ceiling cvi dup slice /q get gt { pop slice /q get } if put 0 1 slice /s get dup mul 1 sub { slice /b get add gsave 0 1 str length 1 sub { str exch 2 index put } for pop dup { gsave ptm setmatrix 1 index str length idiv { str show } repeat 1 index str length mod str exch 0 exch getinterval show grestore 0 height rmoveto } repeat grestore } for 2 npop } { 4 npop } ifelse } if end } def /patternclip { _eo {eoclip} {clip} ifelse } def /patternstrokepath { strokepath } def /patternmatrix matrix def /patternfill { dup type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get } if gsave patternclip Adobe_pattern_AI5 /patternpath get exec grestore newpath } def /patternstroke { dup type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get } if gsave patternstrokepath true { { { newpath moveto } { lineto } { curveto } { closepath 3 copy Adobe_pattern_AI5 /patternfill get exec } pathforall 3 npop } stopped { 5 npop patternclip Adobe_pattern_AI5 /patternfill get exec } if } { patternclip Adobe_pattern_AI5 /patternfill get exec } ifelse grestore newpath } def /vpatternawidthshow { 6 1 roll /_hvay exch ddef /_hvax exch ddef /_hvwb exch ddef /_hvcy exch ddef /_hvcx exch ddef { dup cstring dup length 1 eq _charorientation 1 eq and { -90 rotate currentpoint _fontRotateAdjust add moveto gsave false charpath currentpoint 5 index 5 index 5 index Adobe_pattern_AI5 /patternfill get exec grestore _fontRotateAdjust sub moveto _hvwb eq { _hvcx _hvcy rmoveto } if _hvax _hvay rmoveto 90 rotate } { currentpoint _fontHeight sub _hvax sub 3 index _hvwb eq { _hvcx sub } if currentpoint exch 4 index stringwidth pop 2 div sub exch _fontAscent sub moveto gsave 2 index false charpath 6 index 6 index 6 index Adobe_pattern_AI5 /patternfill get exec grestore newpath moveto pop pop } ifelse } cforall 3 npop } def /hpatternawidthshow { { dup cstring exch gsave 3 index eq { 5 index 5 index rmoveto } if false charpath currentpoint 9 index 9 index 9 index Adobe_pattern_AI5 /patternfill get exec grestore newpath moveto 2 copy rmoveto } cforall 8 npop } def /patternashow { 0 0 0 6 3 roll patternawidthshow } def /patternawidthshow { 6 index type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get 7 1 roll } if _lineorientation 0 eq { hpatternawidthshow } { vpatternawidthshow } ifelse } def /vpatternawidthshowstroke { 7 1 roll 6 1 roll /_hvay exch ddef /_hvax exch ddef /_hvwb exch ddef /_hvcy exch ddef /_hvcx exch ddef { dup cstring dup length 1 eq _charorientation 1 eq and { -90 rotate currentpoint _fontRotateAdjust add moveto gsave false charpath currentpoint 3 index setmatrix 6 index 6 index 6 index Adobe_pattern_AI5 /patternstroke get exec grestore _fontRotateAdjust sub moveto _hvwb eq { _hvcx _hvcy rmoveto } if _hvax _hvay rmoveto 90 rotate } { currentpoint _fontHeight sub _hvax sub 3 index _hvwb eq { _hvcx sub } if currentpoint exch 4 index stringwidth pop 2 div sub exch _fontAscent sub moveto gsave 2 index false charpath 4 index setmatrix 7 index 7 index 7 index Adobe_pattern_AI5 /patternstroke get exec grestore newpath moveto pop pop } ifelse } cforall 4 npop } def /hpatternawidthshowstroke { 7 1 roll { dup cstring exch gsave 3 index eq { 5 index 5 index rmoveto } if false charpath currentpoint 7 index setmatrix 10 index 10 index 10 index Adobe_pattern_AI5 /patternstroke get exec grestore newpath moveto 2 copy rmoveto } cforall 9 npop } def /patternashowstroke { 0 0 0 7 3 roll patternawidthshowstroke } def /patternawidthshowstroke { 7 index type /dicttype eq { patternmatrix /patternmatrix get 8 1 roll } if _lineorientation 0 eq { hpatternawidthshowstroke } { vpatternawidthshowstroke } ifelse } def end setpacking %%EndResource %%EndProlog %%BeginSetup Adobe_level2_AI5 /initialize get exec Adobe_screens_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_typography_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_blend_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_pattern_AI5 /initialize get exec Adobe_ColorImage_AI6 /initialize get exec Adobe_Illustrator_AI5 /initialize get exec [ 39/quotesingle 96/grave 130/quotesinglbase 131/florin 132/quotedblbase 133/ellipsis 134/dagger 135/daggerdbl 136/circumflex 137/perthousand 138/Scaron 139/guilsinglleft 140/OE 145/quoteleft 146/quoteright 147/quotedblleft 148/quotedblright 149/bullet 150/endash 151/emdash 152/tilde 153/trademark 154/scaron 155/guilsinglright 156/oe 157/dotlessi 159/Ydieresis 164/currency 166/brokenbar 168/dieresis 169/copyright 170/ordfeminine 172/logicalnot 174/registered 175/macron 176/ring 177/plusminus 178/twosuperior 179/threesuperior 180/acute 181/mu 183/periodcentered 184/cedilla 185/onesuperior 186/ordmasculine 188/onequarter 189/onehalf 190/threequarters 192/Agrave 193/Aacute 194/Acircumflex 195/Atilde 196/Adieresis 197/Aring 198/AE 199/Ccedilla 200/Egrave 201/Eacute 202/Ecircumflex 203/Edieresis 204/Igrave 205/Iacute 206/Icircumflex 207/Idieresis 208/Eth 209/Ntilde 210/Ograve 211/Oacute 212/Ocircumflex 213/Otilde 214/Odieresis 215/multiply 216/Oslash 217/Ugrave 218/Uacute 219/Ucircumflex 220/Udieresis 221/Yacute 222/Thorn 223/germandbls 224/agrave 225/aacute 226/acircumflex 227/atilde 228/adieresis 229/aring 230/ae 231/ccedilla 232/egrave 233/eacute 234/ecircumflex 235/edieresis 236/igrave 237/iacute 238/icircumflex 239/idieresis 240/eth 241/ntilde 242/ograve 243/oacute 244/ocircumflex 245/otilde 246/odieresis 247/divide 248/oslash 249/ugrave 250/uacute 251/ucircumflex 252/udieresis 253/yacute 254/thorn 255/ydieresis TE %AI3_BeginEncoding: _Helvetica Helvetica [ /_Helvetica/Helvetica 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-Bold Helvetica-Bold [ /_Helvetica-Bold/Helvetica-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-Oblique Helvetica-Oblique [ /_Helvetica-Oblique/Helvetica-Oblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-BoldOblique Helvetica-BoldOblique [ /_Helvetica-BoldOblique/Helvetica-BoldOblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Roman Times-Roman [ /_Times-Roman/Times-Roman 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Bold Times-Bold [ /_Times-Bold/Times-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Italic Times-Italic [ /_Times-Italic/Times-Italic 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-BoldItalic Times-BoldItalic [ /_Times-BoldItalic/Times-BoldItalic 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier Courier [ /_Courier/Courier 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-Bold Courier-Bold [ /_Courier-Bold/Courier-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-Oblique Courier-Oblique [ /_Courier-Oblique/Courier-Oblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-BoldOblique Courier-BoldOblique [ /_Courier-BoldOblique/Courier-BoldOblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Symbol Symbol [ /_Symbol/Symbol 0 0 1 TZ %AI3_EndEncoding AdobeType %%EndSetup 1 XR u 0.000 0.000 0.000 0.000 k [] 0 d 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 145.7008 355.4646 m 217.7008 355.4646 L 217.7008 391.1811 L 145.7008 391.1811 L 145.7008 355.4646 L B U 0 To 1.0000 0.0000 0.0000 1.0000 167.2441 377.0079 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (NUA/\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 151.9370 362.2677 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0.000 0.000 0.000 1.000 k (Sofia stack\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 J 1 j 181.4173 355.4646 m 181.4173 58.3937 L S U u 0.000 0.000 0.000 0.000 k 172.3465 94.1102 m 190.4882 94.1102 L 190.4882 310.1102 L 172.3465 310.1102 L 172.3465 94.1102 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 145.7008 255.6850 m 217.7008 255.6850 L 217.7008 283.4646 L 145.7008 283.4646 L 145.7008 255.6850 L B U 0 To 1.0000 0.0000 0.0000 1.0000 149.1024 265.8898 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (setup media\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 370.7717 310.1102 m 193.8898 310.1102 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 194.4567 307.8425 m 190.4882 310.1102 L 194.4567 312.3780 L 194.4567 307.8425 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 256.8189 313.5118 m 303.8740 313.5118 L 303.8740 324.8504 L 256.8189 324.8504 L 256.8189 313.5118 L F U 0 To 1.0000 0.0000 0.0000 1.0000 257.3858 316.3465 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (INVITE / SDP\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 190.4882 219.9685 m 366.8031 219.9685 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 366.8031 222.2362 m 370.7717 219.9685 L 366.8031 218.2677 L 366.8031 222.2362 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 260.2205 223.3701 m 300.4724 223.3701 L 300.4724 234.7087 L 260.2205 234.7087 L 260.2205 223.3701 L F U 0 To 1.0000 0.0000 0.0000 1.0000 260.7874 226.7717 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (100 Trying\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 190.4882 185.3858 m 366.8031 185.3858 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 366.8031 187.6535 m 370.7717 185.3858 L 366.8031 183.1181 L 366.8031 187.6535 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 257.9528 188.7874 m 302.1732 188.7874 L 302.1732 200.6929 L 257.9528 200.6929 L 257.9528 188.7874 L F U 0 To 1.0000 0.0000 0.0000 1.0000 259.0866 191.6220 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (180 Ringing\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 190.4882 147.9685 m 366.8031 147.9685 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 366.8031 150.2362 m 370.7717 147.9685 L 366.8031 146.2677 L 366.8031 150.2362 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 255.6850 151.3701 m 305.0079 151.3701 L 305.0079 162.7087 L 255.6850 162.7087 L 255.6850 151.3701 L F U 0 To 1.0000 0.0000 0.0000 1.0000 256.8189 154.7717 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (200 Ok / SDP\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 172.9134 94.1102 m 14.1732 94.1102 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 14.1732 91.8425 m 10.2047 94.1102 L 14.1732 95.8110 L 14.1732 91.8425 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 68.0315 97.5118 m 115.0866 97.5118 L 115.0866 108.8504 L 68.0315 108.8504 L 68.0315 97.5118 L F U 0 To 1.0000 0.0000 0.0000 1.0000 69.1654 100.3465 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (nua_i_active\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 370.7717 103.1811 m 193.8898 103.1811 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 194.4567 100.9134 m 190.4882 103.1811 L 194.4567 104.8819 L 194.4567 100.9134 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 270.9921 106.0157 m 289.7008 106.0157 L 289.7008 117.3543 L 270.9921 117.3543 L 270.9921 106.0157 L F U 0 To 1.0000 0.0000 0.0000 1.0000 271.5591 109.4173 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (ACK\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.000 k 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 145.7008 111.6850 m 217.7008 111.6850 L 217.7008 139.4646 L 145.7008 139.4646 L 145.7008 111.6850 L B U 0 To 1.0000 0.0000 0.0000 1.0000 161.0079 129.2598 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (activate\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 164.9764 114.5197 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k (media\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 9.6378 208.6299 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k (\(1\)\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 9.6378 45.9213 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k (\(1\) optional, if NUTAG_AUTOANSWER is set the 200 Ok\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 9.6378 31.1811 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k (response is sent directly by NUA stack\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 172.3465 238.1102 m 14.1732 238.1102 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 14.1732 235.8425 m 10.2047 238.1102 L 14.1732 239.8110 L 14.1732 235.8425 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 69.1654 241.5118 m 113.3858 241.5118 L 113.3858 252.8504 L 69.1654 252.8504 L 69.1654 241.5118 L F U 0 To 1.0000 0.0000 0.0000 1.0000 70.2992 244.3465 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (nua_i_invite\r) Tx TO 0.000 0.000 0.000 1.000 K u [8 4 ] 0 d 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 10.2047 202.3937 m 168.9449 202.3937 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 168.3780 204.0945 m 172.3465 202.3937 L 168.3780 200.1260 L 168.3780 204.0945 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 56.6929 205.7953 m 126.4252 205.7953 L 126.4252 217.1339 L 56.6929 217.1339 L 56.6929 205.7953 L F U 0 To 1.0000 0.0000 0.0000 1.0000 57.8268 208.6299 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr [] 0 d 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (nua_respond\(180\)\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 10.2047 166.1102 m 169.5118 166.1102 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 168.9449 167.8110 m 172.9134 166.1102 L 168.9449 163.8425 L 168.9449 167.8110 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 57.2598 169.5118 m 126.4252 169.5118 L 126.4252 180.8504 L 57.2598 180.8504 L 57.2598 169.5118 L F U 0 To 1.0000 0.0000 0.0000 1.0000 58.3937 172.3465 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (nua_respond\(200\)\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 342.4252 226.7717 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0.000 0.000 0.000 1.000 k (\(1\)\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 342.4252 190.4882 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k (\(2\)\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 9.6378 9.6378 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k (\(2\) sent automatically if NUTAG_AUTOALERT set\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 324.8504 190.4882 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k (\(1\)\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 9.6378 172.3465 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k (\(1\)\r) Tx TO 0.000 0.000 0.000 1.000 K %%PageTrailer gsave annotatepage grestore showpage %%Trailer Adobe_Illustrator_AI5 /terminate get exec Adobe_pattern_AI5 /terminate get exec Adobe_blend_AI5 /terminate get exec Adobe_ColorImage_AI6 /terminate get exec Adobe_typography_AI5 /terminate get exec Adobe_screens_AI5 /terminate get exec Adobe_level2_AI5 /terminate get exec %%EOF II*  (@33GG\\pp""11@@OO^^nn}}""++33<yӫp3u^߷kw]]||Y 8P5gVW{vaoq%ś p y$(cb8i6X\:cJ0XmrnD"TXy<>)EIeex2_e_ci]ly%rfDniy{I[J*f5墌"V>*~NjuInex)ryUUj3)~fZ$Nerֺޭ&6=(~)fkTkqyKkA`zӹ:ƬjZn^ bF׉7k6om[7G|W g, 鯝-'#`N+;eJ֌rY["&\.qZb!jy*(ss}%-J[je~v%w-ئ=^ekkhwMρkӾ Xb>W#]wᲬK;]Rk:BnϑSsLrۻ{;qKgy57|8`A&TaC!F8`1fLhQcGA9dI'Q6J+] `L6SԹgO?yfGV`(ѠOF:jբVw6źkW_j5qK2̴d](l]weHW/D}<‡'V_Ə!Gd˗1gsgϟ=t釕MVZ1j-_}kҶpfwʿ{>"đ'WxϡGG\tןS{͟{?xs&qohOX 9#P4ʩ&٪6iM Ӯ 9JA Eʥ+Q8-00E , FU\q!pG1*mz0oA4Fgҹ,R-U/p:Q.O!2 OL*2/6KQqN:SA -CMTEmG!3l uܠl/)M}L -)KMaLcWmA\s/6SתRdS]Y[]7Z6fuOjͶmR?OS"l-M5Wݹ< ᕏt׭7Nt I=U~K2)O/}X.50=90E./M 'ڸplPsf~+-XΛy3?QwOd6.nYaՎY%a:gZhtBtgwk.Z넯f;ꦽzNWpzszuTbWoߥ>hǑ.z`c,q\9<"nYt5 ]}lFj{?gYMzƟ>--q)NtnlػI1}\ <0… :|1ĉX1ƍ;z2F$K<2ʕ,[| f4Sά3Ν<{J XQ6:} 5ԩT!.=it`֤LrmZ5رd˚]xҙ[ 횶dܳtڽܼ 8~3,l8Ō#]{x%⃓Vn9f{/~ :׮Z)f-˛[~6njѡBVxSunӴW ٻ?'}?|H p`)`[Z5RFpRD9ȡa.&a[ofa*.T0HZq:c>dh\DPF&d-dRהV^9Wn_\~`Id jne^qILYgAIDx Z}6[$FQ6n S(Jۢ6hF C~ VDYjĭ*5kdzYPk(Hm%W>{N[^ԲX,nm2[&Me ۆ%{nb.^e[lKYJ6 r}Kq_L1V1l?%pVr,KoHl2k2̠,80+Ai]t>'%OWBԖYtQSK3 *Cm_ZVD(7* V.\7Y:6xE :HA N]+uHdb L9N gpW5+n9#vÝьY5i^_&C)}j#ju;<]jR$\W>8g,]>+'WrUCg G8R*ͦRK)Tڄ<_ "e%Akgn׼KSss- *MГ)z1S][U > ְud[ >4n]0mK\|lj٦a&2R =gTيSb3<)9zSv7Ή괠CAqOOL+ԕ3,VATYR6lZ"ijY %$XA .dC%NXE5nǂH*\ȰÇ#JHŋ3jȱǏ CIc()Lɲ˗0cʜ q%͘6oɳϟ%s)tѣH*uYbSO68UbեXjUՉ'Bj0,¯5]˶MW[ ]pu˷߿ :{T9 ̸cP8W?̹3deڵL6dϨSioհc<۸kͻѲmNȑ6 SУ/5fik:q҅E,>3er_Ϟ+ǧ|%X h1ʓY&iXiN*ie\&]P:+",6ޱF;ZJkmwi fkѶ݆ҷ▫mBR+koOޫ//N+0Kl0QG/F ?,qNl1=^qvoln l'K<'A,'$23|̴e6LܳN8a&H::%EԽB5VzZ`_IuL;|OǍذ~",5{7^-8\C8ONgw{n9?oz$FUo6t+ܰzGEh3{"Wٝg{yqO_nڇЯ=պ;~֞o޺[mW,l?N?[ hGj)gps B]NM;l )Թءl?àX}z! 1 f24_DCeM~Δ!fe c!,botK"KUm?9ƤX p7J=EWFG-:ֻuiIhÝezzH>S$#-NͺarIuIۤKl4@$[5,h „ 2l!Ĉ'R"7r@cƁA )#J% 4Y%˘)gҬi&Μ a>Ò5d9ˑ?,J'G-a\ (֬ZrU+XE&iR)Yeڔ* Uaҭkkūwo eɓh*eM/}1szlPsRڐТG/4].5؈%m6ܺ^7қ/آ*owcҧ3n :f.޻?eѻ>_\˳[}f)I'R|5%Z}9(~ &X`f%x`Z![5 EV 2uq !hh6b92Yvm'V88ddiG*$$QJSSZy%eVe]z%s\~9&JY&i"mޙ UjgT&ũa6wօ %h&vHu(!xg(?IܡާbBzj:+U+j*rtkۯ:'&ʬ yj-z-Z;.=v)n{.Ȗi/au%/¯a1h%<_Z/Sqz 2g)u2l,rP"u_>ͧ+?3_㯽_߿Fot*0x l` R2qrSi!Nӷu0Bavlw>jN.ܓݬO;!vЄ'n#pʯ|HtٚȊPѢF5tKaB4"!6L>Gao#hnQc;;gZ 2] -76O=<$kP0'/L&T"RGV"D"!JK87۠8&ptEؑ_t$XFhZF / INS/L_b1!ULf\g 5Nx@brn`ig!Kԙ%: =(Bk di<*t5uh 03b_Mmlc#K5ktC)DB]2+PS5uOCMF~ʦaCI93(\J Gd #g:e3[WѕAd{ZoprX Ŧӆ jR26CCZ3to(Z ʍѪwVҙJZZ,d#+R,f3rJ0u8US :Qmj)!j-ϰ=S$99,O/Ж~+D2^jј6:*G9Z{ɱm];؎TYc*%:+ kBsL'vQq5yyUc~׽3*r7mtbD flNnFioYގ501 BjQgCs`p~"6sSVѽ)$: < = !"#$%&'()*+,-./0123456789:;Root EntryFg$B@VisioDocument)SummaryInformation(EDocumentSummaryInformation8Visio (TM) Drawing )\ (VRd !fffMMM333$ $ U8@ TD Arial@NMonotype Sorts@m Wingd NtSymbol5T?? Y@-1U J:DT1EW-hPT8*  .U_b a酸0zGz?@3CfRbU|||%U P } |KpG/Y&4Y$? v AfY&,,' /Dq&z&} | |y  }{})} ?2  | | ||||*|||E-?k4'-'CECE,'*CECECE-?H>?:`}'CEUCECECECEUCECE- O4F2AJY;; AnVnVAbGTfY R_R__ `#f:/lb6p`fW /l /l  Y?5?(\ #!+ | tFf-|J-|-|-wG QUo "OM`EtoA _3=OOOaOsO@O??O?7ܻuR? sU/-O%7I[mRf J+ K5   . ||i| d' 0/UKiR?d?v4Gzt2#&Us s s s) -0jӯY/ƛ!3)󿵶1D///Q+p)?HdYc4AkǿٿYfU|%1I߀O]-(fp ɻ %-=Y[:!#:4)A/q//YkϹ/p?2 Sπ'9}Fɇ7%õ8@\n1$u  (:L^p)BH>ZՔU \ n4!'4#U2q ?/%&k/%&`,`,`',ѓ4?|QԞQyٓA G $z Z$bp6q /#3=/Uq@T0'vr@1N!T0;UOauADV=煤{2r H+"P)Ҳ$2@1@1B,$1//cAm/ߙ߫BVVj /Q?c?u4D?U0O贁 NkRC6$SfMea5t(O"?2RO}q19!S _2_D_"3Htr+*a__//5o2DV õoa`oo1 I+< g4`\\esprn002\HER1F5B1S odWX+'?LetterO_b PRIV0|'r\KhC]>w!tuy //-/?/Q/c/u////////??)?;?M1E%winspool\\esprn002\HER1F5B1IP_172.21?.36.10UFDfP h-RTUUUA@ ?I?a 3h AeqYk Hu_ Q? #,BDrag between shapes to indicate a flow offormation or control.mb?sߛ⿻xw?t? 8HD    3h <>T$  ;MBRAU@?N ?AP6 Ju `u buU  -J ">ۀJuM` Zue"JD4WAQ @%UI>J[@hK'F"U/g%'_-/g JQ#5 L"V &6 霑c ?@IW0?@q`0U>U5Q?!9[a2f`rd}b0@3&/0`A.=@2M @J2uF.3B B$fH2&M+3Q(-DT! @6[Dн8P$?J 3tNsWB Ld!%6 MB##0O贁Nk?<$2%@@PR%|#xQ}T5 B`7Copyright 1999 Visio Corporation. All Rs reserved.J`P_SCPchm!#22776G#2r5ofP"JSfunq&^(E9 Yr[xQ4 0UChange Arrow?head..PVcthe ae siz`n`tyle for`is connectorP1`Bb)WlJhUd>5 yG|(AJ*C<4bZw"M (3,rx srA iVohot'd1dxB3d+=-C2U낥@6f 32`_D/@>W4C)rp -3TqC@@JQ\^E? v!3?|@ 2Pa@0pqB;uK`u`WE @ǗHXC1 aVHl'-d! !Oya HE_9bF ~# . B  U]Ma,k]@+ ]/aTo fPUl4,"H$ @Y,b'@ P NA-|3T7U2@Q Z7BRH<( U2ELQ 7 R(n S =@? =RD< Oi{ UP?V]U$5@*P8FDTey  ahm qTP^UI"H$ @IY,b'@? ?I*M_q2?p^qu2`"ua )elT VU Ea !H!$'$a'$y!'y!(}!'}!(!'!(!'!('$!'!(!'!(!'!(!'!('!(!'!(!'!('(!'(!'!(!'!(!'!(# qP!a!!y!!!!!!9R!!!!!!!!!!!!E___!5iy!|a1m =5 `@*#dn?e/a%f'/PrJ!!0qUQ!w5%y% `Hr-r.-h}! "v*w#d7I=5qZ52ŏ!r 28!NUA/ Sofia? stack"% oo0oBoToko@deGP-DT!f-qu `u `bu `u .@"qx @~xѤo}'r›ofF@$t~t¿Թ>uat`Nt%E{kU{ *ߏaeE~ϜP!`"aL5C}! Z5ߕ}!, U&W8qkEfĞ޾e @@&@A?c *;&fT=3 q!t " 圭ff@I{Ͽ@qy?֋Q(وu`@$a!:8^Ѡ2`ќ tNΡzs (< &߯J# .@$0y!id^ko}oZ(Z(82USQ՗#=5T'nua_i_?invite"y%:8*P9K?/Ssyff}VoYo{Z$Hsco#5GA@aOOO̟V OOQ_"Mwic ș_@a_]#_6o+o=oOoaosoo .ci#oۖu4CbtsƳ"isetup med ia6צؿJ\nߗk*"ۀg̀kV"o͓%/H yם馱B//?Tõ@?٦b?t???????rO9OKO`r INVITE / SDP6-Q-U˿ݿ#7YWpςϨ4.d/v/)-Qt߆/,/&P-]oi-Q);t_q^OpON100 Trying6 E1eL?e"$6H;5}:Nd1(:L^p,|T75l_Y1//L/7/I/[/m///////.>180 R05h?a;?#_?q?`????:p{ @@S2 8sOO[cXp3wSOeOwOu8mOOaOOΒ_._jR_TuC_ba_____"o oo~BoTofoxooooonua_respond(200)bo&8#πG ??̖);MO؏dÏՏ/Vxҟ1o,>Pbt.$Ġ Ok9ѯ1(:L^pepP-DT! ȿ24%_@Bg(\CϭϿ/1ϖ9,>Pbߛߘd[Q[+?=ﭬi_acti ver s8c6) a,c+kh|84B\@@x8@@"?@r`U?$%DQu`+?"uH9B !C-6--9LAcXwgy}UA >X"9p39A45&?75O7N%PObOG4r>OOO4?IO_mN8k2(1ǣo_? ~4𙿫[Ͽbfb`W?88w8Us9K]/Uy$6Zl~\ACKR //Nq\N/`-8/u uvf5v/??/19Ow???? #?`1_C_U_nMX'2.Q '2#+OuOrOCbtOuf_TU/rҖ p]cvZzqate media*5G3/k}i/{/// ,"///1!9'119F?oj?n?F_OOBOOO%OC,@y t_Z2SMq/?!/,?>?7$ sent automatically if NUTAG_AUTOALER=T0t jIv@O! 3\BjdFw vQϼ_qϕLc`` r߄'9KASVw/e?w??O/#/o/*oD??#oK?Yro}o& 14OOOOOOO__LSRq??TG_Y_k_}__CS>____o o2oDoVooo'$o olRd z-?Qcu υ؏ ٫Wi{ß՟EWi/S$E+{ߟ ;Mп⿃*<w$  8-U K-UUd-U  W <-UU\ |& $RA}(DH 0 x Ul4,"H$ @Y,bK'@ DR Q'UA-43_7;Ul4, S ' A>-R 7A_*<N@Q e' KRVg q7uH<( H<( _*<NEQ 9( RVg  Fq {th * g"4pFX(?@(oϫ@P  :TR q&^ !B, 2b>PPOjp܇Bl V$=' "Nc")<6 #X1^U T=`2^ cB?\ FD S(C=G ՜.+,D՜.+,@HP\h t   PagesMastersPage-1Directed line 18_VPID_PREVIEWS@_VPID_ALTERNATENAMES?_PID_LINKBASE A Oh+'0|EHPdp| rinnerahSIP outgoing callGDEhWRSt EMFD l@@VISIODrawing% %   &%   '% V0999% ( % (   Rp Arial,Uw@*wwTHz>THTHUw%wxTHx5`pu>,Uw(%w\xTHTHpu>\#` xdv%   TdAALTNUA/   T,AA LdSofia stack     % &%  W$% ( %  Rp  Arial,Uw@*wwTHTHTHUw%wxTHx`,Uw(%w\xTHTH>\#` xdv%  % &%   '% V0U   UU% ( % (  &%   '% V0999% ( % (   Rp Arial>,Uw@*wwz>THz>THTHUw%wxTHx5`,Uw(%w\xz>THz>TH>\#` xdv%   T0AA Ldsetup media     % &%  W$UEUEUU% ( %  '% % V, RYY URY% % (   '% % V0~<O~OO<~<~O% % (   Rp Arial>,Uw@*wwh>THh>XW|9W|z>@THTHUw%wxTHx>`,Uw(%w\xh>THh>THpu>\#` xdv%   T=LAAJ LdINVITE / SDP    % &%  W$ ? ?% ( %  '% % V,>E>E>>% % (   '% % V0% % (   Rp Arial>,Uw@*wwz>THz>XW|9W|h>@THTHUw%wxTHx>`,Uw(%w\xz>THz>TH\#` xdv%   TAA L`100 Trying  % &%  W$ /?/ /?/% ( %  '% % V,>,E3>,E/>3>,% % (   '% % V0))))% % (   Rp Arial>,Uw@*wwh>THh>XW|9W|z>@THTHUw%wxTHx>`pu>,Uw(%w\xh>THh>THpu>\#` xdv%   T&AA$ Ld180 Ringing  % &%  W$ q?q q?q% ( %  '% % V,>nEu>nEq>u>n% % (   '% % V0|Wk|kkW|W|k% % (   Rp Arial>,Uw@*wwz>THz>XW|9W|h>@THTHUw%wxTHx>`,Uw(%w\xz>THz>TH\#` xdv%   T~YhAA~f Ld200 Ok / SDP   % &%  W$% ( %  '% % V,% % (   '% % V03333% % (   Rp Arial>,Uw@*wwh>THh>XW|9W|z>@THTHUw%wxTHx>`pu>,Uw(%w\xh>THh>THpu>\#` xdv%   T5AA5 Ldnua_i_active % & %  W$EE% ( %  ' % % V,  % % (   ' % % V0% % (   Rp  Arial>,Uw@*wwz>THz>XW|9W|h>@THTHUw%wxTHx>`>,Uw(%w\xz>THz>TH>\#` xdv%   T`AALTACK  % & %   ' % V0999% ( % (  (  Rp Arial,Uw@*wwTHz>THTHUw%wxTHx5`>,Uw(%w\xTHTHX>\#` xdv%   T| AAL\activate     TlAALXmedia   % % (  Rp Arial>,Uw@*wwz>THz>THTHUw%wxTHx5`pu>,Uw(%w\xz>THz>THpu>\#` xdv%   T` AALT(1)  % % ( (  Rp Arial,Uw@*wwTHz>THTHUw%wxTHx5`>,Uw(%w\xTHTH>\#` xdv%   T(AA$3L(1) optional, if NUTAG_AUTOANSWER is set the 200 Ok              T0*'AAA=&Lresponse is sent directly by NUA stack           % &%  W$% ( %  '% % V,% % (  (  '% % V05555% % (   Rp Arial>,Uw@*wwh>THh>XW|9W|@THTHUw%wxTHx>`>,Uw(%w\xh>THh>TH\#` xdv%   T7AA7 Ldnua_i_invite % ( &%  W$% ( %  '% % V,% % (   '% % V0    % % (   Rp Arial,Uw@*wwTHXW|9W|h>@THTHUw%wxTHx>`pu>,Uw(%w\xTHTHpu>\#` xdv%   T! AA!Llnua_respond(180) % ( &%  W$RRRR% ( %  '% % V,NUNRUN% % (  (  '% % V0 8L LL8 8 L% % (   Rp Arial>,Uw@*wwh>THh>XW|9W|@THTHUw%wxTHx>`,Uw(%w\xh>THh>TH\#` xdv%   T"9HAA"FLlnua_respond(200) % % (  Rp  Arial>,Uw@*wwz>THz>h>THTHUw%wxTHx5`,Uw(%w\xz>THz>TH>\#` xdv%   T`*AALT(1)  % % (  Rp Arial>,Uw@*wwh>THh>z>THTHUw%wxTHx5`>,Uw(%w\xh>THh>TH>\#` xdv%   T`*+AA'LT(2)  % % (  Rp Arial>,Uw@*wwz>THz>h>THTHUw%wxTHx5`pu>,Uw(%w\xz>THz>THpu>\#` xdv%   T\QhAAd-L(2) sent automatically if NUTAG_AUTOALERT set              % %  Rp Arial>,Uw@*wwh>THh>z>THTHUw%wxTHx5`>,Uw(%w\xh>THh>TH>\#` xdv%   T` +AA'LT(1)  % ( % (  Rp Arial>,Uw@*wwz>THz>h>THTHUw%wxTHx5`pu>,Uw(%w\xz>THz>THpu>\#` xdv%   T`3JAAFLT(1)  % VisioInformation"sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/docs/pictures/SIP_outgoing_call.eps000066400000000000000000020657761223300710500264410ustar00rootroot00000000000000 j%!PS-Adobe-3.0 EPSF-3.0 %%Creator: ImageMark Software Labs %%For: () () %%Title: V:\work\rinnerah\sofia\SIP outgoing call.eps %%CreationDate: () () %%BoundingBox: 0 0 426 556 %%DocumentProcessColors: Black %%ColorUsage:Color %%DocumentFonts: Helvetica %%+Helvetica-Bold %%+Helvetica-Oblique %%+Helvetica-BoldOblique %%+Times-Roman %%+Times-Bold %%+Times-Italic %%+Times-BoldItalic %%+Courier %%+Courier-Bold %%+Courier-Oblique %%+Courier-BoldOblique %%+Symbol %%DocumentSuppliedResources: procset Adobe_level2_AI5 1.2 0 %%+ procset Adobe_screens_AI5 1.0 0 %%+ procset Adobe_typography_AI5 1.0 0 %%+ procset Adobe_ColorImage_AI6 1.1 0 %%+ procset Adobe_blend_AI5 1.0 0 %%+ procset Adobe_pattern_AI5 1.0 0 %%+ procset Adobe_Illustrator_AI5 1.0 0 %AI5_FileFormat 3.0 %AI3_ColorUsage: Color %AI3_TemplateBox: 0 0 426 556 %AI3_TileBox: 0 0 426 556 %AI3_DocumentPreview: None %%Template: %%PageOrigin:0.0000 0.0000 %AI7_GridSettings: 72 8 72 8 1 0 0.8 0.8 0.8 0.9 0.9 0.9 %%EndComments %%BeginProlog %%BeginResource: procset Adobe_level2_AI5 1.2 0 %%Title: (Adobe Illustrator (R) Version 5.0 Level 2 Emulation) %%Version: 1.2 0 %%CreationDate: (04/10/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /Adobe_level2_AI5 25 dict dup begin put /packedarray where not { userdict begin /packedarray { array astore readonly } bind def /setpacking /pop load def /currentpacking false def end 0 } if pop userdict /defaultpacking currentpacking put true setpacking /initialize { Adobe_level2_AI5 begin } bind def /terminate { currentdict Adobe_level2_AI5 eq { end } if } bind def mark /setcustomcolor where not { /findcmykcustomcolor { 0 6 packedarray } bind def /findrgbcustomcolor { 1 5 packedarray } bind def /setcustomcolor { exch aload pop 0 eq { pop 4 { 4 index mul 4 1 roll } repeat 5 -1 roll pop setcmykcolor } { pop 3 { 1 exch sub 3 index mul 1 exch sub 3 1 roll } repeat 4 -1 roll pop setrgbcolor } ifelse } def } if /gt38? mark {version cvr cvx exec} stopped {cleartomark true} {38 gt exch pop} ifelse def userdict /deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt put userdict /level2? systemdict /languagelevel known dup { pop systemdict /languagelevel get 2 ge } if put /level2ScreenFreq { begin 60 HalftoneType 1 eq { pop Frequency } if HalftoneType 2 eq { pop GrayFrequency } if HalftoneType 5 eq { pop Default level2ScreenFreq } if end } bind def userdict /currentScreenFreq level2? {currenthalftone level2ScreenFreq} {currentscreen pop pop} ifelse put level2? not { /setcmykcolor where not { /setcmykcolor { exch .11 mul add exch .59 mul add exch .3 mul add 1 exch sub setgray } def } if /currentcmykcolor where not { /currentcmykcolor { 0 0 0 1 currentgray sub } def } if /setoverprint where not { /setoverprint /pop load def } if /selectfont where not { /selectfont { exch findfont exch dup type /arraytype eq { makefont } { scalefont } ifelse setfont } bind def } if /cshow where not { /cshow { [ 0 0 5 -1 roll aload pop ] cvx bind forall } bind def } if } if cleartomark /anyColor? { add add add 0 ne } bind def /testColor { gsave setcmykcolor currentcmykcolor grestore } bind def /testCMYKColorThrough { testColor anyColor? } bind def userdict /composite? level2? { gsave 1 1 1 1 setcmykcolor currentcmykcolor grestore add add add 4 eq } { 1 0 0 0 testCMYKColorThrough 0 1 0 0 testCMYKColorThrough 0 0 1 0 testCMYKColorThrough 0 0 0 1 testCMYKColorThrough and and and } ifelse put composite? not { userdict begin gsave /cyan? 1 0 0 0 testCMYKColorThrough def /magenta? 0 1 0 0 testCMYKColorThrough def /yellow? 0 0 1 0 testCMYKColorThrough def /black? 0 0 0 1 testCMYKColorThrough def grestore /isCMYKSep? cyan? magenta? yellow? black? or or or def /customColor? isCMYKSep? not def end } if end defaultpacking setpacking %%EndResource %%BeginResource: procset Adobe_typography_AI5 1.0 1 %%Title: (Typography Operators) %%Version: 1.0 %%CreationDate:(03/26/93) () %%Copyright: ((C) 1987-1993 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_typography_AI5 54 dict dup begin put /initialize { begin begin Adobe_typography_AI5 begin Adobe_typography_AI5 { dup xcheck { bind } if pop pop } forall end end end Adobe_typography_AI5 begin } def /terminate { currentdict Adobe_typography_AI5 eq { end } if } def /modifyEncoding { /_tempEncode exch ddef /_pntr 0 ddef { counttomark -1 roll dup type dup /marktype eq { pop pop exit } { /nametype eq { _tempEncode /_pntr dup load dup 3 1 roll 1 add ddef 3 -1 roll put } { /_pntr exch ddef } ifelse } ifelse } loop _tempEncode } def /TE { StandardEncoding 256 array copy modifyEncoding /_nativeEncoding exch def } def % /TZ { dup type /arraytype eq { /_wv exch def } { /_wv 0 def } ifelse /_useNativeEncoding exch def pop pop findfont _wv type /arraytype eq { _wv makeblendedfont } if dup length 2 add dict begin mark exch { 1 index /FID ne { def } if cleartomark mark } forall pop /FontName exch def counttomark 0 eq { 1 _useNativeEncoding eq { /Encoding _nativeEncoding def } if cleartomark } { /Encoding load 256 array copy modifyEncoding /Encoding exch def } ifelse FontName currentdict end definefont pop } def /tr { _ax _ay 3 2 roll } def /trj { _cx _cy _sp _ax _ay 6 5 roll } def /a0 { /Tx { dup currentpoint 3 2 roll tr _psf newpath moveto tr _ctm _pss } ddef /Tj { dup currentpoint 3 2 roll trj _pjsf newpath moveto trj _ctm _pjss } ddef } def /a1 { /Tx { dup currentpoint 4 2 roll gsave dup currentpoint 3 2 roll tr _psf newpath moveto tr _ctm _pss grestore 3 1 roll moveto tr sp } ddef /Tj { dup currentpoint 4 2 roll gsave dup currentpoint 3 2 roll trj _pjsf newpath moveto trj _ctm _pjss grestore 3 1 roll moveto tr jsp } ddef } def /e0 { /Tx { tr _psf } ddef /Tj { trj _pjsf } ddef } def /e1 { /Tx { dup currentpoint 4 2 roll gsave tr _psf grestore 3 1 roll moveto tr sp } ddef /Tj { dup currentpoint 4 2 roll gsave trj _pjsf grestore 3 1 roll moveto tr jsp } ddef } def /i0 { /Tx { tr sp } ddef /Tj { trj jsp } ddef } def /i1 { W N } def /o0 { /Tx { tr sw rmoveto } ddef /Tj { trj swj rmoveto } ddef } def /r0 { /Tx { tr _ctm _pss } ddef /Tj { trj _ctm _pjss } ddef } def /r1 { /Tx { dup currentpoint 4 2 roll currentpoint gsave newpath moveto tr _ctm _pss grestore 3 1 roll moveto tr sp } ddef /Tj { dup currentpoint 4 2 roll currentpoint gsave newpath moveto trj _ctm _pjss grestore 3 1 roll moveto tr jsp } ddef } def /To { pop _ctm currentmatrix pop } def /TO { iTe _ctm setmatrix newpath } def /Tp { pop _tm astore pop _ctm setmatrix _tDict begin /W { } def /h { } def } def /TP { end iTm 0 0 moveto } def /Tr { _render 3 le { currentpoint newpath moveto } if dup 8 eq { pop 0 } { dup 9 eq { pop 1 } if } ifelse dup /_render exch ddef _renderStart exch get load exec } def /iTm { _ctm setmatrix _tm concat 0 _rise translate _hs 1 scale } def /Tm { _tm astore pop iTm 0 0 moveto } def /Td { _mtx translate _tm _tm concatmatrix pop iTm 0 0 moveto } def /iTe { _render -1 eq { } { _renderEnd _render get dup null ne { load exec } { pop } ifelse } ifelse /_render -1 ddef } def /Ta { pop } def /Tf { dup 1000 div /_fScl exch ddef % selectfont } def /Tl { pop 0 exch _leading astore pop } def /Tt { pop } def /TW { 3 npop } def /Tw { /_cx exch ddef } def /TC { 3 npop } def /Tc { /_ax exch ddef } def /Ts { /_rise exch ddef currentpoint iTm moveto } def /Ti { 3 npop } def /Tz { 100 div /_hs exch ddef iTm } def /TA { pop } def /Tq { pop } def /Th { pop pop pop pop pop } def /TX { pop } def /Tk { exch pop _fScl mul neg 0 rmoveto } def /TK { 2 npop } def /T* { _leading aload pop neg Td } def /T*- { _leading aload pop Td } def /T- { _hyphen Tx } def /T+ { } def /TR { _ctm currentmatrix pop _tm astore pop iTm 0 0 moveto } def /TS { currentfont 3 1 roll /_Symbol_ _fScl 1000 mul selectfont 0 eq { Tx } { Tj } ifelse setfont } def /Xb { pop pop } def /Tb /Xb load def /Xe { pop pop pop pop } def /Te /Xe load def /XB { } def /TB /XB load def currentdict readonly pop end setpacking %%EndResource %%BeginResource: procset Adobe_screens_AI5 1.2 0 %%Title: (Adobe Illustrator (R) Version 5.0 Custom Halftone Screens ProcSet) %%Version: 1.2 0 %%CreationDate: (03/24/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking systemdict begin userdict /Adobe_screens_AI5 15 dict dup begin put /initialize { Adobe_screens_AI5 begin /screenid deviceDPI 600 gt composite? not or { -1 } { deviceDPI currentScreenFreq dup dup 60 ge exch 150 le and deviceDPI 300 le and { pop 60 } if div 1.41421 div 0.5 add cvi } ifelse def 2 screenid eq { /customsize 16 def /customdata /customdata2 def setcustomscreen } if 3 screenid eq { /customsize 24 def /customdata /customdata3 def setcustomscreen } if 4 screenid eq { /customsize 16 def /customdata /customdata4 def setcustomscreen } if 5 screenid eq { /customsize 20 def /customdata /customdata5 def setcustomscreen } if 6 screenid eq { /customsize 24 def /customdata /customdata6 def setcustomscreen } if 7 screenid eq { /customsize 28 def /customdata /customdata7 def setcustomscreen } if 8 screenid eq { /customsize 16 def /customdata /customdata8 def setcustomscreen } if } def /terminate { currentdict Adobe_screens_AI5 eq { end } if } def /setcustomscreen { deviceDPI customsize div 0 { 1 add 2 div customsize mul cvi exch 1 add 2 div customsize mul cvi exch customsize mul add customdata load exch get 256 div } setscreen } def /customdata2 28 28 mul string def currentfile customdata2 readhexstring 4180E8694988E2634382EA6B4B8AE061A01939C8A81737C2A21B3BCAAA1636C0 F8795998F6775796FA7B5B9AF57656952ED8B80727D6B60F2FDABA0626D5B50E 4E8DE6674786EE6F4F8EE5664685ED6EAD1434C6A61F3FCEAE1232C5A51E3ECD F3745493FE7F5F9EF1725291FD7E5E9D24D3B30C2CDEBE0222D1B10A2ADDBD04 4483EB6C4C8BE1624281E96A4A89E364A31C3CCBAB1535C1A11A3AC9A91838C3 FB7C5C9BF4755594F97A5A99F778589730DBBB0525D4B40D2DD9B90828D7B710 508FE4654584EC6D4D8CE7684887EF70AF1131C4A41D3DCCAC1333C7A72040CF F0715190FC7D5D9CF2735392FF80609F21D0B00929DCBC0323D2B20B2BDFBF01 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata3 28 28 mul string def currentfile customdata3 readhexstring 011DC7F5E73D0421CBF3E43A021EC8F6E83E0522CCF2E43A2B648BC4A0762F68 8AC39E732C658CC5A177306989C29D72D5B6521A6192D9B55219608FD6B6531B 6193DAB451185F8FFCEE440C28D2FCED430B27D1FDEF450C29D3FBEC420A26D0 BEA77D366F83BCA77C356E87BFA87E377082BBA67B346D86145B99E0AE4A1259 98DFB14E155C9AE1AD4A115897DEB04D0623CDF4E63C0420CAF8EA400723CDF4 E53B031FC9F7E93F316988C19F752E678EC6A378326A88C09F742D668DC6A278 DBB350175E91D8B8551C6395DCB24F165D90D7B7541C6294FAEC420925CFFFF1 470E2BD5F9EB410824CEFEF0460D2AD4BAA57A336C85BEAA80397180B9A47933 6B84BDA97F387181105797DDAF4C145A9CE3AB480F5696DDAE4B13599BE2AC49 021EC8F6E83E0522CCF2E43A011DC7F5E73D0421CBF3E43A2C658CC5A1773069 89C29D722B648BC4A0762F688AC39E73D6B6531B6193DAB451185F8FD5B6521A 6192D9B55219608FFDEF450C29D3FBEC420A26D0FCEE440C28D2FCED430B27D1 BFA87E377082BBA67B346D86BEA77D366F83BCA77C356E87155C9AE1AD4A1158 97DEB04D145B99E0AE4A125998DFB14E0723CDF4E53B031FC9F7E93F0623CDF4 E63C0420CAF8EA40326A88C09F742D668DC6A278316988C19F752E678EC6A378 DCB24F165D90D7B7541C6294DBB350175E91D8B8551C6395F9EB410824CEFEF0 460D2AD4FAEC420925CFFFF1470E2BD5B9A479336B84BDA97F387181BAA57A33 6C85BEAA803971800F5696DDAE4B13599BE2AC49105797DDAF4C145A9CE3AB48 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata4 28 28 mul string def currentfile customdata4 readhexstring 1139B8E0FAD2531B133BBAE2F8D05119417180A6AE9A7B4B437382A5AD987949 C08867272F6F92CAC28A66262E6E90C8E8DE5F070F37B6F2EADD5E060E36B5F0 FED6571F173FBEE6FDD5561E163EBDE5AB9E7F4F477786A1A99D7E4E467685A3 2C6C96CEC68E62222A6A95CDC58D64240C34B3F6EED95A020A32B1F5EDDB5C04 143CBBE3F9D1521A123AB9E1FBD3541C447483A4AC997A4A427281A7AF9B7C4C C38B65252D6D91C9C1896828307093CBEBDC5D050D35B4F1E9DF60081038B7F3 FCD4551D153DBCE4FFD758201840BFE7A89C7D4D457584A2AA9F8050487887A0 296994CCC48C63232B6B97CFC78F61210931B0F4ECDA5B030B33B2F7EFD85901 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata5 28 28 mul string def currentfile customdata5 readhexstring 010B34C3EBFCF7CE3F16020C35C4EDFBF6CD3E15102552A4D6EADDB5632B1126 54A5D5EADCB3622A3958768499C19E8C7C5E3A59778498C19D8B7B5DC8A99370 47334C7587AFC9AA936F46324B7485AEF1E5BC6B1E0A2351A3D8F2E4BC6A1E09 2351A2D7FFF9D14219050F38C6EFFEF9D04118040E37C6EFE8E0B7662D142856 A8D3E7DFB7652D132856A7D4BF9C8E7F603D5B7A8195BE9A8E7E603C5B798297 314A7389B2CCAD906D442F497289B1CBAC926E4508214FA1DBF4E2B9671B0720 4EA0DAF4E3BA691C030D36C5EDFBF6CD3F16010C34C3ECFDF8CF4017122654A6 D4E9DDB4622A112553A5D6EBDEB5642C3B59788397C09C8B7C5D3A58778599C2 9E8C7D5FCAAB926E46314B7486AFC8AA947048334D7587B0F2E4BB691D082250 A1D8F1E6BD6B1F0A2452A3D9FDF8CF4118030E36C5EEFFFAD1421A050F38C7F0 E6DFB6642C132755A7D3E8E1B8662E152957A8D2BE9A8D7E5F3B5A798296BF9B 8F80613D5C7B80952F487188B1CAAC916D443049728AB3CCAE906C43061F4D9F DAF3E2BA681C07214FA0DBF5E1B8671A00000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata6 28 28 mul string def currentfile customdata6 readhexstring 081A44B6E0F2FDECC150250C091B45B6E1F3FCEBC04F240C1D336199C7D8DCD3 A56C37221E33619AC8D7DBD2A46B36214864798091AEB1958C7E694C49657A81 90ADB0948B7D684BB99D8475593C405C7888A1BEBA9E8574583B3F5B7888A0BD E4CBAA712E1215326098CFE8E4CCA9712D1114315F97CEE7F5F1C6552B040719 43B5DFFAF6F0C6542A03061842B4DEF9FFEDC352270E0B1C47B8E3F4FEECC251 260D0A1C46B7E2F4DAD5A76E39232035639CCAD5D9D4A66D38231F34629BC9D6 AF938E806A4E4A677C838FABAE928D7F694D4A667B828FAC3E5A778AA3BFBC9F 8772563A3D597689A2BEBB9F8673573A14305E97D1EAE6CDA76F2B0F132F5D96 D0E9E5CDA8702C10051742B3DDFCF8EEC4522801041641B2DDFBF7EFC5532902 091B45B6E1F3FCEBC04F240C081A44B6E0F2FDECC150250C1E33619AC8D7DBD2 A46B36211D336199C7D8DCD3A56C372249657A8190ADB0948B7D684B48647980 91AEB1958C7E694CBA9E8574583B3F5B7888A0BDB99D8475593C405C7888A1BE E4CCA9712D1114315F97CEE7E4CBAA712E1215326098CFE8F6F0C6542A030618 42B4DEF9F5F1C6552B04071943B5DFFAFEECC251260D0A1C46B7E2F4FFEDC352 270E0B1C47B8E3F4D9D4A66D38231F34629BC9D6DAD5A76E39232035639CCAD5 AE928D7F694D4A667B828FACAF938E806A4E4A677C838FAB3D597689A2BEBB9F 8673573A3E5A778AA3BFBC9F8772563A132F5D96D0E9E5CDA8702C1014305E97 D1EAE6CDA76F2B0F041641B2DDFBF7EFC5532902051742B3DDFCF8EEC4522801 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata7 28 28 mul string def currentfile customdata7 readhexstring 01061B44B7E1F5FEFBE6BD4A210C01071B45B8E1F6FDFBE6BC4A200B09132A54 A7D1EAF5EED9B05D331609142B55A8D2EAF4EED9AF5C32161D2D3D6993C1CBE0 CEC59B7140301E2E3D6A93C0CADFCDC49A713F3047576C7B828DA2B6A48F867E 6F5A48576C7C828CA1B6A38F867E6E59BAAA958A78634E4451667A8498ADBAAB 968977624E4350657A8398ADE3D4C99F7539251A273C6892C2D7E4D4C89E7539 241A273B6891C1D6F8F2DDB460371005122A53A7D0ECF9F2DDB360360F051229 53A6D0EBFFFDE8BE4C220D03081D46B9E3F7FFFCE7BD4B210D02071C46B8E2F7 F3F0DBB15E34180B152C56A9D3E8F3EFDAB05D34170A142C55A9D2E9DFCCC69C 7341321F2F3F6B94BFC9DECCC59C7241311F2E3E6A94BFCAB5A38E8780705B49 596D7D808BA0B4A28D877F6F5B48586D7C818BA043506479859AAFBCAC978876 614C424F64798499AEBBAB968977624D19263B6791C3D8E5D6C79D7337231825 3A6690C3D7E5D5C79E74382304112952A5CFEDFAF0DBB25E350E03102851A5CE ECF9F1DCB25F360E01071B45B8E1F6FDFBE6BC4A200B01061B44B7E1F5FEFBE6 BD4A210C09142B55A8D2EAF4EED9AF5C321609132A54A7D1EAF5EED9B05D3316 1E2E3D6A93C0CADFCDC49A713F301D2D3D6993C1CBE0CEC59B71403048576C7C 828CA1B6A38F867E6E5947576C7B828DA2B6A48F867E6F5ABAAB968977624E43 50657A8398ADBAAA958A78634E4451667A8498ADE4D4C89E7539241A273B6891 C1D6E3D4C99F7539251A273C6892C2D7F9F2DDB360360F05122953A6D0EBF8F2 DDB460371005122A53A7D0ECFFFCE7BD4B210D02071C46B8E2F7FFFDE8BE4C22 0D03081D46B9E3F7F3EFDAB05D34170A142C55A9D2E9F3F0DBB15E34180B152C 56A9D3E8DECCC59C7241311F2E3E6A94BFCADFCCC69C7341321F2F3F6B94BFC9 B4A28D877F6F5B48586D7C818BA0B5A38E8780705B49596D7D808BA0424F6479 8499AEBBAB968977624D43506479859AAFBCAC978876614C18253A6690C3D7E5 D5C79E74382319263B6791C3D8E5D6C79D73372303102851A5CEECF9F1DCB25F 360E04112952A5CFEDFAF0DBB25E350E pop pop /customdata8 28 28 mul string def currentfile customdata8 readhexstring 050F2747B6D6EEF8FEF4DCBC4D2D1507111D375F9EC6E0E9EBE6CCA4653D1F13 2939556F8EA8C1D1D3C3AE9475573B2B4961717D808999B1B39B8B867F73634B B8A090827A6A5A42445C6C7C8492A2BAD8C8AA97785232222434546E8DACCADA F0E2CFA768401A0A0C1C365E9DC5E4F2FAF7DFBF50301802040E2646B5D5EDFC FFF5DDBD4E2E160806102848B7D7EFF9EAE7CDA5663E2014121E38609FC7E1E8 D2C2AF9576583C2C2A3A56708FA9C0D0B29A8A878074644C4A62727E818898B0 435B6B7B8593A3BBB9A19183796959412333536D8CADCBDBD9C9AB9677513121 0B1B355D9CC4E5F3F1E3CEA6673F1909030D2545B4D4ECFDFBF6DEBE4F2F1701 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop end end defaultpacking setpacking %%EndResource %%BeginResource: procset AGM_Gradient_Sep 1.0 0 %%Title: (AGM Gradient Procset) %%Version: 1.0 0 %%CreationDate: (4/26/96) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /AGM_Gradient_Sep 5 dict dup begin put /AGM_Gradient_Sep_private 100 dict def /initialize{ AGM_Gradient_Sep begin AGM_Gradient_Sep_private begin _compositeJob{ initializeSinglePassSeps }{ initializeMultiPassSeps }ifelse initializeSeps AGM_Gradient_private begin /_fillSD newSpotDict def /_rampSD newSpotDict def /_nCustomColorSD nd end AGM_Gradient_Sep_private { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall AGM_Gradient_Sep { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall end currentdict readonly pop end }def /terminate{ currentdict AGM_Gradient_Sep eq{ end }if }def AGM_Gradient_Sep_private begin /initializeSeps{ _noImage not _level2PS not and{ /_whiteBytes 1 makeByte8 pt /knockOut{ 8 setImageParms _whiteBytes /_image load 5 execImage }def /linealFill{ mySave 8 setImageParms _color{ _nCustomColorSD begin cyan magenta yellow black _spotColor{ spot1 begin /tintImage tintValue 1 exch sub makeByte8 def end spot2 begin /tintImage tintValue 1 exch sub makeByte8 def end }if end 4{ makeByte8 4 1 roll }repeat true 4 _nCustomColorSD ncolorimage }{ _nCustomColorSD/black get 1 exch sub makeByte8 _nCustomColorSD bwImage }ifelse myRestore }def }{ /knockOut{ gsave false setoverprint 1 setgray 0 0 1 1 rectfill grestore }def }ifelse /newSpotDict{ 11 dict dup begin /nSpots 2 def /spot1 7 dict def /spot2 7 dict def end }def /initSpotData { begin /name nd /tintImage nd /tintValue nd /spot_C nd /spot_M nd /spot_Y nd /spot_K nd end }def /initSpotDict{ begin /cyanInk false def /magentaInk false def /yellowInk false def /blackInk false def /cyan nd /magenta nd /yellow nd /black nd spot1 initSpotData spot2 initSpotData end }def /copySpotDict{ /_dst xp begin cyanInk magentaInk yellowInk blackInk cyan magenta yellow black spot1 spot2 end _dst begin /spot1 spot1 maxlength dict def /spot2 spot2 maxlength dict def spot2 copy pop spot1 copy pop /black xd /yellow xd /magenta xd /cyan xd /blackInk xd /yellowInk xd /magentaInk xd /cyanInk xd end }def /setCustomColor { 1 index /Black eq{ 6 1 roll 5 npop 1 exch sub setgray }{ 6 1 roll _ccAry1 astore exch dup null eq{ pop 0 }if setcustomcolor }ifelse }def /setCStop{ /_colorStyle exch pt _colorStyle 0 eq{ 0 0 0 4 -1 roll 1 exch sub _spotColor{ /_colorStyle 3 pt /Black 1 index 1 exch sub }if }if _colorStyle 2 eq{ 3 npop }if _rampSD _fillSD copySpotDict _colorStyle 4 eq{ pop 9 2 roll 3 npop 6 -2 roll } if _colorStyle 3 eq _colorStyle 4 eq or{ _fillSD begin exch dup spot1/name get eq{ spot1 spot2 }{ spot2 spot1 }ifelse begin begin /name xd 1 exch sub /tintValue xd 4{ tintValue mul 4 1 roll }repeat _spotColor not{ /tintValue null def }if end /tintValue 0 def end end }if _fillSD nsetcustomcolor }def /renderCMYK{ spot1/name get null eq spot2/name get null eq and dup not{ pop spot1 spotConverted }if dup not{ pop spot2 spotConverted }if }def /fill_ /fill load def /fillOvp{ currentoverprint{ _inRipSep{ currentcolorspace 0 get dup /DeviceGray eq 1 index /DeviceCMYK eq or{ pop currentcmykcolor add add add 0 eq{ newpath }if }{ /Separation eq{ currentcolor 0 eq{ newpath }if }if }ifelse }{ currentgray 1 eq{ newpath }if }ifelse }if fill_ }def /fill{ _nCustomColorSD begin renderCMYK { fillOvp }{ spot1 begin gsave name null ne{ spot_C spot_M spot_Y spot_K name tintValue setCustomColor }{ 1 setgray }ifelse fillOvp grestore end spot2 begin name null ne{ gsave true setoverprint spot_C spot_M spot_Y spot_K name tintValue setCustomColor fillOvp grestore }if end newpath }ifelse end }def /expandSpot{ _spotColor{ /_len xp _rampSD begin spot1 begin tintImage null ne{ tintImage _len expandOne /tintImage xd }if end spot2 begin tintImage null ne{ tintImage _len expandOne /tintImage xd }if end end }{ pop }ifelse }def /rampImage{ _rampSD begin _color{ /cyanInk _cyanData 0 ne def /magentaInk _magentaData 0 ne def /yellowInk _yellowData 0 ne def /blackInk _blackData 0 ne def _nSamples setImageParms _nSamples expandSpot _cyanData _magentaData _yellowData _blackData _nSamples 4 expandColor true 4 _rampSD ncolorimage }{ /cyanInk false def /magentaInk false def /yellowInk false def /blackInk true def _nSamples setImageParms _blackData _rampSD bwImage }ifelse end }def /nsetcustomcolor where{ pop }{ /nsetcustomcolor { /_nCustomColorSD xp _nCustomColorSD begin 4 copy /black xd /yellow xd /magenta xd /cyan xd 4 copy 0 ne /blackInk xd 0 ne /yellowInk xd 0 ne /magentaInk xd 0 ne /cyanInk xd end setcmykcolor }def }ifelse /nsetcustomcolorend where{ pop }{ /nsetcustomcolorend { /_nCustomColorSD null pt }def }ifelse }def /initializeSinglePassSeps{ /_decodeNorm [0 1] pt /_decodeInvert [1 0] pt /spotConverted { begin name null eq{ false }{ tintValue null eq tintImage null eq and{ true }{ false currentpagedevice/SeparationOrder get{name eq or}forall not }ifelse }ifelse end }def /dictImage { 20 dict dup begin /Dict xd /Decode xd /DataSource xd /ImageMatrix xd /BitsPerComponent xd /Height xd /Width xd /ImageType 1 def Dict end /_image load 1 execImage }def /bwImage{ begin gsave currentoverprint{ blackInk{ [/Separation /Black /DeviceGray{}] setcolorspace _decodeInvert dictImage }{ 5 npop }ifelse }{ /DeviceGray setcolorspace _decodeNorm dictImage }ifelse grestore end }def /ncolorimage where{ pop }{ /ncolorimage{ begin renderCMYK { cyanInk magentaInk and yellowInk and blackInk and not currentoverprint and { pop pop gsave cyanInk{ 8 copy [/Separation /Cyan /DeviceGray{}] setcolorspace 3 npop _decodeNorm dictImage }if magentaInk{ 8 copy [/Separation /Magenta /DeviceGray{}] setcolorspace 4 -1 roll 3 npop _decodeNorm dictImage }if yellowInk{ 8 copy [/Separation /Yellow /DeviceGray{}] setcolorspace 4 -2 roll 3 npop _decodeNorm dictImage }if blackInk{ 4 -3 roll [/Separation /Black /DeviceGray{}] setcolorspace 3 npop _decodeNorm dictImage }{ 8 npop }ifelse grestore }{ /_colorimage load 10 execImage }ifelse }{ 6 npop gsave spot1 begin name null ne tintImage null ne and{ [/Separation name /DeviceGray{}] setcolorspace 4 copy tintImage name /Black eq{ _decodeNorm }{ _decodeInvert }ifelse dictImage }{ 1 setgray fill }ifelse end spot2 begin true setoverprint name null ne tintImage null ne and{ [/Separation name /DeviceGray{}] setcolorspace tintImage name /Black eq{ _decodeNorm }{ _decodeInvert }ifelse dictImage }{ 4 npop 1 setgray fill }ifelse end grestore }ifelse end }def }ifelse }def /initializeMultiPassSeps{ /_isCMYKSep _cyanPlate _magentaPlate or _yellowPlate or _blackPlate or pt /invertXfer{ [ { 1 exch sub }/exec load systemdict /currenttransfer get exec /exec load ] cvx systemdict /settransfer get exec }def /ccThrough{ gsave 1 setCustomColor currentcmykcolor grestore add add add 0 ne }def /spotConverted { begin _isCMYKSep not{ false }{ name null eq{ false }{ tintValue null eq tintImage null eq and{ true }{ spot_C spot_M spot_Y spot_K name ccThrough }ifelse }ifelse }ifelse end }def /spotChannel { _isCMYKSep{ pop false }{ begin name null eq{ false }{ spot_C spot_M spot_Y spot_K name ccThrough }ifelse end }ifelse }def /getChannelData { _isCMYKSep dup{ pop renderCMYK }if { _blackPlate{ 4 1 roll 3 npop blackInk }{ _yellowPlate{ 4 2 roll 3 npop yellowInk }{ _magentaPlate{ 4 3 roll 3 npop magentaInk }{ 3 npop cyanInk }ifelse }ifelse }ifelse { true /nonZeroData }{ true /zeroData }ifelse }{ 4 npop spot1/name get null ne spot1 spotChannel and{ spot1/tintImage get dup null ne{ false /nonZeroData }{ pop false /noData }ifelse }{ spot2/name get null ne spot2 spotChannel and{ spot2/tintImage get dup null ne{ false /nonZeroData }{ pop false /noData }ifelse }{ false /noData }ifelse }ifelse }ifelse }def /renderChannelData { /_tmp xp _tmp /nonZeroData ne currentoverprint and{ pop _tmp /zeroData eq{pop}if 4 npop }{ _tmp /nonZeroData eq{ { invertXfer }if systemdict/image get 5 execImage }{ pop _tmp /zeroData eq{pop}if 4 npop knockOut }ifelse }ifelse }def /bwImage{ begin gsave dup dup dup getChannelData exch pop false exch renderChannelData grestore end }def /ncolorimage{ begin pop pop gsave spot2/name get null ne spot2 spotChannel and{ true setoverprint }if getChannelData renderChannelData grestore end }def }def end end defaultpacking setpacking %%EndResource %%BeginResource: procset AGM_Gradient 1.0 0 %%Title: (AGM Gradient Procset) %%Version: 1.0 0 %%CreationDate: (4/26/96) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /AGM_Gradient 20 dict dup begin put /AGM_Gradient_private 200 dict def /initialize { AGM_Gradient begin AGM_Gradient_private begin initializeVars /bd systemdict/mark get def /ed _level2PS { (>>) }{ (counttomark 2 idiv dup dict begin {def} repeat pop currentdict end) } ifelse cvx def _level2PS{ initializeLev2 }{ initializeLev1 }ifelse queryDevice initializeShading initializeOps _producingSeps{ AGM_Gradient_Sep/initialize get exec }{ initializeComposite }ifelse _illustrator{ /f{}def /F{}def /s{}def /S{}def /b{}def /B{}def }if /image where{ /image get /_image xd }if /colorimage where{ /colorimage get /_colorimage xd }if /rectfill where dup{ exch pop not _producingSeps or }{ not }ifelse { /rectfill{ gsave newpath 4 2 roll moveto 1 index 0 rlineto 0 1 index rlineto 1 index neg 0 rlineto pop pop closepath fill grestore }def }if /linealImage _noImage{ /rectImage load }{ _producingSeps{ AGM_Gradient_Sep/AGM_Gradient_Sep_private get begin /rampImage load end }{ /rampImage load }ifelse }ifelse def AGM_Gradient_private { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall AGM_Gradient { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall end currentdict readonly pop end }def /initializeAI { pop pop AGM_Gradient/AGM_Gradient_private get /_illustrator true put AGM_Gradient/initialize get exec AGM_Gradient begin }def /unload{ systemdict/languagelevel known{ systemdict/languagelevel get 2 ge{ userdict/AGM_Gradient_Sep 2 copy known{ undef }{ pop pop }ifelse userdict/AGM_Gradient 2 copy known{ undef }{ pop pop }ifelse }if }if }def /terminate{ currentdict AGM_Gradient eq{ end }if }def AGM_Gradient_private begin /initializeVars{ /_d255 256 array def 0 1 255{ _d255 exch dup 255 div put }bind for /_d255- 256 array def 0 1 255{ _d255- exch 1 _d255 2 index get sub put }bind for /_sSave nd /_dUserSpace matrix defaultmatrix def /_bUMatrix matrix def /_imageMatrix matrix def /_saveMatrix matrix def /_xm matrix def /_ccAry1 5 array def /_level2PS systemdict/languagelevel known dup{ pop systemdict/languagelevel get 2 ge }if def /_level3PS _level2PS systemdict/shfill known and def currentdict /_illustrator known not{ /_illustrator false def }if }def /initializeOps { AGM_Gradient begin currentdict/Bc known not{ /Bc{ _renderFlag 2 eq{ 6 npop }{ pushBSpace _rampIndex 0 eq{ pop pop setCStop }if linealFill popBSpace }ifelse }def }if currentdict/Bg known not{ /Bg{ 10 npop /_gradName xp /_renderFlag xp _renderFlag 2 ne{ _illustrator{ _of setoverprint }if _illustrator _eo and _renderFlag 3 eq or{ eoclip }{ clip }ifelse _gradNames _gradName 2 copy known{ get mark exch aload pop /_gradType xp 1 sub dup /_rampIndex xp /_maxRampIndex xp mark exch aload pop 0 0 }if pop pop getRampData }{ mark mark }ifelse }def }if currentdict/Bm known not{ /Bm{ _renderFlag 2 ne{ _gradType 0 eq{ linealRamp }{ radialGrad }ifelse }{ 6 npop }ifelse }def }if currentdict/Bh known not{ /Bh{ 2 npop /_yHi xp /_xHi xp /_radHilite _xHi 0 ne _yHi 0 ne or pt }def }if currentdict/Bn known not{ /Bn{ AGM_Gradient_private begin dict /_gradNames xp end }def }if currentdict/Bd known not{ /Bd{ AGM_Gradient begin AGM_Gradient_private begin /_nColorsBd xp /_gradType xp /_gradName xp }def }if currentdict/BD known not{ /BD{ currentdict/_gradNames known not{ /_gradNames 20 dict def }if ] _nColorsBd _gradType ] _gradName exch /_gradNames xput end end }def }if currentdict/Bb known not{ /Bb{ AGM_Gradient begin AGM_Gradient_private begin _producingSeps{ AGM_Gradient_Sep/AGM_Gradient_Sep_private get begin }if mySave }def }if currentdict/BB known not{ /BB{ /_tmp xp cleartomark cleartomark _tmp dup _renderFlag myRestore _producingSeps{ end }if _illustrator end end { 2 ne exch 0 gt and{ 2 eq{ s }{ S }ifelse }{ pop newpath }ifelse }{ pop newpath }ifelse }def }if currentdict/Xm known not{ /Xm{ _xm astore pop }def }if end }def /queryDevice{ /_inRipSep _level2PS{ currentpagedevice/Separations 2 copy known{ get }{ pop pop false }ifelse }{ false }ifelse def /_noImage /lv1Fix where{ pop lv1Fix }{ false }ifelse def /_useShells where{ pop }{ /_useShells true def }ifelse /_useSmoothShade where{ pop }{ /_useSmoothShade false def }ifelse /_cyanPlate 1 0 0 0 testCMYKColorThrough def /_magentaPlate 0 1 0 0 testCMYKColorThrough def /_yellowPlate 0 0 1 0 testCMYKColorThrough def /_blackPlate 0 0 0 1 testCMYKColorThrough def /_compositeJob _cyanPlate _magentaPlate and _yellowPlate and _blackPlate and def /_compositeSpotDevice where{ pop }{ /_compositeSpotDevice _compositeJob not _inRipSep or{ 1 }{ 0 }ifelse def }ifelse /_producingSeps _compositeSpotDevice 0 ne def /_deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt def /_dpiThreshold where{ pop }{ /_dpiThreshold 600 def }ifelse /_screenFreqThreshold where{ pop }{ /_screenFreqThreshold 150 def }ifelse /_contoneDevice where{ pop }{ /_contoneDevice false def }ifelse /_subSampleOK _deviceDPI _dpiThreshold le currentScreenFreq _screenFreqThreshold le and _contoneDevice not and _producingSeps not and def }def /initializeLev1{ /makeByte8{ /_tmp 0 pt 255 mul cvi 8 string 8{ dup _tmp 3 index put /_tmp _tmp 1 add pt }repeat exch pop }def /currentScreenFreq{ currentscreen pop pop }def /_byte 1 string def /colorimage where{ pop }{ /colorimage{ pop pop /_blackTmp xp /_yellowTmp xp /_magentaTmp xp /_cyanTmp xp /_cnt 0 pt [ _byte dup 0 _cyanTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .3 /mul cvx _magentaTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .59 /mul cvx _yellowTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .11 /mul cvx _blackTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx /add cvx /add cvx /add cvx 1 /exch cvx /sub cvx /dup cvx 0 /lt cvx{ pop 0 }/if cvx /dup cvx 1 /gt cvx{ pop 1 }/if cvx 255 /mul cvx /cvi cvx 256 /mod cvx /dup cvx 0 /lt cvx{ pop 0 }/if cvx /put cvx /_cnt dup cvx 1 /add cvx /pt cvx ] cvx bind /_image load 5 execImage }def }ifelse }def /initializeLev2{ /level2ScreenFreq{ begin 60 HalftoneType 1 eq{ pop Frequency }if HalftoneType 2 eq{ pop GrayFrequency }if HalftoneType 5 eq{ pop Default level2ScreenFreq }if end }def /currentScreenFreq{ currenthalftone level2ScreenFreq }def }def /initializeShading{ _useSmoothShade _level3PS and{ /_usingSmoothShade true pt initializeLev3_Ops }{ /_usingSmoothShade false pt }ifelse }def /initializeLev3_Ops { /initShFill{ /_index _gradType 0 eq {0}{_maxRampIndex 1 sub} ifelse pt /_rampFuncsArray _maxRampIndex array pt /_boundsArray _maxRampIndex 1 sub array pt /_encodeArray _maxRampIndex 2 mul array pt /_beginCoord _rampPoint pt /_colorSpace null pt /_firstFill _rampIndex _maxRampIndex eq pt /_lastFill false pt }def /getRampColorSpace{ _nSamples 1 gt{ /_ndx 0 pt [blendColor] cvx exec }if /_C0 [currentcolor] pt /_C0_Space currentcolorspace pt _nSamples 1 gt{ /_ndx _nSamples 1 sub pt [blendColor] cvx exec }if /_C1 [currentcolor] pt /_C1_Space currentcolorspace pt _C0_Space _C1_Space eq{ /_rampColorSpace _C0_Space pt }{ (colorspace conflict!) == showpage stop }ifelse _spotColor{ nsetcustomcolorend }if }def /linealShFill{ popBSpace _xm aload pop pushBSpace /_size _index 1 add pt _size _maxRampIndex lt { /_rampFuncsArray _rampFuncsArray 0 _size getinterval pt /_boundsArray _boundsArray 0 _size 1 sub getinterval pt /_encodeArray _encodeArray 0 _size 2 mul getinterval pt }if bd /ShadingType 2 /ColorSpace _colorSpace /Function bd /FunctionType 3 /Domain [0 1] /Functions _rampFuncsArray /Bounds _boundsArray /Encode _encodeArray ed /Extend [_firstFill _lastFill] /Domain [0 1] /Coords [_beginCoord 0 _endCoord 0] ed shfill }def /radialShFill{ /_size _maxRampIndex _index sub pt _size _maxRampIndex lt { /_rampFuncsArray _rampFuncsArray _index _size getinterval pt /_boundsArray _boundsArray _index _size 1 sub getinterval pt /_encodeArray _encodeArray _index 2 mul _size 2 mul getinterval pt }if /_rampLen _beginCoord _endCoord sub pt bd /ShadingType 3 /ColorSpace _colorSpace /Function bd /FunctionType 3 /Domain [0 1] /Functions _rampFuncsArray /Bounds _boundsArray /Encode _encodeArray ed /Extend [_lastFill _firstFill] /Domain [0 1] /Coords [_xHi _rampLen mul _yHi _rampLen mul _endCoord 0 0 _beginCoord] ed shfill _radHilite{ _xHi _rampLen mul _yHi _rampLen mul translate }if }def /fillRamp{ /_invert _midPoint 0.5 lt pt _rampIndex _maxRampIndex eq { initShFill }if getRampColorSpace _colorSpace null eq{ /_colorSpace _rampColorSpace pt }{ _colorSpace _rampColorSpace ne{ /_index _index 1 _gradType 0 eq{ sub pt linealShFill }{ add pt radialShFill }ifelse initShFill /_colorSpace _rampColorSpace pt } if }ifelse /_endCoord _endPoint pt _rampFuncsArray _index bd /FunctionType 2 /Domain [0 1] /N 0.5 log _invert{1 _midPoint sub}{_midPoint}ifelse log div _gradType 0 eq{ _invert{/C1}{/C0}ifelse _C0 _invert{/C0}{/C1}ifelse _C1 }{ _invert{/C0}{/C1}ifelse _C1 _invert{/C1}{/C0}ifelse _C0 }ifelse ed put _rampIndex 1 ne{ _boundsArray _index _gradType 1 eq{1 sub}if _endCoord put } if 0 1 _invert {exch}if _encodeArray _index 2 mul 1 add 3 -1 roll put _encodeArray _index 2 mul 3 -1 roll put _rampIndex 1 eq { /_lastFill true pt _gradType 0 eq{ linealShFill }{ radialShFill }ifelse }if /_index _index 1 _gradType 0 eq{ add pt }{ sub pt }ifelse }def /radialRamp /fillRamp load def /rampImage /fillRamp load def AGM_Gradient begin /Bc{ 6 npop }def end }def /initializeComposite{ /bwImage{ pop /_image load 5 execImage }def currentdict/rampImage known not{ /rampImage{ _color{ _nSamples setImageParms _rgbRamp{ _redData _greenData _blueData _nSamples 3 expandColor true 3 null ncolorimage }{ _cyanData _magentaData _yellowData _blackData _nSamples 4 expandColor true 4 null ncolorimage }ifelse }{ _nSamples setImageParms _blackData null bwImage }ifelse }def }if /setCStop{ /_colorStyle exch pt _colorStyle 0 eq{ 1 exch sub 0 0 0 4 -1 roll }if _colorStyle 2 eq{ setrgbcolor 4 npop }if _colorStyle 3 eq{ 1 exch sub /_tmp xp pop 4{ _tmp mul 4 1 roll }repeat }if _colorStyle 4 eq{ 3 -1 roll pop pop 1 exch sub /_tmp xp 3{ 1 exch sub _tmp mul 1 exch sub 3 1 roll }repeat setrgbcolor 4 npop }if _colorStyle 2 ne _colorStyle 4 ne and{ null nsetcustomcolor }if }def /nsetcustomcolor { pop setcmykcolor }def /nsetcustomcolorend { }def /ncolorimage{ pop /_colorimage load 10 execImage }def _noImage not _level2PS not and{ /linealFill{ 8 setImageParms _color{ currentcmykcolor 4{ makeByte8 4 1 roll }repeat true 4 null ncolorimage }{ currentgray makeByte8 null bwImage }ifelse }def }if }def /npop{ {pop}repeat }def /xd{ exch def }def /nd{ null def }def /pt{ AGM_Gradient_private 3 1 roll put }def /xp{ exch pt }def /xput{ dup load dup length exch maxlength eq{ dup dup load dup length 2 mul dict copy def }if load begin def end }def /mySave{ save /_sSave xp }def /myRestore{ _sSave type /savetype eq{ _sSave restore }if }def /gMark{ counttomark 2 add -1 roll }def /execImage{ /_tmp xp { exec }stopped{ $error /errorname get /undefinedresult ne{ stop }{ _tmp npop }ifelse }if }def /pushBSpace{ newpath gsave _bUMatrix astore concat }def /popBSpace{ grestore }def /setImageParms{ 1 8 2 index 0 0 1 0 0 _imageMatrix astore }def /linealFill{ 0 0 1 1 rectfill }def /testCMYKColorThrough{ gsave setcmykcolor currentcmykcolor grestore add add add 0 ne }def /expandOne { /_tmp xp dup type /stringtype ne{ _tmp string exch dup 0 ne{ 255 mul cvi 0 1 _tmp 1 sub{ 3 copy exch put pop }for }if pop }if }def /expandColor{ /_channels xp /_len xp _channels{ _len expandOne _channels 1 roll }repeat }def /blendColor{ _color{ _rgbRamp _producingSeps not and{ _redData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _greenData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _blueData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if /setrgbcolor cvx }{ _cyanData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _magentaData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _yellowData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _blackData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _spotColor{ _rampSD begin /_rampSD cvx /begin cvx spot1 begin tintImage dup type /stringtype eq{ /_ndx cvx /get cvx _d255- /exch cvx /get cvx }{ dup null ne{ name type /nametype ne{ 1 exch sub }if }if }ifelse end /spot1 cvx /tintValue 3 -1 /roll cvx /put cvx spot2 begin tintImage dup type /stringtype eq{ /_ndx cvx /get cvx _d255- /exch cvx /get cvx }{ dup null ne{ name type /nametype ne{ 1 exch sub }if }if }ifelse end /spot2 cvx /tintValue 3 -1 /roll cvx /put cvx /end cvx end /_rampSD cvx /nsetcustomcolor cvx }{ /setcmykcolor cvx }ifelse }ifelse }{ _blackData /_ndx cvx /get cvx _d255 /exch cvx /get cvx _usingSmoothShade{ 1 /exch cvx /sub cvx 0 0 0 4 -1 /roll cvx /setcmykcolor cvx }{ /setgray cvx }ifelse }ifelse }def /linealRamp{ pushBSpace _ramp{ linealImage }{ linealFill }ifelse popBSpace /_rampIndex _rampIndex 1 sub pt _rampIndex 0 gt{ getRampData }if }def /radialGrad{ /_firstShell true pt _usingSmoothShade not{ fill }if pushBSpace _radHilite{ _xHi _yHi _bUMatrix idtransform /_yHi xp /_xHi xp _rampPoint 1 lt{ 1 _rampPoint sub dup _xHi mul exch _yHi mul translate }if }if _rampIndex{ radialRamp /_rampIndex _rampIndex 1 sub pt _rampIndex 0 gt{ getRampData }if }repeat popBSpace }def /getNSamples{ 0 exch { dup type /stringtype eq{ length exch pop exit }if pop }forall dup 0 eq{ pop 1 }if }def /getRampData{ /_rampType gMark pt /_color _rampType 0 gt pt /_ccRGB _rampType 5 eq _rampType 6 eq or pt /_rgbRamp _rampType 4 eq _ccRGB or pt /_ccProcess _rampType 2 eq _rampType 3 eq or pt _producingSeps{ _rampSD initSpotDict /_spotColor _ccProcess _ccRGB or pt }{ /_spotColor false pt }ifelse /_ramp true pt 100 div /_rampPoint xp 100 div /_midPoint xp dup /_colorStyle xp _colorStyle 0 eq{ 2 }{ _colorStyle 1 eq{ 5 }{ _colorStyle 2 eq{ 8 }{ _colorStyle 3 eq{ _producingSeps{ _rampSD begin spot1 begin /name 3 index def /spot_K 4 index def /spot_Y 5 index def /spot_M 6 index def /spot_C 7 index def end end }if 7 }{ _producingSeps{ _rampSD begin spot1 begin /name 4 index def /spot_K 8 index def /spot_Y 9 index def /spot_M 10 index def /spot_C 11 index def end end }if 11 } ifelse }ifelse }ifelse }ifelse /_tmp xp _tmp index 100 div /_endPoint xp _gradType 1 eq{ _tmp 1 add index 100 div /_midPoint xp }if _producingSeps{ _tmp 2 add index /_nextColorStyle xp _nextColorStyle 3 eq{ /_tmp _tmp 4 add pt _tmp index dup _rampSD begin spot1 /name get ne{ spot2 begin /name xd /spot_K _tmp 2 add index def /spot_Y _tmp 3 add index def /spot_M _tmp 4 add index def /spot_C _tmp 5 add index def end }{ pop }ifelse end }if _nextColorStyle 4 eq{ /_tmp _tmp 5 add pt _tmp index dup _rampSD begin spot1 /name get ne{ spot2 begin /name xd /spot_K _tmp 5 add index def /spot_Y _tmp 6 add index def /spot_M _tmp 7 add index def /spot_C _tmp 8 add index def end }{ pop }ifelse end }if }if _rampType 3 eq _rampType 6 eq or{ /_tint2Data gMark pt }if _ccProcess _ccRGB or{ /_tint1Data gMark pt }if _rgbRamp{ /_blueData gMark pt /_greenData gMark pt /_redData gMark pt }if _producingSeps{ _rampSD begin _ccProcess _ccRGB or{ _rampType 3 eq _rampType 6 eq or{ spot2 begin /tintImage _gradType 0 eq{ _tint2Data }{ _tint1Data }ifelse def name null eq{ /name /Black def }if end }if spot1 begin /tintImage _gradType 0 eq _rampType 2 eq or _rampType 5 eq or{ _tint1Data }{ _tint2Data }ifelse def _rampType 2 eq _rampType 5 eq or{ name null eq{ /name spot2 /name get def spot2 /name null put }if }{ name null eq{ /name /Black def }if }ifelse end }if end }if /_blackData gMark pt _rampType 0 gt{ counttomark 4 add -3 roll /_yellowData xp /_magentaData xp /_cyanData xp }if _ramp{ /_nSamples [ _rampType 0 eq {_blackData}if _rampType 1 eq {_cyanData _magentaData _yellowData _blackData}if _rampType 2 eq {_cyanData _magentaData _yellowData _blackData _tint1Data}if _rampType 3 eq {_cyanData _magentaData _yellowData _blackData _tint1Data _tint2Data}if _rampType 4 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData}if _rampType 5 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData _tint1Data}if _rampType 6 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData _tint1Data _tint2Data}if ] getNSamples pt _usingSmoothShade not {/_ramp _nSamples 1 gt pt} if } if setCStop }def /rectImage{ gsave /_sInc 1 pt /_bInc 1 _nSamples div pt /_uRampLen 1 0 dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt pt /_pChange _uRampLen 0 eq{0}{_nSamples _uRampLen div}ifelse pt 0 _nSamples [ /dup cvx /_ndx /exch cvx /pt cvx blendColor 0 0 _bInc 1 /rectfill cvx _bInc 0 /translate cvx _sInc /add cvx ] cvx bind repeat pop _spotColor{ nsetcustomcolorend }if grestore }def /radialInit{ /_nRadSamples _nSamples dup 0 eq{pop 1}if pt /_sInc -1 pt /_rampLen _rampPoint _endPoint sub pt /_bInc _rampLen _nSamples div neg pt /_optimize false pt _subSampleOK{ /_uRampLen _rampLen 0 dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt 0 _rampLen dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt 2 copy lt{ exch }if pop pt /_pChange _uRampLen 0 eq{ 0 }{ _nSamples _uRampLen div }ifelse pt _pChange .5 gt dup /_optimize xp{ /_nRadSamples _uRampLen 2 div round cvi dup 1 le{pop 2}if pt /_bInc _rampLen _nRadSamples div neg pt /_sInc _nSamples 1 sub _nRadSamples 1 sub div neg pt }if }if _radHilite{ /_xBCInc _xHi _rampLen mul _nRadSamples div pt /_yBCInc _yHi _rampLen mul _nRadSamples div pt }if }def currentdict/radialRamp known not{ /radialRamp{ /_saveMatrix _saveMatrix currentmatrix def radialInit _rampPoint _nSamples 1 sub _nRadSamples [ /dup cvx _optimize{ /round cvx /cvi cvx }if /_ndx /exch cvx /pt cvx _useShells{ /_firstShell cvx{ /_firstShell false pt }{ 0 0 3 index 360 0 arcn fill }/ifelse cvx }if blendColor _useShells{ 0 0 3 /index cvx 0 360 /arc cvx }{ 0 0 3 /index cvx 0 360 /arc cvx /fill cvx }ifelse /exch cvx _bInc /add cvx /exch cvx _sInc /add cvx _radHilite{ _xBCInc _yBCInc /translate cvx }if ] cvx bind repeat pop pop _saveMatrix setmatrix _radHilite{ _xHi _rampLen mul _yHi _rampLen mul translate }if _useShells _rampIndex 1 eq and{ fill }if _spotColor{ nsetcustomcolorend }if }def }if end end defaultpacking setpacking %%EndResource %%BeginProcSet: Adobe_ColorImage_AI6 1.1 0 userdict /Adobe_ColorImage_AI6 known not { userdict /Adobe_ColorImage_AI6 24 dict put } if userdict /Adobe_ColorImage_AI6 get begin /initialize { Adobe_ColorImage_AI6 begin Adobe_ColorImage_AI6 { dup type /arraytype eq { dup xcheck { bind } if } if pop pop } forall } def /terminate { end } def currentdict /Adobe_ColorImage_AI6_Vars known not { /Adobe_ColorImage_AI6_Vars 15 dict def } if Adobe_ColorImage_AI6_Vars begin /channelcount 0 def /sourcecount 0 def /sourcearray 4 array def /plateindex -1 def /XIMask 0 def /XIBinary 0 def /XIChannelCount 0 def /XIBitsPerPixel 0 def /XIImageHeight 0 def /XIImageWidth 0 def /XIImageMatrix null def /XIBuffer null def /XIDataProc null def /XIVersion 6 def end /WalkRGBString null def /WalkCMYKString null def /StuffRGBIntoGrayString null def /RGBToGrayImageProc null def /StuffCMYKIntoGrayString null def /CMYKToGrayImageProc null def /ColorImageCompositeEmulator null def /SeparateCMYKImageProc null def /FourEqual null def /TestPlateIndex null def currentdict /_colorimage known not { /colorimage where { /colorimage get /_colorimage exch def } { /_colorimage null def } ifelse } if /_currenttransfer systemdict /currenttransfer get def /colorimage null def /XI null def /WalkRGBString { 0 3 index dup length 1 sub 0 3 3 -1 roll { 3 getinterval { } forall 5 index exec 3 index } for 5 { pop } repeat } def /WalkCMYKString { 0 3 index dup length 1 sub 0 4 3 -1 roll { 4 getinterval { } forall 6 index exec 3 index } for 5 { pop } repeat } def /StuffRGBIntoGrayString { .11 mul exch .59 mul add exch .3 mul add cvi 3 copy put pop 1 add } def /RGBToGrayImageProc { Adobe_ColorImage_AI6_Vars begin sourcearray 0 get exec dup length 3 idiv string dup 3 1 roll /StuffRGBIntoGrayString load exch WalkRGBString end } def /StuffCMYKIntoGrayString { exch .11 mul add exch .59 mul add exch .3 mul add dup 255 gt { pop 255 } if 255 exch sub cvi 3 copy put pop 1 add } def /CMYKToGrayImageProc { Adobe_ColorImage_AI6_Vars begin sourcearray 0 get exec dup length 4 idiv string dup 3 1 roll /StuffCMYKIntoGrayString load exch WalkCMYKString end } def /ColorImageCompositeEmulator { pop true eq { Adobe_ColorImage_AI6_Vars /sourcecount get 5 add { pop } repeat } { Adobe_ColorImage_AI6_Vars /channelcount get 1 ne { Adobe_ColorImage_AI6_Vars begin sourcearray 0 3 -1 roll put channelcount 3 eq { /RGBToGrayImageProc } { /CMYKToGrayImageProc } ifelse load end } if image } ifelse } def /SeparateCMYKImageProc { Adobe_ColorImage_AI6_Vars begin sourcecount 0 ne { sourcearray plateindex get exec } { sourcearray 0 get exec dup length 4 idiv string 0 2 index plateindex 4 2 index length 1 sub { get 255 exch sub 3 copy put pop 1 add 2 index } for pop pop exch pop } ifelse end } def /FourEqual { 4 index ne { pop pop pop false } { 4 index ne { pop pop false } { 4 index ne { pop false } { 4 index eq } ifelse } ifelse } ifelse } def /TestPlateIndex { Adobe_ColorImage_AI6_Vars begin /plateindex -1 def /setcmykcolor where { pop gsave 1 0 0 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 1 0 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 0 1 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 0 0 1 setcmykcolor systemdict /currentgray get exec 1 exch sub grestore 1 0 0 0 FourEqual { /plateindex 0 def } { 0 1 0 0 FourEqual { /plateindex 1 def } { 0 0 1 0 FourEqual { /plateindex 2 def } { 0 0 0 1 FourEqual { /plateindex 3 def } { 0 0 0 0 FourEqual { /plateindex 5 def } if } ifelse } ifelse } ifelse } ifelse pop pop pop pop } if plateindex end } def /colorimage { Adobe_ColorImage_AI6_Vars begin /channelcount 1 index def /sourcecount 2 index 1 eq { channelcount 1 sub } { 0 } ifelse def 4 sourcecount add index dup 8 eq exch 1 eq or not end { /_colorimage load null ne { _colorimage } { Adobe_ColorImage_AI6_Vars /sourcecount get 7 add { pop } repeat } ifelse } { dup 3 eq TestPlateIndex dup -1 eq exch 5 eq or or { /_colorimage load null eq { ColorImageCompositeEmulator } { dup 1 eq { pop pop image } { Adobe_ColorImage_AI6_Vars /plateindex get 5 eq { gsave 0 _currenttransfer exec 1 _currenttransfer exec eq { 0 _currenttransfer exec 0.5 lt } { 0 _currenttransfer exec 1 _currenttransfer exec gt } ifelse { { pop 0 } } { { pop 1 } } ifelse systemdict /settransfer get exec } if _colorimage Adobe_ColorImage_AI6_Vars /plateindex get 5 eq { grestore } if } ifelse } ifelse } { dup 1 eq { pop pop image } { pop pop Adobe_ColorImage_AI6_Vars begin sourcecount -1 0 { exch sourcearray 3 1 roll put } for /SeparateCMYKImageProc load end systemdict /image get exec } ifelse } ifelse } ifelse } def /XG { pop pop } def /XF { 13 {pop} repeat } def /Xh { Adobe_ColorImage_AI6_Vars begin gsave /XIMask exch 0 ne def /XIImageHeight exch def /XIImageWidth exch def /XIImageMatrix exch def 0 0 moveto XIImageMatrix concat XIImageWidth XIImageHeight scale XIMask { /_lp /null ddef _fc /_lp /imagemask ddef } if /XIVersion 7 def end } def /XH { Adobe_ColorImage_AI6_Vars begin /XIVersion 6 def grestore end } def /XI { Adobe_ColorImage_AI6_Vars begin gsave /XIMask exch 0 ne def /XIBinary exch 0 ne def pop pop /XIChannelCount exch def /XIBitsPerPixel exch def /XIImageHeight exch def /XIImageWidth exch def pop pop pop pop /XIImageMatrix exch def XIBitsPerPixel 1 eq { XIImageWidth 8 div ceiling cvi } { XIImageWidth XIChannelCount mul } ifelse /XIBuffer exch string def XIBinary { /XIDataProc { currentfile XIBuffer readstring pop } def XIVersion 6 le { currentfile 128 string readline pop pop } if } { /XIDataProc { currentfile XIBuffer readhexstring pop } def } ifelse XIVersion 6 le { 0 0 moveto XIImageMatrix concat XIImageWidth XIImageHeight scale XIMask { /_lp /null ddef _fc /_lp /imagemask ddef } if } if XIMask { XIImageWidth XIImageHeight false [ XIImageWidth 0 0 XIImageHeight neg 0 0 ] /XIDataProc load imagemask } { XIImageWidth XIImageHeight XIBitsPerPixel [ XIImageWidth 0 0 XIImageHeight neg 0 0 ] /XIDataProc load XIChannelCount 1 eq { gsave 0 setgray image grestore } { false XIChannelCount colorimage } ifelse } ifelse grestore end } def end %%EndProcSet %%BeginResource: procset Adobe_Illustrator_AI5 1.1 0 %%Title: (Adobe Illustrator (R) Version 5.0 Full Prolog) %%Version: 1.1 0 %%CreationDate: (3/7/1994) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_Illustrator_AI5_vars 81 dict dup begin put /_eo false def /_lp /none def /_pf { } def /_ps { } def /_psf { } def /_pss { } def /_pjsf { } def /_pjss { } def /_pola 0 def /_doClip 0 def /cf currentflat def /_tm matrix def /_renderStart [ /e0 /r0 /a0 /o0 /e1 /r1 /a1 /i0 ] def /_renderEnd [ null null null null /i1 /i1 /i1 /i1 ] def /_render -1 def /_rise 0 def /_ax 0 def /_ay 0 def /_cx 0 def /_cy 0 def /_leading [ 0 0 ] def /_ctm matrix def /_mtx matrix def /_sp 16#020 def /_hyphen (-) def /_fScl 0 def /_cnt 0 def /_hs 1 def /_nativeEncoding 0 def /_useNativeEncoding 0 def /_tempEncode 0 def /_pntr 0 def /_tDict 2 dict def /_wv 0 def /Tx { } def /Tj { } def /CRender { } def /_AI3_savepage { } def /_gf null def /_cf 4 array def /_if null def /_of false def /_fc { } def /_gs null def /_cs 4 array def /_is null def /_os false def /_sc { } def /_pd 1 dict def /_ed 15 dict def /_pm matrix def /_fm null def /_fd null def /_fdd null def /_sm null def /_sd null def /_sdd null def /_i null def /discardSave null def /buffer 256 string def /beginString null def /endString null def /endStringLength null def /layerCnt 1 def /layerCount 1 def /perCent (%) 0 get def /perCentSeen? false def /newBuff null def /newBuffButFirst null def /newBuffLast null def /clipForward? false def end userdict /Adobe_Illustrator_AI5 known not { userdict /Adobe_Illustrator_AI5 91 dict put } if userdict /Adobe_Illustrator_AI5 get begin /initialize { Adobe_Illustrator_AI5 dup begin Adobe_Illustrator_AI5_vars begin discardDict { bind pop pop } forall dup /nc get begin { dup xcheck 1 index type /operatortype ne and { bind } if pop pop } forall end newpath } def /terminate { end end } def /_ null def /ddef { Adobe_Illustrator_AI5_vars 3 1 roll put } def /xput { dup load dup length exch maxlength eq { dup dup load dup length 2 mul dict copy def } if load begin def end } def /npop { { pop } repeat } def /sw { dup length exch stringwidth exch 5 -1 roll 3 index mul add 4 1 roll 3 1 roll mul add } def /swj { dup 4 1 roll dup length exch stringwidth exch 5 -1 roll 3 index mul add 4 1 roll 3 1 roll mul add 6 2 roll /_cnt 0 ddef { 1 index eq { /_cnt _cnt 1 add ddef } if } forall pop exch _cnt mul exch _cnt mul 2 index add 4 1 roll 2 index add 4 1 roll pop pop } def /ss { 4 1 roll { 2 npop (0) exch 2 copy 0 exch put pop gsave false charpath currentpoint 4 index setmatrix stroke grestore moveto 2 copy rmoveto } exch cshow 3 npop } def /jss { 4 1 roll { 2 npop (0) exch 2 copy 0 exch put gsave _sp eq { exch 6 index 6 index 6 index 5 -1 roll widthshow currentpoint } { false charpath currentpoint 4 index setmatrix stroke } ifelse grestore moveto 2 copy rmoveto } exch cshow 6 npop } def /sp { { 2 npop (0) exch 2 copy 0 exch put pop false charpath 2 copy rmoveto } exch cshow 2 npop } def /jsp { { 2 npop (0) exch 2 copy 0 exch put _sp eq { exch 5 index 5 index 5 index 5 -1 roll widthshow } { false charpath } ifelse 2 copy rmoveto } exch cshow 5 npop } def /pl { transform 0.25 sub round 0.25 add exch 0.25 sub round 0.25 add exch itransform } def /setstrokeadjust where { pop true setstrokeadjust /c { curveto } def /C /c load def /v { currentpoint 6 2 roll curveto } def /V /v load def /y { 2 copy curveto } def /Y /y load def /l { lineto } def /L /l load def /m { moveto } def } { /c { pl curveto } def /C /c load def /v { currentpoint 6 2 roll pl curveto } def /V /v load def /y { pl 2 copy curveto } def /Y /y load def /l { pl lineto } def /L /l load def /m { pl moveto } def } ifelse /d { setdash } def /cf { } def /i { dup 0 eq { pop cf } if setflat } def /j { setlinejoin } def /J { setlinecap } def /M { setmiterlimit } def /w { setlinewidth } def /XR { 0 ne /_eo exch ddef } def /H { } def /h { closepath } def /N { _pola 0 eq { _doClip 1 eq { _eo {eoclip} {clip} ifelse /_doClip 0 ddef } if newpath } { /CRender { N } ddef } ifelse } def /n { N } def /F { _pola 0 eq { _doClip 1 eq { gsave _pf grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _fc /_doClip 0 ddef } { _pf } ifelse } { /CRender { F } ddef } ifelse } def /f { closepath F } def /S { _pola 0 eq { _doClip 1 eq { gsave _ps grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _sc /_doClip 0 ddef } { _ps } ifelse } { /CRender { S } ddef } ifelse } def /s { closepath S } def /B { _pola 0 eq { _doClip 1 eq gsave F grestore { gsave S grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _sc /_doClip 0 ddef } { S } ifelse } { /CRender { B } ddef } ifelse } def /b { closepath B } def /W { /_doClip 1 ddef } def /* { count 0 ne { dup type /stringtype eq { pop } if } if newpath } def /u { } def /U { } def /q { _pola 0 eq { gsave } if } def /Q { _pola 0 eq { grestore } if } def /*u { _pola 1 add /_pola exch ddef } def /*U { _pola 1 sub /_pola exch ddef _pola 0 eq { CRender } if } def /D { pop } def /*w { } def /*W { } def /` { /_i save ddef clipForward? { nulldevice } if 6 1 roll 4 npop concat pop userdict begin /showpage { } def 0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit [] 0 setdash /setstrokeadjust where {pop false setstrokeadjust} if newpath 0 setgray false setoverprint } def /~ { end _i restore } def /O { 0 ne /_of exch ddef /_lp /none ddef } def /R { 0 ne /_os exch ddef /_lp /none ddef } def /g { /_gf exch ddef /_fc { _lp /fill ne { _of setoverprint _gf setgray /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /G { /_gs exch ddef /_sc { _lp /stroke ne { _os setoverprint _gs setgray /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /k { _cf astore pop /_fc { _lp /fill ne { _of setoverprint _cf aload pop setcmykcolor /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /K { _cs astore pop /_sc { _lp /stroke ne { _os setoverprint _cs aload pop setcmykcolor /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /x { /_gf exch ddef findcmykcustomcolor /_if exch ddef /_fc { _lp /fill ne { _of setoverprint _if _gf 1 exch sub setcustomcolor /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /X { /_gs exch ddef findcmykcustomcolor /_is exch ddef /_sc { _lp /stroke ne { _os setoverprint _is _gs 1 exch sub setcustomcolor /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /A { pop } def /annotatepage { userdict /annotatepage 2 copy known {get exec} {pop pop} ifelse } def /XT { pop pop } def /discard { save /discardSave exch store discardDict begin /endString exch store gt38? { 2 add } if load stopped pop end discardSave restore } bind def userdict /discardDict 7 dict dup begin put /pre38Initialize { /endStringLength endString length store /newBuff buffer 0 endStringLength getinterval store /newBuffButFirst newBuff 1 endStringLength 1 sub getinterval store /newBuffLast newBuff endStringLength 1 sub 1 getinterval store } def /shiftBuffer { newBuff 0 newBuffButFirst putinterval newBuffLast 0 currentfile read not { stop } if put } def 0 { pre38Initialize mark currentfile newBuff readstring exch pop { { newBuff endString eq { cleartomark stop } if shiftBuffer } loop } { stop } ifelse } def 1 { pre38Initialize /beginString exch store mark currentfile newBuff readstring exch pop { { newBuff beginString eq { /layerCount dup load 1 add store } { newBuff endString eq { /layerCount dup load 1 sub store layerCount 0 eq { cleartomark stop } if } if } ifelse shiftBuffer } loop } if } def 2 { mark { currentfile buffer readline not { stop } if endString eq { cleartomark stop } if } loop } def 3 { /beginString exch store /layerCnt 1 store mark { currentfile buffer readline not { stop } if dup beginString eq { pop /layerCnt dup load 1 add store } { endString eq { layerCnt 1 eq { cleartomark stop } { /layerCnt dup load 1 sub store } ifelse } if } ifelse } loop } def end userdict /clipRenderOff 15 dict dup begin put { /n /N /s /S /f /F /b /B } { { _doClip 1 eq { /_doClip 0 ddef _eo {eoclip} {clip} ifelse } if newpath } def } forall /Tr /pop load def /Bb {} def /BB /pop load def /Bg {12 npop} def /Bm {6 npop} def /Bc /Bm load def /Bh {4 npop} def end /Lb { 4 npop 6 1 roll pop 4 1 roll pop pop pop 0 eq { 0 eq { (%AI5_BeginLayer) 1 (%AI5_EndLayer--) discard } { /clipForward? true def /Tx /pop load def /Tj /pop load def currentdict end clipRenderOff begin begin } ifelse } { 0 eq { save /discardSave exch store } if } ifelse } bind def /LB { discardSave dup null ne { restore } { pop clipForward? { currentdict end end begin /clipForward? false ddef } if } ifelse } bind def /Pb { pop pop 0 (%AI5_EndPalette) discard } bind def /Np { 0 (%AI5_End_NonPrinting--) discard } bind def /Ln /pop load def /Ap /pop load def /Ar { 72 exch div 0 dtransform dup mul exch dup mul add sqrt dup 1 lt { pop 1 } if setflat } def /Mb { q } def /Md { } def /MB { Q } def /nc 3 dict def nc begin /setgray { pop } bind def /setcmykcolor { 4 npop } bind def /setcustomcolor { 2 npop } bind def currentdict readonly pop end end setpacking %%EndResource %%BeginResource: procset Adobe_blend_AI5 1.4 0 %%Title: (Adobe Illustrator (R) Version 5.0 Blend ProcSet) %%Version: 1.4 0 %%CreationDate: (11/19/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /Adobe_blend_AI5 70 dict dup begin put /bd { bind def } bind def /xs { exch store } bd /nullProc { { } } def /initialize { pop pop Adobe_blend_AI5 begin Adobe_blend_AI5_vars begin /_contoneDevice where { pop } { /_contoneDevice false def } ifelse /_dpiThreshold where { pop } { /_dpiThreshold 600 def } ifelse /_screenFreqThreshold where { pop } { /_screenFreqThreshold 150 def } ifelse /tRectOK? deviceDPI _dpiThreshold le currentScreenFreq _screenFreqThreshold le and _contoneDevice not and def /invertXfer { [ { 1 exch sub } /exec load systemdict/currenttransfer get exec /exec load ] cvx systemdict/settransfer get exec } bd /spotDict 3 dict dup begin /nSpots 2 def /spot1 7 dict def /spot2 7 dict def end def composite? { /_setgray_ /setgray load def /_fill_ /fill load def /_image_ /image load def } { /_setgray_ systemdict/setgray get def /_fill_ systemdict/fill get def /_image_ systemdict/image get def } ifelse } bd /terminate { currentdict Adobe_blend_AI5_vars eq { end currentdict Adobe_blend_AI5 eq { end } if } if } bd /_compositeSpotDevice where { begin _compositeSpotDevice 0 ne {userdict /composite? true put} if end } { /_compositeSpotDevice 0 def } ifelse /nullString () def /d255 256 array def 0 1 255 { d255 exch dup 255 div put } bind for /d255- 256 array def 0 1 255 { d255- exch 1 d255 2 index get sub put } bind for /dUserSpace matrix defaultmatrix def currentdict /Adobe_blend_AI5_vars 89 dict dup begin put { /f /F /s /S /b /B } { null def } bind forall /byte 1 string def /sSave null def /setSSave { save /sSave exch store } bind def /Bm null def /doBlend null def /startC? false def /endC? false def /fCMYK? null def /startTint 0 def /endTint 0 def /bSMatrix matrix def /bUMatrix matrix def /dMatrix matrix def /inLine? true def /pTState? false def /bHi? false def /yHi 0 def /xHi 0 def /noImg /lv1Fix where { pop lv1Fix } { false } ifelse def /ccAry1 5 array def /ccTint 0 def /spotColor? false def /colorimage? true def [ /tint1Data /tint2Data /spotDict /bAxis /ubAxis /pChange /optimize? /nSamples /sInc /blendProc /_bn /xBCInc /yBCInc /bInc /bRender /cBName /cBType /nColors /color? /blend? /colorType /cData /cDataLen /bDataLen /rampPoint /midPoint /endPoint /blendLength /blackData /yeData /mgData /cyData /cnt1 /ndx /_fill /tmp counttomark { null def } bind repeat pop currentdict end currentdict end exch begin begin /unitSq { 0 0 moveto 0 1 lineto 1 1 lineto 1 0 lineto closepath } bd /gMark { counttomark 2 add -1 roll } bd /setCustomColor { dup /ccTint exch store 1 exch sub 6 1 roll ccAry1 astore exch setcustomcolor } bd /currentCustomColor { ccAry1 aload pop ccTint } bd /nsetcustomcolor where { pop } { /nsetcustomcolor { pop setcmykcolor } bd } ifelse /nsetcustomcolorend where { pop } { /nsetcustomcolorend { } bd } ifelse /setBSpace { newpath bUMatrix astore concat unitSq } bd /setCStop { dup 0 eq { pop spotColor? { dup 1 exch sub /ccTint exch def ccAry1 4 /Black put } if setgray } { 1 eq { setcmykcolor } { composite? not colorType 2 lt and { forceCMYK } { setCustomColor } ifelse } ifelse } ifelse } bd /makeByte { /tmp 0 store 255 mul cvi 8 string 8 { dup tmp 3 index put /tmp tmp 1 add store } repeat exch pop } bd /setImgSpace { cDataLen 1 8 2 index 0 0 1 0 0 dMatrix astore } bd /bwImage { setImgSpace cData /_image_ load { exec } stopped { $error /errorname get /undefinedresult ne { stop } { pop pop pop pop pop } ifelse } if } bd level2? { /bFill { _fill } def /bCImg { /cDataLen bDataLen store setImgSpace setSSave expandSpot cyData mgData yeData cData expandCMYK true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd } if /expandOne { dup type /stringtype ne { cDataLen string exch dup 0 ne { 255 mul cvi 0 1 cDataLen 1 sub { 3 copy exch put pop } for } if pop } if } bd /expandSpot { spotColor? { spotDict begin spot1 begin tintImage type /nulltype ne { tintImage expandOne /tintImage exch def } if end spot2 begin tintImage type /nulltype ne { tintImage expandOne /tintImage exch def } if end end } if } bd /expandCMYK { 4 { expandOne 4 1 roll } repeat } bd /colorimage where dup { exch pop /ncolorimage where { pop } { /ncolorimage {pop colorimage} bd } ifelse } if not { /ncolorimage where { pop } { /colorimage? false store /ncolorimage { pop pop pop setSSave /blackData xs /yeData xs /mgData xs /cyData xs /cnt1 0 store [ byte dup 0 cyData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .3 /mul cvx } { .3 mul } ifelse mgData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .59 /mul cvx } { .59 mul } ifelse yeData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .11 /mul cvx } { .11 mul } ifelse blackData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx } if /add cvx /add cvx /add cvx 1 /exch cvx /sub cvx /dup cvx 0 /lt cvx { pop 0 } /if cvx /dup cvx 1 /gt cvx { pop 1 } /if cvx 255 /mul cvx /cvi cvx 256 /mod cvx /dup cvx 0 /lt cvx { pop 0 } /if cvx /put cvx /cnt1 dup cvx 1 /add cvx /store cvx ] cvx bind _image_ sSave restore } bd } ifelse } if level2? not { /bCImg { /cDataLen bDataLen store setImgSpace setSSave expandSpot cyData mgData yeData cData colorimage? { expandCMYK } if true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd /bwFill { setSSave /cDataLen 8 store /cData currentgray makeByte store bwImage sSave restore } bd /c1ImgFill { setSSave /cDataLen 8 store setImgSpace spotColor? { spotDict begin spot1 begin currentCustomColor makeByte /tintImage exch def /name exch def /spot_K exch def /spot_Y exch def /spot_M exch def /spot_C exch def end spot2 initSpotData end } if currentcmykcolor 4 { makeByte 4 1 roll } repeat true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd /bFill noImg { { _fill } } { { color? { c1ImgFill } { bwFill } ifelse } } ifelse bd } if composite? { /bCFun { color? { cyData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if mgData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if yeData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if cData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if spotColor? { spotDict begin /spotDict cvx /begin cvx spot1 begin tintImage dup type /stringtype eq { /ndx cvx /get cvx d255- /exch cvx /get cvx } { dup type /nulltype ne { name type /nametype ne {1 exch sub} if } if } ifelse end /spot1 cvx /tintValue 3 -1 /roll cvx /put cvx spot2 begin tintImage dup type /stringtype eq { /ndx cvx /get cvx d255- /exch cvx /get cvx } { dup type /nulltype ne { name type /nametype ne {1 exch sub} if } if } ifelse end /spot2 cvx /tintValue 3 -1 /roll cvx /put cvx /end cvx end /spotDict cvx /nsetcustomcolor cvx } { /setcmykcolor cvx } ifelse } { cData /ndx cvx /get cvx d255 /exch cvx /get cvx /setgray cvx } ifelse } bd /Bc { newpath gsave setBSpace nColors 1 eq { pop pop setCStop } if bFill grestore } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { linImg } { bFill } ifelse grestore nColors 1 gt { getRData } if } bd /rdBm { /nColors dup load 1 sub store _fill gsave bUMatrix astore concat bHi? { xHi yHi bUMatrix idtransform /yHi exch store /xHi exch store rampPoint 1 lt { 1 rampPoint sub dup xHi mul exch yHi mul translate } if } if nColors { 0 0 rampPoint 0 360 arc _fill blend? bHi? or { rdBlend } if nColors 1 gt { getRData } if /nColors dup load 1 sub store } repeat /nColors 1 store grestore } bd /cGetRData { setCStop /blend? cData type /stringtype eq dup not color? and { pop cyData type /stringtype eq mgData type /stringtype eq yeData type /stringtype eq or or } if store } def /cGetRData } if /eCStop { mark 1 index 3 mul 3 add dup 8 gt { pop 8 } if 1 roll cleartomark } bd composite? not { /knockOut level2? { { 0 0 0 0 setcmykcolor _fill } } { /bFill noImg { { _fill } } { { _of true eq { currentgray 1 ne { bwFill } if } { bwFill } ifelse } } ifelse def /whiteByte 1 makeByte def noImg { { 0 0 0 0 setcmykcolor _fill } } { { cBType 0 eq { setSSave /cData whiteByte store /cDataLen 8 store bwImage sSave restore } { _fill } ifelse } } ifelse } ifelse bd /bCFun { cData dup type /stringtype ne { color? { 1 exch sub } if } { /ndx cvx /get cvx color? customColor? not and { d255- } { d255 } ifelse /exch cvx /get cvx } ifelse /_setgray_ cvx } bd /eCCBlend { dup 3 eq { pop mark 7 1 roll 6 copy ccThrough? dup /blend? xs { /startC? true store setCustomColor customColor? { /cData tint1Data store setCDataLen } if /endC? 3 index 3 eq { 4 index 1 ne } { false } ifelse store } if cleartomark stop } if 1 eq { pop pop pop } if pop /startC? false store 6 { 8 index } repeat ccThrough? dup /blend? xs { /endC? true store blend? not { stop } if customColor? { /cData tint1Data store setCDataLen } if } if } bd /handleOP { _of not { knockOut } if } bd /handleROP { _of not { 0 0 0 0 setcmykcolor _fill } { newpath } ifelse } bd /rdBm { /nColors dup load 1 sub store blend? { _fill } { handleROP } ifelse gsave bUMatrix astore concat bHi? { xHi yHi bUMatrix idtransform /yHi exch store /xHi exch store rampPoint 1 lt { 1 rampPoint sub dup xHi mul exch yHi mul translate } if } if nColors { 0 0 rampPoint 0 360 arc blend? { cData type /stringtype ne bHi? not and { cData color? { 1 exch sub } if _setgray_ _fill_ } { cData type /stringtype ne { /cDataLen 1 store /bDataLen 1 store } if rdBlend } ifelse } { handleROP pTState? { /bAxis rampPoint endPoint sub store xHi bAxis mul yHi bAxis mul translate } if } ifelse nColors 1 gt { getRData } if /nColors dup load 1 sub store } repeat /nColors 1 store grestore } bd /ccThrough? { gsave pop 0 setCustomColor currentcmykcolor grestore anyColor? } bd /forceCMYK { exch pop 1 exch sub 5 1 roll 4 { 4 index mul 4 1 roll } repeat 0 cCMYKData dup /cData ne { dup /yeData eq { pop 1 add } { /mgData eq { 2 } { 3 } ifelse add } ifelse 0 } if pop index 0 eq { pop pop pop pop 0 0 0 0 } if setcmykcolor pop /fCMYK? true store } bd /endCapSepBc { pop pop dup 0 eq { pop setgray } { 1 eq { setcmykcolor } { colorType 1 eq { forceCMYK } { fCMYK? { forceCMYK } { setCustomColor } ifelse } ifelse } ifelse } ifelse currentcmykcolor anyColor? blend? and { bFill } { handleOP } ifelse } bd } if /cCMYKData 0 def composite? dup not { pop customColor? } if not { /cCMYKData /cyData /mgData /yeData /cData black? not { yellow? { exch } { magenta? { 3 } { 4 } ifelse -1 roll } ifelse } if 4 1 roll pop pop pop store /Bc { gsave setBSpace nColors 1 gt { blend? currentcmykcolor anyColor? and { bFill } { handleOP } ifelse } { endCapSepBc } ifelse grestore newpath } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { cCMYKData load dup type /stringtype eq { dup length /cDataLen xs /cData xs gsave colorType 0 ne noImg not and { invertXfer } if linImg grestore } { pop bFill } ifelse } { handleOP } ifelse grestore nColors 1 gt { getRData } if } bd /cmykGetRData { /fCMYK? false store blend? { { cmykDataProcs colorType get exec } stopped pop blend? { /cData cCMYKData load store setCDataLen } if } if } def /cmykDataProcs [ { pop black? dup /blend? xs { setgray 0 } if pop } { cCMYKData load dup type /stringtype ne { 0 0 0 cyan? not { 4 magenta? { 1 } { yellow? { 2 } { 3 } ifelse } ifelse roll } if 4 copy add add add 0 eq { /blend? false store } if setcmykcolor /startC? true store /endC? true store eCStop stop } if pop dup 0 eq { pop setgray } { 1 eq { setcmykcolor } { forceCMYK } ifelse } ifelse } bind /eCCBlend load { cBType 1 eq { tint1Data tint2Data /tint1Data xs /tint2Data xs } if 0 eq { black? { setgray } { 0 0 0 4 -1 roll 1 exch sub setcmykcolor } ifelse black? { /blend? true store } if 6 { 8 index } repeat ccThrough? { /blend? true store } { black? { /cData tint1Data store setCDataLen } { /blend? false store } ifelse } ifelse } { mark 7 1 roll 6 copy ccThrough? { forceCMYK pop stop } if 9 index 0 eq { black? dup /blend? xs { pop 1 setgray /cData tint2Data store setCDataLen 0 } if pop } { /blend? 6 { 16 index } repeat ccThrough? store blend? { forceCMYK } if } ifelse cleartomark } ifelse } bind ] def /cmykGetRData } if composite? dup not { pop isCMYKSep? } if not { /endCapSepBc { /white? false store pop pop dup 0 eq { pop /white? 1 index 1 eq store setgray } { 1 eq { setcmykcolor } { setCustomColor } ifelse } ifelse % currentcmykcolor anyColor? endC? or blend? and { bFill } { handleOP } ifelse } bd /Bc { gsave setBSpace nColors 1 gt { blend? startC? and { bFill } { handleOP } ifelse } { endCapSepBc } ifelse grestore newpath } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { cData type /stringtype eq { linImg } { bFill } ifelse } { handleOP } ifelse grestore nColors 1 gt { getRData } if } bd /discardCMY { counttomark 4 add -3 roll pop pop pop } bd /testTopCC { 6 copy ccThrough? } bd /getCRamp { { ccDataProcs colorType 2 sub get exec } stopped pop blend? cDataLen 0 eq and { /cDataLen bDataLen store } if } bd /ccGetRData { /fCMYK? false store /startC? false store /endC? false store colorType 2 lt { /blend? false def } if blend? { getCRamp } { setCStop } ifelse blend? { /blend? cData 1 ne store blend? { cData dup type /stringtype ne { 1 exch sub /cData xs 0 } if pop } if } if } def /ccDataProcs [ /eCCBlend load { cBType 1 eq { tint1Data tint2Data /tint1Data xs /tint2Data xs } if 0 eq { /blend? false store pop } { mark 7 1 roll testTopCC { /blend? 1 index 1 ne store /startC? blend? store /endC? false store blend? not { cleartomark stop } if /cData tint1Data store setCDataLen setCustomColor pop stop } if cleartomark } ifelse 2 index 0 eq { /blend? false store } { mark 6 { 9 index } repeat testTopCC dup /blend? xs { /blend? 1 index 1 ne store /endC? blend? store /startC? false store blend? not { cleartomark stop } if /cData tint2Data store setCDataLen } if cleartomark } ifelse } bind ] def /ccGetRData } if load Adobe_blend_AI5_vars /getData 3 -1 roll put /setCDataLen { /cDataLen 0 cData dup type /stringtype eq { length exch } if pop store } bd /initSpotData { begin /name null def /tintImage null def /tintValue null def /spot_C null def /spot_M null def /spot_Y null def /spot_K null def end } bd /getRData { /colorType gMark store _compositeSpotDevice 0 ne { spotDict begin spot1 initSpotData spot2 initSpotData end /spotColor? colorType 2 eq colorType 3 eq or def } { /spotColor? false store } ifelse /blend? true store 0 0 0 0 setcmykcolor 100 div /rampPoint xs % (between 13 and 87%) 100 div /midPoint xs dup 0 eq { 2 } { dup 1 eq { 5 } { _compositeSpotDevice 0 ne { spotDict begin spot1 begin /name 3 index def /spot_K 4 index def /spot_Y 5 index def /spot_M 6 index def /spot_C 7 index def end end } if 7 } ifelse } ifelse /tmp exch def tmp index 100 div /endPoint xs _compositeSpotDevice 0 ne { tmp 2 add index 3 eq { /tmp tmp 4 add def tmp index dup spotDict begin spot1/name get ne { spot2 begin /name exch def /spot_K tmp 2 add index def /spot_Y tmp 3 add index def /spot_M tmp 4 add index def /spot_C tmp 5 add index def end } { pop } ifelse end } if } if /color? colorType 0 gt store colorType 3 eq { /tint2Data gMark store } if colorType 2 ge { /tint1Data gMark store } if _compositeSpotDevice 0 ne { spotDict begin colorType 2 ge { colorType 3 eq { spot2 begin /tintImage cBType 0 eq {tint2Data} {tint1Data} ifelse def name null eq {/name /Black def} if end } if spot1 begin /tintImage cBType 0 eq colorType 2 eq or {tint1Data} {tint2Data} ifelse def colorType 2 eq { name null eq { /name spot2/name get def spot2/name null put } if } { name null eq {/name /Black def} if } ifelse end } if end } if /cData gMark store setCDataLen colorType 0 gt { counttomark 4 add -3 roll /yeData xs /mgData xs /cyData xs } if blend? { /bDataLen cDataLen dup 0 eq color? and { [ cyData mgData yeData ] { dup type /stringtype eq { length exch pop exit } if pop } forall } if store bDataLen 0 eq { /bDataLen 1 store } if getData blend? { composite? cDataLen 0 eq and { /cDataLen bDataLen store } if } if } { setCStop } ifelse } bd /Bg { 0 0 0 0 setcmykcolor 6 { pop } repeat /blendLength xs pop pop pop /cBName xs /bRender xs bRender 2 ne { composite? not { _of setoverprint } if _eo {eoclip} {clip} ifelse _bn cBName 2 copy known { get mark exch aload pop /cBType xs /nColors xs mark exch aload pop 0 0 } if pop pop getRData cBType 0 eq { /linealBm } { bHi? { /pTState? nColors 2 gt store } if /doBlend /rdBlend load store /rdBm } ifelse } { inLine? not { mark mark } if /Bc dup { cleartomark mark } bd /nullProc } ifelse load /Bm xs } bd /linImg noImg { { newpath doRctBlend } } { { /doBlend color? composite? and { /bCImg } { /bwImage } ifelse load store 0 0 moveto tRectOK? composite? and { { mark 0 1 dtransform atan cvi 90 mod 0 eq 1 0 dtransform atan cvi 90 mod 0 eq } stopped { cleartomark } { and exch pop { newpath doRctBlend } { doBlend } ifelse } ifelse } { doBlend } ifelse } } ifelse bd /doRctBlend { gsave /sInc 1 store /nSamples bDataLen store /bInc 1 bDataLen div store /ubAxis 1 0 dtransform dUserSpace idtransform dup mul exch dup mul add sqrt store /pChange ubAxis 0 eq { 0 } { bDataLen ubAxis div } ifelse store pChange .5 gt noImg not and dup /optimize? xs { /nSamples ubAxis 2 div round cvi dup 1 le { pop 2 } if store /bInc 1 nSamples div store /sInc bDataLen 1 sub nSamples 1 sub div store } if 0 nSamples [ /dup cvx optimize? { /round cvx /cvi cvx } if /ndx /exch cvx /store cvx bCFun /rectfill where dup { exch pop _compositeSpotDevice 1 ne and } if { 0 0 bInc 1 /rectfill cvx } { 0 0 /moveto cvx bInc 0 /lineto cvx bInc 1 /lineto cvx 0 1 /lineto cvx /closepath cvx /_fill_ cvx } ifelse bInc 0 /translate cvx sInc /add cvx ] cvx bind repeat pop spotColor? {nsetcustomcolorend} if grestore } bd /rdPrep { /nSamples bDataLen dup 0 eq { pop 1 } if store /sInc -1 store /bAxis rampPoint endPoint sub store /bInc bAxis bDataLen div neg store /optimize? false store tRectOK? { /ubAxis bAxis 0 dtransform dUserSpace idtransform dup mul exch dup mul add sqrt 0 bAxis dtransform dUserSpace idtransform dup mul exch dup mul add sqrt 2 copy lt { exch } if pop store /pChange ubAxis 0 eq { 0 } { bDataLen ubAxis div } ifelse store pChange .5 gt noImg not and dup /optimize? xs { /nSamples ubAxis 2 div round cvi dup 1 le { pop 2 } if store /bInc bAxis nSamples div neg store /sInc bDataLen 1 sub nSamples 1 sub div neg store } if } if bHi? { /xBCInc xHi bAxis mul nSamples div store /yBCInc yHi bAxis mul nSamples div store } if } bd /rdBlend { newpath gsave rdPrep rampPoint bDataLen 1 sub nSamples [ /dup cvx optimize? { /round cvx /cvi cvx } if /ndx /exch cvx /store cvx bCFun 0 0 3 /index cvx 0 360 /arc cvx /_fill_ cvx /exch cvx bInc /add cvx /exch cvx sInc /add cvx bHi? { xBCInc yBCInc /translate cvx } if ] cvx bind repeat pop pop spotColor? {nsetcustomcolorend} if grestore pTState? { xHi bAxis mul yHi bAxis mul translate } if } bd /Bh { pop pop /pTState? false store 2 copy 0 ne exch 0 ne or dup /bHi? xs { /yHi xs /xHi xs 0 0 } if pop pop } bd /BD { inLine? not { ] nColors cBType ] _bn cBName 3 -1 roll put end } if } bd /Bn { 1 add dict dup nullString null put /_bn xs } bd /Bd { Adobe_blend_AI5_vars begin 3 -1 roll dup nullString eq dup { setSSave } if /inLine? exch def /cBName exch def /nColors exch def /cBType exch def } bd /Bb { sSave null eq { Adobe_blend_AI5_vars begin setSSave } if composite? { /_fill /fill load store } { /__fill /fill load store /_fill { _of true eq { currentgray 1 ne { __fill } if } { __fill } ifelse } def } ifelse /fill { } def } bd /BB { /cBType xs cleartomark cleartomark cBType dup bRender sSave dup type /savetype eq { restore 0 } if pop currentdict Adobe_blend_AI5_vars eq { end } if 2 ne exch 0 gt and { 2 eq { s } { S } ifelse } { pop newpath } ifelse } bd currentdict readonly pop end end defaultpacking setpacking %%EndResource %%BeginResource: procset Adobe_pattern_AI5 1.1 0 %%Title: (Adobe Illustrator (R) Version 5.0 Pattern Operators) %%Version: 1.1 0 %%CreationDate: (03/26/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_Illustrator_AI5 known not { userdict /Adobe_Illustrator_AI5 95 dict put } if userdict /Adobe_Illustrator_AI5 get begin /@ { } def /& { } def /dp { dup null eq { pop _dp 0 ne { 0 1 _dp 1 sub _dl mod { _da exch get 3 get } for _dp 1 sub _dl mod 1 add packedarray _da 0 get aload pop 8 -1 roll 5 -1 roll pop 4 1 roll definepattern pop } if } { _dp 0 ne _dp _dl mod 0 eq and { null dp } if 7 packedarray _da exch _dp _dl mod exch put _dp _dl mod _da 0 get 4 get 2 packedarray /_dp _dp 1 add def } ifelse } def /E { _ed begin dup 0 get type /arraytype ne { 0 { dup 1 add index type /arraytype eq { 1 add } { exit } ifelse } loop array astore } if /_dd exch def /_ury exch def /_urx exch def /_lly exch def /_llx exch def /_n exch def /_y 0 def /_dl 4 def /_dp 0 def /_da _dl array def 0 1 _dd length 1 sub { /_d exch _dd exch get def 0 2 _d length 2 sub { /_x exch def /_c _d _x get _ ne def /_r _d _x 1 add get cvlit def _r _ ne { _urx _llx sub _ury _lly sub [ 1 0 0 1 0 0 ] [ /save cvx _llx neg _lly neg /translate cvx _c { nc /begin cvx } if _r dup type /stringtype eq { cvx } { { exec } /forall cvx } ifelse _c { /end cvx } if /restore cvx ] cvx /_fn 12 _n length add string def _y _fn cvs pop /_y _y 1 add def _fn 12 _n putinterval _fn _c false dp _d exch _x 1 add exch put } if } for } for null dp _n _dd /_pd end xput } def /fc { _fm dup concatmatrix pop } def /p { /_fm exch ddef 9 -2 roll _pm translate fc 7 -2 roll _pm scale fc 5 -1 roll _pm rotate fc 4 -2 roll exch 0 ne { dup _pm rotate fc 1 -1 _pm scale fc neg _pm rotate fc } { pop } ifelse dup _pm rotate fc exch dup sin exch cos div 1 0 0 1 0 6 2 roll _pm astore fc neg _pm rotate fc _pd exch get /_fdd exch ddef /_pf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm patternfill } { pop fill } ifelse grestore pop } for pop } for restore newpath } ddef /_psf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm 9 copy 6 npop patternashow } { pop 6 copy 3 npop hvashow } ifelse grestore pop } for pop } for restore sw rmoveto } ddef /_pjsf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm 12 copy 6 npop patternawidthshow } { pop 9 copy 3 npop hvawidthshow } ifelse grestore pop } for pop } for restore swj rmoveto } ddef /_lp /none ddef } def /sc { _sm dup concatmatrix pop } def /P { /_sm exch ddef 9 -2 roll _pm translate sc 7 -2 roll _pm scale sc 5 -1 roll _pm rotate sc 4 -2 roll exch 0 ne { dup _pm rotate sc 1 -1 _pm scale sc neg _pm rotate sc } { pop } ifelse dup _pm rotate sc exch dup sin exch cos div 1 0 0 1 0 6 2 roll _pm astore sc neg _pm rotate sc _pd exch get /_sdd exch ddef /_ps { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm patternstroke } { pop stroke } ifelse grestore pop } for pop } for restore newpath } ddef /_pss { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm 10 copy 6 npop patternashowstroke } { pop 7 copy 3 npop ss } ifelse grestore pop } for pop } for restore pop sw rmoveto } ddef /_pjss { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm 13 copy 6 npop patternawidthshowstroke } { pop 10 copy 3 npop jss } ifelse grestore pop } for pop } for restore pop swj rmoveto } ddef /_lp /none ddef } def end userdict /Adobe_pattern_AI5 18 dict dup begin put /initialize { /definepattern where { pop } { begin begin Adobe_pattern_AI5 begin Adobe_pattern_AI5 { dup xcheck { bind } if pop pop } forall mark cachestatus 7 1 roll pop pop pop pop exch pop exch { { 10000 add dup 2 index gt { exit } if dup setcachelimit } loop } stopped cleartomark end end end Adobe_pattern_AI5 begin } ifelse } def /terminate { currentdict Adobe_pattern_AI5 eq { end } if } def errordict /nocurrentpoint { pop stop } put errordict /invalidaccess { pop stop } put /patternencoding 256 array def 0 1 255 { patternencoding exch ( ) 2 copy exch 0 exch put cvn put } for /definepattern { 17 dict begin /uniform exch def /cache exch def /key exch def /procarray exch def /mtx exch matrix invertmatrix def /height exch def /width exch def /ctm matrix currentmatrix def /ptm matrix def /str 32 string def /slice 9 dict def slice /s 1 put slice /q 256 procarray length div sqrt floor cvi put slice /b 0 put /FontBBox [ 0 0 0 0 ] def /FontMatrix mtx matrix copy def /Encoding patternencoding def /FontType 3 def /BuildChar { exch begin /setstrokeadjust where {pop true setstrokeadjust} if slice begin dup q dup mul mod s idiv /i exch def dup q dup mul mod s mod /j exch def q dup mul idiv procarray exch get /xl j width s div mul def /xg j 1 add width s div mul def /yl i height s div mul def /yg i 1 add height s div mul def uniform { 1 1 } { width 0 dtransform dup mul exch dup mul add sqrt dup 1 add exch div 0 height dtransform dup mul exch dup mul add sqrt dup 1 add exch div } ifelse width 0 cache { xl 4 index mul yl 4 index mul xg 6 index mul yg 6 index mul setcachedevice } { setcharwidth } ifelse gsave scale newpath xl yl moveto xg yl lineto xg yg lineto xl yg lineto closepath clip newpath end end exec grestore } def key currentdict definefont end } def /patterncachesize { gsave newpath 0 0 moveto width 0 lineto width height lineto 0 height lineto closepath patternmatrix setmatrix pathbbox exch ceiling 4 -1 roll floor sub 3 1 roll ceiling exch floor sub mul 1 add grestore } def /patterncachelimit { cachestatus 7 1 roll 6 npop 8 mul } def /patternpath { exch dup begin setfont ctm setmatrix concat slice exch /b exch slice /q get dup mul mul put FontMatrix concat uniform { width 0 dtransform round width div exch round width div exch 0 height dtransform round height div exch height div exch 0 0 transform round exch round exch ptm astore setmatrix } { ptm currentmatrix pop } ifelse { currentpoint } stopped not { 2 npop pathbbox true 4 index 3 index eq 4 index 3 index eq and { pop false { { 2 npop } { 3 npop true } { 7 npop true } { pop true } pathforall } stopped { 5 npop true } if } if { height div ceiling height mul 4 1 roll width div ceiling width mul 4 1 roll height div floor height mul 4 1 roll width div floor width mul 4 1 roll 2 index sub height div ceiling cvi exch 3 index sub width div ceiling cvi exch 4 2 roll moveto FontMatrix mtx invertmatrix dup dup 4 get exch 5 get rmoveto ptm ptm concatmatrix pop slice /s patterncachesize patterncachelimit div ceiling sqrt ceiling cvi dup slice /q get gt { pop slice /q get } if put 0 1 slice /s get dup mul 1 sub { slice /b get add gsave 0 1 str length 1 sub { str exch 2 index put } for pop dup { gsave ptm setmatrix 1 index str length idiv { str show } repeat 1 index str length mod str exch 0 exch getinterval show grestore 0 height rmoveto } repeat grestore } for 2 npop } { 4 npop } ifelse } if end } def /patternclip { _eo {eoclip} {clip} ifelse } def /patternstrokepath { strokepath } def /patternmatrix matrix def /patternfill { dup type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get } if gsave patternclip Adobe_pattern_AI5 /patternpath get exec grestore newpath } def /patternstroke { dup type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get } if gsave patternstrokepath true { { { newpath moveto } { lineto } { curveto } { closepath 3 copy Adobe_pattern_AI5 /patternfill get exec } pathforall 3 npop } stopped { 5 npop patternclip Adobe_pattern_AI5 /patternfill get exec } if } { patternclip Adobe_pattern_AI5 /patternfill get exec } ifelse grestore newpath } def /vpatternawidthshow { 6 1 roll /_hvay exch ddef /_hvax exch ddef /_hvwb exch ddef /_hvcy exch ddef /_hvcx exch ddef { dup cstring dup length 1 eq _charorientation 1 eq and { -90 rotate currentpoint _fontRotateAdjust add moveto gsave false charpath currentpoint 5 index 5 index 5 index Adobe_pattern_AI5 /patternfill get exec grestore _fontRotateAdjust sub moveto _hvwb eq { _hvcx _hvcy rmoveto } if _hvax _hvay rmoveto 90 rotate } { currentpoint _fontHeight sub _hvax sub 3 index _hvwb eq { _hvcx sub } if currentpoint exch 4 index stringwidth pop 2 div sub exch _fontAscent sub moveto gsave 2 index false charpath 6 index 6 index 6 index Adobe_pattern_AI5 /patternfill get exec grestore newpath moveto pop pop } ifelse } cforall 3 npop } def /hpatternawidthshow { { dup cstring exch gsave 3 index eq { 5 index 5 index rmoveto } if false charpath currentpoint 9 index 9 index 9 index Adobe_pattern_AI5 /patternfill get exec grestore newpath moveto 2 copy rmoveto } cforall 8 npop } def /patternashow { 0 0 0 6 3 roll patternawidthshow } def /patternawidthshow { 6 index type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get 7 1 roll } if _lineorientation 0 eq { hpatternawidthshow } { vpatternawidthshow } ifelse } def /vpatternawidthshowstroke { 7 1 roll 6 1 roll /_hvay exch ddef /_hvax exch ddef /_hvwb exch ddef /_hvcy exch ddef /_hvcx exch ddef { dup cstring dup length 1 eq _charorientation 1 eq and { -90 rotate currentpoint _fontRotateAdjust add moveto gsave false charpath currentpoint 3 index setmatrix 6 index 6 index 6 index Adobe_pattern_AI5 /patternstroke get exec grestore _fontRotateAdjust sub moveto _hvwb eq { _hvcx _hvcy rmoveto } if _hvax _hvay rmoveto 90 rotate } { currentpoint _fontHeight sub _hvax sub 3 index _hvwb eq { _hvcx sub } if currentpoint exch 4 index stringwidth pop 2 div sub exch _fontAscent sub moveto gsave 2 index false charpath 4 index setmatrix 7 index 7 index 7 index Adobe_pattern_AI5 /patternstroke get exec grestore newpath moveto pop pop } ifelse } cforall 4 npop } def /hpatternawidthshowstroke { 7 1 roll { dup cstring exch gsave 3 index eq { 5 index 5 index rmoveto } if false charpath currentpoint 7 index setmatrix 10 index 10 index 10 index Adobe_pattern_AI5 /patternstroke get exec grestore newpath moveto 2 copy rmoveto } cforall 9 npop } def /patternashowstroke { 0 0 0 7 3 roll patternawidthshowstroke } def /patternawidthshowstroke { 7 index type /dicttype eq { patternmatrix /patternmatrix get 8 1 roll } if _lineorientation 0 eq { hpatternawidthshowstroke } { vpatternawidthshowstroke } ifelse } def end setpacking %%EndResource %%EndProlog %%BeginSetup Adobe_level2_AI5 /initialize get exec Adobe_screens_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_typography_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_blend_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_pattern_AI5 /initialize get exec Adobe_ColorImage_AI6 /initialize get exec Adobe_Illustrator_AI5 /initialize get exec [ 39/quotesingle 96/grave 130/quotesinglbase 131/florin 132/quotedblbase 133/ellipsis 134/dagger 135/daggerdbl 136/circumflex 137/perthousand 138/Scaron 139/guilsinglleft 140/OE 145/quoteleft 146/quoteright 147/quotedblleft 148/quotedblright 149/bullet 150/endash 151/emdash 152/tilde 153/trademark 154/scaron 155/guilsinglright 156/oe 157/dotlessi 159/Ydieresis 164/currency 166/brokenbar 168/dieresis 169/copyright 170/ordfeminine 172/logicalnot 174/registered 175/macron 176/ring 177/plusminus 178/twosuperior 179/threesuperior 180/acute 181/mu 183/periodcentered 184/cedilla 185/onesuperior 186/ordmasculine 188/onequarter 189/onehalf 190/threequarters 192/Agrave 193/Aacute 194/Acircumflex 195/Atilde 196/Adieresis 197/Aring 198/AE 199/Ccedilla 200/Egrave 201/Eacute 202/Ecircumflex 203/Edieresis 204/Igrave 205/Iacute 206/Icircumflex 207/Idieresis 208/Eth 209/Ntilde 210/Ograve 211/Oacute 212/Ocircumflex 213/Otilde 214/Odieresis 215/multiply 216/Oslash 217/Ugrave 218/Uacute 219/Ucircumflex 220/Udieresis 221/Yacute 222/Thorn 223/germandbls 224/agrave 225/aacute 226/acircumflex 227/atilde 228/adieresis 229/aring 230/ae 231/ccedilla 232/egrave 233/eacute 234/ecircumflex 235/edieresis 236/igrave 237/iacute 238/icircumflex 239/idieresis 240/eth 241/ntilde 242/ograve 243/oacute 244/ocircumflex 245/otilde 246/odieresis 247/divide 248/oslash 249/ugrave 250/uacute 251/ucircumflex 252/udieresis 253/yacute 254/thorn 255/ydieresis TE %AI3_BeginEncoding: _Helvetica Helvetica [ /_Helvetica/Helvetica 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-Bold Helvetica-Bold [ /_Helvetica-Bold/Helvetica-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-Oblique Helvetica-Oblique [ /_Helvetica-Oblique/Helvetica-Oblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-BoldOblique Helvetica-BoldOblique [ /_Helvetica-BoldOblique/Helvetica-BoldOblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Roman Times-Roman [ /_Times-Roman/Times-Roman 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Bold Times-Bold [ /_Times-Bold/Times-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Italic Times-Italic [ /_Times-Italic/Times-Italic 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-BoldItalic Times-BoldItalic [ /_Times-BoldItalic/Times-BoldItalic 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier Courier [ /_Courier/Courier 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-Bold Courier-Bold [ /_Courier-Bold/Courier-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-Oblique Courier-Oblique [ /_Courier-Oblique/Courier-Oblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-BoldOblique Courier-BoldOblique [ /_Courier-BoldOblique/Courier-BoldOblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Symbol Symbol [ /_Symbol/Symbol 0 0 1 TZ %AI3_EndEncoding AdobeType %%EndSetup 1 XR u 0.000 0.000 0.000 0.000 k [] 0 d 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 149.6693 517.6063 m 221.1024 517.6063 L 221.1024 553.3228 L 149.6693 553.3228 L 149.6693 517.6063 L B U 0 To 1.0000 0.0000 0.0000 1.0000 171.7795 539.1496 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (NUA/\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 156.4724 524.9764 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0.000 0.000 0.000 1.000 k (Sofia stack\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 J 1 j 185.3858 517.6063 m 185.3858 31.7480 L S U u 14.7402 445.6063 m 181.9843 445.6063 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 181.4173 447.8740 m 185.3858 445.6063 L 181.4173 443.9055 L 181.4173 447.8740 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 74.8346 449.0079 m 124.7244 449.0079 L 124.7244 460.3465 L 74.8346 460.3465 L 74.8346 449.0079 L F U 0 To 1.0000 0.0000 0.0000 1.0000 75.9685 451.8425 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (nua_handle\(\)\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 14.7402 409.3228 m 172.9134 409.3228 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 172.3465 411.5906 m 176.3150 409.3228 L 172.3465 407.0551 L 172.3465 411.5906 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 73.1339 412.7244 m 117.3543 412.7244 L 117.3543 424.6299 L 73.1339 424.6299 L 73.1339 412.7244 L F U 0 To 1.0000 0.0000 0.0000 1.0000 74.2677 415.5591 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (nua_invite\(\)\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.000 k 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 176.3150 158.1732 m 194.4567 158.1732 L 194.4567 409.3228 L 176.3150 409.3228 L 176.3150 158.1732 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 149.6693 355.4646 m 221.1024 355.4646 L 221.1024 382.6772 L 149.6693 382.6772 L 149.6693 355.4646 L B U 0 To 1.0000 0.0000 0.0000 1.0000 153.0709 365.6693 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (setup media\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 194.4567 328.8189 m 370.7717 328.8189 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 370.2047 331.0866 m 374.1732 328.8189 L 370.2047 327.1181 L 370.2047 331.0866 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 260.7874 332.2205 m 307.2756 332.2205 L 307.2756 343.5591 L 260.7874 343.5591 L 260.7874 332.2205 L F U 0 To 1.0000 0.0000 0.0000 1.0000 261.9213 335.0551 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (INVITE / SDP\r) Tx TO 0.000 0.000 0.000 1.000 K u [8 4 ] 0 d 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 374.1732 283.4646 m 197.8583 283.4646 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 198.4252 281.7638 m 194.4567 283.4646 L 198.4252 285.7323 L 198.4252 281.7638 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 264.1890 286.8661 m 303.8740 286.8661 L 303.8740 298.2047 L 264.1890 298.2047 L 264.1890 286.8661 L F U 0 To 1.0000 0.0000 0.0000 1.0000 265.3228 290.2677 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr [] 0 d 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (100 Trying\r) Tx TO 0.000 0.000 0.000 1.000 K u [8 4 ] 0 d 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 358.8661 239.8110 m 197.8583 239.8110 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 198.4252 238.1102 m 194.4567 239.8110 L 198.4252 242.0787 L 198.4252 238.1102 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 254.5512 243.2126 m 298.2047 243.2126 L 298.2047 254.5512 L 254.5512 254.5512 L 254.5512 243.2126 L F U 0 To 1.0000 0.0000 0.0000 1.0000 255.6850 246.6142 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr [] 0 d 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (180 Ringing\r) Tx TO 0.000 0.000 0.000 1.000 K u [8 4 ] 0 d 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 176.3150 229.6063 m 18.1417 229.6063 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 18.7087 227.3386 m 14.7402 229.6063 L 18.7087 231.8740 L 18.7087 227.3386 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 72.5669 233.5748 m 118.4882 233.5748 L 118.4882 244.9134 L 72.5669 244.9134 L 72.5669 233.5748 L F U 0 To 1.0000 0.0000 0.0000 1.0000 73.1339 236.4094 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr [] 0 d 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (nua_r_invite\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 374.1732 202.3937 m 197.8583 202.3937 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 198.4252 200.6929 m 194.4567 202.3937 L 198.4252 204.6614 L 198.4252 200.6929 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 259.6535 205.7953 m 308.4094 205.7953 L 308.4094 217.1339 L 259.6535 217.1339 L 259.6535 205.7953 L F U 0 To 1.0000 0.0000 0.0000 1.0000 260.7874 209.1969 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (200 Ok / SDP\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 176.3150 193.8898 m 18.1417 193.8898 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 18.7087 191.6220 m 14.7402 193.8898 L 18.7087 195.5906 L 18.7087 191.6220 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 72.5669 197.2913 m 118.4882 197.2913 L 118.4882 208.6299 L 72.5669 208.6299 L 72.5669 197.2913 L F U 0 To 1.0000 0.0000 0.0000 1.0000 73.1339 200.1260 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (nua_r_invite\r) Tx TO 0.000 0.000 0.000 1.000 K u [8 4 ] 0 d 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 14.7402 166.6772 m 172.9134 166.6772 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 172.3465 168.9449 m 176.3150 166.6772 L 172.3465 164.9764 L 172.3465 168.9449 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 75.9685 170.0787 m 114.5197 170.0787 L 114.5197 181.4173 L 75.9685 181.4173 L 75.9685 170.0787 L F U 0 To 1.0000 0.0000 0.0000 1.0000 77.1024 173.4803 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr [] 0 d 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (nua_ack\(\)\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 194.4567 158.1732 m 370.7717 158.1732 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 370.2047 159.8740 m 374.1732 158.1732 L 370.2047 155.9055 L 370.2047 159.8740 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 274.9606 161.5748 m 293.1024 161.5748 L 293.1024 172.9134 L 274.9606 172.9134 L 274.9606 161.5748 L F U 0 To 1.0000 0.0000 0.0000 1.0000 276.0945 164.4094 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (ACK\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.000 k 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 149.6693 112.8189 m 221.1024 112.8189 L 221.1024 140.0315 L 149.6693 140.0315 L 149.6693 112.8189 L B U 0 To 1.0000 0.0000 0.0000 1.0000 164.9764 129.8268 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (activate\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 168.9449 115.6535 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k (media\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 185.3858 86.1732 m 18.1417 86.1732 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 18.7087 83.9055 m 14.7402 86.1732 L 18.7087 87.8740 L 18.7087 83.9055 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 75.9685 89.5748 m 123.5906 89.5748 L 123.5906 100.3465 L 75.9685 100.3465 L 75.9685 89.5748 L F U 0 To 1.0000 0.0000 0.0000 1.0000 77.1024 92.4094 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (nua_i_active\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 366.8031 289.1339 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0.000 0.000 0.000 1.000 k (\(1\)\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 13.6063 236.4094 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k (\(1\)\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 366.8031 236.4094 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k (\(1\)\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 9.6378 173.4803 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k (\(2\)\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 9.0709 19.8425 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k (\(1\) optional\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 9.0709 5.1024 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k (\(2\) optional - needed only if no NUTAG_AUTOACK set\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 261.9213 468.2835 m 196.7244 403.0866 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 198.4252 401.9528 m 194.4567 400.2520 L 195.5906 404.7874 L 198.4252 401.9528 L F U 0 To 1.0000 0.0000 0.0000 1.0000 256.8189 468.8504 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (lifetime of INVITE transaction\r) Tx TO 0.000 0.000 0.000 1.000 K %%PageTrailer gsave annotatepage grestore showpage %%Trailer Adobe_Illustrator_AI5 /terminate get exec Adobe_pattern_AI5 /terminate get exec Adobe_blend_AI5 /terminate get exec Adobe_ColorImage_AI6 /terminate get exec Adobe_typography_AI5 /terminate get exec Adobe_screens_AI5 /terminate get exec Adobe_level2_AI5 /terminate get exec %%EOF II*6d(@""11@@OO^^nn}}""++33<k~t)՟u}߀b[~%h F(!IA87v\zሔ[}ӅrX( f4cSu@cDiؐF&K:PV+힭Nk^zj).:fvҡKe_'nr^ l5/l. /V.:^e0 o|-g/**ڟzھvG ̛L#<;.7ͯF'ѵJkFX&t\6]%&E[mljLr Xrr,ڪsw߀wIcG/wzB)Sny\_vw^U枇WG檯~ysh{;zxwwGs.sAf"gc`>I=j̓i'6oiK~;  4xaB 6tbDxcF5vdH#I4yeJ9R`Kg48"Ε;yhPCC̨f0PZhTSVz5jӘK| +Mcɖ5{mֈkBo"[1m^{ 6|oXċ7vدbȓ)W|d̛9wYgѣItjիYDvlٳ}wԶ  .]q5)p‰rpoN=:suwɛ1xs|z6=__G|,~c/y2 \{0' -6 8DʷCC]|0[Ѻ}(H+$ NE |c.A|'U?e?xYXsKيYVyw>ء^tJ^{M_2'xn[|B~) YS4nx}f|AB4.lf Zpwr̄?iMHA-ˆ!W*m uo 4xaB 6tbDxcF9vdȌI4yeJ+YtfL-̴IM;yhP?shhQJd4ӡSVzkVRM&iA_UrzmZkN5S,KɆkm^{_6|qbmrd~J !f 5OthB{״ҧi95`ѳi׶M-Scy/};ިc}yٝ3WzS~{v"wv۶^}zϯw>׷O~~gO Z~馫&YjaZ^^ sֹ|LKأ}7x{Y+(K- 6٢9.go5&^m̛h>E6o`>hBp&OIp#!DRDUJޑѕZXIN|Ӑb YOv˾*(D& $XA .dC%NX`0fG!E$YI)nT K0]ΤYM9u^\'Ks#ƣ;MSONZUYnWaŎYT/E÷mΥ[]ymW_>\ذA fcȑ#.NHYe̙5ov2gСE&3ҩU jOiV[hEy'^1(ଉv7'YuV+h۱'_vxυ4X_{ߵ>[kݟ?}s@%C/Atp:pB 1BޤpC.CCDCK4DPTqEG"EcEkQ0rqGnG#ln!5GtIK=ߪSo.E(2$r%d2S̨\K64-6ݔ8:ԓCs=zlM4> =3C#}2ϻ(RxtS0SHAuԺ,%TTsKuUVi2UX]Q&4*jH^W\+ZJuT3_ufhmWkv[n gw%\Ew]:uTuߕxz|~6VXv#^a+VbA8c;@c9"qcFι*Jd\ђcnd[$7eq~Le9ʾTyhnuPūboFyz(]j}Kk{>E:]u9+mnykQnM..@9.Jv2n\_VQ oѩ.]rkrrzbkv p "Lp!ÆB(q"Ŋ/b̨q#ǎ? )r$ɒ&18aʕ._Œ)s&͚62Ξ> *tED==t)ӦNFL`NVJ*׮^=bJU,6ذn+@ۉ-yM[0,,x0QQ"x51c ,y2eH:V63fl+-zBuGӤ_Î 5\ڲomӶ[޺7X#OsqΟ+kas W}u ^5Xx7s/y[3¹j)zbyRXalޭ_~e{h#NVziIމVy $Xcm٘^e7ێ?TO G~&ZH2i-餔S%WbYYr\[z]9gkV&o¹SsIdw)ygC{ Zzs&k6cF:\VzSfHv?:5z:ݚ+e{!i҅Xvc1[,k!|&-FcBJ;p~ZV"zɛ^b{oc(.Pa{ 28c(N.f*k12rXqjvXlp!g-{̱ .hr0 "\eKpLN3)rF]c3[TPj֔MaD\Fr}ٿh}5bj7r`mng7 j[+Zߖز?'+qmS'U"#]:/%k| e$dˤܿ$d苤c;?ٞ_>brW+Y(7̀m Ia*+K.(UЂzj@v@PQ U$p}b>ġNu6q$CH%q?_'7pG"xD6]H*Xb.z9 kHi2o6/p@H*\ȰÇ#J0ŋ3"Ǐ CIɓ(S$qˆ-_ʜI͛8sdsʞ> Jѣ"tӧPJ)UVjʵWYr ٳhӪ-HVa۟XʝKО1[} e&˸Lċreʒ_ΌY)`̐CMZd˙ 'm:/ś_.Mm k>lpŅy}GRTN9У5\fuسkwxkkޕoߺ>_}Ͽq'H&XUF*'afxޅva ~(H(>a,Y_}֛ _;#d+%X!Fk&#?6Vt-)_GIQؒxoV9&\ju^)(IxW|~TcJhN8ʟ6'F:'V&f$v":"!:! Z(F jxު+x*lvksl.lz>+-Nkmq kצVy%KeeuշYﺫZa*TS۪[B&oj/ndhk;'.iWZ<궅p-Lr*o,Y<벌Oa MшAA JL6IUNO42d)vhOvl{ [p/vtkMv}uzOwO}S: Ȁ:wr7&e;8rgopY_n\55c& r!.j {|dz{袼;oS˓O.L|Dۗ͐W,=]ԇ|}]՛ٽU~䡿$?;/hciOfkŚ缅Kd[%P tG(AQ0߮.AjPWB(B}:! J.t cX6rXʉ|?;zD/zP:<,`9 |@@ DPB >QD cF=~RH%MDRʆ+dSL5mĹfB;s1OEEc]:eM>h5P:UXe͎ĊukPSujӰg/fZ^}M;WnV<aP?Yd*\YfΝ=,hҥMnj֭]s]l)Ɲ[n޽}\pōV][rv^0sխ_vݯOx?l^zѣo_|ǟ}¤+<(o@RK\@+ɭ0Úڒ=ҊK C Wd--9wԩCQ0 r,LE%nQ;&,),OG,6%p $s/BdD"-lN>LN?OA%LBE4'Cet4RIm;RK/4SM7&JPuJ55UU%BuUW_VYg]V[o W]wŌW_MXagmuXc,XeLvYgwlYiK6V6[]U.T=;\ ]PēH$܊Osu7ߤ;EKw%.JsM^-8 Fb/w51xo쳷{{m7|Vwiz~W׿oH..0\ t iMϲA A,W%t@H*\ȰÇ#JH"3jȱǏ CIɓ(S^Tɲ˗0cʜI͉oɳϟ@)ѣH*]ʴӧPJJի7 @W_;JٳL:+W\n߿]n]W1cKLF 73g[:kӁ1'n8\ƭcFMma9܋w|EGNwȓmHzУKNسk.T-)6Xp/=/v⡅gN߼e#7Gum[|U؞krN8[Yh%:H߈&"qbpcf,Zx}fdԖSb(ZyJ~aYYߐaB_w!Q#MEZNiber`vPejY(y(t6۞vzn gzvJ\g9c4ک&"?*$Y*f託zw몥2 Lgulv!|fv;sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/docs/pictures/SIP_outgoing_call.vsd000066400000000000000000001050001223300710500264130ustar00rootroot00000000000000ࡱ> B C !"#$%&'()*+,-./0123456789:;<=>?@ARoot EntryF@ԂOB@VisioDocumentG,SummaryInformation(MDocumentSummaryInformation8Visio (TM) Drawing G,\ *VRd !fffMMM333$ $ U8@ TD Arial@NMonotype Sorts@m Wingd NtSymbol5T?? Y@-1U J:DT1EW-hPT8*  .U_b a酸0zGz?@3CfRbU|||%U P } |KpG/Y&4Y$? v AfY&,,' /Dq&z&} | |y  }{})} ?2  | | ||||*|||E-?k4'-'CECE,'*CECECE-?H>?:`}'CEUCECECECEUCECE- O4F2AJY;; AnVnVAbGTfY R_R__ `#f:/lb6p`fW /l /l  Y?5?(\ #!+ | tFf-|J-|-|-wG QUo "OM`EtoA _3=OOOaOsO@O??O?7ܻuR? sU/-O%7I[mRf J+ K5   . ||i| d' 0/UKiR?d?v4Gzt2#&Us s s s) -0jӯY/ƛ!3)󿵶1D///Q+p)?HdYc4AkǿٿYfU|%1I߀O]-(fp ɻ %-=Y[:!#:4)A/q//YkϹ/p?2 Sπ'9}Fɇ7%õ8@\n1$u  (:L^p)BH>ZՔU \ n4!'4#U2q ?/%&k/%&`,`,`',ѓ4?|QԞQyٓA G $z Z$bp6q /#3=/Uq@T0'vr@1N!T0;UOauADV=煤{2r H+"P)Ҳ$2@1@1B,$1//cAm/ߙ߫BVVj /Q?c?u4D?U0O贁 NkRC6$SfMea5t(O"?2RO}q19!S _2_D_"3Htr+*a__//5o2DV õoa`oo1 I+< g4`\\esprn002\HER1F5B1S odWX+'?LetterO_b PRIV0|'r\KhC]>w!tuy //-/?/Q/c/u////////??)?;?M1E%winspool\\esprn002\HER1F5B1IP_172.21?.36.10UFDfP h-RTUUUA@ ?I?a 3h AeqYk Hu_ Q? #,BDrag between shapes to indicate a flow offormation or control.mb?sߛ⿻xw?t? 8HD    3h <>T$  ;MBRAU@?N ?AP6 Ju `u buU  -J ">ۀJuM` Zue"JD4WAQ @%UI>J[@hK'F"U/g%'_-/g JQ#5 L"V &6 霑c ?@IW0?@q`0U>U5Q?!9[a2f`rd}b0@3&/0`A.=@2M @J2uF.3B B$fH2&M+3Q(-DT! @6[Dн8P$?J 3tNsWB Ld!%6 MB##0O贁Nk?<$2%@@PR%|#xQ}T5 B`7Copyright 1999 Visio Corporation. All Rs reserved.J`P_SCPchm!#22776G#2r5ofP"JSfunq&^(E9 Yr[xQ4 0UChange Arrow?head..PVcthe ae siz`n`tyle for`is connectorP1`Bb)WlJhUd>5 yG|(AJ*C<4bZw"M (3,rx srA iVohot'd1dxB3d+=-C2U낥@6f 32`_D/@>W4C)rp -3TqC@@JQ\^E? v!3?|@ 2Pa@0pqB;uK`u`WE @ǗHXC1 aVHl'-d! !Oya HE_9bFT w~# . B  ]Ma ]@U+Lk]/aT fPUl4,"H$ @Y,b'@ D QA-  W7U2@ ]7ERH<( U2E 7 R(n S @@? =RD\KOi{ UP?V]U$5@*P8FDTey  ahm qTP^UI"H$ @IY,b'@? ?I*M_q2?p^qu2`"ua )e*t\F!`F! aU U Q !!H!$'$a'$!'!(!'!(!'!(!'!('$!'!(!'!(!'!(!'!(!'!(!'!(!'!('('(!'!(!'!(!'!('(!'!(F!#CP!!!a!D!!!!D!!!!!D!!!!!!D!!!!!!!!eEo&o8oJo\ono#5i!|am E5 `@*Ӏ%8tJ~? u/Pq%{v'/Rrl!0qU QUm/' /`r-r.-څ! "{*2G]#Mt̏E5 W/b528H!r u!NUA/ Sofia stack"y%ooooo{,-AuAu ʧP-DTw!f-qu `u `bu `u @"q @F!fC TjP}xr*@vض@$swxiϸʝ*EWuat-E, U *bɨә!"aT5C!"b5jb!,oU&_8{EɀAu#@@@AY?Jfz&?7 fT@I_?@qQ #a!mun`J@B8F!2yp(?/Q/c/u/////Z180 R %;/]q?2?D?V? h?z??EL?? "cŅ$@QoOON٨COO]qO ___}zu_Ι]q oo1oCoUogoyoo-ooooo,nua_r_invitedraҿ5Oa-  7R/AkߛRMŸlR,>Pb./ί2 Ok 9QZl~ƿؿp+=#5shzʏ܏$'ߛVߔߦ߸t$6HZl~( 7q!/` "99*担=7y=0 !2q! .G?@B>m+6>_`q!4S_qT%OYq! 2DVhzA> /"%)F:$,hC+R/ack()E!u/QE!/o/*0Z?d s?_3qbM3p?,>8p~O1OE!SOeOE!_/_A_S_e____7~____oo*oeO0p܇Bl U$B'/ \SN) VW HBY1U B=v`2 (V?\ D*GD1 5 C=5 ՜.+,D՜.+,@HP\h t   PagesMastersPage-1Directed line 18_VPID_PREVIEWS@_VPID_ALTERNATENAMES?_PID_LINKBASE A Oh+'0`MHPdp| rinnerahSIP outgoing callGLY|WRSt EMFL3 l@@VISIODrawing% %   &%   '% V0Y999YY% ( % (   Rp Arial>,Uw@*ww>|H>k>|H|HUw%wx|Hxu>`h>,Uw(%w\x>|H>|Hh>\#` xdv%   Td`wAAsLTNUA/   Ty,AA LdSofia stack     % &%  W$% ( % Rp  Arialt,Uw@*w<w|H>|H|H,Uw%wx|Hx s>>tUw(%w\x|H|H>#` @xdv% %  %  % &%  W$% ( %  '% % V,% % (   '% % V08888% % (   Rp Arial>,Uw@*ww>|H>XW|9W|>@|H|HUw%wx|Hx p>`y>,Uw(%w\x>|H>|Hh>\#` xdv%   T: AA:  Ldnua_handle() % &%  W$UUUU% ( %  '% % V,RYRUYR% % (   '% % V05<O5OO<5<5O% % (   Rp Arial>,Uw@*ww>|H>XW|9W|>@|H|HUw%wx|Hx p>`>,Uw(%w\x>|H>|H>\#` xdv%   T7=LAA7J Ldnua_invite() % &%   '% V0U   UU% ( % (  &%   '% V0999% ( % (  Rp Arial>t,Uw@*w<wk>|Hk>>|H|H,Uw%wx|Hxu>tUw(%w\xk>|Hk>|Hh>#` @xdv% %  %   T0AA Ldsetup media     % &%  W$ ? ?% ( %  '% % V,>E>E>>% % (   '% % V0~~~~% % (  Rp Arial>t,Uw@*w<w>|H>>|H|H,Uw%wx|Hx p>h>tUw(%w\x>|H>|H>#` @xdv% %  %   TAA LdINVITE / SDP    % &%  W$2E2E22% ( %  '% % V, .66 2.6% % (   '% % V0,,,,% % (   Rp Arial>,Uw@*ww>|H>XW|9W|>@|H|HUw%wx|Hx p>`>,Uw(%w\x>|H>|H>\#` xdv%   T)AA' L`100 Trying  % &%  W$**% ( %  '% % V, | |% % (  (  '% % V0seysyyesesy% % (   Rp Arial>,Uw@*ww>|H>XW|9W|>@|H|HUw%wx|Hx p>`>,Uw(%w\x>|H>|H>\#` xdv%   TugvAAut Ld180 Ringing  % ( &%  W$% ( %  '% % V,% % (   '% % V04w4w4w4% % (   Rp Arial>,Uw@*ww>|H>XW|9W|>@|H|HUw%wx|Hx p>`>,Uw(%w\x>|H>|H>\#` xdv%   T6xAA6 Ldnua_r_invite % ( &%  W$EE% ( %  '% % V,  % % (   '% % V0||||% % (   Rp Arial>,Uw@*ww>|H>XW|9W|>@|H|HUw%wx|Hx p>`>,Uw(%w\x>|H>|H>\#` xdv%   T~AA~ Ld200 Ok / SDP   % ( &%  W$% ( %  '% % V,% % (   '% % V04444% % (   Rp Arial>,Uw@*ww>|H>XW|9W|>@|H|HUw%wx|Hx p>`>,Uw(%w\x>|H>|H>\#` xdv%   T6AA6 Ldnua_r_invite % &%  W$% ( %  '% % V,% % (  (  '% % V0:~:~~::% % (   Rp Arial>,Uw@*ww>|H>XW|9W|>@|H|HUw%wx|Hx p>`>,Uw(%w\x>|H>|H>\#` xdv%   T<{AA< L`nua_ack() % &%  W$ ? ?% ( %  '% % V,> E> E>> % % (  (  '% % V0    % % (   Rp Arial>,Uw@*ww>|H>XW|9W|>@|H|HUw%wx|Hx p>`j>,Uw(%w\x>|H>|Hj>\#` xdv%   T`AALTACK  % &%   ' % V0.9]]9]9..]% ( % (  ( Rp Arial>t,Uw@*w<wk>|Hk>>|H|H,Uw%wx|Hxu>j>tUw(%w\xk>|Hk>|H>#` @xdv% Rp  Arial>t,Uw@*w<w>|H>6Uw*wk>|H|H,Uw%wx|Hxu>k>tUw(%w\x>|H>|H>#` @xdv% ( %  %   T|- DAA@L\activate     TlF]AAYLXmedia   % &%  W$% ( %  '% % V,% % (  (  '% % V0:s:s:s:% % (  Rp Arial>t,Uw@*w<w>|H>k>|H|H,Uw%wx|Hx p>>tUw(%w\x>|H>|Hh>#` @xdv% %  %   T<uAA< Ldnua_i_active % % (  %   T`8N,AA8(LT(1)  % %  Rp Arial>,Uw@*wwk>|Hk>>|H|HUw%wx|Hxu>`j>,Uw(%w\xk>|Hk>|Hj>\#` xdv%   T`rAALT(1)  % ( %  Rp Arial>,Uw@*ww>|H>k>|H|HUw%wx|Hxu>`>,Uw(%w\x>|H>|H>\#` xdv%   T`8rNAA8LT(1)  % ( % (  Rp Arial>,Uw@*wwk>|Hk>>|H|HUw%wx|Hxu>`j>,Uw(%w\xk>|Hk>|Hj>\#` xdv%   T`AALT(2)  % %  Rp Arial>,Uw@*ww>|H>k>|H|HUw%wx|Hxu>`>,Uw(%w\x>|H>|H>\#` xdv%   T+AA Ld(1) optional     TxAA2L(2) optional - needed only if no NUTAG_AUTOACK set             % &%  W$aa% ( %  '% % V, ^ec e ^c% % (  (  Rp Arial>,Uw@*wwy>|Hy>>|H|HUw%wx|Hx]z>`,Uw(%w\xy>|Hy>|H>\#` xdv%  % %  Rp Arial>,Uw@*wwk>|Hk>y>|H|HUw%wx|Hxu>`>,Uw(%w\xk>|Hk>|H>\#` xdv%   Tw|AAwLlifetime of INVITE transaction        % ( VisioInformation"sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/docs/pictures/SIP_outgoing_operation_with_auth.eps000066400000000000000000011272111223300710500315600ustar00rootroot00000000000000i%!PS-Adobe-3.0 EPSF-3.0 %%Creator: ImageMark Software Labs %%For: () () %%Title: V:\work\rinnerah\sofia\SIP outgoing operation with auth.eps %%CreationDate: () () %%BoundingBox: 0 0 372 269 %%DocumentProcessColors: Black %%ColorUsage:Color %%DocumentFonts: Helvetica %%+Helvetica-Bold %%+Helvetica-Oblique %%+Helvetica-BoldOblique %%+Times-Roman %%+Times-Bold %%+Times-Italic %%+Times-BoldItalic %%+Courier %%+Courier-Bold %%+Courier-Oblique %%+Courier-BoldOblique %%+Symbol %%DocumentSuppliedResources: procset Adobe_level2_AI5 1.2 0 %%+ procset Adobe_screens_AI5 1.0 0 %%+ procset Adobe_typography_AI5 1.0 0 %%+ procset Adobe_ColorImage_AI6 1.1 0 %%+ procset Adobe_blend_AI5 1.0 0 %%+ procset Adobe_pattern_AI5 1.0 0 %%+ procset Adobe_Illustrator_AI5 1.0 0 %AI5_FileFormat 3.0 %AI3_ColorUsage: Color %AI3_TemplateBox: 0 0 372 269 %AI3_TileBox: 0 0 372 269 %AI3_DocumentPreview: None %%Template: %%PageOrigin:0.0000 0.0000 %AI7_GridSettings: 72 8 72 8 1 0 0.8 0.8 0.8 0.9 0.9 0.9 %%EndComments %%BeginProlog %%BeginResource: procset Adobe_level2_AI5 1.2 0 %%Title: (Adobe Illustrator (R) Version 5.0 Level 2 Emulation) %%Version: 1.2 0 %%CreationDate: (04/10/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /Adobe_level2_AI5 25 dict dup begin put /packedarray where not { userdict begin /packedarray { array astore readonly } bind def /setpacking /pop load def /currentpacking false def end 0 } if pop userdict /defaultpacking currentpacking put true setpacking /initialize { Adobe_level2_AI5 begin } bind def /terminate { currentdict Adobe_level2_AI5 eq { end } if } bind def mark /setcustomcolor where not { /findcmykcustomcolor { 0 6 packedarray } bind def /findrgbcustomcolor { 1 5 packedarray } bind def /setcustomcolor { exch aload pop 0 eq { pop 4 { 4 index mul 4 1 roll } repeat 5 -1 roll pop setcmykcolor } { pop 3 { 1 exch sub 3 index mul 1 exch sub 3 1 roll } repeat 4 -1 roll pop setrgbcolor } ifelse } def } if /gt38? mark {version cvr cvx exec} stopped {cleartomark true} {38 gt exch pop} ifelse def userdict /deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt put userdict /level2? systemdict /languagelevel known dup { pop systemdict /languagelevel get 2 ge } if put /level2ScreenFreq { begin 60 HalftoneType 1 eq { pop Frequency } if HalftoneType 2 eq { pop GrayFrequency } if HalftoneType 5 eq { pop Default level2ScreenFreq } if end } bind def userdict /currentScreenFreq level2? {currenthalftone level2ScreenFreq} {currentscreen pop pop} ifelse put level2? not { /setcmykcolor where not { /setcmykcolor { exch .11 mul add exch .59 mul add exch .3 mul add 1 exch sub setgray } def } if /currentcmykcolor where not { /currentcmykcolor { 0 0 0 1 currentgray sub } def } if /setoverprint where not { /setoverprint /pop load def } if /selectfont where not { /selectfont { exch findfont exch dup type /arraytype eq { makefont } { scalefont } ifelse setfont } bind def } if /cshow where not { /cshow { [ 0 0 5 -1 roll aload pop ] cvx bind forall } bind def } if } if cleartomark /anyColor? { add add add 0 ne } bind def /testColor { gsave setcmykcolor currentcmykcolor grestore } bind def /testCMYKColorThrough { testColor anyColor? } bind def userdict /composite? level2? { gsave 1 1 1 1 setcmykcolor currentcmykcolor grestore add add add 4 eq } { 1 0 0 0 testCMYKColorThrough 0 1 0 0 testCMYKColorThrough 0 0 1 0 testCMYKColorThrough 0 0 0 1 testCMYKColorThrough and and and } ifelse put composite? not { userdict begin gsave /cyan? 1 0 0 0 testCMYKColorThrough def /magenta? 0 1 0 0 testCMYKColorThrough def /yellow? 0 0 1 0 testCMYKColorThrough def /black? 0 0 0 1 testCMYKColorThrough def grestore /isCMYKSep? cyan? magenta? yellow? black? or or or def /customColor? isCMYKSep? not def end } if end defaultpacking setpacking %%EndResource %%BeginResource: procset Adobe_typography_AI5 1.0 1 %%Title: (Typography Operators) %%Version: 1.0 %%CreationDate:(03/26/93) () %%Copyright: ((C) 1987-1993 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_typography_AI5 54 dict dup begin put /initialize { begin begin Adobe_typography_AI5 begin Adobe_typography_AI5 { dup xcheck { bind } if pop pop } forall end end end Adobe_typography_AI5 begin } def /terminate { currentdict Adobe_typography_AI5 eq { end } if } def /modifyEncoding { /_tempEncode exch ddef /_pntr 0 ddef { counttomark -1 roll dup type dup /marktype eq { pop pop exit } { /nametype eq { _tempEncode /_pntr dup load dup 3 1 roll 1 add ddef 3 -1 roll put } { /_pntr exch ddef } ifelse } ifelse } loop _tempEncode } def /TE { StandardEncoding 256 array copy modifyEncoding /_nativeEncoding exch def } def % /TZ { dup type /arraytype eq { /_wv exch def } { /_wv 0 def } ifelse /_useNativeEncoding exch def pop pop findfont _wv type /arraytype eq { _wv makeblendedfont } if dup length 2 add dict begin mark exch { 1 index /FID ne { def } if cleartomark mark } forall pop /FontName exch def counttomark 0 eq { 1 _useNativeEncoding eq { /Encoding _nativeEncoding def } if cleartomark } { /Encoding load 256 array copy modifyEncoding /Encoding exch def } ifelse FontName currentdict end definefont pop } def /tr { _ax _ay 3 2 roll } def /trj { _cx _cy _sp _ax _ay 6 5 roll } def /a0 { /Tx { dup currentpoint 3 2 roll tr _psf newpath moveto tr _ctm _pss } ddef /Tj { dup currentpoint 3 2 roll trj _pjsf newpath moveto trj _ctm _pjss } ddef } def /a1 { /Tx { dup currentpoint 4 2 roll gsave dup currentpoint 3 2 roll tr _psf newpath moveto tr _ctm _pss grestore 3 1 roll moveto tr sp } ddef /Tj { dup currentpoint 4 2 roll gsave dup currentpoint 3 2 roll trj _pjsf newpath moveto trj _ctm _pjss grestore 3 1 roll moveto tr jsp } ddef } def /e0 { /Tx { tr _psf } ddef /Tj { trj _pjsf } ddef } def /e1 { /Tx { dup currentpoint 4 2 roll gsave tr _psf grestore 3 1 roll moveto tr sp } ddef /Tj { dup currentpoint 4 2 roll gsave trj _pjsf grestore 3 1 roll moveto tr jsp } ddef } def /i0 { /Tx { tr sp } ddef /Tj { trj jsp } ddef } def /i1 { W N } def /o0 { /Tx { tr sw rmoveto } ddef /Tj { trj swj rmoveto } ddef } def /r0 { /Tx { tr _ctm _pss } ddef /Tj { trj _ctm _pjss } ddef } def /r1 { /Tx { dup currentpoint 4 2 roll currentpoint gsave newpath moveto tr _ctm _pss grestore 3 1 roll moveto tr sp } ddef /Tj { dup currentpoint 4 2 roll currentpoint gsave newpath moveto trj _ctm _pjss grestore 3 1 roll moveto tr jsp } ddef } def /To { pop _ctm currentmatrix pop } def /TO { iTe _ctm setmatrix newpath } def /Tp { pop _tm astore pop _ctm setmatrix _tDict begin /W { } def /h { } def } def /TP { end iTm 0 0 moveto } def /Tr { _render 3 le { currentpoint newpath moveto } if dup 8 eq { pop 0 } { dup 9 eq { pop 1 } if } ifelse dup /_render exch ddef _renderStart exch get load exec } def /iTm { _ctm setmatrix _tm concat 0 _rise translate _hs 1 scale } def /Tm { _tm astore pop iTm 0 0 moveto } def /Td { _mtx translate _tm _tm concatmatrix pop iTm 0 0 moveto } def /iTe { _render -1 eq { } { _renderEnd _render get dup null ne { load exec } { pop } ifelse } ifelse /_render -1 ddef } def /Ta { pop } def /Tf { dup 1000 div /_fScl exch ddef % selectfont } def /Tl { pop 0 exch _leading astore pop } def /Tt { pop } def /TW { 3 npop } def /Tw { /_cx exch ddef } def /TC { 3 npop } def /Tc { /_ax exch ddef } def /Ts { /_rise exch ddef currentpoint iTm moveto } def /Ti { 3 npop } def /Tz { 100 div /_hs exch ddef iTm } def /TA { pop } def /Tq { pop } def /Th { pop pop pop pop pop } def /TX { pop } def /Tk { exch pop _fScl mul neg 0 rmoveto } def /TK { 2 npop } def /T* { _leading aload pop neg Td } def /T*- { _leading aload pop Td } def /T- { _hyphen Tx } def /T+ { } def /TR { _ctm currentmatrix pop _tm astore pop iTm 0 0 moveto } def /TS { currentfont 3 1 roll /_Symbol_ _fScl 1000 mul selectfont 0 eq { Tx } { Tj } ifelse setfont } def /Xb { pop pop } def /Tb /Xb load def /Xe { pop pop pop pop } def /Te /Xe load def /XB { } def /TB /XB load def currentdict readonly pop end setpacking %%EndResource %%BeginResource: procset Adobe_screens_AI5 1.2 0 %%Title: (Adobe Illustrator (R) Version 5.0 Custom Halftone Screens ProcSet) %%Version: 1.2 0 %%CreationDate: (03/24/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking systemdict begin userdict /Adobe_screens_AI5 15 dict dup begin put /initialize { Adobe_screens_AI5 begin /screenid deviceDPI 600 gt composite? not or { -1 } { deviceDPI currentScreenFreq dup dup 60 ge exch 150 le and deviceDPI 300 le and { pop 60 } if div 1.41421 div 0.5 add cvi } ifelse def 2 screenid eq { /customsize 16 def /customdata /customdata2 def setcustomscreen } if 3 screenid eq { /customsize 24 def /customdata /customdata3 def setcustomscreen } if 4 screenid eq { /customsize 16 def /customdata /customdata4 def setcustomscreen } if 5 screenid eq { /customsize 20 def /customdata /customdata5 def setcustomscreen } if 6 screenid eq { /customsize 24 def /customdata /customdata6 def setcustomscreen } if 7 screenid eq { /customsize 28 def /customdata /customdata7 def setcustomscreen } if 8 screenid eq { /customsize 16 def /customdata /customdata8 def setcustomscreen } if } def /terminate { currentdict Adobe_screens_AI5 eq { end } if } def /setcustomscreen { deviceDPI customsize div 0 { 1 add 2 div customsize mul cvi exch 1 add 2 div customsize mul cvi exch customsize mul add customdata load exch get 256 div } setscreen } def /customdata2 28 28 mul string def currentfile customdata2 readhexstring 4180E8694988E2634382EA6B4B8AE061A01939C8A81737C2A21B3BCAAA1636C0 F8795998F6775796FA7B5B9AF57656952ED8B80727D6B60F2FDABA0626D5B50E 4E8DE6674786EE6F4F8EE5664685ED6EAD1434C6A61F3FCEAE1232C5A51E3ECD F3745493FE7F5F9EF1725291FD7E5E9D24D3B30C2CDEBE0222D1B10A2ADDBD04 4483EB6C4C8BE1624281E96A4A89E364A31C3CCBAB1535C1A11A3AC9A91838C3 FB7C5C9BF4755594F97A5A99F778589730DBBB0525D4B40D2DD9B90828D7B710 508FE4654584EC6D4D8CE7684887EF70AF1131C4A41D3DCCAC1333C7A72040CF F0715190FC7D5D9CF2735392FF80609F21D0B00929DCBC0323D2B20B2BDFBF01 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata3 28 28 mul string def currentfile customdata3 readhexstring 011DC7F5E73D0421CBF3E43A021EC8F6E83E0522CCF2E43A2B648BC4A0762F68 8AC39E732C658CC5A177306989C29D72D5B6521A6192D9B55219608FD6B6531B 6193DAB451185F8FFCEE440C28D2FCED430B27D1FDEF450C29D3FBEC420A26D0 BEA77D366F83BCA77C356E87BFA87E377082BBA67B346D86145B99E0AE4A1259 98DFB14E155C9AE1AD4A115897DEB04D0623CDF4E63C0420CAF8EA400723CDF4 E53B031FC9F7E93F316988C19F752E678EC6A378326A88C09F742D668DC6A278 DBB350175E91D8B8551C6395DCB24F165D90D7B7541C6294FAEC420925CFFFF1 470E2BD5F9EB410824CEFEF0460D2AD4BAA57A336C85BEAA80397180B9A47933 6B84BDA97F387181105797DDAF4C145A9CE3AB480F5696DDAE4B13599BE2AC49 021EC8F6E83E0522CCF2E43A011DC7F5E73D0421CBF3E43A2C658CC5A1773069 89C29D722B648BC4A0762F688AC39E73D6B6531B6193DAB451185F8FD5B6521A 6192D9B55219608FFDEF450C29D3FBEC420A26D0FCEE440C28D2FCED430B27D1 BFA87E377082BBA67B346D86BEA77D366F83BCA77C356E87155C9AE1AD4A1158 97DEB04D145B99E0AE4A125998DFB14E0723CDF4E53B031FC9F7E93F0623CDF4 E63C0420CAF8EA40326A88C09F742D668DC6A278316988C19F752E678EC6A378 DCB24F165D90D7B7541C6294DBB350175E91D8B8551C6395F9EB410824CEFEF0 460D2AD4FAEC420925CFFFF1470E2BD5B9A479336B84BDA97F387181BAA57A33 6C85BEAA803971800F5696DDAE4B13599BE2AC49105797DDAF4C145A9CE3AB48 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata4 28 28 mul string def currentfile customdata4 readhexstring 1139B8E0FAD2531B133BBAE2F8D05119417180A6AE9A7B4B437382A5AD987949 C08867272F6F92CAC28A66262E6E90C8E8DE5F070F37B6F2EADD5E060E36B5F0 FED6571F173FBEE6FDD5561E163EBDE5AB9E7F4F477786A1A99D7E4E467685A3 2C6C96CEC68E62222A6A95CDC58D64240C34B3F6EED95A020A32B1F5EDDB5C04 143CBBE3F9D1521A123AB9E1FBD3541C447483A4AC997A4A427281A7AF9B7C4C C38B65252D6D91C9C1896828307093CBEBDC5D050D35B4F1E9DF60081038B7F3 FCD4551D153DBCE4FFD758201840BFE7A89C7D4D457584A2AA9F8050487887A0 296994CCC48C63232B6B97CFC78F61210931B0F4ECDA5B030B33B2F7EFD85901 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata5 28 28 mul string def currentfile customdata5 readhexstring 010B34C3EBFCF7CE3F16020C35C4EDFBF6CD3E15102552A4D6EADDB5632B1126 54A5D5EADCB3622A3958768499C19E8C7C5E3A59778498C19D8B7B5DC8A99370 47334C7587AFC9AA936F46324B7485AEF1E5BC6B1E0A2351A3D8F2E4BC6A1E09 2351A2D7FFF9D14219050F38C6EFFEF9D04118040E37C6EFE8E0B7662D142856 A8D3E7DFB7652D132856A7D4BF9C8E7F603D5B7A8195BE9A8E7E603C5B798297 314A7389B2CCAD906D442F497289B1CBAC926E4508214FA1DBF4E2B9671B0720 4EA0DAF4E3BA691C030D36C5EDFBF6CD3F16010C34C3ECFDF8CF4017122654A6 D4E9DDB4622A112553A5D6EBDEB5642C3B59788397C09C8B7C5D3A58778599C2 9E8C7D5FCAAB926E46314B7486AFC8AA947048334D7587B0F2E4BB691D082250 A1D8F1E6BD6B1F0A2452A3D9FDF8CF4118030E36C5EEFFFAD1421A050F38C7F0 E6DFB6642C132755A7D3E8E1B8662E152957A8D2BE9A8D7E5F3B5A798296BF9B 8F80613D5C7B80952F487188B1CAAC916D443049728AB3CCAE906C43061F4D9F DAF3E2BA681C07214FA0DBF5E1B8671A00000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata6 28 28 mul string def currentfile customdata6 readhexstring 081A44B6E0F2FDECC150250C091B45B6E1F3FCEBC04F240C1D336199C7D8DCD3 A56C37221E33619AC8D7DBD2A46B36214864798091AEB1958C7E694C49657A81 90ADB0948B7D684BB99D8475593C405C7888A1BEBA9E8574583B3F5B7888A0BD E4CBAA712E1215326098CFE8E4CCA9712D1114315F97CEE7F5F1C6552B040719 43B5DFFAF6F0C6542A03061842B4DEF9FFEDC352270E0B1C47B8E3F4FEECC251 260D0A1C46B7E2F4DAD5A76E39232035639CCAD5D9D4A66D38231F34629BC9D6 AF938E806A4E4A677C838FABAE928D7F694D4A667B828FAC3E5A778AA3BFBC9F 8772563A3D597689A2BEBB9F8673573A14305E97D1EAE6CDA76F2B0F132F5D96 D0E9E5CDA8702C10051742B3DDFCF8EEC4522801041641B2DDFBF7EFC5532902 091B45B6E1F3FCEBC04F240C081A44B6E0F2FDECC150250C1E33619AC8D7DBD2 A46B36211D336199C7D8DCD3A56C372249657A8190ADB0948B7D684B48647980 91AEB1958C7E694CBA9E8574583B3F5B7888A0BDB99D8475593C405C7888A1BE E4CCA9712D1114315F97CEE7E4CBAA712E1215326098CFE8F6F0C6542A030618 42B4DEF9F5F1C6552B04071943B5DFFAFEECC251260D0A1C46B7E2F4FFEDC352 270E0B1C47B8E3F4D9D4A66D38231F34629BC9D6DAD5A76E39232035639CCAD5 AE928D7F694D4A667B828FACAF938E806A4E4A677C838FAB3D597689A2BEBB9F 8673573A3E5A778AA3BFBC9F8772563A132F5D96D0E9E5CDA8702C1014305E97 D1EAE6CDA76F2B0F041641B2DDFBF7EFC5532902051742B3DDFCF8EEC4522801 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata7 28 28 mul string def currentfile customdata7 readhexstring 01061B44B7E1F5FEFBE6BD4A210C01071B45B8E1F6FDFBE6BC4A200B09132A54 A7D1EAF5EED9B05D331609142B55A8D2EAF4EED9AF5C32161D2D3D6993C1CBE0 CEC59B7140301E2E3D6A93C0CADFCDC49A713F3047576C7B828DA2B6A48F867E 6F5A48576C7C828CA1B6A38F867E6E59BAAA958A78634E4451667A8498ADBAAB 968977624E4350657A8398ADE3D4C99F7539251A273C6892C2D7E4D4C89E7539 241A273B6891C1D6F8F2DDB460371005122A53A7D0ECF9F2DDB360360F051229 53A6D0EBFFFDE8BE4C220D03081D46B9E3F7FFFCE7BD4B210D02071C46B8E2F7 F3F0DBB15E34180B152C56A9D3E8F3EFDAB05D34170A142C55A9D2E9DFCCC69C 7341321F2F3F6B94BFC9DECCC59C7241311F2E3E6A94BFCAB5A38E8780705B49 596D7D808BA0B4A28D877F6F5B48586D7C818BA043506479859AAFBCAC978876 614C424F64798499AEBBAB968977624D19263B6791C3D8E5D6C79D7337231825 3A6690C3D7E5D5C79E74382304112952A5CFEDFAF0DBB25E350E03102851A5CE ECF9F1DCB25F360E01071B45B8E1F6FDFBE6BC4A200B01061B44B7E1F5FEFBE6 BD4A210C09142B55A8D2EAF4EED9AF5C321609132A54A7D1EAF5EED9B05D3316 1E2E3D6A93C0CADFCDC49A713F301D2D3D6993C1CBE0CEC59B71403048576C7C 828CA1B6A38F867E6E5947576C7B828DA2B6A48F867E6F5ABAAB968977624E43 50657A8398ADBAAA958A78634E4451667A8498ADE4D4C89E7539241A273B6891 C1D6E3D4C99F7539251A273C6892C2D7F9F2DDB360360F05122953A6D0EBF8F2 DDB460371005122A53A7D0ECFFFCE7BD4B210D02071C46B8E2F7FFFDE8BE4C22 0D03081D46B9E3F7F3EFDAB05D34170A142C55A9D2E9F3F0DBB15E34180B152C 56A9D3E8DECCC59C7241311F2E3E6A94BFCADFCCC69C7341321F2F3F6B94BFC9 B4A28D877F6F5B48586D7C818BA0B5A38E8780705B49596D7D808BA0424F6479 8499AEBBAB968977624D43506479859AAFBCAC978876614C18253A6690C3D7E5 D5C79E74382319263B6791C3D8E5D6C79D73372303102851A5CEECF9F1DCB25F 360E04112952A5CFEDFAF0DBB25E350E pop pop /customdata8 28 28 mul string def currentfile customdata8 readhexstring 050F2747B6D6EEF8FEF4DCBC4D2D1507111D375F9EC6E0E9EBE6CCA4653D1F13 2939556F8EA8C1D1D3C3AE9475573B2B4961717D808999B1B39B8B867F73634B B8A090827A6A5A42445C6C7C8492A2BAD8C8AA97785232222434546E8DACCADA F0E2CFA768401A0A0C1C365E9DC5E4F2FAF7DFBF50301802040E2646B5D5EDFC FFF5DDBD4E2E160806102848B7D7EFF9EAE7CDA5663E2014121E38609FC7E1E8 D2C2AF9576583C2C2A3A56708FA9C0D0B29A8A878074644C4A62727E818898B0 435B6B7B8593A3BBB9A19183796959412333536D8CADCBDBD9C9AB9677513121 0B1B355D9CC4E5F3F1E3CEA6673F1909030D2545B4D4ECFDFBF6DEBE4F2F1701 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop end end defaultpacking setpacking %%EndResource %%BeginResource: procset AGM_Gradient_Sep 1.0 0 %%Title: (AGM Gradient Procset) %%Version: 1.0 0 %%CreationDate: (4/26/96) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /AGM_Gradient_Sep 5 dict dup begin put /AGM_Gradient_Sep_private 100 dict def /initialize{ AGM_Gradient_Sep begin AGM_Gradient_Sep_private begin _compositeJob{ initializeSinglePassSeps }{ initializeMultiPassSeps }ifelse initializeSeps AGM_Gradient_private begin /_fillSD newSpotDict def /_rampSD newSpotDict def /_nCustomColorSD nd end AGM_Gradient_Sep_private { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall AGM_Gradient_Sep { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall end currentdict readonly pop end }def /terminate{ currentdict AGM_Gradient_Sep eq{ end }if }def AGM_Gradient_Sep_private begin /initializeSeps{ _noImage not _level2PS not and{ /_whiteBytes 1 makeByte8 pt /knockOut{ 8 setImageParms _whiteBytes /_image load 5 execImage }def /linealFill{ mySave 8 setImageParms _color{ _nCustomColorSD begin cyan magenta yellow black _spotColor{ spot1 begin /tintImage tintValue 1 exch sub makeByte8 def end spot2 begin /tintImage tintValue 1 exch sub makeByte8 def end }if end 4{ makeByte8 4 1 roll }repeat true 4 _nCustomColorSD ncolorimage }{ _nCustomColorSD/black get 1 exch sub makeByte8 _nCustomColorSD bwImage }ifelse myRestore }def }{ /knockOut{ gsave false setoverprint 1 setgray 0 0 1 1 rectfill grestore }def }ifelse /newSpotDict{ 11 dict dup begin /nSpots 2 def /spot1 7 dict def /spot2 7 dict def end }def /initSpotData { begin /name nd /tintImage nd /tintValue nd /spot_C nd /spot_M nd /spot_Y nd /spot_K nd end }def /initSpotDict{ begin /cyanInk false def /magentaInk false def /yellowInk false def /blackInk false def /cyan nd /magenta nd /yellow nd /black nd spot1 initSpotData spot2 initSpotData end }def /copySpotDict{ /_dst xp begin cyanInk magentaInk yellowInk blackInk cyan magenta yellow black spot1 spot2 end _dst begin /spot1 spot1 maxlength dict def /spot2 spot2 maxlength dict def spot2 copy pop spot1 copy pop /black xd /yellow xd /magenta xd /cyan xd /blackInk xd /yellowInk xd /magentaInk xd /cyanInk xd end }def /setCustomColor { 1 index /Black eq{ 6 1 roll 5 npop 1 exch sub setgray }{ 6 1 roll _ccAry1 astore exch dup null eq{ pop 0 }if setcustomcolor }ifelse }def /setCStop{ /_colorStyle exch pt _colorStyle 0 eq{ 0 0 0 4 -1 roll 1 exch sub _spotColor{ /_colorStyle 3 pt /Black 1 index 1 exch sub }if }if _colorStyle 2 eq{ 3 npop }if _rampSD _fillSD copySpotDict _colorStyle 4 eq{ pop 9 2 roll 3 npop 6 -2 roll } if _colorStyle 3 eq _colorStyle 4 eq or{ _fillSD begin exch dup spot1/name get eq{ spot1 spot2 }{ spot2 spot1 }ifelse begin begin /name xd 1 exch sub /tintValue xd 4{ tintValue mul 4 1 roll }repeat _spotColor not{ /tintValue null def }if end /tintValue 0 def end end }if _fillSD nsetcustomcolor }def /renderCMYK{ spot1/name get null eq spot2/name get null eq and dup not{ pop spot1 spotConverted }if dup not{ pop spot2 spotConverted }if }def /fill_ /fill load def /fillOvp{ currentoverprint{ _inRipSep{ currentcolorspace 0 get dup /DeviceGray eq 1 index /DeviceCMYK eq or{ pop currentcmykcolor add add add 0 eq{ newpath }if }{ /Separation eq{ currentcolor 0 eq{ newpath }if }if }ifelse }{ currentgray 1 eq{ newpath }if }ifelse }if fill_ }def /fill{ _nCustomColorSD begin renderCMYK { fillOvp }{ spot1 begin gsave name null ne{ spot_C spot_M spot_Y spot_K name tintValue setCustomColor }{ 1 setgray }ifelse fillOvp grestore end spot2 begin name null ne{ gsave true setoverprint spot_C spot_M spot_Y spot_K name tintValue setCustomColor fillOvp grestore }if end newpath }ifelse end }def /expandSpot{ _spotColor{ /_len xp _rampSD begin spot1 begin tintImage null ne{ tintImage _len expandOne /tintImage xd }if end spot2 begin tintImage null ne{ tintImage _len expandOne /tintImage xd }if end end }{ pop }ifelse }def /rampImage{ _rampSD begin _color{ /cyanInk _cyanData 0 ne def /magentaInk _magentaData 0 ne def /yellowInk _yellowData 0 ne def /blackInk _blackData 0 ne def _nSamples setImageParms _nSamples expandSpot _cyanData _magentaData _yellowData _blackData _nSamples 4 expandColor true 4 _rampSD ncolorimage }{ /cyanInk false def /magentaInk false def /yellowInk false def /blackInk true def _nSamples setImageParms _blackData _rampSD bwImage }ifelse end }def /nsetcustomcolor where{ pop }{ /nsetcustomcolor { /_nCustomColorSD xp _nCustomColorSD begin 4 copy /black xd /yellow xd /magenta xd /cyan xd 4 copy 0 ne /blackInk xd 0 ne /yellowInk xd 0 ne /magentaInk xd 0 ne /cyanInk xd end setcmykcolor }def }ifelse /nsetcustomcolorend where{ pop }{ /nsetcustomcolorend { /_nCustomColorSD null pt }def }ifelse }def /initializeSinglePassSeps{ /_decodeNorm [0 1] pt /_decodeInvert [1 0] pt /spotConverted { begin name null eq{ false }{ tintValue null eq tintImage null eq and{ true }{ false currentpagedevice/SeparationOrder get{name eq or}forall not }ifelse }ifelse end }def /dictImage { 20 dict dup begin /Dict xd /Decode xd /DataSource xd /ImageMatrix xd /BitsPerComponent xd /Height xd /Width xd /ImageType 1 def Dict end /_image load 1 execImage }def /bwImage{ begin gsave currentoverprint{ blackInk{ [/Separation /Black /DeviceGray{}] setcolorspace _decodeInvert dictImage }{ 5 npop }ifelse }{ /DeviceGray setcolorspace _decodeNorm dictImage }ifelse grestore end }def /ncolorimage where{ pop }{ /ncolorimage{ begin renderCMYK { cyanInk magentaInk and yellowInk and blackInk and not currentoverprint and { pop pop gsave cyanInk{ 8 copy [/Separation /Cyan /DeviceGray{}] setcolorspace 3 npop _decodeNorm dictImage }if magentaInk{ 8 copy [/Separation /Magenta /DeviceGray{}] setcolorspace 4 -1 roll 3 npop _decodeNorm dictImage }if yellowInk{ 8 copy [/Separation /Yellow /DeviceGray{}] setcolorspace 4 -2 roll 3 npop _decodeNorm dictImage }if blackInk{ 4 -3 roll [/Separation /Black /DeviceGray{}] setcolorspace 3 npop _decodeNorm dictImage }{ 8 npop }ifelse grestore }{ /_colorimage load 10 execImage }ifelse }{ 6 npop gsave spot1 begin name null ne tintImage null ne and{ [/Separation name /DeviceGray{}] setcolorspace 4 copy tintImage name /Black eq{ _decodeNorm }{ _decodeInvert }ifelse dictImage }{ 1 setgray fill }ifelse end spot2 begin true setoverprint name null ne tintImage null ne and{ [/Separation name /DeviceGray{}] setcolorspace tintImage name /Black eq{ _decodeNorm }{ _decodeInvert }ifelse dictImage }{ 4 npop 1 setgray fill }ifelse end grestore }ifelse end }def }ifelse }def /initializeMultiPassSeps{ /_isCMYKSep _cyanPlate _magentaPlate or _yellowPlate or _blackPlate or pt /invertXfer{ [ { 1 exch sub }/exec load systemdict /currenttransfer get exec /exec load ] cvx systemdict /settransfer get exec }def /ccThrough{ gsave 1 setCustomColor currentcmykcolor grestore add add add 0 ne }def /spotConverted { begin _isCMYKSep not{ false }{ name null eq{ false }{ tintValue null eq tintImage null eq and{ true }{ spot_C spot_M spot_Y spot_K name ccThrough }ifelse }ifelse }ifelse end }def /spotChannel { _isCMYKSep{ pop false }{ begin name null eq{ false }{ spot_C spot_M spot_Y spot_K name ccThrough }ifelse end }ifelse }def /getChannelData { _isCMYKSep dup{ pop renderCMYK }if { _blackPlate{ 4 1 roll 3 npop blackInk }{ _yellowPlate{ 4 2 roll 3 npop yellowInk }{ _magentaPlate{ 4 3 roll 3 npop magentaInk }{ 3 npop cyanInk }ifelse }ifelse }ifelse { true /nonZeroData }{ true /zeroData }ifelse }{ 4 npop spot1/name get null ne spot1 spotChannel and{ spot1/tintImage get dup null ne{ false /nonZeroData }{ pop false /noData }ifelse }{ spot2/name get null ne spot2 spotChannel and{ spot2/tintImage get dup null ne{ false /nonZeroData }{ pop false /noData }ifelse }{ false /noData }ifelse }ifelse }ifelse }def /renderChannelData { /_tmp xp _tmp /nonZeroData ne currentoverprint and{ pop _tmp /zeroData eq{pop}if 4 npop }{ _tmp /nonZeroData eq{ { invertXfer }if systemdict/image get 5 execImage }{ pop _tmp /zeroData eq{pop}if 4 npop knockOut }ifelse }ifelse }def /bwImage{ begin gsave dup dup dup getChannelData exch pop false exch renderChannelData grestore end }def /ncolorimage{ begin pop pop gsave spot2/name get null ne spot2 spotChannel and{ true setoverprint }if getChannelData renderChannelData grestore end }def }def end end defaultpacking setpacking %%EndResource %%BeginResource: procset AGM_Gradient 1.0 0 %%Title: (AGM Gradient Procset) %%Version: 1.0 0 %%CreationDate: (4/26/96) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /AGM_Gradient 20 dict dup begin put /AGM_Gradient_private 200 dict def /initialize { AGM_Gradient begin AGM_Gradient_private begin initializeVars /bd systemdict/mark get def /ed _level2PS { (>>) }{ (counttomark 2 idiv dup dict begin {def} repeat pop currentdict end) } ifelse cvx def _level2PS{ initializeLev2 }{ initializeLev1 }ifelse queryDevice initializeShading initializeOps _producingSeps{ AGM_Gradient_Sep/initialize get exec }{ initializeComposite }ifelse _illustrator{ /f{}def /F{}def /s{}def /S{}def /b{}def /B{}def }if /image where{ /image get /_image xd }if /colorimage where{ /colorimage get /_colorimage xd }if /rectfill where dup{ exch pop not _producingSeps or }{ not }ifelse { /rectfill{ gsave newpath 4 2 roll moveto 1 index 0 rlineto 0 1 index rlineto 1 index neg 0 rlineto pop pop closepath fill grestore }def }if /linealImage _noImage{ /rectImage load }{ _producingSeps{ AGM_Gradient_Sep/AGM_Gradient_Sep_private get begin /rampImage load end }{ /rampImage load }ifelse }ifelse def AGM_Gradient_private { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall AGM_Gradient { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall end currentdict readonly pop end }def /initializeAI { pop pop AGM_Gradient/AGM_Gradient_private get /_illustrator true put AGM_Gradient/initialize get exec AGM_Gradient begin }def /unload{ systemdict/languagelevel known{ systemdict/languagelevel get 2 ge{ userdict/AGM_Gradient_Sep 2 copy known{ undef }{ pop pop }ifelse userdict/AGM_Gradient 2 copy known{ undef }{ pop pop }ifelse }if }if }def /terminate{ currentdict AGM_Gradient eq{ end }if }def AGM_Gradient_private begin /initializeVars{ /_d255 256 array def 0 1 255{ _d255 exch dup 255 div put }bind for /_d255- 256 array def 0 1 255{ _d255- exch 1 _d255 2 index get sub put }bind for /_sSave nd /_dUserSpace matrix defaultmatrix def /_bUMatrix matrix def /_imageMatrix matrix def /_saveMatrix matrix def /_xm matrix def /_ccAry1 5 array def /_level2PS systemdict/languagelevel known dup{ pop systemdict/languagelevel get 2 ge }if def /_level3PS _level2PS systemdict/shfill known and def currentdict /_illustrator known not{ /_illustrator false def }if }def /initializeOps { AGM_Gradient begin currentdict/Bc known not{ /Bc{ _renderFlag 2 eq{ 6 npop }{ pushBSpace _rampIndex 0 eq{ pop pop setCStop }if linealFill popBSpace }ifelse }def }if currentdict/Bg known not{ /Bg{ 10 npop /_gradName xp /_renderFlag xp _renderFlag 2 ne{ _illustrator{ _of setoverprint }if _illustrator _eo and _renderFlag 3 eq or{ eoclip }{ clip }ifelse _gradNames _gradName 2 copy known{ get mark exch aload pop /_gradType xp 1 sub dup /_rampIndex xp /_maxRampIndex xp mark exch aload pop 0 0 }if pop pop getRampData }{ mark mark }ifelse }def }if currentdict/Bm known not{ /Bm{ _renderFlag 2 ne{ _gradType 0 eq{ linealRamp }{ radialGrad }ifelse }{ 6 npop }ifelse }def }if currentdict/Bh known not{ /Bh{ 2 npop /_yHi xp /_xHi xp /_radHilite _xHi 0 ne _yHi 0 ne or pt }def }if currentdict/Bn known not{ /Bn{ AGM_Gradient_private begin dict /_gradNames xp end }def }if currentdict/Bd known not{ /Bd{ AGM_Gradient begin AGM_Gradient_private begin /_nColorsBd xp /_gradType xp /_gradName xp }def }if currentdict/BD known not{ /BD{ currentdict/_gradNames known not{ /_gradNames 20 dict def }if ] _nColorsBd _gradType ] _gradName exch /_gradNames xput end end }def }if currentdict/Bb known not{ /Bb{ AGM_Gradient begin AGM_Gradient_private begin _producingSeps{ AGM_Gradient_Sep/AGM_Gradient_Sep_private get begin }if mySave }def }if currentdict/BB known not{ /BB{ /_tmp xp cleartomark cleartomark _tmp dup _renderFlag myRestore _producingSeps{ end }if _illustrator end end { 2 ne exch 0 gt and{ 2 eq{ s }{ S }ifelse }{ pop newpath }ifelse }{ pop newpath }ifelse }def }if currentdict/Xm known not{ /Xm{ _xm astore pop }def }if end }def /queryDevice{ /_inRipSep _level2PS{ currentpagedevice/Separations 2 copy known{ get }{ pop pop false }ifelse }{ false }ifelse def /_noImage /lv1Fix where{ pop lv1Fix }{ false }ifelse def /_useShells where{ pop }{ /_useShells true def }ifelse /_useSmoothShade where{ pop }{ /_useSmoothShade false def }ifelse /_cyanPlate 1 0 0 0 testCMYKColorThrough def /_magentaPlate 0 1 0 0 testCMYKColorThrough def /_yellowPlate 0 0 1 0 testCMYKColorThrough def /_blackPlate 0 0 0 1 testCMYKColorThrough def /_compositeJob _cyanPlate _magentaPlate and _yellowPlate and _blackPlate and def /_compositeSpotDevice where{ pop }{ /_compositeSpotDevice _compositeJob not _inRipSep or{ 1 }{ 0 }ifelse def }ifelse /_producingSeps _compositeSpotDevice 0 ne def /_deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt def /_dpiThreshold where{ pop }{ /_dpiThreshold 600 def }ifelse /_screenFreqThreshold where{ pop }{ /_screenFreqThreshold 150 def }ifelse /_contoneDevice where{ pop }{ /_contoneDevice false def }ifelse /_subSampleOK _deviceDPI _dpiThreshold le currentScreenFreq _screenFreqThreshold le and _contoneDevice not and _producingSeps not and def }def /initializeLev1{ /makeByte8{ /_tmp 0 pt 255 mul cvi 8 string 8{ dup _tmp 3 index put /_tmp _tmp 1 add pt }repeat exch pop }def /currentScreenFreq{ currentscreen pop pop }def /_byte 1 string def /colorimage where{ pop }{ /colorimage{ pop pop /_blackTmp xp /_yellowTmp xp /_magentaTmp xp /_cyanTmp xp /_cnt 0 pt [ _byte dup 0 _cyanTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .3 /mul cvx _magentaTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .59 /mul cvx _yellowTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .11 /mul cvx _blackTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx /add cvx /add cvx /add cvx 1 /exch cvx /sub cvx /dup cvx 0 /lt cvx{ pop 0 }/if cvx /dup cvx 1 /gt cvx{ pop 1 }/if cvx 255 /mul cvx /cvi cvx 256 /mod cvx /dup cvx 0 /lt cvx{ pop 0 }/if cvx /put cvx /_cnt dup cvx 1 /add cvx /pt cvx ] cvx bind /_image load 5 execImage }def }ifelse }def /initializeLev2{ /level2ScreenFreq{ begin 60 HalftoneType 1 eq{ pop Frequency }if HalftoneType 2 eq{ pop GrayFrequency }if HalftoneType 5 eq{ pop Default level2ScreenFreq }if end }def /currentScreenFreq{ currenthalftone level2ScreenFreq }def }def /initializeShading{ _useSmoothShade _level3PS and{ /_usingSmoothShade true pt initializeLev3_Ops }{ /_usingSmoothShade false pt }ifelse }def /initializeLev3_Ops { /initShFill{ /_index _gradType 0 eq {0}{_maxRampIndex 1 sub} ifelse pt /_rampFuncsArray _maxRampIndex array pt /_boundsArray _maxRampIndex 1 sub array pt /_encodeArray _maxRampIndex 2 mul array pt /_beginCoord _rampPoint pt /_colorSpace null pt /_firstFill _rampIndex _maxRampIndex eq pt /_lastFill false pt }def /getRampColorSpace{ _nSamples 1 gt{ /_ndx 0 pt [blendColor] cvx exec }if /_C0 [currentcolor] pt /_C0_Space currentcolorspace pt _nSamples 1 gt{ /_ndx _nSamples 1 sub pt [blendColor] cvx exec }if /_C1 [currentcolor] pt /_C1_Space currentcolorspace pt _C0_Space _C1_Space eq{ /_rampColorSpace _C0_Space pt }{ (colorspace conflict!) == showpage stop }ifelse _spotColor{ nsetcustomcolorend }if }def /linealShFill{ popBSpace _xm aload pop pushBSpace /_size _index 1 add pt _size _maxRampIndex lt { /_rampFuncsArray _rampFuncsArray 0 _size getinterval pt /_boundsArray _boundsArray 0 _size 1 sub getinterval pt /_encodeArray _encodeArray 0 _size 2 mul getinterval pt }if bd /ShadingType 2 /ColorSpace _colorSpace /Function bd /FunctionType 3 /Domain [0 1] /Functions _rampFuncsArray /Bounds _boundsArray /Encode _encodeArray ed /Extend [_firstFill _lastFill] /Domain [0 1] /Coords [_beginCoord 0 _endCoord 0] ed shfill }def /radialShFill{ /_size _maxRampIndex _index sub pt _size _maxRampIndex lt { /_rampFuncsArray _rampFuncsArray _index _size getinterval pt /_boundsArray _boundsArray _index _size 1 sub getinterval pt /_encodeArray _encodeArray _index 2 mul _size 2 mul getinterval pt }if /_rampLen _beginCoord _endCoord sub pt bd /ShadingType 3 /ColorSpace _colorSpace /Function bd /FunctionType 3 /Domain [0 1] /Functions _rampFuncsArray /Bounds _boundsArray /Encode _encodeArray ed /Extend [_lastFill _firstFill] /Domain [0 1] /Coords [_xHi _rampLen mul _yHi _rampLen mul _endCoord 0 0 _beginCoord] ed shfill _radHilite{ _xHi _rampLen mul _yHi _rampLen mul translate }if }def /fillRamp{ /_invert _midPoint 0.5 lt pt _rampIndex _maxRampIndex eq { initShFill }if getRampColorSpace _colorSpace null eq{ /_colorSpace _rampColorSpace pt }{ _colorSpace _rampColorSpace ne{ /_index _index 1 _gradType 0 eq{ sub pt linealShFill }{ add pt radialShFill }ifelse initShFill /_colorSpace _rampColorSpace pt } if }ifelse /_endCoord _endPoint pt _rampFuncsArray _index bd /FunctionType 2 /Domain [0 1] /N 0.5 log _invert{1 _midPoint sub}{_midPoint}ifelse log div _gradType 0 eq{ _invert{/C1}{/C0}ifelse _C0 _invert{/C0}{/C1}ifelse _C1 }{ _invert{/C0}{/C1}ifelse _C1 _invert{/C1}{/C0}ifelse _C0 }ifelse ed put _rampIndex 1 ne{ _boundsArray _index _gradType 1 eq{1 sub}if _endCoord put } if 0 1 _invert {exch}if _encodeArray _index 2 mul 1 add 3 -1 roll put _encodeArray _index 2 mul 3 -1 roll put _rampIndex 1 eq { /_lastFill true pt _gradType 0 eq{ linealShFill }{ radialShFill }ifelse }if /_index _index 1 _gradType 0 eq{ add pt }{ sub pt }ifelse }def /radialRamp /fillRamp load def /rampImage /fillRamp load def AGM_Gradient begin /Bc{ 6 npop }def end }def /initializeComposite{ /bwImage{ pop /_image load 5 execImage }def currentdict/rampImage known not{ /rampImage{ _color{ _nSamples setImageParms _rgbRamp{ _redData _greenData _blueData _nSamples 3 expandColor true 3 null ncolorimage }{ _cyanData _magentaData _yellowData _blackData _nSamples 4 expandColor true 4 null ncolorimage }ifelse }{ _nSamples setImageParms _blackData null bwImage }ifelse }def }if /setCStop{ /_colorStyle exch pt _colorStyle 0 eq{ 1 exch sub 0 0 0 4 -1 roll }if _colorStyle 2 eq{ setrgbcolor 4 npop }if _colorStyle 3 eq{ 1 exch sub /_tmp xp pop 4{ _tmp mul 4 1 roll }repeat }if _colorStyle 4 eq{ 3 -1 roll pop pop 1 exch sub /_tmp xp 3{ 1 exch sub _tmp mul 1 exch sub 3 1 roll }repeat setrgbcolor 4 npop }if _colorStyle 2 ne _colorStyle 4 ne and{ null nsetcustomcolor }if }def /nsetcustomcolor { pop setcmykcolor }def /nsetcustomcolorend { }def /ncolorimage{ pop /_colorimage load 10 execImage }def _noImage not _level2PS not and{ /linealFill{ 8 setImageParms _color{ currentcmykcolor 4{ makeByte8 4 1 roll }repeat true 4 null ncolorimage }{ currentgray makeByte8 null bwImage }ifelse }def }if }def /npop{ {pop}repeat }def /xd{ exch def }def /nd{ null def }def /pt{ AGM_Gradient_private 3 1 roll put }def /xp{ exch pt }def /xput{ dup load dup length exch maxlength eq{ dup dup load dup length 2 mul dict copy def }if load begin def end }def /mySave{ save /_sSave xp }def /myRestore{ _sSave type /savetype eq{ _sSave restore }if }def /gMark{ counttomark 2 add -1 roll }def /execImage{ /_tmp xp { exec }stopped{ $error /errorname get /undefinedresult ne{ stop }{ _tmp npop }ifelse }if }def /pushBSpace{ newpath gsave _bUMatrix astore concat }def /popBSpace{ grestore }def /setImageParms{ 1 8 2 index 0 0 1 0 0 _imageMatrix astore }def /linealFill{ 0 0 1 1 rectfill }def /testCMYKColorThrough{ gsave setcmykcolor currentcmykcolor grestore add add add 0 ne }def /expandOne { /_tmp xp dup type /stringtype ne{ _tmp string exch dup 0 ne{ 255 mul cvi 0 1 _tmp 1 sub{ 3 copy exch put pop }for }if pop }if }def /expandColor{ /_channels xp /_len xp _channels{ _len expandOne _channels 1 roll }repeat }def /blendColor{ _color{ _rgbRamp _producingSeps not and{ _redData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _greenData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _blueData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if /setrgbcolor cvx }{ _cyanData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _magentaData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _yellowData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _blackData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _spotColor{ _rampSD begin /_rampSD cvx /begin cvx spot1 begin tintImage dup type /stringtype eq{ /_ndx cvx /get cvx _d255- /exch cvx /get cvx }{ dup null ne{ name type /nametype ne{ 1 exch sub }if }if }ifelse end /spot1 cvx /tintValue 3 -1 /roll cvx /put cvx spot2 begin tintImage dup type /stringtype eq{ /_ndx cvx /get cvx _d255- /exch cvx /get cvx }{ dup null ne{ name type /nametype ne{ 1 exch sub }if }if }ifelse end /spot2 cvx /tintValue 3 -1 /roll cvx /put cvx /end cvx end /_rampSD cvx /nsetcustomcolor cvx }{ /setcmykcolor cvx }ifelse }ifelse }{ _blackData /_ndx cvx /get cvx _d255 /exch cvx /get cvx _usingSmoothShade{ 1 /exch cvx /sub cvx 0 0 0 4 -1 /roll cvx /setcmykcolor cvx }{ /setgray cvx }ifelse }ifelse }def /linealRamp{ pushBSpace _ramp{ linealImage }{ linealFill }ifelse popBSpace /_rampIndex _rampIndex 1 sub pt _rampIndex 0 gt{ getRampData }if }def /radialGrad{ /_firstShell true pt _usingSmoothShade not{ fill }if pushBSpace _radHilite{ _xHi _yHi _bUMatrix idtransform /_yHi xp /_xHi xp _rampPoint 1 lt{ 1 _rampPoint sub dup _xHi mul exch _yHi mul translate }if }if _rampIndex{ radialRamp /_rampIndex _rampIndex 1 sub pt _rampIndex 0 gt{ getRampData }if }repeat popBSpace }def /getNSamples{ 0 exch { dup type /stringtype eq{ length exch pop exit }if pop }forall dup 0 eq{ pop 1 }if }def /getRampData{ /_rampType gMark pt /_color _rampType 0 gt pt /_ccRGB _rampType 5 eq _rampType 6 eq or pt /_rgbRamp _rampType 4 eq _ccRGB or pt /_ccProcess _rampType 2 eq _rampType 3 eq or pt _producingSeps{ _rampSD initSpotDict /_spotColor _ccProcess _ccRGB or pt }{ /_spotColor false pt }ifelse /_ramp true pt 100 div /_rampPoint xp 100 div /_midPoint xp dup /_colorStyle xp _colorStyle 0 eq{ 2 }{ _colorStyle 1 eq{ 5 }{ _colorStyle 2 eq{ 8 }{ _colorStyle 3 eq{ _producingSeps{ _rampSD begin spot1 begin /name 3 index def /spot_K 4 index def /spot_Y 5 index def /spot_M 6 index def /spot_C 7 index def end end }if 7 }{ _producingSeps{ _rampSD begin spot1 begin /name 4 index def /spot_K 8 index def /spot_Y 9 index def /spot_M 10 index def /spot_C 11 index def end end }if 11 } ifelse }ifelse }ifelse }ifelse /_tmp xp _tmp index 100 div /_endPoint xp _gradType 1 eq{ _tmp 1 add index 100 div /_midPoint xp }if _producingSeps{ _tmp 2 add index /_nextColorStyle xp _nextColorStyle 3 eq{ /_tmp _tmp 4 add pt _tmp index dup _rampSD begin spot1 /name get ne{ spot2 begin /name xd /spot_K _tmp 2 add index def /spot_Y _tmp 3 add index def /spot_M _tmp 4 add index def /spot_C _tmp 5 add index def end }{ pop }ifelse end }if _nextColorStyle 4 eq{ /_tmp _tmp 5 add pt _tmp index dup _rampSD begin spot1 /name get ne{ spot2 begin /name xd /spot_K _tmp 5 add index def /spot_Y _tmp 6 add index def /spot_M _tmp 7 add index def /spot_C _tmp 8 add index def end }{ pop }ifelse end }if }if _rampType 3 eq _rampType 6 eq or{ /_tint2Data gMark pt }if _ccProcess _ccRGB or{ /_tint1Data gMark pt }if _rgbRamp{ /_blueData gMark pt /_greenData gMark pt /_redData gMark pt }if _producingSeps{ _rampSD begin _ccProcess _ccRGB or{ _rampType 3 eq _rampType 6 eq or{ spot2 begin /tintImage _gradType 0 eq{ _tint2Data }{ _tint1Data }ifelse def name null eq{ /name /Black def }if end }if spot1 begin /tintImage _gradType 0 eq _rampType 2 eq or _rampType 5 eq or{ _tint1Data }{ _tint2Data }ifelse def _rampType 2 eq _rampType 5 eq or{ name null eq{ /name spot2 /name get def spot2 /name null put }if }{ name null eq{ /name /Black def }if }ifelse end }if end }if /_blackData gMark pt _rampType 0 gt{ counttomark 4 add -3 roll /_yellowData xp /_magentaData xp /_cyanData xp }if _ramp{ /_nSamples [ _rampType 0 eq {_blackData}if _rampType 1 eq {_cyanData _magentaData _yellowData _blackData}if _rampType 2 eq {_cyanData _magentaData _yellowData _blackData _tint1Data}if _rampType 3 eq {_cyanData _magentaData _yellowData _blackData _tint1Data _tint2Data}if _rampType 4 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData}if _rampType 5 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData _tint1Data}if _rampType 6 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData _tint1Data _tint2Data}if ] getNSamples pt _usingSmoothShade not {/_ramp _nSamples 1 gt pt} if } if setCStop }def /rectImage{ gsave /_sInc 1 pt /_bInc 1 _nSamples div pt /_uRampLen 1 0 dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt pt /_pChange _uRampLen 0 eq{0}{_nSamples _uRampLen div}ifelse pt 0 _nSamples [ /dup cvx /_ndx /exch cvx /pt cvx blendColor 0 0 _bInc 1 /rectfill cvx _bInc 0 /translate cvx _sInc /add cvx ] cvx bind repeat pop _spotColor{ nsetcustomcolorend }if grestore }def /radialInit{ /_nRadSamples _nSamples dup 0 eq{pop 1}if pt /_sInc -1 pt /_rampLen _rampPoint _endPoint sub pt /_bInc _rampLen _nSamples div neg pt /_optimize false pt _subSampleOK{ /_uRampLen _rampLen 0 dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt 0 _rampLen dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt 2 copy lt{ exch }if pop pt /_pChange _uRampLen 0 eq{ 0 }{ _nSamples _uRampLen div }ifelse pt _pChange .5 gt dup /_optimize xp{ /_nRadSamples _uRampLen 2 div round cvi dup 1 le{pop 2}if pt /_bInc _rampLen _nRadSamples div neg pt /_sInc _nSamples 1 sub _nRadSamples 1 sub div neg pt }if }if _radHilite{ /_xBCInc _xHi _rampLen mul _nRadSamples div pt /_yBCInc _yHi _rampLen mul _nRadSamples div pt }if }def currentdict/radialRamp known not{ /radialRamp{ /_saveMatrix _saveMatrix currentmatrix def radialInit _rampPoint _nSamples 1 sub _nRadSamples [ /dup cvx _optimize{ /round cvx /cvi cvx }if /_ndx /exch cvx /pt cvx _useShells{ /_firstShell cvx{ /_firstShell false pt }{ 0 0 3 index 360 0 arcn fill }/ifelse cvx }if blendColor _useShells{ 0 0 3 /index cvx 0 360 /arc cvx }{ 0 0 3 /index cvx 0 360 /arc cvx /fill cvx }ifelse /exch cvx _bInc /add cvx /exch cvx _sInc /add cvx _radHilite{ _xBCInc _yBCInc /translate cvx }if ] cvx bind repeat pop pop _saveMatrix setmatrix _radHilite{ _xHi _rampLen mul _yHi _rampLen mul translate }if _useShells _rampIndex 1 eq and{ fill }if _spotColor{ nsetcustomcolorend }if }def }if end end defaultpacking setpacking %%EndResource %%BeginProcSet: Adobe_ColorImage_AI6 1.1 0 userdict /Adobe_ColorImage_AI6 known not { userdict /Adobe_ColorImage_AI6 24 dict put } if userdict /Adobe_ColorImage_AI6 get begin /initialize { Adobe_ColorImage_AI6 begin Adobe_ColorImage_AI6 { dup type /arraytype eq { dup xcheck { bind } if } if pop pop } forall } def /terminate { end } def currentdict /Adobe_ColorImage_AI6_Vars known not { /Adobe_ColorImage_AI6_Vars 15 dict def } if Adobe_ColorImage_AI6_Vars begin /channelcount 0 def /sourcecount 0 def /sourcearray 4 array def /plateindex -1 def /XIMask 0 def /XIBinary 0 def /XIChannelCount 0 def /XIBitsPerPixel 0 def /XIImageHeight 0 def /XIImageWidth 0 def /XIImageMatrix null def /XIBuffer null def /XIDataProc null def /XIVersion 6 def end /WalkRGBString null def /WalkCMYKString null def /StuffRGBIntoGrayString null def /RGBToGrayImageProc null def /StuffCMYKIntoGrayString null def /CMYKToGrayImageProc null def /ColorImageCompositeEmulator null def /SeparateCMYKImageProc null def /FourEqual null def /TestPlateIndex null def currentdict /_colorimage known not { /colorimage where { /colorimage get /_colorimage exch def } { /_colorimage null def } ifelse } if /_currenttransfer systemdict /currenttransfer get def /colorimage null def /XI null def /WalkRGBString { 0 3 index dup length 1 sub 0 3 3 -1 roll { 3 getinterval { } forall 5 index exec 3 index } for 5 { pop } repeat } def /WalkCMYKString { 0 3 index dup length 1 sub 0 4 3 -1 roll { 4 getinterval { } forall 6 index exec 3 index } for 5 { pop } repeat } def /StuffRGBIntoGrayString { .11 mul exch .59 mul add exch .3 mul add cvi 3 copy put pop 1 add } def /RGBToGrayImageProc { Adobe_ColorImage_AI6_Vars begin sourcearray 0 get exec dup length 3 idiv string dup 3 1 roll /StuffRGBIntoGrayString load exch WalkRGBString end } def /StuffCMYKIntoGrayString { exch .11 mul add exch .59 mul add exch .3 mul add dup 255 gt { pop 255 } if 255 exch sub cvi 3 copy put pop 1 add } def /CMYKToGrayImageProc { Adobe_ColorImage_AI6_Vars begin sourcearray 0 get exec dup length 4 idiv string dup 3 1 roll /StuffCMYKIntoGrayString load exch WalkCMYKString end } def /ColorImageCompositeEmulator { pop true eq { Adobe_ColorImage_AI6_Vars /sourcecount get 5 add { pop } repeat } { Adobe_ColorImage_AI6_Vars /channelcount get 1 ne { Adobe_ColorImage_AI6_Vars begin sourcearray 0 3 -1 roll put channelcount 3 eq { /RGBToGrayImageProc } { /CMYKToGrayImageProc } ifelse load end } if image } ifelse } def /SeparateCMYKImageProc { Adobe_ColorImage_AI6_Vars begin sourcecount 0 ne { sourcearray plateindex get exec } { sourcearray 0 get exec dup length 4 idiv string 0 2 index plateindex 4 2 index length 1 sub { get 255 exch sub 3 copy put pop 1 add 2 index } for pop pop exch pop } ifelse end } def /FourEqual { 4 index ne { pop pop pop false } { 4 index ne { pop pop false } { 4 index ne { pop false } { 4 index eq } ifelse } ifelse } ifelse } def /TestPlateIndex { Adobe_ColorImage_AI6_Vars begin /plateindex -1 def /setcmykcolor where { pop gsave 1 0 0 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 1 0 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 0 1 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 0 0 1 setcmykcolor systemdict /currentgray get exec 1 exch sub grestore 1 0 0 0 FourEqual { /plateindex 0 def } { 0 1 0 0 FourEqual { /plateindex 1 def } { 0 0 1 0 FourEqual { /plateindex 2 def } { 0 0 0 1 FourEqual { /plateindex 3 def } { 0 0 0 0 FourEqual { /plateindex 5 def } if } ifelse } ifelse } ifelse } ifelse pop pop pop pop } if plateindex end } def /colorimage { Adobe_ColorImage_AI6_Vars begin /channelcount 1 index def /sourcecount 2 index 1 eq { channelcount 1 sub } { 0 } ifelse def 4 sourcecount add index dup 8 eq exch 1 eq or not end { /_colorimage load null ne { _colorimage } { Adobe_ColorImage_AI6_Vars /sourcecount get 7 add { pop } repeat } ifelse } { dup 3 eq TestPlateIndex dup -1 eq exch 5 eq or or { /_colorimage load null eq { ColorImageCompositeEmulator } { dup 1 eq { pop pop image } { Adobe_ColorImage_AI6_Vars /plateindex get 5 eq { gsave 0 _currenttransfer exec 1 _currenttransfer exec eq { 0 _currenttransfer exec 0.5 lt } { 0 _currenttransfer exec 1 _currenttransfer exec gt } ifelse { { pop 0 } } { { pop 1 } } ifelse systemdict /settransfer get exec } if _colorimage Adobe_ColorImage_AI6_Vars /plateindex get 5 eq { grestore } if } ifelse } ifelse } { dup 1 eq { pop pop image } { pop pop Adobe_ColorImage_AI6_Vars begin sourcecount -1 0 { exch sourcearray 3 1 roll put } for /SeparateCMYKImageProc load end systemdict /image get exec } ifelse } ifelse } ifelse } def /XG { pop pop } def /XF { 13 {pop} repeat } def /Xh { Adobe_ColorImage_AI6_Vars begin gsave /XIMask exch 0 ne def /XIImageHeight exch def /XIImageWidth exch def /XIImageMatrix exch def 0 0 moveto XIImageMatrix concat XIImageWidth XIImageHeight scale XIMask { /_lp /null ddef _fc /_lp /imagemask ddef } if /XIVersion 7 def end } def /XH { Adobe_ColorImage_AI6_Vars begin /XIVersion 6 def grestore end } def /XI { Adobe_ColorImage_AI6_Vars begin gsave /XIMask exch 0 ne def /XIBinary exch 0 ne def pop pop /XIChannelCount exch def /XIBitsPerPixel exch def /XIImageHeight exch def /XIImageWidth exch def pop pop pop pop /XIImageMatrix exch def XIBitsPerPixel 1 eq { XIImageWidth 8 div ceiling cvi } { XIImageWidth XIChannelCount mul } ifelse /XIBuffer exch string def XIBinary { /XIDataProc { currentfile XIBuffer readstring pop } def XIVersion 6 le { currentfile 128 string readline pop pop } if } { /XIDataProc { currentfile XIBuffer readhexstring pop } def } ifelse XIVersion 6 le { 0 0 moveto XIImageMatrix concat XIImageWidth XIImageHeight scale XIMask { /_lp /null ddef _fc /_lp /imagemask ddef } if } if XIMask { XIImageWidth XIImageHeight false [ XIImageWidth 0 0 XIImageHeight neg 0 0 ] /XIDataProc load imagemask } { XIImageWidth XIImageHeight XIBitsPerPixel [ XIImageWidth 0 0 XIImageHeight neg 0 0 ] /XIDataProc load XIChannelCount 1 eq { gsave 0 setgray image grestore } { false XIChannelCount colorimage } ifelse } ifelse grestore end } def end %%EndProcSet %%BeginResource: procset Adobe_Illustrator_AI5 1.1 0 %%Title: (Adobe Illustrator (R) Version 5.0 Full Prolog) %%Version: 1.1 0 %%CreationDate: (3/7/1994) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_Illustrator_AI5_vars 81 dict dup begin put /_eo false def /_lp /none def /_pf { } def /_ps { } def /_psf { } def /_pss { } def /_pjsf { } def /_pjss { } def /_pola 0 def /_doClip 0 def /cf currentflat def /_tm matrix def /_renderStart [ /e0 /r0 /a0 /o0 /e1 /r1 /a1 /i0 ] def /_renderEnd [ null null null null /i1 /i1 /i1 /i1 ] def /_render -1 def /_rise 0 def /_ax 0 def /_ay 0 def /_cx 0 def /_cy 0 def /_leading [ 0 0 ] def /_ctm matrix def /_mtx matrix def /_sp 16#020 def /_hyphen (-) def /_fScl 0 def /_cnt 0 def /_hs 1 def /_nativeEncoding 0 def /_useNativeEncoding 0 def /_tempEncode 0 def /_pntr 0 def /_tDict 2 dict def /_wv 0 def /Tx { } def /Tj { } def /CRender { } def /_AI3_savepage { } def /_gf null def /_cf 4 array def /_if null def /_of false def /_fc { } def /_gs null def /_cs 4 array def /_is null def /_os false def /_sc { } def /_pd 1 dict def /_ed 15 dict def /_pm matrix def /_fm null def /_fd null def /_fdd null def /_sm null def /_sd null def /_sdd null def /_i null def /discardSave null def /buffer 256 string def /beginString null def /endString null def /endStringLength null def /layerCnt 1 def /layerCount 1 def /perCent (%) 0 get def /perCentSeen? false def /newBuff null def /newBuffButFirst null def /newBuffLast null def /clipForward? false def end userdict /Adobe_Illustrator_AI5 known not { userdict /Adobe_Illustrator_AI5 91 dict put } if userdict /Adobe_Illustrator_AI5 get begin /initialize { Adobe_Illustrator_AI5 dup begin Adobe_Illustrator_AI5_vars begin discardDict { bind pop pop } forall dup /nc get begin { dup xcheck 1 index type /operatortype ne and { bind } if pop pop } forall end newpath } def /terminate { end end } def /_ null def /ddef { Adobe_Illustrator_AI5_vars 3 1 roll put } def /xput { dup load dup length exch maxlength eq { dup dup load dup length 2 mul dict copy def } if load begin def end } def /npop { { pop } repeat } def /sw { dup length exch stringwidth exch 5 -1 roll 3 index mul add 4 1 roll 3 1 roll mul add } def /swj { dup 4 1 roll dup length exch stringwidth exch 5 -1 roll 3 index mul add 4 1 roll 3 1 roll mul add 6 2 roll /_cnt 0 ddef { 1 index eq { /_cnt _cnt 1 add ddef } if } forall pop exch _cnt mul exch _cnt mul 2 index add 4 1 roll 2 index add 4 1 roll pop pop } def /ss { 4 1 roll { 2 npop (0) exch 2 copy 0 exch put pop gsave false charpath currentpoint 4 index setmatrix stroke grestore moveto 2 copy rmoveto } exch cshow 3 npop } def /jss { 4 1 roll { 2 npop (0) exch 2 copy 0 exch put gsave _sp eq { exch 6 index 6 index 6 index 5 -1 roll widthshow currentpoint } { false charpath currentpoint 4 index setmatrix stroke } ifelse grestore moveto 2 copy rmoveto } exch cshow 6 npop } def /sp { { 2 npop (0) exch 2 copy 0 exch put pop false charpath 2 copy rmoveto } exch cshow 2 npop } def /jsp { { 2 npop (0) exch 2 copy 0 exch put _sp eq { exch 5 index 5 index 5 index 5 -1 roll widthshow } { false charpath } ifelse 2 copy rmoveto } exch cshow 5 npop } def /pl { transform 0.25 sub round 0.25 add exch 0.25 sub round 0.25 add exch itransform } def /setstrokeadjust where { pop true setstrokeadjust /c { curveto } def /C /c load def /v { currentpoint 6 2 roll curveto } def /V /v load def /y { 2 copy curveto } def /Y /y load def /l { lineto } def /L /l load def /m { moveto } def } { /c { pl curveto } def /C /c load def /v { currentpoint 6 2 roll pl curveto } def /V /v load def /y { pl 2 copy curveto } def /Y /y load def /l { pl lineto } def /L /l load def /m { pl moveto } def } ifelse /d { setdash } def /cf { } def /i { dup 0 eq { pop cf } if setflat } def /j { setlinejoin } def /J { setlinecap } def /M { setmiterlimit } def /w { setlinewidth } def /XR { 0 ne /_eo exch ddef } def /H { } def /h { closepath } def /N { _pola 0 eq { _doClip 1 eq { _eo {eoclip} {clip} ifelse /_doClip 0 ddef } if newpath } { /CRender { N } ddef } ifelse } def /n { N } def /F { _pola 0 eq { _doClip 1 eq { gsave _pf grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _fc /_doClip 0 ddef } { _pf } ifelse } { /CRender { F } ddef } ifelse } def /f { closepath F } def /S { _pola 0 eq { _doClip 1 eq { gsave _ps grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _sc /_doClip 0 ddef } { _ps } ifelse } { /CRender { S } ddef } ifelse } def /s { closepath S } def /B { _pola 0 eq { _doClip 1 eq gsave F grestore { gsave S grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _sc /_doClip 0 ddef } { S } ifelse } { /CRender { B } ddef } ifelse } def /b { closepath B } def /W { /_doClip 1 ddef } def /* { count 0 ne { dup type /stringtype eq { pop } if } if newpath } def /u { } def /U { } def /q { _pola 0 eq { gsave } if } def /Q { _pola 0 eq { grestore } if } def /*u { _pola 1 add /_pola exch ddef } def /*U { _pola 1 sub /_pola exch ddef _pola 0 eq { CRender } if } def /D { pop } def /*w { } def /*W { } def /` { /_i save ddef clipForward? { nulldevice } if 6 1 roll 4 npop concat pop userdict begin /showpage { } def 0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit [] 0 setdash /setstrokeadjust where {pop false setstrokeadjust} if newpath 0 setgray false setoverprint } def /~ { end _i restore } def /O { 0 ne /_of exch ddef /_lp /none ddef } def /R { 0 ne /_os exch ddef /_lp /none ddef } def /g { /_gf exch ddef /_fc { _lp /fill ne { _of setoverprint _gf setgray /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /G { /_gs exch ddef /_sc { _lp /stroke ne { _os setoverprint _gs setgray /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /k { _cf astore pop /_fc { _lp /fill ne { _of setoverprint _cf aload pop setcmykcolor /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /K { _cs astore pop /_sc { _lp /stroke ne { _os setoverprint _cs aload pop setcmykcolor /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /x { /_gf exch ddef findcmykcustomcolor /_if exch ddef /_fc { _lp /fill ne { _of setoverprint _if _gf 1 exch sub setcustomcolor /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /X { /_gs exch ddef findcmykcustomcolor /_is exch ddef /_sc { _lp /stroke ne { _os setoverprint _is _gs 1 exch sub setcustomcolor /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /A { pop } def /annotatepage { userdict /annotatepage 2 copy known {get exec} {pop pop} ifelse } def /XT { pop pop } def /discard { save /discardSave exch store discardDict begin /endString exch store gt38? { 2 add } if load stopped pop end discardSave restore } bind def userdict /discardDict 7 dict dup begin put /pre38Initialize { /endStringLength endString length store /newBuff buffer 0 endStringLength getinterval store /newBuffButFirst newBuff 1 endStringLength 1 sub getinterval store /newBuffLast newBuff endStringLength 1 sub 1 getinterval store } def /shiftBuffer { newBuff 0 newBuffButFirst putinterval newBuffLast 0 currentfile read not { stop } if put } def 0 { pre38Initialize mark currentfile newBuff readstring exch pop { { newBuff endString eq { cleartomark stop } if shiftBuffer } loop } { stop } ifelse } def 1 { pre38Initialize /beginString exch store mark currentfile newBuff readstring exch pop { { newBuff beginString eq { /layerCount dup load 1 add store } { newBuff endString eq { /layerCount dup load 1 sub store layerCount 0 eq { cleartomark stop } if } if } ifelse shiftBuffer } loop } if } def 2 { mark { currentfile buffer readline not { stop } if endString eq { cleartomark stop } if } loop } def 3 { /beginString exch store /layerCnt 1 store mark { currentfile buffer readline not { stop } if dup beginString eq { pop /layerCnt dup load 1 add store } { endString eq { layerCnt 1 eq { cleartomark stop } { /layerCnt dup load 1 sub store } ifelse } if } ifelse } loop } def end userdict /clipRenderOff 15 dict dup begin put { /n /N /s /S /f /F /b /B } { { _doClip 1 eq { /_doClip 0 ddef _eo {eoclip} {clip} ifelse } if newpath } def } forall /Tr /pop load def /Bb {} def /BB /pop load def /Bg {12 npop} def /Bm {6 npop} def /Bc /Bm load def /Bh {4 npop} def end /Lb { 4 npop 6 1 roll pop 4 1 roll pop pop pop 0 eq { 0 eq { (%AI5_BeginLayer) 1 (%AI5_EndLayer--) discard } { /clipForward? true def /Tx /pop load def /Tj /pop load def currentdict end clipRenderOff begin begin } ifelse } { 0 eq { save /discardSave exch store } if } ifelse } bind def /LB { discardSave dup null ne { restore } { pop clipForward? { currentdict end end begin /clipForward? false ddef } if } ifelse } bind def /Pb { pop pop 0 (%AI5_EndPalette) discard } bind def /Np { 0 (%AI5_End_NonPrinting--) discard } bind def /Ln /pop load def /Ap /pop load def /Ar { 72 exch div 0 dtransform dup mul exch dup mul add sqrt dup 1 lt { pop 1 } if setflat } def /Mb { q } def /Md { } def /MB { Q } def /nc 3 dict def nc begin /setgray { pop } bind def /setcmykcolor { 4 npop } bind def /setcustomcolor { 2 npop } bind def currentdict readonly pop end end setpacking %%EndResource %%BeginResource: procset Adobe_blend_AI5 1.4 0 %%Title: (Adobe Illustrator (R) Version 5.0 Blend ProcSet) %%Version: 1.4 0 %%CreationDate: (11/19/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /Adobe_blend_AI5 70 dict dup begin put /bd { bind def } bind def /xs { exch store } bd /nullProc { { } } def /initialize { pop pop Adobe_blend_AI5 begin Adobe_blend_AI5_vars begin /_contoneDevice where { pop } { /_contoneDevice false def } ifelse /_dpiThreshold where { pop } { /_dpiThreshold 600 def } ifelse /_screenFreqThreshold where { pop } { /_screenFreqThreshold 150 def } ifelse /tRectOK? deviceDPI _dpiThreshold le currentScreenFreq _screenFreqThreshold le and _contoneDevice not and def /invertXfer { [ { 1 exch sub } /exec load systemdict/currenttransfer get exec /exec load ] cvx systemdict/settransfer get exec } bd /spotDict 3 dict dup begin /nSpots 2 def /spot1 7 dict def /spot2 7 dict def end def composite? { /_setgray_ /setgray load def /_fill_ /fill load def /_image_ /image load def } { /_setgray_ systemdict/setgray get def /_fill_ systemdict/fill get def /_image_ systemdict/image get def } ifelse } bd /terminate { currentdict Adobe_blend_AI5_vars eq { end currentdict Adobe_blend_AI5 eq { end } if } if } bd /_compositeSpotDevice where { begin _compositeSpotDevice 0 ne {userdict /composite? true put} if end } { /_compositeSpotDevice 0 def } ifelse /nullString () def /d255 256 array def 0 1 255 { d255 exch dup 255 div put } bind for /d255- 256 array def 0 1 255 { d255- exch 1 d255 2 index get sub put } bind for /dUserSpace matrix defaultmatrix def currentdict /Adobe_blend_AI5_vars 89 dict dup begin put { /f /F /s /S /b /B } { null def } bind forall /byte 1 string def /sSave null def /setSSave { save /sSave exch store } bind def /Bm null def /doBlend null def /startC? false def /endC? false def /fCMYK? null def /startTint 0 def /endTint 0 def /bSMatrix matrix def /bUMatrix matrix def /dMatrix matrix def /inLine? true def /pTState? false def /bHi? false def /yHi 0 def /xHi 0 def /noImg /lv1Fix where { pop lv1Fix } { false } ifelse def /ccAry1 5 array def /ccTint 0 def /spotColor? false def /colorimage? true def [ /tint1Data /tint2Data /spotDict /bAxis /ubAxis /pChange /optimize? /nSamples /sInc /blendProc /_bn /xBCInc /yBCInc /bInc /bRender /cBName /cBType /nColors /color? /blend? /colorType /cData /cDataLen /bDataLen /rampPoint /midPoint /endPoint /blendLength /blackData /yeData /mgData /cyData /cnt1 /ndx /_fill /tmp counttomark { null def } bind repeat pop currentdict end currentdict end exch begin begin /unitSq { 0 0 moveto 0 1 lineto 1 1 lineto 1 0 lineto closepath } bd /gMark { counttomark 2 add -1 roll } bd /setCustomColor { dup /ccTint exch store 1 exch sub 6 1 roll ccAry1 astore exch setcustomcolor } bd /currentCustomColor { ccAry1 aload pop ccTint } bd /nsetcustomcolor where { pop } { /nsetcustomcolor { pop setcmykcolor } bd } ifelse /nsetcustomcolorend where { pop } { /nsetcustomcolorend { } bd } ifelse /setBSpace { newpath bUMatrix astore concat unitSq } bd /setCStop { dup 0 eq { pop spotColor? { dup 1 exch sub /ccTint exch def ccAry1 4 /Black put } if setgray } { 1 eq { setcmykcolor } { composite? not colorType 2 lt and { forceCMYK } { setCustomColor } ifelse } ifelse } ifelse } bd /makeByte { /tmp 0 store 255 mul cvi 8 string 8 { dup tmp 3 index put /tmp tmp 1 add store } repeat exch pop } bd /setImgSpace { cDataLen 1 8 2 index 0 0 1 0 0 dMatrix astore } bd /bwImage { setImgSpace cData /_image_ load { exec } stopped { $error /errorname get /undefinedresult ne { stop } { pop pop pop pop pop } ifelse } if } bd level2? { /bFill { _fill } def /bCImg { /cDataLen bDataLen store setImgSpace setSSave expandSpot cyData mgData yeData cData expandCMYK true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd } if /expandOne { dup type /stringtype ne { cDataLen string exch dup 0 ne { 255 mul cvi 0 1 cDataLen 1 sub { 3 copy exch put pop } for } if pop } if } bd /expandSpot { spotColor? { spotDict begin spot1 begin tintImage type /nulltype ne { tintImage expandOne /tintImage exch def } if end spot2 begin tintImage type /nulltype ne { tintImage expandOne /tintImage exch def } if end end } if } bd /expandCMYK { 4 { expandOne 4 1 roll } repeat } bd /colorimage where dup { exch pop /ncolorimage where { pop } { /ncolorimage {pop colorimage} bd } ifelse } if not { /ncolorimage where { pop } { /colorimage? false store /ncolorimage { pop pop pop setSSave /blackData xs /yeData xs /mgData xs /cyData xs /cnt1 0 store [ byte dup 0 cyData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .3 /mul cvx } { .3 mul } ifelse mgData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .59 /mul cvx } { .59 mul } ifelse yeData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .11 /mul cvx } { .11 mul } ifelse blackData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx } if /add cvx /add cvx /add cvx 1 /exch cvx /sub cvx /dup cvx 0 /lt cvx { pop 0 } /if cvx /dup cvx 1 /gt cvx { pop 1 } /if cvx 255 /mul cvx /cvi cvx 256 /mod cvx /dup cvx 0 /lt cvx { pop 0 } /if cvx /put cvx /cnt1 dup cvx 1 /add cvx /store cvx ] cvx bind _image_ sSave restore } bd } ifelse } if level2? not { /bCImg { /cDataLen bDataLen store setImgSpace setSSave expandSpot cyData mgData yeData cData colorimage? { expandCMYK } if true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd /bwFill { setSSave /cDataLen 8 store /cData currentgray makeByte store bwImage sSave restore } bd /c1ImgFill { setSSave /cDataLen 8 store setImgSpace spotColor? { spotDict begin spot1 begin currentCustomColor makeByte /tintImage exch def /name exch def /spot_K exch def /spot_Y exch def /spot_M exch def /spot_C exch def end spot2 initSpotData end } if currentcmykcolor 4 { makeByte 4 1 roll } repeat true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd /bFill noImg { { _fill } } { { color? { c1ImgFill } { bwFill } ifelse } } ifelse bd } if composite? { /bCFun { color? { cyData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if mgData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if yeData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if cData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if spotColor? { spotDict begin /spotDict cvx /begin cvx spot1 begin tintImage dup type /stringtype eq { /ndx cvx /get cvx d255- /exch cvx /get cvx } { dup type /nulltype ne { name type /nametype ne {1 exch sub} if } if } ifelse end /spot1 cvx /tintValue 3 -1 /roll cvx /put cvx spot2 begin tintImage dup type /stringtype eq { /ndx cvx /get cvx d255- /exch cvx /get cvx } { dup type /nulltype ne { name type /nametype ne {1 exch sub} if } if } ifelse end /spot2 cvx /tintValue 3 -1 /roll cvx /put cvx /end cvx end /spotDict cvx /nsetcustomcolor cvx } { /setcmykcolor cvx } ifelse } { cData /ndx cvx /get cvx d255 /exch cvx /get cvx /setgray cvx } ifelse } bd /Bc { newpath gsave setBSpace nColors 1 eq { pop pop setCStop } if bFill grestore } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { linImg } { bFill } ifelse grestore nColors 1 gt { getRData } if } bd /rdBm { /nColors dup load 1 sub store _fill gsave bUMatrix astore concat bHi? { xHi yHi bUMatrix idtransform /yHi exch store /xHi exch store rampPoint 1 lt { 1 rampPoint sub dup xHi mul exch yHi mul translate } if } if nColors { 0 0 rampPoint 0 360 arc _fill blend? bHi? or { rdBlend } if nColors 1 gt { getRData } if /nColors dup load 1 sub store } repeat /nColors 1 store grestore } bd /cGetRData { setCStop /blend? cData type /stringtype eq dup not color? and { pop cyData type /stringtype eq mgData type /stringtype eq yeData type /stringtype eq or or } if store } def /cGetRData } if /eCStop { mark 1 index 3 mul 3 add dup 8 gt { pop 8 } if 1 roll cleartomark } bd composite? not { /knockOut level2? { { 0 0 0 0 setcmykcolor _fill } } { /bFill noImg { { _fill } } { { _of true eq { currentgray 1 ne { bwFill } if } { bwFill } ifelse } } ifelse def /whiteByte 1 makeByte def noImg { { 0 0 0 0 setcmykcolor _fill } } { { cBType 0 eq { setSSave /cData whiteByte store /cDataLen 8 store bwImage sSave restore } { _fill } ifelse } } ifelse } ifelse bd /bCFun { cData dup type /stringtype ne { color? { 1 exch sub } if } { /ndx cvx /get cvx color? customColor? not and { d255- } { d255 } ifelse /exch cvx /get cvx } ifelse /_setgray_ cvx } bd /eCCBlend { dup 3 eq { pop mark 7 1 roll 6 copy ccThrough? dup /blend? xs { /startC? true store setCustomColor customColor? { /cData tint1Data store setCDataLen } if /endC? 3 index 3 eq { 4 index 1 ne } { false } ifelse store } if cleartomark stop } if 1 eq { pop pop pop } if pop /startC? false store 6 { 8 index } repeat ccThrough? dup /blend? xs { /endC? true store blend? not { stop } if customColor? { /cData tint1Data store setCDataLen } if } if } bd /handleOP { _of not { knockOut } if } bd /handleROP { _of not { 0 0 0 0 setcmykcolor _fill } { newpath } ifelse } bd /rdBm { /nColors dup load 1 sub store blend? { _fill } { handleROP } ifelse gsave bUMatrix astore concat bHi? { xHi yHi bUMatrix idtransform /yHi exch store /xHi exch store rampPoint 1 lt { 1 rampPoint sub dup xHi mul exch yHi mul translate } if } if nColors { 0 0 rampPoint 0 360 arc blend? { cData type /stringtype ne bHi? not and { cData color? { 1 exch sub } if _setgray_ _fill_ } { cData type /stringtype ne { /cDataLen 1 store /bDataLen 1 store } if rdBlend } ifelse } { handleROP pTState? { /bAxis rampPoint endPoint sub store xHi bAxis mul yHi bAxis mul translate } if } ifelse nColors 1 gt { getRData } if /nColors dup load 1 sub store } repeat /nColors 1 store grestore } bd /ccThrough? { gsave pop 0 setCustomColor currentcmykcolor grestore anyColor? } bd /forceCMYK { exch pop 1 exch sub 5 1 roll 4 { 4 index mul 4 1 roll } repeat 0 cCMYKData dup /cData ne { dup /yeData eq { pop 1 add } { /mgData eq { 2 } { 3 } ifelse add } ifelse 0 } if pop index 0 eq { pop pop pop pop 0 0 0 0 } if setcmykcolor pop /fCMYK? true store } bd /endCapSepBc { pop pop dup 0 eq { pop setgray } { 1 eq { setcmykcolor } { colorType 1 eq { forceCMYK } { fCMYK? { forceCMYK } { setCustomColor } ifelse } ifelse } ifelse } ifelse currentcmykcolor anyColor? blend? and { bFill } { handleOP } ifelse } bd } if /cCMYKData 0 def composite? dup not { pop customColor? } if not { /cCMYKData /cyData /mgData /yeData /cData black? not { yellow? { exch } { magenta? { 3 } { 4 } ifelse -1 roll } ifelse } if 4 1 roll pop pop pop store /Bc { gsave setBSpace nColors 1 gt { blend? currentcmykcolor anyColor? and { bFill } { handleOP } ifelse } { endCapSepBc } ifelse grestore newpath } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { cCMYKData load dup type /stringtype eq { dup length /cDataLen xs /cData xs gsave colorType 0 ne noImg not and { invertXfer } if linImg grestore } { pop bFill } ifelse } { handleOP } ifelse grestore nColors 1 gt { getRData } if } bd /cmykGetRData { /fCMYK? false store blend? { { cmykDataProcs colorType get exec } stopped pop blend? { /cData cCMYKData load store setCDataLen } if } if } def /cmykDataProcs [ { pop black? dup /blend? xs { setgray 0 } if pop } { cCMYKData load dup type /stringtype ne { 0 0 0 cyan? not { 4 magenta? { 1 } { yellow? { 2 } { 3 } ifelse } ifelse roll } if 4 copy add add add 0 eq { /blend? false store } if setcmykcolor /startC? true store /endC? true store eCStop stop } if pop dup 0 eq { pop setgray } { 1 eq { setcmykcolor } { forceCMYK } ifelse } ifelse } bind /eCCBlend load { cBType 1 eq { tint1Data tint2Data /tint1Data xs /tint2Data xs } if 0 eq { black? { setgray } { 0 0 0 4 -1 roll 1 exch sub setcmykcolor } ifelse black? { /blend? true store } if 6 { 8 index } repeat ccThrough? { /blend? true store } { black? { /cData tint1Data store setCDataLen } { /blend? false store } ifelse } ifelse } { mark 7 1 roll 6 copy ccThrough? { forceCMYK pop stop } if 9 index 0 eq { black? dup /blend? xs { pop 1 setgray /cData tint2Data store setCDataLen 0 } if pop } { /blend? 6 { 16 index } repeat ccThrough? store blend? { forceCMYK } if } ifelse cleartomark } ifelse } bind ] def /cmykGetRData } if composite? dup not { pop isCMYKSep? } if not { /endCapSepBc { /white? false store pop pop dup 0 eq { pop /white? 1 index 1 eq store setgray } { 1 eq { setcmykcolor } { setCustomColor } ifelse } ifelse % currentcmykcolor anyColor? endC? or blend? and { bFill } { handleOP } ifelse } bd /Bc { gsave setBSpace nColors 1 gt { blend? startC? and { bFill } { handleOP } ifelse } { endCapSepBc } ifelse grestore newpath } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { cData type /stringtype eq { linImg } { bFill } ifelse } { handleOP } ifelse grestore nColors 1 gt { getRData } if } bd /discardCMY { counttomark 4 add -3 roll pop pop pop } bd /testTopCC { 6 copy ccThrough? } bd /getCRamp { { ccDataProcs colorType 2 sub get exec } stopped pop blend? cDataLen 0 eq and { /cDataLen bDataLen store } if } bd /ccGetRData { /fCMYK? false store /startC? false store /endC? false store colorType 2 lt { /blend? false def } if blend? { getCRamp } { setCStop } ifelse blend? { /blend? cData 1 ne store blend? { cData dup type /stringtype ne { 1 exch sub /cData xs 0 } if pop } if } if } def /ccDataProcs [ /eCCBlend load { cBType 1 eq { tint1Data tint2Data /tint1Data xs /tint2Data xs } if 0 eq { /blend? false store pop } { mark 7 1 roll testTopCC { /blend? 1 index 1 ne store /startC? blend? store /endC? false store blend? not { cleartomark stop } if /cData tint1Data store setCDataLen setCustomColor pop stop } if cleartomark } ifelse 2 index 0 eq { /blend? false store } { mark 6 { 9 index } repeat testTopCC dup /blend? xs { /blend? 1 index 1 ne store /endC? blend? store /startC? false store blend? not { cleartomark stop } if /cData tint2Data store setCDataLen } if cleartomark } ifelse } bind ] def /ccGetRData } if load Adobe_blend_AI5_vars /getData 3 -1 roll put /setCDataLen { /cDataLen 0 cData dup type /stringtype eq { length exch } if pop store } bd /initSpotData { begin /name null def /tintImage null def /tintValue null def /spot_C null def /spot_M null def /spot_Y null def /spot_K null def end } bd /getRData { /colorType gMark store _compositeSpotDevice 0 ne { spotDict begin spot1 initSpotData spot2 initSpotData end /spotColor? colorType 2 eq colorType 3 eq or def } { /spotColor? false store } ifelse /blend? true store 0 0 0 0 setcmykcolor 100 div /rampPoint xs % (between 13 and 87%) 100 div /midPoint xs dup 0 eq { 2 } { dup 1 eq { 5 } { _compositeSpotDevice 0 ne { spotDict begin spot1 begin /name 3 index def /spot_K 4 index def /spot_Y 5 index def /spot_M 6 index def /spot_C 7 index def end end } if 7 } ifelse } ifelse /tmp exch def tmp index 100 div /endPoint xs _compositeSpotDevice 0 ne { tmp 2 add index 3 eq { /tmp tmp 4 add def tmp index dup spotDict begin spot1/name get ne { spot2 begin /name exch def /spot_K tmp 2 add index def /spot_Y tmp 3 add index def /spot_M tmp 4 add index def /spot_C tmp 5 add index def end } { pop } ifelse end } if } if /color? colorType 0 gt store colorType 3 eq { /tint2Data gMark store } if colorType 2 ge { /tint1Data gMark store } if _compositeSpotDevice 0 ne { spotDict begin colorType 2 ge { colorType 3 eq { spot2 begin /tintImage cBType 0 eq {tint2Data} {tint1Data} ifelse def name null eq {/name /Black def} if end } if spot1 begin /tintImage cBType 0 eq colorType 2 eq or {tint1Data} {tint2Data} ifelse def colorType 2 eq { name null eq { /name spot2/name get def spot2/name null put } if } { name null eq {/name /Black def} if } ifelse end } if end } if /cData gMark store setCDataLen colorType 0 gt { counttomark 4 add -3 roll /yeData xs /mgData xs /cyData xs } if blend? { /bDataLen cDataLen dup 0 eq color? and { [ cyData mgData yeData ] { dup type /stringtype eq { length exch pop exit } if pop } forall } if store bDataLen 0 eq { /bDataLen 1 store } if getData blend? { composite? cDataLen 0 eq and { /cDataLen bDataLen store } if } if } { setCStop } ifelse } bd /Bg { 0 0 0 0 setcmykcolor 6 { pop } repeat /blendLength xs pop pop pop /cBName xs /bRender xs bRender 2 ne { composite? not { _of setoverprint } if _eo {eoclip} {clip} ifelse _bn cBName 2 copy known { get mark exch aload pop /cBType xs /nColors xs mark exch aload pop 0 0 } if pop pop getRData cBType 0 eq { /linealBm } { bHi? { /pTState? nColors 2 gt store } if /doBlend /rdBlend load store /rdBm } ifelse } { inLine? not { mark mark } if /Bc dup { cleartomark mark } bd /nullProc } ifelse load /Bm xs } bd /linImg noImg { { newpath doRctBlend } } { { /doBlend color? composite? and { /bCImg } { /bwImage } ifelse load store 0 0 moveto tRectOK? composite? and { { mark 0 1 dtransform atan cvi 90 mod 0 eq 1 0 dtransform atan cvi 90 mod 0 eq } stopped { cleartomark } { and exch pop { newpath doRctBlend } { doBlend } ifelse } ifelse } { doBlend } ifelse } } ifelse bd /doRctBlend { gsave /sInc 1 store /nSamples bDataLen store /bInc 1 bDataLen div store /ubAxis 1 0 dtransform dUserSpace idtransform dup mul exch dup mul add sqrt store /pChange ubAxis 0 eq { 0 } { bDataLen ubAxis div } ifelse store pChange .5 gt noImg not and dup /optimize? xs { /nSamples ubAxis 2 div round cvi dup 1 le { pop 2 } if store /bInc 1 nSamples div store /sInc bDataLen 1 sub nSamples 1 sub div store } if 0 nSamples [ /dup cvx optimize? { /round cvx /cvi cvx } if /ndx /exch cvx /store cvx bCFun /rectfill where dup { exch pop _compositeSpotDevice 1 ne and } if { 0 0 bInc 1 /rectfill cvx } { 0 0 /moveto cvx bInc 0 /lineto cvx bInc 1 /lineto cvx 0 1 /lineto cvx /closepath cvx /_fill_ cvx } ifelse bInc 0 /translate cvx sInc /add cvx ] cvx bind repeat pop spotColor? {nsetcustomcolorend} if grestore } bd /rdPrep { /nSamples bDataLen dup 0 eq { pop 1 } if store /sInc -1 store /bAxis rampPoint endPoint sub store /bInc bAxis bDataLen div neg store /optimize? false store tRectOK? { /ubAxis bAxis 0 dtransform dUserSpace idtransform dup mul exch dup mul add sqrt 0 bAxis dtransform dUserSpace idtransform dup mul exch dup mul add sqrt 2 copy lt { exch } if pop store /pChange ubAxis 0 eq { 0 } { bDataLen ubAxis div } ifelse store pChange .5 gt noImg not and dup /optimize? xs { /nSamples ubAxis 2 div round cvi dup 1 le { pop 2 } if store /bInc bAxis nSamples div neg store /sInc bDataLen 1 sub nSamples 1 sub div neg store } if } if bHi? { /xBCInc xHi bAxis mul nSamples div store /yBCInc yHi bAxis mul nSamples div store } if } bd /rdBlend { newpath gsave rdPrep rampPoint bDataLen 1 sub nSamples [ /dup cvx optimize? { /round cvx /cvi cvx } if /ndx /exch cvx /store cvx bCFun 0 0 3 /index cvx 0 360 /arc cvx /_fill_ cvx /exch cvx bInc /add cvx /exch cvx sInc /add cvx bHi? { xBCInc yBCInc /translate cvx } if ] cvx bind repeat pop pop spotColor? {nsetcustomcolorend} if grestore pTState? { xHi bAxis mul yHi bAxis mul translate } if } bd /Bh { pop pop /pTState? false store 2 copy 0 ne exch 0 ne or dup /bHi? xs { /yHi xs /xHi xs 0 0 } if pop pop } bd /BD { inLine? not { ] nColors cBType ] _bn cBName 3 -1 roll put end } if } bd /Bn { 1 add dict dup nullString null put /_bn xs } bd /Bd { Adobe_blend_AI5_vars begin 3 -1 roll dup nullString eq dup { setSSave } if /inLine? exch def /cBName exch def /nColors exch def /cBType exch def } bd /Bb { sSave null eq { Adobe_blend_AI5_vars begin setSSave } if composite? { /_fill /fill load store } { /__fill /fill load store /_fill { _of true eq { currentgray 1 ne { __fill } if } { __fill } ifelse } def } ifelse /fill { } def } bd /BB { /cBType xs cleartomark cleartomark cBType dup bRender sSave dup type /savetype eq { restore 0 } if pop currentdict Adobe_blend_AI5_vars eq { end } if 2 ne exch 0 gt and { 2 eq { s } { S } ifelse } { pop newpath } ifelse } bd currentdict readonly pop end end defaultpacking setpacking %%EndResource %%BeginResource: procset Adobe_pattern_AI5 1.1 0 %%Title: (Adobe Illustrator (R) Version 5.0 Pattern Operators) %%Version: 1.1 0 %%CreationDate: (03/26/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_Illustrator_AI5 known not { userdict /Adobe_Illustrator_AI5 95 dict put } if userdict /Adobe_Illustrator_AI5 get begin /@ { } def /& { } def /dp { dup null eq { pop _dp 0 ne { 0 1 _dp 1 sub _dl mod { _da exch get 3 get } for _dp 1 sub _dl mod 1 add packedarray _da 0 get aload pop 8 -1 roll 5 -1 roll pop 4 1 roll definepattern pop } if } { _dp 0 ne _dp _dl mod 0 eq and { null dp } if 7 packedarray _da exch _dp _dl mod exch put _dp _dl mod _da 0 get 4 get 2 packedarray /_dp _dp 1 add def } ifelse } def /E { _ed begin dup 0 get type /arraytype ne { 0 { dup 1 add index type /arraytype eq { 1 add } { exit } ifelse } loop array astore } if /_dd exch def /_ury exch def /_urx exch def /_lly exch def /_llx exch def /_n exch def /_y 0 def /_dl 4 def /_dp 0 def /_da _dl array def 0 1 _dd length 1 sub { /_d exch _dd exch get def 0 2 _d length 2 sub { /_x exch def /_c _d _x get _ ne def /_r _d _x 1 add get cvlit def _r _ ne { _urx _llx sub _ury _lly sub [ 1 0 0 1 0 0 ] [ /save cvx _llx neg _lly neg /translate cvx _c { nc /begin cvx } if _r dup type /stringtype eq { cvx } { { exec } /forall cvx } ifelse _c { /end cvx } if /restore cvx ] cvx /_fn 12 _n length add string def _y _fn cvs pop /_y _y 1 add def _fn 12 _n putinterval _fn _c false dp _d exch _x 1 add exch put } if } for } for null dp _n _dd /_pd end xput } def /fc { _fm dup concatmatrix pop } def /p { /_fm exch ddef 9 -2 roll _pm translate fc 7 -2 roll _pm scale fc 5 -1 roll _pm rotate fc 4 -2 roll exch 0 ne { dup _pm rotate fc 1 -1 _pm scale fc neg _pm rotate fc } { pop } ifelse dup _pm rotate fc exch dup sin exch cos div 1 0 0 1 0 6 2 roll _pm astore fc neg _pm rotate fc _pd exch get /_fdd exch ddef /_pf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm patternfill } { pop fill } ifelse grestore pop } for pop } for restore newpath } ddef /_psf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm 9 copy 6 npop patternashow } { pop 6 copy 3 npop hvashow } ifelse grestore pop } for pop } for restore sw rmoveto } ddef /_pjsf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm 12 copy 6 npop patternawidthshow } { pop 9 copy 3 npop hvawidthshow } ifelse grestore pop } for pop } for restore swj rmoveto } ddef /_lp /none ddef } def /sc { _sm dup concatmatrix pop } def /P { /_sm exch ddef 9 -2 roll _pm translate sc 7 -2 roll _pm scale sc 5 -1 roll _pm rotate sc 4 -2 roll exch 0 ne { dup _pm rotate sc 1 -1 _pm scale sc neg _pm rotate sc } { pop } ifelse dup _pm rotate sc exch dup sin exch cos div 1 0 0 1 0 6 2 roll _pm astore sc neg _pm rotate sc _pd exch get /_sdd exch ddef /_ps { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm patternstroke } { pop stroke } ifelse grestore pop } for pop } for restore newpath } ddef /_pss { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm 10 copy 6 npop patternashowstroke } { pop 7 copy 3 npop ss } ifelse grestore pop } for pop } for restore pop sw rmoveto } ddef /_pjss { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm 13 copy 6 npop patternawidthshowstroke } { pop 10 copy 3 npop jss } ifelse grestore pop } for pop } for restore pop swj rmoveto } ddef /_lp /none ddef } def end userdict /Adobe_pattern_AI5 18 dict dup begin put /initialize { /definepattern where { pop } { begin begin Adobe_pattern_AI5 begin Adobe_pattern_AI5 { dup xcheck { bind } if pop pop } forall mark cachestatus 7 1 roll pop pop pop pop exch pop exch { { 10000 add dup 2 index gt { exit } if dup setcachelimit } loop } stopped cleartomark end end end Adobe_pattern_AI5 begin } ifelse } def /terminate { currentdict Adobe_pattern_AI5 eq { end } if } def errordict /nocurrentpoint { pop stop } put errordict /invalidaccess { pop stop } put /patternencoding 256 array def 0 1 255 { patternencoding exch ( ) 2 copy exch 0 exch put cvn put } for /definepattern { 17 dict begin /uniform exch def /cache exch def /key exch def /procarray exch def /mtx exch matrix invertmatrix def /height exch def /width exch def /ctm matrix currentmatrix def /ptm matrix def /str 32 string def /slice 9 dict def slice /s 1 put slice /q 256 procarray length div sqrt floor cvi put slice /b 0 put /FontBBox [ 0 0 0 0 ] def /FontMatrix mtx matrix copy def /Encoding patternencoding def /FontType 3 def /BuildChar { exch begin /setstrokeadjust where {pop true setstrokeadjust} if slice begin dup q dup mul mod s idiv /i exch def dup q dup mul mod s mod /j exch def q dup mul idiv procarray exch get /xl j width s div mul def /xg j 1 add width s div mul def /yl i height s div mul def /yg i 1 add height s div mul def uniform { 1 1 } { width 0 dtransform dup mul exch dup mul add sqrt dup 1 add exch div 0 height dtransform dup mul exch dup mul add sqrt dup 1 add exch div } ifelse width 0 cache { xl 4 index mul yl 4 index mul xg 6 index mul yg 6 index mul setcachedevice } { setcharwidth } ifelse gsave scale newpath xl yl moveto xg yl lineto xg yg lineto xl yg lineto closepath clip newpath end end exec grestore } def key currentdict definefont end } def /patterncachesize { gsave newpath 0 0 moveto width 0 lineto width height lineto 0 height lineto closepath patternmatrix setmatrix pathbbox exch ceiling 4 -1 roll floor sub 3 1 roll ceiling exch floor sub mul 1 add grestore } def /patterncachelimit { cachestatus 7 1 roll 6 npop 8 mul } def /patternpath { exch dup begin setfont ctm setmatrix concat slice exch /b exch slice /q get dup mul mul put FontMatrix concat uniform { width 0 dtransform round width div exch round width div exch 0 height dtransform round height div exch height div exch 0 0 transform round exch round exch ptm astore setmatrix } { ptm currentmatrix pop } ifelse { currentpoint } stopped not { 2 npop pathbbox true 4 index 3 index eq 4 index 3 index eq and { pop false { { 2 npop } { 3 npop true } { 7 npop true } { pop true } pathforall } stopped { 5 npop true } if } if { height div ceiling height mul 4 1 roll width div ceiling width mul 4 1 roll height div floor height mul 4 1 roll width div floor width mul 4 1 roll 2 index sub height div ceiling cvi exch 3 index sub width div ceiling cvi exch 4 2 roll moveto FontMatrix mtx invertmatrix dup dup 4 get exch 5 get rmoveto ptm ptm concatmatrix pop slice /s patterncachesize patterncachelimit div ceiling sqrt ceiling cvi dup slice /q get gt { pop slice /q get } if put 0 1 slice /s get dup mul 1 sub { slice /b get add gsave 0 1 str length 1 sub { str exch 2 index put } for pop dup { gsave ptm setmatrix 1 index str length idiv { str show } repeat 1 index str length mod str exch 0 exch getinterval show grestore 0 height rmoveto } repeat grestore } for 2 npop } { 4 npop } ifelse } if end } def /patternclip { _eo {eoclip} {clip} ifelse } def /patternstrokepath { strokepath } def /patternmatrix matrix def /patternfill { dup type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get } if gsave patternclip Adobe_pattern_AI5 /patternpath get exec grestore newpath } def /patternstroke { dup type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get } if gsave patternstrokepath true { { { newpath moveto } { lineto } { curveto } { closepath 3 copy Adobe_pattern_AI5 /patternfill get exec } pathforall 3 npop } stopped { 5 npop patternclip Adobe_pattern_AI5 /patternfill get exec } if } { patternclip Adobe_pattern_AI5 /patternfill get exec } ifelse grestore newpath } def /vpatternawidthshow { 6 1 roll /_hvay exch ddef /_hvax exch ddef /_hvwb exch ddef /_hvcy exch ddef /_hvcx exch ddef { dup cstring dup length 1 eq _charorientation 1 eq and { -90 rotate currentpoint _fontRotateAdjust add moveto gsave false charpath currentpoint 5 index 5 index 5 index Adobe_pattern_AI5 /patternfill get exec grestore _fontRotateAdjust sub moveto _hvwb eq { _hvcx _hvcy rmoveto } if _hvax _hvay rmoveto 90 rotate } { currentpoint _fontHeight sub _hvax sub 3 index _hvwb eq { _hvcx sub } if currentpoint exch 4 index stringwidth pop 2 div sub exch _fontAscent sub moveto gsave 2 index false charpath 6 index 6 index 6 index Adobe_pattern_AI5 /patternfill get exec grestore newpath moveto pop pop } ifelse } cforall 3 npop } def /hpatternawidthshow { { dup cstring exch gsave 3 index eq { 5 index 5 index rmoveto } if false charpath currentpoint 9 index 9 index 9 index Adobe_pattern_AI5 /patternfill get exec grestore newpath moveto 2 copy rmoveto } cforall 8 npop } def /patternashow { 0 0 0 6 3 roll patternawidthshow } def /patternawidthshow { 6 index type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get 7 1 roll } if _lineorientation 0 eq { hpatternawidthshow } { vpatternawidthshow } ifelse } def /vpatternawidthshowstroke { 7 1 roll 6 1 roll /_hvay exch ddef /_hvax exch ddef /_hvwb exch ddef /_hvcy exch ddef /_hvcx exch ddef { dup cstring dup length 1 eq _charorientation 1 eq and { -90 rotate currentpoint _fontRotateAdjust add moveto gsave false charpath currentpoint 3 index setmatrix 6 index 6 index 6 index Adobe_pattern_AI5 /patternstroke get exec grestore _fontRotateAdjust sub moveto _hvwb eq { _hvcx _hvcy rmoveto } if _hvax _hvay rmoveto 90 rotate } { currentpoint _fontHeight sub _hvax sub 3 index _hvwb eq { _hvcx sub } if currentpoint exch 4 index stringwidth pop 2 div sub exch _fontAscent sub moveto gsave 2 index false charpath 4 index setmatrix 7 index 7 index 7 index Adobe_pattern_AI5 /patternstroke get exec grestore newpath moveto pop pop } ifelse } cforall 4 npop } def /hpatternawidthshowstroke { 7 1 roll { dup cstring exch gsave 3 index eq { 5 index 5 index rmoveto } if false charpath currentpoint 7 index setmatrix 10 index 10 index 10 index Adobe_pattern_AI5 /patternstroke get exec grestore newpath moveto 2 copy rmoveto } cforall 9 npop } def /patternashowstroke { 0 0 0 7 3 roll patternawidthshowstroke } def /patternawidthshowstroke { 7 index type /dicttype eq { patternmatrix /patternmatrix get 8 1 roll } if _lineorientation 0 eq { hpatternawidthshowstroke } { vpatternawidthshowstroke } ifelse } def end setpacking %%EndResource %%EndProlog %%BeginSetup Adobe_level2_AI5 /initialize get exec Adobe_screens_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_typography_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_blend_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_pattern_AI5 /initialize get exec Adobe_ColorImage_AI6 /initialize get exec Adobe_Illustrator_AI5 /initialize get exec [ 39/quotesingle 96/grave 130/quotesinglbase 131/florin 132/quotedblbase 133/ellipsis 134/dagger 135/daggerdbl 136/circumflex 137/perthousand 138/Scaron 139/guilsinglleft 140/OE 145/quoteleft 146/quoteright 147/quotedblleft 148/quotedblright 149/bullet 150/endash 151/emdash 152/tilde 153/trademark 154/scaron 155/guilsinglright 156/oe 157/dotlessi 159/Ydieresis 164/currency 166/brokenbar 168/dieresis 169/copyright 170/ordfeminine 172/logicalnot 174/registered 175/macron 176/ring 177/plusminus 178/twosuperior 179/threesuperior 180/acute 181/mu 183/periodcentered 184/cedilla 185/onesuperior 186/ordmasculine 188/onequarter 189/onehalf 190/threequarters 192/Agrave 193/Aacute 194/Acircumflex 195/Atilde 196/Adieresis 197/Aring 198/AE 199/Ccedilla 200/Egrave 201/Eacute 202/Ecircumflex 203/Edieresis 204/Igrave 205/Iacute 206/Icircumflex 207/Idieresis 208/Eth 209/Ntilde 210/Ograve 211/Oacute 212/Ocircumflex 213/Otilde 214/Odieresis 215/multiply 216/Oslash 217/Ugrave 218/Uacute 219/Ucircumflex 220/Udieresis 221/Yacute 222/Thorn 223/germandbls 224/agrave 225/aacute 226/acircumflex 227/atilde 228/adieresis 229/aring 230/ae 231/ccedilla 232/egrave 233/eacute 234/ecircumflex 235/edieresis 236/igrave 237/iacute 238/icircumflex 239/idieresis 240/eth 241/ntilde 242/ograve 243/oacute 244/ocircumflex 245/otilde 246/odieresis 247/divide 248/oslash 249/ugrave 250/uacute 251/ucircumflex 252/udieresis 253/yacute 254/thorn 255/ydieresis TE %AI3_BeginEncoding: _Helvetica Helvetica [ /_Helvetica/Helvetica 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-Bold Helvetica-Bold [ /_Helvetica-Bold/Helvetica-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-Oblique Helvetica-Oblique [ /_Helvetica-Oblique/Helvetica-Oblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-BoldOblique Helvetica-BoldOblique [ /_Helvetica-BoldOblique/Helvetica-BoldOblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Roman Times-Roman [ /_Times-Roman/Times-Roman 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Bold Times-Bold [ /_Times-Bold/Times-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Italic Times-Italic [ /_Times-Italic/Times-Italic 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-BoldItalic Times-BoldItalic [ /_Times-BoldItalic/Times-BoldItalic 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier Courier [ /_Courier/Courier 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-Bold Courier-Bold [ /_Courier-Bold/Courier-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-Oblique Courier-Oblique [ /_Courier-Oblique/Courier-Oblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-BoldOblique Courier-BoldOblique [ /_Courier-BoldOblique/Courier-BoldOblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Symbol Symbol [ /_Symbol/Symbol 0 0 1 TZ %AI3_EndEncoding AdobeType %%EndSetup 1 XR u 0.000 0.000 0.000 0.000 k [] 0 d 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 140.0315 230.7402 m 212.0315 230.7402 L 212.0315 266.4567 L 140.0315 266.4567 L 140.0315 230.7402 L B U 0 To 1.0000 0.0000 0.0000 1.0000 162.1417 252.2835 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (NUA/\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 146.8346 238.1102 0 Tp TP /_Helvetica 11.7500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0.000 0.000 0.000 1.000 k (Sofia stack\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 J 1 j 175.7480 230.7402 m 175.7480 2.2677 L S U u 5.6693 198.9921 m 172.3465 198.9921 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 171.7795 201.2598 m 175.7480 198.9921 L 171.7795 197.2913 L 171.7795 201.2598 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 65.7638 202.9606 m 115.6535 202.9606 L 115.6535 214.2992 L 65.7638 214.2992 L 65.7638 202.9606 L F U 0 To 1.0000 0.0000 0.0000 1.0000 66.3307 205.7953 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (nua_handle\(\)\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 5.6693 163.2756 m 163.2756 163.2756 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 162.7087 165.5433 m 166.6772 163.2756 L 162.7087 161.5748 L 162.7087 165.5433 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 56.6929 166.6772 m 115.6535 166.6772 L 115.6535 178.0157 L 56.6929 178.0157 L 56.6929 166.6772 L F U 0 To 1.0000 0.0000 0.0000 1.0000 57.8268 169.5118 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (nua_message\(\)\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.000 k 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 166.6772 19.8425 m 184.8189 19.8425 L 184.8189 163.2756 L 166.6772 163.2756 L 166.6772 19.8425 L B U u 0.000 0.000 0.000 1.000 K 184.8189 154.2047 m 361.1339 154.2047 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 360.5669 156.4724 m 364.5354 154.2047 L 360.5669 152.5039 L 360.5669 156.4724 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 255.1181 157.6063 m 294.2362 157.6063 L 294.2362 168.9449 L 255.1181 168.9449 L 255.1181 157.6063 L F U 0 To 1.0000 0.0000 0.0000 1.0000 255.6850 161.0079 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (MESSAGE\r) Tx TO 0.000 0.000 0.000 1.000 K u [8 4 ] 0 d 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 364.5354 127.5591 m 187.6535 127.5591 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 188.2205 125.8583 m 184.2520 127.5591 L 188.2205 129.8268 L 188.2205 125.8583 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 266.4567 130.9606 m 281.7638 130.9606 L 281.7638 142.2992 L 266.4567 142.2992 L 266.4567 130.9606 L F U 0 To 1.0000 0.0000 0.0000 1.0000 267.5906 133.7953 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr [] 0 d 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (407\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 364.5354 37.9843 m 188.2205 37.9843 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 188.7874 35.7165 m 184.8189 37.9843 L 188.7874 39.6850 L 188.7874 35.7165 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 260.7874 41.3858 m 288.0000 41.3858 L 288.0000 52.7244 L 260.7874 52.7244 L 260.7874 41.3858 L F U 0 To 1.0000 0.0000 0.0000 1.0000 261.9213 44.2205 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (200 Ok\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 5.6693 91.8425 m 163.2756 91.8425 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 162.7087 94.1102 m 166.6772 91.8425 L 162.7087 90.1417 L 162.7087 94.1102 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 51.0236 95.2441 m 121.3228 95.2441 L 121.3228 106.5827 L 51.0236 106.5827 L 51.0236 95.2441 L F U 0 To 1.0000 0.0000 0.0000 1.0000 52.1575 98.0787 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (nua_authenticate\(\)\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 166.1102 118.4882 m 9.0709 118.4882 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 9.6378 116.7874 m 5.6693 118.4882 L 9.6378 120.7559 L 9.6378 116.7874 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 55.5591 121.8898 m 116.2205 121.8898 L 116.2205 133.2283 L 55.5591 133.2283 L 55.5591 121.8898 L F U 0 To 1.0000 0.0000 0.0000 1.0000 56.6929 125.2913 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (nua_r_message\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 184.8189 74.2677 m 361.1339 74.2677 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 360.5669 75.9685 m 364.5354 74.2677 L 360.5669 72.0000 L 360.5669 75.9685 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 255.1181 77.6693 m 294.2362 77.6693 L 294.2362 89.0079 L 255.1181 89.0079 L 255.1181 77.6693 L F U 0 To 1.0000 0.0000 0.0000 1.0000 255.6850 80.5039 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (MESSAGE\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 166.1102 55.5591 m 9.0709 55.5591 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 9.6378 53.8583 m 5.6693 55.5591 L 9.6378 57.8268 L 9.6378 53.8583 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 49.8898 58.9606 m 121.8898 58.9606 L 121.8898 70.8661 L 49.8898 70.8661 L 49.8898 58.9606 L F U 0 To 1.0000 0.0000 0.0000 1.0000 51.0236 61.7953 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (nua_r_authenticate\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 175.7480 19.8425 m 9.0709 19.8425 L S U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 9.6378 18.1417 m 5.6693 19.8425 L 9.6378 22.1102 L 9.6378 18.1417 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 60.0945 23.2441 m 120.7559 23.2441 L 120.7559 34.5827 L 60.0945 34.5827 L 60.0945 23.2441 L F U 0 To 1.0000 0.0000 0.0000 1.0000 61.2283 26.0787 0 Tp TP /_Helvetica 7.7500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (nua_r_message\r) Tx TO 0.000 0.000 0.000 1.000 K %%PageTrailer gsave annotatepage grestore showpage %%Trailer Adobe_Illustrator_AI5 /terminate get exec Adobe_pattern_AI5 /terminate get exec Adobe_blend_AI5 /terminate get exec Adobe_ColorImage_AI6 /terminate get exec Adobe_typography_AI5 /terminate get exec Adobe_screens_AI5 /terminate get exec Adobe_level2_AI5 /terminate get exec %%EOF II*ff:(@33GG\\pp""11@@OO^^nn}}""++33<`]Oy`F݄v ($h(",(1eH7a}9\s]v z=e#L6E:)eKNi啳Av\%Zjt1Fh&)Qi䐥}u>8FFUeg8h6x(ll TnD&*i9-ovUCiZa hj7kE@@ DPB >Q"-^ȰbF=~RH%McUti"L4SęSN=}i#MaYTMM>UTKzUV]FZp#Қ1]LzT,ڲ2U\ur{a^}`… F̓obƍ?&dʕJ66Lʘ-ɞEF:5ڱ];lڵm?6}[nOs\+gȿG~R(iɝ?^ۜ#,jfoF/x?zӷ4ٷ?{Ьk8f ,|ˈB"0;*pB %\kC5p C,KDS?s1FqFoFwLtH8$482J)J+Đ&r%-C|2MTM7bX;M 83= KA%PCK@O0cJ?dMG+V̴.4KD2$:UDTU*J[WcռYk5W]? <0… :|1ĉ+Z1ƍ;z2ȑ$!(rɔ,[| 3̙ W҄iΝ<{ 2gƕ9m (Ԩ} 5ԩ-6%Ht Sz튴Ud˚=VkZc׺} 7ȶrҭ7޽a~mX| >߂EȪ1VǍO옡`Ĝ;{~xifȘ+ۥ|ykd[~]vfٴkێyoۼ{ޝċ_n<=3=:Iҫ[N܏w>[WH'e_ >NȠ{ Ra>]aa"R&8*".826f9^U8[ވC68_XKFɤdZ^eHYQFd襍9&}9liz*~P((Pu&(t6 irFJoGjmV'Fdx騝ZCisj秦ZY(ړ?(dV˙Je. mpFK}V-emv n߆kc*Y$9+]z;䰲zD t2;/G vU ?SO_㶯8'zIu.bzA>ʋ\o0ϜEr;2͚ɬs3_,d<$|s ۔佾n*SSM ]%d˾٫{}] ~lk3@(o(P;A¹o33S/>jC\B ST>P\E]JFkFpqGtGHfRrI&\I( H)R+R-Һ/3**4LTsMdM1݄s-*s#OO&<436mRC 1ERHCLG*U>K0+WѻԐhE5Nj1[ou^V`55w=64'uYhvZj]Z/vDVJm7q1\s ]u۝]wU ^y-^{J_~÷_ x`% FxafxSO1}XHNzt=ESY8A=4ӘEpdaqTHěgD˕@zo0eC\FziMk6K/ܮz:j6lV9ĚVi{JlUn " ߖp ^r3|s(G rCotK/ qS't['ucP-ktcg'8߇̘ፇԢ'uE>{Ƿ>iNYY~|9'{\S Ҕpm nóp-}bl"RJocbvD,Bd+"Qx`cF.)B,#.:\yo#Y"0$"HGK`jT'%-xdFVDoQ&镭k OK9NBFoB.5K_ $8wLd&S],9 Sp p "Lp!ÆB(q"E*q#ǎ? )r$ɒ&O,ʔ._Œ)s&M[6ĹPgM<#)t(ѢF!R~.*TVժԭAn,ٲfϊӄjVZ+\t"/߾~*lJfݹfZ֬N ^wάy3猔!G2ˣONz5EnYÎ-{lyiν)m{fďn9Οި:Ng{};n 0 1 !"#$%&'()*+,-./Root EntryFP B@VisioDocument#SummaryInformation(2DocumentSummaryInformation8Visio (TM) Drawing #l "VRd !fffMMM333$ $ U8@ TD Arial@NMonotype Sorts@m Wingd NtSymbol5T?? Y@-1U J:DT1EW-hPT8*  .U_b a酸0zGz?@3CfRbU|||%U P } |KpG/Y&4Y$? v AfY&,,' /Dq&z&} | |y  }{})} ?2  | | ||||*|||E-?k4'-'CECE,'*CECECE-?H>?:`}'CEUCECECECEUCECE- O4F2AJY;; AnVnVAbGTfY R_R__ `#f:/lb6p`fW /l /l  Y?5?(\ #!+ | tFf-|J-|-|-wG QUo "OM`EtoA _3=OOOaOsO@O??O?7ܻuR? sU/-O%7I[mRf J+ K5   . ||i| d' 0/UKiR?d?v4Gzt2#&Us s s s) -0jӯY/ƛ!3)󿵶1D///Q+p)?HdYc4AkǿٿYfU|%1I߀O]-(fp ɻ %-=Y[:!#:4)A/q//YkϹ/p?2 Sπ'9}Fɇ7%õ8@\n1$u  (:L^p)BH>ZՔU \ n4!'4#U2q ?/%&k/%&`,`,`',ѓ4?|QԞQyٓA G $z Z$bp6q /#3=/Uq@T0'vr@1N!T0;UOauADV=煤{2r H+"P)Ҳ$2@1@1B,$1//cAm/ߙ߫BVVj /Q?c?u4D?U0O贁 NkRC6$SfMea5t(O"?2RO}q19!S _2_D_"3Htr+*a__//5o2DV õoa`oo1 I+< g4`\\esprn002\HER1F5B1S odWX+'?LetterO_b PRIV0|'r\KhC]>w!tuy //-/?/Q/c/u////////??)?;?M1E%winspool\\esprn002\HER1F5B1IP_172.21?.36.10UFDfP h-RTUUUA@ ?I?a 3h AeqYk Hu_ Q? #,BDrag between shapes to indicate a flow offormation or control.mb?sߛ⿻xw?t? 8HD    3h <>T$  ;MBRAU@?N ?AP6 Ju `u buU  -J ">ۀJuM` Zue"JD4WAQ @%UI>J[@hK'F"U/g%'_-/g JQ#5 L"V &6 霑c ?@IW0?@q`0U>U5Q?!9[a2f`rd}b0@3&/0`A.=@2M @J2uF.3B B$fH2&M+3Q(-DT! @6[Dн8P$?J 3tNsWB Ld!%6 MB##0O贁Nk?<$2%@@PR%|#xQ}T5 B`7Copyright 1999 Visio Corporation. All Rs reserved.J`P_SCPchm!#22776G#2r5ofP"JSfunq&^(E9 Yr[xQ4 0UChange Arrow?head..PVcthe ae siz`n`tyle for`is connectorP1`Bb)WlJhUd>5 yG|(AJ*C<4bZw"M (3,rx srA iVohot'd1dxB3d+=-C2U낥@6f 32`_D/@>W4C)rp -3TqC@@JQ\^E? v!3?|@ 2Pa@0pqB;uK`u`WE @ǗHXC1 aVHl'-d! !Oya HE_9bFT w~#DF . B LW ]Maku]@+k]/ao fPUl4,"H$ @Y,b'@ D OA- U7U2@ [7ERH<( U2E 7 R(n S >@? =RD\KOi{ UP?V]U$5@*P8FDTey  ahm qTP^UI"H$ @IY,b'@? ?I*M_q2?p^qu2`"ua )e* L4F!`F! a ! !H!$'$a'$!'!(!'!(!'!(!'!('$!'!(!'!(!'!(!'!(F!#qP!!!a!!!!1E!!!!!!A!!!!e%!AF!OOO!%0i!|a)] 5 @*`$T^?U/Q%V'/ bl!0qUQ5Em/#! `HR-R.-X! f*goo# qT/Aw q5i{o}:52Ar *0ANUA/ Sofia? stack"y%__(_:_L_[_ T UP-DT!f-qu `u `buF `u y]@"qpsvp{ɔ߁_mo b_Q#UU@$lނvl̩6ealFdEkcooU%k*Yu]=vsH!X"a,53!:5߁ׅ!,!:5io[E⛺UV@A̮?ZJ3&^LJa 圭f^@Ic?@q*laaQ #la!u;`@82P(<䃹 ϧ6ay%0,>iaa yCd^c_u_u82$UUV & &C5Xnua_handle()"ye8"4FXj|ώT`"πRc"P1CUaa܅τ#!ӿ +8J\nU!3EWomessag߁W_//_@"U %vU/ZmF1oCoUoyoooo{heV F7OR=_9[_m__k_O .@01AEhO,UV!4-5Ep[ Dstm \ a;U@Eq9x3@pVVub՛@mqas#(iy; AWi{ڍIA //0/B/T/D~w/??//"huQ hu$f$f/mr5yooIoooo9u!C@@kW0nĀˀ5ߡJاVbr 䍾#5GFXj4/ϣNŏ׏ 1Cfx///QmMESSAGE8\njGyOOMtzץT&R\]o;|Ru6J\nw98'5$G Ʌ#0O贁NkCRXṡTB! dvϚϬϾπ);Mҟ䟂.407 ߱n=ȯX#)G! fE 0 xfUl4,"H$ @Y,bK'@  D!UA-3R7;Ul4,  ! AJ-37A_*<N@$ X! KRVg q6uH<( H<( _*<NEt *" RVg< 7q {th * g"4pFX(?@( ϫ@P , :TR q&^ !B< 2b>MOp܇B| U$@'/ xRNjx)l' W1 Z=`2 eV?  NED𼯣 D"C="՜.+,D՜.+,@HP\h t   PagesMastersPage-1Directed line 18_VPID_ALTERNATENAMES_VPID_PREVIEWS?_PID_LINKBASE A Oh+'02HPdp| rinnerahSIP outgoing callG2EqWRSt EMF1 l@@VISIODrawing% %   &%   '% V0999% ( % (  Rp Arialdv% Rp Arial>t,Uw@*w<wd>\Hd>1Uw*wЌ\H\H,Uw%wx\Hx>ЌtUw(%w\xd>\Hd>\Hd>#` @xdv% %  %   TdAALTNUA/   T,AA LdSofia stack2     % &%  W$qq% ( % Rp  Arialdv% %  %  % &%  W$% ( %  '% % V,% % (   '% % V08888% % (  Rp Arialkdv% %  %   T: AA:  Ldnua_handle() % &%  W$UUUU% ( %  '% % V,RYRUYR% % (   '% % V0)<O)OO<)<)O% % (  Rp Arialt,Uw@*w<w8\H8Ќ\H\H,Uw%wx\Hx> o>tUw(%w\x8\H8\H o>#` @xdv% %  %   T*=LAA*J Lhnua_message()  % &%   '% V0U RR R UUR% ( % (  &%  W$ e?e e?e% ( %  '% % V,>bEi>bEe>i>b% % (   '% % V0K___KK_% % (  Rp Arialt,Uw@*w<w8\H8Ќ\H\H,Uw%wx\Hx>8o>tUw(%w\x8\H8\H8o>#` @xdv% %  %   TxM\AAZL\MESSAGE  % &%  W$EE% ( %  '% % V,  % % (   '% % V0{{{% % (  Rp Arialt,Uw@*w<w8\H8Ќ\H\H,Uw%wx\Hx> o>tUw(%w\x8\H8\H o>#` @xdv% %  %   T`|AALT407 % &%  W$2E2E22% ( %  '% % V, .66 2.6% % (  ( (  '% % V0,,,,% % (  Rp Arialt,Uw@*w<w8\H8Ќ\H\H,Uw%wx\Hx>8o>tUw(%w\x8\H8\H8o>#` @xdv% % (  %   Tp)AA'LX200 Ok  % &%  W$% ( %  '% % V,% % (   '% % V0% % (  Rp Arialt,Uw@*w<w8\H8Ќ\H\H,Uw%wx\Hx>`tUw(%w\x8\H8\H`#` @xdv% % (  %   T!AA!Lpnua_authenticate() % &%  W$% ( %  '% % V,% % (   '% % V0''''% % (  Rp Arialt,Uw@*w<w8\H8Ќ\H\H,Uw%wx\Hx>H>tUw(%w\x8\H8\HH>#` @xdv% % (  %   T(AA( Lhnua_r_message  % &%  W$ ? ?% ( %  '% % V,>E>E>>% % (   '% % V0% % (  Rp Arialt,Uw@*w<w8\H8Ќ\H\H,Uw%wx\Hx> o>tUw(%w\x8\H8\H o>#` @xdv% % (  %   TxAAL\MESSAGE  % &%  W$% ( %  '% % V,% % (   '% % V0    % % (  Rp Arialt,Uw@*w<w8\H8Ќ\H\H,Uw%wx\Hx>`tUw(%w\x8\H8\H`#` @xdv% % (  %   T AALpnua_r_authenticate % &%  W$RRRR% ( %  '% % V,NUURNU% % (   '% % V0/8L/LL8/8/L% % (  Rp Arialt,Uw@*w<w8\H8Ќ\H\H,Uw%wx\Hx>8o>tUw(%w\x8\H8\H8o>#` @xdv% % (  %   T19HAA1F Lhnua_r_message  % VisioInformation"sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/docs/pictures/autotools.eps000066400000000000000000017175101223300710500251160ustar00rootroot000000000000006BVB\%!PS-Adobe-3.0 EPSF-3.0 %%Creator: ImageMark Software Labs %%For: () () %%Title: V:\work\rinnerah\sofia\autotools.eps %%CreationDate: () () %%BoundingBox: 0 0 453 436 %%DocumentProcessColors: Black %%ColorUsage:Color %%DocumentFonts: Helvetica %%+Helvetica-Bold %%+Helvetica-Oblique %%+Helvetica-BoldOblique %%+Times-Roman %%+Times-Bold %%+Times-Italic %%+Times-BoldItalic %%+Courier %%+Courier-Bold %%+Courier-Oblique %%+Courier-BoldOblique %%+Symbol %%DocumentSuppliedResources: procset Adobe_level2_AI5 1.2 0 %%+ procset Adobe_screens_AI5 1.0 0 %%+ procset Adobe_typography_AI5 1.0 0 %%+ procset Adobe_ColorImage_AI6 1.1 0 %%+ procset Adobe_blend_AI5 1.0 0 %%+ procset Adobe_pattern_AI5 1.0 0 %%+ procset Adobe_Illustrator_AI5 1.0 0 %AI5_FileFormat 3.0 %AI3_ColorUsage: Color %AI3_TemplateBox: 0 0 453 436 %AI3_TileBox: 0 0 453 436 %AI3_DocumentPreview: None %%Template: %%PageOrigin:0.0000 0.0000 %AI7_GridSettings: 72 8 72 8 1 0 0.8 0.8 0.8 0.9 0.9 0.9 %%EndComments %%BeginProlog %%BeginResource: procset Adobe_level2_AI5 1.2 0 %%Title: (Adobe Illustrator (R) Version 5.0 Level 2 Emulation) %%Version: 1.2 0 %%CreationDate: (04/10/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /Adobe_level2_AI5 25 dict dup begin put /packedarray where not { userdict begin /packedarray { array astore readonly } bind def /setpacking /pop load def /currentpacking false def end 0 } if pop userdict /defaultpacking currentpacking put true setpacking /initialize { Adobe_level2_AI5 begin } bind def /terminate { currentdict Adobe_level2_AI5 eq { end } if } bind def mark /setcustomcolor where not { /findcmykcustomcolor { 0 6 packedarray } bind def /findrgbcustomcolor { 1 5 packedarray } bind def /setcustomcolor { exch aload pop 0 eq { pop 4 { 4 index mul 4 1 roll } repeat 5 -1 roll pop setcmykcolor } { pop 3 { 1 exch sub 3 index mul 1 exch sub 3 1 roll } repeat 4 -1 roll pop setrgbcolor } ifelse } def } if /gt38? mark {version cvr cvx exec} stopped {cleartomark true} {38 gt exch pop} ifelse def userdict /deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt put userdict /level2? systemdict /languagelevel known dup { pop systemdict /languagelevel get 2 ge } if put /level2ScreenFreq { begin 60 HalftoneType 1 eq { pop Frequency } if HalftoneType 2 eq { pop GrayFrequency } if HalftoneType 5 eq { pop Default level2ScreenFreq } if end } bind def userdict /currentScreenFreq level2? {currenthalftone level2ScreenFreq} {currentscreen pop pop} ifelse put level2? not { /setcmykcolor where not { /setcmykcolor { exch .11 mul add exch .59 mul add exch .3 mul add 1 exch sub setgray } def } if /currentcmykcolor where not { /currentcmykcolor { 0 0 0 1 currentgray sub } def } if /setoverprint where not { /setoverprint /pop load def } if /selectfont where not { /selectfont { exch findfont exch dup type /arraytype eq { makefont } { scalefont } ifelse setfont } bind def } if /cshow where not { /cshow { [ 0 0 5 -1 roll aload pop ] cvx bind forall } bind def } if } if cleartomark /anyColor? { add add add 0 ne } bind def /testColor { gsave setcmykcolor currentcmykcolor grestore } bind def /testCMYKColorThrough { testColor anyColor? } bind def userdict /composite? level2? { gsave 1 1 1 1 setcmykcolor currentcmykcolor grestore add add add 4 eq } { 1 0 0 0 testCMYKColorThrough 0 1 0 0 testCMYKColorThrough 0 0 1 0 testCMYKColorThrough 0 0 0 1 testCMYKColorThrough and and and } ifelse put composite? not { userdict begin gsave /cyan? 1 0 0 0 testCMYKColorThrough def /magenta? 0 1 0 0 testCMYKColorThrough def /yellow? 0 0 1 0 testCMYKColorThrough def /black? 0 0 0 1 testCMYKColorThrough def grestore /isCMYKSep? cyan? magenta? yellow? black? or or or def /customColor? isCMYKSep? not def end } if end defaultpacking setpacking %%EndResource %%BeginResource: procset Adobe_typography_AI5 1.0 1 %%Title: (Typography Operators) %%Version: 1.0 %%CreationDate:(03/26/93) () %%Copyright: ((C) 1987-1993 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_typography_AI5 54 dict dup begin put /initialize { begin begin Adobe_typography_AI5 begin Adobe_typography_AI5 { dup xcheck { bind } if pop pop } forall end end end Adobe_typography_AI5 begin } def /terminate { currentdict Adobe_typography_AI5 eq { end } if } def /modifyEncoding { /_tempEncode exch ddef /_pntr 0 ddef { counttomark -1 roll dup type dup /marktype eq { pop pop exit } { /nametype eq { _tempEncode /_pntr dup load dup 3 1 roll 1 add ddef 3 -1 roll put } { /_pntr exch ddef } ifelse } ifelse } loop _tempEncode } def /TE { StandardEncoding 256 array copy modifyEncoding /_nativeEncoding exch def } def % /TZ { dup type /arraytype eq { /_wv exch def } { /_wv 0 def } ifelse /_useNativeEncoding exch def pop pop findfont _wv type /arraytype eq { _wv makeblendedfont } if dup length 2 add dict begin mark exch { 1 index /FID ne { def } if cleartomark mark } forall pop /FontName exch def counttomark 0 eq { 1 _useNativeEncoding eq { /Encoding _nativeEncoding def } if cleartomark } { /Encoding load 256 array copy modifyEncoding /Encoding exch def } ifelse FontName currentdict end definefont pop } def /tr { _ax _ay 3 2 roll } def /trj { _cx _cy _sp _ax _ay 6 5 roll } def /a0 { /Tx { dup currentpoint 3 2 roll tr _psf newpath moveto tr _ctm _pss } ddef /Tj { dup currentpoint 3 2 roll trj _pjsf newpath moveto trj _ctm _pjss } ddef } def /a1 { /Tx { dup currentpoint 4 2 roll gsave dup currentpoint 3 2 roll tr _psf newpath moveto tr _ctm _pss grestore 3 1 roll moveto tr sp } ddef /Tj { dup currentpoint 4 2 roll gsave dup currentpoint 3 2 roll trj _pjsf newpath moveto trj _ctm _pjss grestore 3 1 roll moveto tr jsp } ddef } def /e0 { /Tx { tr _psf } ddef /Tj { trj _pjsf } ddef } def /e1 { /Tx { dup currentpoint 4 2 roll gsave tr _psf grestore 3 1 roll moveto tr sp } ddef /Tj { dup currentpoint 4 2 roll gsave trj _pjsf grestore 3 1 roll moveto tr jsp } ddef } def /i0 { /Tx { tr sp } ddef /Tj { trj jsp } ddef } def /i1 { W N } def /o0 { /Tx { tr sw rmoveto } ddef /Tj { trj swj rmoveto } ddef } def /r0 { /Tx { tr _ctm _pss } ddef /Tj { trj _ctm _pjss } ddef } def /r1 { /Tx { dup currentpoint 4 2 roll currentpoint gsave newpath moveto tr _ctm _pss grestore 3 1 roll moveto tr sp } ddef /Tj { dup currentpoint 4 2 roll currentpoint gsave newpath moveto trj _ctm _pjss grestore 3 1 roll moveto tr jsp } ddef } def /To { pop _ctm currentmatrix pop } def /TO { iTe _ctm setmatrix newpath } def /Tp { pop _tm astore pop _ctm setmatrix _tDict begin /W { } def /h { } def } def /TP { end iTm 0 0 moveto } def /Tr { _render 3 le { currentpoint newpath moveto } if dup 8 eq { pop 0 } { dup 9 eq { pop 1 } if } ifelse dup /_render exch ddef _renderStart exch get load exec } def /iTm { _ctm setmatrix _tm concat 0 _rise translate _hs 1 scale } def /Tm { _tm astore pop iTm 0 0 moveto } def /Td { _mtx translate _tm _tm concatmatrix pop iTm 0 0 moveto } def /iTe { _render -1 eq { } { _renderEnd _render get dup null ne { load exec } { pop } ifelse } ifelse /_render -1 ddef } def /Ta { pop } def /Tf { dup 1000 div /_fScl exch ddef % selectfont } def /Tl { pop 0 exch _leading astore pop } def /Tt { pop } def /TW { 3 npop } def /Tw { /_cx exch ddef } def /TC { 3 npop } def /Tc { /_ax exch ddef } def /Ts { /_rise exch ddef currentpoint iTm moveto } def /Ti { 3 npop } def /Tz { 100 div /_hs exch ddef iTm } def /TA { pop } def /Tq { pop } def /Th { pop pop pop pop pop } def /TX { pop } def /Tk { exch pop _fScl mul neg 0 rmoveto } def /TK { 2 npop } def /T* { _leading aload pop neg Td } def /T*- { _leading aload pop Td } def /T- { _hyphen Tx } def /T+ { } def /TR { _ctm currentmatrix pop _tm astore pop iTm 0 0 moveto } def /TS { currentfont 3 1 roll /_Symbol_ _fScl 1000 mul selectfont 0 eq { Tx } { Tj } ifelse setfont } def /Xb { pop pop } def /Tb /Xb load def /Xe { pop pop pop pop } def /Te /Xe load def /XB { } def /TB /XB load def currentdict readonly pop end setpacking %%EndResource %%BeginResource: procset Adobe_screens_AI5 1.2 0 %%Title: (Adobe Illustrator (R) Version 5.0 Custom Halftone Screens ProcSet) %%Version: 1.2 0 %%CreationDate: (03/24/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking systemdict begin userdict /Adobe_screens_AI5 15 dict dup begin put /initialize { Adobe_screens_AI5 begin /screenid deviceDPI 600 gt composite? not or { -1 } { deviceDPI currentScreenFreq dup dup 60 ge exch 150 le and deviceDPI 300 le and { pop 60 } if div 1.41421 div 0.5 add cvi } ifelse def 2 screenid eq { /customsize 16 def /customdata /customdata2 def setcustomscreen } if 3 screenid eq { /customsize 24 def /customdata /customdata3 def setcustomscreen } if 4 screenid eq { /customsize 16 def /customdata /customdata4 def setcustomscreen } if 5 screenid eq { /customsize 20 def /customdata /customdata5 def setcustomscreen } if 6 screenid eq { /customsize 24 def /customdata /customdata6 def setcustomscreen } if 7 screenid eq { /customsize 28 def /customdata /customdata7 def setcustomscreen } if 8 screenid eq { /customsize 16 def /customdata /customdata8 def setcustomscreen } if } def /terminate { currentdict Adobe_screens_AI5 eq { end } if } def /setcustomscreen { deviceDPI customsize div 0 { 1 add 2 div customsize mul cvi exch 1 add 2 div customsize mul cvi exch customsize mul add customdata load exch get 256 div } setscreen } def /customdata2 28 28 mul string def currentfile customdata2 readhexstring 4180E8694988E2634382EA6B4B8AE061A01939C8A81737C2A21B3BCAAA1636C0 F8795998F6775796FA7B5B9AF57656952ED8B80727D6B60F2FDABA0626D5B50E 4E8DE6674786EE6F4F8EE5664685ED6EAD1434C6A61F3FCEAE1232C5A51E3ECD F3745493FE7F5F9EF1725291FD7E5E9D24D3B30C2CDEBE0222D1B10A2ADDBD04 4483EB6C4C8BE1624281E96A4A89E364A31C3CCBAB1535C1A11A3AC9A91838C3 FB7C5C9BF4755594F97A5A99F778589730DBBB0525D4B40D2DD9B90828D7B710 508FE4654584EC6D4D8CE7684887EF70AF1131C4A41D3DCCAC1333C7A72040CF F0715190FC7D5D9CF2735392FF80609F21D0B00929DCBC0323D2B20B2BDFBF01 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata3 28 28 mul string def currentfile customdata3 readhexstring 011DC7F5E73D0421CBF3E43A021EC8F6E83E0522CCF2E43A2B648BC4A0762F68 8AC39E732C658CC5A177306989C29D72D5B6521A6192D9B55219608FD6B6531B 6193DAB451185F8FFCEE440C28D2FCED430B27D1FDEF450C29D3FBEC420A26D0 BEA77D366F83BCA77C356E87BFA87E377082BBA67B346D86145B99E0AE4A1259 98DFB14E155C9AE1AD4A115897DEB04D0623CDF4E63C0420CAF8EA400723CDF4 E53B031FC9F7E93F316988C19F752E678EC6A378326A88C09F742D668DC6A278 DBB350175E91D8B8551C6395DCB24F165D90D7B7541C6294FAEC420925CFFFF1 470E2BD5F9EB410824CEFEF0460D2AD4BAA57A336C85BEAA80397180B9A47933 6B84BDA97F387181105797DDAF4C145A9CE3AB480F5696DDAE4B13599BE2AC49 021EC8F6E83E0522CCF2E43A011DC7F5E73D0421CBF3E43A2C658CC5A1773069 89C29D722B648BC4A0762F688AC39E73D6B6531B6193DAB451185F8FD5B6521A 6192D9B55219608FFDEF450C29D3FBEC420A26D0FCEE440C28D2FCED430B27D1 BFA87E377082BBA67B346D86BEA77D366F83BCA77C356E87155C9AE1AD4A1158 97DEB04D145B99E0AE4A125998DFB14E0723CDF4E53B031FC9F7E93F0623CDF4 E63C0420CAF8EA40326A88C09F742D668DC6A278316988C19F752E678EC6A378 DCB24F165D90D7B7541C6294DBB350175E91D8B8551C6395F9EB410824CEFEF0 460D2AD4FAEC420925CFFFF1470E2BD5B9A479336B84BDA97F387181BAA57A33 6C85BEAA803971800F5696DDAE4B13599BE2AC49105797DDAF4C145A9CE3AB48 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata4 28 28 mul string def currentfile customdata4 readhexstring 1139B8E0FAD2531B133BBAE2F8D05119417180A6AE9A7B4B437382A5AD987949 C08867272F6F92CAC28A66262E6E90C8E8DE5F070F37B6F2EADD5E060E36B5F0 FED6571F173FBEE6FDD5561E163EBDE5AB9E7F4F477786A1A99D7E4E467685A3 2C6C96CEC68E62222A6A95CDC58D64240C34B3F6EED95A020A32B1F5EDDB5C04 143CBBE3F9D1521A123AB9E1FBD3541C447483A4AC997A4A427281A7AF9B7C4C C38B65252D6D91C9C1896828307093CBEBDC5D050D35B4F1E9DF60081038B7F3 FCD4551D153DBCE4FFD758201840BFE7A89C7D4D457584A2AA9F8050487887A0 296994CCC48C63232B6B97CFC78F61210931B0F4ECDA5B030B33B2F7EFD85901 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata5 28 28 mul string def currentfile customdata5 readhexstring 010B34C3EBFCF7CE3F16020C35C4EDFBF6CD3E15102552A4D6EADDB5632B1126 54A5D5EADCB3622A3958768499C19E8C7C5E3A59778498C19D8B7B5DC8A99370 47334C7587AFC9AA936F46324B7485AEF1E5BC6B1E0A2351A3D8F2E4BC6A1E09 2351A2D7FFF9D14219050F38C6EFFEF9D04118040E37C6EFE8E0B7662D142856 A8D3E7DFB7652D132856A7D4BF9C8E7F603D5B7A8195BE9A8E7E603C5B798297 314A7389B2CCAD906D442F497289B1CBAC926E4508214FA1DBF4E2B9671B0720 4EA0DAF4E3BA691C030D36C5EDFBF6CD3F16010C34C3ECFDF8CF4017122654A6 D4E9DDB4622A112553A5D6EBDEB5642C3B59788397C09C8B7C5D3A58778599C2 9E8C7D5FCAAB926E46314B7486AFC8AA947048334D7587B0F2E4BB691D082250 A1D8F1E6BD6B1F0A2452A3D9FDF8CF4118030E36C5EEFFFAD1421A050F38C7F0 E6DFB6642C132755A7D3E8E1B8662E152957A8D2BE9A8D7E5F3B5A798296BF9B 8F80613D5C7B80952F487188B1CAAC916D443049728AB3CCAE906C43061F4D9F DAF3E2BA681C07214FA0DBF5E1B8671A00000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata6 28 28 mul string def currentfile customdata6 readhexstring 081A44B6E0F2FDECC150250C091B45B6E1F3FCEBC04F240C1D336199C7D8DCD3 A56C37221E33619AC8D7DBD2A46B36214864798091AEB1958C7E694C49657A81 90ADB0948B7D684BB99D8475593C405C7888A1BEBA9E8574583B3F5B7888A0BD E4CBAA712E1215326098CFE8E4CCA9712D1114315F97CEE7F5F1C6552B040719 43B5DFFAF6F0C6542A03061842B4DEF9FFEDC352270E0B1C47B8E3F4FEECC251 260D0A1C46B7E2F4DAD5A76E39232035639CCAD5D9D4A66D38231F34629BC9D6 AF938E806A4E4A677C838FABAE928D7F694D4A667B828FAC3E5A778AA3BFBC9F 8772563A3D597689A2BEBB9F8673573A14305E97D1EAE6CDA76F2B0F132F5D96 D0E9E5CDA8702C10051742B3DDFCF8EEC4522801041641B2DDFBF7EFC5532902 091B45B6E1F3FCEBC04F240C081A44B6E0F2FDECC150250C1E33619AC8D7DBD2 A46B36211D336199C7D8DCD3A56C372249657A8190ADB0948B7D684B48647980 91AEB1958C7E694CBA9E8574583B3F5B7888A0BDB99D8475593C405C7888A1BE E4CCA9712D1114315F97CEE7E4CBAA712E1215326098CFE8F6F0C6542A030618 42B4DEF9F5F1C6552B04071943B5DFFAFEECC251260D0A1C46B7E2F4FFEDC352 270E0B1C47B8E3F4D9D4A66D38231F34629BC9D6DAD5A76E39232035639CCAD5 AE928D7F694D4A667B828FACAF938E806A4E4A677C838FAB3D597689A2BEBB9F 8673573A3E5A778AA3BFBC9F8772563A132F5D96D0E9E5CDA8702C1014305E97 D1EAE6CDA76F2B0F041641B2DDFBF7EFC5532902051742B3DDFCF8EEC4522801 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata7 28 28 mul string def currentfile customdata7 readhexstring 01061B44B7E1F5FEFBE6BD4A210C01071B45B8E1F6FDFBE6BC4A200B09132A54 A7D1EAF5EED9B05D331609142B55A8D2EAF4EED9AF5C32161D2D3D6993C1CBE0 CEC59B7140301E2E3D6A93C0CADFCDC49A713F3047576C7B828DA2B6A48F867E 6F5A48576C7C828CA1B6A38F867E6E59BAAA958A78634E4451667A8498ADBAAB 968977624E4350657A8398ADE3D4C99F7539251A273C6892C2D7E4D4C89E7539 241A273B6891C1D6F8F2DDB460371005122A53A7D0ECF9F2DDB360360F051229 53A6D0EBFFFDE8BE4C220D03081D46B9E3F7FFFCE7BD4B210D02071C46B8E2F7 F3F0DBB15E34180B152C56A9D3E8F3EFDAB05D34170A142C55A9D2E9DFCCC69C 7341321F2F3F6B94BFC9DECCC59C7241311F2E3E6A94BFCAB5A38E8780705B49 596D7D808BA0B4A28D877F6F5B48586D7C818BA043506479859AAFBCAC978876 614C424F64798499AEBBAB968977624D19263B6791C3D8E5D6C79D7337231825 3A6690C3D7E5D5C79E74382304112952A5CFEDFAF0DBB25E350E03102851A5CE ECF9F1DCB25F360E01071B45B8E1F6FDFBE6BC4A200B01061B44B7E1F5FEFBE6 BD4A210C09142B55A8D2EAF4EED9AF5C321609132A54A7D1EAF5EED9B05D3316 1E2E3D6A93C0CADFCDC49A713F301D2D3D6993C1CBE0CEC59B71403048576C7C 828CA1B6A38F867E6E5947576C7B828DA2B6A48F867E6F5ABAAB968977624E43 50657A8398ADBAAA958A78634E4451667A8498ADE4D4C89E7539241A273B6891 C1D6E3D4C99F7539251A273C6892C2D7F9F2DDB360360F05122953A6D0EBF8F2 DDB460371005122A53A7D0ECFFFCE7BD4B210D02071C46B8E2F7FFFDE8BE4C22 0D03081D46B9E3F7F3EFDAB05D34170A142C55A9D2E9F3F0DBB15E34180B152C 56A9D3E8DECCC59C7241311F2E3E6A94BFCADFCCC69C7341321F2F3F6B94BFC9 B4A28D877F6F5B48586D7C818BA0B5A38E8780705B49596D7D808BA0424F6479 8499AEBBAB968977624D43506479859AAFBCAC978876614C18253A6690C3D7E5 D5C79E74382319263B6791C3D8E5D6C79D73372303102851A5CEECF9F1DCB25F 360E04112952A5CFEDFAF0DBB25E350E pop pop /customdata8 28 28 mul string def currentfile customdata8 readhexstring 050F2747B6D6EEF8FEF4DCBC4D2D1507111D375F9EC6E0E9EBE6CCA4653D1F13 2939556F8EA8C1D1D3C3AE9475573B2B4961717D808999B1B39B8B867F73634B B8A090827A6A5A42445C6C7C8492A2BAD8C8AA97785232222434546E8DACCADA F0E2CFA768401A0A0C1C365E9DC5E4F2FAF7DFBF50301802040E2646B5D5EDFC FFF5DDBD4E2E160806102848B7D7EFF9EAE7CDA5663E2014121E38609FC7E1E8 D2C2AF9576583C2C2A3A56708FA9C0D0B29A8A878074644C4A62727E818898B0 435B6B7B8593A3BBB9A19183796959412333536D8CADCBDBD9C9AB9677513121 0B1B355D9CC4E5F3F1E3CEA6673F1909030D2545B4D4ECFDFBF6DEBE4F2F1701 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop end end defaultpacking setpacking %%EndResource %%BeginResource: procset AGM_Gradient_Sep 1.0 0 %%Title: (AGM Gradient Procset) %%Version: 1.0 0 %%CreationDate: (4/26/96) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /AGM_Gradient_Sep 5 dict dup begin put /AGM_Gradient_Sep_private 100 dict def /initialize{ AGM_Gradient_Sep begin AGM_Gradient_Sep_private begin _compositeJob{ initializeSinglePassSeps }{ initializeMultiPassSeps }ifelse initializeSeps AGM_Gradient_private begin /_fillSD newSpotDict def /_rampSD newSpotDict def /_nCustomColorSD nd end AGM_Gradient_Sep_private { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall AGM_Gradient_Sep { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall end currentdict readonly pop end }def /terminate{ currentdict AGM_Gradient_Sep eq{ end }if }def AGM_Gradient_Sep_private begin /initializeSeps{ _noImage not _level2PS not and{ /_whiteBytes 1 makeByte8 pt /knockOut{ 8 setImageParms _whiteBytes /_image load 5 execImage }def /linealFill{ mySave 8 setImageParms _color{ _nCustomColorSD begin cyan magenta yellow black _spotColor{ spot1 begin /tintImage tintValue 1 exch sub makeByte8 def end spot2 begin /tintImage tintValue 1 exch sub makeByte8 def end }if end 4{ makeByte8 4 1 roll }repeat true 4 _nCustomColorSD ncolorimage }{ _nCustomColorSD/black get 1 exch sub makeByte8 _nCustomColorSD bwImage }ifelse myRestore }def }{ /knockOut{ gsave false setoverprint 1 setgray 0 0 1 1 rectfill grestore }def }ifelse /newSpotDict{ 11 dict dup begin /nSpots 2 def /spot1 7 dict def /spot2 7 dict def end }def /initSpotData { begin /name nd /tintImage nd /tintValue nd /spot_C nd /spot_M nd /spot_Y nd /spot_K nd end }def /initSpotDict{ begin /cyanInk false def /magentaInk false def /yellowInk false def /blackInk false def /cyan nd /magenta nd /yellow nd /black nd spot1 initSpotData spot2 initSpotData end }def /copySpotDict{ /_dst xp begin cyanInk magentaInk yellowInk blackInk cyan magenta yellow black spot1 spot2 end _dst begin /spot1 spot1 maxlength dict def /spot2 spot2 maxlength dict def spot2 copy pop spot1 copy pop /black xd /yellow xd /magenta xd /cyan xd /blackInk xd /yellowInk xd /magentaInk xd /cyanInk xd end }def /setCustomColor { 1 index /Black eq{ 6 1 roll 5 npop 1 exch sub setgray }{ 6 1 roll _ccAry1 astore exch dup null eq{ pop 0 }if setcustomcolor }ifelse }def /setCStop{ /_colorStyle exch pt _colorStyle 0 eq{ 0 0 0 4 -1 roll 1 exch sub _spotColor{ /_colorStyle 3 pt /Black 1 index 1 exch sub }if }if _colorStyle 2 eq{ 3 npop }if _rampSD _fillSD copySpotDict _colorStyle 4 eq{ pop 9 2 roll 3 npop 6 -2 roll } if _colorStyle 3 eq _colorStyle 4 eq or{ _fillSD begin exch dup spot1/name get eq{ spot1 spot2 }{ spot2 spot1 }ifelse begin begin /name xd 1 exch sub /tintValue xd 4{ tintValue mul 4 1 roll }repeat _spotColor not{ /tintValue null def }if end /tintValue 0 def end end }if _fillSD nsetcustomcolor }def /renderCMYK{ spot1/name get null eq spot2/name get null eq and dup not{ pop spot1 spotConverted }if dup not{ pop spot2 spotConverted }if }def /fill_ /fill load def /fillOvp{ currentoverprint{ _inRipSep{ currentcolorspace 0 get dup /DeviceGray eq 1 index /DeviceCMYK eq or{ pop currentcmykcolor add add add 0 eq{ newpath }if }{ /Separation eq{ currentcolor 0 eq{ newpath }if }if }ifelse }{ currentgray 1 eq{ newpath }if }ifelse }if fill_ }def /fill{ _nCustomColorSD begin renderCMYK { fillOvp }{ spot1 begin gsave name null ne{ spot_C spot_M spot_Y spot_K name tintValue setCustomColor }{ 1 setgray }ifelse fillOvp grestore end spot2 begin name null ne{ gsave true setoverprint spot_C spot_M spot_Y spot_K name tintValue setCustomColor fillOvp grestore }if end newpath }ifelse end }def /expandSpot{ _spotColor{ /_len xp _rampSD begin spot1 begin tintImage null ne{ tintImage _len expandOne /tintImage xd }if end spot2 begin tintImage null ne{ tintImage _len expandOne /tintImage xd }if end end }{ pop }ifelse }def /rampImage{ _rampSD begin _color{ /cyanInk _cyanData 0 ne def /magentaInk _magentaData 0 ne def /yellowInk _yellowData 0 ne def /blackInk _blackData 0 ne def _nSamples setImageParms _nSamples expandSpot _cyanData _magentaData _yellowData _blackData _nSamples 4 expandColor true 4 _rampSD ncolorimage }{ /cyanInk false def /magentaInk false def /yellowInk false def /blackInk true def _nSamples setImageParms _blackData _rampSD bwImage }ifelse end }def /nsetcustomcolor where{ pop }{ /nsetcustomcolor { /_nCustomColorSD xp _nCustomColorSD begin 4 copy /black xd /yellow xd /magenta xd /cyan xd 4 copy 0 ne /blackInk xd 0 ne /yellowInk xd 0 ne /magentaInk xd 0 ne /cyanInk xd end setcmykcolor }def }ifelse /nsetcustomcolorend where{ pop }{ /nsetcustomcolorend { /_nCustomColorSD null pt }def }ifelse }def /initializeSinglePassSeps{ /_decodeNorm [0 1] pt /_decodeInvert [1 0] pt /spotConverted { begin name null eq{ false }{ tintValue null eq tintImage null eq and{ true }{ false currentpagedevice/SeparationOrder get{name eq or}forall not }ifelse }ifelse end }def /dictImage { 20 dict dup begin /Dict xd /Decode xd /DataSource xd /ImageMatrix xd /BitsPerComponent xd /Height xd /Width xd /ImageType 1 def Dict end /_image load 1 execImage }def /bwImage{ begin gsave currentoverprint{ blackInk{ [/Separation /Black /DeviceGray{}] setcolorspace _decodeInvert dictImage }{ 5 npop }ifelse }{ /DeviceGray setcolorspace _decodeNorm dictImage }ifelse grestore end }def /ncolorimage where{ pop }{ /ncolorimage{ begin renderCMYK { cyanInk magentaInk and yellowInk and blackInk and not currentoverprint and { pop pop gsave cyanInk{ 8 copy [/Separation /Cyan /DeviceGray{}] setcolorspace 3 npop _decodeNorm dictImage }if magentaInk{ 8 copy [/Separation /Magenta /DeviceGray{}] setcolorspace 4 -1 roll 3 npop _decodeNorm dictImage }if yellowInk{ 8 copy [/Separation /Yellow /DeviceGray{}] setcolorspace 4 -2 roll 3 npop _decodeNorm dictImage }if blackInk{ 4 -3 roll [/Separation /Black /DeviceGray{}] setcolorspace 3 npop _decodeNorm dictImage }{ 8 npop }ifelse grestore }{ /_colorimage load 10 execImage }ifelse }{ 6 npop gsave spot1 begin name null ne tintImage null ne and{ [/Separation name /DeviceGray{}] setcolorspace 4 copy tintImage name /Black eq{ _decodeNorm }{ _decodeInvert }ifelse dictImage }{ 1 setgray fill }ifelse end spot2 begin true setoverprint name null ne tintImage null ne and{ [/Separation name /DeviceGray{}] setcolorspace tintImage name /Black eq{ _decodeNorm }{ _decodeInvert }ifelse dictImage }{ 4 npop 1 setgray fill }ifelse end grestore }ifelse end }def }ifelse }def /initializeMultiPassSeps{ /_isCMYKSep _cyanPlate _magentaPlate or _yellowPlate or _blackPlate or pt /invertXfer{ [ { 1 exch sub }/exec load systemdict /currenttransfer get exec /exec load ] cvx systemdict /settransfer get exec }def /ccThrough{ gsave 1 setCustomColor currentcmykcolor grestore add add add 0 ne }def /spotConverted { begin _isCMYKSep not{ false }{ name null eq{ false }{ tintValue null eq tintImage null eq and{ true }{ spot_C spot_M spot_Y spot_K name ccThrough }ifelse }ifelse }ifelse end }def /spotChannel { _isCMYKSep{ pop false }{ begin name null eq{ false }{ spot_C spot_M spot_Y spot_K name ccThrough }ifelse end }ifelse }def /getChannelData { _isCMYKSep dup{ pop renderCMYK }if { _blackPlate{ 4 1 roll 3 npop blackInk }{ _yellowPlate{ 4 2 roll 3 npop yellowInk }{ _magentaPlate{ 4 3 roll 3 npop magentaInk }{ 3 npop cyanInk }ifelse }ifelse }ifelse { true /nonZeroData }{ true /zeroData }ifelse }{ 4 npop spot1/name get null ne spot1 spotChannel and{ spot1/tintImage get dup null ne{ false /nonZeroData }{ pop false /noData }ifelse }{ spot2/name get null ne spot2 spotChannel and{ spot2/tintImage get dup null ne{ false /nonZeroData }{ pop false /noData }ifelse }{ false /noData }ifelse }ifelse }ifelse }def /renderChannelData { /_tmp xp _tmp /nonZeroData ne currentoverprint and{ pop _tmp /zeroData eq{pop}if 4 npop }{ _tmp /nonZeroData eq{ { invertXfer }if systemdict/image get 5 execImage }{ pop _tmp /zeroData eq{pop}if 4 npop knockOut }ifelse }ifelse }def /bwImage{ begin gsave dup dup dup getChannelData exch pop false exch renderChannelData grestore end }def /ncolorimage{ begin pop pop gsave spot2/name get null ne spot2 spotChannel and{ true setoverprint }if getChannelData renderChannelData grestore end }def }def end end defaultpacking setpacking %%EndResource %%BeginResource: procset AGM_Gradient 1.0 0 %%Title: (AGM Gradient Procset) %%Version: 1.0 0 %%CreationDate: (4/26/96) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /AGM_Gradient 20 dict dup begin put /AGM_Gradient_private 200 dict def /initialize { AGM_Gradient begin AGM_Gradient_private begin initializeVars /bd systemdict/mark get def /ed _level2PS { (>>) }{ (counttomark 2 idiv dup dict begin {def} repeat pop currentdict end) } ifelse cvx def _level2PS{ initializeLev2 }{ initializeLev1 }ifelse queryDevice initializeShading initializeOps _producingSeps{ AGM_Gradient_Sep/initialize get exec }{ initializeComposite }ifelse _illustrator{ /f{}def /F{}def /s{}def /S{}def /b{}def /B{}def }if /image where{ /image get /_image xd }if /colorimage where{ /colorimage get /_colorimage xd }if /rectfill where dup{ exch pop not _producingSeps or }{ not }ifelse { /rectfill{ gsave newpath 4 2 roll moveto 1 index 0 rlineto 0 1 index rlineto 1 index neg 0 rlineto pop pop closepath fill grestore }def }if /linealImage _noImage{ /rectImage load }{ _producingSeps{ AGM_Gradient_Sep/AGM_Gradient_Sep_private get begin /rampImage load end }{ /rampImage load }ifelse }ifelse def AGM_Gradient_private { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall AGM_Gradient { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall end currentdict readonly pop end }def /initializeAI { pop pop AGM_Gradient/AGM_Gradient_private get /_illustrator true put AGM_Gradient/initialize get exec AGM_Gradient begin }def /unload{ systemdict/languagelevel known{ systemdict/languagelevel get 2 ge{ userdict/AGM_Gradient_Sep 2 copy known{ undef }{ pop pop }ifelse userdict/AGM_Gradient 2 copy known{ undef }{ pop pop }ifelse }if }if }def /terminate{ currentdict AGM_Gradient eq{ end }if }def AGM_Gradient_private begin /initializeVars{ /_d255 256 array def 0 1 255{ _d255 exch dup 255 div put }bind for /_d255- 256 array def 0 1 255{ _d255- exch 1 _d255 2 index get sub put }bind for /_sSave nd /_dUserSpace matrix defaultmatrix def /_bUMatrix matrix def /_imageMatrix matrix def /_saveMatrix matrix def /_xm matrix def /_ccAry1 5 array def /_level2PS systemdict/languagelevel known dup{ pop systemdict/languagelevel get 2 ge }if def /_level3PS _level2PS systemdict/shfill known and def currentdict /_illustrator known not{ /_illustrator false def }if }def /initializeOps { AGM_Gradient begin currentdict/Bc known not{ /Bc{ _renderFlag 2 eq{ 6 npop }{ pushBSpace _rampIndex 0 eq{ pop pop setCStop }if linealFill popBSpace }ifelse }def }if currentdict/Bg known not{ /Bg{ 10 npop /_gradName xp /_renderFlag xp _renderFlag 2 ne{ _illustrator{ _of setoverprint }if _illustrator _eo and _renderFlag 3 eq or{ eoclip }{ clip }ifelse _gradNames _gradName 2 copy known{ get mark exch aload pop /_gradType xp 1 sub dup /_rampIndex xp /_maxRampIndex xp mark exch aload pop 0 0 }if pop pop getRampData }{ mark mark }ifelse }def }if currentdict/Bm known not{ /Bm{ _renderFlag 2 ne{ _gradType 0 eq{ linealRamp }{ radialGrad }ifelse }{ 6 npop }ifelse }def }if currentdict/Bh known not{ /Bh{ 2 npop /_yHi xp /_xHi xp /_radHilite _xHi 0 ne _yHi 0 ne or pt }def }if currentdict/Bn known not{ /Bn{ AGM_Gradient_private begin dict /_gradNames xp end }def }if currentdict/Bd known not{ /Bd{ AGM_Gradient begin AGM_Gradient_private begin /_nColorsBd xp /_gradType xp /_gradName xp }def }if currentdict/BD known not{ /BD{ currentdict/_gradNames known not{ /_gradNames 20 dict def }if ] _nColorsBd _gradType ] _gradName exch /_gradNames xput end end }def }if currentdict/Bb known not{ /Bb{ AGM_Gradient begin AGM_Gradient_private begin _producingSeps{ AGM_Gradient_Sep/AGM_Gradient_Sep_private get begin }if mySave }def }if currentdict/BB known not{ /BB{ /_tmp xp cleartomark cleartomark _tmp dup _renderFlag myRestore _producingSeps{ end }if _illustrator end end { 2 ne exch 0 gt and{ 2 eq{ s }{ S }ifelse }{ pop newpath }ifelse }{ pop newpath }ifelse }def }if currentdict/Xm known not{ /Xm{ _xm astore pop }def }if end }def /queryDevice{ /_inRipSep _level2PS{ currentpagedevice/Separations 2 copy known{ get }{ pop pop false }ifelse }{ false }ifelse def /_noImage /lv1Fix where{ pop lv1Fix }{ false }ifelse def /_useShells where{ pop }{ /_useShells true def }ifelse /_useSmoothShade where{ pop }{ /_useSmoothShade false def }ifelse /_cyanPlate 1 0 0 0 testCMYKColorThrough def /_magentaPlate 0 1 0 0 testCMYKColorThrough def /_yellowPlate 0 0 1 0 testCMYKColorThrough def /_blackPlate 0 0 0 1 testCMYKColorThrough def /_compositeJob _cyanPlate _magentaPlate and _yellowPlate and _blackPlate and def /_compositeSpotDevice where{ pop }{ /_compositeSpotDevice _compositeJob not _inRipSep or{ 1 }{ 0 }ifelse def }ifelse /_producingSeps _compositeSpotDevice 0 ne def /_deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt def /_dpiThreshold where{ pop }{ /_dpiThreshold 600 def }ifelse /_screenFreqThreshold where{ pop }{ /_screenFreqThreshold 150 def }ifelse /_contoneDevice where{ pop }{ /_contoneDevice false def }ifelse /_subSampleOK _deviceDPI _dpiThreshold le currentScreenFreq _screenFreqThreshold le and _contoneDevice not and _producingSeps not and def }def /initializeLev1{ /makeByte8{ /_tmp 0 pt 255 mul cvi 8 string 8{ dup _tmp 3 index put /_tmp _tmp 1 add pt }repeat exch pop }def /currentScreenFreq{ currentscreen pop pop }def /_byte 1 string def /colorimage where{ pop }{ /colorimage{ pop pop /_blackTmp xp /_yellowTmp xp /_magentaTmp xp /_cyanTmp xp /_cnt 0 pt [ _byte dup 0 _cyanTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .3 /mul cvx _magentaTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .59 /mul cvx _yellowTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .11 /mul cvx _blackTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx /add cvx /add cvx /add cvx 1 /exch cvx /sub cvx /dup cvx 0 /lt cvx{ pop 0 }/if cvx /dup cvx 1 /gt cvx{ pop 1 }/if cvx 255 /mul cvx /cvi cvx 256 /mod cvx /dup cvx 0 /lt cvx{ pop 0 }/if cvx /put cvx /_cnt dup cvx 1 /add cvx /pt cvx ] cvx bind /_image load 5 execImage }def }ifelse }def /initializeLev2{ /level2ScreenFreq{ begin 60 HalftoneType 1 eq{ pop Frequency }if HalftoneType 2 eq{ pop GrayFrequency }if HalftoneType 5 eq{ pop Default level2ScreenFreq }if end }def /currentScreenFreq{ currenthalftone level2ScreenFreq }def }def /initializeShading{ _useSmoothShade _level3PS and{ /_usingSmoothShade true pt initializeLev3_Ops }{ /_usingSmoothShade false pt }ifelse }def /initializeLev3_Ops { /initShFill{ /_index _gradType 0 eq {0}{_maxRampIndex 1 sub} ifelse pt /_rampFuncsArray _maxRampIndex array pt /_boundsArray _maxRampIndex 1 sub array pt /_encodeArray _maxRampIndex 2 mul array pt /_beginCoord _rampPoint pt /_colorSpace null pt /_firstFill _rampIndex _maxRampIndex eq pt /_lastFill false pt }def /getRampColorSpace{ _nSamples 1 gt{ /_ndx 0 pt [blendColor] cvx exec }if /_C0 [currentcolor] pt /_C0_Space currentcolorspace pt _nSamples 1 gt{ /_ndx _nSamples 1 sub pt [blendColor] cvx exec }if /_C1 [currentcolor] pt /_C1_Space currentcolorspace pt _C0_Space _C1_Space eq{ /_rampColorSpace _C0_Space pt }{ (colorspace conflict!) == showpage stop }ifelse _spotColor{ nsetcustomcolorend }if }def /linealShFill{ popBSpace _xm aload pop pushBSpace /_size _index 1 add pt _size _maxRampIndex lt { /_rampFuncsArray _rampFuncsArray 0 _size getinterval pt /_boundsArray _boundsArray 0 _size 1 sub getinterval pt /_encodeArray _encodeArray 0 _size 2 mul getinterval pt }if bd /ShadingType 2 /ColorSpace _colorSpace /Function bd /FunctionType 3 /Domain [0 1] /Functions _rampFuncsArray /Bounds _boundsArray /Encode _encodeArray ed /Extend [_firstFill _lastFill] /Domain [0 1] /Coords [_beginCoord 0 _endCoord 0] ed shfill }def /radialShFill{ /_size _maxRampIndex _index sub pt _size _maxRampIndex lt { /_rampFuncsArray _rampFuncsArray _index _size getinterval pt /_boundsArray _boundsArray _index _size 1 sub getinterval pt /_encodeArray _encodeArray _index 2 mul _size 2 mul getinterval pt }if /_rampLen _beginCoord _endCoord sub pt bd /ShadingType 3 /ColorSpace _colorSpace /Function bd /FunctionType 3 /Domain [0 1] /Functions _rampFuncsArray /Bounds _boundsArray /Encode _encodeArray ed /Extend [_lastFill _firstFill] /Domain [0 1] /Coords [_xHi _rampLen mul _yHi _rampLen mul _endCoord 0 0 _beginCoord] ed shfill _radHilite{ _xHi _rampLen mul _yHi _rampLen mul translate }if }def /fillRamp{ /_invert _midPoint 0.5 lt pt _rampIndex _maxRampIndex eq { initShFill }if getRampColorSpace _colorSpace null eq{ /_colorSpace _rampColorSpace pt }{ _colorSpace _rampColorSpace ne{ /_index _index 1 _gradType 0 eq{ sub pt linealShFill }{ add pt radialShFill }ifelse initShFill /_colorSpace _rampColorSpace pt } if }ifelse /_endCoord _endPoint pt _rampFuncsArray _index bd /FunctionType 2 /Domain [0 1] /N 0.5 log _invert{1 _midPoint sub}{_midPoint}ifelse log div _gradType 0 eq{ _invert{/C1}{/C0}ifelse _C0 _invert{/C0}{/C1}ifelse _C1 }{ _invert{/C0}{/C1}ifelse _C1 _invert{/C1}{/C0}ifelse _C0 }ifelse ed put _rampIndex 1 ne{ _boundsArray _index _gradType 1 eq{1 sub}if _endCoord put } if 0 1 _invert {exch}if _encodeArray _index 2 mul 1 add 3 -1 roll put _encodeArray _index 2 mul 3 -1 roll put _rampIndex 1 eq { /_lastFill true pt _gradType 0 eq{ linealShFill }{ radialShFill }ifelse }if /_index _index 1 _gradType 0 eq{ add pt }{ sub pt }ifelse }def /radialRamp /fillRamp load def /rampImage /fillRamp load def AGM_Gradient begin /Bc{ 6 npop }def end }def /initializeComposite{ /bwImage{ pop /_image load 5 execImage }def currentdict/rampImage known not{ /rampImage{ _color{ _nSamples setImageParms _rgbRamp{ _redData _greenData _blueData _nSamples 3 expandColor true 3 null ncolorimage }{ _cyanData _magentaData _yellowData _blackData _nSamples 4 expandColor true 4 null ncolorimage }ifelse }{ _nSamples setImageParms _blackData null bwImage }ifelse }def }if /setCStop{ /_colorStyle exch pt _colorStyle 0 eq{ 1 exch sub 0 0 0 4 -1 roll }if _colorStyle 2 eq{ setrgbcolor 4 npop }if _colorStyle 3 eq{ 1 exch sub /_tmp xp pop 4{ _tmp mul 4 1 roll }repeat }if _colorStyle 4 eq{ 3 -1 roll pop pop 1 exch sub /_tmp xp 3{ 1 exch sub _tmp mul 1 exch sub 3 1 roll }repeat setrgbcolor 4 npop }if _colorStyle 2 ne _colorStyle 4 ne and{ null nsetcustomcolor }if }def /nsetcustomcolor { pop setcmykcolor }def /nsetcustomcolorend { }def /ncolorimage{ pop /_colorimage load 10 execImage }def _noImage not _level2PS not and{ /linealFill{ 8 setImageParms _color{ currentcmykcolor 4{ makeByte8 4 1 roll }repeat true 4 null ncolorimage }{ currentgray makeByte8 null bwImage }ifelse }def }if }def /npop{ {pop}repeat }def /xd{ exch def }def /nd{ null def }def /pt{ AGM_Gradient_private 3 1 roll put }def /xp{ exch pt }def /xput{ dup load dup length exch maxlength eq{ dup dup load dup length 2 mul dict copy def }if load begin def end }def /mySave{ save /_sSave xp }def /myRestore{ _sSave type /savetype eq{ _sSave restore }if }def /gMark{ counttomark 2 add -1 roll }def /execImage{ /_tmp xp { exec }stopped{ $error /errorname get /undefinedresult ne{ stop }{ _tmp npop }ifelse }if }def /pushBSpace{ newpath gsave _bUMatrix astore concat }def /popBSpace{ grestore }def /setImageParms{ 1 8 2 index 0 0 1 0 0 _imageMatrix astore }def /linealFill{ 0 0 1 1 rectfill }def /testCMYKColorThrough{ gsave setcmykcolor currentcmykcolor grestore add add add 0 ne }def /expandOne { /_tmp xp dup type /stringtype ne{ _tmp string exch dup 0 ne{ 255 mul cvi 0 1 _tmp 1 sub{ 3 copy exch put pop }for }if pop }if }def /expandColor{ /_channels xp /_len xp _channels{ _len expandOne _channels 1 roll }repeat }def /blendColor{ _color{ _rgbRamp _producingSeps not and{ _redData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _greenData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _blueData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if /setrgbcolor cvx }{ _cyanData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _magentaData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _yellowData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _blackData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _spotColor{ _rampSD begin /_rampSD cvx /begin cvx spot1 begin tintImage dup type /stringtype eq{ /_ndx cvx /get cvx _d255- /exch cvx /get cvx }{ dup null ne{ name type /nametype ne{ 1 exch sub }if }if }ifelse end /spot1 cvx /tintValue 3 -1 /roll cvx /put cvx spot2 begin tintImage dup type /stringtype eq{ /_ndx cvx /get cvx _d255- /exch cvx /get cvx }{ dup null ne{ name type /nametype ne{ 1 exch sub }if }if }ifelse end /spot2 cvx /tintValue 3 -1 /roll cvx /put cvx /end cvx end /_rampSD cvx /nsetcustomcolor cvx }{ /setcmykcolor cvx }ifelse }ifelse }{ _blackData /_ndx cvx /get cvx _d255 /exch cvx /get cvx _usingSmoothShade{ 1 /exch cvx /sub cvx 0 0 0 4 -1 /roll cvx /setcmykcolor cvx }{ /setgray cvx }ifelse }ifelse }def /linealRamp{ pushBSpace _ramp{ linealImage }{ linealFill }ifelse popBSpace /_rampIndex _rampIndex 1 sub pt _rampIndex 0 gt{ getRampData }if }def /radialGrad{ /_firstShell true pt _usingSmoothShade not{ fill }if pushBSpace _radHilite{ _xHi _yHi _bUMatrix idtransform /_yHi xp /_xHi xp _rampPoint 1 lt{ 1 _rampPoint sub dup _xHi mul exch _yHi mul translate }if }if _rampIndex{ radialRamp /_rampIndex _rampIndex 1 sub pt _rampIndex 0 gt{ getRampData }if }repeat popBSpace }def /getNSamples{ 0 exch { dup type /stringtype eq{ length exch pop exit }if pop }forall dup 0 eq{ pop 1 }if }def /getRampData{ /_rampType gMark pt /_color _rampType 0 gt pt /_ccRGB _rampType 5 eq _rampType 6 eq or pt /_rgbRamp _rampType 4 eq _ccRGB or pt /_ccProcess _rampType 2 eq _rampType 3 eq or pt _producingSeps{ _rampSD initSpotDict /_spotColor _ccProcess _ccRGB or pt }{ /_spotColor false pt }ifelse /_ramp true pt 100 div /_rampPoint xp 100 div /_midPoint xp dup /_colorStyle xp _colorStyle 0 eq{ 2 }{ _colorStyle 1 eq{ 5 }{ _colorStyle 2 eq{ 8 }{ _colorStyle 3 eq{ _producingSeps{ _rampSD begin spot1 begin /name 3 index def /spot_K 4 index def /spot_Y 5 index def /spot_M 6 index def /spot_C 7 index def end end }if 7 }{ _producingSeps{ _rampSD begin spot1 begin /name 4 index def /spot_K 8 index def /spot_Y 9 index def /spot_M 10 index def /spot_C 11 index def end end }if 11 } ifelse }ifelse }ifelse }ifelse /_tmp xp _tmp index 100 div /_endPoint xp _gradType 1 eq{ _tmp 1 add index 100 div /_midPoint xp }if _producingSeps{ _tmp 2 add index /_nextColorStyle xp _nextColorStyle 3 eq{ /_tmp _tmp 4 add pt _tmp index dup _rampSD begin spot1 /name get ne{ spot2 begin /name xd /spot_K _tmp 2 add index def /spot_Y _tmp 3 add index def /spot_M _tmp 4 add index def /spot_C _tmp 5 add index def end }{ pop }ifelse end }if _nextColorStyle 4 eq{ /_tmp _tmp 5 add pt _tmp index dup _rampSD begin spot1 /name get ne{ spot2 begin /name xd /spot_K _tmp 5 add index def /spot_Y _tmp 6 add index def /spot_M _tmp 7 add index def /spot_C _tmp 8 add index def end }{ pop }ifelse end }if }if _rampType 3 eq _rampType 6 eq or{ /_tint2Data gMark pt }if _ccProcess _ccRGB or{ /_tint1Data gMark pt }if _rgbRamp{ /_blueData gMark pt /_greenData gMark pt /_redData gMark pt }if _producingSeps{ _rampSD begin _ccProcess _ccRGB or{ _rampType 3 eq _rampType 6 eq or{ spot2 begin /tintImage _gradType 0 eq{ _tint2Data }{ _tint1Data }ifelse def name null eq{ /name /Black def }if end }if spot1 begin /tintImage _gradType 0 eq _rampType 2 eq or _rampType 5 eq or{ _tint1Data }{ _tint2Data }ifelse def _rampType 2 eq _rampType 5 eq or{ name null eq{ /name spot2 /name get def spot2 /name null put }if }{ name null eq{ /name /Black def }if }ifelse end }if end }if /_blackData gMark pt _rampType 0 gt{ counttomark 4 add -3 roll /_yellowData xp /_magentaData xp /_cyanData xp }if _ramp{ /_nSamples [ _rampType 0 eq {_blackData}if _rampType 1 eq {_cyanData _magentaData _yellowData _blackData}if _rampType 2 eq {_cyanData _magentaData _yellowData _blackData _tint1Data}if _rampType 3 eq {_cyanData _magentaData _yellowData _blackData _tint1Data _tint2Data}if _rampType 4 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData}if _rampType 5 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData _tint1Data}if _rampType 6 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData _tint1Data _tint2Data}if ] getNSamples pt _usingSmoothShade not {/_ramp _nSamples 1 gt pt} if } if setCStop }def /rectImage{ gsave /_sInc 1 pt /_bInc 1 _nSamples div pt /_uRampLen 1 0 dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt pt /_pChange _uRampLen 0 eq{0}{_nSamples _uRampLen div}ifelse pt 0 _nSamples [ /dup cvx /_ndx /exch cvx /pt cvx blendColor 0 0 _bInc 1 /rectfill cvx _bInc 0 /translate cvx _sInc /add cvx ] cvx bind repeat pop _spotColor{ nsetcustomcolorend }if grestore }def /radialInit{ /_nRadSamples _nSamples dup 0 eq{pop 1}if pt /_sInc -1 pt /_rampLen _rampPoint _endPoint sub pt /_bInc _rampLen _nSamples div neg pt /_optimize false pt _subSampleOK{ /_uRampLen _rampLen 0 dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt 0 _rampLen dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt 2 copy lt{ exch }if pop pt /_pChange _uRampLen 0 eq{ 0 }{ _nSamples _uRampLen div }ifelse pt _pChange .5 gt dup /_optimize xp{ /_nRadSamples _uRampLen 2 div round cvi dup 1 le{pop 2}if pt /_bInc _rampLen _nRadSamples div neg pt /_sInc _nSamples 1 sub _nRadSamples 1 sub div neg pt }if }if _radHilite{ /_xBCInc _xHi _rampLen mul _nRadSamples div pt /_yBCInc _yHi _rampLen mul _nRadSamples div pt }if }def currentdict/radialRamp known not{ /radialRamp{ /_saveMatrix _saveMatrix currentmatrix def radialInit _rampPoint _nSamples 1 sub _nRadSamples [ /dup cvx _optimize{ /round cvx /cvi cvx }if /_ndx /exch cvx /pt cvx _useShells{ /_firstShell cvx{ /_firstShell false pt }{ 0 0 3 index 360 0 arcn fill }/ifelse cvx }if blendColor _useShells{ 0 0 3 /index cvx 0 360 /arc cvx }{ 0 0 3 /index cvx 0 360 /arc cvx /fill cvx }ifelse /exch cvx _bInc /add cvx /exch cvx _sInc /add cvx _radHilite{ _xBCInc _yBCInc /translate cvx }if ] cvx bind repeat pop pop _saveMatrix setmatrix _radHilite{ _xHi _rampLen mul _yHi _rampLen mul translate }if _useShells _rampIndex 1 eq and{ fill }if _spotColor{ nsetcustomcolorend }if }def }if end end defaultpacking setpacking %%EndResource %%BeginProcSet: Adobe_ColorImage_AI6 1.1 0 userdict /Adobe_ColorImage_AI6 known not { userdict /Adobe_ColorImage_AI6 24 dict put } if userdict /Adobe_ColorImage_AI6 get begin /initialize { Adobe_ColorImage_AI6 begin Adobe_ColorImage_AI6 { dup type /arraytype eq { dup xcheck { bind } if } if pop pop } forall } def /terminate { end } def currentdict /Adobe_ColorImage_AI6_Vars known not { /Adobe_ColorImage_AI6_Vars 15 dict def } if Adobe_ColorImage_AI6_Vars begin /channelcount 0 def /sourcecount 0 def /sourcearray 4 array def /plateindex -1 def /XIMask 0 def /XIBinary 0 def /XIChannelCount 0 def /XIBitsPerPixel 0 def /XIImageHeight 0 def /XIImageWidth 0 def /XIImageMatrix null def /XIBuffer null def /XIDataProc null def /XIVersion 6 def end /WalkRGBString null def /WalkCMYKString null def /StuffRGBIntoGrayString null def /RGBToGrayImageProc null def /StuffCMYKIntoGrayString null def /CMYKToGrayImageProc null def /ColorImageCompositeEmulator null def /SeparateCMYKImageProc null def /FourEqual null def /TestPlateIndex null def currentdict /_colorimage known not { /colorimage where { /colorimage get /_colorimage exch def } { /_colorimage null def } ifelse } if /_currenttransfer systemdict /currenttransfer get def /colorimage null def /XI null def /WalkRGBString { 0 3 index dup length 1 sub 0 3 3 -1 roll { 3 getinterval { } forall 5 index exec 3 index } for 5 { pop } repeat } def /WalkCMYKString { 0 3 index dup length 1 sub 0 4 3 -1 roll { 4 getinterval { } forall 6 index exec 3 index } for 5 { pop } repeat } def /StuffRGBIntoGrayString { .11 mul exch .59 mul add exch .3 mul add cvi 3 copy put pop 1 add } def /RGBToGrayImageProc { Adobe_ColorImage_AI6_Vars begin sourcearray 0 get exec dup length 3 idiv string dup 3 1 roll /StuffRGBIntoGrayString load exch WalkRGBString end } def /StuffCMYKIntoGrayString { exch .11 mul add exch .59 mul add exch .3 mul add dup 255 gt { pop 255 } if 255 exch sub cvi 3 copy put pop 1 add } def /CMYKToGrayImageProc { Adobe_ColorImage_AI6_Vars begin sourcearray 0 get exec dup length 4 idiv string dup 3 1 roll /StuffCMYKIntoGrayString load exch WalkCMYKString end } def /ColorImageCompositeEmulator { pop true eq { Adobe_ColorImage_AI6_Vars /sourcecount get 5 add { pop } repeat } { Adobe_ColorImage_AI6_Vars /channelcount get 1 ne { Adobe_ColorImage_AI6_Vars begin sourcearray 0 3 -1 roll put channelcount 3 eq { /RGBToGrayImageProc } { /CMYKToGrayImageProc } ifelse load end } if image } ifelse } def /SeparateCMYKImageProc { Adobe_ColorImage_AI6_Vars begin sourcecount 0 ne { sourcearray plateindex get exec } { sourcearray 0 get exec dup length 4 idiv string 0 2 index plateindex 4 2 index length 1 sub { get 255 exch sub 3 copy put pop 1 add 2 index } for pop pop exch pop } ifelse end } def /FourEqual { 4 index ne { pop pop pop false } { 4 index ne { pop pop false } { 4 index ne { pop false } { 4 index eq } ifelse } ifelse } ifelse } def /TestPlateIndex { Adobe_ColorImage_AI6_Vars begin /plateindex -1 def /setcmykcolor where { pop gsave 1 0 0 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 1 0 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 0 1 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 0 0 1 setcmykcolor systemdict /currentgray get exec 1 exch sub grestore 1 0 0 0 FourEqual { /plateindex 0 def } { 0 1 0 0 FourEqual { /plateindex 1 def } { 0 0 1 0 FourEqual { /plateindex 2 def } { 0 0 0 1 FourEqual { /plateindex 3 def } { 0 0 0 0 FourEqual { /plateindex 5 def } if } ifelse } ifelse } ifelse } ifelse pop pop pop pop } if plateindex end } def /colorimage { Adobe_ColorImage_AI6_Vars begin /channelcount 1 index def /sourcecount 2 index 1 eq { channelcount 1 sub } { 0 } ifelse def 4 sourcecount add index dup 8 eq exch 1 eq or not end { /_colorimage load null ne { _colorimage } { Adobe_ColorImage_AI6_Vars /sourcecount get 7 add { pop } repeat } ifelse } { dup 3 eq TestPlateIndex dup -1 eq exch 5 eq or or { /_colorimage load null eq { ColorImageCompositeEmulator } { dup 1 eq { pop pop image } { Adobe_ColorImage_AI6_Vars /plateindex get 5 eq { gsave 0 _currenttransfer exec 1 _currenttransfer exec eq { 0 _currenttransfer exec 0.5 lt } { 0 _currenttransfer exec 1 _currenttransfer exec gt } ifelse { { pop 0 } } { { pop 1 } } ifelse systemdict /settransfer get exec } if _colorimage Adobe_ColorImage_AI6_Vars /plateindex get 5 eq { grestore } if } ifelse } ifelse } { dup 1 eq { pop pop image } { pop pop Adobe_ColorImage_AI6_Vars begin sourcecount -1 0 { exch sourcearray 3 1 roll put } for /SeparateCMYKImageProc load end systemdict /image get exec } ifelse } ifelse } ifelse } def /XG { pop pop } def /XF { 13 {pop} repeat } def /Xh { Adobe_ColorImage_AI6_Vars begin gsave /XIMask exch 0 ne def /XIImageHeight exch def /XIImageWidth exch def /XIImageMatrix exch def 0 0 moveto XIImageMatrix concat XIImageWidth XIImageHeight scale XIMask { /_lp /null ddef _fc /_lp /imagemask ddef } if /XIVersion 7 def end } def /XH { Adobe_ColorImage_AI6_Vars begin /XIVersion 6 def grestore end } def /XI { Adobe_ColorImage_AI6_Vars begin gsave /XIMask exch 0 ne def /XIBinary exch 0 ne def pop pop /XIChannelCount exch def /XIBitsPerPixel exch def /XIImageHeight exch def /XIImageWidth exch def pop pop pop pop /XIImageMatrix exch def XIBitsPerPixel 1 eq { XIImageWidth 8 div ceiling cvi } { XIImageWidth XIChannelCount mul } ifelse /XIBuffer exch string def XIBinary { /XIDataProc { currentfile XIBuffer readstring pop } def XIVersion 6 le { currentfile 128 string readline pop pop } if } { /XIDataProc { currentfile XIBuffer readhexstring pop } def } ifelse XIVersion 6 le { 0 0 moveto XIImageMatrix concat XIImageWidth XIImageHeight scale XIMask { /_lp /null ddef _fc /_lp /imagemask ddef } if } if XIMask { XIImageWidth XIImageHeight false [ XIImageWidth 0 0 XIImageHeight neg 0 0 ] /XIDataProc load imagemask } { XIImageWidth XIImageHeight XIBitsPerPixel [ XIImageWidth 0 0 XIImageHeight neg 0 0 ] /XIDataProc load XIChannelCount 1 eq { gsave 0 setgray image grestore } { false XIChannelCount colorimage } ifelse } ifelse grestore end } def end %%EndProcSet %%BeginResource: procset Adobe_Illustrator_AI5 1.1 0 %%Title: (Adobe Illustrator (R) Version 5.0 Full Prolog) %%Version: 1.1 0 %%CreationDate: (3/7/1994) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_Illustrator_AI5_vars 81 dict dup begin put /_eo false def /_lp /none def /_pf { } def /_ps { } def /_psf { } def /_pss { } def /_pjsf { } def /_pjss { } def /_pola 0 def /_doClip 0 def /cf currentflat def /_tm matrix def /_renderStart [ /e0 /r0 /a0 /o0 /e1 /r1 /a1 /i0 ] def /_renderEnd [ null null null null /i1 /i1 /i1 /i1 ] def /_render -1 def /_rise 0 def /_ax 0 def /_ay 0 def /_cx 0 def /_cy 0 def /_leading [ 0 0 ] def /_ctm matrix def /_mtx matrix def /_sp 16#020 def /_hyphen (-) def /_fScl 0 def /_cnt 0 def /_hs 1 def /_nativeEncoding 0 def /_useNativeEncoding 0 def /_tempEncode 0 def /_pntr 0 def /_tDict 2 dict def /_wv 0 def /Tx { } def /Tj { } def /CRender { } def /_AI3_savepage { } def /_gf null def /_cf 4 array def /_if null def /_of false def /_fc { } def /_gs null def /_cs 4 array def /_is null def /_os false def /_sc { } def /_pd 1 dict def /_ed 15 dict def /_pm matrix def /_fm null def /_fd null def /_fdd null def /_sm null def /_sd null def /_sdd null def /_i null def /discardSave null def /buffer 256 string def /beginString null def /endString null def /endStringLength null def /layerCnt 1 def /layerCount 1 def /perCent (%) 0 get def /perCentSeen? false def /newBuff null def /newBuffButFirst null def /newBuffLast null def /clipForward? false def end userdict /Adobe_Illustrator_AI5 known not { userdict /Adobe_Illustrator_AI5 91 dict put } if userdict /Adobe_Illustrator_AI5 get begin /initialize { Adobe_Illustrator_AI5 dup begin Adobe_Illustrator_AI5_vars begin discardDict { bind pop pop } forall dup /nc get begin { dup xcheck 1 index type /operatortype ne and { bind } if pop pop } forall end newpath } def /terminate { end end } def /_ null def /ddef { Adobe_Illustrator_AI5_vars 3 1 roll put } def /xput { dup load dup length exch maxlength eq { dup dup load dup length 2 mul dict copy def } if load begin def end } def /npop { { pop } repeat } def /sw { dup length exch stringwidth exch 5 -1 roll 3 index mul add 4 1 roll 3 1 roll mul add } def /swj { dup 4 1 roll dup length exch stringwidth exch 5 -1 roll 3 index mul add 4 1 roll 3 1 roll mul add 6 2 roll /_cnt 0 ddef { 1 index eq { /_cnt _cnt 1 add ddef } if } forall pop exch _cnt mul exch _cnt mul 2 index add 4 1 roll 2 index add 4 1 roll pop pop } def /ss { 4 1 roll { 2 npop (0) exch 2 copy 0 exch put pop gsave false charpath currentpoint 4 index setmatrix stroke grestore moveto 2 copy rmoveto } exch cshow 3 npop } def /jss { 4 1 roll { 2 npop (0) exch 2 copy 0 exch put gsave _sp eq { exch 6 index 6 index 6 index 5 -1 roll widthshow currentpoint } { false charpath currentpoint 4 index setmatrix stroke } ifelse grestore moveto 2 copy rmoveto } exch cshow 6 npop } def /sp { { 2 npop (0) exch 2 copy 0 exch put pop false charpath 2 copy rmoveto } exch cshow 2 npop } def /jsp { { 2 npop (0) exch 2 copy 0 exch put _sp eq { exch 5 index 5 index 5 index 5 -1 roll widthshow } { false charpath } ifelse 2 copy rmoveto } exch cshow 5 npop } def /pl { transform 0.25 sub round 0.25 add exch 0.25 sub round 0.25 add exch itransform } def /setstrokeadjust where { pop true setstrokeadjust /c { curveto } def /C /c load def /v { currentpoint 6 2 roll curveto } def /V /v load def /y { 2 copy curveto } def /Y /y load def /l { lineto } def /L /l load def /m { moveto } def } { /c { pl curveto } def /C /c load def /v { currentpoint 6 2 roll pl curveto } def /V /v load def /y { pl 2 copy curveto } def /Y /y load def /l { pl lineto } def /L /l load def /m { pl moveto } def } ifelse /d { setdash } def /cf { } def /i { dup 0 eq { pop cf } if setflat } def /j { setlinejoin } def /J { setlinecap } def /M { setmiterlimit } def /w { setlinewidth } def /XR { 0 ne /_eo exch ddef } def /H { } def /h { closepath } def /N { _pola 0 eq { _doClip 1 eq { _eo {eoclip} {clip} ifelse /_doClip 0 ddef } if newpath } { /CRender { N } ddef } ifelse } def /n { N } def /F { _pola 0 eq { _doClip 1 eq { gsave _pf grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _fc /_doClip 0 ddef } { _pf } ifelse } { /CRender { F } ddef } ifelse } def /f { closepath F } def /S { _pola 0 eq { _doClip 1 eq { gsave _ps grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _sc /_doClip 0 ddef } { _ps } ifelse } { /CRender { S } ddef } ifelse } def /s { closepath S } def /B { _pola 0 eq { _doClip 1 eq gsave F grestore { gsave S grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _sc /_doClip 0 ddef } { S } ifelse } { /CRender { B } ddef } ifelse } def /b { closepath B } def /W { /_doClip 1 ddef } def /* { count 0 ne { dup type /stringtype eq { pop } if } if newpath } def /u { } def /U { } def /q { _pola 0 eq { gsave } if } def /Q { _pola 0 eq { grestore } if } def /*u { _pola 1 add /_pola exch ddef } def /*U { _pola 1 sub /_pola exch ddef _pola 0 eq { CRender } if } def /D { pop } def /*w { } def /*W { } def /` { /_i save ddef clipForward? { nulldevice } if 6 1 roll 4 npop concat pop userdict begin /showpage { } def 0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit [] 0 setdash /setstrokeadjust where {pop false setstrokeadjust} if newpath 0 setgray false setoverprint } def /~ { end _i restore } def /O { 0 ne /_of exch ddef /_lp /none ddef } def /R { 0 ne /_os exch ddef /_lp /none ddef } def /g { /_gf exch ddef /_fc { _lp /fill ne { _of setoverprint _gf setgray /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /G { /_gs exch ddef /_sc { _lp /stroke ne { _os setoverprint _gs setgray /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /k { _cf astore pop /_fc { _lp /fill ne { _of setoverprint _cf aload pop setcmykcolor /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /K { _cs astore pop /_sc { _lp /stroke ne { _os setoverprint _cs aload pop setcmykcolor /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /x { /_gf exch ddef findcmykcustomcolor /_if exch ddef /_fc { _lp /fill ne { _of setoverprint _if _gf 1 exch sub setcustomcolor /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /X { /_gs exch ddef findcmykcustomcolor /_is exch ddef /_sc { _lp /stroke ne { _os setoverprint _is _gs 1 exch sub setcustomcolor /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /A { pop } def /annotatepage { userdict /annotatepage 2 copy known {get exec} {pop pop} ifelse } def /XT { pop pop } def /discard { save /discardSave exch store discardDict begin /endString exch store gt38? { 2 add } if load stopped pop end discardSave restore } bind def userdict /discardDict 7 dict dup begin put /pre38Initialize { /endStringLength endString length store /newBuff buffer 0 endStringLength getinterval store /newBuffButFirst newBuff 1 endStringLength 1 sub getinterval store /newBuffLast newBuff endStringLength 1 sub 1 getinterval store } def /shiftBuffer { newBuff 0 newBuffButFirst putinterval newBuffLast 0 currentfile read not { stop } if put } def 0 { pre38Initialize mark currentfile newBuff readstring exch pop { { newBuff endString eq { cleartomark stop } if shiftBuffer } loop } { stop } ifelse } def 1 { pre38Initialize /beginString exch store mark currentfile newBuff readstring exch pop { { newBuff beginString eq { /layerCount dup load 1 add store } { newBuff endString eq { /layerCount dup load 1 sub store layerCount 0 eq { cleartomark stop } if } if } ifelse shiftBuffer } loop } if } def 2 { mark { currentfile buffer readline not { stop } if endString eq { cleartomark stop } if } loop } def 3 { /beginString exch store /layerCnt 1 store mark { currentfile buffer readline not { stop } if dup beginString eq { pop /layerCnt dup load 1 add store } { endString eq { layerCnt 1 eq { cleartomark stop } { /layerCnt dup load 1 sub store } ifelse } if } ifelse } loop } def end userdict /clipRenderOff 15 dict dup begin put { /n /N /s /S /f /F /b /B } { { _doClip 1 eq { /_doClip 0 ddef _eo {eoclip} {clip} ifelse } if newpath } def } forall /Tr /pop load def /Bb {} def /BB /pop load def /Bg {12 npop} def /Bm {6 npop} def /Bc /Bm load def /Bh {4 npop} def end /Lb { 4 npop 6 1 roll pop 4 1 roll pop pop pop 0 eq { 0 eq { (%AI5_BeginLayer) 1 (%AI5_EndLayer--) discard } { /clipForward? true def /Tx /pop load def /Tj /pop load def currentdict end clipRenderOff begin begin } ifelse } { 0 eq { save /discardSave exch store } if } ifelse } bind def /LB { discardSave dup null ne { restore } { pop clipForward? { currentdict end end begin /clipForward? false ddef } if } ifelse } bind def /Pb { pop pop 0 (%AI5_EndPalette) discard } bind def /Np { 0 (%AI5_End_NonPrinting--) discard } bind def /Ln /pop load def /Ap /pop load def /Ar { 72 exch div 0 dtransform dup mul exch dup mul add sqrt dup 1 lt { pop 1 } if setflat } def /Mb { q } def /Md { } def /MB { Q } def /nc 3 dict def nc begin /setgray { pop } bind def /setcmykcolor { 4 npop } bind def /setcustomcolor { 2 npop } bind def currentdict readonly pop end end setpacking %%EndResource %%BeginResource: procset Adobe_blend_AI5 1.4 0 %%Title: (Adobe Illustrator (R) Version 5.0 Blend ProcSet) %%Version: 1.4 0 %%CreationDate: (11/19/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /Adobe_blend_AI5 70 dict dup begin put /bd { bind def } bind def /xs { exch store } bd /nullProc { { } } def /initialize { pop pop Adobe_blend_AI5 begin Adobe_blend_AI5_vars begin /_contoneDevice where { pop } { /_contoneDevice false def } ifelse /_dpiThreshold where { pop } { /_dpiThreshold 600 def } ifelse /_screenFreqThreshold where { pop } { /_screenFreqThreshold 150 def } ifelse /tRectOK? deviceDPI _dpiThreshold le currentScreenFreq _screenFreqThreshold le and _contoneDevice not and def /invertXfer { [ { 1 exch sub } /exec load systemdict/currenttransfer get exec /exec load ] cvx systemdict/settransfer get exec } bd /spotDict 3 dict dup begin /nSpots 2 def /spot1 7 dict def /spot2 7 dict def end def composite? { /_setgray_ /setgray load def /_fill_ /fill load def /_image_ /image load def } { /_setgray_ systemdict/setgray get def /_fill_ systemdict/fill get def /_image_ systemdict/image get def } ifelse } bd /terminate { currentdict Adobe_blend_AI5_vars eq { end currentdict Adobe_blend_AI5 eq { end } if } if } bd /_compositeSpotDevice where { begin _compositeSpotDevice 0 ne {userdict /composite? true put} if end } { /_compositeSpotDevice 0 def } ifelse /nullString () def /d255 256 array def 0 1 255 { d255 exch dup 255 div put } bind for /d255- 256 array def 0 1 255 { d255- exch 1 d255 2 index get sub put } bind for /dUserSpace matrix defaultmatrix def currentdict /Adobe_blend_AI5_vars 89 dict dup begin put { /f /F /s /S /b /B } { null def } bind forall /byte 1 string def /sSave null def /setSSave { save /sSave exch store } bind def /Bm null def /doBlend null def /startC? false def /endC? false def /fCMYK? null def /startTint 0 def /endTint 0 def /bSMatrix matrix def /bUMatrix matrix def /dMatrix matrix def /inLine? true def /pTState? false def /bHi? false def /yHi 0 def /xHi 0 def /noImg /lv1Fix where { pop lv1Fix } { false } ifelse def /ccAry1 5 array def /ccTint 0 def /spotColor? false def /colorimage? true def [ /tint1Data /tint2Data /spotDict /bAxis /ubAxis /pChange /optimize? /nSamples /sInc /blendProc /_bn /xBCInc /yBCInc /bInc /bRender /cBName /cBType /nColors /color? /blend? /colorType /cData /cDataLen /bDataLen /rampPoint /midPoint /endPoint /blendLength /blackData /yeData /mgData /cyData /cnt1 /ndx /_fill /tmp counttomark { null def } bind repeat pop currentdict end currentdict end exch begin begin /unitSq { 0 0 moveto 0 1 lineto 1 1 lineto 1 0 lineto closepath } bd /gMark { counttomark 2 add -1 roll } bd /setCustomColor { dup /ccTint exch store 1 exch sub 6 1 roll ccAry1 astore exch setcustomcolor } bd /currentCustomColor { ccAry1 aload pop ccTint } bd /nsetcustomcolor where { pop } { /nsetcustomcolor { pop setcmykcolor } bd } ifelse /nsetcustomcolorend where { pop } { /nsetcustomcolorend { } bd } ifelse /setBSpace { newpath bUMatrix astore concat unitSq } bd /setCStop { dup 0 eq { pop spotColor? { dup 1 exch sub /ccTint exch def ccAry1 4 /Black put } if setgray } { 1 eq { setcmykcolor } { composite? not colorType 2 lt and { forceCMYK } { setCustomColor } ifelse } ifelse } ifelse } bd /makeByte { /tmp 0 store 255 mul cvi 8 string 8 { dup tmp 3 index put /tmp tmp 1 add store } repeat exch pop } bd /setImgSpace { cDataLen 1 8 2 index 0 0 1 0 0 dMatrix astore } bd /bwImage { setImgSpace cData /_image_ load { exec } stopped { $error /errorname get /undefinedresult ne { stop } { pop pop pop pop pop } ifelse } if } bd level2? { /bFill { _fill } def /bCImg { /cDataLen bDataLen store setImgSpace setSSave expandSpot cyData mgData yeData cData expandCMYK true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd } if /expandOne { dup type /stringtype ne { cDataLen string exch dup 0 ne { 255 mul cvi 0 1 cDataLen 1 sub { 3 copy exch put pop } for } if pop } if } bd /expandSpot { spotColor? { spotDict begin spot1 begin tintImage type /nulltype ne { tintImage expandOne /tintImage exch def } if end spot2 begin tintImage type /nulltype ne { tintImage expandOne /tintImage exch def } if end end } if } bd /expandCMYK { 4 { expandOne 4 1 roll } repeat } bd /colorimage where dup { exch pop /ncolorimage where { pop } { /ncolorimage {pop colorimage} bd } ifelse } if not { /ncolorimage where { pop } { /colorimage? false store /ncolorimage { pop pop pop setSSave /blackData xs /yeData xs /mgData xs /cyData xs /cnt1 0 store [ byte dup 0 cyData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .3 /mul cvx } { .3 mul } ifelse mgData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .59 /mul cvx } { .59 mul } ifelse yeData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .11 /mul cvx } { .11 mul } ifelse blackData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx } if /add cvx /add cvx /add cvx 1 /exch cvx /sub cvx /dup cvx 0 /lt cvx { pop 0 } /if cvx /dup cvx 1 /gt cvx { pop 1 } /if cvx 255 /mul cvx /cvi cvx 256 /mod cvx /dup cvx 0 /lt cvx { pop 0 } /if cvx /put cvx /cnt1 dup cvx 1 /add cvx /store cvx ] cvx bind _image_ sSave restore } bd } ifelse } if level2? not { /bCImg { /cDataLen bDataLen store setImgSpace setSSave expandSpot cyData mgData yeData cData colorimage? { expandCMYK } if true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd /bwFill { setSSave /cDataLen 8 store /cData currentgray makeByte store bwImage sSave restore } bd /c1ImgFill { setSSave /cDataLen 8 store setImgSpace spotColor? { spotDict begin spot1 begin currentCustomColor makeByte /tintImage exch def /name exch def /spot_K exch def /spot_Y exch def /spot_M exch def /spot_C exch def end spot2 initSpotData end } if currentcmykcolor 4 { makeByte 4 1 roll } repeat true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd /bFill noImg { { _fill } } { { color? { c1ImgFill } { bwFill } ifelse } } ifelse bd } if composite? { /bCFun { color? { cyData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if mgData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if yeData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if cData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if spotColor? { spotDict begin /spotDict cvx /begin cvx spot1 begin tintImage dup type /stringtype eq { /ndx cvx /get cvx d255- /exch cvx /get cvx } { dup type /nulltype ne { name type /nametype ne {1 exch sub} if } if } ifelse end /spot1 cvx /tintValue 3 -1 /roll cvx /put cvx spot2 begin tintImage dup type /stringtype eq { /ndx cvx /get cvx d255- /exch cvx /get cvx } { dup type /nulltype ne { name type /nametype ne {1 exch sub} if } if } ifelse end /spot2 cvx /tintValue 3 -1 /roll cvx /put cvx /end cvx end /spotDict cvx /nsetcustomcolor cvx } { /setcmykcolor cvx } ifelse } { cData /ndx cvx /get cvx d255 /exch cvx /get cvx /setgray cvx } ifelse } bd /Bc { newpath gsave setBSpace nColors 1 eq { pop pop setCStop } if bFill grestore } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { linImg } { bFill } ifelse grestore nColors 1 gt { getRData } if } bd /rdBm { /nColors dup load 1 sub store _fill gsave bUMatrix astore concat bHi? { xHi yHi bUMatrix idtransform /yHi exch store /xHi exch store rampPoint 1 lt { 1 rampPoint sub dup xHi mul exch yHi mul translate } if } if nColors { 0 0 rampPoint 0 360 arc _fill blend? bHi? or { rdBlend } if nColors 1 gt { getRData } if /nColors dup load 1 sub store } repeat /nColors 1 store grestore } bd /cGetRData { setCStop /blend? cData type /stringtype eq dup not color? and { pop cyData type /stringtype eq mgData type /stringtype eq yeData type /stringtype eq or or } if store } def /cGetRData } if /eCStop { mark 1 index 3 mul 3 add dup 8 gt { pop 8 } if 1 roll cleartomark } bd composite? not { /knockOut level2? { { 0 0 0 0 setcmykcolor _fill } } { /bFill noImg { { _fill } } { { _of true eq { currentgray 1 ne { bwFill } if } { bwFill } ifelse } } ifelse def /whiteByte 1 makeByte def noImg { { 0 0 0 0 setcmykcolor _fill } } { { cBType 0 eq { setSSave /cData whiteByte store /cDataLen 8 store bwImage sSave restore } { _fill } ifelse } } ifelse } ifelse bd /bCFun { cData dup type /stringtype ne { color? { 1 exch sub } if } { /ndx cvx /get cvx color? customColor? not and { d255- } { d255 } ifelse /exch cvx /get cvx } ifelse /_setgray_ cvx } bd /eCCBlend { dup 3 eq { pop mark 7 1 roll 6 copy ccThrough? dup /blend? xs { /startC? true store setCustomColor customColor? { /cData tint1Data store setCDataLen } if /endC? 3 index 3 eq { 4 index 1 ne } { false } ifelse store } if cleartomark stop } if 1 eq { pop pop pop } if pop /startC? false store 6 { 8 index } repeat ccThrough? dup /blend? xs { /endC? true store blend? not { stop } if customColor? { /cData tint1Data store setCDataLen } if } if } bd /handleOP { _of not { knockOut } if } bd /handleROP { _of not { 0 0 0 0 setcmykcolor _fill } { newpath } ifelse } bd /rdBm { /nColors dup load 1 sub store blend? { _fill } { handleROP } ifelse gsave bUMatrix astore concat bHi? { xHi yHi bUMatrix idtransform /yHi exch store /xHi exch store rampPoint 1 lt { 1 rampPoint sub dup xHi mul exch yHi mul translate } if } if nColors { 0 0 rampPoint 0 360 arc blend? { cData type /stringtype ne bHi? not and { cData color? { 1 exch sub } if _setgray_ _fill_ } { cData type /stringtype ne { /cDataLen 1 store /bDataLen 1 store } if rdBlend } ifelse } { handleROP pTState? { /bAxis rampPoint endPoint sub store xHi bAxis mul yHi bAxis mul translate } if } ifelse nColors 1 gt { getRData } if /nColors dup load 1 sub store } repeat /nColors 1 store grestore } bd /ccThrough? { gsave pop 0 setCustomColor currentcmykcolor grestore anyColor? } bd /forceCMYK { exch pop 1 exch sub 5 1 roll 4 { 4 index mul 4 1 roll } repeat 0 cCMYKData dup /cData ne { dup /yeData eq { pop 1 add } { /mgData eq { 2 } { 3 } ifelse add } ifelse 0 } if pop index 0 eq { pop pop pop pop 0 0 0 0 } if setcmykcolor pop /fCMYK? true store } bd /endCapSepBc { pop pop dup 0 eq { pop setgray } { 1 eq { setcmykcolor } { colorType 1 eq { forceCMYK } { fCMYK? { forceCMYK } { setCustomColor } ifelse } ifelse } ifelse } ifelse currentcmykcolor anyColor? blend? and { bFill } { handleOP } ifelse } bd } if /cCMYKData 0 def composite? dup not { pop customColor? } if not { /cCMYKData /cyData /mgData /yeData /cData black? not { yellow? { exch } { magenta? { 3 } { 4 } ifelse -1 roll } ifelse } if 4 1 roll pop pop pop store /Bc { gsave setBSpace nColors 1 gt { blend? currentcmykcolor anyColor? and { bFill } { handleOP } ifelse } { endCapSepBc } ifelse grestore newpath } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { cCMYKData load dup type /stringtype eq { dup length /cDataLen xs /cData xs gsave colorType 0 ne noImg not and { invertXfer } if linImg grestore } { pop bFill } ifelse } { handleOP } ifelse grestore nColors 1 gt { getRData } if } bd /cmykGetRData { /fCMYK? false store blend? { { cmykDataProcs colorType get exec } stopped pop blend? { /cData cCMYKData load store setCDataLen } if } if } def /cmykDataProcs [ { pop black? dup /blend? xs { setgray 0 } if pop } { cCMYKData load dup type /stringtype ne { 0 0 0 cyan? not { 4 magenta? { 1 } { yellow? { 2 } { 3 } ifelse } ifelse roll } if 4 copy add add add 0 eq { /blend? false store } if setcmykcolor /startC? true store /endC? true store eCStop stop } if pop dup 0 eq { pop setgray } { 1 eq { setcmykcolor } { forceCMYK } ifelse } ifelse } bind /eCCBlend load { cBType 1 eq { tint1Data tint2Data /tint1Data xs /tint2Data xs } if 0 eq { black? { setgray } { 0 0 0 4 -1 roll 1 exch sub setcmykcolor } ifelse black? { /blend? true store } if 6 { 8 index } repeat ccThrough? { /blend? true store } { black? { /cData tint1Data store setCDataLen } { /blend? false store } ifelse } ifelse } { mark 7 1 roll 6 copy ccThrough? { forceCMYK pop stop } if 9 index 0 eq { black? dup /blend? xs { pop 1 setgray /cData tint2Data store setCDataLen 0 } if pop } { /blend? 6 { 16 index } repeat ccThrough? store blend? { forceCMYK } if } ifelse cleartomark } ifelse } bind ] def /cmykGetRData } if composite? dup not { pop isCMYKSep? } if not { /endCapSepBc { /white? false store pop pop dup 0 eq { pop /white? 1 index 1 eq store setgray } { 1 eq { setcmykcolor } { setCustomColor } ifelse } ifelse % currentcmykcolor anyColor? endC? or blend? and { bFill } { handleOP } ifelse } bd /Bc { gsave setBSpace nColors 1 gt { blend? startC? and { bFill } { handleOP } ifelse } { endCapSepBc } ifelse grestore newpath } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { cData type /stringtype eq { linImg } { bFill } ifelse } { handleOP } ifelse grestore nColors 1 gt { getRData } if } bd /discardCMY { counttomark 4 add -3 roll pop pop pop } bd /testTopCC { 6 copy ccThrough? } bd /getCRamp { { ccDataProcs colorType 2 sub get exec } stopped pop blend? cDataLen 0 eq and { /cDataLen bDataLen store } if } bd /ccGetRData { /fCMYK? false store /startC? false store /endC? false store colorType 2 lt { /blend? false def } if blend? { getCRamp } { setCStop } ifelse blend? { /blend? cData 1 ne store blend? { cData dup type /stringtype ne { 1 exch sub /cData xs 0 } if pop } if } if } def /ccDataProcs [ /eCCBlend load { cBType 1 eq { tint1Data tint2Data /tint1Data xs /tint2Data xs } if 0 eq { /blend? false store pop } { mark 7 1 roll testTopCC { /blend? 1 index 1 ne store /startC? blend? store /endC? false store blend? not { cleartomark stop } if /cData tint1Data store setCDataLen setCustomColor pop stop } if cleartomark } ifelse 2 index 0 eq { /blend? false store } { mark 6 { 9 index } repeat testTopCC dup /blend? xs { /blend? 1 index 1 ne store /endC? blend? store /startC? false store blend? not { cleartomark stop } if /cData tint2Data store setCDataLen } if cleartomark } ifelse } bind ] def /ccGetRData } if load Adobe_blend_AI5_vars /getData 3 -1 roll put /setCDataLen { /cDataLen 0 cData dup type /stringtype eq { length exch } if pop store } bd /initSpotData { begin /name null def /tintImage null def /tintValue null def /spot_C null def /spot_M null def /spot_Y null def /spot_K null def end } bd /getRData { /colorType gMark store _compositeSpotDevice 0 ne { spotDict begin spot1 initSpotData spot2 initSpotData end /spotColor? colorType 2 eq colorType 3 eq or def } { /spotColor? false store } ifelse /blend? true store 0 0 0 0 setcmykcolor 100 div /rampPoint xs % (between 13 and 87%) 100 div /midPoint xs dup 0 eq { 2 } { dup 1 eq { 5 } { _compositeSpotDevice 0 ne { spotDict begin spot1 begin /name 3 index def /spot_K 4 index def /spot_Y 5 index def /spot_M 6 index def /spot_C 7 index def end end } if 7 } ifelse } ifelse /tmp exch def tmp index 100 div /endPoint xs _compositeSpotDevice 0 ne { tmp 2 add index 3 eq { /tmp tmp 4 add def tmp index dup spotDict begin spot1/name get ne { spot2 begin /name exch def /spot_K tmp 2 add index def /spot_Y tmp 3 add index def /spot_M tmp 4 add index def /spot_C tmp 5 add index def end } { pop } ifelse end } if } if /color? colorType 0 gt store colorType 3 eq { /tint2Data gMark store } if colorType 2 ge { /tint1Data gMark store } if _compositeSpotDevice 0 ne { spotDict begin colorType 2 ge { colorType 3 eq { spot2 begin /tintImage cBType 0 eq {tint2Data} {tint1Data} ifelse def name null eq {/name /Black def} if end } if spot1 begin /tintImage cBType 0 eq colorType 2 eq or {tint1Data} {tint2Data} ifelse def colorType 2 eq { name null eq { /name spot2/name get def spot2/name null put } if } { name null eq {/name /Black def} if } ifelse end } if end } if /cData gMark store setCDataLen colorType 0 gt { counttomark 4 add -3 roll /yeData xs /mgData xs /cyData xs } if blend? { /bDataLen cDataLen dup 0 eq color? and { [ cyData mgData yeData ] { dup type /stringtype eq { length exch pop exit } if pop } forall } if store bDataLen 0 eq { /bDataLen 1 store } if getData blend? { composite? cDataLen 0 eq and { /cDataLen bDataLen store } if } if } { setCStop } ifelse } bd /Bg { 0 0 0 0 setcmykcolor 6 { pop } repeat /blendLength xs pop pop pop /cBName xs /bRender xs bRender 2 ne { composite? not { _of setoverprint } if _eo {eoclip} {clip} ifelse _bn cBName 2 copy known { get mark exch aload pop /cBType xs /nColors xs mark exch aload pop 0 0 } if pop pop getRData cBType 0 eq { /linealBm } { bHi? { /pTState? nColors 2 gt store } if /doBlend /rdBlend load store /rdBm } ifelse } { inLine? not { mark mark } if /Bc dup { cleartomark mark } bd /nullProc } ifelse load /Bm xs } bd /linImg noImg { { newpath doRctBlend } } { { /doBlend color? composite? and { /bCImg } { /bwImage } ifelse load store 0 0 moveto tRectOK? composite? and { { mark 0 1 dtransform atan cvi 90 mod 0 eq 1 0 dtransform atan cvi 90 mod 0 eq } stopped { cleartomark } { and exch pop { newpath doRctBlend } { doBlend } ifelse } ifelse } { doBlend } ifelse } } ifelse bd /doRctBlend { gsave /sInc 1 store /nSamples bDataLen store /bInc 1 bDataLen div store /ubAxis 1 0 dtransform dUserSpace idtransform dup mul exch dup mul add sqrt store /pChange ubAxis 0 eq { 0 } { bDataLen ubAxis div } ifelse store pChange .5 gt noImg not and dup /optimize? xs { /nSamples ubAxis 2 div round cvi dup 1 le { pop 2 } if store /bInc 1 nSamples div store /sInc bDataLen 1 sub nSamples 1 sub div store } if 0 nSamples [ /dup cvx optimize? { /round cvx /cvi cvx } if /ndx /exch cvx /store cvx bCFun /rectfill where dup { exch pop _compositeSpotDevice 1 ne and } if { 0 0 bInc 1 /rectfill cvx } { 0 0 /moveto cvx bInc 0 /lineto cvx bInc 1 /lineto cvx 0 1 /lineto cvx /closepath cvx /_fill_ cvx } ifelse bInc 0 /translate cvx sInc /add cvx ] cvx bind repeat pop spotColor? {nsetcustomcolorend} if grestore } bd /rdPrep { /nSamples bDataLen dup 0 eq { pop 1 } if store /sInc -1 store /bAxis rampPoint endPoint sub store /bInc bAxis bDataLen div neg store /optimize? false store tRectOK? { /ubAxis bAxis 0 dtransform dUserSpace idtransform dup mul exch dup mul add sqrt 0 bAxis dtransform dUserSpace idtransform dup mul exch dup mul add sqrt 2 copy lt { exch } if pop store /pChange ubAxis 0 eq { 0 } { bDataLen ubAxis div } ifelse store pChange .5 gt noImg not and dup /optimize? xs { /nSamples ubAxis 2 div round cvi dup 1 le { pop 2 } if store /bInc bAxis nSamples div neg store /sInc bDataLen 1 sub nSamples 1 sub div neg store } if } if bHi? { /xBCInc xHi bAxis mul nSamples div store /yBCInc yHi bAxis mul nSamples div store } if } bd /rdBlend { newpath gsave rdPrep rampPoint bDataLen 1 sub nSamples [ /dup cvx optimize? { /round cvx /cvi cvx } if /ndx /exch cvx /store cvx bCFun 0 0 3 /index cvx 0 360 /arc cvx /_fill_ cvx /exch cvx bInc /add cvx /exch cvx sInc /add cvx bHi? { xBCInc yBCInc /translate cvx } if ] cvx bind repeat pop pop spotColor? {nsetcustomcolorend} if grestore pTState? { xHi bAxis mul yHi bAxis mul translate } if } bd /Bh { pop pop /pTState? false store 2 copy 0 ne exch 0 ne or dup /bHi? xs { /yHi xs /xHi xs 0 0 } if pop pop } bd /BD { inLine? not { ] nColors cBType ] _bn cBName 3 -1 roll put end } if } bd /Bn { 1 add dict dup nullString null put /_bn xs } bd /Bd { Adobe_blend_AI5_vars begin 3 -1 roll dup nullString eq dup { setSSave } if /inLine? exch def /cBName exch def /nColors exch def /cBType exch def } bd /Bb { sSave null eq { Adobe_blend_AI5_vars begin setSSave } if composite? { /_fill /fill load store } { /__fill /fill load store /_fill { _of true eq { currentgray 1 ne { __fill } if } { __fill } ifelse } def } ifelse /fill { } def } bd /BB { /cBType xs cleartomark cleartomark cBType dup bRender sSave dup type /savetype eq { restore 0 } if pop currentdict Adobe_blend_AI5_vars eq { end } if 2 ne exch 0 gt and { 2 eq { s } { S } ifelse } { pop newpath } ifelse } bd currentdict readonly pop end end defaultpacking setpacking %%EndResource %%BeginResource: procset Adobe_pattern_AI5 1.1 0 %%Title: (Adobe Illustrator (R) Version 5.0 Pattern Operators) %%Version: 1.1 0 %%CreationDate: (03/26/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_Illustrator_AI5 known not { userdict /Adobe_Illustrator_AI5 95 dict put } if userdict /Adobe_Illustrator_AI5 get begin /@ { } def /& { } def /dp { dup null eq { pop _dp 0 ne { 0 1 _dp 1 sub _dl mod { _da exch get 3 get } for _dp 1 sub _dl mod 1 add packedarray _da 0 get aload pop 8 -1 roll 5 -1 roll pop 4 1 roll definepattern pop } if } { _dp 0 ne _dp _dl mod 0 eq and { null dp } if 7 packedarray _da exch _dp _dl mod exch put _dp _dl mod _da 0 get 4 get 2 packedarray /_dp _dp 1 add def } ifelse } def /E { _ed begin dup 0 get type /arraytype ne { 0 { dup 1 add index type /arraytype eq { 1 add } { exit } ifelse } loop array astore } if /_dd exch def /_ury exch def /_urx exch def /_lly exch def /_llx exch def /_n exch def /_y 0 def /_dl 4 def /_dp 0 def /_da _dl array def 0 1 _dd length 1 sub { /_d exch _dd exch get def 0 2 _d length 2 sub { /_x exch def /_c _d _x get _ ne def /_r _d _x 1 add get cvlit def _r _ ne { _urx _llx sub _ury _lly sub [ 1 0 0 1 0 0 ] [ /save cvx _llx neg _lly neg /translate cvx _c { nc /begin cvx } if _r dup type /stringtype eq { cvx } { { exec } /forall cvx } ifelse _c { /end cvx } if /restore cvx ] cvx /_fn 12 _n length add string def _y _fn cvs pop /_y _y 1 add def _fn 12 _n putinterval _fn _c false dp _d exch _x 1 add exch put } if } for } for null dp _n _dd /_pd end xput } def /fc { _fm dup concatmatrix pop } def /p { /_fm exch ddef 9 -2 roll _pm translate fc 7 -2 roll _pm scale fc 5 -1 roll _pm rotate fc 4 -2 roll exch 0 ne { dup _pm rotate fc 1 -1 _pm scale fc neg _pm rotate fc } { pop } ifelse dup _pm rotate fc exch dup sin exch cos div 1 0 0 1 0 6 2 roll _pm astore fc neg _pm rotate fc _pd exch get /_fdd exch ddef /_pf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm patternfill } { pop fill } ifelse grestore pop } for pop } for restore newpath } ddef /_psf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm 9 copy 6 npop patternashow } { pop 6 copy 3 npop hvashow } ifelse grestore pop } for pop } for restore sw rmoveto } ddef /_pjsf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm 12 copy 6 npop patternawidthshow } { pop 9 copy 3 npop hvawidthshow } ifelse grestore pop } for pop } for restore swj rmoveto } ddef /_lp /none ddef } def /sc { _sm dup concatmatrix pop } def /P { /_sm exch ddef 9 -2 roll _pm translate sc 7 -2 roll _pm scale sc 5 -1 roll _pm rotate sc 4 -2 roll exch 0 ne { dup _pm rotate sc 1 -1 _pm scale sc neg _pm rotate sc } { pop } ifelse dup _pm rotate sc exch dup sin exch cos div 1 0 0 1 0 6 2 roll _pm astore sc neg _pm rotate sc _pd exch get /_sdd exch ddef /_ps { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm patternstroke } { pop stroke } ifelse grestore pop } for pop } for restore newpath } ddef /_pss { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm 10 copy 6 npop patternashowstroke } { pop 7 copy 3 npop ss } ifelse grestore pop } for pop } for restore pop sw rmoveto } ddef /_pjss { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm 13 copy 6 npop patternawidthshowstroke } { pop 10 copy 3 npop jss } ifelse grestore pop } for pop } for restore pop swj rmoveto } ddef /_lp /none ddef } def end userdict /Adobe_pattern_AI5 18 dict dup begin put /initialize { /definepattern where { pop } { begin begin Adobe_pattern_AI5 begin Adobe_pattern_AI5 { dup xcheck { bind } if pop pop } forall mark cachestatus 7 1 roll pop pop pop pop exch pop exch { { 10000 add dup 2 index gt { exit } if dup setcachelimit } loop } stopped cleartomark end end end Adobe_pattern_AI5 begin } ifelse } def /terminate { currentdict Adobe_pattern_AI5 eq { end } if } def errordict /nocurrentpoint { pop stop } put errordict /invalidaccess { pop stop } put /patternencoding 256 array def 0 1 255 { patternencoding exch ( ) 2 copy exch 0 exch put cvn put } for /definepattern { 17 dict begin /uniform exch def /cache exch def /key exch def /procarray exch def /mtx exch matrix invertmatrix def /height exch def /width exch def /ctm matrix currentmatrix def /ptm matrix def /str 32 string def /slice 9 dict def slice /s 1 put slice /q 256 procarray length div sqrt floor cvi put slice /b 0 put /FontBBox [ 0 0 0 0 ] def /FontMatrix mtx matrix copy def /Encoding patternencoding def /FontType 3 def /BuildChar { exch begin /setstrokeadjust where {pop true setstrokeadjust} if slice begin dup q dup mul mod s idiv /i exch def dup q dup mul mod s mod /j exch def q dup mul idiv procarray exch get /xl j width s div mul def /xg j 1 add width s div mul def /yl i height s div mul def /yg i 1 add height s div mul def uniform { 1 1 } { width 0 dtransform dup mul exch dup mul add sqrt dup 1 add exch div 0 height dtransform dup mul exch dup mul add sqrt dup 1 add exch div } ifelse width 0 cache { xl 4 index mul yl 4 index mul xg 6 index mul yg 6 index mul setcachedevice } { setcharwidth } ifelse gsave scale newpath xl yl moveto xg yl lineto xg yg lineto xl yg lineto closepath clip newpath end end exec grestore } def key currentdict definefont end } def /patterncachesize { gsave newpath 0 0 moveto width 0 lineto width height lineto 0 height lineto closepath patternmatrix setmatrix pathbbox exch ceiling 4 -1 roll floor sub 3 1 roll ceiling exch floor sub mul 1 add grestore } def /patterncachelimit { cachestatus 7 1 roll 6 npop 8 mul } def /patternpath { exch dup begin setfont ctm setmatrix concat slice exch /b exch slice /q get dup mul mul put FontMatrix concat uniform { width 0 dtransform round width div exch round width div exch 0 height dtransform round height div exch height div exch 0 0 transform round exch round exch ptm astore setmatrix } { ptm currentmatrix pop } ifelse { currentpoint } stopped not { 2 npop pathbbox true 4 index 3 index eq 4 index 3 index eq and { pop false { { 2 npop } { 3 npop true } { 7 npop true } { pop true } pathforall } stopped { 5 npop true } if } if { height div ceiling height mul 4 1 roll width div ceiling width mul 4 1 roll height div floor height mul 4 1 roll width div floor width mul 4 1 roll 2 index sub height div ceiling cvi exch 3 index sub width div ceiling cvi exch 4 2 roll moveto FontMatrix mtx invertmatrix dup dup 4 get exch 5 get rmoveto ptm ptm concatmatrix pop slice /s patterncachesize patterncachelimit div ceiling sqrt ceiling cvi dup slice /q get gt { pop slice /q get } if put 0 1 slice /s get dup mul 1 sub { slice /b get add gsave 0 1 str length 1 sub { str exch 2 index put } for pop dup { gsave ptm setmatrix 1 index str length idiv { str show } repeat 1 index str length mod str exch 0 exch getinterval show grestore 0 height rmoveto } repeat grestore } for 2 npop } { 4 npop } ifelse } if end } def /patternclip { _eo {eoclip} {clip} ifelse } def /patternstrokepath { strokepath } def /patternmatrix matrix def /patternfill { dup type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get } if gsave patternclip Adobe_pattern_AI5 /patternpath get exec grestore newpath } def /patternstroke { dup type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get } if gsave patternstrokepath true { { { newpath moveto } { lineto } { curveto } { closepath 3 copy Adobe_pattern_AI5 /patternfill get exec } pathforall 3 npop } stopped { 5 npop patternclip Adobe_pattern_AI5 /patternfill get exec } if } { patternclip Adobe_pattern_AI5 /patternfill get exec } ifelse grestore newpath } def /vpatternawidthshow { 6 1 roll /_hvay exch ddef /_hvax exch ddef /_hvwb exch ddef /_hvcy exch ddef /_hvcx exch ddef { dup cstring dup length 1 eq _charorientation 1 eq and { -90 rotate currentpoint _fontRotateAdjust add moveto gsave false charpath currentpoint 5 index 5 index 5 index Adobe_pattern_AI5 /patternfill get exec grestore _fontRotateAdjust sub moveto _hvwb eq { _hvcx _hvcy rmoveto } if _hvax _hvay rmoveto 90 rotate } { currentpoint _fontHeight sub _hvax sub 3 index _hvwb eq { _hvcx sub } if currentpoint exch 4 index stringwidth pop 2 div sub exch _fontAscent sub moveto gsave 2 index false charpath 6 index 6 index 6 index Adobe_pattern_AI5 /patternfill get exec grestore newpath moveto pop pop } ifelse } cforall 3 npop } def /hpatternawidthshow { { dup cstring exch gsave 3 index eq { 5 index 5 index rmoveto } if false charpath currentpoint 9 index 9 index 9 index Adobe_pattern_AI5 /patternfill get exec grestore newpath moveto 2 copy rmoveto } cforall 8 npop } def /patternashow { 0 0 0 6 3 roll patternawidthshow } def /patternawidthshow { 6 index type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get 7 1 roll } if _lineorientation 0 eq { hpatternawidthshow } { vpatternawidthshow } ifelse } def /vpatternawidthshowstroke { 7 1 roll 6 1 roll /_hvay exch ddef /_hvax exch ddef /_hvwb exch ddef /_hvcy exch ddef /_hvcx exch ddef { dup cstring dup length 1 eq _charorientation 1 eq and { -90 rotate currentpoint _fontRotateAdjust add moveto gsave false charpath currentpoint 3 index setmatrix 6 index 6 index 6 index Adobe_pattern_AI5 /patternstroke get exec grestore _fontRotateAdjust sub moveto _hvwb eq { _hvcx _hvcy rmoveto } if _hvax _hvay rmoveto 90 rotate } { currentpoint _fontHeight sub _hvax sub 3 index _hvwb eq { _hvcx sub } if currentpoint exch 4 index stringwidth pop 2 div sub exch _fontAscent sub moveto gsave 2 index false charpath 4 index setmatrix 7 index 7 index 7 index Adobe_pattern_AI5 /patternstroke get exec grestore newpath moveto pop pop } ifelse } cforall 4 npop } def /hpatternawidthshowstroke { 7 1 roll { dup cstring exch gsave 3 index eq { 5 index 5 index rmoveto } if false charpath currentpoint 7 index setmatrix 10 index 10 index 10 index Adobe_pattern_AI5 /patternstroke get exec grestore newpath moveto 2 copy rmoveto } cforall 9 npop } def /patternashowstroke { 0 0 0 7 3 roll patternawidthshowstroke } def /patternawidthshowstroke { 7 index type /dicttype eq { patternmatrix /patternmatrix get 8 1 roll } if _lineorientation 0 eq { hpatternawidthshowstroke } { vpatternawidthshowstroke } ifelse } def end setpacking %%EndResource %%EndProlog %%BeginSetup Adobe_level2_AI5 /initialize get exec Adobe_screens_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_typography_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_blend_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_pattern_AI5 /initialize get exec Adobe_ColorImage_AI6 /initialize get exec Adobe_Illustrator_AI5 /initialize get exec [ 39/quotesingle 96/grave 130/quotesinglbase 131/florin 132/quotedblbase 133/ellipsis 134/dagger 135/daggerdbl 136/circumflex 137/perthousand 138/Scaron 139/guilsinglleft 140/OE 145/quoteleft 146/quoteright 147/quotedblleft 148/quotedblright 149/bullet 150/endash 151/emdash 152/tilde 153/trademark 154/scaron 155/guilsinglright 156/oe 157/dotlessi 159/Ydieresis 164/currency 166/brokenbar 168/dieresis 169/copyright 170/ordfeminine 172/logicalnot 174/registered 175/macron 176/ring 177/plusminus 178/twosuperior 179/threesuperior 180/acute 181/mu 183/periodcentered 184/cedilla 185/onesuperior 186/ordmasculine 188/onequarter 189/onehalf 190/threequarters 192/Agrave 193/Aacute 194/Acircumflex 195/Atilde 196/Adieresis 197/Aring 198/AE 199/Ccedilla 200/Egrave 201/Eacute 202/Ecircumflex 203/Edieresis 204/Igrave 205/Iacute 206/Icircumflex 207/Idieresis 208/Eth 209/Ntilde 210/Ograve 211/Oacute 212/Ocircumflex 213/Otilde 214/Odieresis 215/multiply 216/Oslash 217/Ugrave 218/Uacute 219/Ucircumflex 220/Udieresis 221/Yacute 222/Thorn 223/germandbls 224/agrave 225/aacute 226/acircumflex 227/atilde 228/adieresis 229/aring 230/ae 231/ccedilla 232/egrave 233/eacute 234/ecircumflex 235/edieresis 236/igrave 237/iacute 238/icircumflex 239/idieresis 240/eth 241/ntilde 242/ograve 243/oacute 244/ocircumflex 245/otilde 246/odieresis 247/divide 248/oslash 249/ugrave 250/uacute 251/ucircumflex 252/udieresis 253/yacute 254/thorn 255/ydieresis TE %AI3_BeginEncoding: _Helvetica Helvetica [ /_Helvetica/Helvetica 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-Bold Helvetica-Bold [ /_Helvetica-Bold/Helvetica-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-Oblique Helvetica-Oblique [ /_Helvetica-Oblique/Helvetica-Oblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-BoldOblique Helvetica-BoldOblique [ /_Helvetica-BoldOblique/Helvetica-BoldOblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Roman Times-Roman [ /_Times-Roman/Times-Roman 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Bold Times-Bold [ /_Times-Bold/Times-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Italic Times-Italic [ /_Times-Italic/Times-Italic 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-BoldItalic Times-BoldItalic [ /_Times-BoldItalic/Times-BoldItalic 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier Courier [ /_Courier/Courier 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-Bold Courier-Bold [ /_Courier-Bold/Courier-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-Oblique Courier-Oblique [ /_Courier-Oblique/Courier-Oblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-BoldOblique Courier-BoldOblique [ /_Courier-BoldOblique/Courier-BoldOblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Symbol Symbol [ /_Symbol/Symbol 0 0 1 TZ %AI3_EndEncoding AdobeType %%EndSetup 1 XR u 0.000 0.000 0.000 0.000 k [] 0 d 1.0000 w 0.000 0.000 0.000 1.000 K 1 j 144.8386 414.9884 m 198.6290 414.9884 L 198.6290 432.9584 L 144.8386 432.9584 L 144.8386 414.9884 L B U 0 To 1.0000 0.0000 0.0000 1.0000 148.7920 421.5774 0 Tp TP /_Helvetica-Bold 8.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (configure.in\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.000 k 1.0000 w 0.000 0.000 0.000 1.000 K 1 j 216.5990 414.9884 m 306.3295 414.9884 L 306.3295 432.9584 L 216.5990 432.9584 L 216.5990 414.9884 L B U 0 To 1.0000 0.0000 0.0000 1.0000 226.1830 421.5774 0 Tp TP /_Helvetica-Bold 8.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (../sofia-version.m4\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.000 k 1.0000 w 0.000 0.000 0.000 1.000 K 1 j 315.3145 414.9884 m 369.1048 414.9884 L 369.1048 432.9584 L 315.3145 432.9584 L 315.3145 414.9884 L B U 0 To 1.0000 0.0000 0.0000 1.0000 322.5025 421.5774 0 Tp TP /_Helvetica-Bold 8.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (../sofia.m4\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.000 k 1.0000 w 0.000 0.000 0.000 1.000 K 1 j 353.4110 379.1681 m 438.5890 379.1681 L 438.5890 397.1381 L 353.4110 397.1381 L 353.4110 379.1681 L B U 0 To 1.0000 0.0000 0.0000 1.0000 359.4010 385.7571 0 Tp TP /_Helvetica-Bold 8.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (/usr/share/aclocal/*\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.000 k 1.0000 w 0.000 0.000 0.000 1.000 K 1 j 292.9118 340.2329 m 293.0316 342.7488 L 293.7504 345.2646 L 294.9484 347.6606 L 296.5058 349.9368 L 298.4226 352.0932 L 300.8186 354.1298 L 303.4542 355.9268 L 306.4493 357.4842 L 309.6839 358.8020 L 313.1581 359.8802 L 316.7521 360.5990 L 320.4659 361.0782 L 324.2995 361.1980 L 328.0133 361.0782 L 331.7271 360.5990 L 335.3211 359.8802 L 338.7953 358.8020 L 342.0300 357.4842 L 345.0250 355.9268 L 347.7804 354.1298 L 350.0566 352.0932 L 352.0932 349.9368 L 353.6506 347.6606 L 354.7288 345.2646 L 355.4476 342.7488 L 355.6872 340.2329 L 355.4476 337.7171 L 354.7288 335.2013 L 353.6506 332.8053 L 352.0932 330.5291 L 350.0566 328.3727 L 347.7804 326.4559 L 345.0250 324.6589 L 342.0300 323.1015 L 338.7953 321.7837 L 335.3211 320.7055 L 331.7271 319.9867 L 328.0133 319.5075 L 324.2995 319.3877 L 320.4659 319.5075 L 316.7521 319.9867 L 313.1581 320.7055 L 309.6839 321.7837 L 306.4493 323.1015 L 303.4542 324.6589 L 300.8186 326.4559 L 298.4226 328.3727 L 296.5058 330.5291 L 294.9484 332.8053 L 293.7504 335.2013 L 293.0316 337.7171 L 292.9118 340.2329 L B U 0 To 1.0000 0.0000 0.0000 1.0000 310.6423 337.8369 0 Tp TP /_Helvetica-Bold 8.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (aclocal\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 J 1 j 171.7937 414.9884 m 301.4176 362.1564 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 301.8968 365.3910 m 309.5641 358.8020 L 299.3810 359.4010 L 301.8968 365.3910 L F U u 0.5000 w 0.000 0.000 0.000 1.000 K 396.0599 379.1681 m 349.2180 361.1980 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 351.1348 358.4426 m 340.8319 357.9634 L 348.7388 364.5524 L 351.1348 358.4426 L F U u 0.5000 w 0.000 0.000 0.000 1.000 K 261.4043 414.9884 m 317.5907 366.9484 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 319.0283 369.9434 m 324.2995 361.1980 L 314.8353 365.0316 L 319.0283 369.9434 L F U u 0.5000 w 0.000 0.000 0.000 1.000 K 342.1498 414.9884 m 333.1647 369.3444 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 336.5191 369.5840 m 331.4875 360.5990 L 330.1697 370.7820 L 336.5191 369.5840 L F U u 0.000 0.000 0.000 0.000 k 1.0000 w 0.000 0.000 0.000 1.000 K 297.3444 271.4676 m 351.1348 271.4676 L 351.1348 289.4376 L 297.3444 289.4376 L 297.3444 271.4676 L B U 0 To 1.0000 0.0000 0.0000 1.0000 303.6938 278.0566 0 Tp TP /_Helvetica-Bold 8.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (aclocal.m4\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 324.2995 319.3877 m 324.2995 317.9501 L S U u 0.000 0.000 0.000 1.000 K 324.2995 316.5125 m 324.2995 315.0749 L S U u 324.2995 313.6373 m 324.2995 312.1997 L S U u 324.2995 310.7621 m 324.2995 309.3245 L S U u 324.2995 307.8869 m 324.2995 306.4493 L S U u 324.2995 305.0116 m 324.2995 303.5740 L S U u 324.2995 302.1364 m 324.2995 300.6988 L S U u 324.2995 299.2612 m 324.2995 298.3028 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 327.4143 299.1414 m 324.2995 289.4376 L 321.0649 299.1414 L 327.4143 299.1414 L F U u 0.000 0.000 0.000 0.000 k 1.0000 w 0.000 0.000 0.000 1.000 K 140.2862 205.6972 m 140.5258 208.2130 L 141.2446 210.7288 L 142.4426 213.1248 L 144.0000 215.4010 L 145.9168 217.5574 L 148.1930 219.5940 L 150.9484 221.3910 L 153.9434 222.9484 L 157.1780 224.2662 L 160.6522 225.3444 L 164.2463 226.0632 L 167.9601 226.5424 L 171.7937 226.6622 L 175.6273 226.5424 L 179.3411 226.0632 L 182.8153 225.3444 L 186.2895 224.2662 L 189.5241 222.9484 L 192.5191 221.3910 L 195.1547 219.5940 L 197.5507 217.5574 L 199.4676 215.4010 L 201.0250 213.1248 L 202.2230 210.7288 L 202.9418 208.2130 L 203.0616 205.6972 L 202.9418 203.1814 L 202.2230 200.6656 L 201.0250 198.2696 L 199.4676 195.9933 L 197.5507 193.8369 L 195.1547 191.8003 L 192.5191 190.0033 L 189.5241 188.4459 L 186.2895 187.1281 L 182.8153 186.0499 L 179.3411 185.3311 L 175.6273 184.8519 L 171.7937 184.7321 L 167.9601 184.8519 L 164.2463 185.3311 L 160.6522 186.0499 L 157.1780 187.1281 L 153.9434 188.4459 L 150.9484 190.0033 L 148.1930 191.8003 L 145.9168 193.8369 L 144.0000 195.9933 L 142.4426 198.2696 L 141.2446 200.6656 L 140.5258 203.1814 L 140.2862 205.6972 L B U 0 To 1.0000 0.0000 0.0000 1.0000 154.9018 203.3012 0 Tp TP /_Helvetica-Bold 8.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (autoconf\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.000 k 1.0000 w 0.000 0.000 0.000 1.000 K 1 j 292.9118 205.6972 m 293.0316 208.2130 L 293.7504 210.7288 L 294.9484 213.1248 L 296.5058 215.4010 L 298.4226 217.5574 L 300.8186 219.5940 L 303.4542 221.3910 L 306.4493 222.9484 L 309.6839 224.2662 L 313.1581 225.3444 L 316.7521 226.0632 L 320.4659 226.5424 L 324.2995 226.6622 L 328.0133 226.5424 L 331.7271 226.0632 L 335.3211 225.3444 L 338.7953 224.2662 L 342.0300 222.9484 L 345.0250 221.3910 L 347.7804 219.5940 L 350.0566 217.5574 L 352.0932 215.4010 L 353.6506 213.1248 L 354.7288 210.7288 L 355.4476 208.2130 L 355.6872 205.6972 L 355.4476 203.1814 L 354.7288 200.6656 L 353.6506 198.2696 L 352.0932 195.9933 L 350.0566 193.8369 L 347.7804 191.8003 L 345.0250 190.0033 L 342.0300 188.4459 L 338.7953 187.1281 L 335.3211 186.0499 L 331.7271 185.3311 L 328.0133 184.8519 L 324.2995 184.7321 L 320.4659 184.8519 L 316.7521 185.3311 L 313.1581 186.0499 L 309.6839 187.1281 L 306.4493 188.4459 L 303.4542 190.0033 L 300.8186 191.8003 L 298.4226 193.8369 L 296.5058 195.9933 L 294.9484 198.2696 L 293.7504 200.6656 L 293.0316 203.1814 L 292.9118 205.6972 L B U 0 To 1.0000 0.0000 0.0000 1.0000 302.7354 203.3012 0 Tp TP /_Helvetica-Bold 8.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (autoheader\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.000 k 1.0000 w 0.000 0.000 0.000 1.000 K 1 j 14.7354 206.6556 m 14.9750 209.1714 L 15.6938 211.6872 L 16.7720 214.0832 L 18.3295 216.4792 L 20.3661 218.6356 L 22.6423 220.5524 L 25.3977 222.3494 L 28.3927 223.9068 L 31.6273 225.2246 L 35.1015 226.3028 L 38.5757 227.0216 L 42.2895 227.5008 L 46.1231 227.6206 L 49.9567 227.5008 L 53.6705 227.0216 L 57.2646 226.3028 L 60.7388 225.2246 L 63.9734 223.9068 L 66.9684 222.3494 L 69.6040 220.5524 L 72.0000 218.6356 L 73.9168 216.4792 L 75.4742 214.0832 L 76.6722 211.6872 L 77.3910 209.1714 L 77.5108 206.6556 L 77.3910 204.1398 L 76.6722 201.6240 L 75.4742 199.2280 L 73.9168 196.9517 L 72.0000 194.7953 L 69.6040 192.7587 L 66.9684 190.9617 L 63.9734 189.4043 L 60.7388 188.0865 L 57.2646 187.1281 L 53.6705 186.2895 L 49.9567 185.9301 L 46.1231 185.6905 L 42.2895 185.9301 L 38.5757 186.2895 L 35.1015 187.1281 L 31.6273 188.0865 L 28.3927 189.4043 L 25.3977 190.9617 L 22.6423 192.7587 L 20.3661 194.7953 L 18.3295 196.9517 L 16.7720 199.2280 L 15.6938 201.6240 L 14.9750 204.1398 L 14.7354 206.6556 L B U 0 To 1.0000 0.0000 0.0000 1.0000 27.5541 204.2596 0 Tp TP /_Helvetica-Bold 8.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (automake\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.000 k 1.0000 w 0.000 0.000 0.000 1.000 K 1 j 17.0116 415.4676 m 75.3544 415.4676 L 75.3544 432.4792 L 17.0116 432.4792 L 17.0116 415.4676 L B U 0 To 1.0000 0.0000 0.0000 1.0000 23.3611 421.5774 0 Tp TP /_Helvetica-Bold 8.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (Makefile.am\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 324.2995 271.4676 m 324.2995 235.5275 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 327.4143 236.3661 m 324.2995 226.6622 L 321.0649 236.3661 L 327.4143 236.3661 L F U u 0.5000 w 0.000 0.000 0.000 1.000 K 46.1231 415.4676 m 46.1231 236.6057 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 49.3577 237.3245 m 46.1231 227.6206 L 42.8885 237.3245 L 49.3577 237.3245 L F U u 0.5000 w 0.000 0.000 0.000 1.000 K 171.7937 414.9884 m 171.7937 235.5275 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 175.0283 236.3661 m 171.7937 226.6622 L 168.5591 236.3661 L 175.0283 236.3661 L F U u 0.5000 w 0.000 0.000 0.000 1.000 K 171.7937 414.9884 m 309.0849 232.7720 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 311.2413 235.2879 m 314.4759 225.5840 L 306.0899 231.4542 L 311.2413 235.2879 L F U u 0.5000 w 0.000 0.000 0.000 1.000 K 171.7937 414.9884 m 61.8170 233.8502 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 65.0516 232.8918 m 57.2646 226.3028 L 59.5408 236.2463 L 65.0516 232.8918 L F U u 0.5000 w 0.000 0.000 0.000 1.000 K 324.2995 271.4676 m 73.3178 225.3444 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 74.6356 222.2296 m 64.5724 223.6672 L 73.4376 228.5790 L 74.6356 222.2296 L F U u 0.5000 w 0.000 0.000 0.000 1.000 K 324.2995 271.4676 m 190.2429 228.3394 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 191.9201 225.4642 m 181.7371 225.5840 L 190.0033 231.5740 L 191.9201 225.4642 L F U u 0.000 0.000 0.000 0.000 k 1.0000 w 0.000 0.000 0.000 1.000 K 17.0116 118.9617 m 75.3544 118.9617 L 75.3544 135.7338 L 17.0116 135.7338 L 17.0116 118.9617 L B U 0 To 1.0000 0.0000 0.0000 1.0000 25.6373 124.9517 0 Tp TP /_Helvetica-Bold 8.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (Makefile.in\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.000 k 1.0000 w 0.000 0.000 0.000 1.000 K 1 j 283.9268 118.9617 m 364.6722 118.9617 L 364.6722 136.9318 L 283.9268 136.9318 L 283.9268 118.9617 L B U 0 To 1.0000 0.0000 0.0000 1.0000 303.9334 125.5507 0 Tp TP /_Helvetica-Bold 8.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (config.h.in\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.000 k 1.0000 w 0.000 0.000 0.000 1.000 K 1 j 140.2862 127.9468 m 140.5258 130.4626 L 141.2446 132.9784 L 142.4426 135.3744 L 144.0000 137.6506 L 145.9168 139.8070 L 148.1930 141.8436 L 150.9484 143.6406 L 153.9434 145.1980 L 157.1780 146.5158 L 160.6522 147.5940 L 164.2463 148.3128 L 167.9601 148.7920 L 171.7937 148.9118 L 175.6273 148.7920 L 179.3411 148.3128 L 182.8153 147.5940 L 186.2895 146.5158 L 189.5241 145.1980 L 192.5191 143.6406 L 195.1547 141.8436 L 197.5507 139.8070 L 199.4676 137.6506 L 201.0250 135.3744 L 202.2230 132.9784 L 202.9418 130.4626 L 203.0616 127.9468 L 202.9418 125.4309 L 202.2230 122.9151 L 201.0250 120.5191 L 199.4676 118.2429 L 197.5507 116.0865 L 195.1547 114.0499 L 192.5191 112.2529 L 189.5241 110.6955 L 186.2895 109.3777 L 182.8153 108.4193 L 179.3411 107.7005 L 175.6273 107.2213 L 171.7937 107.1015 L 167.9601 107.2213 L 164.2463 107.7005 L 160.6522 108.4193 L 157.1780 109.3777 L 153.9434 110.6955 L 150.9484 112.2529 L 148.1930 114.0499 L 145.9168 116.0865 L 144.0000 118.2429 L 142.4426 120.5191 L 141.2446 122.9151 L 140.5258 125.4309 L 140.2862 127.9468 L B U 0 To 1.0000 0.0000 0.0000 1.0000 153.4642 125.5507 0 Tp TP /_Helvetica-Bold 8.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (configure\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.000 k 1.0000 w 0.000 0.000 0.000 1.000 K 1 j 91.0483 2.3960 m 171.7937 2.3960 L 171.7937 20.3661 L 91.0483 20.3661 L 91.0483 2.3960 L B U 0 To 1.0000 0.0000 0.0000 1.0000 115.4875 8.9850 0 Tp TP /_Helvetica-Bold 8.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (Makefile\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.000 k 1.0000 w 0.000 0.000 0.000 1.000 K 1 j 176.2263 2.3960 m 256.9717 2.3960 L 256.9717 20.3661 L 176.2263 20.3661 L 176.2263 2.3960 L B U 0 To 1.0000 0.0000 0.0000 1.0000 200.9052 8.9850 0 Tp TP /_Helvetica-Bold 8.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (config.h\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 46.1231 185.6905 m 46.1231 184.2529 L S U u 46.1231 182.8153 m 46.1231 181.3777 L S U u 46.1231 180.0599 m 46.1231 178.6223 L S U u 46.1231 177.1847 m 46.1231 175.7471 L S U u 46.1231 174.3095 m 46.1231 172.8719 L S U u 46.1231 171.4343 m 46.1231 169.9967 L S U u 46.1231 168.5591 m 46.1231 167.1215 L S U u 46.1231 165.6839 m 46.1231 164.2463 L S U u 46.1231 162.8087 m 46.1231 161.3710 L S U u 46.1231 159.9334 m 46.1231 158.4958 L S U u 46.1231 157.0582 m 46.1231 155.6206 L S U u 46.1231 154.1830 m 46.1231 152.7454 L S U u 46.1231 151.3078 m 46.1231 149.8702 L S U u 46.1231 148.4326 m 46.1231 146.9950 L S U u 46.1231 145.5574 m 46.1231 144.5990 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 49.3577 145.4376 m 46.1231 135.7338 L 42.8885 145.4376 L 49.3577 145.4376 L F U u 0.5000 w 0.000 0.000 0.000 1.000 K 171.7937 184.7321 m 171.7937 183.2945 L S U u 171.7937 181.8569 m 171.7937 180.5391 L S U u 171.7937 179.1015 m 171.7937 177.6639 L S U u 171.7937 176.2263 m 171.7937 174.7887 L S U u 171.7937 173.3511 m 171.7937 171.9135 L S U u 171.7937 170.4759 m 171.7937 169.0383 L S U u 171.7937 167.6007 m 171.7937 166.1631 L S U u 171.7937 164.7255 m 171.7937 163.2879 L S U u 171.7937 161.8502 m 171.7937 160.4126 L S U u 171.7937 158.9750 m 171.7937 157.7770 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 175.0283 158.6156 m 171.7937 148.9118 L 168.5591 158.6156 L 175.0283 158.6156 L F U u 0.5000 w 0.000 0.000 0.000 1.000 K 324.2995 184.7321 m 324.2995 183.2945 L S U u 324.2995 181.8569 m 324.2995 180.5391 L S U u 324.2995 179.1015 m 324.2995 177.6639 L S U u 324.2995 176.2263 m 324.2995 174.7887 L S U u 324.2995 173.3511 m 324.2995 171.9135 L S U u 324.2995 170.4759 m 324.2995 169.0383 L S U u 324.2995 167.6007 m 324.2995 166.1631 L S U u 324.2995 164.7255 m 324.2995 163.2879 L S U u 324.2995 161.8502 m 324.2995 160.4126 L S U u 324.2995 158.9750 m 324.2995 157.5374 L S U u 324.2995 156.0998 m 324.2995 154.6622 L S U u 324.2995 153.2246 m 324.2995 151.7870 L S U u 324.2995 150.3494 m 324.2995 148.9118 L S U u 324.2995 147.4742 m 324.2995 146.0366 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 327.4143 146.6356 m 324.2995 136.9318 L 321.0649 146.6356 L 327.4143 146.6356 L F U u 0.5000 w 0.000 0.000 0.000 1.000 K 324.2995 118.9617 m 190.9617 90.0899 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 192.5191 87.0948 m 182.3361 88.1730 L 191.0815 93.4443 L 192.5191 87.0948 L F U u 0.5000 w 0.000 0.000 0.000 1.000 K 46.1231 118.9617 m 149.0316 89.8502 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 149.1514 93.2047 m 157.6572 87.4542 L 147.3544 86.9750 L 149.1514 93.2047 L F U u 0.5000 w 0.000 0.000 0.000 1.000 K 163.4077 47.8003 m 162.3295 46.8419 L S U u 161.2512 45.8835 m 160.1730 44.9251 L S U u 159.0948 44.0865 m 158.0166 43.1281 L S U u 156.9384 42.1697 m 155.8602 41.2113 L S U u 154.7820 40.3727 m 153.7038 39.4143 L S U u 152.6256 38.4559 m 151.5474 37.4975 L S U u 150.4692 36.6589 m 149.3910 35.8203 L S U u 148.3128 34.8619 m 147.2346 33.9035 L S U u 146.1564 32.9451 m 145.0782 32.1065 L S U u 144.0000 31.1481 m 142.9218 30.1897 L S U u 141.8436 29.2313 m 140.7654 28.3927 L S U u 139.6872 27.4343 m 138.6090 26.4759 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 140.7654 24.1997 m 131.3012 20.3661 L 136.5724 29.1115 L 140.7654 24.1997 L F U u 0.5000 w 0.000 0.000 0.000 1.000 K 180.7787 47.8003 m 181.8569 46.9617 L S U u 182.9351 46.0033 m 184.1331 45.1647 L S U u 185.2113 44.3261 m 186.2895 43.4875 L S U u 187.3677 42.6489 m 188.5657 41.8103 L S U u 189.6439 40.8519 m 190.8419 40.0133 L S U u 191.9201 39.1747 m 192.9983 38.3361 L S U u 194.0765 37.4975 m 195.2745 36.6589 L S U u 196.3527 35.8203 m 197.5507 34.9817 L S U u 198.6290 34.1431 m 199.7072 33.3045 L S U u 200.7854 32.4659 m 201.9834 31.6273 L S U u 203.0616 30.6689 m 204.2596 29.8303 L S U u 205.3378 28.9917 m 206.4160 28.1531 L S U u 207.4942 27.3145 m 208.6922 26.4759 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 210.8486 28.8719 m 216.5990 20.3661 L 206.8952 23.7205 L 210.8486 28.8719 L F U u 0.5000 w 0.000 0.000 0.000 1.000 K 261.4043 83.1414 m 324.4193 83.1414 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 323.5807 86.3760 m 333.1647 83.1414 L 323.5807 79.9068 L 323.5807 86.3760 L F U u 0.5000 w 0.000 0.000 0.000 1.000 K 261.4043 56.1864 m 262.8419 56.1864 L S U u 264.2795 56.1864 m 265.7171 56.1864 L S U u 267.1547 56.1864 m 268.5923 56.1864 L S U u 270.0300 56.1864 m 271.4676 56.1864 L S U u 272.9052 56.1864 m 274.3428 56.1864 L S U u 275.7804 56.1864 m 277.2180 56.1864 L S U u 278.6556 56.1864 m 280.0932 56.1864 L S U u 281.5308 56.1864 m 282.9684 56.1864 L S U u 284.4060 56.1864 m 285.8436 56.1864 L S U u 287.2812 56.1864 m 288.7188 56.1864 L S U u 290.1564 56.1864 m 291.5940 56.1864 L S U u 293.0316 56.1864 m 294.4692 56.1864 L S U u 295.9068 56.1864 m 297.3444 56.1864 L S U u 298.7820 56.1864 m 300.2196 56.1864 L S U u 301.6572 56.1864 m 303.0948 56.1864 L S U u 304.5324 56.1864 m 305.9700 56.1864 L S U u 307.4077 56.1864 m 308.8453 56.1864 L S U u 310.2829 56.1864 m 311.7205 56.1864 L S U u 313.1581 56.1864 m 314.5957 56.1864 L S U u 316.0333 56.1864 m 317.4709 56.1864 L S U u 318.9085 56.1864 m 320.3461 56.1864 L S U u 321.7837 56.1864 m 323.2213 56.1864 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 323.5807 59.4210 m 333.1647 56.1864 L 323.5807 52.9517 L 323.5807 59.4210 L F U 0 To 1.0000 0.0000 0.0000 1.0000 349.6972 80.7454 0 Tp TP /_Helvetica 8.0000 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (used as input\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 355.5674 53.7903 0 Tp TP /_Helvetica 8.0000 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k (generated\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.0000 w 0.000 0.000 0.000 1.000 K 1 j 1.3178 162.3295 m 449.8502 162.3295 L 449.8502 406.0033 L 1.3178 406.0033 L 1.3178 162.3295 L S U u 0.000 0.000 0.000 0.000 k 1.0000 w 0.000 0.000 0.000 1.000 K 382.6423 187.7271 m 382.8819 190.2429 L 383.4809 192.7587 L 384.6789 195.1547 L 386.2363 197.4309 L 388.1531 199.5874 L 390.5491 201.6240 L 393.1847 203.4210 L 396.1797 204.9784 L 399.2945 206.2962 L 402.7687 207.3744 L 406.3627 208.0932 L 410.0765 208.5724 L 413.9101 208.6922 L 417.7438 208.5724 L 421.4576 208.0932 L 425.0516 207.3744 L 428.5258 206.2962 L 431.7604 204.9784 L 434.7554 203.4210 L 437.5108 201.6240 L 439.7870 199.5874 L 441.8236 197.4309 L 443.3810 195.1547 L 444.4592 192.7587 L 445.1780 190.2429 L 445.4176 187.7271 L 445.1780 185.2113 L 444.4592 182.6955 L 443.3810 180.4193 L 441.8236 178.1431 L 439.7870 175.9867 L 437.5108 173.9501 L 434.7554 172.1531 L 431.7604 170.5957 L 428.5258 169.2779 L 425.0516 168.1997 L 421.4576 167.4809 L 417.7438 167.0017 L 413.9101 166.8819 L 410.0765 167.0017 L 406.3627 167.4809 L 402.7687 168.1997 L 399.2945 169.2779 L 396.1797 170.5957 L 393.1847 172.1531 L 390.5491 173.9501 L 388.1531 175.9867 L 386.2363 178.1431 L 384.6789 180.4193 L 383.4809 182.6955 L 382.8819 185.2113 L 382.6423 187.7271 L B U 0 To 1.0000 0.0000 0.0000 1.0000 391.2679 185.3311 0 Tp TP /_Helvetica-Bold 8.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (autoconf-all\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.5000 w 0.000 0.000 0.000 1.000 K 1 j 171.7937 107.1015 m 171.7937 105.6639 L S U u 171.7937 104.2263 m 171.7937 102.7887 L S U u 171.7937 101.3511 m 171.7937 99.9135 L S U u 171.7937 98.4759 m 171.7937 97.9967 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 175.0283 98.8353 m 171.7937 89.1314 L 168.5591 98.8353 L 175.0283 98.8353 L F U u 0.000 0.000 0.000 0.000 k 1.0000 w 0.000 0.000 0.000 1.000 K 135.8536 68.1664 m 136.0932 70.5624 L 136.6922 72.8386 L 137.8902 75.1148 L 139.4476 77.2712 L 141.3644 79.3078 L 143.6406 81.2246 L 146.3960 83.0216 L 149.3910 84.5790 L 152.6256 85.8968 L 156.2196 87.0948 L 159.9334 87.9334 L 163.7671 88.6522 L 167.7205 89.0116 L 171.7937 89.1314 L 175.8669 89.0116 L 179.8203 88.6522 L 183.5341 87.9334 L 187.2479 87.0948 L 190.8419 85.8968 L 194.0765 84.5790 L 197.0715 83.0216 L 199.8270 81.2246 L 202.1032 79.3078 L 204.0200 77.2712 L 205.5774 75.1148 L 206.6556 72.8386 L 207.3744 70.5624 L 207.6140 68.1664 L 207.3744 65.7704 L 206.6556 63.4942 L 205.5774 61.2180 L 204.0200 59.0616 L 202.1032 57.0250 L 199.8270 55.1082 L 197.0715 53.3111 L 194.0765 51.7537 L 190.8419 50.4359 L 187.2479 49.2379 L 183.5341 48.3993 L 179.8203 47.6805 L 175.8669 47.3211 L 171.7937 47.2013 L 167.7205 47.3211 L 163.7671 47.6805 L 159.9334 48.3993 L 156.2196 49.2379 L 152.6256 50.4359 L 149.3910 51.7537 L 146.3960 53.3111 L 143.6406 55.1082 L 141.3644 57.0250 L 139.4476 59.0616 L 137.8902 61.2180 L 136.6922 63.4942 L 136.0932 65.7704 L 135.8536 68.1664 L B U 0 To 1.0000 0.0000 0.0000 1.0000 146.8752 65.7704 0 Tp TP /_Helvetica-Bold 8.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (config.status\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.000 k 1.0000 w 0.000 0.000 0.000 1.000 K 1 j 216.5990 136.9318 m 279.3744 136.9318 L 279.3744 154.9018 L 216.5990 154.9018 L 216.5990 136.9318 L B U 0 To 1.0000 0.0000 0.0000 1.0000 223.5474 143.5208 0 Tp TP /_Helvetica-Bold 8.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (config.cache\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.0000 w 0.000 0.000 0.000 1.000 K 1 j 199.8270 137.2912 m 200.3062 137.5308 L S U u 200.7854 137.7704 m 201.2646 138.0100 L S U u 201.7438 138.2496 m 202.1032 138.4892 L S U u 202.5824 138.7288 m 203.0616 138.9684 L S U u 203.5408 139.2080 m 204.0200 139.4476 L S U u 204.4992 139.6872 m 204.9784 139.9268 L S U u 205.4576 140.1664 m 205.9368 140.4060 L S U u 206.4160 140.6456 m 206.7754 140.8852 L S U u 207.2546 141.1248 m 207.7338 141.3644 L S U u 208.2130 141.6040 m 208.6922 141.8436 L S U u 209.1714 142.0832 m 209.6506 142.3228 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 207.9734 144.5990 m 216.5990 145.9168 L 210.4892 139.6872 L 207.9734 144.5990 L F U u 0.0000 w 0.000 0.000 0.000 1.000 K 225.5840 136.9318 m 210.1298 130.7022 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 211.8070 128.4260 m 203.0616 127.9468 L 209.7704 133.5774 L 211.8070 128.4260 L F U %%PageTrailer gsave annotatepage grestore showpage %%Trailer Adobe_Illustrator_AI5 /terminate get exec Adobe_pattern_AI5 /terminate get exec Adobe_blend_AI5 /terminate get exec Adobe_ColorImage_AI6 /terminate get exec Adobe_typography_AI5 /terminate get exec Adobe_screens_AI5 /terminate get exec Adobe_level2_AI5 /terminate get exec %%EOF II*[DD,V(@nn}}""++33<=X4b̦3NZj[˶pglg7m?3p;#NKS/9^Ak/R)ҎLd5:9evEI.%})*Z99 :G]eWv~HRgcy{Z%pʠZti㕐bf>a((Jj&*Ʃ\ :*Hfig'u: +p:kg$VIlrzl-[:nYqkV޴`x;U^.oʆjdmk #pʯ׿[yˆ"IK(=9<z/B\Mw0 o[r@nK؆i#8uƜq{++ˬ;44EZDqPG-*$-]SWh1im`o,#KvyhjʱO<]=pqp#щwl_"@{:V8T΃CS .%G0{"8umTZ&X7u|9ձ6k~A4)! I"(EX|6,t.` a(AQhLp62z%389Ѝp(:=񏭃Wh<2>`Fʎ$ 0vC9 <3lRK$aGrL*WJlZz&-w&]r &dfFPk c4wB(x  … :|1ĉ+Z1ƍp2dA",2ʕOvd ˘4k8B uLӧǞ@9(D9o:U9QDwRs(ҞLJmŬFz%ZBu0CoGb{ɪEmH,ӧ k&Č[6vɉG͍/s zФCz.աO~M8]aom[q݇s 522c !`˨n\pM'7tQg4{EFeҖ<]բNsYke=V)ꑭg3xn/؞iJws w.+U7?~|uZ+lp֨pȂWygSSw:t@w |r9jQll|}!|/}۹t;~(?.7sݸSvjr'zu;@i +e@ }t׽Kx纮zh\[.fV\_CtsIٲ=m+8!9h?S!$>X&T[ΠEQM,Q[h4>L"ب8Q=8<8hpIrEWpAQCGJr]YAD;Rr\fNr$%SRHE%{JJr-X[r(%/ ` sRDL=zJ3# +t g;'<1fP==s Kd <0… :|1ĉ+Z1ƍ;z2ȏF,XJ)WzlI˙!eI"ΜJiC%gVbcjaTdHiU?r9hmbHޢvyhd9jZdkZoN I)zWf̥(ZJi4+|4w ,3z鈿8,w[] *ji+^_Sn%n -ײjEU~nxfBSԾtakѾ"lb 3\ij ʯܺ+On;l\ǞFr$2Wj <)#ͭ5鳿8zvt}I޶tKhirJgXC5\u?LIMpǭEw붾 MwuJ6z܄Mʂ_%ϖoȈcx?\svWRb.Uv{^,F;Hێ:M 5z];G8z3 {3|tnQiȽEax2|"H8"ߒD]Fk(998Sb)+I^dkQ chCPeb NDtK2\\2i.nbI;ǛC%9KPv`|eW90ɝˬҩN['lLra P-J1 *|/A%PI"(7S<A%zG5ٝ~-KҜΉ2;)8SHL{<ш/5]"9I2* j`U5p®k`kXVqk,Li(vCj]z̃ɦ+EC%4Kx%v{t$FiVQ4 u;~cb>)͢"16+Y*֠2]MhשX˩C#5߂N՚8W\FWer:]YfwX \-0WY@O\w}Og*q=߉"[aVI&UUm{Y>K`]+Z;v)Y_jt<7N`XxƆZnuX |C.Y,bO\,6H+$B Ӽt&ks efi3LְJOKY=@oA3pB , 3pØÐCc)9kM5+@[ͮ] qY47OނGH"4!QH&t$rJ*J,1K.(sLL2TS5tA4ߔsNN:,>Cm85T+A;$PFZ|T'MiКBkLnɿեBTRoT3 S%SeQs}4QWyW`5X* p "Lp!ÆB(q"Ŋ/b̨q#ǎ? )r$ɒ&OB r%˖._Œ)sˋ4o̩s'Ϝ { z%Ѣ  4)SKڌ uŧR5+׍[j{أRˢ-HvڴjMW\menһ{J*51:Yz'-֬e^*,,=:5kԭW;k5F vݾu6;4+;,;8o6rԥGSG~ۏK.>tvɮw_|Uy{ESjG1xwe WuvqᙆfGtᇆ 8"s&¨\lAӱ^ȣx߆ :E wu(V])YU_4&idahleTrv(p&xf&TY&iޟu(Z ըRRbbJӢJ)hozZ*IZTj+ΘjF :kG·ziF hF8kȒ,딀Ξ+rۭ߂vU]*ջbto#pC0H#+\^+*ŸgvqI&Cϩ<)7c]q3}Br=eDB_tUsTV,W+-[wtW_9u1K(ZYZl3;g,7 hOK㽨[g8=vā^p涉d{w(c^Xd\M~o;b&HXB:w7b"2!'zV/er L _}knuS3WTsWtSyOi~~d|ڸNoe?10o 6JTeZ)`b^w=]Da"WƆ`{b(Y: `gHB s>l]߈r<-+wCl9xA%.'KHέ%2byh,&;%@a^(0dmL L9[b5H1oJCF jHEPdXxQ"KX p7MI*UAM~&q5^`D˳ R#6LbɌ$ &%;W1ֲuD&W'BspM 2|_314ԣ2xl''Me gxNIO*U)MO-՚ 8-.|1g9ϙ^DZn'@_^ϲ]8Y=iKϛ:bфeS泚3Ԋ;Kej@TtU]HT4ԡgJJZU5SY lke+5#:Zu3 UDk3#(GQ:2Tq^!kXvUlZ+X-%^7JYf:s-dX/m^V֤umc׭EBS }=_ܑF-JltmTlj+Rr5/5TZv%{вzW)T8dyE&Xz%?UÍlr{1®;-a*4;l1dnjE2jlg44ja봓lu˚eĝS6;ݟ#z̶nn}On{ms?<՛sGx俷v_=}|1t-7~*`H lU)rg!8a}]9Han~u hu~&w∧(!OaVz〔ِn0hRH YwM:!AVܗ!eee"%iЅsdQ6`l''IhbT"nv$i蕮9hxJ>Xiښ[fejl|*؝)ڨgŊ"ͩzky):V밳z+qS~:#.k, T-R-zf+CbvBdWgꮱ>ʯ:;&1䞚zO︤^*p׋2K!cHoK,~lr6ʡ<]:lqĪG:ӡ<oOS9'OQ?yK_Qv@u/|wp{dG(Gl'8i GbrKҜ*]&dyBIg5 Y:#qъⓉ2;)q~07FlKL^צ+/M١1َ~f1hX9ѝ*5=VNhGn>PI긮i1}d!XX[tUI=bLI +cKΑidP %RH]/ E(rF7hD̵MsjK4YSM.m9,ₖq5_8TN:i.l)yX3t'=EOhjK>*PMP%@P~l<-iЉRtLA+FfQM ɎC q&%)(O#z1Lc*әҴ6)Nsӝ>)P*ԡF=jNYC^t*T*պQlpj~LZUr W?V?x:TX(R+UFUcfv57!ww>:2fcT;o+d6+!6aYH#H]hOҁdmKҊvem[;xYmmS ܒam+\\գ2|O JSru#ܳhH=/m^չldu^ص0P+^V󝊚&|y&U<ʽl%e=԰30->!ld׭bBG%)G lm&(h鲙$l=36qf7cY+Fk [vV0)Rxu"wc\Uy5V2+c`xBi`O=Y* sNؾyzfEծW~^K_oMiaz~4iň:Us4=j)ڎ8C) ,h „ 2l0D'Rhq`ċ3j#ȃG,i$ʔ*WlY˘ 9)̑6q'Р=a -jP'ҤFjD)ԨR$J*VNr+X:$;Ԫٴjײ-ܘcҭk˷q}/KÊ3^kRf6lcE#g3Њ ԪWF}S3KӬgӮΦ%6UQrŭ3o}j݋3Y~oi ;pN ;<1 1׋1{F2%Og2)0*<2\3&Ϝ33Ц4Ѽ}4I+\L;OKZU=58uzif5(6emƙ6Thg6q[yMy뽴7-7 `됳^p'lm3AN[cnߧhS''.1g9k )jzeb~gt:ꪩNc{:v{|ZU<jZzF%^~ٻ/秾;Y/?'>h<;sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/docs/pictures/autotools.vsd000066400000000000000000001440001223300710500251060ustar00rootroot00000000000000ࡱ> ;b  !"#$%&'()*+,-./0123456789:a>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`Root EntryF <VisioDocumentqSummaryInformation(=\FDocumentSummaryInformation8Visio (TM) Drawing qT ouRt !fffMMM333?YV$ $ U8@ Td Arial@NWingdzs@m Monotype Sort+ NtSymbol5T?? Y@-1U!J:DT1EW-hTT<* /Ub bO0zGz?@8@H2!kWb*U  +$PL/^&9^$? { Ak^&,,'%/v&& * 1y   )P? 2   U U12?k9aBBHEHEHEHEHEHEH@?>?:`T2BBHEHEHEUHEHEHEHE%H@%O9 F7AOY@;P AsVsVA!gLTkY W_W__ !`#k4lb6u`kW *4l 4l %Y?@:?-\ #%|QLe2|2|2|I2wGQAUoTMeE$ttA%_8BOTOfOxOO??HO?7ܻXuW?YsU42 T*PbtφϘϪϼ(:L^p߂O߳ 1CUgb{.);M_xa"4FX 0Bzas//'/9/K/]/o/////////?#?zaB?T?f?x????@????OOUbb7OQV.e_OqOOOOOOOO_wk#_5_G_Y_k_}________U lAoSoeowoooooooxa(:L^p cwo!3EWi{Ï٦ .@Rdvk}*B'Chk#bz@.`c.`/%b /=QN3L/^/p////////??7`?Pbtί(:L^p݇Z;ɼٿِ>.@*Ҁ[m߅3O贁Nkd ȼP2q?߃?\.? Aqش*$$$'@9K]ڊ䐾伩jPj| xԕIW&V;03E0<kDB!ߵ V /ASew+=Oa/09K]o?!?%`\\esprn002\HER1A3B1S odWX+'?LetterO_b PRIV0|'r\KhC]>w!tuy //-/?/Q/c/u////////??)?;?M1E%winspool\\esprn002\HER1A3B1IP_172.21?.36.14UFDfP h> /T6DUmA@ ?ۿI?Y{O1@3EEbOeZ Hu P(:{W_qQRectangle. with text and connion points. Can be stretched toy dimenss.mb?贁No?k?4 HDB $# ?h-(>TT9 UA??Q6 u` 6u mB>00XA0(2s@sJLsT>5 LO@{5 `7Copyright 1999 Visio Corporation. All "s reserved.` _Sba.chm!#22430Bd9 l>0>Udd!!T <hb 261 g,s724?`b?M1EY?r?91M1|;6==5P2?;zrA IB=OCq,^35/V:NAC=AK?OI="3AO<_OOKAE[6:_ L_Ij_|U|\_oo_AnHl'-n !OyaGE-szFb (# JB  U[akoo@++ po3aTk o\8!%' ,UFDfP h> /T6DUmA@ ?ۿI?Y{O1@3EEbOeZ HG 9V?o)>  `r/`wpw> ȳpke{rpgTHYY9 mAUA? @ ?Q6 u` ?Mu ~YYA|XA44 4> !bJfvqQ >!"q06DNX lL>U5 LO@%#A?AE^?AL#l%u%?P6 @*  L#&H   " ' ]{%#W1\!\!5 `7Copyright 1999 Visio Corporation. All 2s reserved.`0_Sba.chm!#22427Bd(,*9 l>(>Ud!E (!(ZU$ B$bW*$UdvE \b4 *1B$b24R(@][v[D ZQi@ a59 93O'2"q?.g;2GHlw-* O`EW )Fm J#\G 7B U6 OGdo@5 UFDf h-TUU[U@@??I?`d buoqYkQhu23u` Connector ` e1Crw UH ^   -}|5 p`I`V?}`xa833ސ]3σ3u 33?, ?Gxpx^& CThis connector automatically routes between the shapi ts.b?贁N? HD @# =h8T YY9 BT#F oU@? P6 u `u bA@]u  .(#DB uu`h?\hr|uVa@-?bl;'bE-ho'$y( 2rq?@I ?$%? @"U*5L -br  ^vv"(2uI."q28v"uh9Bd&</MS{ #145 `Vis_Sba.chm!#22446`7Copyright 1999 @io Corporation. All $Ud vE \/4 *&1$b24R(^[w[D ZQi a59 93O'2"q?/g;2GHl'jt !OyaGE_=szF$w w#I 7B 6 $d:!@+k"s <k \!Ul4,"H$ @Y,b'@ p $A-37"A%Ul4,"H$ @Y,b'@ q %A-37"A'Ul4,"H$ @Y,b'@  _%*A-3e7,Ul4,"H$ @Y,b'@  %*A-37UzZ@Tq $FR ) %t5 k;C? MH<( H<( H<( H<( UzZEq =& R ) J5 W; l d( S B  B!L |/" c"S  ,$,?56 %w@RD: q&)< UP?$@U+@F:DTey  ah$ T ]UI"H$ @IY,ob'@??I.Qc. H|2a?-(u6` N"T"u^)2%&н..(s+&t?gI?'Pz4&Tu` Black & Whiteny1 E_&03Color Schemes...1`'Set the c2Bs8B f4@this document@@ `2` 1JQ o_!O?&KdK50Hidde%nrDzA R WA@OAJ3 ConnectorYgR mZe 4-1QPQ 1^D tA  "gQ!T!1)AT}11DU!"#%4U()*'+,tAH~adg%dgd1g5dQgQhagdQgQhAgEdQgQhtAgtAhQgQhgdQgQhagahagahghghagahgQggQhagahghT!gT!h1g1hgF5d.ag.ah)Ag)Ah}1g}1h1g1h>ag>ahBagBahFagFah_!g_%dNagNahRagRahVagVahgh^ag^ah1g1hragrahfagfahjagjahnagnahvagvahzag@zahQcf1uIPgQNaNaRaRaVaVa1^a^aQ11tAraraQfafajajaQnanaavavaaľU1/W.a0d)ACACA}111fa)A)Aja>a>avaoϽa"ui1Q1faR19E*@2@$@{@*?@*k?տ??Q$731"[Vk"a1`a/gQCaW(1*A̳WU02CBfa<9 ?*ߨ1c%configure.inlad*F=aH_S?Qa(5 ui6qXzaƅ`&\xug8/h7$$6HZ,Xd %e, /5@/R/Ci??g8g8 '2q0ea/t^5.@RбDuKQ ub0cAP9FIEa$e../sofia-version.m4ASeyQqX0_82/:o_^p/_d j0/1DBGBH3Bo_/V/</&/8/N\//o//////6U!?8>?P?b?t????Ҁ$OO+K MLO^OpOOTꉢOOбIaOaO_!_WoE_W_o{_$_Я _o$o6oHouloڥheo6IWmϣn=!3E6shB͏ߏ#@@+c=Oa,JM擟ɟTEѩI&/usr/share/acl?ocal/*?QcGci8\nuȿe< G uϟϾ/*7B³3(2r?@I>@?4Dp=CZ뫗XHA5E4>=ᯙA(=y455ԿIy>jU?Apyu `u _i iDj 4~i@)>sp !3'@z3-3EBp`rXnIgxӿ2r?@I ϕ?J>u@`pd?Iu` *\H&<_{Gz šhQ>@`13A(;OWCa2&kCͯT QAH$W௙P_A~I[4c >H#?5?C\1˕=Oas*pu/ 1CU6VU@e!tB'CQMV9  )ReV__ aV__ T JgT(:{?^l~/ /LRT/٤c/c%/// ??oB?k}DlӠ??????O?O/:tE.q'm-..lIlk`FtP-DT!a-Ru`u]`?b6X@"$$6X.T/S;R6R(>[gYZ(7BV! (*Єҿ-Beo,π3emYl~{qlՇ&)J#!qە-?Qs!@%(:L^p*d3ÊV 1CUgџ+@9 @@>A\@ҧo WHi9?Y{ïկ 4FXjs@@XCq " O8+!s .@Rdv߈߬߾ԁHL/ -?Qc H#@\\ @@BSx^@ &OmW3a#uzt1F,>Pjpf=@@MzxFGF_&^GA_\_nY G0_Tfx1sf//+/=/O/a/ӂ>o//////}?%?7?I?[?m?????@ICj7C@@wΪ@@Ko Olai]OO)O;OMO_OqOqO!ؾOO7f @@' @@)KUx! !FӟTV7_6__oB-o?oQocouoooooooolp-?Qcuu&8&0@@a$iӯOa3B͏ߏ% Pbt*,ad@@؏IpxֲÔ8Je0kTxx>ѯ+=Oasѿτ8;OPϧϹ(E@@w@@o?@ݚ?ٗ?Q  ($.BcLA&ўA$RU0R"me~3p3nW>;?e:q*8,d!5?68d:@g83#f ' (bOUA!?zOIUAaNON3CX_UAE>@@OOֺ-DT!0шu `u Qbu Q Vn@@MD_O耩@)TO Zd_ѳuu`?5uZݏ88@An%$JUg~K)p̑e@z3rJp4 3E߁!b.GU0{Gzbi u)1KPGA;UAQ5xh .l,Pbt߆ߘߪ٤@@ 1* "0BTfxG!6 "-256H676nIO[N7vOOIFIOO.$,V_+_n6VB V*<N`r=yo//*/xH/Z/l/~///////٣@@VUpP&qU(?:?L?^?p?????q??O}'Kq bpInASnPҖA_џ.aa$#f_x__݆S____o"o4oFoXojo|oo[qoo oo"D@Rdv@p ׋@@r@@ 04/.Ef Wy̔k3EWi{7 }s@@$ @00$@ Kֳn9KfٱYU9^p+|xӤ?ӬA*OPObOtOOOO#n'OO__,_>_,Ȃa__q________S@@̙LNa:z,*hؘm`oroooooـoj$&H˧,&3OAp  `M}jijV@v7It(:LgvЏ*<ҵvПQዡ .HG Vh可 #6*h=gX -?Q?$Qn\-h@?8#zt}v OOKo߁ߓߥߜI Å;Pb'ASew` m6'9K*j u676ztO N7;OvVOhI-=O/sPE_ F%/#/Y5Y Q/c/UQ&싡h1)0Y@8{U{U{U?%`cQ?@mf?9<9AL/1E[P0G!i3q3qM% _T![9 3_`_\Qb9\]{f\Ued`Q%Ptot]PYVused as input&____oo*o1LqWxT/PXv#0O贁Nka .@Rv~ӯR 0BTfx @p٨OhwhŮH`=f 1CUgy&Ƴŏ"$3M.@[lv߈0Qԟv#4"4)9Pbtq UVU!"U#$%&U'()*U+-./01Ul4,"H$ @Y,bK'@ p EZUHC-37AU2@$p Z7LRH<( U2Elp Z7 RUlL( 8'2 4Z@?B )RD$C [<U$ < ?@U @+g( "*^p=*4 -z~ #5GYk} C:\Program Files\Microsoft Visio\Solutions\Block Dia\Basic Shapes.VSS`(,<*> [LC!:K +/U1(5 O"D&U=Q Jf )h"/Ty*+U, Ʌ&Q- H *9(TYkEQ/,GuideTheDocPage-1Gesture FormatVisio 90ConnectorVisio 00Visio 01Visio 02Visio 03Visio 10Visio 11Visio 12Visio 13Visio 20Visio 21Visio 22Visio 23Visio 50Visio 51Visio 52Visio 53Visio 70Visio 80BasicBasic ShadowEllipse.41SchemeNameRectangle.40Ellipse.43RectangleRectangle.2Rectangle.3Rectangle.4EllipseRectangle.10Dynamic conn?ectorEllipse.12Ellipse.13Ellipse.14Rectangle.15Dynamic connector.4Rectangle.23Rectangle.24Ellipse.25Rectangle.26Rectangle.27_pL23T$ ;] EdE tP- [TGsU Uc c c % Uc ,c DUc \c tUc c ^d )Ԫ)*)& 7)mD)4mQ)Lm^)dmk)|mxT)m)Jm)-m_/ m}D )m7$Ag'W I* W )x$W ) 7DVhz .@Rdv 763* 3!/3/E/W/i/{//////// ??/?A?S?e?w??????;Ro0tE;n0ryO 5!AO|@VBAMOOO5.O^EThisD0c?ume2 _<_fA1 _S_fA_qD_PRO J0C@__.T0A __+!!@.fA!- kA3/B/RZ!"U#$%&U'()*U+,3./013645*678/oo(:L^p7U..q.kTK>@zaA"U_N`WHfA%v!qx d8ME;7/߿ A 2DV7aSL^?St?s3Dk@!wP3D2dm6,Syem`Lr@bA [%e@vRP\1]%Z3=BT^nzWNT?SJ@s0eP\Qd0tby`UOEu0oPt&Y3@_@  ʋB߿>PrM`OS`12J03`0`FU-RA%f@ A //0/B/T/f/x////////??,?>?P?b?t???????okT5I+j1`k`-R  ``VisioVBA"@Win16~5D32,AMac/A6#autotools/`stdole?` 26t<^@@_EvaluEjӲ-<ݼ4P< @b5b_?{4R0* pHod`bEDsa@ = p (J J< rs@NrB>@ %\*\GL20430-@Cd}#2.0#0t:\WINNSystem32\c2.tlb@#OLE Am`ation^rK_F}DBGDQUSnY2Q`H1%} ,C>"+KPE}I _CID="{25CAB2EE-8C1F-462D-9259-C08DA91A16f@E=}I/&HMb )e="bF@HelpContexta0@Ver'@nCompPble32="393222M@CMG="6C6E803680A684VyaPB="D`34C735ts@GC="4446A85E78CB79q3eq [Host Extender Info] f1={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;@isa A:L^roo`ˏݏ%7I[mǟٟ!3EWi{ïկ /ASewѿ+=Oasυϗϻ'9K]o߁ߓߥ߷#5GYk} 1CUgy : |4+bL BU^U U UUUl4,"H$ @Y,bK'@ _ KUC-3AUl4, p >m AJ- 3H7A_*<N@4 l KRVg\F Jm6uH<( H<( _*<NE m RVgF q &AM3'AM3(PPT)PPT1_*/W3 ad0 L;t;j;;;1 U<dܧ2 ,T|Rm6)4T|j5 UDW.lW.W.W.W.+ -n A, :*, G*D T "&'() !1T*!"#$%{ * g"4pFX(8&^@(E#,@  :`R, q& !B 5> >h_ OoB{U B5$/'t *[#SN})> \\;1 ՗= `2$ *V \, wl+? D mGD4E 5 CZ=$n._( bY A R/՜.+,D՜.+,L@HP\h t   PagesMastersPage-1 RectangleEllipseDynamic connectorDynamic connector.48_VPID_PREVIEWS@_VPID_ALTERNATENAMES#@_PID_LINKBASE AOh+'0,FHPdp| rinnerahKC:\Program Files\Microsoft Visio\Solutions\Block Diagram\Basic Diagram.vst autotoolsG4E EMF,El@@VISIODrawingLD ??d(@(@ʦ VisioInformation" sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/docs/pictures/nta-receiving-message.eps000066400000000000000000003244621223300710500272410ustar00rootroot00000000000000א;%!PS-Adobe-3.0 EPSF-3.0 %%Creator: ImageMark Software Labs %%For: () () %%Title: G:\Src\sipterm\pictures\nta-receiving-message.eps %%CreationDate: () () %%BoundingBox: 0.0000 0.0000 463.0000 358.0000 %%DocumentProcessColors: Black %%ColorUsage:Color %%DocumentFonts: Helvetica %%+Helvetica-Bold %%+Helvetica-Oblique %%+Helvetica-BoldOblique %%+Times-Roman %%+Times-Bold %%+Times-Italic %%+Times-BoldItalic %%+Courier %%+Courier-Bold %%+Courier-Oblique %%+Courier-BoldOblique %%+Symbol %%DocumentSuppliedResources: procset Adobe_level2_AI5 1.2 0 %%+ procset Adobe_screens_AI5 1.0 0 %%+ procset AGM_Gradient 1.0 0 %%+ procset Adobe_ColorImage_AI6 1.1 0 %%+ procset Adobe_Illustrator_AI5 1.0 0 %AI5_FileFormat 3.0 %AI3_ColorUsage: Color %AI3_TemplateBox: 0.0000 0.0000 463.0000 358.0000 %AI3_TileBox: 0.0000 0.0000 463.0000 358.0000 %AI3_DocumentPreview: None %%Template: %%PageOrigin:0.0000 0.0000 %AI7_GridSettings: 72 8 72 8 1 0 0.8 0.8 0.8 0.9 0.9 0.9 %%EndComments %%BeginProlog %%BeginResource: procset Adobe_level2_AI5 1.2 0 %%Title: (Adobe Illustrator (R) Version 5.0 Level 2 Emulation) %%Version: 1.2 0 %%CreationDate: (04/10/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /Adobe_level2_AI5 25 dict dup begin put /packedarray where not { userdict begin /packedarray { array astore readonly } bind def /setpacking /pop load def /currentpacking false def end 0 } if pop userdict /defaultpacking currentpacking put true setpacking /initialize { Adobe_level2_AI5 begin } bind def /terminate { currentdict Adobe_level2_AI5 eq { end } if } bind def mark /setcustomcolor where not { /findcmykcustomcolor { 0 6 packedarray } bind def /findrgbcustomcolor { 1 5 packedarray } bind def /setcustomcolor { exch aload pop 0 eq { pop 4 { 4 index mul 4 1 roll } repeat 5 -1 roll pop setcmykcolor } { pop 3 { 1 exch sub 3 index mul 1 exch sub 3 1 roll } repeat 4 -1 roll pop setrgbcolor } ifelse } def } if /gt38? mark {version cvr cvx exec} stopped {cleartomark true} {38 gt exch pop} ifelse def userdict /deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt put userdict /level2? systemdict /languagelevel known dup { pop systemdict /languagelevel get 2 ge } if put /level2ScreenFreq { begin 60 HalftoneType 1 eq { pop Frequency } if HalftoneType 2 eq { pop GrayFrequency } if HalftoneType 5 eq { pop Default level2ScreenFreq } if end } bind def userdict /currentScreenFreq level2? {currenthalftone level2ScreenFreq} {currentscreen pop pop} ifelse put level2? not { /setcmykcolor where not { /setcmykcolor { exch .11 mul add exch .59 mul add exch .3 mul add 1 exch sub setgray } def } if /currentcmykcolor where not { /currentcmykcolor { 0 0 0 1 currentgray sub } def } if /setoverprint where not { /setoverprint /pop load def } if /selectfont where not { /selectfont { exch findfont exch dup type /arraytype eq { makefont } { scalefont } ifelse setfont } bind def } if /cshow where not { /cshow { [ 0 0 5 -1 roll aload pop ] cvx bind forall } bind def } if } if cleartomark /anyColor? { add add add 0 ne } bind def /testColor { gsave setcmykcolor currentcmykcolor grestore } bind def /testCMYKColorThrough { testColor anyColor? } bind def userdict /composite? level2? { gsave 1 1 1 1 setcmykcolor currentcmykcolor grestore add add add 4 eq } { 1 0 0 0 testCMYKColorThrough 0 1 0 0 testCMYKColorThrough 0 0 1 0 testCMYKColorThrough 0 0 0 1 testCMYKColorThrough and and and } ifelse put composite? not { userdict begin gsave /cyan? 1 0 0 0 testCMYKColorThrough def /magenta? 0 1 0 0 testCMYKColorThrough def /yellow? 0 0 1 0 testCMYKColorThrough def /black? 0 0 0 1 testCMYKColorThrough def grestore /isCMYKSep? cyan? magenta? yellow? black? or or or def /customColor? isCMYKSep? not def end } if end defaultpacking setpacking %%EndResource %%BeginResource: procset Adobe_screens_AI5 1.2 0 %%Title: (Adobe Illustrator (R) Version 5.0 Custom Halftone Screens ProcSet) %%Version: 1.2 0 %%CreationDate: (03/24/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking systemdict begin userdict /Adobe_screens_AI5 15 dict dup begin put /initialize { Adobe_screens_AI5 begin /screenid deviceDPI 600 gt composite? not or { -1 } { deviceDPI currentScreenFreq dup dup 60 ge exch 150 le and deviceDPI 300 le and { pop 60 } if div 1.41421 div 0.5 add cvi } ifelse def 2 screenid eq { /customsize 16 def /customdata /customdata2 def setcustomscreen } if 3 screenid eq { /customsize 24 def /customdata /customdata3 def setcustomscreen } if 4 screenid eq { /customsize 16 def /customdata /customdata4 def setcustomscreen } if 5 screenid eq { /customsize 20 def /customdata /customdata5 def setcustomscreen } if 6 screenid eq { /customsize 24 def /customdata /customdata6 def setcustomscreen } if 7 screenid eq { /customsize 28 def /customdata /customdata7 def setcustomscreen } if 8 screenid eq { /customsize 16 def /customdata /customdata8 def setcustomscreen } if } def /terminate { currentdict Adobe_screens_AI5 eq { end } if } def /setcustomscreen { deviceDPI customsize div 0 { 1 add 2 div customsize mul cvi exch 1 add 2 div customsize mul cvi exch customsize mul add customdata load exch get 256 div } setscreen } def /customdata2 28 28 mul string def currentfile customdata2 readhexstring 4180E8694988E2634382EA6B4B8AE061A01939C8A81737C2A21B3BCAAA1636C0 F8795998F6775796FA7B5B9AF57656952ED8B80727D6B60F2FDABA0626D5B50E 4E8DE6674786EE6F4F8EE5664685ED6EAD1434C6A61F3FCEAE1232C5A51E3ECD F3745493FE7F5F9EF1725291FD7E5E9D24D3B30C2CDEBE0222D1B10A2ADDBD04 4483EB6C4C8BE1624281E96A4A89E364A31C3CCBAB1535C1A11A3AC9A91838C3 FB7C5C9BF4755594F97A5A99F778589730DBBB0525D4B40D2DD9B90828D7B710 508FE4654584EC6D4D8CE7684887EF70AF1131C4A41D3DCCAC1333C7A72040CF F0715190FC7D5D9CF2735392FF80609F21D0B00929DCBC0323D2B20B2BDFBF01 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata3 28 28 mul string def currentfile customdata3 readhexstring 011DC7F5E73D0421CBF3E43A021EC8F6E83E0522CCF2E43A2B648BC4A0762F68 8AC39E732C658CC5A177306989C29D72D5B6521A6192D9B55219608FD6B6531B 6193DAB451185F8FFCEE440C28D2FCED430B27D1FDEF450C29D3FBEC420A26D0 BEA77D366F83BCA77C356E87BFA87E377082BBA67B346D86145B99E0AE4A1259 98DFB14E155C9AE1AD4A115897DEB04D0623CDF4E63C0420CAF8EA400723CDF4 E53B031FC9F7E93F316988C19F752E678EC6A378326A88C09F742D668DC6A278 DBB350175E91D8B8551C6395DCB24F165D90D7B7541C6294FAEC420925CFFFF1 470E2BD5F9EB410824CEFEF0460D2AD4BAA57A336C85BEAA80397180B9A47933 6B84BDA97F387181105797DDAF4C145A9CE3AB480F5696DDAE4B13599BE2AC49 021EC8F6E83E0522CCF2E43A011DC7F5E73D0421CBF3E43A2C658CC5A1773069 89C29D722B648BC4A0762F688AC39E73D6B6531B6193DAB451185F8FD5B6521A 6192D9B55219608FFDEF450C29D3FBEC420A26D0FCEE440C28D2FCED430B27D1 BFA87E377082BBA67B346D86BEA77D366F83BCA77C356E87155C9AE1AD4A1158 97DEB04D145B99E0AE4A125998DFB14E0723CDF4E53B031FC9F7E93F0623CDF4 E63C0420CAF8EA40326A88C09F742D668DC6A278316988C19F752E678EC6A378 DCB24F165D90D7B7541C6294DBB350175E91D8B8551C6395F9EB410824CEFEF0 460D2AD4FAEC420925CFFFF1470E2BD5B9A479336B84BDA97F387181BAA57A33 6C85BEAA803971800F5696DDAE4B13599BE2AC49105797DDAF4C145A9CE3AB48 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata4 28 28 mul string def currentfile customdata4 readhexstring 1139B8E0FAD2531B133BBAE2F8D05119417180A6AE9A7B4B437382A5AD987949 C08867272F6F92CAC28A66262E6E90C8E8DE5F070F37B6F2EADD5E060E36B5F0 FED6571F173FBEE6FDD5561E163EBDE5AB9E7F4F477786A1A99D7E4E467685A3 2C6C96CEC68E62222A6A95CDC58D64240C34B3F6EED95A020A32B1F5EDDB5C04 143CBBE3F9D1521A123AB9E1FBD3541C447483A4AC997A4A427281A7AF9B7C4C C38B65252D6D91C9C1896828307093CBEBDC5D050D35B4F1E9DF60081038B7F3 FCD4551D153DBCE4FFD758201840BFE7A89C7D4D457584A2AA9F8050487887A0 296994CCC48C63232B6B97CFC78F61210931B0F4ECDA5B030B33B2F7EFD85901 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata5 28 28 mul string def currentfile customdata5 readhexstring 010B34C3EBFCF7CE3F16020C35C4EDFBF6CD3E15102552A4D6EADDB5632B1126 54A5D5EADCB3622A3958768499C19E8C7C5E3A59778498C19D8B7B5DC8A99370 47334C7587AFC9AA936F46324B7485AEF1E5BC6B1E0A2351A3D8F2E4BC6A1E09 2351A2D7FFF9D14219050F38C6EFFEF9D04118040E37C6EFE8E0B7662D142856 A8D3E7DFB7652D132856A7D4BF9C8E7F603D5B7A8195BE9A8E7E603C5B798297 314A7389B2CCAD906D442F497289B1CBAC926E4508214FA1DBF4E2B9671B0720 4EA0DAF4E3BA691C030D36C5EDFBF6CD3F16010C34C3ECFDF8CF4017122654A6 D4E9DDB4622A112553A5D6EBDEB5642C3B59788397C09C8B7C5D3A58778599C2 9E8C7D5FCAAB926E46314B7486AFC8AA947048334D7587B0F2E4BB691D082250 A1D8F1E6BD6B1F0A2452A3D9FDF8CF4118030E36C5EEFFFAD1421A050F38C7F0 E6DFB6642C132755A7D3E8E1B8662E152957A8D2BE9A8D7E5F3B5A798296BF9B 8F80613D5C7B80952F487188B1CAAC916D443049728AB3CCAE906C43061F4D9F DAF3E2BA681C07214FA0DBF5E1B8671A00000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata6 28 28 mul string def currentfile customdata6 readhexstring 081A44B6E0F2FDECC150250C091B45B6E1F3FCEBC04F240C1D336199C7D8DCD3 A56C37221E33619AC8D7DBD2A46B36214864798091AEB1958C7E694C49657A81 90ADB0948B7D684BB99D8475593C405C7888A1BEBA9E8574583B3F5B7888A0BD E4CBAA712E1215326098CFE8E4CCA9712D1114315F97CEE7F5F1C6552B040719 43B5DFFAF6F0C6542A03061842B4DEF9FFEDC352270E0B1C47B8E3F4FEECC251 260D0A1C46B7E2F4DAD5A76E39232035639CCAD5D9D4A66D38231F34629BC9D6 AF938E806A4E4A677C838FABAE928D7F694D4A667B828FAC3E5A778AA3BFBC9F 8772563A3D597689A2BEBB9F8673573A14305E97D1EAE6CDA76F2B0F132F5D96 D0E9E5CDA8702C10051742B3DDFCF8EEC4522801041641B2DDFBF7EFC5532902 091B45B6E1F3FCEBC04F240C081A44B6E0F2FDECC150250C1E33619AC8D7DBD2 A46B36211D336199C7D8DCD3A56C372249657A8190ADB0948B7D684B48647980 91AEB1958C7E694CBA9E8574583B3F5B7888A0BDB99D8475593C405C7888A1BE E4CCA9712D1114315F97CEE7E4CBAA712E1215326098CFE8F6F0C6542A030618 42B4DEF9F5F1C6552B04071943B5DFFAFEECC251260D0A1C46B7E2F4FFEDC352 270E0B1C47B8E3F4D9D4A66D38231F34629BC9D6DAD5A76E39232035639CCAD5 AE928D7F694D4A667B828FACAF938E806A4E4A677C838FAB3D597689A2BEBB9F 8673573A3E5A778AA3BFBC9F8772563A132F5D96D0E9E5CDA8702C1014305E97 D1EAE6CDA76F2B0F041641B2DDFBF7EFC5532902051742B3DDFCF8EEC4522801 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata7 28 28 mul string def currentfile customdata7 readhexstring 01061B44B7E1F5FEFBE6BD4A210C01071B45B8E1F6FDFBE6BC4A200B09132A54 A7D1EAF5EED9B05D331609142B55A8D2EAF4EED9AF5C32161D2D3D6993C1CBE0 CEC59B7140301E2E3D6A93C0CADFCDC49A713F3047576C7B828DA2B6A48F867E 6F5A48576C7C828CA1B6A38F867E6E59BAAA958A78634E4451667A8498ADBAAB 968977624E4350657A8398ADE3D4C99F7539251A273C6892C2D7E4D4C89E7539 241A273B6891C1D6F8F2DDB460371005122A53A7D0ECF9F2DDB360360F051229 53A6D0EBFFFDE8BE4C220D03081D46B9E3F7FFFCE7BD4B210D02071C46B8E2F7 F3F0DBB15E34180B152C56A9D3E8F3EFDAB05D34170A142C55A9D2E9DFCCC69C 7341321F2F3F6B94BFC9DECCC59C7241311F2E3E6A94BFCAB5A38E8780705B49 596D7D808BA0B4A28D877F6F5B48586D7C818BA043506479859AAFBCAC978876 614C424F64798499AEBBAB968977624D19263B6791C3D8E5D6C79D7337231825 3A6690C3D7E5D5C79E74382304112952A5CFEDFAF0DBB25E350E03102851A5CE ECF9F1DCB25F360E01071B45B8E1F6FDFBE6BC4A200B01061B44B7E1F5FEFBE6 BD4A210C09142B55A8D2EAF4EED9AF5C321609132A54A7D1EAF5EED9B05D3316 1E2E3D6A93C0CADFCDC49A713F301D2D3D6993C1CBE0CEC59B71403048576C7C 828CA1B6A38F867E6E5947576C7B828DA2B6A48F867E6F5ABAAB968977624E43 50657A8398ADBAAA958A78634E4451667A8498ADE4D4C89E7539241A273B6891 C1D6E3D4C99F7539251A273C6892C2D7F9F2DDB360360F05122953A6D0EBF8F2 DDB460371005122A53A7D0ECFFFCE7BD4B210D02071C46B8E2F7FFFDE8BE4C22 0D03081D46B9E3F7F3EFDAB05D34170A142C55A9D2E9F3F0DBB15E34180B152C 56A9D3E8DECCC59C7241311F2E3E6A94BFCADFCCC69C7341321F2F3F6B94BFC9 B4A28D877F6F5B48586D7C818BA0B5A38E8780705B49596D7D808BA0424F6479 8499AEBBAB968977624D43506479859AAFBCAC978876614C18253A6690C3D7E5 D5C79E74382319263B6791C3D8E5D6C79D73372303102851A5CEECF9F1DCB25F 360E04112952A5CFEDFAF0DBB25E350E pop pop /customdata8 28 28 mul string def currentfile customdata8 readhexstring 050F2747B6D6EEF8FEF4DCBC4D2D1507111D375F9EC6E0E9EBE6CCA4653D1F13 2939556F8EA8C1D1D3C3AE9475573B2B4961717D808999B1B39B8B867F73634B B8A090827A6A5A42445C6C7C8492A2BAD8C8AA97785232222434546E8DACCADA F0E2CFA768401A0A0C1C365E9DC5E4F2FAF7DFBF50301802040E2646B5D5EDFC FFF5DDBD4E2E160806102848B7D7EFF9EAE7CDA5663E2014121E38609FC7E1E8 D2C2AF9576583C2C2A3A56708FA9C0D0B29A8A878074644C4A62727E818898B0 435B6B7B8593A3BBB9A19183796959412333536D8CADCBDBD9C9AB9677513121 0B1B355D9CC4E5F3F1E3CEA6673F1909030D2545B4D4ECFDFBF6DEBE4F2F1701 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop end end defaultpacking setpacking %%EndResource %%BeginResource: procset AGM_Gradient_Sep 1.0 0 %%Title: (AGM Gradient Procset) %%Version: 1.0 0 %%CreationDate: (4/26/96) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /AGM_Gradient_Sep 5 dict dup begin put /AGM_Gradient_Sep_private 100 dict def /initialize{ AGM_Gradient_Sep begin AGM_Gradient_Sep_private begin _compositeJob{ initializeSinglePassSeps }{ initializeMultiPassSeps }ifelse initializeSeps AGM_Gradient_private begin /_fillSD newSpotDict def /_rampSD newSpotDict def /_nCustomColorSD nd end AGM_Gradient_Sep_private { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall AGM_Gradient_Sep { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall end currentdict readonly pop end }def /terminate{ currentdict AGM_Gradient_Sep eq{ end }if }def AGM_Gradient_Sep_private begin /initializeSeps{ _noImage not _level2PS not and{ /_whiteBytes 1 makeByte8 pt /knockOut{ 8 setImageParms _whiteBytes /_image load 5 execImage }def /linealFill{ mySave 8 setImageParms _color{ _nCustomColorSD begin cyan magenta yellow black _spotColor{ spot1 begin /tintImage tintValue 1 exch sub makeByte8 def end spot2 begin /tintImage tintValue 1 exch sub makeByte8 def end }if end 4{ makeByte8 4 1 roll }repeat true 4 _nCustomColorSD ncolorimage }{ _nCustomColorSD/black get 1 exch sub makeByte8 _nCustomColorSD bwImage }ifelse myRestore }def }{ /knockOut{ gsave false setoverprint 1 setgray 0 0 1 1 rectfill grestore }def }ifelse /newSpotDict{ 11 dict dup begin /nSpots 2 def /spot1 7 dict def /spot2 7 dict def end }def /initSpotData { begin /name nd /tintImage nd /tintValue nd /spot_C nd /spot_M nd /spot_Y nd /spot_K nd end }def /initSpotDict{ begin /cyanInk false def /magentaInk false def /yellowInk false def /blackInk false def /cyan nd /magenta nd /yellow nd /black nd spot1 initSpotData spot2 initSpotData end }def /copySpotDict{ /_dst xp begin cyanInk magentaInk yellowInk blackInk cyan magenta yellow black spot1 spot2 end _dst begin /spot1 spot1 maxlength dict def /spot2 spot2 maxlength dict def spot2 copy pop spot1 copy pop /black xd /yellow xd /magenta xd /cyan xd /blackInk xd /yellowInk xd /magentaInk xd /cyanInk xd end }def /setCustomColor { 1 index /Black eq{ 6 1 roll 5 npop 1 exch sub setgray }{ 6 1 roll _ccAry1 astore exch dup null eq{ pop 0 }if setcustomcolor }ifelse }def /setCStop{ /_colorStyle exch pt _colorStyle 0 eq{ 0 0 0 4 -1 roll 1 exch sub _spotColor{ /_colorStyle 3 pt /Black 1 index 1 exch sub }if }if _colorStyle 2 eq{ 3 npop }if _rampSD _fillSD copySpotDict _colorStyle 4 eq{ pop 9 2 roll 3 npop 6 -2 roll } if _colorStyle 3 eq _colorStyle 4 eq or{ _fillSD begin exch dup spot1/name get eq{ spot1 spot2 }{ spot2 spot1 }ifelse begin begin /name xd 1 exch sub /tintValue xd 4{ tintValue mul 4 1 roll }repeat _spotColor not{ /tintValue null def }if end /tintValue 0 def end end }if _fillSD nsetcustomcolor }def /renderCMYK{ spot1/name get null eq spot2/name get null eq and dup not{ pop spot1 spotConverted }if dup not{ pop spot2 spotConverted }if }def /fill_ /fill load def /fillOvp{ currentoverprint{ _inRipSep{ currentcolorspace 0 get dup /DeviceGray eq 1 index /DeviceCMYK eq or{ pop currentcmykcolor add add add 0 eq{ newpath }if }{ /Separation eq{ currentcolor 0 eq{ newpath }if }if }ifelse }{ currentgray 1 eq{ newpath }if }ifelse }if fill_ }def /fill{ _nCustomColorSD begin renderCMYK { fillOvp }{ spot1 begin gsave name null ne{ spot_C spot_M spot_Y spot_K name tintValue setCustomColor }{ 1 setgray }ifelse fillOvp grestore end spot2 begin name null ne{ gsave true setoverprint spot_C spot_M spot_Y spot_K name tintValue setCustomColor fillOvp grestore }if end newpath }ifelse end }def /expandSpot{ _spotColor{ /_len xp _rampSD begin spot1 begin tintImage null ne{ tintImage _len expandOne /tintImage xd }if end spot2 begin tintImage null ne{ tintImage _len expandOne /tintImage xd }if end end }{ pop }ifelse }def /rampImage{ _rampSD begin _color{ /cyanInk _cyanData 0 ne def /magentaInk _magentaData 0 ne def /yellowInk _yellowData 0 ne def /blackInk _blackData 0 ne def _nSamples setImageParms _nSamples expandSpot _cyanData _magentaData _yellowData _blackData _nSamples 4 expandColor true 4 _rampSD ncolorimage }{ /cyanInk false def /magentaInk false def /yellowInk false def /blackInk true def _nSamples setImageParms _blackData _rampSD bwImage }ifelse end }def /nsetcustomcolor where{ pop }{ /nsetcustomcolor { /_nCustomColorSD xp _nCustomColorSD begin 4 copy /black xd /yellow xd /magenta xd /cyan xd 4 copy 0 ne /blackInk xd 0 ne /yellowInk xd 0 ne /magentaInk xd 0 ne /cyanInk xd end setcmykcolor }def }ifelse /nsetcustomcolorend where{ pop }{ /nsetcustomcolorend { /_nCustomColorSD null pt }def }ifelse }def /initializeSinglePassSeps{ /_decodeNorm [0 1] pt /_decodeInvert [1 0] pt /spotConverted { begin name null eq{ false }{ tintValue null eq tintImage null eq and{ true }{ false currentpagedevice/SeparationOrder get{name eq or}forall not }ifelse }ifelse end }def /dictImage { 20 dict dup begin /Dict xd /Decode xd /DataSource xd /ImageMatrix xd /BitsPerComponent xd /Height xd /Width xd /ImageType 1 def Dict end /_image load 1 execImage }def /bwImage{ begin gsave currentoverprint{ blackInk{ [/Separation /Black /DeviceGray{}] setcolorspace _decodeInvert dictImage }{ 5 npop }ifelse }{ /DeviceGray setcolorspace _decodeNorm dictImage }ifelse grestore end }def /ncolorimage where{ pop }{ /ncolorimage{ begin renderCMYK { cyanInk magentaInk and yellowInk and blackInk and not currentoverprint and { pop pop gsave cyanInk{ 8 copy [/Separation /Cyan /DeviceGray{}] setcolorspace 3 npop _decodeNorm dictImage }if magentaInk{ 8 copy [/Separation /Magenta /DeviceGray{}] setcolorspace 4 -1 roll 3 npop _decodeNorm dictImage }if yellowInk{ 8 copy [/Separation /Yellow /DeviceGray{}] setcolorspace 4 -2 roll 3 npop _decodeNorm dictImage }if blackInk{ 4 -3 roll [/Separation /Black /DeviceGray{}] setcolorspace 3 npop _decodeNorm dictImage }{ 8 npop }ifelse grestore }{ /_colorimage load 10 execImage }ifelse }{ 6 npop gsave spot1 begin name null ne tintImage null ne and{ [/Separation name /DeviceGray{}] setcolorspace 4 copy tintImage name /Black eq{ _decodeNorm }{ _decodeInvert }ifelse dictImage }{ 1 setgray fill }ifelse end spot2 begin true setoverprint name null ne tintImage null ne and{ [/Separation name /DeviceGray{}] setcolorspace tintImage name /Black eq{ _decodeNorm }{ _decodeInvert }ifelse dictImage }{ 4 npop 1 setgray fill }ifelse end grestore }ifelse end }def }ifelse }def /initializeMultiPassSeps{ /_isCMYKSep _cyanPlate _magentaPlate or _yellowPlate or _blackPlate or pt /invertXfer{ [ { 1 exch sub }/exec load systemdict /currenttransfer get exec /exec load ] cvx systemdict /settransfer get exec }def /ccThrough{ gsave 1 setCustomColor currentcmykcolor grestore add add add 0 ne }def /spotConverted { begin _isCMYKSep not{ false }{ name null eq{ false }{ tintValue null eq tintImage null eq and{ true }{ spot_C spot_M spot_Y spot_K name ccThrough }ifelse }ifelse }ifelse end }def /spotChannel { _isCMYKSep{ pop false }{ begin name null eq{ false }{ spot_C spot_M spot_Y spot_K name ccThrough }ifelse end }ifelse }def /getChannelData { _isCMYKSep dup{ pop renderCMYK }if { _blackPlate{ 4 1 roll 3 npop blackInk }{ _yellowPlate{ 4 2 roll 3 npop yellowInk }{ _magentaPlate{ 4 3 roll 3 npop magentaInk }{ 3 npop cyanInk }ifelse }ifelse }ifelse { true /nonZeroData }{ true /zeroData }ifelse }{ 4 npop spot1/name get null ne spot1 spotChannel and{ spot1/tintImage get dup null ne{ false /nonZeroData }{ pop false /noData }ifelse }{ spot2/name get null ne spot2 spotChannel and{ spot2/tintImage get dup null ne{ false /nonZeroData }{ pop false /noData }ifelse }{ false /noData }ifelse }ifelse }ifelse }def /renderChannelData { /_tmp xp _tmp /nonZeroData ne currentoverprint and{ pop _tmp /zeroData eq{pop}if 4 npop }{ _tmp /nonZeroData eq{ { invertXfer }if systemdict/image get 5 execImage }{ pop _tmp /zeroData eq{pop}if 4 npop knockOut }ifelse }ifelse }def /bwImage{ begin gsave dup dup dup getChannelData exch pop false exch renderChannelData grestore end }def /ncolorimage{ begin pop pop gsave spot2/name get null ne spot2 spotChannel and{ true setoverprint }if getChannelData renderChannelData grestore end }def }def end end defaultpacking setpacking %%EndResource %%BeginResource: procset AGM_Gradient 1.0 0 %%Title: (AGM Gradient Procset) %%Version: 1.0 0 %%CreationDate: (4/26/96) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /AGM_Gradient 20 dict dup begin put /AGM_Gradient_private 200 dict def /initialize { AGM_Gradient begin AGM_Gradient_private begin initializeVars /bd systemdict/mark get def /ed _level2PS { (>>) }{ (counttomark 2 idiv dup dict begin {def} repeat pop currentdict end) } ifelse cvx def _level2PS{ initializeLev2 }{ initializeLev1 }ifelse queryDevice initializeShading initializeOps _producingSeps{ AGM_Gradient_Sep/initialize get exec }{ initializeComposite }ifelse _illustrator{ /f{}def /F{}def /s{}def /S{}def /b{}def /B{}def }if /image where{ /image get /_image xd }if /colorimage where{ /colorimage get /_colorimage xd }if /rectfill where dup{ exch pop not _producingSeps or }{ not }ifelse { /rectfill{ gsave newpath 4 2 roll moveto 1 index 0 rlineto 0 1 index rlineto 1 index neg 0 rlineto pop pop closepath fill grestore }def }if /linealImage _noImage{ /rectImage load }{ _producingSeps{ AGM_Gradient_Sep/AGM_Gradient_Sep_private get begin /rampImage load end }{ /rampImage load }ifelse }ifelse def AGM_Gradient_private { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall AGM_Gradient { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall end currentdict readonly pop end }def /initializeAI { pop pop AGM_Gradient/AGM_Gradient_private get /_illustrator true put AGM_Gradient/initialize get exec AGM_Gradient begin }def /unload{ systemdict/languagelevel known{ systemdict/languagelevel get 2 ge{ userdict/AGM_Gradient_Sep 2 copy known{ undef }{ pop pop }ifelse userdict/AGM_Gradient 2 copy known{ undef }{ pop pop }ifelse }if }if }def /terminate{ currentdict AGM_Gradient eq{ end }if }def AGM_Gradient_private begin /initializeVars{ /_d255 256 array def 0 1 255{ _d255 exch dup 255 div put }bind for /_d255- 256 array def 0 1 255{ _d255- exch 1 _d255 2 index get sub put }bind for /_sSave nd /_dUserSpace matrix defaultmatrix def /_bUMatrix matrix def /_imageMatrix matrix def /_saveMatrix matrix def /_xm matrix def /_ccAry1 5 array def /_level2PS systemdict/languagelevel known dup{ pop systemdict/languagelevel get 2 ge }if def /_level3PS _level2PS systemdict/shfill known and def currentdict /_illustrator known not{ /_illustrator false def }if }def /initializeOps { AGM_Gradient begin currentdict/Bc known not{ /Bc{ _renderFlag 2 eq{ 6 npop }{ pushBSpace _rampIndex 0 eq{ pop pop setCStop }if linealFill popBSpace }ifelse }def }if currentdict/Bg known not{ /Bg{ 10 npop /_gradName xp /_renderFlag xp _renderFlag 2 ne{ _illustrator{ _of setoverprint }if _illustrator _eo and _renderFlag 3 eq or{ eoclip }{ clip }ifelse _gradNames _gradName 2 copy known{ get mark exch aload pop /_gradType xp 1 sub dup /_rampIndex xp /_maxRampIndex xp mark exch aload pop 0 0 }if pop pop getRampData }{ mark mark }ifelse }def }if currentdict/Bm known not{ /Bm{ _renderFlag 2 ne{ _gradType 0 eq{ linealRamp }{ radialGrad }ifelse }{ 6 npop }ifelse }def }if currentdict/Bh known not{ /Bh{ 2 npop /_yHi xp /_xHi xp /_radHilite _xHi 0 ne _yHi 0 ne or pt }def }if currentdict/Bn known not{ /Bn{ AGM_Gradient_private begin dict /_gradNames xp end }def }if currentdict/Bd known not{ /Bd{ AGM_Gradient begin AGM_Gradient_private begin /_nColorsBd xp /_gradType xp /_gradName xp }def }if currentdict/BD known not{ /BD{ currentdict/_gradNames known not{ /_gradNames 20 dict def }if ] _nColorsBd _gradType ] _gradName exch /_gradNames xput end end }def }if currentdict/Bb known not{ /Bb{ AGM_Gradient begin AGM_Gradient_private begin _producingSeps{ AGM_Gradient_Sep/AGM_Gradient_Sep_private get begin }if mySave }def }if currentdict/BB known not{ /BB{ /_tmp xp cleartomark cleartomark _tmp dup _renderFlag myRestore _producingSeps{ end }if _illustrator end end { 2 ne exch 0 gt and{ 2 eq{ s }{ S }ifelse }{ pop newpath }ifelse }{ pop newpath }ifelse }def }if currentdict/Xm known not{ /Xm{ _xm astore pop }def }if end }def /queryDevice{ /_inRipSep _level2PS{ currentpagedevice/Separations 2 copy known{ get }{ pop pop false }ifelse }{ false }ifelse def /_noImage /lv1Fix where{ pop lv1Fix }{ false }ifelse def /_useShells where{ pop }{ /_useShells true def }ifelse /_useSmoothShade where{ pop }{ /_useSmoothShade false def }ifelse /_cyanPlate 1 0 0 0 testCMYKColorThrough def /_magentaPlate 0 1 0 0 testCMYKColorThrough def /_yellowPlate 0 0 1 0 testCMYKColorThrough def /_blackPlate 0 0 0 1 testCMYKColorThrough def /_compositeJob _cyanPlate _magentaPlate and _yellowPlate and _blackPlate and def /_compositeSpotDevice where{ pop }{ /_compositeSpotDevice _compositeJob not _inRipSep or{ 1 }{ 0 }ifelse def }ifelse /_producingSeps _compositeSpotDevice 0 ne def /_deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt def /_dpiThreshold where{ pop }{ /_dpiThreshold 600 def }ifelse /_screenFreqThreshold where{ pop }{ /_screenFreqThreshold 150 def }ifelse /_contoneDevice where{ pop }{ /_contoneDevice false def }ifelse /_subSampleOK _deviceDPI _dpiThreshold le currentScreenFreq _screenFreqThreshold le and _contoneDevice not and _producingSeps not and def }def /initializeLev1{ /makeByte8{ /_tmp 0 pt 255 mul cvi 8 string 8{ dup _tmp 3 index put /_tmp _tmp 1 add pt }repeat exch pop }def /currentScreenFreq{ currentscreen pop pop }def /_byte 1 string def /colorimage where{ pop }{ /colorimage{ pop pop /_blackTmp xp /_yellowTmp xp /_magentaTmp xp /_cyanTmp xp /_cnt 0 pt [ _byte dup 0 _cyanTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .3 /mul cvx _magentaTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .59 /mul cvx _yellowTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .11 /mul cvx _blackTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx /add cvx /add cvx /add cvx 1 /exch cvx /sub cvx /dup cvx 0 /lt cvx{ pop 0 }/if cvx /dup cvx 1 /gt cvx{ pop 1 }/if cvx 255 /mul cvx /cvi cvx 256 /mod cvx /dup cvx 0 /lt cvx{ pop 0 }/if cvx /put cvx /_cnt dup cvx 1 /add cvx /pt cvx ] cvx bind /_image load 5 execImage }def }ifelse }def /initializeLev2{ /level2ScreenFreq{ begin 60 HalftoneType 1 eq{ pop Frequency }if HalftoneType 2 eq{ pop GrayFrequency }if HalftoneType 5 eq{ pop Default level2ScreenFreq }if end }def /currentScreenFreq{ currenthalftone level2ScreenFreq }def }def /initializeShading{ _useSmoothShade _level3PS and{ /_usingSmoothShade true pt initializeLev3_Ops }{ /_usingSmoothShade false pt }ifelse }def /initializeLev3_Ops { /initShFill{ /_index _gradType 0 eq {0}{_maxRampIndex 1 sub} ifelse pt /_rampFuncsArray _maxRampIndex array pt /_boundsArray _maxRampIndex 1 sub array pt /_encodeArray _maxRampIndex 2 mul array pt /_beginCoord _rampPoint pt /_colorSpace null pt /_firstFill _rampIndex _maxRampIndex eq pt /_lastFill false pt }def /getRampColorSpace{ _nSamples 1 gt{ /_ndx 0 pt [blendColor] cvx exec }if /_C0 [currentcolor] pt /_C0_Space currentcolorspace pt _nSamples 1 gt{ /_ndx _nSamples 1 sub pt [blendColor] cvx exec }if /_C1 [currentcolor] pt /_C1_Space currentcolorspace pt _C0_Space _C1_Space eq{ /_rampColorSpace _C0_Space pt }{ (colorspace conflict!) == showpage stop }ifelse _spotColor{ nsetcustomcolorend }if }def /linealShFill{ popBSpace _xm aload pop pushBSpace /_size _index 1 add pt _size _maxRampIndex lt { /_rampFuncsArray _rampFuncsArray 0 _size getinterval pt /_boundsArray _boundsArray 0 _size 1 sub getinterval pt /_encodeArray _encodeArray 0 _size 2 mul getinterval pt }if bd /ShadingType 2 /ColorSpace _colorSpace /Function bd /FunctionType 3 /Domain [0 1] /Functions _rampFuncsArray /Bounds _boundsArray /Encode _encodeArray ed /Extend [_firstFill _lastFill] /Domain [0 1] /Coords [_beginCoord 0 _endCoord 0] ed shfill }def /radialShFill{ /_size _maxRampIndex _index sub pt _size _maxRampIndex lt { /_rampFuncsArray _rampFuncsArray _index _size getinterval pt /_boundsArray _boundsArray _index _size 1 sub getinterval pt /_encodeArray _encodeArray _index 2 mul _size 2 mul getinterval pt }if /_rampLen _beginCoord _endCoord sub pt bd /ShadingType 3 /ColorSpace _colorSpace /Function bd /FunctionType 3 /Domain [0 1] /Functions _rampFuncsArray /Bounds _boundsArray /Encode _encodeArray ed /Extend [_lastFill _firstFill] /Domain [0 1] /Coords [_xHi _rampLen mul _yHi _rampLen mul _endCoord 0 0 _beginCoord] ed shfill _radHilite{ _xHi _rampLen mul _yHi _rampLen mul translate }if }def /fillRamp{ /_invert _midPoint 0.5 lt pt _rampIndex _maxRampIndex eq { initShFill }if getRampColorSpace _colorSpace null eq{ /_colorSpace _rampColorSpace pt }{ _colorSpace _rampColorSpace ne{ /_index _index 1 _gradType 0 eq{ sub pt linealShFill }{ add pt radialShFill }ifelse initShFill /_colorSpace _rampColorSpace pt } if }ifelse /_endCoord _endPoint pt _rampFuncsArray _index bd /FunctionType 2 /Domain [0 1] /N 0.5 log _invert{1 _midPoint sub}{_midPoint}ifelse log div _gradType 0 eq{ _invert{/C1}{/C0}ifelse _C0 _invert{/C0}{/C1}ifelse _C1 }{ _invert{/C0}{/C1}ifelse _C1 _invert{/C1}{/C0}ifelse _C0 }ifelse ed put _rampIndex 1 ne{ _boundsArray _index _gradType 1 eq{1 sub}if _endCoord put } if 0 1 _invert {exch}if _encodeArray _index 2 mul 1 add 3 -1 roll put _encodeArray _index 2 mul 3 -1 roll put _rampIndex 1 eq { /_lastFill true pt _gradType 0 eq{ linealShFill }{ radialShFill }ifelse }if /_index _index 1 _gradType 0 eq{ add pt }{ sub pt }ifelse }def /radialRamp /fillRamp load def /rampImage /fillRamp load def AGM_Gradient begin /Bc{ 6 npop }def end }def /initializeComposite{ /bwImage{ pop /_image load 5 execImage }def currentdict/rampImage known not{ /rampImage{ _color{ _nSamples setImageParms _rgbRamp{ _redData _greenData _blueData _nSamples 3 expandColor true 3 null ncolorimage }{ _cyanData _magentaData _yellowData _blackData _nSamples 4 expandColor true 4 null ncolorimage }ifelse }{ _nSamples setImageParms _blackData null bwImage }ifelse }def }if /setCStop{ /_colorStyle exch pt _colorStyle 0 eq{ 1 exch sub 0 0 0 4 -1 roll }if _colorStyle 2 eq{ setrgbcolor 4 npop }if _colorStyle 3 eq{ 1 exch sub /_tmp xp pop 4{ _tmp mul 4 1 roll }repeat }if _colorStyle 4 eq{ 3 -1 roll pop pop 1 exch sub /_tmp xp 3{ 1 exch sub _tmp mul 1 exch sub 3 1 roll }repeat setrgbcolor 4 npop }if _colorStyle 2 ne _colorStyle 4 ne and{ null nsetcustomcolor }if }def /nsetcustomcolor { pop setcmykcolor }def /nsetcustomcolorend { }def /ncolorimage{ pop /_colorimage load 10 execImage }def _noImage not _level2PS not and{ /linealFill{ 8 setImageParms _color{ currentcmykcolor 4{ makeByte8 4 1 roll }repeat true 4 null ncolorimage }{ currentgray makeByte8 null bwImage }ifelse }def }if }def /npop{ {pop}repeat }def /xd{ exch def }def /nd{ null def }def /pt{ AGM_Gradient_private 3 1 roll put }def /xp{ exch pt }def /xput{ dup load dup length exch maxlength eq{ dup dup load dup length 2 mul dict copy def }if load begin def end }def /mySave{ save /_sSave xp }def /myRestore{ _sSave type /savetype eq{ _sSave restore }if }def /gMark{ counttomark 2 add -1 roll }def /execImage{ /_tmp xp { exec }stopped{ $error /errorname get /undefinedresult ne{ stop }{ _tmp npop }ifelse }if }def /pushBSpace{ newpath gsave _bUMatrix astore concat }def /popBSpace{ grestore }def /setImageParms{ 1 8 2 index 0 0 1 0 0 _imageMatrix astore }def /linealFill{ 0 0 1 1 rectfill }def /testCMYKColorThrough{ gsave setcmykcolor currentcmykcolor grestore add add add 0 ne }def /expandOne { /_tmp xp dup type /stringtype ne{ _tmp string exch dup 0 ne{ 255 mul cvi 0 1 _tmp 1 sub{ 3 copy exch put pop }for }if pop }if }def /expandColor{ /_channels xp /_len xp _channels{ _len expandOne _channels 1 roll }repeat }def /blendColor{ _color{ _rgbRamp _producingSeps not and{ _redData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _greenData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _blueData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if /setrgbcolor cvx }{ _cyanData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _magentaData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _yellowData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _blackData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _spotColor{ _rampSD begin /_rampSD cvx /begin cvx spot1 begin tintImage dup type /stringtype eq{ /_ndx cvx /get cvx _d255- /exch cvx /get cvx }{ dup null ne{ name type /nametype ne{ 1 exch sub }if }if }ifelse end /spot1 cvx /tintValue 3 -1 /roll cvx /put cvx spot2 begin tintImage dup type /stringtype eq{ /_ndx cvx /get cvx _d255- /exch cvx /get cvx }{ dup null ne{ name type /nametype ne{ 1 exch sub }if }if }ifelse end /spot2 cvx /tintValue 3 -1 /roll cvx /put cvx /end cvx end /_rampSD cvx /nsetcustomcolor cvx }{ /setcmykcolor cvx }ifelse }ifelse }{ _blackData /_ndx cvx /get cvx _d255 /exch cvx /get cvx _usingSmoothShade{ 1 /exch cvx /sub cvx 0 0 0 4 -1 /roll cvx /setcmykcolor cvx }{ /setgray cvx }ifelse }ifelse }def /linealRamp{ pushBSpace _ramp{ linealImage }{ linealFill }ifelse popBSpace /_rampIndex _rampIndex 1 sub pt _rampIndex 0 gt{ getRampData }if }def /radialGrad{ /_firstShell true pt _usingSmoothShade not{ fill }if pushBSpace _radHilite{ _xHi _yHi _bUMatrix idtransform /_yHi xp /_xHi xp _rampPoint 1 lt{ 1 _rampPoint sub dup _xHi mul exch _yHi mul translate }if }if _rampIndex{ radialRamp /_rampIndex _rampIndex 1 sub pt _rampIndex 0 gt{ getRampData }if }repeat popBSpace }def /getNSamples{ 0 exch { dup type /stringtype eq{ length exch pop exit }if pop }forall dup 0 eq{ pop 1 }if }def /getRampData{ /_rampType gMark pt /_color _rampType 0 gt pt /_ccRGB _rampType 5 eq _rampType 6 eq or pt /_rgbRamp _rampType 4 eq _ccRGB or pt /_ccProcess _rampType 2 eq _rampType 3 eq or pt _producingSeps{ _rampSD initSpotDict /_spotColor _ccProcess _ccRGB or pt }{ /_spotColor false pt }ifelse /_ramp true pt 100 div /_rampPoint xp 100 div /_midPoint xp dup /_colorStyle xp _colorStyle 0 eq{ 2 }{ _colorStyle 1 eq{ 5 }{ _colorStyle 2 eq{ 8 }{ _colorStyle 3 eq{ _producingSeps{ _rampSD begin spot1 begin /name 3 index def /spot_K 4 index def /spot_Y 5 index def /spot_M 6 index def /spot_C 7 index def end end }if 7 }{ _producingSeps{ _rampSD begin spot1 begin /name 4 index def /spot_K 8 index def /spot_Y 9 index def /spot_M 10 index def /spot_C 11 index def end end }if 11 } ifelse }ifelse }ifelse }ifelse /_tmp xp _tmp index 100 div /_endPoint xp _gradType 1 eq{ _tmp 1 add index 100 div /_midPoint xp }if _producingSeps{ _tmp 2 add index /_nextColorStyle xp _nextColorStyle 3 eq{ /_tmp _tmp 4 add pt _tmp index dup _rampSD begin spot1 /name get ne{ spot2 begin /name xd /spot_K _tmp 2 add index def /spot_Y _tmp 3 add index def /spot_M _tmp 4 add index def /spot_C _tmp 5 add index def end }{ pop }ifelse end }if _nextColorStyle 4 eq{ /_tmp _tmp 5 add pt _tmp index dup _rampSD begin spot1 /name get ne{ spot2 begin /name xd /spot_K _tmp 5 add index def /spot_Y _tmp 6 add index def /spot_M _tmp 7 add index def /spot_C _tmp 8 add index def end }{ pop }ifelse end }if }if _rampType 3 eq _rampType 6 eq or{ /_tint2Data gMark pt }if _ccProcess _ccRGB or{ /_tint1Data gMark pt }if _rgbRamp{ /_blueData gMark pt /_greenData gMark pt /_redData gMark pt }if _producingSeps{ _rampSD begin _ccProcess _ccRGB or{ _rampType 3 eq _rampType 6 eq or{ spot2 begin /tintImage _gradType 0 eq{ _tint2Data }{ _tint1Data }ifelse def name null eq{ /name /Black def }if end }if spot1 begin /tintImage _gradType 0 eq _rampType 2 eq or _rampType 5 eq or{ _tint1Data }{ _tint2Data }ifelse def _rampType 2 eq _rampType 5 eq or{ name null eq{ /name spot2 /name get def spot2 /name null put }if }{ name null eq{ /name /Black def }if }ifelse end }if end }if /_blackData gMark pt _rampType 0 gt{ counttomark 4 add -3 roll /_yellowData xp /_magentaData xp /_cyanData xp }if _ramp{ /_nSamples [ _rampType 0 eq {_blackData}if _rampType 1 eq {_cyanData _magentaData _yellowData _blackData}if _rampType 2 eq {_cyanData _magentaData _yellowData _blackData _tint1Data}if _rampType 3 eq {_cyanData _magentaData _yellowData _blackData _tint1Data _tint2Data}if _rampType 4 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData}if _rampType 5 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData _tint1Data}if _rampType 6 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData _tint1Data _tint2Data}if ] getNSamples pt _usingSmoothShade not {/_ramp _nSamples 1 gt pt} if } if setCStop }def /rectImage{ gsave /_sInc 1 pt /_bInc 1 _nSamples div pt /_uRampLen 1 0 dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt pt /_pChange _uRampLen 0 eq{0}{_nSamples _uRampLen div}ifelse pt 0 _nSamples [ /dup cvx /_ndx /exch cvx /pt cvx blendColor 0 0 _bInc 1 /rectfill cvx _bInc 0 /translate cvx _sInc /add cvx ] cvx bind repeat pop _spotColor{ nsetcustomcolorend }if grestore }def /radialInit{ /_nRadSamples _nSamples dup 0 eq{pop 1}if pt /_sInc -1 pt /_rampLen _rampPoint _endPoint sub pt /_bInc _rampLen _nSamples div neg pt /_optimize false pt _subSampleOK{ /_uRampLen _rampLen 0 dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt 0 _rampLen dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt 2 copy lt{ exch }if pop pt /_pChange _uRampLen 0 eq{ 0 }{ _nSamples _uRampLen div }ifelse pt _pChange .5 gt dup /_optimize xp{ /_nRadSamples _uRampLen 2 div round cvi dup 1 le{pop 2}if pt /_bInc _rampLen _nRadSamples div neg pt /_sInc _nSamples 1 sub _nRadSamples 1 sub div neg pt }if }if _radHilite{ /_xBCInc _xHi _rampLen mul _nRadSamples div pt /_yBCInc _yHi _rampLen mul _nRadSamples div pt }if }def currentdict/radialRamp known not{ /radialRamp{ /_saveMatrix _saveMatrix currentmatrix def radialInit _rampPoint _nSamples 1 sub _nRadSamples [ /dup cvx _optimize{ /round cvx /cvi cvx }if /_ndx /exch cvx /pt cvx _useShells{ /_firstShell cvx{ /_firstShell false pt }{ 0 0 3 index 360 0 arcn fill }/ifelse cvx }if blendColor _useShells{ 0 0 3 /index cvx 0 360 /arc cvx }{ 0 0 3 /index cvx 0 360 /arc cvx /fill cvx }ifelse /exch cvx _bInc /add cvx /exch cvx _sInc /add cvx _radHilite{ _xBCInc _yBCInc /translate cvx }if ] cvx bind repeat pop pop _saveMatrix setmatrix _radHilite{ _xHi _rampLen mul _yHi _rampLen mul translate }if _useShells _rampIndex 1 eq and{ fill }if _spotColor{ nsetcustomcolorend }if }def }if end end defaultpacking setpacking %%EndResource %%BeginProcSet: Adobe_ColorImage_AI6 1.1 0 userdict /Adobe_ColorImage_AI6 known not { userdict /Adobe_ColorImage_AI6 24 dict put } if userdict /Adobe_ColorImage_AI6 get begin /initialize { Adobe_ColorImage_AI6 begin Adobe_ColorImage_AI6 { dup type /arraytype eq { dup xcheck { bind } if } if pop pop } forall } def /terminate { end } def currentdict /Adobe_ColorImage_AI6_Vars known not { /Adobe_ColorImage_AI6_Vars 15 dict def } if Adobe_ColorImage_AI6_Vars begin /channelcount 0 def /sourcecount 0 def /sourcearray 4 array def /plateindex -1 def /XIMask 0 def /XIBinary 0 def /XIChannelCount 0 def /XIBitsPerPixel 0 def /XIImageHeight 0 def /XIImageWidth 0 def /XIImageMatrix null def /XIBuffer null def /XIDataProc null def /XIVersion 6 def end /WalkRGBString null def /WalkCMYKString null def /StuffRGBIntoGrayString null def /RGBToGrayImageProc null def /StuffCMYKIntoGrayString null def /CMYKToGrayImageProc null def /ColorImageCompositeEmulator null def /SeparateCMYKImageProc null def /FourEqual null def /TestPlateIndex null def currentdict /_colorimage known not { /colorimage where { /colorimage get /_colorimage exch def } { /_colorimage null def } ifelse } if /_currenttransfer systemdict /currenttransfer get def /colorimage null def /XI null def /WalkRGBString { 0 3 index dup length 1 sub 0 3 3 -1 roll { 3 getinterval { } forall 5 index exec 3 index } for 5 { pop } repeat } def /WalkCMYKString { 0 3 index dup length 1 sub 0 4 3 -1 roll { 4 getinterval { } forall 6 index exec 3 index } for 5 { pop } repeat } def /StuffRGBIntoGrayString { .11 mul exch .59 mul add exch .3 mul add cvi 3 copy put pop 1 add } def /RGBToGrayImageProc { Adobe_ColorImage_AI6_Vars begin sourcearray 0 get exec dup length 3 idiv string dup 3 1 roll /StuffRGBIntoGrayString load exch WalkRGBString end } def /StuffCMYKIntoGrayString { exch .11 mul add exch .59 mul add exch .3 mul add dup 255 gt { pop 255 } if 255 exch sub cvi 3 copy put pop 1 add } def /CMYKToGrayImageProc { Adobe_ColorImage_AI6_Vars begin sourcearray 0 get exec dup length 4 idiv string dup 3 1 roll /StuffCMYKIntoGrayString load exch WalkCMYKString end } def /ColorImageCompositeEmulator { pop true eq { Adobe_ColorImage_AI6_Vars /sourcecount get 5 add { pop } repeat } { Adobe_ColorImage_AI6_Vars /channelcount get 1 ne { Adobe_ColorImage_AI6_Vars begin sourcearray 0 3 -1 roll put channelcount 3 eq { /RGBToGrayImageProc } { /CMYKToGrayImageProc } ifelse load end } if image } ifelse } def /SeparateCMYKImageProc { Adobe_ColorImage_AI6_Vars begin sourcecount 0 ne { sourcearray plateindex get exec } { sourcearray 0 get exec dup length 4 idiv string 0 2 index plateindex 4 2 index length 1 sub { get 255 exch sub 3 copy put pop 1 add 2 index } for pop pop exch pop } ifelse end } def /FourEqual { 4 index ne { pop pop pop false } { 4 index ne { pop pop false } { 4 index ne { pop false } { 4 index eq } ifelse } ifelse } ifelse } def /TestPlateIndex { Adobe_ColorImage_AI6_Vars begin /plateindex -1 def /setcmykcolor where { pop gsave 1 0 0 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 1 0 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 0 1 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 0 0 1 setcmykcolor systemdict /currentgray get exec 1 exch sub grestore 1 0 0 0 FourEqual { /plateindex 0 def } { 0 1 0 0 FourEqual { /plateindex 1 def } { 0 0 1 0 FourEqual { /plateindex 2 def } { 0 0 0 1 FourEqual { /plateindex 3 def } { 0 0 0 0 FourEqual { /plateindex 5 def } if } ifelse } ifelse } ifelse } ifelse pop pop pop pop } if plateindex end } def /colorimage { Adobe_ColorImage_AI6_Vars begin /channelcount 1 index def /sourcecount 2 index 1 eq { channelcount 1 sub } { 0 } ifelse def 4 sourcecount add index dup 8 eq exch 1 eq or not end { /_colorimage load null ne { _colorimage } { Adobe_ColorImage_AI6_Vars /sourcecount get 7 add { pop } repeat } ifelse } { dup 3 eq TestPlateIndex dup -1 eq exch 5 eq or or { /_colorimage load null eq { ColorImageCompositeEmulator } { dup 1 eq { pop pop image } { Adobe_ColorImage_AI6_Vars /plateindex get 5 eq { gsave 0 _currenttransfer exec 1 _currenttransfer exec eq { 0 _currenttransfer exec 0.5 lt } { 0 _currenttransfer exec 1 _currenttransfer exec gt } ifelse { { pop 0 } } { { pop 1 } } ifelse systemdict /settransfer get exec } if _colorimage Adobe_ColorImage_AI6_Vars /plateindex get 5 eq { grestore } if } ifelse } ifelse } { dup 1 eq { pop pop image } { pop pop Adobe_ColorImage_AI6_Vars begin sourcecount -1 0 { exch sourcearray 3 1 roll put } for /SeparateCMYKImageProc load end systemdict /image get exec } ifelse } ifelse } ifelse } def /XG { pop pop } def /XF { 13 {pop} repeat } def /Xh { Adobe_ColorImage_AI6_Vars begin gsave /XIMask exch 0 ne def /XIImageHeight exch def /XIImageWidth exch def /XIImageMatrix exch def 0 0 moveto XIImageMatrix concat XIImageWidth XIImageHeight scale XIMask { /_lp /null ddef _fc /_lp /imagemask ddef } if /XIVersion 7 def end } def /XH { Adobe_ColorImage_AI6_Vars begin /XIVersion 6 def grestore end } def /XI { Adobe_ColorImage_AI6_Vars begin gsave /XIMask exch 0 ne def /XIBinary exch 0 ne def pop pop /XIChannelCount exch def /XIBitsPerPixel exch def /XIImageHeight exch def /XIImageWidth exch def pop pop pop pop /XIImageMatrix exch def XIBitsPerPixel 1 eq { XIImageWidth 8 div ceiling cvi } { XIImageWidth XIChannelCount mul } ifelse /XIBuffer exch string def XIBinary { /XIDataProc { currentfile XIBuffer readstring pop } def XIVersion 6 le { currentfile 128 string readline pop pop } if } { /XIDataProc { currentfile XIBuffer readhexstring pop } def } ifelse XIVersion 6 le { 0 0 moveto XIImageMatrix concat XIImageWidth XIImageHeight scale XIMask { /_lp /null ddef _fc /_lp /imagemask ddef } if } if XIMask { XIImageWidth XIImageHeight false [ XIImageWidth 0 0 XIImageHeight neg 0 0 ] /XIDataProc load imagemask } { XIImageWidth XIImageHeight XIBitsPerPixel [ XIImageWidth 0 0 XIImageHeight neg 0 0 ] /XIDataProc load XIChannelCount 1 eq { gsave 0 setgray image grestore } { false XIChannelCount colorimage } ifelse } ifelse grestore end } def end %%EndProcSet %%BeginResource: procset Adobe_Illustrator_AI5 1.1 0 %%Title: (Adobe Illustrator (R) Version 5.0 Full Prolog) %%Version: 1.1 0 %%CreationDate: (3/7/1994) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_Illustrator_AI5_vars 81 dict dup begin put /_eo false def /_lp /none def /_pf { } def /_ps { } def /_psf { } def /_pss { } def /_pjsf { } def /_pjss { } def /_pola 0 def /_doClip 0 def /cf currentflat def /_tm matrix def /_renderStart [ /e0 /r0 /a0 /o0 /e1 /r1 /a1 /i0 ] def /_renderEnd [ null null null null /i1 /i1 /i1 /i1 ] def /_render -1 def /_rise 0 def /_ax 0 def /_ay 0 def /_cx 0 def /_cy 0 def /_leading [ 0 0 ] def /_ctm matrix def /_mtx matrix def /_sp 16#020 def /_hyphen (-) def /_fScl 0 def /_cnt 0 def /_hs 1 def /_nativeEncoding 0 def /_useNativeEncoding 0 def /_tempEncode 0 def /_pntr 0 def /_tDict 2 dict def /_wv 0 def /Tx { } def /Tj { } def /CRender { } def /_AI3_savepage { } def /_gf null def /_cf 4 array def /_if null def /_of false def /_fc { } def /_gs null def /_cs 4 array def /_is null def /_os false def /_sc { } def /_pd 1 dict def /_ed 15 dict def /_pm matrix def /_fm null def /_fd null def /_fdd null def /_sm null def /_sd null def /_sdd null def /_i null def /discardSave null def /buffer 256 string def /beginString null def /endString null def /endStringLength null def /layerCnt 1 def /layerCount 1 def /perCent (%) 0 get def /perCentSeen? false def /newBuff null def /newBuffButFirst null def /newBuffLast null def /clipForward? false def end userdict /Adobe_Illustrator_AI5 known not { userdict /Adobe_Illustrator_AI5 91 dict put } if userdict /Adobe_Illustrator_AI5 get begin /initialize { Adobe_Illustrator_AI5 dup begin Adobe_Illustrator_AI5_vars begin discardDict { bind pop pop } forall dup /nc get begin { dup xcheck 1 index type /operatortype ne and { bind } if pop pop } forall end newpath } def /terminate { end end } def /_ null def /ddef { Adobe_Illustrator_AI5_vars 3 1 roll put } def /xput { dup load dup length exch maxlength eq { dup dup load dup length 2 mul dict copy def } if load begin def end } def /npop { { pop } repeat } def /sw { dup length exch stringwidth exch 5 -1 roll 3 index mul add 4 1 roll 3 1 roll mul add } def /swj { dup 4 1 roll dup length exch stringwidth exch 5 -1 roll 3 index mul add 4 1 roll 3 1 roll mul add 6 2 roll /_cnt 0 ddef { 1 index eq { /_cnt _cnt 1 add ddef } if } forall pop exch _cnt mul exch _cnt mul 2 index add 4 1 roll 2 index add 4 1 roll pop pop } def /ss { 4 1 roll { 2 npop (0) exch 2 copy 0 exch put pop gsave false charpath currentpoint 4 index setmatrix stroke grestore moveto 2 copy rmoveto } exch cshow 3 npop } def /jss { 4 1 roll { 2 npop (0) exch 2 copy 0 exch put gsave _sp eq { exch 6 index 6 index 6 index 5 -1 roll widthshow currentpoint } { false charpath currentpoint 4 index setmatrix stroke } ifelse grestore moveto 2 copy rmoveto } exch cshow 6 npop } def /sp { { 2 npop (0) exch 2 copy 0 exch put pop false charpath 2 copy rmoveto } exch cshow 2 npop } def /jsp { { 2 npop (0) exch 2 copy 0 exch put _sp eq { exch 5 index 5 index 5 index 5 -1 roll widthshow } { false charpath } ifelse 2 copy rmoveto } exch cshow 5 npop } def /pl { transform 0.25 sub round 0.25 add exch 0.25 sub round 0.25 add exch itransform } def /setstrokeadjust where { pop true setstrokeadjust /c { curveto } def /C /c load def /v { currentpoint 6 2 roll curveto } def /V /v load def /y { 2 copy curveto } def /Y /y load def /l { lineto } def /L /l load def /m { moveto } def } { /c { pl curveto } def /C /c load def /v { currentpoint 6 2 roll pl curveto } def /V /v load def /y { pl 2 copy curveto } def /Y /y load def /l { pl lineto } def /L /l load def /m { pl moveto } def } ifelse /d { setdash } def /cf { } def /i { dup 0 eq { pop cf } if setflat } def /j { setlinejoin } def /J { setlinecap } def /M { setmiterlimit } def /w { setlinewidth } def /XR { 0 ne /_eo exch ddef } def /H { } def /h { closepath } def /N { _pola 0 eq { _doClip 1 eq { _eo {eoclip} {clip} ifelse /_doClip 0 ddef } if newpath } { /CRender { N } ddef } ifelse } def /n { N } def /F { _pola 0 eq { _doClip 1 eq { gsave _pf grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _fc /_doClip 0 ddef } { _pf } ifelse } { /CRender { F } ddef } ifelse } def /f { closepath F } def /S { _pola 0 eq { _doClip 1 eq { gsave _ps grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _sc /_doClip 0 ddef } { _ps } ifelse } { /CRender { S } ddef } ifelse } def /s { closepath S } def /B { _pola 0 eq { _doClip 1 eq gsave F grestore { gsave S grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _sc /_doClip 0 ddef } { S } ifelse } { /CRender { B } ddef } ifelse } def /b { closepath B } def /W { /_doClip 1 ddef } def /* { count 0 ne { dup type /stringtype eq { pop } if } if newpath } def /u { } def /U { } def /q { _pola 0 eq { gsave } if } def /Q { _pola 0 eq { grestore } if } def /*u { _pola 1 add /_pola exch ddef } def /*U { _pola 1 sub /_pola exch ddef _pola 0 eq { CRender } if } def /D { pop } def /*w { } def /*W { } def /` { /_i save ddef clipForward? { nulldevice } if 6 1 roll 4 npop concat pop userdict begin /showpage { } def 0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit [] 0 setdash /setstrokeadjust where {pop false setstrokeadjust} if newpath 0 setgray false setoverprint } def /~ { end _i restore } def /O { 0 ne /_of exch ddef /_lp /none ddef } def /R { 0 ne /_os exch ddef /_lp /none ddef } def /g { /_gf exch ddef /_fc { _lp /fill ne { _of setoverprint _gf setgray /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /G { /_gs exch ddef /_sc { _lp /stroke ne { _os setoverprint _gs setgray /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /k { _cf astore pop /_fc { _lp /fill ne { _of setoverprint _cf aload pop setcmykcolor /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /K { _cs astore pop /_sc { _lp /stroke ne { _os setoverprint _cs aload pop setcmykcolor /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /x { /_gf exch ddef findcmykcustomcolor /_if exch ddef /_fc { _lp /fill ne { _of setoverprint _if _gf 1 exch sub setcustomcolor /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /X { /_gs exch ddef findcmykcustomcolor /_is exch ddef /_sc { _lp /stroke ne { _os setoverprint _is _gs 1 exch sub setcustomcolor /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /A { pop } def /annotatepage { userdict /annotatepage 2 copy known {get exec} {pop pop} ifelse } def /XT { pop pop } def /discard { save /discardSave exch store discardDict begin /endString exch store gt38? { 2 add } if load stopped pop end discardSave restore } bind def userdict /discardDict 7 dict dup begin put /pre38Initialize { /endStringLength endString length store /newBuff buffer 0 endStringLength getinterval store /newBuffButFirst newBuff 1 endStringLength 1 sub getinterval store /newBuffLast newBuff endStringLength 1 sub 1 getinterval store } def /shiftBuffer { newBuff 0 newBuffButFirst putinterval newBuffLast 0 currentfile read not { stop } if put } def 0 { pre38Initialize mark currentfile newBuff readstring exch pop { { newBuff endString eq { cleartomark stop } if shiftBuffer } loop } { stop } ifelse } def 1 { pre38Initialize /beginString exch store mark currentfile newBuff readstring exch pop { { newBuff beginString eq { /layerCount dup load 1 add store } { newBuff endString eq { /layerCount dup load 1 sub store layerCount 0 eq { cleartomark stop } if } if } ifelse shiftBuffer } loop } if } def 2 { mark { currentfile buffer readline not { stop } if endString eq { cleartomark stop } if } loop } def 3 { /beginString exch store /layerCnt 1 store mark { currentfile buffer readline not { stop } if dup beginString eq { pop /layerCnt dup load 1 add store } { endString eq { layerCnt 1 eq { cleartomark stop } { /layerCnt dup load 1 sub store } ifelse } if } ifelse } loop } def end userdict /clipRenderOff 15 dict dup begin put { /n /N /s /S /f /F /b /B } { { _doClip 1 eq { /_doClip 0 ddef _eo {eoclip} {clip} ifelse } if newpath } def } forall /Tr /pop load def /Bb {} def /BB /pop load def /Bg {12 npop} def /Bm {6 npop} def /Bc /Bm load def /Bh {4 npop} def end /Lb { 4 npop 6 1 roll pop 4 1 roll pop pop pop 0 eq { 0 eq { (%AI5_BeginLayer) 1 (%AI5_EndLayer--) discard } { /clipForward? true def /Tx /pop load def /Tj /pop load def currentdict end clipRenderOff begin begin } ifelse } { 0 eq { save /discardSave exch store } if } ifelse } bind def /LB { discardSave dup null ne { restore } { pop clipForward? { currentdict end end begin /clipForward? false ddef } if } ifelse } bind def /Pb { pop pop 0 (%AI5_EndPalette) discard } bind def /Np { 0 (%AI5_End_NonPrinting--) discard } bind def /Ln /pop load def /Ap /pop load def /Ar { 72 exch div 0 dtransform dup mul exch dup mul add sqrt dup 1 lt { pop 1 } if setflat } def /Mb { q } def /Md { } def /MB { Q } def /nc 3 dict def nc begin /setgray { pop } bind def /setcmykcolor { 4 npop } bind def /setcustomcolor { 2 npop } bind def currentdict readonly pop end end setpacking %%EndResource %%EndProlog %%BeginSetup Adobe_level2_AI5 /initialize get exec Adobe_screens_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 AGM_Gradient /initializeAI get exec Adobe_ColorImage_AI6 /initialize get exec Adobe_Illustrator_AI5 /initialize get exec %%EndSetup 1 XR u [] 0 d 2.2500 w 0.000 0.000 0.000 1.000 K 1 J 1 j 4.3200 307.5600 m 457.9200 307.5600 L S U u 0.000 0.000 0.000 0.000 k 0.2500 w 0.000 0.000 0.000 1.000 K 188.5200 116.2800 m 188.7600 118.4400 L 189.4800 120.7200 L 190.6800 122.8800 L 192.2400 124.9200 L 194.2800 126.8400 L 196.6800 128.7600 L 199.4400 130.4400 L 202.6800 132.1200 L 206.0400 133.4400 L 209.8800 134.6400 L 213.8400 135.7200 L 217.9200 136.4400 L 222.2400 137.0400 L 226.6800 137.4000 L 231.1200 137.5200 L 235.5600 137.4000 L 239.8800 137.0400 L 244.2000 136.4400 L 248.4000 135.7200 L 252.3600 134.6400 L 256.0800 133.4400 L 259.5600 132.1200 L 262.6800 130.4400 L 265.4400 128.7600 L 267.9600 126.8400 L 269.8800 124.9200 L 271.5600 122.8800 L 272.6400 120.7200 L 273.3600 118.4400 L 273.6000 116.2800 L 273.3600 114.0000 L 272.6400 111.8400 L 271.5600 109.6800 L 269.8800 107.6400 L 267.9600 105.6000 L 265.4400 103.8000 L 262.6800 102.0000 L 259.5600 100.4400 L 256.0800 99.1200 L 252.3600 97.8000 L 248.4000 96.8400 L 244.2000 96.0000 L 239.8800 95.5200 L 235.5600 95.1600 L 231.1200 95.0400 L 226.6800 95.1600 L 222.2400 95.5200 L 217.9200 96.0000 L 213.8400 96.8400 L 209.8800 97.8000 L 206.0400 99.1200 L 202.6800 100.4400 L 199.4400 102.0000 L 196.6800 103.8000 L 194.2800 105.6000 L 192.2400 107.6400 L 190.6800 109.6800 L 189.4800 111.8400 L 188.7600 114.0000 L 188.5200 116.2800 L B U 0 To 1.0000 0.0000 0.0000 1.0000 203.7600 119.2800 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (agent_recv_\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 210.7200 107.2800 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0.000 0.000 0.000 1.000 k (message\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.000 k 0.2500 w 0.000 0.000 0.000 1.000 K 1 j 301.9200 158.7600 m 302.1600 161.0400 L 302.8800 163.2000 L 304.0800 165.3600 L 305.6400 167.4000 L 307.6800 169.4400 L 310.0800 171.2400 L 312.8400 173.0400 L 316.0800 174.6000 L 319.4400 176.0400 L 323.1600 177.2400 L 327.2400 178.2000 L 331.3200 179.0400 L 335.6400 179.5200 L 340.0800 179.8800 L 344.5200 180.0000 L 348.9600 179.8800 L 353.2800 179.5200 L 357.6000 179.0400 L 361.8000 178.2000 L 365.7600 177.2400 L 369.4800 176.0400 L 372.9600 174.6000 L 376.0800 173.0400 L 378.8400 171.2400 L 381.3600 169.4400 L 383.2800 167.4000 L 384.9600 165.3600 L 386.0400 163.2000 L 386.7600 161.0400 L 387.0000 158.7600 L 386.7600 156.6000 L 386.0400 154.3200 L 384.9600 152.1600 L 383.2800 150.1200 L 381.3600 148.2000 L 378.8400 146.2800 L 376.0800 144.6000 L 372.9600 143.0400 L 369.4800 141.6000 L 365.7600 140.4000 L 361.8000 139.3200 L 357.6000 138.6000 L 353.2800 138.0000 L 348.9600 137.6400 L 344.5200 137.5200 L 340.0800 137.6400 L 335.6400 138.0000 L 331.3200 138.6000 L 327.2400 139.3200 L 323.1600 140.4000 L 319.4400 141.6000 L 316.0800 143.0400 L 312.8400 144.6000 L 310.0800 146.2800 L 307.6800 148.2000 L 305.6400 150.1200 L 304.0800 152.1600 L 302.8800 154.3200 L 302.1600 156.6000 L 301.9200 158.7600 L B U 0 To 1.0000 0.0000 0.0000 1.0000 317.0400 161.7600 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (agent_recv_\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 327.8400 149.7600 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k (request\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.000 k 0.2500 w 0.000 0.000 0.000 1.000 K 1 j 75.2400 158.7600 m 75.3600 161.0400 L 76.0800 163.2000 L 77.2800 165.3600 L 78.8400 167.4000 L 80.8800 169.4400 L 83.2800 171.2400 L 86.1600 173.0400 L 89.2800 174.6000 L 92.7600 176.0400 L 96.4800 177.2400 L 100.4400 178.2000 L 104.5200 179.0400 L 108.8400 179.5200 L 113.2800 179.8800 L 117.7200 180.0000 L 122.1600 179.8800 L 126.6000 179.5200 L 130.8000 179.0400 L 135.0000 178.2000 L 138.9600 177.2400 L 142.6800 176.0400 L 146.1600 174.6000 L 149.2800 173.0400 L 152.1600 171.2400 L 154.5600 169.4400 L 156.6000 167.4000 L 158.1600 165.3600 L 159.2400 163.2000 L 159.9600 161.0400 L 160.2000 158.7600 L 159.9600 156.6000 L 159.2400 154.3200 L 158.1600 152.1600 L 156.6000 150.1200 L 154.5600 148.2000 L 152.1600 146.2800 L 149.2800 144.6000 L 146.1600 143.0400 L 142.6800 141.6000 L 138.9600 140.4000 L 135.0000 139.3200 L 130.8000 138.6000 L 126.6000 138.0000 L 122.1600 137.6400 L 117.7200 137.5200 L 113.2800 137.6400 L 108.8400 138.0000 L 104.5200 138.6000 L 100.4400 139.3200 L 96.4800 140.4000 L 92.7600 141.6000 L 89.2800 143.0400 L 86.1600 144.6000 L 83.2800 146.2800 L 80.8800 148.2000 L 78.8400 150.1200 L 77.2800 152.1600 L 76.0800 154.3200 L 75.3600 156.6000 L 75.2400 158.7600 L B U 0 To 1.0000 0.0000 0.0000 1.0000 90.3600 161.7600 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (agent_recv_\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 97.2000 149.7600 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k (response\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.2500 w 0.000 0.000 0.000 1.000 K 1 j 87.6000 173.7600 m 83.1600 180.3600 L 78.9600 187.2000 L 75.2400 194.1600 L 71.7600 201.3600 L 68.7600 208.6800 L 66.1200 216.2400 L 63.8400 223.8000 L 62.0400 231.6000 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 60.9600 236.7600 m 65.7600 230.5200 L 63.9600 230.8800 L 62.1600 230.7600 L 60.4800 230.1600 L 58.9200 229.2000 L 60.9600 236.7600 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 55.4400 206.8800 m 55.4400 181.4400 L 94.9200 181.4400 L 94.9200 206.8800 L 55.4400 206.8800 L F U 0 To 1.0000 0.0000 0.0000 1.0000 62.6400 197.1600 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (found\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 56.1600 185.1600 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k (outgoing\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.2500 w 0.000 0.000 0.000 1.000 K 1 j 273.6000 116.2800 m 283.4400 117.6000 L 293.0400 119.4000 L 302.7600 121.6800 L 312.2400 124.4400 L 321.6000 127.5600 L 330.7200 131.1600 L 339.7200 135.2400 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 344.5200 137.5200 m 336.7200 137.5200 L 338.0400 136.3200 L 339.0000 134.7600 L 339.6000 133.0800 L 339.7200 131.2800 L 344.5200 137.5200 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 291.2400 129.9600 m 291.2400 116.5200 L 325.9200 116.5200 L 325.9200 129.9600 L 291.2400 129.9600 L F U 0 To 1.0000 0.0000 0.0000 1.0000 291.9600 120.2400 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (request\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.2500 w 0.000 0.000 0.000 1.000 K 1 j 314.4000 173.7600 m 309.1200 176.0400 L 303.9600 178.2000 L 298.9200 180.4800 L 294.2400 182.6400 L 289.6800 184.9200 L 285.2400 187.3200 L 281.0400 189.6000 L 277.0800 192.0000 L 273.3600 194.4000 L 269.7600 196.8000 L 266.4000 199.2000 L 263.1600 201.7200 L 260.1600 204.2400 L 257.4000 206.7600 L 254.7600 209.2800 L 252.3600 211.9200 L 250.2000 214.4400 L 248.1600 217.0800 L 246.3600 219.8400 L 244.8000 222.4800 L 243.3600 225.2400 L 242.1600 228.0000 L 241.0800 230.7600 L 240.0000 234.2400 L 238.9200 237.9600 L 237.8400 241.6800 L 236.8800 245.5200 L 236.0400 249.3600 L 235.2000 253.4400 L 234.4800 257.4000 L 233.8800 261.6000 L 233.2800 265.8000 L 232.8000 270.1200 L 232.3200 274.4400 L 231.9600 278.8800 L 231.6000 283.4400 L 231.3600 288.0000 L 231.2400 292.6800 L 231.1200 297.4800 L 231.0000 302.2800 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 231.1200 307.5600 m 234.4800 300.6000 L 232.8000 301.2000 L 231.0000 301.4400 L 229.2000 301.3200 L 227.5200 300.7200 L 231.1200 307.5600 L F U u 2.2500 w 0.000 0.000 0.000 1.000 K 4.3200 52.4400 m 457.9200 52.4400 L S U 0.000 0.000 0.000 1.000 k 0.2500 w 0.000 0.000 0.000 1.000 K *u 241.6800 190.6800 m 220.4400 169.4400 L 241.6800 190.6800 L s u 220.4400 190.6800 m 241.6800 169.4400 L 220.4400 190.6800 L s U *U u 0.000 0.000 0.000 1.000 K 188.5200 116.2800 m 178.8000 117.6000 L 169.0800 119.4000 L 159.4800 121.6800 L 150.0000 124.4400 L 140.6400 127.5600 L 131.4000 131.1600 L 122.4000 135.2400 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 117.7200 137.5200 m 125.5200 137.5200 L 124.2000 136.3200 L 123.2400 134.7600 L 122.6400 133.0800 L 122.4000 131.2800 L 117.7200 137.5200 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 132.3600 129.9600 m 132.3600 116.5200 L 174.8400 116.5200 L 174.8400 129.9600 L 132.3600 129.9600 L F U 0 To 1.0000 0.0000 0.0000 1.0000 133.0800 120.2400 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (response\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.2500 w 0.000 0.000 0.000 1.000 K 1 j 231.1200 137.5200 m 231.1200 174.7200 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 231.1200 180.0000 m 234.6000 173.0400 L 232.9200 173.6400 L 231.1200 173.8800 L 229.3200 173.6400 L 227.6400 173.0400 L 231.1200 180.0000 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 212.1600 158.4000 m 212.1600 144.9600 L 250.0800 144.9600 L 250.0800 158.4000 L 212.1600 158.4000 L F U 0 To 1.0000 0.0000 0.0000 1.0000 212.8800 148.6800 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (garbage\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.000 k 0.2500 w 0.000 0.000 0.000 1.000 K 1 j 259.4400 258.0000 m 259.6800 260.1600 L 260.4000 262.4400 L 261.4800 264.6000 L 263.1600 266.6400 L 265.0800 268.6800 L 267.6000 270.4800 L 270.3600 272.1600 L 273.4800 273.8400 L 276.9600 275.1600 L 280.6800 276.3600 L 284.6400 277.4400 L 288.8400 278.1600 L 293.1600 278.7600 L 297.4800 279.1200 L 301.9200 279.2400 L 306.3600 279.1200 L 310.8000 278.7600 L 315.1200 278.1600 L 319.2000 277.4400 L 323.1600 276.3600 L 327.0000 275.1600 L 330.3600 273.8400 L 333.6000 272.1600 L 336.3600 270.4800 L 338.7600 268.6800 L 340.8000 266.6400 L 342.3600 264.6000 L 343.5600 262.4400 L 344.2800 260.1600 L 344.5200 258.0000 L 344.2800 255.7200 L 343.5600 253.5600 L 342.3600 251.4000 L 340.8000 249.3600 L 338.7600 247.3200 L 336.3600 245.5200 L 333.6000 243.7200 L 330.3600 242.1600 L 327.0000 240.8400 L 323.1600 239.6400 L 319.2000 238.5600 L 315.1200 237.7200 L 310.8000 237.2400 L 306.3600 236.8800 L 301.9200 236.7600 L 297.4800 236.8800 L 293.1600 237.2400 L 288.8400 237.7200 L 284.6400 238.5600 L 280.6800 239.6400 L 276.9600 240.8400 L 273.4800 242.1600 L 270.3600 243.7200 L 267.6000 245.5200 L 265.0800 247.3200 L 263.1600 249.3600 L 261.4800 251.4000 L 260.4000 253.5600 L 259.6800 255.7200 L 259.4400 258.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 283.2000 255.0000 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (leg_recv\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.000 k 0.2500 w 0.000 0.000 0.000 1.000 K 1 j 358.6800 258.0000 m 358.9200 260.1600 L 359.5200 262.4400 L 360.7200 264.6000 L 362.2800 266.6400 L 364.3200 268.6800 L 366.7200 270.4800 L 369.6000 272.1600 L 372.7200 273.8400 L 376.2000 275.1600 L 379.9200 276.3600 L 383.8800 277.4400 L 388.0800 278.1600 L 392.2800 278.7600 L 396.7200 279.1200 L 401.1600 279.2400 L 405.6000 279.1200 L 410.0400 278.7600 L 414.3600 278.1600 L 418.4400 277.4400 L 422.4000 276.3600 L 426.1200 275.1600 L 429.6000 273.8400 L 432.7200 272.1600 L 435.6000 270.4800 L 438.0000 268.6800 L 440.0400 266.6400 L 441.6000 264.6000 L 442.8000 262.4400 L 443.4000 260.1600 L 443.6400 258.0000 L 443.4000 255.7200 L 442.8000 253.5600 L 441.6000 251.4000 L 440.0400 249.3600 L 438.0000 247.3200 L 435.6000 245.5200 L 432.7200 243.7200 L 429.6000 242.1600 L 426.1200 240.8400 L 422.4000 239.6400 L 418.4400 238.5600 L 414.3600 237.7200 L 410.0400 237.2400 L 405.6000 236.8800 L 401.1600 236.7600 L 396.7200 236.8800 L 392.2800 237.2400 L 388.0800 237.7200 L 383.8800 238.5600 L 379.9200 239.6400 L 376.2000 240.8400 L 372.7200 242.1600 L 369.6000 243.7200 L 366.7200 245.5200 L 364.3200 247.3200 L 362.2800 249.3600 L 360.7200 251.4000 L 359.5200 253.5600 L 358.9200 255.7200 L 358.6800 258.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 369.0000 255.0000 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (incoming_recv\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.000 k 0.2500 w 0.000 0.000 0.000 1.000 K 1 j 18.4800 258.0000 m 18.7200 260.1600 L 19.4400 262.4400 L 20.5200 264.6000 L 22.2000 266.6400 L 24.2400 268.6800 L 26.6400 270.4800 L 29.4000 272.1600 L 32.5200 273.8400 L 36.0000 275.1600 L 39.7200 276.3600 L 43.6800 277.4400 L 47.8800 278.1600 L 52.2000 278.7600 L 56.5200 279.1200 L 60.9600 279.2400 L 65.4000 279.1200 L 69.8400 278.7600 L 74.1600 278.1600 L 78.3600 277.4400 L 82.3200 276.3600 L 86.0400 275.1600 L 89.5200 273.8400 L 92.6400 272.1600 L 95.4000 270.4800 L 97.8000 268.6800 L 99.8400 266.6400 L 101.4000 264.6000 L 102.6000 262.4400 L 103.3200 260.1600 L 103.5600 258.0000 L 103.3200 255.7200 L 102.6000 253.5600 L 101.4000 251.4000 L 99.8400 249.3600 L 97.8000 247.3200 L 95.4000 245.5200 L 92.6400 243.7200 L 89.5200 242.1600 L 86.0400 240.8400 L 82.3200 239.6400 L 78.3600 238.5600 L 74.1600 237.7200 L 69.8400 237.2400 L 65.4000 236.8800 L 60.9600 236.7600 L 56.5200 236.8800 L 52.2000 237.2400 L 47.8800 237.7200 L 43.6800 238.5600 L 39.7200 239.6400 L 36.0000 240.8400 L 32.5200 242.1600 L 29.4000 243.7200 L 26.6400 245.5200 L 24.2400 247.3200 L 22.2000 249.3600 L 20.5200 251.4000 L 19.4400 253.5600 L 18.7200 255.7200 L 18.4800 258.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 29.7600 255.0000 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (outgoing_recv\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.2500 w 0.000 0.000 0.000 1.000 K 1 j 344.5200 180.0000 m 339.0000 183.8400 L 333.7200 188.0400 L 328.6800 192.4800 L 324.0000 197.2800 L 319.6800 202.4400 L 315.7200 207.8400 L 312.1200 213.4800 L 308.8800 219.3600 L 306.0000 225.4800 L 303.6000 231.7200 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 301.9200 236.7600 m 307.4400 231.1200 L 305.6400 231.2400 L 303.8400 230.8800 L 302.1600 230.1600 L 300.7200 229.0800 L 301.9200 236.7600 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 300.6000 206.6400 m 300.6000 193.2000 L 342.9600 193.2000 L 342.9600 206.6400 L 300.6000 206.6400 L F U 0 To 1.0000 0.0000 0.0000 1.0000 301.3200 196.9200 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (found leg\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.2500 w 0.000 0.000 0.000 1.000 K 1 j 147.7200 173.7600 m 153.1200 176.0400 L 158.2800 178.2000 L 163.2000 180.4800 L 168.0000 182.6400 L 172.5600 184.9200 L 176.8800 187.3200 L 181.0800 189.6000 L 185.0400 192.0000 L 188.8800 194.4000 L 192.3600 196.8000 L 195.8400 199.2000 L 198.9600 201.7200 L 201.9600 204.2400 L 204.7200 206.7600 L 207.3600 209.2800 L 209.7600 211.9200 L 212.0400 214.4400 L 213.9600 217.0800 L 215.7600 219.8400 L 217.4400 222.4800 L 218.8800 225.2400 L 220.0800 228.0000 L 221.0400 230.7600 L 222.2400 234.2400 L 223.3200 237.9600 L 224.2800 241.6800 L 225.2400 245.5200 L 226.0800 249.3600 L 226.9200 253.4400 L 227.6400 257.4000 L 228.3600 261.6000 L 228.9600 265.8000 L 229.4400 270.1200 L 229.9200 274.4400 L 230.2800 278.8800 L 230.6400 283.4400 L 230.8800 288.0000 L 231.0000 292.6800 L 231.1200 297.4800 L 231.1200 302.2800 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 231.1200 307.5600 m 227.6400 300.6000 L 229.3200 301.2000 L 231.1200 301.4400 L 232.9200 301.3200 L 234.6000 300.7200 L 231.1200 307.5600 L F U u 0.2500 w 0.000 0.000 0.000 1.000 K 374.5200 173.7600 m 378.8400 177.2400 L 382.8000 181.0800 L 386.5200 185.2800 L 389.7600 189.7200 L 392.7600 194.4000 L 395.2800 199.3200 L 397.4400 204.3600 L 399.1200 209.6400 L 400.4400 215.0400 L 401.2800 220.4400 L 401.6400 225.9600 L 401.6400 231.4800 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 401.1600 236.7600 m 398.2800 229.4400 L 399.9600 230.2800 L 401.7600 230.6400 L 403.5600 230.5200 L 405.2400 230.1600 L 401.1600 236.7600 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 372.0000 206.8800 m 372.0000 181.4400 L 413.4000 181.4400 L 413.4000 206.8800 L 372.0000 206.8800 L F U 0 To 1.0000 0.0000 0.0000 1.0000 380.1600 197.1600 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (found\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 372.7200 185.1600 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k (incoming\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.2500 w 0.000 0.000 0.000 1.000 K 1 j 231.1200 24.1200 m 231.1200 47.1600 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 231.1200 52.4400 m 234.6000 45.4800 L 232.9200 46.0800 L 231.1200 46.3200 L 229.3200 46.0800 L 227.6400 45.4800 L 231.1200 52.4400 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 190.5600 16.6800 m 190.5600 3.2400 L 271.6800 3.2400 L 271.6800 16.6800 L 190.5600 16.6800 L F U 0 To 1.0000 0.0000 0.0000 1.0000 191.2800 6.9600 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (msg_stream_recv\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.2500 w 0.000 0.000 0.000 1.000 K 1 j 301.9200 279.2400 m 301.9200 302.2800 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 301.9200 307.5600 m 305.4000 300.6000 L 303.7200 301.2000 L 301.9200 301.4400 L 300.1200 301.2000 L 298.4400 300.6000 L 301.9200 307.5600 L F U u 0.2500 w 0.000 0.000 0.000 1.000 K 401.1600 279.2400 m 401.1600 302.2800 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 401.1600 307.5600 m 404.6400 300.6000 L 402.9600 301.2000 L 401.1600 301.4400 L 399.3600 301.2000 L 397.6800 300.6000 L 401.1600 307.5600 L F U u 0.2500 w 0.000 0.000 0.000 1.000 K 60.9600 279.2400 m 60.9600 302.2800 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 60.9600 307.5600 m 64.4400 300.6000 L 62.7600 301.2000 L 60.9600 301.4400 L 59.2800 301.2000 L 57.4800 300.6000 L 60.9600 307.5600 L F U 0.000 0.000 0.000 1.000 k 0.2500 w 0.000 0.000 0.000 1.000 K *u 231.1200 314.6400 m 231.1200 336.0000 L 231.1200 314.6400 L s u 231.1200 307.5600 m 232.3200 307.8000 L 233.4000 308.4000 L 234.1200 309.3600 L 234.6000 310.5600 L 234.6000 311.7600 L 234.1200 312.9600 L 233.4000 313.8000 L 232.3200 314.5200 L 231.1200 314.6400 L 229.9200 314.5200 L 228.8400 313.8000 L 228.0000 312.9600 L 227.6400 311.7600 L 227.6400 310.5600 L 228.0000 309.3600 L 228.8400 308.4000 L 229.9200 307.8000 L 231.1200 307.5600 L 231.1200 307.5600 L s U *U 0 To 1.0000 0.0000 0.0000 1.0000 196.9200 347.1600 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (nta_message_f\r) Tx TO 0.000 0.000 0.000 1.000 K 0.000 0.000 0.000 1.000 k 0.2500 w 0.000 0.000 0.000 1.000 K 1 j *u 301.9200 314.6400 m 301.9200 336.0000 L 301.9200 314.6400 L s u 301.9200 307.5600 m 303.1200 307.8000 L 304.2000 308.4000 L 305.0400 309.3600 L 305.4000 310.5600 L 305.4000 311.7600 L 305.0400 312.9600 L 304.2000 313.8000 L 303.1200 314.5200 L 301.9200 314.6400 L 300.7200 314.5200 L 299.6400 313.8000 L 298.9200 312.9600 L 298.4400 311.7600 L 298.4400 310.5600 L 298.9200 309.3600 L 299.6400 308.4000 L 300.7200 307.8000 L 301.9200 307.5600 L 301.9200 307.5600 L s U *U 0 To 1.0000 0.0000 0.0000 1.0000 271.4400 347.1600 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (nta_request_f\r) Tx TO 0.000 0.000 0.000 1.000 K 0.000 0.000 0.000 1.000 k 0.2500 w 0.000 0.000 0.000 1.000 K 1 j *u 60.9600 314.6400 m 60.9600 336.0000 L 60.9600 314.6400 L s u 60.9600 307.5600 m 62.2800 307.8000 L 63.2400 308.4000 L 64.0800 309.3600 L 64.5600 310.5600 L 64.5600 311.7600 L 64.0800 312.9600 L 63.2400 313.8000 L 62.2800 314.5200 L 60.9600 314.6400 L 59.7600 314.5200 L 58.6800 313.8000 L 57.9600 312.9600 L 57.4800 311.7600 L 57.4800 310.5600 L 57.9600 309.3600 L 58.6800 308.4000 L 59.7600 307.8000 L 60.9600 307.5600 L 60.9600 307.5600 L s U *U 0 To 1.0000 0.0000 0.0000 1.0000 26.6400 347.1600 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (nta_response_f\r) Tx TO 0.000 0.000 0.000 1.000 K 0.000 0.000 0.000 1.000 k 0.2500 w 0.000 0.000 0.000 1.000 K 1 j *u 401.1600 314.6400 m 401.1600 336.0000 L 401.1600 314.6400 L s u 401.1600 307.5600 m 402.3600 307.8000 L 403.4400 308.4000 L 404.2800 309.3600 L 404.6400 310.5600 L 404.6400 311.7600 L 404.2800 312.9600 L 403.4400 313.8000 L 402.3600 314.5200 L 401.1600 314.6400 L 399.9600 314.5200 L 398.8800 313.8000 L 398.1600 312.9600 L 397.6800 311.7600 L 397.6800 310.5600 L 398.1600 309.3600 L 398.8800 308.4000 L 399.9600 307.8000 L 401.1600 307.5600 L 401.1600 307.5600 L s U *U 0 To 1.0000 0.0000 0.0000 1.0000 362.2800 347.1600 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (nta_ack_cancel_f\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.2500 w 0.000 0.000 0.000 1.000 K 1 j 30.9600 243.0000 m 29.8800 238.8000 L 28.9200 234.6000 L 27.9600 230.4000 L 27.1200 226.3200 L 26.5200 222.2400 L 25.9200 218.1600 L 25.4400 214.0800 L 24.9600 210.0000 L 24.7200 205.9200 L 24.4800 201.8400 L 24.3600 197.8800 L 24.3600 193.9200 L 24.4800 189.9600 L 24.7200 186.0000 L 24.9600 182.0400 L 25.3200 178.0800 L 25.8000 174.2400 L 26.4000 170.2800 L 27.1200 166.4400 L 27.8400 162.6000 L 28.8000 158.7600 L 29.7600 154.9200 L 31.2000 149.5200 L 32.7600 143.8800 L 34.4400 138.1200 L 36.1200 132.2400 L 37.9200 126.2400 L 39.7200 120.0000 L 41.6400 113.7600 L 43.5600 107.1600 L 45.6000 100.5600 L 47.7600 93.7200 L 49.9200 86.7600 L 52.2000 79.6800 L 54.4800 72.4800 L 56.8800 65.0400 L 59.4000 57.4800 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 60.9600 52.4400 m 55.5600 57.9600 L 57.3600 57.9600 L 59.1600 58.3200 L 60.7200 59.0400 L 62.1600 60.1200 L 60.9600 52.4400 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 22.9200 160.4400 m 22.9200 135.0000 L 68.8800 135.0000 L 68.8800 160.4400 L 22.9200 160.4400 L F U 0 To 1.0000 0.0000 0.0000 1.0000 23.6400 150.7200 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (retransmit\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 34.3200 138.7200 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k ( ACK\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.2500 w 0.000 0.000 0.000 1.000 K 1 j 431.2800 243.0000 m 432.3600 238.8000 L 433.3200 234.6000 L 434.1600 230.4000 L 435.0000 226.3200 L 435.7200 222.2400 L 436.3200 218.1600 L 436.8000 214.0800 L 437.1600 210.0000 L 437.5200 205.9200 L 437.7600 201.8400 L 437.7600 197.8800 L 437.7600 193.9200 L 437.7600 189.9600 L 437.5200 186.0000 L 437.2800 182.0400 L 436.8000 178.0800 L 436.3200 174.2400 L 435.7200 170.2800 L 435.1200 166.4400 L 434.2800 162.6000 L 433.4400 158.7600 L 432.3600 154.9200 L 430.9200 149.5200 L 429.3600 143.8800 L 427.8000 138.1200 L 426.0000 132.2400 L 424.3200 126.2400 L 422.4000 120.0000 L 420.6000 113.7600 L 418.5600 107.1600 L 416.5200 100.5600 L 414.4800 93.7200 L 412.2000 86.7600 L 410.0400 79.6800 L 407.6400 72.4800 L 405.2400 65.0400 L 402.8400 57.4800 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 401.1600 52.4400 m 406.6800 57.9600 L 404.8800 57.9600 L 403.0800 58.3200 L 401.4000 59.0400 L 400.0800 60.1200 L 401.1600 52.4400 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 393.2400 160.4400 m 393.2400 135.0000 L 439.2000 135.0000 L 439.2000 160.4400 L 393.2400 160.4400 L F U 0 To 1.0000 0.0000 0.0000 1.0000 393.9600 150.7200 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (retransmit\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 395.6400 138.7200 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k (response\r) Tx TO 0.000 0.000 0.000 1.000 K 0.000 0.000 0.000 1.000 k 0.2500 w 0.000 0.000 0.000 1.000 K 1 j *u 60.9600 45.3600 m 60.9600 24.1200 L 60.9600 45.3600 L s u 60.9600 52.4400 m 62.2800 52.3200 L 63.2400 51.6000 L 64.0800 50.7600 L 64.5600 49.5600 L 64.5600 48.3600 L 64.0800 47.1600 L 63.2400 46.2000 L 62.2800 45.6000 L 60.9600 45.3600 L 59.7600 45.6000 L 58.6800 46.2000 L 57.9600 47.1600 L 57.4800 48.3600 L 57.4800 49.5600 L 57.9600 50.7600 L 58.6800 51.6000 L 59.7600 52.3200 L 60.9600 52.4400 L 60.9600 52.4400 L s U *U 0 To 1.0000 0.0000 0.0000 1.0000 19.8000 6.9600 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (msg_stream_send\r) Tx TO 0.000 0.000 0.000 1.000 K 0.000 0.000 0.000 1.000 k 0.2500 w 0.000 0.000 0.000 1.000 K 1 j *u 401.1600 45.3600 m 401.1600 24.1200 L 401.1600 45.3600 L s u 401.1600 52.4400 m 402.3600 52.3200 L 403.4400 51.6000 L 404.2800 50.7600 L 404.6400 49.5600 L 404.6400 48.3600 L 404.2800 47.1600 L 403.4400 46.2000 L 402.3600 45.6000 L 401.1600 45.3600 L 399.9600 45.6000 L 398.8800 46.2000 L 398.1600 47.1600 L 397.6800 48.3600 L 397.6800 49.5600 L 398.1600 50.7600 L 398.8800 51.6000 L 399.9600 52.3200 L 401.1600 52.4400 L 401.1600 52.4400 L s U *U 0 To 1.0000 0.0000 0.0000 1.0000 359.8800 6.9600 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (msg_stream_send\r) Tx TO 0.000 0.000 0.000 1.000 K 0.000 0.000 0.000 1.000 k 0.2500 w 0.000 0.000 0.000 1.000 K 1 j *u 231.1200 59.5200 m 231.1200 80.8800 L 231.1200 59.5200 L s u 231.1200 52.4400 m 232.3200 52.6800 L 233.4000 53.2800 L 234.1200 54.2400 L 234.6000 55.4400 L 234.6000 56.6400 L 234.1200 57.8400 L 233.4000 58.6800 L 232.3200 59.4000 L 231.1200 59.5200 L 229.9200 59.4000 L 228.8400 58.6800 L 228.0000 57.8400 L 227.6400 56.6400 L 227.6400 55.4400 L 228.0000 54.2400 L 228.8400 53.2800 L 229.9200 52.6800 L 231.1200 52.4400 L 231.1200 52.4400 L s U *U u 0.000 0.000 0.000 0.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 208.6800 79.0800 m 208.6800 65.6400 L 253.5600 65.6400 L 253.5600 79.0800 L 208.6800 79.0800 L F U 0 To 1.0000 0.0000 0.0000 1.0000 209.4000 69.3600 0 Tp TP /_Helvetica 10.0000 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (mac_recv\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.2500 w 0.000 0.000 0.000 1.000 K 1 j 231.1200 80.8800 m 231.1200 89.7600 L S U u 0.000 0.000 0.000 1.000 k 0.0000 w 0.000 0.000 0.000 1.000 K 231.1200 95.0400 m 234.6000 88.0800 L 232.9200 88.6800 L 231.1200 88.9200 L 229.3200 88.6800 L 227.6400 88.0800 L 231.1200 95.0400 L F U %%PageTrailer gsave annotatepage grestore showpage %%Trailer Adobe_Illustrator_AI5 /terminate get exec Adobe_ColorImage_AI6 /terminate get exec AGM_Gradient /terminate get exec Adobe_screens_AI5 /terminate get exec Adobe_level2_AI5 /terminate get exec Adobe_cshow /terminate get exec %%EOF II* h`` * S ?P8$ BaPd6DbQ8VA_㰇%B_p)<H S(a$J%RɌ 4@Їэ1/1c?zŭz1ùG'{<;?akrenn3u;3o nŭͯkyu~vvR[ﳶ-oBo-oۣhwn588g`|}{vw ;-́~R 0ѝ#P}h;F3l԰;nlTOlbОq}v3C Y갥Z93®eN/x\H]ȉ\vWz#x{"XU5kԖta7Z}!]%W_Vxc67Z?d6NG^VOe6Wbd2(\؇AL 8@~'~(yy W0r|hqgG| dІruBoh^ۥ}S"}S gIs5=>MO6]o]׀O/r!:#L=g"9CDž[猄hi_>@!:&yg3W<"G.!yL(۳'!{ !ئŕb!8 +Ug!.?vAO, nH= |"}B]t+xTEac,~4Öit=H|Y*8qL1ݧGBymBU0}Hh!qbAc$50#E"G$qyZSY[+<#RM*HC nB 1ռu!Rԁ@A\nZghB&4[mv. q)z8ȘD$ElH;n!6倱TDz9Aӂky<) &(B^y6XB h \*Gi¢|RUC Z\?%[IO M81ZS*D~֖. AIʎB$A$$0"S<q%Zb%Q֩Y3%)7bn5n'}<8i,66-_* l̐d}&07Yr fP05VQ)lzڴ f p53݋ooH#`-R"\scXv=QT> \;ҳVΛ\c ~M˶A^[5y^o~ v?x0xܻ&UҥZ`Z$Ь["XVIօOPP |&H u *<̽UA2S(JAKkZR:*B3X jXAUXS3|^_TĆ*u&33ys*9CAyo3z H.S SIHNgEs+'Q b4]ӉeBTԋl2HdrA(=cC&  ?n{ ipB7j]X|3P~;Un,G9ًBX1ɇ;l5ƶNeNJAdMdGA.4x#Y5>?b">WϒP ^-ojoB(C$m*>FO.8P< 07O ZbEXFńd@!ps("L\* }Wװ1 o"$mҨP*BL΂pMRPpPd p.Px$[|ƪ^dlS 'O a/@b`:K @nva+" 8=7फ़gR`@d9>4Qd")$8 8`> m CR Q@bqv$ <aqLM'X!.-TZp"ڂh/j!~\ Dmg#0_21 輣 O… $rX  k&-XA*`&DZ6ɟeN#q$j1 LiBM6+ҥ8VʸrΪ=Ҽ!$2 ,i )R)*/ҳA''gkBJHK.Ю/͆sL$!|&ҥ m7V2w"h  !rI#5B#B8!HMy:  = 06F.zk7,NhJh!NV* ?O `  bw H; RjÃQ~E)oy,3H}EL ߜIGjx}j}&?( .?,1۝>RA e!yMm<1ZwC|-S( AeM_"s)j@RYrMQ?igkpoi^${;.>⽩K7 x0c,%.G' c1m P 㱚lnr ;@7x^#(`7tc!,{K}Ƨ| c4s{/No3ܘntf\lCΩc0Kf'#>t?NBk 3ʠ3)VTG@ ~|! y^ժ$>U =p *֕WEuW +0X1ISm5+#4cfQn2[MHCclͺ`&X0Pn%lv:]oxs\7}rQ v}T7y3Pl7VqƉx RҸwo;3t~@HH{-W? q#d]k??G{9F@b{C]GM+.1=و:ƭY-KAbi);@i@=PHweZ)(faښMwEhE'!$R >.BtЃ-%[˜HDZ%@?(|m sEbj@|nA"QiZR L_ⲓN*,?(h<%`Z,%{/e@L(WS"A, bZzGI%"BT"ԬtMR쨜*2`D jnd3 52s&tK'}5K%y@H4|j?e=H5 XehQ+ެy ʓɑI/ kwMK1FQ*th2@kݥ{O_BԿ//\a RI|n祖'P\!͚~p",Q.p@PD5 9yl p`p_CS'opfװPܐ{mqPЋ00uspY S pi P 0  Nq '  0p0pƾD\(7 \!kA~! a `^ZXbCӪ]˶۷pʝKݻx˷߿;LOÇ 1Zǐ# 1嶖/7ά3^ΚA{&)z_Q^7j\]^;_ޭ6m¾n[k#_qʙt.]^G=;V_ѷVϞboй79?.dXYr%Y9 =QX ~a7(Q|"bzv_x"Qo߽[u..]:iG ?1DАVeZWZe*e7Gfm%ufoFy_gә6'eA)e{Ix@&꘠b]pM)] is TYI6jMJլ_-Jiҝjm էZ%lUuaǒUĎl,'];" gEנl+)y+R+ko(o7}zcg؉\ƕZ|ڴfl,)obr2\k-첵FJB\Ǖm<ڼiHkhֆ_OW{1nf=SR9jD250h]82nh ZVX%b` g4EpL WhA|ISD]l\#4qzcIZXUp#H̐).=al%ŖЋA!Sh%rz,L׈ύ[DFgn#hz] ةAji|ݔ `8e$M3sA+R+*,cX6NiP]i-[d}Br ç&md|5>(S214kegNr]jY1$~ۆfsdsL:Mߵ@y׋lRku=lD/ٓ4'7ax紲C%X͒9H>noڳ=\gMU!68{ gjQJۧS`ʓL:ۭZiX@pKtDxm+l]y]_~*3h܇$=OguS6WχJ(nxhma6bV{fWg*%LbS'd(_Se7Gj,'^QwuR5erqr}P0WQEH?c2Qly4V"VUX-bKQ`6`RdfwUKKBSX|Ԃ]₆p~sv}SkȇQxhFq,E~Ֆ?g\\cujxTp8f2Un 3v'('6eVi[5hy͇mDoԊ}0݆mXUHBf\XuG`}RG.Rz"8"ƒ:1_+.+Xi;(؀c\eA5;耛7o(UxRRljv{+GI&kwa"hwa~&oﴀ *nwMrwzYe7VQZZx+BV}җ|s|8Hj~T)|hԘmL 2ԲUC%?!'ק|ø[Tn33H}87eecNJio&)u|2rڇ}U)XrynjaNUGuyHw9%7sMSlDvtuԎŚ)6v告\{6OGI'vXYQoIw)h8ȉzzٙ2c配C{Dc)^)%Cusd^Zׅ;H*(HafhÈH\Yy?Fؖ[նDƥI(ude;:$kZV5zR*qKFwxz|ڧ~:sz6E}CtJ`wqYgqn7Zhzajqکc?Lzڪ'Y{iXMYf_YHmVtmꄑWX&g7)cU5BjI E Jl #ɗUllD[uڮ:vvمfDB j)19h9mwG&{9ڟj*,63 ;dKx'd뺒 ^}mj|" $;{ZN5+!@VF:U;ӄʰ=HOe3ٕ\ k|oC*cFE[Y_)Pkv"D$uʶLIu[T-w|۷~;[{BMKʀv-* W{+빧F ˺;`Iu;X+ ǹk˻^yrk{{9m#u[/x+eEke+ǐ?<{kV[(:[{蛾껾E;[Tw~ǥu:vÛ Kn ( 6 lG뺧 *jI+J2Juv ̼{-\/<&Lökv3<Lg*<),'ĤFw u\|@I5cK|7!1xĮť.`Bƨ4N62EX8SٓxrLR$Hȯy頁\W%{~j.JBi@L|͙E9@L ʥ|׫ʡL)z܆ѺlSܩSj!+rhH9YAiH|/*8ZS5cp <~֌c,j5匫/ CxZT,ZM!T|xhh)ռȴd˶֭By6zP Ш7g*eԒ}Yx)=9ݑ3΄ɦl԰:k* Uu==j=y3H"b,8r)֜BF$jM o۹$f̄t}6!b/n 8AУM@"i:V~UXtX|Y쎸Y=\kWYλvJsFǧ=};lƖۀHG 07 E-˱[(zܻ _H+|č"y ڍClb-mjȷӭ9X=]m{Tm% 1mlwN >|2cߡ ԟF|nY75 =kֳJ&.cމLi{M=P&JBLN>n⓸WYQS;ȞPTJ$oY p :X0B_MfB "~::~<x~^y+#(>JF0u5ZNk^~]NʔnU.On{]U}Uxތsbn*0}~bp<>Ǯx/nԄ> SGmY)V{A~~i7Yʂ/*>݈-.Wx]X]ڪ.o> &'z4,~H-՝.$?,Pm-;O u\-*רl^h2kF܌z;s3n-YbnWt T6|?)f+M&xLy n}_-Ε̣4Dݻ.|G۵v/5\U@}6N,7^߲fr :59̤}H0Xm״ MU9\o}4@V^A_1D,va͍)Ͱٝ 8`A.dC%NaE hQ B  bF'QdK1e$9J3kɲI&k(ΞIS"Uji̝ONZU*SY#bdί]6:kYif)٫hz;ݹQ6ջ/^jTߖbK#OI!S绛9^)2&2!e&Z[ϸa t߉}Zp3~qOotұ+냬:yͲCTzT^PnKpc0AB0䩻 5th>:(PP/l1/qq)ꑹ!HАD,B#j'"dް?-GC-Lr W8$.,S,1}Ln(Ӕ$s=SNl tP̳ Ҏ PhAEUR(|85905Q SE}HFOTM U0<-Ies5KCBm X6YMakOZ\VH\)ken˿ov+uu/\/Dq7Axsw}ݗ*€X{ >8[s;؇#Rew`-޴TF9DɝV36dLِ^4eQraelNu92&G9O&>PW醝ޙdҰ%A=kmlS' |>tm6(^Z;FJ_|\j% ]ˏ9s_a?vU: oi{zɷ7Bъwg~%%}߇?ǟet-g@ q D%Ap1|BAaP_Ѳ}0AihWB"C#BñpkNXCoo;a}C QC$bxD$&QKdbD(*vQbxE,fQ[b--8!Ȍ:=)Ѝu>Mqv# Sofia-SIP @VERSION@ - Copyright (C) 2006 Nokia Corporation. All rights reserved. Licensed under the terms of the GNU Lesser General Public License. sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/features/000077500000000000000000000000001223300710500213705ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/features/ChangeLog000066400000000000000000000024701223300710500231450ustar00rootroot000000000000002005-10-27 Pekka Pessi * Fixed features. Added libfeatures.la into .so. Renamed sofia_has_* as sofia_sip_has_*. Using features in nua_cli.c M ./libsofia-sip-ua/Makefile.am +1 M ./libsofia-sip-ua/features/Makefile.am -2 +2 M ./libsofia-sip-ua/features/sofia_sip_features.c -14 +14 M ./libsofia-sip-ua/features/sofia_sip_features.docs -10 +10 M ./libsofia-sip-ua/features/sofia_sip_features.h.in -10 +10 M ./libsofia-sip-ua/stun/stun.c -2 +2 M ./utils/Makefile.am -1 +2 M ./utils/nua_cli.c -2 +29 * Added "features" module. ./libsofia-sip-ua/nua/sofia_config.c -> ./libsofia-sip-ua/sofia/sofia_sip_features.c ./libsofia-sip-ua/nua/sofia_config.h.in -> ./libsofia-sip-ua/sofia/sofia_sip_features.h.in ./libsofia-sip-ua/sofia -> ./libsofia-sip-ua/features M ./configure.ac -2 +3 M ./libsofia-sip-ua/Makefile.am -1 +1 A ./libsofia-sip-ua/features/Doxyfile A ./libsofia-sip-ua/features/Makefile.am M ./libsofia-sip-ua/features/sofia_sip_features.c -21 +78 A ./libsofia-sip-ua/features/sofia_sip_features.docs M ./libsofia-sip-ua/features/sofia_sip_features.h.in -15 +20 M ./libsofia-sip-ua/nua/Makefile.am -4 +3 A ./libsofia-sip-ua/sofia/ M ./libsofia-sip-ua/stun/stun.c -1 +6 M ./libsofia-sip-ua/stun/stun.h +2 sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/features/Doxyfile.in000066400000000000000000000015521223300710500235060ustar00rootroot00000000000000PROJECT_NAME = "features" OUTPUT_DIRECTORY = ../docs/html/features INPUT = @srcdir@/features.docs @srcdir@/sofia-sip sofia-sip @srcdir@ . @INCLUDE_PATH = . @srcdir@ @INCLUDE = ../docs/Doxyfile.conf TAGFILES += ../docs/docs.doxytags=.. TAGFILES += ../docs/su.doxytags=../su TAGFILES += ../docs/ipt.doxytags=../ipt TAGFILES += ../docs/bnf.doxytags=../bnf TAGFILES += ../docs/url.doxytags=../url TAGFILES += ../docs/msg.doxytags=../msg TAGFILES += ../docs/sip.doxytags=../sip TAGFILES += ../docs/sresolv.doxytags=../sresolv TAGFILES += ../docs/tport.doxytags=../tport TAGFILES += ../docs/nta.doxytags=../nta TAGFILES += ../docs/sdp.doxytags=../sdp GENERATE_TAGFILE = ../docs/features.doxytags ALIASES += sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/features/Makefile.am000066400000000000000000000017031223300710500234250ustar00rootroot00000000000000# # Makefile.am for sofia features module # # Copyright (C) 2005,2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # ---------------------------------------------------------------------- # Header paths INCLUDES = $(INTERNAL_INCLUDES) # ---------------------------------------------------------------------- # Build targets noinst_LTLIBRARIES = libfeatures.la # ---------------------------------------------------------------------- # Rules for building the targets # This is used by platforms not supporting autoconf nobase_include_sofia_HEADERS = sofia-sip/sofia_features.h libfeatures_la_SOURCES = features.c # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST = features.docs # ---------------------------------------------------------------------- # Sofia specific rules LDADD = include $(top_srcdir)/rules/sofia.am sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/features/Makefile.in000066400000000000000000000767111223300710500234510ustar00rootroot00000000000000# Makefile.in generated by automake 1.14 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 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 sofia features module # # Copyright (C) 2005,2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # ---------------------------------------------------------------------- # Header paths # common Makefile targets for libsofia-sip-ua(-glib) modules # ---------------------------------------------------------- # # run tests with valgrind # # Copyright (C) 2007 Nokia Corporation. # 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 file contains free software from Makefile.in by the Free Software # Foundation: # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 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. # # Generate lcov output # # # Copyright (C) 2007 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # # Silent compilation w/ Automake 1.9 or 1.10 # ---------------------------------------------------------- # Automake 1.9.6 is not clever enough to override suffix rules within if # if SOFIA_COMPILE_SILENT VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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@ DIST_COMMON = $(top_srcdir)/rules/sofia.am \ $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am \ $(top_srcdir)/rules/silent.am $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(srcdir)/Doxyfile.in \ $(top_srcdir)/depcomp $(nobase_include_sofia_HEADERS) \ ChangeLog # Use with --enable-ndebug @NDEBUG_TRUE@am__append_1 = -DNDEBUG @HAVE_GENPNG_TRUE@@HAVE_LCOV_TRUE@am__append_2 = --frames @HAVE_LCOV_TRUE@am__append_3 = lcov lcov-report lcov-rerun clean-lcov covcheck uncovered subdir = libsofia-sip-ua/features ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(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)/m4/sac-coverage.m4 \ $(top_srcdir)/m4/sac-general.m4 \ $(top_srcdir)/m4/sac-openssl.m4 \ $(top_srcdir)/m4/sac-pkg-config.m4 $(top_srcdir)/m4/sac-su2.m4 \ $(top_srcdir)/m4/sac-tport.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libsofia-sip-ua/su/sofia-sip/su_configure.h CONFIG_CLEAN_FILES = Doxyfile CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libfeatures_la_LIBADD = am_libfeatures_la_OBJECTS = features.lo libfeatures_la_OBJECTS = $(am_libfeatures_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) -I$(top_builddir)/libsofia-sip-ua/su/sofia-sip depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f 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) 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 = $(libfeatures_la_SOURCES) DIST_SOURCES = $(libfeatures_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)$(include_sofiadir)" HEADERS = $(nobase_include_sofia_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)` CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CHECK_CFLAGS = @CHECK_CFLAGS@ CHECK_LIBS = @CHECK_LIBS@ COVERAGE_FLAGS = @COVERAGE_FLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CWFLAG = @CWFLAG@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV = @GCOV@ GENHTML = @GENHTML@ GENPNG = @GENPNG@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GLIB_VERSION = @GLIB_VERSION@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVER_SOFIA_SIP_UA_AGE = @LIBVER_SOFIA_SIP_UA_AGE@ LIBVER_SOFIA_SIP_UA_CUR = @LIBVER_SOFIA_SIP_UA_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_AGE = @LIBVER_SOFIA_SIP_UA_GLIB_AGE@ LIBVER_SOFIA_SIP_UA_GLIB_CUR = @LIBVER_SOFIA_SIP_UA_GLIB_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_REV = @LIBVER_SOFIA_SIP_UA_GLIB_REV@ LIBVER_SOFIA_SIP_UA_GLIB_SOVER = @LIBVER_SOFIA_SIP_UA_GLIB_SOVER@ LIBVER_SOFIA_SIP_UA_REV = @LIBVER_SOFIA_SIP_UA_REV@ LIBVER_SOFIA_SIP_UA_SOVER = @LIBVER_SOFIA_SIP_UA_SOVER@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MINGW_ENVIRONMENT = @MINGW_ENVIRONMENT@ MKDIR_P = @MKDIR_P@ MOSTLYCLEANFILES = @MOSTLYCLEANFILES@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ RANLIB = @RANLIB@ REPLACE_LIBADD = @REPLACE_LIBADD@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ SOFIA_GLIB_CFLAGS = @SOFIA_GLIB_CFLAGS@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ SOFIA_PLAT_CFLAGS = @SOFIA_PLAT_CFLAGS@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ VERSION = @VERSION@ VER_LIBSOFIA_SIP_UA_MAJOR_MINOR = @VER_LIBSOFIA_SIP_UA_MAJOR_MINOR@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ include_sofiadir = @include_sofiadir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ openssl_CFLAGS = @openssl_CFLAGS@ openssl_LIBS = @openssl_LIBS@ 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@ INCLUDES = $(INTERNAL_INCLUDES) # ---------------------------------------------------------------------- # Build targets noinst_LTLIBRARIES = libfeatures.la # ---------------------------------------------------------------------- # Rules for building the targets # This is used by platforms not supporting autoconf nobase_include_sofia_HEADERS = sofia-sip/sofia_features.h libfeatures_la_SOURCES = features.c # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST = features.docs # ---------------------------------------------------------------------- # Sofia specific rules LDADD = $(openssl_LIBS) sofiasrcdir = ${top_srcdir}/libsofia-sip-ua sofiabuilddir = ${top_builddir}/libsofia-sip-ua AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(SOFIA_CFLAGS) \ $(openssl_CFLAGS) $(SOFIA_PLAT_CFLAGS) $(am__append_1) SOFIA_COVERAGE = $(COVERAGE_FLAGS) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files TAG_AWK = ${sofiasrcdir}/su/tag_dll.awk SUFFIXES = _tag_ref.c _tag.c INTERNAL_INCLUDES = \ -I${sofiasrcdir}/features -I${sofiabuilddir}/features \ -I${sofiasrcdir}/ipt -I${sofiabuilddir}/ipt \ -I${sofiasrcdir}/iptsec -I${sofiabuilddir}/iptsec \ -I${sofiasrcdir}/bnf -I${sofiabuilddir}/bnf \ -I${sofiasrcdir}/http -I${sofiabuilddir}/http \ -I${sofiasrcdir}/msg -I${sofiabuilddir}/msg \ -I${sofiasrcdir}/nth -I${sofiabuilddir}/nth \ -I${sofiasrcdir}/nta -I${sofiabuilddir}/nta \ -I${sofiasrcdir}/nea -I${sofiabuilddir}/nea \ -I${sofiasrcdir}/nua -I${sofiabuilddir}/nua \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sdp -I${sofiabuilddir}/sdp \ -I${sofiasrcdir}/sip -I${sofiabuilddir}/sip \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sresolv -I${sofiabuilddir}/sresolv \ -I${sofiasrcdir}/tport -I${sofiabuilddir}/tport \ -I${sofiasrcdir}/stun -I${sofiabuilddir}/stun \ -I${sofiasrcdir}/url -I${sofiabuilddir}/url \ -I${sofiasrcdir}/su -I${sofiabuilddir}/su PHONY = built-sources clean-built-sources $(am__append_3) VALGRIND = valgrind VALGRINDFLAGS = --tool=memcheck # Scripts @HAVE_LCOV_TRUE@LCOV_UNCOVERED = ${top_srcdir}/scripts/uncovered @HAVE_LCOV_TRUE@LCOV_REPORT = ${top_srcdir}/scripts/lcov-report # Report directory @HAVE_LCOV_TRUE@lcovdir = ${top_builddir}/lcov # Options @HAVE_LCOV_TRUE@GENHTML_OPTIONS = --show-details --legend \ @HAVE_LCOV_TRUE@ $(am__append_2) # Fancy shell command that expands to directory relative to top_builddir @HAVE_LCOV_TRUE@expand_subdir = `pwd|sed "s'\`cd ${top_builddir};pwd\`''"` SOFIA_SILENT = @ LIBTOOL_FLAGS = --silent # From Automake 1.9.6 - LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(LIBTOOL_FLAGS) \ $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) LINK = ${SOFIA_SILENT}test "${SOFIA_SILENT}" != @ || echo ' LINK $@'; \ $(LIBTOOL) --tag=CC --mode=link $(LIBTOOL_FLAGS) \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ all: all-am .SUFFIXES: .SUFFIXES: _tag_ref.c _tag.c .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.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 libsofia-sip-ua/features/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu libsofia-sip-ua/features/Makefile .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.am: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): Doxyfile: $(top_builddir)/config.status $(srcdir)/Doxyfile.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ 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}; \ } libfeatures.la: $(libfeatures_la_OBJECTS) $(libfeatures_la_DEPENDENCIES) $(EXTRA_libfeatures_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libfeatures_la_OBJECTS) $(libfeatures_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/features.Plo@am__quote@ .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.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) '$<'` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-nobase_include_sofiaHEADERS: $(nobase_include_sofia_HEADERS) @$(NORMAL_INSTALL) @list='$(nobase_include_sofia_HEADERS)'; test -n "$(include_sofiadir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(include_sofiadir)'"; \ $(MKDIR_P) "$(DESTDIR)$(include_sofiadir)" || exit 1; \ fi; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo " $(MKDIR_P) '$(DESTDIR)$(include_sofiadir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(include_sofiadir)/$$dir"; }; \ echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(include_sofiadir)/$$dir'"; \ $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(include_sofiadir)/$$dir" || exit $$?; }; \ done uninstall-nobase_include_sofiaHEADERS: @$(NORMAL_UNINSTALL) @list='$(nobase_include_sofia_HEADERS)'; test -n "$(include_sofiadir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ dir='$(DESTDIR)$(include_sofiadir)'; $(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: $(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) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(include_sofiadir)"; 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 "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) 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) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." @HAVE_LCOV_FALSE@clean-local: clean: clean-am clean-am: clean-generic clean-libtool clean-local \ clean-noinstLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -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-nobase_include_sofiaHEADERS 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 -rf ./$(DEPDIR) -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-nobase_include_sofiaHEADERS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-local 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-nobase_include_sofiaHEADERS 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-nobase_include_sofiaHEADERS built-sources: $(BUILT_SOURCES) clean-built-sources: -rm -rf $(BUILT_SOURCES) $(BUILT_SOURCES:%=$(srcdir)/%) *_tag_ref.c: $(TAG_AWK) _tag.c_tag_ref.c: $(AWK) -f $(TAG_AWK) NODLL=1 $(TAG_DLL_FLAGS) REF=$@ $< ../bnf/libbnf.la ../http/libhttp.la ../ipt/libipt.la ../iptsec/libiptsec.la \ ../msg/libmsg.la ../nea/libnea.la ../nta/libnta.la ../nth/libnth.la \ ../nua/libnua.la ../sdp/libsdp.la ../sip/libsip.la ../soa/libsoa.la \ ../sresolv/libsresolv.la ../stun/libstun.la ../su/libsu.la \ ../tport/libtport.la ../url/liburl.la: cd $(@D) && $(MAKE) $(@F) checklib: $(noinst_LTLIBRARIES) $(check_LTLIBRARIES) valcheck: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) valcheck-am valcheck-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS # Run tests with valgrind in valcheck-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ list='$(TESTS)'; \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ if case $$tst in \ run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ $${dir}$$tst ;; \ esac ; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ echo "XPASS: $$tst"; \ ;; \ *) \ echo "PASS: $$tst"; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xfail=`expr $$xfail + 1`; \ echo "XFAIL: $$tst"; \ ;; \ *) \ failed=`expr $$failed + 1`; \ echo "FAIL: $$tst"; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ echo "SKIP: $$tst"; \ fi; \ done; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="All $$all tests passed"; \ else \ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all tests failed"; \ else \ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ skipped="($$skip tests were not run)"; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ report=""; \ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ report="Please report to $(PACKAGE_BUGREPORT)"; \ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ echo "$$dashes"; \ echo "$$banner"; \ test -z "$$skipped" || echo "$$skipped"; \ test -z "$$report" || echo "$$report"; \ echo "$$dashes"; \ test "$$failed" -eq 0; \ else :; fi # # Generate pretty coverage report (unless it has been already done) # @HAVE_LCOV_TRUE@lcov: @HAVE_LCOV_TRUE@ @-test -r ${lcovdir}${expand_subdir}/lcov.info \ @HAVE_LCOV_TRUE@ || make lcov-report # Generate pretty coverage report based on current coverage data @HAVE_LCOV_TRUE@lcov-report: @HAVE_LCOV_TRUE@ sub=${expand_subdir} odir=${lcovdir}$$sub ; \ @HAVE_LCOV_TRUE@ rm -rf $$odir ; mkdir -p $$odir && \ @HAVE_LCOV_TRUE@ ${LCOV_REPORT} ${GENHTML_OPTIONS} \ @HAVE_LCOV_TRUE@ --title "${PACKAGE_NAME}-${PACKAGE_VERSION}$$sub" \ @HAVE_LCOV_TRUE@ --srcdir=${srcdir} -o $$odir # Rerun checks before generating report @HAVE_LCOV_TRUE@lcov-rerun: clean-lcov @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) lcov-report # Show all uncovered lines as errors @HAVE_LCOV_TRUE@uncovered: @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} # Run check in current dir and show all uncovered lines as errors @HAVE_LCOV_TRUE@covcheck: @HAVE_LCOV_TRUE@ -find . -name "*.gcda" | xargs rm -rf @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} @HAVE_LCOV_TRUE@clean-local:: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true @HAVE_LCOV_TRUE@clean-lcov: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true # Rules from depend2.am (GENERIC = TRUE, SUBDIROBJ = FALSE, %FASTDEP% = am_fastdepCC) silenced. .c.o: @test "${SOFIA_SILENT}" != @ || echo ' COMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(COMPILE) -c -o $@ $< .c.lo: @test "${SOFIA_SILENT}" != @ || echo ' LTCOMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(LTCOMPILE) -c -o $@ $< # endif # 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: sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/features/features.c000066400000000000000000000075361223300710500233650ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE features.c * Provide features available through the sofia-sip library. * * @author Pekka Pessi * * @date Created: Mon Oct 24 14:51:32 2005 ppessi */ #include "config.h" #include #include #include "tport_tls.h" #include "sofia-sip/sofia_features.h" /** The name and version of software package providing Sofia-SIP-UA library. * @showinitializer */ char const * const sofia_sip_name_version = SOFIA_SIP_NAME_VERSION; /** The name and version of software package providing S/MIME functionality, * NULL if none. */ char const * sofia_sip_has_smime; /** The name and version of software package providing TLS functionality, * NULL if none. * * TLS over TCP is used as transport for SIP messages when using SIPS * scheme. Using TLS over TCP with SIP is described in @RFC3261. */ #if HAVE_OPENSSL char const * sofia_sip_has_tls = tls_version; #else char const * sofia_sip_has_tls; #endif /** The name and version of software package providing DTLS functionality, * NULL if none. * * DTLS or TLS over datagram transport (UDP) can be used as transport for * SIP messages. */ char const * sofia_sip_has_dtls; /** The name and version of software package providing TLS over SCTP functionality, * NULL if none. * * TLS over SCTP can be used as transport for SIP messages. */ char const * sofia_sip_has_tls_sctp; #if HAVE_SOFIA_SIGCOMP #include #endif /** The name and version of software package providing SigComp functionality, * NULL if none. * * SigComp can be used to compress SIP messages. */ #if HAVE_SOFIA_SIGCOMP char const * sofia_sip_has_sigcomp = sigcomp_package_version; #else char const * sofia_sip_has_sigcomp; #endif /** The name and version of software package providing STUN functionality, * NULL if none. * * STUN is a protocol used to traverse NATs with UDP. */ #if HAVE_SOFIA_STUN extern char const stun_version[]; char const * sofia_sip_has_stun = stun_version; #else char const * sofia_sip_has_stun; #endif /** The name and version of software package providing TURN functionality, * NULL if none. * * TURN is a protocol used to traverse NATs or firewalls with TCP or UDP. */ char const * sofia_sip_has_turn; /** The name and version of software package providing UPnP functionality, * NULL if none. * * UPnP (Universal Plug and Play) can be used to traverse NATs or firewalls. */ char const * sofia_sip_has_upnp; /** The name and version of software package providing SCTP functionality, * NULL if none. * * SCTP can be used as transport for SIP messages. The software providing it * can be, for example, LKSCTP (Linux kernel SCTP) for Linux. */ char const * sofia_sip_has_sctp; /* We don't have viable SCTP transport interface */ /** The name and version of software package providing IPv6 functionality, * NULL if none. * * IPv6 can be used to send SIP messages. */ #if SU_HAVE_IN6 char const * sofia_sip_has_ipv6 = "IPv6"; #else char const * sofia_sip_has_ipv6; #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/features/features.docs000066400000000000000000000021531223300710500240610ustar00rootroot00000000000000/* -*- text -*- */ /**@MODULEPAGE "features" Module @section features_meta Module Meta Information The @b features module provides application information about the various features possibly available through the @ref subdirs "sofia-sip-ua" binary API. @CONTACT Pekka Pessi @STATUS @SofiaSIP Core library @LICENSE LGPL @par Contributor(s): - Pekka Pessi @section features_overview Overview The #sofia_sip_name_version contains the name and release of currently installed @a libsofia-sip-ua.so library. The macro #SOFIA_SIP_NAME_VERSION contains the name and release of currently available include files. The Sofia SIP binary API hides some protocols used under the SIP stack. While the binary API stays the same, the features are not necessarily there. These features are mainly related to encryption, compression and underlying transports. - #sofia_sip_has_smime - #sofia_sip_has_tls - #sofia_sip_has_dtls - #sofia_sip_has_tls_sctp - #sofia_sip_has_sigcomp - #sofia_sip_has_stun - #sofia_sip_has_turn - #sofia_sip_has_upnp - #sofia_sip_has_sctp - #sofia_sip_has_ipv6 */sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/features/sofia-sip/000077500000000000000000000000001223300710500232625ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/features/sofia-sip/sofia_features.h.in000066400000000000000000000041531223300710500270420ustar00rootroot00000000000000/* This -*- C -*- file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /* @configure_input@ */ /**@file sofia-sip/sofia_features.h * @brief Sofia-SIP Library Features * * Macros and string constants listing features supported or not supported * by sofia-sip-ua library. * * @author Pekka Pessi * * @date Created: Wed Feb 14 17:09:44 2001 ppessi */ #ifndef SOFIA_SIP_FEATURES_H /** Defined when has been included. */ #define SOFIA_SIP_FEATURES_H /** Current Sofia version. @showinitializer */ #define SOFIA_SIP_VERSION "@PACKAGE_VERSION@" /** Current Sofia package name and version. @showinitializer */ #define SOFIA_SIP_NAME_VERSION "@PACKAGE_NAME@-@PACKAGE_VERSION@" #ifdef __cplusplus extern "C" { #endif SOFIAPUBVAR char const * const sofia_sip_name_version; SOFIAPUBVAR char const * sofia_sip_has_smime; SOFIAPUBVAR char const * sofia_sip_has_tls; SOFIAPUBVAR char const * sofia_sip_has_dtls; SOFIAPUBVAR char const * sofia_sip_has_tls_sctp; SOFIAPUBVAR char const * sofia_sip_has_sigcomp; SOFIAPUBVAR char const * sofia_sip_has_stun; SOFIAPUBVAR char const * sofia_sip_has_turn; SOFIAPUBVAR char const * sofia_sip_has_upnp; SOFIAPUBVAR char const * sofia_sip_has_sctp; SOFIAPUBVAR char const * sofia_sip_has_ipv6; #ifdef __cplusplus } #endif #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/http/000077500000000000000000000000001223300710500205315ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/http/ChangeLog000066400000000000000000000003001223300710500222740ustar00rootroot000000000000002005-11-08 Pekka Pessi * Renamed http_test.c as test_http.c 2005-07-18 Kai Vehmanen * Initial import of the module to Sofia-SIP tree. sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/http/Doxyfile.in000066400000000000000000000007551223300710500226530ustar00rootroot00000000000000PROJECT_NAME = "http" OUTPUT_DIRECTORY = ../docs/html/http INPUT = @srcdir@/http.docs @srcdir@/sofia-sip sofia-sip @srcdir@ . @INCLUDE_PATH = . @srcdir@ @INCLUDE = ../docs/Doxyfile.conf TAGFILES += \ ../docs/su.doxytags=../su \ ../docs/ipt.doxytags=../ipt \ ../docs/bnf.doxytags=../bnf \ ../docs/url.doxytags=../url \ ../docs/msg.doxytags=../msg GENERATE_TAGFILE = ../docs/http.doxytags ALIASES += \ "HTTP_HEADER=@ingroup http_headers\n@defgroup" \ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/http/Makefile.am000066400000000000000000000052141223300710500225670ustar00rootroot00000000000000# # Makefile.am for http module # # Copyright (C) 2005,2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # ---------------------------------------------------------------------- # Header paths INCLUDES = -I$(srcdir)/../bnf -I../bnf \ -I$(srcdir)/../msg -I../msg \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su -I../su # ---------------------------------------------------------------------- # Build targets noinst_LTLIBRARIES = libhttp.la check_PROGRAMS = test_http TESTS = test_http # ---------------------------------------------------------------------- # Rules for building the targets PUBLIC_H = sofia-sip/http.h sofia-sip/http_header.h \ sofia-sip/http_parser.h sofia-sip/http_tag_class.h \ sofia-sip/http_status.h sofia-sip/http_hclasses.h BUILT_H = sofia-sip/http_protos.h sofia-sip/http_tag.h BUILT_C = http_tag.c http_parser_table.c BUILT_SOURCES = $(BUILT_H) $(BUILT_C) http_tag_ref.c nobase_include_sofia_HEADERS = $(BUILT_H) $(PUBLIC_H) libhttp_la_SOURCES = $(INTERNAL_H) \ http_parser.c http_header.c \ http_basic.c http_extra.c http_inlined.c \ http_status.c http_tag_class.c \ $(BUILT_SOURCES) COVERAGE_INPUT = $(libhttp_la_SOURCES) $(include_sofia_HEADERS) LDADD = libhttp.la \ ../bnf/libbnf.la \ ../msg/libmsg.la \ ../url/liburl.la \ ../ipt/libipt.la \ ../su/libsu.la test_http_LDFLAGS = -static # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST = http.docs \ sofia-sip/http_protos.h.in \ sofia-sip/http_tag.h.in \ http_parser_table.c.in \ http_tag.c.in # ---------------------------------------------------------------------- # Sofia specific rules include $(top_srcdir)/rules/sofia.am TAG_DLL_FLAGS = DLLREF=1 MSG_PARSER_AWK = ${srcdir}/../msg/msg_parser.awk AWK_HTTP_AWK = LC_ALL=C ${AWK} -f ${MSG_PARSER_AWK} module=http SS_HTTP_H = ${srcdir}/sofia-sip/http.h ${BUILT_H} ${BUILT_C}: ${srcdir}/sofia-sip/http.h ${MSG_PARSER_AWK} sofia-sip/http_protos.h: ${srcdir}/sofia-sip/http_protos.h.in @-mkdir sofia-sip 2>/dev/null || true ${AWK_HTTP_AWK} PR=$@ TEMPLATE=${srcdir}/sofia-sip/http_protos.h.in ${SS_HTTP_H} sofia-sip/http_tag.h: ${srcdir}/sofia-sip/http_tag.h.in @-mkdir sofia-sip 2>/dev/null || true ${AWK_HTTP_AWK} PR=$@ TEMPLATE=${srcdir}/sofia-sip/http_tag.h.in ${SS_HTTP_H} http_tag.c: ${srcdir}/http_tag.c.in ${AWK_HTTP_AWK} PR=$@ TEMPLATE=${srcdir}/http_tag.c.in ${SS_HTTP_H} http_parser_table.c: ${srcdir}/http_parser_table.c.in ${AWK_HTTP_AWK} PT=$@ TEMPLATE=${srcdir}/http_parser_table.c.in \ MC_HASH_SIZE=127 ${SS_HTTP_H} sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/http/Makefile.in000066400000000000000000001370151223300710500226050ustar00rootroot00000000000000# Makefile.in generated by automake 1.14 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 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 http module # # Copyright (C) 2005,2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # ---------------------------------------------------------------------- # Header paths # common Makefile targets for libsofia-sip-ua(-glib) modules # ---------------------------------------------------------- # # run tests with valgrind # # Copyright (C) 2007 Nokia Corporation. # 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 file contains free software from Makefile.in by the Free Software # Foundation: # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 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. # # Generate lcov output # # # Copyright (C) 2007 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # # Silent compilation w/ Automake 1.9 or 1.10 # ---------------------------------------------------------- # Automake 1.9.6 is not clever enough to override suffix rules within if # if SOFIA_COMPILE_SILENT VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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@ check_PROGRAMS = test_http$(EXEEXT) TESTS = test_http$(EXEEXT) DIST_COMMON = $(top_srcdir)/rules/sofia.am \ $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am \ $(top_srcdir)/rules/silent.am $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(srcdir)/Doxyfile.in \ $(top_srcdir)/depcomp $(nobase_include_sofia_HEADERS) \ $(top_srcdir)/test-driver ChangeLog # Use with --enable-ndebug @NDEBUG_TRUE@am__append_1 = -DNDEBUG @HAVE_GENPNG_TRUE@@HAVE_LCOV_TRUE@am__append_2 = --frames @HAVE_LCOV_TRUE@am__append_3 = lcov lcov-report lcov-rerun clean-lcov covcheck uncovered subdir = libsofia-sip-ua/http ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(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)/m4/sac-coverage.m4 \ $(top_srcdir)/m4/sac-general.m4 \ $(top_srcdir)/m4/sac-openssl.m4 \ $(top_srcdir)/m4/sac-pkg-config.m4 $(top_srcdir)/m4/sac-su2.m4 \ $(top_srcdir)/m4/sac-tport.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libsofia-sip-ua/su/sofia-sip/su_configure.h CONFIG_CLEAN_FILES = Doxyfile CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libhttp_la_LIBADD = am__objects_1 = am__objects_2 = http_tag.lo http_parser_table.lo am__objects_3 = $(am__objects_1) $(am__objects_2) http_tag_ref.lo am_libhttp_la_OBJECTS = http_parser.lo http_header.lo http_basic.lo \ http_extra.lo http_inlined.lo http_status.lo http_tag_class.lo \ $(am__objects_3) libhttp_la_OBJECTS = $(am_libhttp_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_http_SOURCES = test_http.c test_http_OBJECTS = test_http.$(OBJEXT) test_http_LDADD = $(LDADD) am__DEPENDENCIES_1 = test_http_DEPENDENCIES = libhttp.la ../bnf/libbnf.la ../msg/libmsg.la \ ../url/liburl.la ../ipt/libipt.la ../su/libsu.la \ $(am__DEPENDENCIES_1) test_http_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(test_http_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) -I$(top_builddir)/libsofia-sip-ua/su/sofia-sip depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f 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) 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 = $(libhttp_la_SOURCES) test_http.c DIST_SOURCES = $(libhttp_la_SOURCES) test_http.c 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)$(include_sofiadir)" HEADERS = $(nobase_include_sofia_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)` 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=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ 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_DRIVER = $(SHELL) $(top_srcdir)/test-driver 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) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CHECK_CFLAGS = @CHECK_CFLAGS@ CHECK_LIBS = @CHECK_LIBS@ COVERAGE_FLAGS = @COVERAGE_FLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CWFLAG = @CWFLAG@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV = @GCOV@ GENHTML = @GENHTML@ GENPNG = @GENPNG@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GLIB_VERSION = @GLIB_VERSION@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVER_SOFIA_SIP_UA_AGE = @LIBVER_SOFIA_SIP_UA_AGE@ LIBVER_SOFIA_SIP_UA_CUR = @LIBVER_SOFIA_SIP_UA_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_AGE = @LIBVER_SOFIA_SIP_UA_GLIB_AGE@ LIBVER_SOFIA_SIP_UA_GLIB_CUR = @LIBVER_SOFIA_SIP_UA_GLIB_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_REV = @LIBVER_SOFIA_SIP_UA_GLIB_REV@ LIBVER_SOFIA_SIP_UA_GLIB_SOVER = @LIBVER_SOFIA_SIP_UA_GLIB_SOVER@ LIBVER_SOFIA_SIP_UA_REV = @LIBVER_SOFIA_SIP_UA_REV@ LIBVER_SOFIA_SIP_UA_SOVER = @LIBVER_SOFIA_SIP_UA_SOVER@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MINGW_ENVIRONMENT = @MINGW_ENVIRONMENT@ MKDIR_P = @MKDIR_P@ MOSTLYCLEANFILES = @MOSTLYCLEANFILES@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ RANLIB = @RANLIB@ REPLACE_LIBADD = @REPLACE_LIBADD@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ SOFIA_GLIB_CFLAGS = @SOFIA_GLIB_CFLAGS@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ SOFIA_PLAT_CFLAGS = @SOFIA_PLAT_CFLAGS@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ VERSION = @VERSION@ VER_LIBSOFIA_SIP_UA_MAJOR_MINOR = @VER_LIBSOFIA_SIP_UA_MAJOR_MINOR@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ include_sofiadir = @include_sofiadir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ openssl_CFLAGS = @openssl_CFLAGS@ openssl_LIBS = @openssl_LIBS@ 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@ INCLUDES = -I$(srcdir)/../bnf -I../bnf \ -I$(srcdir)/../msg -I../msg \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su -I../su # ---------------------------------------------------------------------- # Build targets noinst_LTLIBRARIES = libhttp.la # ---------------------------------------------------------------------- # Rules for building the targets PUBLIC_H = sofia-sip/http.h sofia-sip/http_header.h \ sofia-sip/http_parser.h sofia-sip/http_tag_class.h \ sofia-sip/http_status.h sofia-sip/http_hclasses.h BUILT_H = sofia-sip/http_protos.h sofia-sip/http_tag.h BUILT_C = http_tag.c http_parser_table.c BUILT_SOURCES = $(BUILT_H) $(BUILT_C) http_tag_ref.c nobase_include_sofia_HEADERS = $(BUILT_H) $(PUBLIC_H) libhttp_la_SOURCES = $(INTERNAL_H) \ http_parser.c http_header.c \ http_basic.c http_extra.c http_inlined.c \ http_status.c http_tag_class.c \ $(BUILT_SOURCES) COVERAGE_INPUT = $(libhttp_la_SOURCES) $(include_sofia_HEADERS) LDADD = libhttp.la ../bnf/libbnf.la ../msg/libmsg.la ../url/liburl.la \ ../ipt/libipt.la ../su/libsu.la $(openssl_LIBS) test_http_LDFLAGS = -static # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST = http.docs \ sofia-sip/http_protos.h.in \ sofia-sip/http_tag.h.in \ http_parser_table.c.in \ http_tag.c.in sofiasrcdir = ${top_srcdir}/libsofia-sip-ua sofiabuilddir = ${top_builddir}/libsofia-sip-ua AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(SOFIA_CFLAGS) \ $(openssl_CFLAGS) $(SOFIA_PLAT_CFLAGS) $(am__append_1) SOFIA_COVERAGE = $(COVERAGE_FLAGS) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files TAG_AWK = ${sofiasrcdir}/su/tag_dll.awk SUFFIXES = _tag_ref.c _tag.c INTERNAL_INCLUDES = \ -I${sofiasrcdir}/features -I${sofiabuilddir}/features \ -I${sofiasrcdir}/ipt -I${sofiabuilddir}/ipt \ -I${sofiasrcdir}/iptsec -I${sofiabuilddir}/iptsec \ -I${sofiasrcdir}/bnf -I${sofiabuilddir}/bnf \ -I${sofiasrcdir}/http -I${sofiabuilddir}/http \ -I${sofiasrcdir}/msg -I${sofiabuilddir}/msg \ -I${sofiasrcdir}/nth -I${sofiabuilddir}/nth \ -I${sofiasrcdir}/nta -I${sofiabuilddir}/nta \ -I${sofiasrcdir}/nea -I${sofiabuilddir}/nea \ -I${sofiasrcdir}/nua -I${sofiabuilddir}/nua \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sdp -I${sofiabuilddir}/sdp \ -I${sofiasrcdir}/sip -I${sofiabuilddir}/sip \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sresolv -I${sofiabuilddir}/sresolv \ -I${sofiasrcdir}/tport -I${sofiabuilddir}/tport \ -I${sofiasrcdir}/stun -I${sofiabuilddir}/stun \ -I${sofiasrcdir}/url -I${sofiabuilddir}/url \ -I${sofiasrcdir}/su -I${sofiabuilddir}/su PHONY = built-sources clean-built-sources $(am__append_3) VALGRIND = valgrind VALGRINDFLAGS = --tool=memcheck # Scripts @HAVE_LCOV_TRUE@LCOV_UNCOVERED = ${top_srcdir}/scripts/uncovered @HAVE_LCOV_TRUE@LCOV_REPORT = ${top_srcdir}/scripts/lcov-report # Report directory @HAVE_LCOV_TRUE@lcovdir = ${top_builddir}/lcov # Options @HAVE_LCOV_TRUE@GENHTML_OPTIONS = --show-details --legend \ @HAVE_LCOV_TRUE@ $(am__append_2) # Fancy shell command that expands to directory relative to top_builddir @HAVE_LCOV_TRUE@expand_subdir = `pwd|sed "s'\`cd ${top_builddir};pwd\`''"` SOFIA_SILENT = @ LIBTOOL_FLAGS = --silent # From Automake 1.9.6 - LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(LIBTOOL_FLAGS) \ $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) LINK = ${SOFIA_SILENT}test "${SOFIA_SILENT}" != @ || echo ' LINK $@'; \ $(LIBTOOL) --tag=CC --mode=link $(LIBTOOL_FLAGS) \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ # ---------------------------------------------------------------------- # Sofia specific rules TAG_DLL_FLAGS = DLLREF=1 MSG_PARSER_AWK = ${srcdir}/../msg/msg_parser.awk AWK_HTTP_AWK = LC_ALL=C ${AWK} -f ${MSG_PARSER_AWK} module=http SS_HTTP_H = ${srcdir}/sofia-sip/http.h all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: _tag_ref.c _tag.c .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.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 libsofia-sip-ua/http/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu libsofia-sip-ua/http/Makefile .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.am: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): Doxyfile: $(top_builddir)/config.status $(srcdir)/Doxyfile.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ 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}; \ } libhttp.la: $(libhttp_la_OBJECTS) $(libhttp_la_DEPENDENCIES) $(EXTRA_libhttp_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libhttp_la_OBJECTS) $(libhttp_la_LIBADD) $(LIBS) 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_http$(EXEEXT): $(test_http_OBJECTS) $(test_http_DEPENDENCIES) $(EXTRA_test_http_DEPENDENCIES) @rm -f test_http$(EXEEXT) $(AM_V_CCLD)$(test_http_LINK) $(test_http_OBJECTS) $(test_http_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_basic.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_extra.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_header.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_inlined.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_parser.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_parser_table.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_status.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_tag.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_tag_class.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_tag_ref.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_http.Po@am__quote@ .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.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) '$<'` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-nobase_include_sofiaHEADERS: $(nobase_include_sofia_HEADERS) @$(NORMAL_INSTALL) @list='$(nobase_include_sofia_HEADERS)'; test -n "$(include_sofiadir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(include_sofiadir)'"; \ $(MKDIR_P) "$(DESTDIR)$(include_sofiadir)" || exit 1; \ fi; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo " $(MKDIR_P) '$(DESTDIR)$(include_sofiadir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(include_sofiadir)/$$dir"; }; \ echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(include_sofiadir)/$$dir'"; \ $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(include_sofiadir)/$$dir" || exit $$?; }; \ done uninstall-nobase_include_sofiaHEADERS: @$(NORMAL_UNINSTALL) @list='$(nobase_include_sofia_HEADERS)'; test -n "$(include_sofiadir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ dir='$(DESTDIR)$(include_sofiadir)'; $(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; \ else \ 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 $(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_http.log: test_http$(EXEEXT) @p='test_http$(EXEEXT)'; \ b='test_http'; \ $(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: $(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: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(include_sofiadir)"; 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: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) -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: 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) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) 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) @HAVE_LCOV_FALSE@clean-local: clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libtool clean-local \ clean-noinstLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -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-nobase_include_sofiaHEADERS 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 -rf ./$(DEPDIR) -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-nobase_include_sofiaHEADERS .MAKE: all check check-am install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libtool clean-local \ 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-nobase_include_sofiaHEADERS 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 \ uninstall-nobase_include_sofiaHEADERS built-sources: $(BUILT_SOURCES) clean-built-sources: -rm -rf $(BUILT_SOURCES) $(BUILT_SOURCES:%=$(srcdir)/%) *_tag_ref.c: $(TAG_AWK) _tag.c_tag_ref.c: $(AWK) -f $(TAG_AWK) NODLL=1 $(TAG_DLL_FLAGS) REF=$@ $< ../bnf/libbnf.la ../http/libhttp.la ../ipt/libipt.la ../iptsec/libiptsec.la \ ../msg/libmsg.la ../nea/libnea.la ../nta/libnta.la ../nth/libnth.la \ ../nua/libnua.la ../sdp/libsdp.la ../sip/libsip.la ../soa/libsoa.la \ ../sresolv/libsresolv.la ../stun/libstun.la ../su/libsu.la \ ../tport/libtport.la ../url/liburl.la: cd $(@D) && $(MAKE) $(@F) checklib: $(noinst_LTLIBRARIES) $(check_LTLIBRARIES) valcheck: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) valcheck-am valcheck-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS # Run tests with valgrind in valcheck-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ list='$(TESTS)'; \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ if case $$tst in \ run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ $${dir}$$tst ;; \ esac ; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ echo "XPASS: $$tst"; \ ;; \ *) \ echo "PASS: $$tst"; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xfail=`expr $$xfail + 1`; \ echo "XFAIL: $$tst"; \ ;; \ *) \ failed=`expr $$failed + 1`; \ echo "FAIL: $$tst"; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ echo "SKIP: $$tst"; \ fi; \ done; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="All $$all tests passed"; \ else \ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all tests failed"; \ else \ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ skipped="($$skip tests were not run)"; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ report=""; \ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ report="Please report to $(PACKAGE_BUGREPORT)"; \ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ echo "$$dashes"; \ echo "$$banner"; \ test -z "$$skipped" || echo "$$skipped"; \ test -z "$$report" || echo "$$report"; \ echo "$$dashes"; \ test "$$failed" -eq 0; \ else :; fi # # Generate pretty coverage report (unless it has been already done) # @HAVE_LCOV_TRUE@lcov: @HAVE_LCOV_TRUE@ @-test -r ${lcovdir}${expand_subdir}/lcov.info \ @HAVE_LCOV_TRUE@ || make lcov-report # Generate pretty coverage report based on current coverage data @HAVE_LCOV_TRUE@lcov-report: @HAVE_LCOV_TRUE@ sub=${expand_subdir} odir=${lcovdir}$$sub ; \ @HAVE_LCOV_TRUE@ rm -rf $$odir ; mkdir -p $$odir && \ @HAVE_LCOV_TRUE@ ${LCOV_REPORT} ${GENHTML_OPTIONS} \ @HAVE_LCOV_TRUE@ --title "${PACKAGE_NAME}-${PACKAGE_VERSION}$$sub" \ @HAVE_LCOV_TRUE@ --srcdir=${srcdir} -o $$odir # Rerun checks before generating report @HAVE_LCOV_TRUE@lcov-rerun: clean-lcov @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) lcov-report # Show all uncovered lines as errors @HAVE_LCOV_TRUE@uncovered: @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} # Run check in current dir and show all uncovered lines as errors @HAVE_LCOV_TRUE@covcheck: @HAVE_LCOV_TRUE@ -find . -name "*.gcda" | xargs rm -rf @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} @HAVE_LCOV_TRUE@clean-local:: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true @HAVE_LCOV_TRUE@clean-lcov: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true # Rules from depend2.am (GENERIC = TRUE, SUBDIROBJ = FALSE, %FASTDEP% = am_fastdepCC) silenced. .c.o: @test "${SOFIA_SILENT}" != @ || echo ' COMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(COMPILE) -c -o $@ $< .c.lo: @test "${SOFIA_SILENT}" != @ || echo ' LTCOMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(LTCOMPILE) -c -o $@ $< # endif ${BUILT_H} ${BUILT_C}: ${srcdir}/sofia-sip/http.h ${MSG_PARSER_AWK} sofia-sip/http_protos.h: ${srcdir}/sofia-sip/http_protos.h.in @-mkdir sofia-sip 2>/dev/null || true ${AWK_HTTP_AWK} PR=$@ TEMPLATE=${srcdir}/sofia-sip/http_protos.h.in ${SS_HTTP_H} sofia-sip/http_tag.h: ${srcdir}/sofia-sip/http_tag.h.in @-mkdir sofia-sip 2>/dev/null || true ${AWK_HTTP_AWK} PR=$@ TEMPLATE=${srcdir}/sofia-sip/http_tag.h.in ${SS_HTTP_H} http_tag.c: ${srcdir}/http_tag.c.in ${AWK_HTTP_AWK} PR=$@ TEMPLATE=${srcdir}/http_tag.c.in ${SS_HTTP_H} http_parser_table.c: ${srcdir}/http_parser_table.c.in ${AWK_HTTP_AWK} PT=$@ TEMPLATE=${srcdir}/http_parser_table.c.in \ MC_HASH_SIZE=127 ${SS_HTTP_H} # 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: sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/http/http.docs000066400000000000000000000032061223300710500223630ustar00rootroot00000000000000/* -*- c -*- */ /**@MODULEPAGE "http" - HTTP Parser Module * * @section http_meta Module Meta Information * * The @b http module contains interface to the HTTP parser and the header * and message objects. * * @CONTACT Pekka Pessi * * @STATUS @SofiaSIP Core library * * @LICENSE LGPL * * @section http_overview Overview * * Each HTTP header has a structure defined for it in . All the * variables, objects and functions related to a particular HTTP header are * documented in a submodule for the header. In * addition to the header structure, there is defined a @em header @em class * structure and some standard functions for each header in the * include file. For header @c X, there are types, * functions, macros and header class as follows: * * - @c http_X_t is the structure used to store parsed header, * - @c HTTP_X_INIT() initializes a static instance of http_X_t, * - @c http_X_p() tests if header object is instance of header X, * - @c http_X_make() is a macro that creates a header X object by decoding given string, * - @c http_X_dup() duplicates (deeply copies) the header X (macro), * - @c http_X_copy() is a macro that copies the header X (macro), * - @c #msg_hclass_t http_X_class[] contains the @em header @em class * for header X. * * In addition to this interface, the parser provider interface is * documented in the SIP Parser module. * The parser provider interface makes it possible to extend HTTP parser with * new headers or extend existing ones. */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/http/http_basic.c000066400000000000000000001335611223300710500230260ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE http_basic.c * @brief HTTP basic header * * The file @b http_basic.c contains implementation of header classes for * basic HTTP headers, like request and status lines, payload, @b Call-ID, @b * CSeq, @b Contact, @b Content-Length, @b Date, @b Expires, @b From, @b * Route, @b Record-Route, @b To, and @b Via. * * @author Pekka Pessi * * @date Created: Tue Jun 13 02:57:51 2000 ppessi */ #include "config.h" /* Avoid casting http_t to msg_pub_t and http_header_t to msg_header_t */ #define MSG_PUB_T struct http_s #define MSG_HDR_T union http_header_u #include #include #include #include #include #include #include #include #include #include #include #include /* ====================================================================== */ /**@HTTP_HEADER http_request HTTP request line. * * The HTTP request line contains the method, URL, and an optional HTTP * protocol version. The missing version indicates version 0.9 without any * request headers. */ /** * Parse request line of a HTTP message. * * The function @c http_request_d() parses the request line from a a HTTP * message. */ issize_t http_request_d(su_home_t *home, http_header_t *h, char *s, isize_t slen) { http_request_t *rq = (http_request_t *)h; char *uri, *version; if (msg_firstline_d(s, &uri, &version) < 0 || (rq->rq_method = http_method_d(&s, &rq->rq_method_name)) < 0 || *s || url_d(rq->rq_url, uri) < 0 || (http_version_d(&version, &rq->rq_version) < 0 || version[0])) return -1; return 0; } /** * Encode a HTTP request line. * * The function @c http_request_e() prints a HTTP request line. */ issize_t http_request_e(char b[], isize_t bsiz, http_header_t const *h, int flags) { http_request_t const *rq = (http_request_t const *)h; return snprintf(b, bsiz, "%s " URL_FORMAT_STRING "%s%s" CRLF, rq->rq_method_name, URL_PRINT_ARGS(rq->rq_url), rq->rq_version ? " " : "", rq->rq_version ? rq->rq_version : ""); } isize_t http_request_dup_xtra(http_header_t const *h, isize_t offset) { http_request_t const *rq = (http_request_t const *)h; offset += url_xtra(rq->rq_url); if (!rq->rq_method) offset += MSG_STRING_SIZE(rq->rq_method_name); if (rq->rq_version) offset += http_version_xtra(rq->rq_version); return offset; } /** Duplicate one request header. */ char *http_request_dup_one(http_header_t *dst, http_header_t const *src, char *b, isize_t xtra) { http_request_t *rq = (http_request_t *)dst; http_request_t const *o = (http_request_t const *)src; char *end = b + xtra; URL_DUP(b, end, rq->rq_url, o->rq_url); if (!(rq->rq_method = o->rq_method)) MSG_STRING_DUP(b, rq->rq_method_name, o->rq_method_name); else rq->rq_method_name = o->rq_method_name; http_version_dup(&b, &rq->rq_version, o->rq_version); assert(b <= end); return b; } /** Create a request line object. * * Note that version string is not copied; it @b MUST remain constant during * lifetime of the @c http_request_t object. You can use constants * http_version_1_1 or http_version_1_0 declared in . */ http_request_t *http_request_create(su_home_t *home, http_method_t method, char const *name, url_string_t const *url, char const *version) { size_t xtra; http_request_t *rq; if (method) name = http_method_name(method, name); if (!name) return NULL; xtra = url_xtra(url->us_url) + (method ? 0 : strlen(name) + 1); rq = (void *)msg_header_alloc(home, http_request_class, (isize_t)xtra); if (rq) { char *b = (char *)(rq + 1), *end = b + xtra; rq->rq_method = method; rq->rq_method_name = name; if (!method) MSG_STRING_DUP(b, rq->rq_method_name, name); URL_DUP(b, end, rq->rq_url, url->us_url); rq->rq_version = version ? version : HTTP_VERSION_CURRENT; assert(b == end); } return rq; } msg_hclass_t http_request_class[] = HTTP_HEADER_CLASS(request, NULL, rq_common, single_critical, request); /* ====================================================================== */ /**@HTTP_HEADER http_status HTTP status line. * * The HTTP status line contains the HTTP protocol version, a reason code * (100..599) and reason phrase. */ /** Parse status line */ issize_t http_status_d(su_home_t *home, http_header_t *h, char *s, isize_t slen) { http_status_t *st = (http_status_t *)h; char *status, *phrase; uint32_t code; if (msg_firstline_d(s, &status, &phrase) < 0 || http_version_d(&s, &st->st_version) < 0 || *s || msg_uint32_d(&status, &code) == -1 || status[0]) return -1; st->st_status = code; st->st_phrase = phrase; return 0; } issize_t http_status_e(char b[], isize_t bsiz, http_header_t const *h, int flags) { http_status_t const *st = (http_status_t const *)h; char const *phrase = st->st_phrase; if (phrase == NULL) phrase = ""; if (st->st_version) return snprintf(b, bsiz, "%s %03u %s" CRLF, st->st_version, st->st_status, phrase); else return snprintf(b, bsiz, "%03u %s" CRLF, st->st_status, phrase); } /** Extra size of a http_status_t object. */ isize_t http_status_dup_xtra(http_header_t const *h, isize_t offset) { http_status_t const *st = (http_status_t const *)h; if (st->st_version) offset += http_version_xtra(st->st_version); offset += MSG_STRING_SIZE(st->st_phrase); return offset; } /** Duplicate one status header. */ char *http_status_dup_one(http_header_t *dst, http_header_t const *src, char *b, isize_t xtra) { http_status_t *st = (http_status_t *)dst; http_status_t const *o = (http_status_t const *)src; char *end = b + xtra; if (o->st_version) http_version_dup(&b, &st->st_version, o->st_version); st->st_status = o->st_status; MSG_STRING_DUP(b, st->st_phrase, o->st_phrase); assert(b <= end); (void)end; return b; } /** Create a status line object. * * Note that version is not copied; it @b MUST remain constant during * lifetime of the @c http_status_t object. */ http_status_t *http_status_create(su_home_t *home, unsigned status, char const *phrase, char const *version) { http_status_t *st; if (phrase == NULL && (phrase = http_status_phrase(status)) == NULL) return NULL; st = (void *) msg_header_alloc(home, http_status_class, 0); if (st) { st->st_status = status; st->st_phrase = phrase; st->st_version = version ? version : HTTP_VERSION_CURRENT; } return st; } msg_hclass_t http_status_class[] = HTTP_HEADER_CLASS(status, NULL, st_common, single_critical, status); /* ====================================================================== */ /**@HTTP_HEADER http_accept Accept header. * * We use MIME Accept header. */ /* ====================================================================== */ /**@HTTP_HEADER http_accept_charset Accept-Charset header. * * We use MIME Accept-Charset header. */ /* ====================================================================== */ /**@HTTP_HEADER http_accept_encoding Accept-Encoding header. * * We use MIME Accept-Encoding header. */ /* ====================================================================== */ /**@HTTP_HEADER http_accept_language Accept-Language header. * * We use MIME Accept-Language header. */ /* ====================================================================== */ /**@HTTP_HEADER http_accept_ranges Accept-Ranges header. */ #define http_accept_ranges_d msg_list_d #define http_accept_ranges_e msg_list_e msg_hclass_t http_accept_ranges_class[] = HTTP_HEADER_CLASS_LIST(accept_ranges, "Accept-Ranges", list); /* ====================================================================== */ /**@HTTP_HEADER http_age Age header. */ #define http_age_d msg_numeric_d #define http_age_e msg_numeric_e #define http_age_dup_xtra msg_default_dup_xtra #define http_age_dup_one msg_default_dup_one msg_hclass_t http_age_class[] = HTTP_HEADER_CLASS(age, "Age", x_common, single, age); /* ====================================================================== */ /**@HTTP_HEADER http_allow Allow header. */ #define http_allow_d msg_list_d #define http_allow_e msg_list_e msg_hclass_t http_allow_class[] = HTTP_HEADER_CLASS_LIST(allow, "Allow", list); /* ====================================================================== */ /**@HTTP_HEADER http_authentication_info Authentication-Info header. * @sa RFC 2617 */ #define http_authentication_info_d msg_list_d #define http_authentication_info_e msg_list_e #define http_authentication_info_dup_xtra msg_list_dup_xtra #define http_authentication_info_dup_one msg_list_dup_one msg_hclass_t http_authentication_info_class[] = HTTP_HEADER_CLASS(authentication_info, "Authentication-Info", ai_params, list, authentication_info); /* ====================================================================== */ /**@HTTP_HEADER http_authorization Authorization header. * * We use MIME Authorization header. */ #define http_authorization_d msg_auth_d #define http_authorization_e msg_auth_e msg_hclass_t http_authorization_class[] = HTTP_HEADER_CLASS_AUTH(authorization, "Authorization", single); /* ====================================================================== */ /**@HTTP_HEADER http_cache_control Cache-Control header. */ #define http_cache_control_d msg_list_d #define http_cache_control_e msg_list_e msg_hclass_t http_cache_control_class[] = HTTP_HEADER_CLASS_LIST(cache_control, "Cache-Control", list); /* ====================================================================== */ /**@HTTP_HEADER http_connection Connection header. */ #define http_connection_d msg_list_d #define http_connection_e msg_list_e msg_hclass_t http_connection_class[] = HTTP_HEADER_CLASS_LIST(connection, "Connection", list_critical); /* ====================================================================== */ /**@HTTP_HEADER http_content_encoding Content-Encoding header. * * We use MIME Content-Encoding header. */ /* ====================================================================== */ /**@HTTP_HEADER http_content_language Content-Language header. * * We use MIME Content-Language header. */ /* ====================================================================== */ /**@HTTP_HEADER http_content_length Content-Length header. * * We use MIME Content-Length header. */ /* ====================================================================== */ /**@HTTP_HEADER http_content_location Content-Location header. * * We use MIME Content-Location header. */ /* ====================================================================== */ /**@HTTP_HEADER http_content_md5 Content-MD5 header. * * We use MIME Content-MD5 header. */ /* ====================================================================== */ /**@HTTP_HEADER http_content_range Content-Range header. * * The Content-Range entity-header is sent with a partial entity-body to * specify where in the full entity-body the partial body should be * applied. Its syntax is defined in [H14.16] as follows: * * @code * Content-Range = "Content-Range" ":" content-range-spec * content-range-spec = byte-content-range-spec * byte-content-range-spec = bytes-unit SP * byte-range-resp-spec "/" * ( instance-length | "*" ) * * byte-range-resp-spec = (first-byte-pos "-" last-byte-pos) * | "*" * instance-length = 1*DIGIT * @endcode * */ /**@ingroup http_content_range * @typedef typedef struct http_content_range_s http_content_range_t; * * The structure #http_content_range_t contains representation of * @b Content-Range header. * * The #http_content_range_t is defined as follows: * @code * typedef struct { * msg_common_t cr_common[1]; * msg_error_t *cr_next; * off_t cr_first; // First-byte-pos * off_t cr_last; // Last-byte-pos * off_t cr_length; // Instance-length * } http_content_range_t; * @endcode */ issize_t http_content_range_d(su_home_t *home, http_header_t *h, char *s, isize_t slen) { http_content_range_t *cr = (http_content_range_t *)h; if (!su_casenmatch(s, "bytes", 5)) return -1; s += 5; skip_lws(&s); if (s[0] == '*') { cr->cr_first = cr->cr_last = (http_off_t)-1; s++; skip_lws(&s); } else { if (msg_delta_d((char const **)&s, &cr->cr_first) < 0) return -1; if (s[0] != '-') return -1; s++; skip_lws(&s); if (msg_delta_d((char const **)&s, &cr->cr_last) < 0) return -1; } if (s[0] != '/') return -1; s++; skip_lws(&s); if (s[0] == '*') { cr->cr_length = (http_off_t)-1; s++; skip_lws(&s); } else { if (msg_delta_d((char const **)&s, &cr->cr_length) < 0) return -1; } return s[0] ? -1 : 0; } issize_t http_content_range_e(char b[], isize_t bsiz, http_header_t const *h, int f) { http_content_range_t const *cr = (http_content_range_t const *)h; if (cr->cr_first == (http_off_t)-1) { if (cr->cr_length == (http_off_t)-1) return snprintf(b, bsiz, "bytes */*"); else return snprintf(b, bsiz, "bytes */%lu", cr->cr_length); } else { if (cr->cr_length == (http_off_t)-1) return snprintf(b, bsiz, "bytes %lu-%lu/*", cr->cr_first, cr->cr_last); else return snprintf(b, bsiz, "bytes %lu-%lu/%lu", cr->cr_first, cr->cr_last, cr->cr_length); } } msg_hclass_t http_content_range_class[] = HTTP_HEADER_CLASS(content_range, "Content-Range", cr_common, single, default); /* ====================================================================== */ /**@HTTP_HEADER http_content_type Content-Type header. * * We use MIME Content-Type header. */ /* ====================================================================== */ /**@HTTP_HEADER http_date Date header. * * The Date header field reflects the time when the request or response was * first sent. Its syntax is defined in [H14.18] as * follows: * * @code * Date = "Date" HCOLON HTTP-date * HTTP-date = rfc1123-date * rfc1123-date = wkday "," SP date1 SP time SP "GMT" * date1 = 2DIGIT SP month SP 4DIGIT * ; day month year (e.g., 02 Jun 1982) * time = 2DIGIT ":" 2DIGIT ":" 2DIGIT * ; 00:00:00 - 23:59:59 * wkday = "Mon" / "Tue" / "Wed" * / "Thu" / "Fri" / "Sat" / "Sun" * month = "Jan" / "Feb" / "Mar" / "Apr" * / "May" / "Jun" / "Jul" / "Aug" * / "Sep" / "Oct" / "Nov" / "Dec" * @endcode * */ /**@ingroup http_date * @typedef typedef struct http_date_s http_date_t; * * The structure #http_date_t contains representation of @b Date header. * * The #http_date_t is defined as follows: * @code * typedef struct { * msg_common_t d_common[1]; // Common fragment info * msg_error_t *d_next; // Link to next (dummy) * http_time_t d_time; // Seconds since Jan 1, 1900 * } http_date_t; * @endcode */ issize_t http_date_d(su_home_t *home, http_header_t *h, char *s, isize_t slen) { http_date_t *date = (http_date_t *)h; if (msg_date_d((char const **)&s, &date->d_time) < 0 || *s) return -1; else return 0; } issize_t http_date_e(char b[], isize_t bsiz, http_header_t const *h, int f) { http_date_t const *date = (http_date_t const *)h; return msg_date_e(b, bsiz, date->d_time); } /**@ingroup http_date * @brief Create an @b Date header object. * * The function http_date_create() creates a Date header object with the * date @a date. If @date is 0, current time (as returned by msg_now()) is * used. * * @param home memory home * @param date date expressed as seconds since Mon, 01 Jan 1900 00:00:00 * * @return * The function http_date_create() returns a pointer to newly created * @b Date header object when successful, or NULL upon an error. */ http_date_t *http_date_create(su_home_t *home, http_time_t date) { http_date_t *d = (void *)msg_header_alloc(home, http_date_class, 0); if (d) { if (date == 0) date = msg_now(); d->d_time = date; } return d; } msg_hclass_t http_date_class[] = HTTP_HEADER_CLASS(date, "Date", d_common, single, default); /* ====================================================================== */ /**@HTTP_HEADER http_etag ETag header. */ #define http_etag_d msg_generic_d #define http_etag_e msg_generic_e msg_hclass_t http_etag_class[] = HTTP_HEADER_CLASS_G(etag, "ETag", single); /* ====================================================================== */ /**@HTTP_HEADER http_expect Expect header. */ #define http_expect_d msg_generic_d #define http_expect_e msg_generic_e msg_hclass_t http_expect_class[] = HTTP_HEADER_CLASS_G(expect, "Expect", single); /* ====================================================================== */ /**@HTTP_HEADER http_expires Expires header. * * The Expires header field gives the date and time after which the message * content expires. Its syntax is defined in RFC 1428 section 14.21 as * follows: * * @code * Expires = "Expires:" HTTP-date * @endcode * */ /**@ingroup http_expires * @typedef typedef struct http_expires_s http_expires_t; * * The structure #http_expires_t contains representation of @b Expires * header. * * The #http_expires_t is defined as follows: * @code * typedef struct { * msg_common_t d_common[1]; // Common fragment info * msg_error_t *d_next; // Link to next (dummy) * http_time_t d_time; // Seconds since Jan 1, 1900 * } http_expires_t; * @endcode */ #define http_expires_d http_date_d #define http_expires_e http_date_e msg_hclass_t http_expires_class[] = HTTP_HEADER_CLASS(expires, "Expires", d_common, single, default); /* ====================================================================== */ /**@HTTP_HEADER http_from From header. * * @code * From = "From" ":" mailbox * @endcode */ #define http_from_d msg_generic_d #define http_from_e msg_generic_e msg_hclass_t http_from_class[] = HTTP_HEADER_CLASS_G(from, "From", single); /* ====================================================================== */ /**@HTTP_HEADER http_host Host header. * * @code * Host = "Host" ":" host [ ":" port ] * @endcode */ /** Parse Host header */ issize_t http_host_d(su_home_t *home, http_header_t *h, char *s, isize_t slen) { http_host_t *host = (http_host_t *)h; if (msg_hostport_d(&s, &host->h_host, &host->h_port) < 0 || *s) return -1; return 0; } /** Print Host header */ issize_t http_host_e(char b[], isize_t bsiz, http_header_t const *h, int flags) { http_host_t const *host = (http_host_t const *)h; char *b0 = b, *end = b + bsiz; MSG_STRING_E(b, end, host->h_host); if (host->h_port) { MSG_CHAR_E(b, end, ':'); MSG_STRING_E(b, end, host->h_port); } return b - b0; } /** Extra size of a http_host_t object. */ static isize_t http_host_dup_xtra(http_header_t const *h, isize_t offset) { http_host_t const *host = (http_host_t const *)h; offset += MSG_STRING_SIZE(host->h_host); offset += MSG_STRING_SIZE(host->h_port); return offset; } /** Duplicate one Host header. */ static char *http_host_dup_one(http_header_t *dst, http_header_t const *src, char *b, isize_t xtra) { http_host_t *h = (http_host_t *)dst; http_host_t const *o = (http_host_t const *)src; char *end = b + xtra; MSG_STRING_DUP(b, h->h_host, o->h_host); MSG_STRING_DUP(b, h->h_port, o->h_port); assert(b <= end); (void)end; return b; } /**Create a Host object. */ http_host_t *http_host_create(su_home_t *home, char const *host, char const *port) { http_host_t h[1]; http_host_init(h); h->h_host = host, h->h_port = port; if (host) { return http_host_dup(home, h); } else return NULL; } msg_hclass_t http_host_class[] = HTTP_HEADER_CLASS(host, "Host", h_common, single, host); /* ====================================================================== */ /**@HTTP_HEADER http_if_match If-Match header. */ #define http_if_match_d msg_list_d #define http_if_match_e msg_list_e msg_hclass_t http_if_match_class[] = HTTP_HEADER_CLASS_LIST(if_match, "If-Match", list); /* ====================================================================== */ /**@HTTP_HEADER http_if_modified_since If-Modified-Since header. * * The If-Modified-Since header field The If-Modified-Since request-header * field is used with a method to make it conditional: if the requested * variant has not been modified since the time specified in this field, an * entity will not be returned from the server; instead, a 304 (not * modified) response will be returned without any message-body. Its syntax * is defined in RFC 2616 secion 14.25 as follows: * * @code * If-Modified-Since = "If-Modified-Since" ":" HTTP-date * @endcode * */ /**@ingroup http_if_modified_since * @typedef typedef struct http_if_modified_since_s http_if_modified_since_t; * * The structure #http_if_modified_since_t contains representation of * @b If-Modified-Since header. * * The #http_if_modified_since_t is defined as follows: * @code * typedef struct { * msg_common_t d_common[1]; // Common fragment info * msg_error_t *d_next; // Link to next (dummy) * http_time_t d_time; // Seconds since Jan 1, 1900 * } http_if_modified_since_t; * @endcode */ #define http_if_modified_since_d http_date_d #define http_if_modified_since_e http_date_e msg_hclass_t http_if_modified_since_class[] = HTTP_HEADER_CLASS(if_modified_since, "If-Modified-Since", d_common, single, default); /* ====================================================================== */ /**@HTTP_HEADER http_if_none_match If-None-Match header. */ #define http_if_none_match_d msg_list_d #define http_if_none_match_e msg_list_e msg_hclass_t http_if_none_match_class[] = HTTP_HEADER_CLASS_LIST(if_none_match, "If-None-Match", list); /* ====================================================================== */ /**@HTTP_HEADER http_if_range If-Range header. * * The @b If-Range header is used when a client has a partial copy of an * entity in its cache, and wishes to have an up-to-date copy of the entire * entity. Informally, its meaning is `if the entity is unchanged, send * me the part(s) that I am missing; otherwise, send me the entire new * entity'. Its syntax is defined in RFC 2616 as follows: * * @code * If-Range = "If-Range" ":" ( entity-tag / HTTP-date ) * @endcode */ /** Parse If-Range header */ issize_t http_if_range_d(su_home_t *home, http_header_t *h, char *s, isize_t slen) { http_if_range_t *ifr = (http_if_range_t *)h; if (s[0] == '"' || su_casenmatch(s, "W/\"", 3)) { ifr->ifr_tag = s; return 0; } else { return msg_date_d((char const **)&s, &ifr->ifr_time); } } /** Print If-Range header */ issize_t http_if_range_e(char b[], isize_t bsiz, http_header_t const *h, int flags) { http_if_range_t const *ifr = (http_if_range_t const *)h; char *b0 = b, *end = b + bsiz; if (ifr->ifr_tag) { MSG_STRING_E(b, end, ifr->ifr_tag); return b - b0; } else { return msg_date_e(b, bsiz, ifr->ifr_time); } } /** Extra size of a http_if_range_t object. */ static isize_t http_if_range_dup_xtra(http_header_t const *h, isize_t offset) { http_if_range_t const *ifr = (http_if_range_t const *)h; offset += MSG_STRING_SIZE(ifr->ifr_tag); return offset; } /** Duplicate one If-Range header. */ static char *http_if_range_dup_one(http_header_t *dst, http_header_t const *src, char *b, isize_t xtra) { http_if_range_t *ifr = (http_if_range_t *)dst; http_if_range_t const *o = (http_if_range_t const *)src; char *end = b + xtra; MSG_STRING_DUP(b, ifr->ifr_tag, o->ifr_tag); ifr->ifr_time = o->ifr_time; assert(b <= end); (void)end; return b; } msg_hclass_t http_if_range_class[] = HTTP_HEADER_CLASS(if_range, "If-Range", ifr_common, single, if_range); /* ====================================================================== */ /**@HTTP_HEADER http_if_unmodified_since If-Unmodified-Since header. * * The @b If-Unmodified-Since header is used with a method to make it * conditional. If the requested resource has not been modified since the * time specified in this field, the server SHOULD perform the requested * operation as if the If-Unmodified-Since header were not present. Its * syntax is defined in RFC 2616 14.28 as follows: * * @code * If-Unmodified-Since = "If-Unmodified-Since:" HTTP-date * @endcode * */ /**@ingroup http_if_unmodified_since * @typedef typedef http_date_t http_if_unmodified_since_t; * * The structure #http_if_unmodified_since_t contains representation of * @b If-Unmodified-Since header. * * The #http_if_unmodified_since_t is defined as follows: * @code * typedef struct { * msg_common_t d_common[1]; // Common fragment info * msg_error_t *d_next; // Link to next (dummy) * http_time_t d_time; // Seconds since Jan 1, 1900 * } http_if_unmodified_since_t; * @endcode */ #define http_if_unmodified_since_d http_date_d #define http_if_unmodified_since_e http_date_e msg_hclass_t http_if_unmodified_since_class[] = HTTP_HEADER_CLASS(if_unmodified_since, "If-Unmodified-Since", d_common, single, default); /* ====================================================================== */ /**@HTTP_HEADER http_last_modified Last-Modified header. * * The Last-Modified header field gives the date and time after which the * message content last_modified. Its syntax is defined in [] as follows: * * @code * Last-Modified = "Last-Modified:" HTTP-date * @endcode * */ /**@ingroup http_last_modified * @typedef typedef struct http_last_modified_s http_last_modified_t; * * The structure #http_last_modified_t contains representation of @b * Last-Modified header. * * The #http_last_modified_t is defined as follows: * @code * typedef struct { * msg_common_t d_common[1]; // Common fragment info * msg_error_t *d_next; // Link to next (dummy) * http_time_t d_time; // Seconds since Jan 1, 1900 * } http_last_modified_t; * @endcode */ #define http_last_modified_d http_date_d #define http_last_modified_e http_date_e msg_hclass_t http_last_modified_class[] = HTTP_HEADER_CLASS(last_modified, "Last-Modified", d_common, single, default); /* ====================================================================== */ /**@HTTP_HEADER http_location Location Header * * The Location header is used to redirect the recipient to a location other * than the Request-URI for completion of the request or identification of a * new resource. Its syntax is defined in RFC 2616 section 14.30 as follows: * * @code * Location = "Location" ":" absoluteURI * @endcode * */ /**@ingroup http_location * * @typedef typedef struct http_location_s http_location_t; * * The structure http_location_t contains representation of @b Location * header. * * The http_location_t is defined as follows: * @code * typedef struct http_location_s * { * msg_common_t loc_common[1]; * msg_error_t *loc_next; * url_t loc_url[1]; * } http_location_t; * @endcode */ /** Decode (parse) a Location header */ issize_t http_location_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { http_location_t *loc = (http_location_t *)h; return url_d(loc->loc_url, s); } /** Encode (print) a Location header */ issize_t http_location_e(char b[], isize_t bsiz, msg_header_t const *h, int flags) { http_location_t const *loc = (http_location_t *)h; return url_e(b, bsiz, loc->loc_url); } /** Calculate extra storage used by Location header field */ isize_t http_location_dup_xtra(msg_header_t const *h, isize_t offset) { http_location_t const *loc = (http_location_t *)h; offset += url_xtra(loc->loc_url); return offset; } /** Duplicate a Location header field */ char *http_location_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra) { http_location_t *loc = (http_location_t *)dst; http_location_t const *o = (http_location_t const *)src; char *end = b + xtra; URL_DUP(b, end, loc->loc_url, o->loc_url); assert(b <= end); return b; } msg_hclass_t http_location_class[] = HTTP_HEADER_CLASS(location, "Location", loc_common, single, location); /* ====================================================================== */ /**@HTTP_HEADER http_max_forwards Max-Forwards header. */ #define http_max_forwards_d msg_numeric_d #define http_max_forwards_e msg_numeric_e msg_hclass_t http_max_forwards_class[] = HTTP_HEADER_CLASS(max_forwards, "Max-Forwards", mf_common, single, numeric); /* ====================================================================== */ /**@HTTP_HEADER http_pragma Pragma header. */ #define http_pragma_d msg_list_d #define http_pragma_e msg_list_e msg_hclass_t http_pragma_class[] = HTTP_HEADER_CLASS_LIST(pragma, "Pragma", list); /* ====================================================================== */ /**@HTTP_HEADER http_proxy_authenticate Proxy-Authenticate header. */ #define http_proxy_authenticate_d msg_auth_d #define http_proxy_authenticate_e msg_auth_e msg_hclass_t http_proxy_authenticate_class[] = HTTP_HEADER_CLASS_AUTH(proxy_authenticate, "Proxy-Authenticate", append); /* ====================================================================== */ /**@HTTP_HEADER http_proxy_authorization Proxy-Authorization header. */ #define http_proxy_authorization_d msg_auth_d #define http_proxy_authorization_e msg_auth_e msg_hclass_t http_proxy_authorization_class[] = HTTP_HEADER_CLASS_AUTH(proxy_authorization, "Proxy-Authorization", append); /* ====================================================================== */ /**@HTTP_HEADER http_range Range header. * * The Range header is used to GET one or more sub-ranges of an entity * instead of the entire entity. Its syntax is defined in RFC 2616 section * 14.35 as follows: * * @code * Range = "Range" ":" ranges-specifier * ranges-specifier = byte-ranges-specifier * byte-ranges-specifier = bytes-unit "=" byte-range-set * byte-range-set = 1#( byte-range-spec | suffix-byte-range-spec ) * byte-range-spec = first-byte-pos "-" [last-byte-pos] * first-byte-pos = 1*DIGIT * last-byte-pos = 1*DIGIT * @endcode * */ /**@ingroup http_range * * @typedef typedef struct http_range_s http_range_t; * * The structure http_range_t contains representation of @b Range header. * * The http_range_t is defined as follows: * @code * typedef struct http_range_s * { * msg_common_t rng_common[1]; * msg_error_t *rng_next; * char const *rng_unit; * char const * const *rng_specs; * } http_range_t; * @endcode */ static issize_t range_spec_scan(char *start); /** Decode (parse) a Range header */ issize_t http_range_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { http_range_t *rng = (http_range_t *)h; rng->rng_unit = s; skip_token(&s); if (s == rng->rng_unit) return -1; if (IS_LWS(*s)) { *s++ = '\0'; skip_lws(&s); } if (*s != '=') return -1; *s++ = '\0'; skip_lws(&s); /* XXX - use range-scanner */ return msg_commalist_d(home, &s, &rng->rng_specs, range_spec_scan); } /** Scan and compact a range spec. */ static issize_t range_spec_scan(char *start) { size_t tlen; char *s, *p; s = p = start; if (s[0] == ',') return 0; /* Three forms: 1*DIGIT "-" 1*DIGIT | 1*DIGIT "-" | "-" 1*DIGIT */ if (*s != '-') { tlen = span_digit(s); if (tlen == 0) return -1; p += tlen; s += tlen; skip_lws(&s); } if (*s != '-') return -1; if (p != s) *p = *s; p++, s++; skip_lws(&s); if (IS_DIGIT(*s)) { tlen = span_digit(s); if (tlen == 0) return -1; if (p != s) memmove(p, s, tlen); p += tlen; s += tlen; skip_lws(&s); } if (p != s) *p = '\0'; return s - start; } /** Encode (print) a Range header */ issize_t http_range_e(char b[], isize_t bsiz, msg_header_t const *h, int flags) { http_range_t const *rng = (http_range_t *)h; char *b0 = b, *end = b + bsiz; MSG_STRING_E(b, end, rng->rng_unit); MSG_CHAR_E(b, end, '='); MSG_COMMALIST_E(b, end, rng->rng_specs, MSG_IS_COMPACT(flags)); MSG_TERM_E(b, end); return b - b0; } /** Calculate extra storage used by Range header field */ isize_t http_range_dup_xtra(msg_header_t const *h, isize_t offset) { http_range_t const *rng = (http_range_t *)h; MSG_PARAMS_SIZE(offset, rng->rng_specs); offset += MSG_STRING_SIZE(rng->rng_unit); return offset; } /** Duplicate a Range header field */ char *http_range_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra) { http_range_t *rng = (http_range_t *)dst; http_range_t const *o = (http_range_t const *)src; char *end = b + xtra; b = msg_params_dup((msg_param_t const **)&rng->rng_specs, o->rng_specs, b, xtra); MSG_STRING_DUP(b, rng->rng_unit, o->rng_unit); assert(b <= end); (void)end; return b; } msg_hclass_t http_range_class[] = HTTP_HEADER_CLASS(range, "Range", rng_specs, single, range); /* ====================================================================== */ /**@HTTP_HEADER http_referer Referer header. * * The Referer header is used to redirect the recipient to a referer other * than the Request-URI for completion of the request or identification of a * new resource. Its syntax is defined in RFC 2616 section 14.30 as follows: * * @code * Referer = "Referer" ":" absoluteURI * @endcode * */ /**@ingroup http_referer * * @typedef typedef struct http_referer_s http_referer_t; * * The structure http_referer_t contains representation of @b Referer * header. * * The http_referer_t is defined as follows: * @code * typedef struct http_referer_s * { * msg_common_t loc_common[1]; * msg_error_t *loc_next; * url_t loc_url[1]; * } http_referer_t; * @endcode */ #define http_referer_d http_location_d #define http_referer_e http_location_e msg_hclass_t http_referer_class[] = HTTP_HEADER_CLASS(referer, "Referer", loc_common, single, location); /* ====================================================================== */ /**@HTTP_HEADER http_mime_version MIME-Version header. * * We use MIME MIME-Version header. */ /* ====================================================================== */ /**@HTTP_HEADER http_retry_after Retry-After header. * * The Retry-After response-header field can be used with a 503 (Service * Unavailable) response to indicate how long the service is expected to be * unavailable to the requesting client. This field MAY also be used with * any 3xx (Redirection) response to indicate the minimum time the * user-agent is asked wait before issuing the redirected request. Its * syntax is defined in RFC 2616 section 14.37 as follows: * * @code * Retry-After = "Retry-After" ":" ( HTTP-date / delta-seconds ) * @endcode * */ /**@ingroup http_retry_after * @typedef typedef struct http_retry_after_s http_retry_after_t; * * The structure #http_retry_after_t contains representation of @b * Retry-After header. * * The #http_retry_after_t is defined as follows: * @code * typedef struct { * msg_common_t ra_common[1]; // Common fragment info * msg_error_t *ra_next; // Link to next (dummy) * http_time_t ra_date; // When to retry * http_time_t ra_delta; // Seconds to before retry * } http_retry_after_t; * @endcode */ issize_t http_retry_after_d(su_home_t *home, http_header_t *h, char *s, isize_t slen) { http_retry_after_t *ra = (http_retry_after_t *)h; if (msg_date_delta_d((char const **)&s, &ra->ra_date, &ra->ra_delta) < 0 || *s) return -1; else return 0; } issize_t http_retry_after_e(char b[], isize_t bsiz, http_header_t const *h, int f) { http_retry_after_t const *ra = (http_retry_after_t const *)h; if (ra->ra_date) return msg_date_e(b, bsiz, ra->ra_date + ra->ra_delta); else return msg_delta_e(b, bsiz, ra->ra_delta); } msg_hclass_t http_retry_after_class[] = HTTP_HEADER_CLASS(retry_after, "Retry-After", ra_common, single, default); /* ====================================================================== */ /**@HTTP_HEADER http_server Server header. */ #define http_server_d msg_generic_d #define http_server_e msg_generic_e msg_hclass_t http_server_class[] = HTTP_HEADER_CLASS_G(server, "Server", single); /* ====================================================================== */ /**@HTTP_HEADER http_te TE header. * * The TE request-header field indicates what extension transfer-codings it * is willing to accept in the response and whether or not it is willing to * accept trailer fields in a chunked transfer-coding. Its value may consist * of the keyword "trailers" and/or a comma-separated list of extension * transfer-coding names with optional accept parameters. Its syntax is * defined in [H14.39] as follows: * * @code * TE = "TE" ":" #( t-codings ) * t-codings = "trailers" | ( transfer-extension [ accept-params ] ) * @endcode * */ /**@ingroup http_te * @typedef typedef strucy http_te_s http_te_t; * * The structure http_te_t contains representation of @b TE header. * * The http_te_t is defined as follows: * @code * typedef struct http_te_s { * } http_te_t; * @endcode */ su_inline void http_te_update(http_te_t *te) { te->te_q = msg_header_find_param(te->te_common, "q"); } issize_t http_te_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { msg_header_t **hh = &h->sh_succ, *h0 = h; http_te_t *te = (http_te_t *)h; assert(h); assert(sizeof(*h)); for (;*s;) { /* Ignore empty entries (comma-whitespace) */ if (*s == ',') { *s++ = '\0'; skip_lws(&s); continue; } if (!h) { /* Allocate next header structure */ if (!(h = msg_header_alloc(home, h0->sh_class, 0))) break; *hh = h; h->sh_prev = hh; hh = &h->sh_succ; te = te->te_next = (http_te_t *)h; } /* "TE:" #(transfer-extension ; *(parameters))) */ if (msg_token_d(&s, &te->te_extension) == -1) return -1; if (*s == ';' && msg_params_d(home, &s, &te->te_params) == -1) return -1; if (*s != '\0' && *s != ',') return -1; if (te->te_params) http_te_update(te); h = NULL; } return 0; } issize_t http_te_e(char b[], isize_t bsiz, msg_header_t const *h, int flags) { char *b0 = b, *end = b + bsiz; http_te_t const *te = (http_te_t *)h; assert(http_is_te(h)); MSG_STRING_E(b, end, te->te_extension); MSG_PARAMS_E(b, end, te->te_params, flags); MSG_TERM_E(b, end); return b - b0; } isize_t http_te_dup_xtra(msg_header_t const *h, isize_t offset) { http_te_t const *te = (http_te_t const *)h; MSG_PARAMS_SIZE(offset, te->te_params); offset += MSG_STRING_SIZE(te->te_extension); return offset; } /** Duplicate one http_te_t object */ char *http_te_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra) { http_te_t *te = (http_te_t *)dst; http_te_t const *o = (http_te_t const *)src; char *end = b + xtra; b = msg_params_dup(&te->te_params, o->te_params, b, xtra); MSG_STRING_DUP(b, te->te_extension, o->te_extension); if (te->te_params) http_te_update(te); assert(b <= end); (void)end; return b; } msg_hclass_t http_te_class[] = HTTP_HEADER_CLASS(te, "TE", te_params, append, te); /* ====================================================================== */ /**@HTTP_HEADER http_trailer Trailer header. */ #define http_trailer_d msg_list_d #define http_trailer_e msg_list_e msg_hclass_t http_trailer_class[] = HTTP_HEADER_CLASS_LIST(trailer, "Trailer", list_critical); /* ====================================================================== */ /**@HTTP_HEADER http_transfer_encoding Transfer-Encoding header. */ #define http_transfer_encoding_d msg_list_d #define http_transfer_encoding_e msg_list_e msg_hclass_t http_transfer_encoding_class[] = HTTP_HEADER_CLASS_LIST(transfer_encoding, "Transfer-Encoding", list_critical); /* ====================================================================== */ /**@HTTP_HEADER http_upgrade Upgrade header. */ #define http_upgrade_d msg_list_d #define http_upgrade_e msg_list_e msg_hclass_t http_upgrade_class[] = HTTP_HEADER_CLASS_LIST(upgrade, "Upgrade", list_critical); /* ====================================================================== */ /**@HTTP_HEADER http_user_agent User-Agent header. */ #define http_user_agent_d msg_generic_d #define http_user_agent_e msg_generic_e msg_hclass_t http_user_agent_class[] = HTTP_HEADER_CLASS_G(user_agent, "User-Agent", single); /* ====================================================================== */ /**@HTTP_HEADER http_vary Vary header. */ #define http_vary_d msg_list_d #define http_vary_e msg_list_e msg_hclass_t http_vary_class[] = HTTP_HEADER_CLASS_LIST(vary, "Vary", list); /* ====================================================================== */ /**@HTTP_HEADER http_via Via header. * * @code * Via = "Via" ":" 1#( received-protocol received-by [ comment ] ) * received-protocol = [ protocol-name "/" ] protocol-version * protocol-name = token * protocol-version = token * received-by = ( host [ ":" port ] ) | pseudonym * pseudonym = token * @endcode */ issize_t http_via_d(su_home_t *home, http_header_t *h, char *s, isize_t slen) { http_header_t **hh = &h->sh_succ, *h0 = h; http_via_t *v = (http_via_t *)h; assert(h && h->sh_class); for (;*s;) { /* Ignore empty entries (comma-whitespace) */ if (*s == ',') { *s++ = '\0'; skip_lws(&s); continue; } if (!h) { /* Allocate next header structure */ if (!(h = msg_header_alloc(home, h0->sh_class, 0))) return -1; *hh = h; h->sh_prev = hh; hh = &h->sh_succ; v = v->v_next = (http_via_t *)h; } if (http_version_d(&s, &v->v_version) == -1) /* Parse protocol version */ return -1; if (msg_hostport_d(&s, &v->v_host, &v->v_port) == -1) /* Host (and port) */ return -1; if (*s == '(' && msg_comment_d(&s, &v->v_comment) == -1) /* Comment */ return -1; if (*s != '\0' && *s != ',') /* Extra before next header field? */ return -1; h = NULL; } if (h) /* List without valid header via */ return -1; return 0; } issize_t http_via_e(char b[], isize_t bsiz, http_header_t const *h, int flags) { int const compact = MSG_IS_COMPACT(flags); char *b0 = b, *end = b + bsiz; http_via_t const *v = (http_via_t const *)h; MSG_STRING_E(b, end, v->v_version); MSG_CHAR_E(b, end, ' '); MSG_STRING_E(b, end, v->v_host); if (v->v_port) { MSG_CHAR_E(b, end, ':'); MSG_STRING_E(b, end, v->v_port); } if (v->v_comment) { if (!compact) MSG_CHAR_E(b, end, ' '); MSG_CHAR_E(b, end, '('); MSG_STRING_E(b, end, v->v_comment); MSG_CHAR_E(b, end, ')'); } MSG_TERM_E(b, end); return b - b0; } static isize_t http_via_dup_xtra(http_header_t const *h, isize_t offset) { http_via_t const *v = (http_via_t const *)h; offset += MSG_STRING_SIZE(v->v_version); offset += MSG_STRING_SIZE(v->v_host); offset += MSG_STRING_SIZE(v->v_port); offset += MSG_STRING_SIZE(v->v_comment); return offset; } /** Duplicate one http_via_t object */ static char *http_via_dup_one(http_header_t *dst, http_header_t const *src, char *b, isize_t xtra) { http_via_t *v = (http_via_t *)dst; http_via_t const *o = (http_via_t const *)src; char *end = b + xtra; MSG_STRING_DUP(b, v->v_version, o->v_version); MSG_STRING_DUP(b, v->v_host, o->v_host); MSG_STRING_DUP(b, v->v_port, o->v_port); MSG_STRING_DUP(b, v->v_comment, o->v_comment); assert(b <= end); (void)end; return b; } msg_hclass_t http_via_class[] = HTTP_HEADER_CLASS(via, "Via", v_common, prepend, via); /* ====================================================================== */ /**@HTTP_HEADER http_warning Warning header. */ #define http_warning_d msg_warning_d #define http_warning_e msg_warning_e #define http_warning_dup_xtra msg_warning_dup_xtra #define http_warning_dup_one msg_warning_dup_one msg_hclass_t http_warning_class[] = HTTP_HEADER_CLASS(warning, "Warning", w_common, append, warning); /* ====================================================================== */ /**@HTTP_HEADER http_www_authenticate WWW-Authenticate header. */ #define http_www_authenticate_d msg_auth_d #define http_www_authenticate_e msg_auth_e msg_hclass_t http_www_authenticate_class[] = HTTP_HEADER_CLASS_AUTH(www_authenticate, "WWW-Authenticate", single); /* ====================================================================== */ /**@HTTP_HEADER http_error Erroneous headers. * * We use erroneous header object from @b msg module. */ /* ====================================================================== */ /**@HTTP_HEADER http_unknown Unknown headers. * * We use unknown header object from @b msg module. */ /* ====================================================================== */ /**@HTTP_HEADER http_separator Header separator. * * We use header separator object from @b msg module. */ /* ====================================================================== */ /**@HTTP_HEADER http_payload Message payload. * * We use message body object from @b msg module. */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/http/http_extra.c000066400000000000000000000263051223300710500230650ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE http_extra.c * * Extra HTTP headers * * @author Pekka Pessi * * @date Created: Tue Jun 13 02:57:51 2000 ppessi */ #include "config.h" #include /* Avoid casting http_t to msg_pub_t and http_header_t to msg_header_t */ #define MSG_PUB_T struct http_s #define MSG_HDR_T union http_header_u #include "sofia-sip/http_parser.h" #include #include #include #include #include /* ========================================================================== */ /**@HTTP_HEADER http_proxy_connection Proxy-Connection extension header. */ #define http_proxy_connection_d msg_list_d #define http_proxy_connection_e msg_list_e msg_hclass_t http_proxy_connection_class[] = HTTP_HEADER_CLASS_LIST(proxy_connection, "Proxy-Connection", list); /* ====================================================================== */ /**@HTTP_HEADER http_cookie Cookie extension header. * * The Cookie header is used to transmit state information from server * back to the http client. Its syntax is defined in RFC 2109 section 4.3.4 * as follows: * * @code * cookie = "Cookie:" cookie-version * 1*((";" | ",") cookie-value) * cookie-value = NAME "=" VALUE [";" path] [";" domain] * cookie-version = "$Version" "=" value * NAME = attr * VALUE = value * path = "$Path" "=" value * domain = "$Domain" "=" value * @endcode * */ /**@ingroup http_cookie * * @typedef typedef struct http_cookie_s http_cookie_t; * * The structure http_cookie_t contains representation of @b Cookie * header. Please note that a single http_cookie_t can contain many * cookies. * * The http_cookie_t is defined as follows: * @code * typedef struct http_cookie_s * { * } http_cookie_t; * @endcode */ /**Update Cookie parameters. * * The function http_cookie_update() updates a @b Cookie parameter * shortcuts. * * @param sc pointer to a @c http_cookie_t object */ su_inline void http_cookie_update(http_cookie_t *c) { size_t i; c->c_name = NULL; c->c_version = NULL, c->c_domain = NULL, c->c_path = NULL; if (!c->c_params) return; if (!(MSG_PARAM_MATCH(c->c_version, c->c_params[0], "$Version"))) return; if (!c->c_params[1] || c->c_params[1][0] == '$') return; c->c_name = c->c_params[1]; for (i = 2; ; i++) { msg_param_t p = c->c_params[i]; if (!p || *p++ != '$') break; switch (p[0]) { case 'd': case 'D': MSG_PARAM_MATCH(c->c_domain, p, "Domain"); break; case 'p': case 'P': MSG_PARAM_MATCH(c->c_path, p, "Path"); break; } } } /* Scan a cookie parameter */ static issize_t cookie_scanner(char *s) { char *p = s; size_t tlen; skip_token(&s); if (s == p) /* invalid parameter name */ return -1; tlen = s - p; if (IS_LWS(*s)) { *s++ = '\0'; skip_lws(&s); } if (*s == '=') { char *v; s++; skip_lws(&s); v = s; /* get value */ if (*s == '"') { size_t qlen = span_quoted(s); if (!qlen) return -1; s += qlen; } else { s += strcspn(s, ",;" LWS); if (s == v) return -1; } if (p + tlen + 1 != v) { memmove(p + tlen + 1, v, s - v); p[tlen] = '='; p[tlen + 1 + (s - v)] = '\0'; } } if (IS_LWS(*s)) { *s++ = '\0'; skip_lws(&s); } return s - p; } /** Decode (parse) a Cookie header */ issize_t http_cookie_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { http_cookie_t *c = (http_cookie_t *)h; assert(h); assert(sizeof(*h)); for (;*s;) { /* Ignore empty entries (comma-whitespace) */ if (*s == ',') { *s++ = '\0'; skip_lws(&s); continue; } if (msg_any_list_d(home, &s, (msg_param_t **)&c->c_params, cookie_scanner, ';') == -1) return -1; if (*s != '\0' && *s != ',') return -1; if (!c->c_params) return -1; } http_cookie_update(c); return 0; } /** Encode (print) a Cookie header */ issize_t http_cookie_e(char b[], isize_t bsiz, msg_header_t const *h, int flags) { char *b0 = b, *end = b + bsiz; http_cookie_t const *c = (http_cookie_t *)h; size_t i; if (c->c_params) { for (i = 0; c->c_params[i]; i++) { if (i > 0) MSG_CHAR_E(b, end, ';'); MSG_STRING_E(b, end, c->c_params[i]); } } MSG_TERM_E(b, end); return b - b0; } /** Calculate extra storage used by Cookie header field */ isize_t http_cookie_dup_xtra(msg_header_t const *h, isize_t offset) { http_cookie_t const *c = (http_cookie_t *)h; MSG_PARAMS_SIZE(offset, c->c_params); return offset; } /** Duplicate a Cookie header field */ char *http_cookie_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra) { http_cookie_t *c = (http_cookie_t *)dst; http_cookie_t const *o = (http_cookie_t const *)src; char *end = b + xtra; b = msg_params_dup(&c->c_params, o->c_params, b, xtra); http_cookie_update(c); assert(b <= end); (void)end; return b; } msg_hclass_t http_cookie_class[] = HTTP_HEADER_CLASS(cookie, "Cookie", c_params, append, cookie); /* ====================================================================== */ /**@HTTP_HEADER http_set_cookie Set-Cookie extension header. * * The Set-Cookie header is used to transmit state information from server * back to the http client. Its syntax is defined in RFC 2109 section 4.2.2 * as follows: * * @code * set-cookie = "Set-Cookie:" cookies * cookies = 1#cookie * cookie = NAME "=" VALUE *(";" cookie-av) * NAME = attr * VALUE = value * cookie-av = "Comment" "=" value * | "Domain" "=" value * | "Max-Age" "=" value * | "Path" "=" value * | "Secure" * | "Version" "=" 1*DIGIT * * @endcode * */ /**@ingroup http_set_cookie * * @typedef typedef struct http_set_cookie_s http_set_cookie_t; * * The structure http_set_cookie_t contains representation of @b Set-Cookie * header. * * The http_set_cookie_t is defined as follows: * @code * typedef struct http_set_cookie_s * { * } http_set_cookie_t; * @endcode */ /**Update Set-Cookie parameters. * * The function http_set_cookie_update() updates a @b Set-Cookie parameter * shortcuts. * * @param sc pointer to a @c http_set_cookie_t object */ su_inline void http_set_cookie_update(http_set_cookie_t *sc) { size_t i; sc->sc_name = NULL; sc->sc_version = NULL, sc->sc_domain = NULL, sc->sc_path = NULL; sc->sc_comment = NULL, sc->sc_max_age = NULL, sc->sc_secure = 0; if (!sc->sc_params) return; sc->sc_name = sc->sc_params[0]; for (i = 1; sc->sc_params[i]; i++) { msg_param_t p = sc->sc_params[i]; switch (p[0]) { case 'c': case 'C': MSG_PARAM_MATCH(sc->sc_comment, p, "Comment"); break; case 'd': case 'D': MSG_PARAM_MATCH(sc->sc_domain, p, "Domain"); break; case 'm': case 'M': MSG_PARAM_MATCH(sc->sc_max_age, p, "Max-Age"); break; case 'p': case 'P': MSG_PARAM_MATCH(sc->sc_path, p, "Path"); break; case 's': case 'S': MSG_PARAM_MATCH_P(sc->sc_secure, p, "Secure"); break; case 'v': case 'V': MSG_PARAM_MATCH(sc->sc_version, p, "Version"); break; } } } #include /* Scan a cookie parameter */ static issize_t set_cookie_scanner(char *s) { char *rest; #define LOOKING_AT(s, what) \ (su_casenmatch((s), what, strlen(what)) && (rest = s + strlen(what))) /* Special cases from Netscape spec */ if (LOOKING_AT(s, "expires=")) { msg_time_t value; msg_date_d((char const **)&rest, &value); } else if (LOOKING_AT(s, "path=/")) { for (;;) { rest += span_unreserved(rest); if (*rest != '/') break; rest++; } } else { return msg_attribute_value_scanner(s); } #undef LOOKING_AT if (IS_LWS(*rest)) { *rest++ = '\0'; skip_lws(&rest); } return rest - s; } /** Decode (parse) Set-Cookie header */ issize_t http_set_cookie_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { msg_header_t **hh = &h->sh_succ, *h0 = h; http_set_cookie_t *sc = (http_set_cookie_t *)h; msg_param_t *params; assert(h); assert(sizeof(*h)); for (;*s;) { /* Ignore empty entries (comma-whitespace) */ if (*s == ',') { *s++ = '\0'; skip_lws(&s); continue; } if (!h) { /* Allocate next header structure */ if (!(h = msg_header_alloc(home, h0->sh_class, 0))) return -1; *hh = h; h->sh_prev = hh; hh = &h->sh_succ; sc = sc->sc_next = (http_set_cookie_t *)h; } /* "Set-Cookie:" 1#(NAME "=" VALUE *(";" cookie-av))) */ params = su_zalloc(home, MSG_PARAMS_NUM(1) * sizeof(msg_param_t)); if (!params) return -1; params[0] = s, sc->sc_params = params; s += strcspn(s, ",;" LWS); if (*s) { *s++ = '\0'; skip_lws(&s); if (*s && msg_any_list_d(home, &s, (msg_param_t **)&sc->sc_params, set_cookie_scanner, ';') == -1) return -1; } if (*s != '\0' && *s != ',') return -1; if (sc->sc_params) http_set_cookie_update(sc); h = NULL; } return 0; } /** Encode (print) Set-Cookie header */ issize_t http_set_cookie_e(char b[], isize_t bsiz, msg_header_t const *h, int flags) { char *b0 = b, *end = b + bsiz; http_set_cookie_t const *sc = (http_set_cookie_t *)h; size_t i; if (sc->sc_params) { for (i = 0; sc->sc_params[i]; i++) { if (i > 0) MSG_CHAR_E(b, end, ';'); MSG_STRING_E(b, end, sc->sc_params[i]); } } MSG_TERM_E(b, end); return b - b0; } /** Calculate extra storage used by Set-Cookie header field */ isize_t http_set_cookie_dup_xtra(msg_header_t const *h, isize_t offset) { http_set_cookie_t const *sc = (http_set_cookie_t *)h; MSG_PARAMS_SIZE(offset, sc->sc_params); return offset; } /** Duplicate a Set-Cookie header field */ char *http_set_cookie_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra) { http_set_cookie_t *sc = (http_set_cookie_t *)dst; http_set_cookie_t const *o = (http_set_cookie_t const *)src; char *end = b + xtra; b = msg_params_dup(&sc->sc_params, o->sc_params, b, xtra); http_set_cookie_update(sc); assert(b <= end); (void)end; return b; } msg_hclass_t http_set_cookie_class[] = HTTP_HEADER_CLASS(set_cookie, "Set-Cookie", sc_params, append, set_cookie); sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/http/http_header.c000066400000000000000000000153461223300710500231750ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE http_header.c * * HTTP header handling. * * @author Pekka Pessi * * @date Created: Tue Jun 13 02:57:51 2000 ppessi */ #include "config.h" #include #include #include #include #include #include #include #include /* Avoid casting http_t to msg_pub_t and http_header_t to msg_header_t */ #define MSG_PUB_T struct http_s #define MSG_HDR_T union http_header_u #define HTTP_STATIC_INLINE #include "sofia-sip/http_parser.h" #include #include #ifndef UINT32_MAX #define UINT32_MAX (0xffffffffU) #endif /** Complete a HTTP request. */ int http_request_complete(msg_t *msg) { size_t len = 0; http_t *http = http_object(msg); http_payload_t const *pl; su_home_t *home = msg_home(msg); if (!http) return -1; if (!http->http_request) return -1; if (!http->http_host) return -1; for (pl = http->http_payload; pl; pl = pl->pl_next) len += pl->pl_len; if (len > UINT32_MAX) return -1; if (!http->http_content_length) { http->http_content_length = http_content_length_create(home, (uint32_t)len); } else { if (http->http_content_length->l_length != len) { http->http_content_length->l_length = (uint32_t)len; msg_fragment_clear(http->http_content_length->l_common); } } if (!http->http_separator) http->http_separator = http_separator_create(home); return 0; } /** Remove schema, host, port, and fragment from HTTP/HTTPS URL */ int http_strip_hostport(url_t *url) { if (url->url_type == url_http || url->url_type == url_https) { url->url_type = url_unknown; url->url_scheme = NULL; url->url_user = NULL; url->url_password = NULL; url->url_host = NULL; url->url_port = NULL; if (url->url_path == NULL) { url->url_root = '/'; url->url_path = ""; } } url->url_fragment = NULL; return 0; } /** Add a Content-Length and separator to a message */ int http_message_complete(msg_t *msg, http_t *http) { #if 1 if (!http->http_content_length) { http_content_length_t *l; http_payload_t *pl; size_t len = 0; for (pl = http->http_payload; pl; pl = pl->pl_next) len += pl->pl_len; if (len > UINT32_MAX) return -1; l = http_content_length_create(msg_home(msg), (uint32_t)len); if (msg_header_insert(msg, http, (http_header_t *)l) < 0) return -1; } #endif if (!http->http_separator) { http_separator_t *sep = http_separator_create(msg_home(msg)); if (msg_header_insert(msg, http, (http_header_t *)sep) < 0) return -1; } return 0; } /** Add headers from the request to the response message. */ int http_complete_response(msg_t *msg, int status, char const *phrase, http_t const *request) { su_home_t *home = msg_home(msg); http_t *http = msg_object(msg); if (!http || !request || !request->http_request) return -1; if (!http->http_status) http->http_status = http_status_create(home, status, phrase, NULL); if (!http->http_status) return -1; if (!http->http_separator) { http_separator_t *sep = http_separator_create(msg_home(msg)); if (msg_header_insert(msg, http, (http_header_t *)sep) < 0) return -1; } return 0; } /** Copy a HTTP header. */ http_header_t *http_header_copy(su_home_t *home, http_header_t const *h) { if (h == NULL || h == HTTP_NONE) return NULL; return msg_header_copy_as(home, h->sh_class, h); } /** Duplicate a HTTP header. */ http_header_t *http_header_dup(su_home_t *home, http_header_t const *h) { if (h == NULL || h == HTTP_NONE) return NULL; return msg_header_dup_as(home, h->sh_class, h); } /** Decode a HTTP header. */ http_header_t *http_header_d(su_home_t *home, msg_t const *msg, char const *b) { return msg_header_d(home, msg, b); } /** Encode a HTTP header. */ int http_header_e(char b[], int bsiz, http_header_t const *h, int flags) { return msg_header_e(b, bsiz, h, flags); } /** Encode HTTP header contents. */ int http_header_field_e(char b[], int bsiz, http_header_t const *h, int flags) { assert(h); assert(h->sh_class); return h->sh_class->hc_print(b, bsiz, h, flags); } http_header_t *http_header_format(su_home_t *home, msg_hclass_t *hc, char const *fmt, ...) { http_header_t *h; va_list ap; va_start(ap, fmt); h = http_header_vformat(home, hc, fmt, ap); va_end(ap); return h; } /** Add a duplicate of header object to a HTTP message. */ int http_add_dup(msg_t *msg, http_t *http, http_header_t const *o) { if (o == HTTP_NONE) return 0; if (msg == NULL || o == NULL) return -1; return msg_header_insert(msg, http, msg_header_dup(msg_home(msg), o)); } int http_add_make(msg_t *msg, http_t *http, msg_hclass_t *hc, char const *s) { if (s == NULL) return 0; if (msg == NULL) return -1; return msg_header_insert(msg, http, msg_header_make(msg_home(msg), hc, s)); } int http_add_format(msg_t *msg, http_t *http, msg_hclass_t *hc, char const *fmt, ...) { http_header_t *h; va_list ap; if (fmt == NULL) return 0; if (msg == NULL) return -1; va_start(ap, fmt); h = http_header_vformat(msg_home(msg), hc, fmt, ap); va_end(ap); return msg_header_insert(msg, http, h); } /** Compare two HTTP URLs. */ int http_url_cmp(url_t const *a, url_t const *b) { int rv; if ((rv = url_cmp(a, b))) return rv; if (a->url_path != b->url_path) { if (a->url_path == NULL) return -1; if (b->url_path == NULL) return +1; if ((rv = strcmp(a->url_path, b->url_path))) return rv; } /* Params? */ /* Query */ if (a->url_headers != b->url_headers) { if (a->url_headers == NULL) return -1; if (b->url_headers == NULL) return +1; if ((rv = strcmp(a->url_headers, b->url_headers))) return rv; } return 0; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/http/http_inlined.c000066400000000000000000000023621223300710500233610ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE http_inlined.c * * Expand inlined http functions non-inline. * */ #include "config.h" #include #if SU_HAVE_INLINE extern int xyzzy; #else #include "sofia-sip/msg_header.h" #include "sofia-sip/su_tag.h" #undef SU_HAVE_INLINE #undef su_inline #define SU_HAVE_INLINE 1 #define su_inline #include "sofia-sip/http_header.h" #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/http/http_parser.c000066400000000000000000000342741223300710500232420ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE http_parser.c * * HTTP parser. * * @author Pekka Pessi * * @date Created: Thu Oct 5 14:01:24 2000 ppessi */ #include "config.h" /* Avoid casting http_t to msg_pub_t and http_header_t to msg_header_t */ #define MSG_PUB_T struct http_s #define MSG_HDR_T union http_header_u #include #include #include "sofia-sip/http_parser.h" #include #include #include #include #include #include #include #include #include #include #include /** HTTP version 1.1. */ char const http_version_1_1[] = "HTTP/1.1"; /** HTTP version 1.0. */ char const http_version_1_0[] = "HTTP/1.0"; /** HTTP version 0.9 is an empty string. */ char const http_version_0_9[] = ""; msg_mclass_t const *http_default_mclass(void) { extern msg_mclass_t const http_mclass[]; return http_mclass; } static issize_t http_extract_chunk(msg_t *, http_t *, char b[], isize_t bsiz, int eos); /** Calculate length of line ending (0, 1 or 2) */ #define CRLF_TEST(s) \ (((s)[0]) == '\r' ? (((s)[1]) == '\n') + 1 : ((s)[0])=='\n') /** Extract the HTTP message body, including separator line. * * @retval -1 error * @retval 0 cannot proceed * @retval other number of bytes extracted */ issize_t http_extract_body(msg_t *msg, http_t *http, char b[], isize_t bsiz, int eos) { issize_t m = 0; size_t body_len; int flags = http->http_flags; if (eos && bsiz == 0) { msg_mark_as_complete(msg, MSG_FLG_COMPLETE); return 0; } if (flags & MSG_FLG_TRAILERS) { /* The empty line after trailers */ if (!eos && (bsiz == 0 || (bsiz == 1 && b[0] == '\r'))) return 0; m = CRLF_TEST(b); assert(m > 0 || eos); /* We should be looking at an empty line */ /* We have completed trailers */ msg_mark_as_complete(msg, MSG_FLG_COMPLETE); return m; } if (flags & MSG_FLG_CHUNKS) return http_extract_chunk(msg, http, b, bsiz, eos); if (!(flags & MSG_FLG_BODY)) { /* We are looking at a potential empty line */ m = msg_extract_separator(msg, http, b, bsiz, eos); if (m == 0) /* Not yet */ return 0; http->http_flags |= MSG_FLG_BODY; b += m, bsiz -= m; } /* body_len is determined by rules in RFC2616 sections 4.3 and 4.4 */ /* 1XX, 204, 304 do not have message-body, ever */ if (http->http_status) { int status = http->http_status->st_status; if (status < 200 || status == 204 || status == 304) flags |= HTTP_FLG_NO_BODY; } if (flags & HTTP_FLG_NO_BODY) { msg_mark_as_complete(msg, MSG_FLG_COMPLETE); return m; } if (http->http_transfer_encoding) { if (/* NOTE - there is really no Transfer-Encoding: identity in RFC 2616 * but it was used in drafts... */ http->http_transfer_encoding->k_items && http->http_transfer_encoding->k_items[0] && !su_casematch(http->http_transfer_encoding->k_items[0], "identity")) { http->http_flags |= MSG_FLG_CHUNKS; if (http->http_flags & MSG_FLG_STREAMING) msg_set_streaming(msg, msg_start_streaming); if (m) return m; return http_extract_chunk(msg, http, b, bsiz, eos); } } if (http->http_content_length) body_len = http->http_content_length->l_length; /* We cannot parse multipart/byteranges ... */ else if (http->http_content_type && http->http_content_type->c_type && su_casematch(http->http_content_type->c_type, "multipart/byteranges")) return -1; else if (MSG_IS_MAILBOX(flags)) /* message fragments */ body_len = 0; else if (http->http_request) body_len = 0; else if (eos) body_len = bsiz; else return 0; /* XXX */ if (body_len == 0) { msg_mark_as_complete(msg, MSG_FLG_COMPLETE); return m; } if (http->http_flags & MSG_FLG_STREAMING) msg_set_streaming(msg, msg_start_streaming); if (m) return m; m = msg_extract_payload(msg, http, NULL, body_len, b, bsiz, eos); if (m == -1) return -1; /* We have now all message fragments in place */ http->http_flags |= MSG_FLG_FRAGS; if (bsiz >= body_len) { msg_mark_as_complete(msg, MSG_FLG_COMPLETE); } return m; } /** Extract a chunk. * * @retval -1 error * @retval 0 cannot proceed * @retval other number of bytes extracted */ issize_t http_extract_chunk(msg_t *msg, http_t *http, char b[], isize_t bsiz, int eos) { size_t n; unsigned crlf, chunk_len; char *b0 = b, *s; union { msg_header_t *header; msg_payload_t *chunk; } h = { NULL }; size_t bsiz0 = bsiz; if (bsiz == 0) return 0; /* We should be looking at an empty line followed by the chunk header */ while ((crlf = CRLF_TEST(b))) { if (bsiz == 1 && crlf == 1 && b[0] == '\r' && !eos) return 0; if (crlf == bsiz) { if (eos) { msg_mark_as_complete(msg, MSG_FLG_COMPLETE | MSG_FLG_FRAGS); return (b - b0) + crlf; } else return 0; } assert(crlf < bsiz); /* Skip crlf */ b += crlf; bsiz -= crlf; } /* Now, looking at the chunk header */ n = strcspn(b, CRLF); if (!eos && n == bsiz) return 0; crlf = CRLF_TEST(b + n); if (n == 0) { if (crlf == bsiz && eos) { msg_mark_as_complete(msg, MSG_FLG_COMPLETE | MSG_FLG_FRAGS); return crlf; } else return -1; /* XXX - should we be more liberal? */ } if (!eos && n + crlf == bsiz && (crlf == 0 || (crlf == 1 && b[n] == '\r'))) return 0; chunk_len = strtoul(b, &s, 16); if (s == b) return -1; skip_ws(&s); if (s != b + n && s[0] != ';') /* Extra stuff that is not parameter */ return -1; if (chunk_len == 0) { /* We found last-chunk */ b += n + crlf, bsiz -= n + crlf; crlf = bsiz > 0 ? CRLF_TEST(b) : 0; if ((eos && bsiz == 0) || crlf == 2 || (crlf == 1 && (bsiz > 1 || b[0] == '\n'))) { /* Shortcut - We got empty trailers */ b += crlf; msg_mark_as_complete(msg, MSG_FLG_COMPLETE | MSG_FLG_FRAGS); } else { /* We have to parse trailers */ http->http_flags |= MSG_FLG_TRAILERS; } return b - b0; } else { issize_t chunk; b += n + crlf, bsiz -= n + crlf; /* Extract chunk */ chunk = msg_extract_payload(msg, http, &h.header, chunk_len + (b - b0), b0, bsiz0, eos); if (chunk != -1 && h.header) { assert(h.chunk->pl_data); h.chunk->pl_data += (b - b0); h.chunk->pl_len -= (b - b0); } return chunk; } } /** Parse HTTP version. * * The function http_version_d() parses a HTTP method. * * @retval 0 when successful, * @retval -1 upon an error. */ int http_version_d(char **ss, char const **ver) { char *s = *ss; char const *result; int const version_size = sizeof(http_version_1_1) - 1; if (su_casenmatch(s, http_version_1_1, version_size) && !IS_TOKEN(s[version_size])) { result = http_version_1_1; s += version_size; } else if (su_casenmatch(s, http_version_1_0, version_size) && !IS_TOKEN(s[version_size])) { result = http_version_1_0; s += version_size; } else if (s[0] == '\0') { result = http_version_0_9; } else { /* Version consists of one or two tokens, separated by / */ size_t l1 = 0, l2 = 0, n; result = s; l1 = span_token(s); for (n = l1; IS_LWS(s[n]); n++) s[n] = '\0'; if (s[n] == '/') { for (n = n + 1; IS_LWS(s[n]); n++) {} l2 = span_token(s + n); n += l2; } if (l1 == 0) return -1; /* If there is extra ws between tokens, compact version */ if (l2 > 0 && n > l1 + 1 + l2) { s[l1] = '/'; memmove(s + l1 + 1, s + n - l2, l2); s[l1 + 1 + l2] = 0; /* Compare again with compacted version */ if (su_casematch(s, http_version_1_1)) result = http_version_1_1; else if (su_casematch(s, http_version_1_0)) result = http_version_1_0; } s += n; } while (IS_LWS(*s)) *s++ = '\0'; *ss = s; if (ver) *ver = result; return 0; } /** Calculate extra space required by version string */ isize_t http_version_xtra(char const *version) { if (version == http_version_1_1) return 0; else if (version == http_version_1_0) return 0; else return MSG_STRING_SIZE(version); } /** Duplicate a transport string */ void http_version_dup(char **pp, char const **dd, char const *s) { if (s == http_version_1_1) *dd = s; else if (s == http_version_1_0) *dd = s; else MSG_STRING_DUP(*pp, *dd, s); } /** Well-known HTTP method names. */ static char const * const methods[] = { "", http_method_name_get, http_method_name_post, http_method_name_head, http_method_name_options, http_method_name_put, http_method_name_delete, http_method_name_trace, http_method_name_connect, NULL, /* If you add something here, add also them to http_method_d! */ }; char const http_method_name_get[] = "GET"; char const http_method_name_post[] = "POST"; char const http_method_name_head[] = "HEAD"; char const http_method_name_options[] = "OPTIONS"; char const http_method_name_put[] = "PUT"; char const http_method_name_delete[] = "DELETE"; char const http_method_name_trace[] = "TRACE"; char const http_method_name_connect[] = "CONNECT"; char const *http_method_name(http_method_t method, char const *name) { if (method > 0 && (size_t)method < sizeof(methods)/sizeof(methods[0])) return methods[method]; else if (method == 0) return name; else return NULL; } /**Parse a HTTP method name. * * The function @c http_method_d() parses a HTTP method, and returns a code * corresponding to the method. It stores the address of the first non-LWS * character after method name in @c *ss. * * @param ss pointer to pointer to string to be parsed * @param nname pointer to value-result parameter formethod name * * @note * If there is no whitespace after method name, the value in @a *nname * may not be NUL-terminated. The calling function @b must NUL terminate * the value by setting the @a **ss to NUL after first examining its value. * * @return The function @c http_method_d returns the method code if method * was identified, 0 (@c http_method_unknown) if method is not known, or @c -1 * (@c http_method_invalid) if an error occurred. * * If the value-result argument @a nname is not @c NULL, http_method_d() * stores a pointer to the method name to it. */ http_method_t http_method_d(char **ss, char const **nname) { char *s = *ss, c = *s; char const *name; int code = http_method_unknown; size_t n = 0; #define MATCH(s, m) (su_casenmatch(s, m, n = sizeof(m) - 1)) if (c >= 'a' && c <= 'z') c += 'A' - 'a'; switch (c) { case 'C': if (MATCH(s, "CONNECT")) code = http_method_connect; break; case 'D': if (MATCH(s, "DELETE")) code = http_method_delete; break; case 'G': if (MATCH(s, "GET")) code = http_method_get; break; case 'H': if (MATCH(s, "HEAD")) code = http_method_head; break; case 'O': if (MATCH(s, "OPTIONS")) code = http_method_options; break; case 'P': if (MATCH(s, "POST")) code = http_method_post; else if (MATCH(s, "PUT")) code = http_method_put; break; case 'T': if (MATCH(s, "TRACE")) code = http_method_trace; break; } #undef MATCH if (!code || IS_NON_WS(s[n])) { /* Unknown method */ code = http_method_unknown; name = s; for (n = 0; IS_UNRESERVED(s[n]); n++) ; if (s[n]) { if (!IS_LWS(s[n])) return http_method_invalid; if (nname) s[n++] = '\0'; } } else { name = methods[code]; } while (IS_LWS(s[n])) n++; *ss = (s + n); if (nname) *nname = name; return (http_method_t)code; } /** Get method enum corresponding to method name */ http_method_t http_method_code(char const *name) { /* Note that http_method_d() does not change string if nname is NULL */ return http_method_d((char **)&name, NULL); } /**Parse HTTP query string. * * The function http_query_parse() searches for the given keys in HTTP @a * query. For each key, a query element (in the form name=value) is searched * from the query string. If a query element has a beginning matching with * the key, a copy of the rest of the element is returned in corresponding * return_value argument. * * @note The @a query string will be modified. * * @return * The function http_query_parse() returns number keys that matched within * the @a query string. */ issize_t http_query_parse(char *query, /* char const *key, char **return_value, */ ...) { va_list ap; char *q, *q_next; char *name, *value, **return_value; char const *key; size_t namelen, valuelen, keylen; isize_t N; int has_value; if (!query) return -1; for (q = query, N = 0; *q; q = q_next) { namelen = strcspn(q, "=&"); valuelen = namelen + strcspn(q + namelen, "&"); q_next = q + valuelen; if (*q_next) *q_next++ = '\0'; value = q + namelen; has_value = (*value) != '\0'; /* is the part in form of name=value? */ if (has_value) *value++ = '\0'; name = url_unescape(q, q); if (has_value) { namelen = strlen(name); name[namelen] = '='; url_unescape(name + namelen + 1, value); } va_start(ap, query); while ((key = va_arg(ap, char const *))) { return_value = va_arg(ap, char **); keylen = strlen(key); if (strncmp(key, name, keylen) == 0) { *return_value = name + keylen; N++; } } va_end(ap); } return N; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/http/http_parser_table.c.in000066400000000000000000000030301223300710500250000ustar00rootroot00000000000000/** -*- C -*- * @IFILE http_parser_table.c.in * * Template for . * * @date Created: Tue Oct 1 20:37:52 2002 ppessi */ /* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@internal * @CFILE http_parser_table.c * @brief HTTP parser table * * #AUTO# * * @author Pekka Pessi * * @date Created: Tue Oct 1 20:37:52 2002 ppessi */ #include "config.h" #include #include /* Avoid casting http_t to msg_pub_t and http_header_t to msg_header_t */ #define MSG_PUB_T struct http_s #define MSG_HDR_T union http_header_u #include #include #define HTTP_PARSER_FLAGS (MSG_FLG_CHUNKING) sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/http/http_status.c000066400000000000000000000121321223300710500232560ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE http_status.c HTTP status codes. * * @author Pekka Pessi * * @date Created: Tue Sep 18 18:58:21 2001 ppessi */ #include "config.h" #include #include char const http_100_continue[] = "Continue", http_101_switching[] = "Switching Protocols", http_200_ok[] = "OK", http_201_created[] = "Created", http_202_accepted[] = "Accepted", http_203_non_auth_info[] = "Non-Authoritative Information", http_204_no_content[] = "No Content", http_205_reset_content[] = "Reset Content", http_206_partial_content[] = "Partial Content", http_300_multiple_choices[] = "Multiple Choices", http_301_moved_permanently[] = "Moved Permanently", http_302_found[] = "Found", http_303_see_other[] = "See Other", http_304_not_modified[] = "Not Modified", http_305_use_proxy[] = "Use Proxy", http_307_temporary_redirect[] = "Temporary Redirect", http_400_bad_request[] = "Bad Request", http_401_unauthorized[] = "Unauthorized", http_402_payment_required[] = "Payment Required", http_403_forbidden[] = "Forbidden", http_404_not_found[] = "Not Found", http_405_not_allowed[] = "Method Not Allowed", http_406_not_acceptable[] = "Not Acceptable", http_407_proxy_auth[] = "Proxy Authentication Required", http_408_timeout[] = "Request Timeout", http_409_conflict[] = "Conflict", http_410_gone[] = "Gone", http_411_no_length[] = "Length Required", http_412_precondition[] = "Precondition Failed", http_413_entity_too_large[] = "Request Entity Too Large", http_414_uri_too_long[] = "Request-URI Too Long", http_415_media_type[] = "Unsupported Media Type", http_416_requested_range[] = "Requested Range Not Satisfiable", http_417_expectation[] = "Expectation Failed", http_426_upgrade[] = "Upgrade Required", http_500_internal_server[] = "Internal Server Error", http_501_not_implemented[] = "Not Implemented", http_502_bad_gateway[] = "Bad Gateway", http_503_no_service[] = "Service Unavailable", http_504_gateway_timeout[] = "Gateway Timeout", http_505_http_version[] = "HTTP Version Not Supported"; char const *http_status_phrase(int status) { if (status < 100 || status > 699) return NULL; switch (status) { case 100: return http_100_continue; case 101: return http_101_switching; case 200: return http_200_ok; case 201: return http_201_created; case 202: return http_202_accepted; case 203: return http_203_non_auth_info; case 204: return http_204_no_content; case 205: return http_205_reset_content; case 206: return http_206_partial_content; case 300: return http_300_multiple_choices; case 301: return http_301_moved_permanently; case 302: return http_302_found; case 303: return http_303_see_other; case 304: return http_304_not_modified; case 305: return http_305_use_proxy; case 307: return http_307_temporary_redirect; case 400: return http_400_bad_request; case 401: return http_401_unauthorized; case 402: return http_402_payment_required; case 403: return http_403_forbidden; case 404: return http_404_not_found; case 405: return http_405_not_allowed; case 406: return http_406_not_acceptable; case 407: return http_407_proxy_auth; case 408: return http_408_timeout; case 409: return http_409_conflict; case 410: return http_410_gone; case 411: return http_411_no_length; case 412: return http_412_precondition; case 413: return http_413_entity_too_large; case 414: return http_414_uri_too_long; case 415: return http_415_media_type; case 416: return http_416_requested_range; case 417: return http_417_expectation; case 426: return http_426_upgrade; case 500: return http_500_internal_server; case 501: return http_501_not_implemented; case 502: return http_502_bad_gateway; case 503: return http_503_no_service; case 504: return http_504_gateway_timeout; case 505: return http_505_http_version; } return " "; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/http/http_tag.c.in000066400000000000000000000035561223300710500231250ustar00rootroot00000000000000/**@HTTP * @IFILE http_tag.c.in * * Template for . * * @date Created: Wed Feb 21 11:01:45 2001 ppessi */ /* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@internal @file http_tag.c HTTP Tag classes * * This file is autogenerated from . * * #AUTO# * * @author Pekka Pessi */ #include "config.h" #define TAG_NAMESPACE "http" #include #include #include #include #include #include #include #include tag_typedef_t httptag_any = NSTAG_TYPEDEF(*); tag_typedef_t httptag_http = HTTPMSGTAG_TYPEDEF(http); tag_typedef_t httptag_version = STRTAG_TYPEDEF(version); tag_typedef_t httptag_header = {{ TAG_NAMESPACE, "header", httphdrtag_class, 0 }}; tag_typedef_t httptag_header_str = STRTAG_TYPEDEF(header_str); tag_typedef_t httptag_#xxxxxx# = HTTPHDRTAG_TYPEDEF(#xxxxxx#); tag_typedef_t httptag_#xxxxxx#_str = HTTPSTRTAG_TYPEDEF(#xxxxxx#); sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/http/http_tag_class.c000066400000000000000000000125071223300710500237010ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE http_tag_class.c HTTP tag classes * * @author Pekka Pessi * * @date Created: Fri Feb 23 12:46:42 2001 ppessi */ #include "config.h" #include #include #include #include /* Avoid casting http_t to msg_pub_t and http_header_t to msg_header_t */ #define MSG_PUB_T struct http_s #define MSG_HDR_T union http_header_u #include #include #include #include #include #include tag_class_t httphdrtag_class[1] = {{ sizeof(httphdrtag_class), /* tc_next */ NULL, /* tc_len */ NULL, /* tc_move */ NULL, /* tc_xtra */ msghdrtag_xtra, /* tc_dup */ msghdrtag_dup, /* tc_free */ NULL, /* tc_find */ NULL, /* tc_snprintf */ msghdrtag_snprintf, /* tc_filter */ httptag_filter, /* tc_ref_set */ t_ptr_ref_set, /* tc_scan */ msghdrtag_scan, }}; tag_class_t httpstrtag_class[1] = {{ sizeof(httpstrtag_class), /* tc_next */ NULL, /* tc_len */ NULL, /* tc_move */ NULL, /* tc_xtra */ t_str_xtra, /* tc_dup */ t_str_dup, /* tc_free */ NULL, /* tc_find */ NULL, /* tc_snprintf */ t_str_snprintf, /* tc_filter */ NULL /* msgtag_str_filter */, /* tc_ref_set */ t_ptr_ref_set, /* tc_scan */ msghdrtag_scan, }}; tag_class_t httpmsgtag_class[1] = {{ sizeof(httpmsgtag_class), /* tc_next */ NULL, /* tc_len */ NULL, /* tc_move */ NULL, /* tc_xtra */ msgobjtag_xtra, /* tc_dup */ msgobjtag_dup, /* tc_free */ NULL, /* tc_find */ NULL, /* tc_snprintf */ msgobjtag_snprintf, /* tc_filter */ NULL /* httptag_http_filter */, /* tc_ref_set */ t_ptr_ref_set, /* tc_scan */ t_str_scan }}; /** Filter a HTTP header structure. */ tagi_t *httptag_filter(tagi_t *dst, tagi_t const f[], tagi_t const *src, void **bb) { tagi_t stub[2] = {{ NULL }}; tag_type_t sctt, tt = f->t_tag; msg_hclass_t *hc = (msg_hclass_t *)tt->tt_magic; assert(src); sctt = src->t_tag; if (sctt && sctt->tt_class == httpmsgtag_class) { http_t const *http; msg_mclass_t const *mc; http_header_t const *h, **hh; http = (http_t const *)src->t_value; if (http == NULL) return dst; mc = (void *)http->http_common->h_class; hh = (void *)msg_hclass_offset(mc, http, hc); if (hh == NULL || (char *)hh >= ((char *)http + http->http_size) || (char *)hh < (char *)&http->http_request) return dst; h = *hh; if (h == NULL) return dst; stub[0].t_tag = tt; stub[0].t_value = (tag_value_t)h; src = stub; sctt = tt; } if (tt != sctt) return dst; if (!src->t_value) return dst; else if (dst) { return t_dup(dst, src, bb); } else { *bb = (char *)*bb + t_xtra(src, (size_t)*bb); return dst + 1; } } /** Duplicate headers from taglist and add them to the HTTP message. * * Return the number of headers added to the HTTP message. */ int http_add_tl(msg_t *msg, http_t *http, tag_type_t tag, tag_value_t value, ...) { tagi_t const *t; ta_list ta; int retval = 0; if (msg == NULL) return -1; if (http == NULL) http = msg_object(msg); ta_start(ta, tag, value); for (t = ta_args(ta); t; t = tl_next(t)) { if (!(tag = t->t_tag) || !(value = t->t_value)) continue; if (HTTPTAG_P(tag)) { msg_hclass_t *hc = (msg_hclass_t *)tag->tt_magic; http_header_t *h = (http_header_t *)value, **hh; if (h == HTTP_NONE) { /* Remove header(s) */ if (hc == NULL) break; hh = msg_hclass_offset(msg_mclass(msg), http, hc); if (!hh) break; while (*hh) { msg_header_remove(msg, http, *hh); } } else if (h == NULL) { continue; } else { if (tag == httptag_header) hc = h->sh_class; if (msg_header_add_dup_as(msg, http, hc, h) < 0) break; } } else if (HTTPTAG_STR_P(tag)) { msg_hclass_t *hc = (msg_hclass_t *)tag->tt_magic; char const *s = (char const *)value; if (s && msg_header_add_make(msg, http, hc, s) < 0) break; } else if (tag == httptag_header_str) { if (msg_header_add_str(msg, http, (char const *)value) < 0) break; } else continue; retval++; } ta_end(ta); if (t) return -1; return retval; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/http/sofia-sip/000077500000000000000000000000001223300710500224235ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/http/sofia-sip/http.h000066400000000000000000000452161223300710500235630ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef HTTP_H /** Defined when has been included. */ #define HTTP_H /**@file sofia-sip/http.h * * HTTP message, methods, headers. * * @sa RFC 2616 * * @author Pekka Pessi . * * @date Created : Thu Jun 8 19:28:55 2000 ppessi */ #ifndef MSG_H #include #endif #ifndef URL_H #include #endif #ifndef MSG_MIME_H #include #endif SOFIA_BEGIN_DECLS /* ---------------------------------------------------------------------- * 1) Constants */ #define HTTP_NONE ((http_header_t *)MSG_HEADER_NONE) #define HTTP_DEFAULT_PORT (80) #define HTTP_DEFAULT_SERV "80" /** HTTP protocol identifier */ #define HTTP_PROTOCOL_TAG ((void *)(uintptr_t)0x48545450) /* 'HTTP' */ /** HTTP parser flags */ enum { HTTP_FLG_NO_BODY = (1 << 15) }; /** IDs for well-known HTTP methods. */ typedef enum { http_method_invalid = -1, /**< Invalid method name */ http_method_unknown = 0, /**< Unknown method, use @c method_name */ http_method_get, /**< GET */ http_method_post, /**< POST */ http_method_head, /**< HEAD */ http_method_options, /**< OPTIONS */ http_method_put, /**< PUT */ http_method_delete, /**< DELETE */ http_method_trace, /**< TRACE */ http_method_connect, /**< CONNECT */ } http_method_t; #define HTTP_METHOD(s) http_method_unknown, #s #define HTTP_NO_METHOD http_method_unknown, NULL #define HTTP_METHOD_GET http_method_get, "GET" #define HTTP_METHOD_POST http_method_post, "POST" #define HTTP_METHOD_HEAD http_method_head, "HEAD" #define HTTP_METHOD_OPTIONS http_method_options, "OPTIONS" #define HTTP_METHOD_PUT http_method_put, "PUT" #define HTTP_METHOD_DELETE http_method_delete, "DELETE" #define HTTP_METHOD_TRACE http_method_trace, "TRACE" #define HTTP_METHOD_CONNECT http_method_connect, "CONNECT" /* ---------------------------------------------------------------------- * 2) Type declarations */ /** HTTP message object. */ typedef struct http_s http_t; /** Any HTTP header - union of all possible HTTP headers. */ typedef union http_header_u http_header_t; typedef struct http_request_s http_request_t; typedef struct http_status_s http_status_t; typedef msg_accept_t http_accept_t; typedef msg_accept_charset_t http_accept_charset_t; typedef msg_accept_encoding_t http_accept_encoding_t; typedef msg_accept_language_t http_accept_language_t; typedef msg_list_t http_accept_ranges_t; typedef msg_numeric_t http_age_t; typedef msg_list_t http_allow_t; typedef msg_auth_info_t http_authentication_info_t; typedef msg_auth_t http_authorization_t; typedef msg_list_t http_cache_control_t; typedef msg_list_t http_connection_t; typedef msg_content_encoding_t http_content_encoding_t; typedef msg_content_language_t http_content_language_t; typedef msg_content_length_t http_content_length_t; typedef msg_content_location_t http_content_location_t; typedef msg_generic_t http_content_md5_t; typedef struct http_content_range_s http_content_range_t; typedef msg_content_type_t http_content_type_t; typedef struct http_date_s http_date_t; typedef msg_generic_t http_etag_t; typedef msg_generic_t http_expect_t; typedef http_date_t http_expires_t; typedef msg_generic_t http_from_t; typedef struct http_host_s http_host_t; typedef msg_list_t http_if_match_t; typedef http_date_t http_if_modified_since_t; typedef msg_list_t http_if_none_match_t; typedef struct http_if_range_s http_if_range_t; typedef http_date_t http_if_unmodified_since_t; typedef http_date_t http_last_modified_t; typedef struct http_location_s http_location_t; typedef struct http_max_forwards_s http_max_forwards_t; typedef msg_generic_t http_mime_version_t; typedef msg_list_t http_pragma_t; typedef msg_auth_t http_proxy_authenticate_t; typedef msg_auth_t http_proxy_authorization_t; typedef struct http_range_s http_range_t; typedef struct http_location_s http_referer_t; typedef struct http_retry_after_s http_retry_after_t; typedef msg_generic_t http_server_t; typedef struct http_te_s http_te_t; typedef msg_list_t http_trailer_t; typedef msg_list_t http_transfer_encoding_t; typedef msg_list_t http_upgrade_t; typedef msg_generic_t http_user_agent_t; typedef msg_list_t http_vary_t; typedef struct http_via_s http_via_t; typedef msg_warning_t http_warning_t; typedef msg_auth_t http_www_authenticate_t; typedef msg_list_t http_proxy_connection_t; typedef struct http_set_cookie_s http_set_cookie_t; typedef struct http_cookie_s http_cookie_t; /** Erroneous header. */ typedef msg_error_t http_error_t; /** Unknown header. */ typedef msg_generic_t http_unknown_t; /** Separator line between headers and message contents */ typedef msg_separator_t http_separator_t; /** Entity-body */ typedef msg_payload_t http_payload_t; /** Time in seconds since 01-Jan-1900. */ typedef unsigned long http_time_t; /** Range offset. */ typedef unsigned long http_off_t; /* ---------------------------------------------------------------------- * 3) Structure definitions */ /** HTTP request line */ struct http_request_s { msg_common_t rq_common[1]; http_error_t *rq_next; http_method_t rq_method; /** Method enum. */ char const *rq_method_name; /** Method name. */ url_t rq_url[1]; /** URL. */ char const *rq_version; /** Protocol version. */ }; /** HTTP status line */ struct http_status_s { msg_common_t st_common[1]; http_error_t *st_next; char const *st_version; int st_status; char const *st_phrase; }; /**@ingroup http_authentication_info * @brief Structure for @b Authentication-Info header. * * @deprecated Use struct msg_auth_info_s instead. */ struct http_authentication_info_s { msg_common_t ai_common[1]; /**< Common fragment info */ msg_error_t *ai_next; /**< Dummy link to next */ msg_param_t const *ai_params; /**< List of authentication info */ }; /** Content-Range */ struct http_content_range_s { msg_common_t cr_common[1]; http_error_t *cr_next; http_off_t cr_first; /**< First-byte-pos */ http_off_t cr_last; /**< Last-byte-pos */ http_off_t cr_length; /**< Instance-length */ }; /** Date, Expires, If-Modified-Since, If-Unmodified-Since, Last-Modified */ struct http_date_s { msg_common_t d_common[1]; http_error_t *d_next; http_time_t d_time; /**< Seconds since Jan 1, 1900 */ }; /** Host */ struct http_host_s { msg_common_t h_common[1]; http_error_t *h_next; char const *h_host; char const *h_port; }; /** If-Range */ struct http_if_range_s { msg_common_t ifr_common[1]; http_error_t *ifr_next; char const *ifr_tag; /**< Tag */ http_time_t ifr_time; /**< Timestamp */ }; /** Location, Referer */ struct http_location_s { msg_common_t loc_common[1]; http_error_t *loc_next; url_t loc_url[1]; }; /** Max-Forwards */ struct http_max_forwards_s { msg_common_t mf_common[1]; http_error_t *mf_next; unsigned long mf_count; }; /** Range */ struct http_range_s { msg_common_t rng_common[1]; http_error_t *rng_next; char const *rng_unit; char const **rng_specs; }; /** Retry-After. */ struct http_retry_after_s { msg_common_t ra_common[1]; /**< Common fragment info */ http_error_t *ra_next; /**< Link to next (dummy) */ http_time_t ra_date; /**< When to retry */ http_time_t ra_delta; /**< Seconds to before retry */ }; /** TE */ struct http_te_s { msg_common_t te_common[1]; /**< Common fragment info */ http_te_t *te_next; /**< Link to next t-coding */ char const *te_extension; /**< Transfer-Extension */ msg_param_t const *te_params; /**< List of parameters */ char const *te_q; /**< Q-value */ }; /** Via */ struct http_via_s { msg_common_t v_common[1]; http_via_t *v_next; char const *v_version; char const *v_host; char const *v_port; char const *v_comment; }; /** Cookie */ struct http_cookie_s { msg_common_t c_common[1]; http_cookie_t *c_next; msg_param_t const *c_params; char const *c_version; char const *c_name; char const *c_domain; char const *c_path; }; /** Set-Cookie */ struct http_set_cookie_s { msg_common_t sc_common[1]; http_set_cookie_t *sc_next; msg_param_t const *sc_params; char const *sc_name; char const *sc_version; char const *sc_domain; char const *sc_path; char const *sc_comment; char const *sc_max_age; unsigned sc_secure; }; /**HTTP message object. * * This structure contains a HTTP message object. It is used to access the * headers and payload within the message. The generic transport aspects of * the message, like network address, is accessed using a @b msg_t object * directly. */ struct http_s { msg_common_t http_common[1]; /**< For recursive inclusion */ msg_pub_t *http_next; /**< Dummy pointer to next part */ void *http_user; /**< Application data */ unsigned http_size; /**< Size of this structure */ int http_flags; /**< Flags */ http_error_t *http_error; /**< Erroneous headers */ http_request_t *http_request; /**< Request line */ http_status_t *http_status; /**< Status line */ /* === Headers start here */ http_accept_t *http_accept; /**< Accept */ http_accept_charset_t *http_accept_charset; /**< Accept-Charset */ http_accept_encoding_t *http_accept_encoding; /**< Accept-Encoding */ http_accept_language_t *http_accept_language; /**< Accept-Language */ http_accept_ranges_t *http_accept_ranges; /**< Accept-Ranges */ http_allow_t *http_allow; /**< Allow */ http_authentication_info_t*http_authentication_info;/** * * 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 * */ #ifndef HTTP_HCLASSES_H /** Defined when has been included. */ #define HTTP_HCLASSES_H /**@file sofia-sip/http_hclasses.h * @brief HTTP header classes. * * @author Pekka Pessi * */ #ifndef MSG_TYPES_H #include #endif SOFIA_BEGIN_DECLS /* Use directly these header classes */ #define http_accept_class msg_accept_class #define http_accept_charset_class msg_accept_charset_class #define http_accept_encoding_class msg_accept_encoding_class #define http_accept_language_class msg_accept_language_class #define http_content_encoding_class msg_content_encoding_class #define http_content_length_class msg_content_length_class #define http_content_md5_class msg_content_md5_class #define http_content_type_class msg_content_type_class #define http_content_id_class msg_content_id_class #define http_content_location_class msg_content_location_class #define http_content_language_class msg_content_language_class #define http_mime_version_class msg_mime_version_class #define http_error_class msg_error_class #define http_unknown_class msg_unknown_class #define http_separator_class msg_separator_class #define http_payload_class msg_payload_class SOFIA_END_DECLS #ifndef HTTP_PROTOS_H #define HTTP_HCLASSES_ONLY #include #undef HTTP_HCLASSES_ONLY #endif #endif /* !defined HTTP_HCLASSES_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/http/sofia-sip/http_header.h000066400000000000000000000177301223300710500250730ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef HTTP_HEADER_H /** Defined when has been included.*/ #define HTTP_HEADER_H /**@file sofia-sip/http_header.h * * HTTP library prototypes. * * @author Pekka Pessi * * @date Created: Tue Jun 13 02:58:26 2000 ppessi */ #ifndef SU_ALLOC_H #include #endif #ifndef SU_TAG_H #include #endif #ifndef HTTP_H #include #endif #ifndef MSG_HEADER_H #include #endif SOFIA_BEGIN_DECLS /* ---------------------------------------------------------------------- * 1) Macros */ /** Initialize a HTTP header structure. */ #define HTTP_HEADER_INIT(h, http_class, size) \ ((void)memset((h), 0, (size)), \ (void)(((msg_common_t *)(h))->h_class = (http_class)), \ (h)) #define HTTP_METHOD_NAME(method, name) \ ((method) == http_method_unknown ? (name) : http_method_name(method, name)) /* ---------------------------------------------------------------------- * 2) Variables */ SOFIAPUBVAR char const http_method_name_get[]; SOFIAPUBVAR char const http_method_name_post[]; SOFIAPUBVAR char const http_method_name_head[]; SOFIAPUBVAR char const http_method_name_options[]; SOFIAPUBVAR char const http_method_name_put[]; SOFIAPUBVAR char const http_method_name_delete[]; SOFIAPUBVAR char const http_method_name_trace[]; SOFIAPUBVAR char const http_method_name_connect[]; /** HTTP 0.9 */ SOFIAPUBVAR char const http_version_0_9[]; /** HTTP 1.0 */ SOFIAPUBVAR char const http_version_1_0[]; /** HTTP 1.1 version. */ SOFIAPUBVAR char const http_version_1_1[]; #define HTTP_VERSION_CURRENT http_version_1_1 /* ---------------------------------------------------------------------- * 3) Prototypes */ /** HTTP parser description. */ SOFIAPUBFUN msg_mclass_t const *http_default_mclass(void); /** Complete a HTTP request. */ SOFIAPUBFUN int http_request_complete(msg_t *msg); /** Complete a HTTP message. */ SOFIAPUBFUN int http_message_complete(msg_t *msg, http_t *http); /** Add a duplicate of header object to a HTTP message. */ SOFIAPUBFUN int http_add_dup(msg_t *, http_t *, http_header_t const *); /** Add a header to the HTTP message. */ SOFIAPUBFUN int http_add_make(msg_t *msg, http_t *http, msg_hclass_t *hc, char const *s); /** Add a header to the HTTP message. */ SOFIAPUBFUN int http_add_format(msg_t *msg, http_t *http, msg_hclass_t *hc, char const *fmt, ...); /** Add tagged headers to the HTTP message */ SOFIAPUBFUN int http_add_tl(msg_t *msg, http_t *http, tag_type_t tag, tag_value_t value, ...); /** Remove schema, host, and port from URL */ SOFIAPUBFUN int http_strip_hostport(url_t *url); /** Add required headers to the response message */ SOFIAPUBFUN int http_complete_response(msg_t *msg, int status, char const *phrase, http_t const *request); /** Return string corresponding to the method. */ SOFIAPUBFUN char const *http_method_name(http_method_t method, char const *name); /** Return enum corresponding to the method name */ SOFIAPUBFUN http_method_t http_method_code(char const *name); #if !SU_HAVE_INLINE SOFIAPUBFUN http_t *http_object(msg_t *msg); SOFIAPUBFUN int http_header_insert(msg_t *msg, http_t *http, http_header_t *h); SOFIAPUBFUN int http_header_remove(msg_t *msg, http_t *http, http_header_t *h); SOFIAPUBFUN char const *http_header_name(http_header_t const *h, int compact); SOFIAPUBFUN void *http_header_data(http_header_t *h); SOFIAPUBFUN http_content_length_t *http_content_length_create(su_home_t *home, uint32_t n); SOFIAPUBFUN http_payload_t *http_payload_create(su_home_t *home, void const *data, usize_t len); SOFIAPUBFUN http_separator_t *http_separator_create(su_home_t *home); #endif SOFIAPUBFUN http_header_t *http_header_format(su_home_t *home, msg_hclass_t *, char const *fmt, ...); /** Create a request line object. */ SOFIAPUBFUN http_request_t *http_request_create(su_home_t *home, http_method_t method, const char *name, url_string_t const *url, char const *version); /** Create a status line object. */ SOFIAPUBFUN http_status_t *http_status_create(su_home_t *home, unsigned status, char const *phrase, char const *version); /** Create an @b Host header object. */ SOFIAPUBFUN http_host_t *http_host_create(su_home_t *home, char const *host, char const *port); /** Create an @b Date header object. */ SOFIAPUBFUN http_date_t *http_date_create(su_home_t *home, http_time_t t); /** Create an @b Expires header object. */ SOFIAPUBFUN http_expires_t *http_expires_create(su_home_t *home, http_time_t delta); /** Compare two HTTP URLs. */ SOFIAPUBFUN int http_url_cmp(url_t const *a, url_t const *b); /** Parse query part in HTTP URL. */ SOFIAPUBFUN issize_t http_query_parse(char *query, /* char const *key, char **return_value, */ ...); /* ---------------------------------------------------------------------- * 4) Inlined functions */ #if SU_HAVE_INLINE /** Get HTTP structure from msg. */ su_inline http_t *http_object(msg_t *msg) { return (http_t *)msg_public(msg, HTTP_PROTOCOL_TAG); } /** Insert a (list of) header(s) to the header structure and fragment chain. * * The function @c http_header_insert() inserts header or list of headers * into a HTTP message. It also inserts them into the the message fragment * chain, if it exists. * * When inserting headers into the fragment chain, a request (or status) is * inserted first and replaces the existing request (or status). The Via * headers are inserted after the request or status, and rest of the headers * after request, status, or Via headers. * * If the header is a singleton, existing headers with the same class are * removed. * * @param msg message owning the fragment chain * @param http HTTP message structure to which header is added * @param h list of header(s) to be added */ su_inline int http_header_insert(msg_t *msg, http_t *http, http_header_t *h) { return msg_header_insert(msg, (msg_pub_t *)http, (msg_header_t *)h); } /** Remove a header from a HTTP message. */ su_inline int http_header_remove(msg_t *msg, http_t *http, http_header_t *h) { return msg_header_remove(msg, (msg_pub_t *)http, (msg_header_t *)h); } /** Return name of the header. */ su_inline char const *http_header_name(http_header_t const *h, int compact) { if (compact && h->sh_class->hc_short[0]) return h->sh_class->hc_short; else return h->sh_class->hc_name; } /** Return data after header structure. */ su_inline void *http_header_data(http_header_t *h) { return h && h != HTTP_NONE ? h->sh_class->hc_size + (char *)h : NULL; } su_inline http_content_length_t *http_content_length_create(su_home_t *home, uint32_t n) { return msg_content_length_create(home, n); } su_inline http_payload_t *http_payload_create(su_home_t *home, void const *data, isize_t len) { return msg_payload_create(home, data, len); } su_inline http_separator_t *http_separator_create(su_home_t *home) { return msg_separator_create(home); } #endif SOFIA_END_DECLS #ifndef HTTP_PROTOS_H #include #endif #endif /* !defined(HTTP_HEADER_H) */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/http/sofia-sip/http_parser.h000066400000000000000000000066731223300710500251430ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef HTTP_PARSER_H /**Defined when has been included.*/ #define HTTP_PARSER_H /**@file sofia-sip/http_parser.h * @brief Typedefs and prototypes used by HTTP parser. * * @author Pekka Pessi * * @date Created: Tue Jun 13 02:58:26 2000 ppessi */ #ifndef SU_ALLOC_H #include #endif #ifndef MSG_H #include #endif #ifndef MSG_PARSER_H #include #endif #ifndef HTTP_H #include #endif #ifndef HTTP_HEADER_H #include #endif SOFIA_BEGIN_DECLS /* --------------------------------------------------------------------------- * 1) Macros for defining boilerplate functions and structures for each header */ #define HTTP_HCLASS_TAG HTTP_PROTOCOL_TAG #define HTTP_HCLASS_TEST(x) ((x) && (x)->hc_tag == HTTP_PROTOCOL_TAG) #define HTTP_HDR_TEST(x) ((x)->sh_class && HTTP_HCLASS_TEST((x)->sh_class)) /** Define a header class for a HTTP header. */ #define HTTP_HEADER_CLASS(c, l, params, kind, dup) \ MSG_HEADER_CLASS(http_, c, l, "", params, kind, http_ ## dup, http_no) /** This is used by headers with no extra data in copy */ #define HTTP_HEADER_CLASS_G(c, l, kind) \ MSG_HEADER_CLASS(http_, c, l, "", g_common, kind, msg_generic, http_no) /** Define a header class for a msg_list_t kind of header */ #define HTTP_HEADER_CLASS_LIST(c, l, kind) \ MSG_HEADER_CLASS(http_, c, l, "", k_items, kind, msg_list, http_no) /** Define a authorization header class */ #define HTTP_HEADER_CLASS_AUTH(c, l, kind) \ MSG_HEADER_CLASS(http_, c, l, "", au_params, kind, msg_auth, http_no) #define http_numeric_dup_xtra msg_default_dup_xtra #define http_numeric_dup_one msg_default_dup_one #define http_default_dup_xtra msg_default_dup_xtra #define http_default_dup_one msg_default_dup_one #define http_no_update NULL /* --------------------------------------------------------------------------- * 2) Prototypes for HTTP-specific decoding/encoding functions */ /* Version strings */ SOFIAPUBFUN int http_version_d(char **ss, char const **ver); SOFIAPUBFUN isize_t http_version_xtra(char const *version); SOFIAPUBFUN void http_version_dup(char **pp, char const **dd, char const *s); /* Method */ SOFIAPUBFUN http_method_t http_method_d(char **ss, char const **nname); SOFIAPUBFUN char const *http_method_name(http_method_t method, char const *name); /** Extract HTTP message body */ SOFIAPUBFUN issize_t http_extract_body(msg_t *, http_t *, char b[], isize_t bsiz, int eos); SOFIA_END_DECLS #endif /* !defined(HTTP_PARSER_H) */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/http/sofia-sip/http_protos.h.in000066400000000000000000000211261223300710500255700ustar00rootroot00000000000000/** -*- C -*- * @file sofia-sip/http_protos.h.in * * Template for . */ /* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef HTTP_PROTOS_H /** Defined when has been included. */ #define HTTP_PROTOS_H /**@file sofia-sip/http_protos.h * * Macros for each HTTP header. * * #AUTO# * * @author Pekka Pessi */ #include #ifndef HTTP_HEADER_H #include #endif #ifndef HTTP_HCLASSES_H #include #endif #define http_header_make(h, c, s) \ ((http_header_t *)msg_header_make((h), (c), (s))) #define http_header_vformat(h, c, f, a) \ ((http_header_t *)msg_header_vformat((h), (c), (f), (a))) SOFIA_BEGIN_DECLS /* Declare internal prototypes for #xxxxxxx_xxxxxxx# */ /**@addtogroup http_#xxxxxx#*/ /** @{ */ enum { /** Hash of #xxxxxxx_xxxxxxx#. @internal*/ http_#xxxxxx#_hash = #hash# }; /**Header class for HTTP #xxxxxxx_xxxxxxx#. * * The header class http_#xxxxxx#_class defines how a HTTP * #xxxxxxx_xxxxxxx# is parsed and printed. It also * contains methods used by HTTP parser and other functions * to manipulate the http_#xxxxxx#_t header structure. * */ SOFIAPUBVAR msg_hclass_t http_#xxxxxx#_class[]; #ifndef HTTP_HCLASSES_ONLY /** Decode (parse) a #xxxxxxx_xxxxxxx#. @internal */ SOFIAPUBFUN msg_parse_f http_#xxxxxx#_d; /** Encode (print) a #xxxxxxx_xxxxxxx#. @internal */ SOFIAPUBFUN msg_print_f http_#xxxxxx#_e; /**Initializer for structure http_#xxxxxx#_t. * * A static http_#xxxxxx#_t structure must be initialized * with the HTTP_#XXXXXX#_INIT() macro. For instance, * @code * * http_#xxxxxx#_t http_#xxxxxx# = HTTP_#XXXXXX#_INIT; * * @endcode * @HI */ #define HTTP_#XXXXXX#_INIT() HTTP_HDR_INIT(#xxxxxx#) /**Initialize a structure http_#xxxxxx#_t. * * An http_#xxxxxx#_t structure can be initialized with the * http_#xxxxxx#_init() function/macro. For instance, * @code * * http_#xxxxxx#_t http_#xxxxxx#; * * http_#xxxxxx#_init(&http_#xxxxxx#); * * @endcode * @HI */ #if SU_HAVE_INLINE su_inline http_#xxxxxx#_t *http_#xxxxxx#_init(http_#xxxxxx#_t x[1]) { return HTTP_HEADER_INIT(x, http_#xxxxxx#_class, sizeof(http_#xxxxxx#_t)); } #else #define http_#xxxxxx#_init(x) \ HTTP_HEADER_INIT(x, http_#xxxxxx#_class, sizeof(http_#xxxxxx#_t)) #endif /**Test if header object is instance of http_#xxxxxx#_t. * * The function http_is_#xxxxxx#() returns true (nonzero) if * the header class is an instance of #xxxxxxx_xxxxxxx# * object and false (zero) otherwise. * * @param header pointer to the header structure to be tested * * @return * The function http_is_x#xxxxxx#() returns true (nonzero) if * the header object is an instance of header #xxxxxx# and * false (zero) otherwise. */ #if SU_HAVE_INLINE su_inline int http_is_#xxxxxx#(http_header_t const *header) { return header && header->sh_class->hc_hash == http_#xxxxxx#_hash; } #else #define http_is_#xxxxxx#(h) \ ((h) && ((msg_common_t *)(h))->h_class->hc_hash == http_#xxxxxx#_hash) #endif /**Duplicate (deep copy) @c http_#xxxxxx#_t. * * The function http_#xxxxxx#_dup() duplicates a header * structure @a hdr. If the header structure @a hdr * contains a reference (@c hdr->x_next) to a list of * headers, all the headers in the list are duplicated, too. * * @param home memory home used to allocate new structure * @param hdr header structure to be duplicated * * When duplicating, all parameter lists and non-constant * strings attached to the header are copied, too. The * function uses given memory @a home to allocate all the * memory areas used to copy the header. * * @par Example * @code * * #xxxxxx# = http_#xxxxxx#_dup(home, http->http_#xxxxxx#); * * @endcode * * @return * The function http_#xxxxxx#_dup() returns a pointer to the * newly duplicated http_#xxxxxx#_t header structure, or NULL * upon an error. */ #if SU_HAVE_INLINE su_inline #endif http_#xxxxxx#_t *http_#xxxxxx#_dup(su_home_t *home, http_#xxxxxx#_t const *hdr) __attribute__((__malloc__)); /**Copy a http_#xxxxxx#_t header structure. * * The function http_#xxxxxx#_copy() copies a header structure @a * hdr. If the header structure @a hdr contains a reference (@c * hdr->h_next) to a list of headers, all the headers in that * list are copied, too. The function uses given memory @a home * to allocate all the memory areas used to copy the header * structure @a hdr. * * @param home memory home used to allocate new structure * @param hdr pointer to the header structure to be duplicated * * When copying, only the header structure and parameter lists * attached to it are duplicated. The new header structure * retains all the references to the strings within the old @a * header, including the encoding of the old header, if present. * * @par Example * @code * * #xxxxxx# = http_#xxxxxx#_copy(home, http->http_#xxxxxx#); * * @endcode * * @return * The function http_#xxxxxx#_copy() returns a pointer to * newly copied header structure, or NULL upon an error. */ #if SU_HAVE_INLINE su_inline #endif http_#xxxxxx#_t *http_#xxxxxx#_copy(su_home_t *home, http_#xxxxxx#_t const *hdr) __attribute__((__malloc__)); /**Make a header structure http_#xxxxxx#_t. * * The function http_#xxxxxx#_make() makes a new * http_#xxxxxx#_t header structure. It allocates a new * header structure, and decodes the string @a s as the * value of the structure. * * @param home memory home used to allocate new header structure. * @param s string to be decoded as value of the new header structure * * @note This function is usually implemented as a macro calling * http_header_make(). * * @return * The function http_#xxxxxx#_make() returns a pointer to * newly maked http_#xxxxxx#_t header structure, or NULL upon * an error. */ #if SU_HAVE_INLINE su_inline #endif http_#xxxxxx#_t *http_#xxxxxx#_make(su_home_t *home, char const *s) __attribute__((__malloc__)); /**Make a #xxxxxxx_xxxxxxx# from formatting result. * * The function http_#xxxxxx#_format() makes a new * #xxxxxxx_xxxxxxx# object using formatting result as its * value. The function first prints the arguments according to * the format @a fmt specified. Then it allocates a new header * structure, and uses the formatting result as the header * value. * * @param home memory home used to allocate new header structure. * @param fmt string used as a printf()-style format * @param ... argument list for format * * @note This function is usually implemented as a macro calling * msg_header_format(). * * @return * The function http_#xxxxxx#_format() returns a pointer to newly * makes header structure, or NULL upon an error. * * @HIDE */ #if SU_HAVE_INLINE su_inline #endif http_#xxxxxx#_t *http_#xxxxxx#_format(su_home_t *home, char const *fmt, ...) __attribute__((__malloc__, __format__ (printf, 2, 3))); /* Inlined functions */ #if SU_HAVE_INLINE su_inline http_#xxxxxx#_t *http_#xxxxxx#_format(su_home_t *home, char const *fmt, ...) { http_header_t *h; va_list ap; va_start(ap, fmt); h = http_header_vformat(home, http_#xxxxxx#_class, fmt, ap); va_end(ap); return (http_#xxxxxx#_t *)h; } su_inline http_#xxxxxx#_t *http_#xxxxxx#_dup(su_home_t *home, http_#xxxxxx#_t const *o) { return (http_#xxxxxx#_t *) msg_header_dup_as(home, http_#xxxxxx#_class, (msg_header_t const *)o); } su_inline http_#xxxxxx#_t *http_#xxxxxx#_copy(su_home_t *home, http_#xxxxxx#_t const *o) { return (http_#xxxxxx#_t *) msg_header_copy_as(home, http_#xxxxxx#_class, (msg_header_t const *)o); } su_inline http_#xxxxxx#_t *http_#xxxxxx#_make(su_home_t *home, char const *s) { return (http_#xxxxxx#_t *)http_header_make(home, http_#xxxxxx#_class, s); } #endif #endif /* !define HTTP_HCLASSES_ONLY */ /** @} */ SOFIA_END_DECLS #endif /* !defined(HTTP_PROTOS_H) */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/http/sofia-sip/http_status.h000066400000000000000000000131331223300710500251570ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef HTTP_STATUS_H #define HTTP_STATUS_H /**@file sofia-sip/http_status.h * * HTTP status codes. * * @author Pekka Pessi * * @date Created: Tue Sep 18 18:55:09 2001 ppessi */ #include SOFIA_BEGIN_DECLS SOFIAPUBFUN char const *http_status_phrase(int status); #define HTTP_100_CONTINUE 100, http_100_continue #define HTTP_101_SWITCHING 101, http_101_switching #define HTTP_200_OK 200, http_200_ok #define HTTP_201_CREATED 201, http_201_created #define HTTP_202_ACCEPTED 202, http_202_accepted #define HTTP_203_NON_AUTH_INFO 203, http_203_non_auth_info #define HTTP_204_NO_CONTENT 204, http_204_no_content #define HTTP_205_RESET_CONTENT 205, http_205_reset_content #define HTTP_206_PARTIAL_CONTENT 206, http_206_partial_content #define HTTP_300_MULTIPLE_CHOICES 300, http_300_multiple_choices #define HTTP_301_MOVED_PERMANENTLY 301, http_301_moved_permanently #define HTTP_302_FOUND 302, http_302_found #define HTTP_303_SEE_OTHER 303, http_303_see_other #define HTTP_304_NOT_MODIFIED 304, http_304_not_modified #define HTTP_305_USE_PROXY 305, http_305_use_proxy #define HTTP_307_TEMPORARY_REDIRECT 307, http_307_temporary_redirect #define HTTP_400_BAD_REQUEST 400, http_400_bad_request #define HTTP_401_UNAUTHORIZED 401, http_401_unauthorized #define HTTP_402_PAYMENT_REQUIRED 402, http_402_payment_required #define HTTP_403_FORBIDDEN 403, http_403_forbidden #define HTTP_404_NOT_FOUND 404, http_404_not_found #define HTTP_405_NOT_ALLOWED 405, http_405_not_allowed #define HTTP_406_NOT_ACCEPTABLE 406, http_406_not_acceptable #define HTTP_407_PROXY_AUTH 407, http_407_proxy_auth #define HTTP_408_TIMEOUT 408, http_408_timeout #define HTTP_409_CONFLICT 409, http_409_conflict #define HTTP_410_GONE 410, http_410_gone #define HTTP_411_NO_LENGTH 411, http_411_no_length #define HTTP_412_PRECONDITION 412, http_412_precondition #define HTTP_413_ENTITY_TOO_LARGE 413, http_413_entity_too_large #define HTTP_414_URI_TOO_LONG 414, http_414_uri_too_long #define HTTP_415_MEDIA_TYPE 415, http_415_media_type #define HTTP_416_REQUESTED_RANGE 416, http_416_requested_range #define HTTP_417_EXPECTATION 417, http_417_expectation #define HTTP_426_UPGRADE 426, http_426_upgrade #define HTTP_500_INTERNAL_SERVER 500, http_500_internal_server #define HTTP_501_NOT_IMPLEMENTED 501, http_501_not_implemented #define HTTP_502_BAD_GATEWAY 502, http_502_bad_gateway #define HTTP_503_NO_SERVICE 503, http_503_no_service #define HTTP_504_GATEWAY_TIMEOUT 504, http_504_gateway_timeout #define HTTP_505_HTTP_VERSION 505, http_505_http_version SOFIAPUBVAR char const http_100_continue[]; SOFIAPUBVAR char const http_101_switching[]; SOFIAPUBVAR char const http_200_ok[]; SOFIAPUBVAR char const http_201_created[]; SOFIAPUBVAR char const http_202_accepted[]; SOFIAPUBVAR char const http_203_non_auth_info[]; SOFIAPUBVAR char const http_204_no_content[]; SOFIAPUBVAR char const http_205_reset_content[]; SOFIAPUBVAR char const http_206_partial_content[]; SOFIAPUBVAR char const http_300_multiple_choices[]; SOFIAPUBVAR char const http_301_moved_permanently[]; SOFIAPUBVAR char const http_302_found[]; SOFIAPUBVAR char const http_303_see_other[]; SOFIAPUBVAR char const http_304_not_modified[]; SOFIAPUBVAR char const http_305_use_proxy[]; SOFIAPUBVAR char const http_307_temporary_redirect[]; SOFIAPUBVAR char const http_400_bad_request[]; SOFIAPUBVAR char const http_401_unauthorized[]; SOFIAPUBVAR char const http_402_payment_required[]; SOFIAPUBVAR char const http_403_forbidden[]; SOFIAPUBVAR char const http_404_not_found[]; SOFIAPUBVAR char const http_405_not_allowed[]; SOFIAPUBVAR char const http_406_not_acceptable[]; SOFIAPUBVAR char const http_407_proxy_auth[]; SOFIAPUBVAR char const http_408_timeout[]; SOFIAPUBVAR char const http_409_conflict[]; SOFIAPUBVAR char const http_410_gone[]; SOFIAPUBVAR char const http_411_no_length[]; SOFIAPUBVAR char const http_412_precondition[]; SOFIAPUBVAR char const http_413_entity_too_large[]; SOFIAPUBVAR char const http_414_uri_too_long[]; SOFIAPUBVAR char const http_415_media_type[]; SOFIAPUBVAR char const http_416_requested_range[]; SOFIAPUBVAR char const http_417_expectation[]; SOFIAPUBVAR char const http_426_upgrade[]; SOFIAPUBVAR char const http_500_internal_server[]; SOFIAPUBVAR char const http_501_not_implemented[]; SOFIAPUBVAR char const http_502_bad_gateway[]; SOFIAPUBVAR char const http_503_no_service[]; SOFIAPUBVAR char const http_504_gateway_timeout[]; SOFIAPUBVAR char const http_505_http_version[]; SOFIA_END_DECLS #endif /* HTTP_STATUS_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/http/sofia-sip/http_tag.h.in000066400000000000000000000155431223300710500250230ustar00rootroot00000000000000/**@file sofia-sip/http_tag.h.in * * Template for . * * @date Created: Wed Feb 21 11:01:45 2001 ppessi */ /* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef HTTP_TAG_H /** Defined when has been included. */ #define HTTP_TAG_H /**@file sofia-sip/http_tag.h * @brief Tag class for HTTP headers * * #AUTO# * * @author Pekka Pessi * */ #ifndef SU_TAG_H #include #endif #ifndef SU_TAG_CLASS_H #include #endif #ifndef SU_TAG_CLASS_H #include #endif #ifndef HTTP_H #include #endif SOFIA_BEGIN_DECLS #define HTTPTAG(c, x) httptag_##c, httptag_##c##_v(x) #define HTTPTAG_REF(c, x) httptag_##c##_ref, httptag_##c##_vr(&(x)) #define HTTPTAG_STR(c, s) httptag_##c##_str, tag_str_v(s) #define HTTPTAG_STR_REF(c, s) httptag_##c##_str_ref, tag_str_vr(&(s)) /** Test if tag type marks a http_t structure. @HIDE */ #define HTTPTAG_P(tt) ((tt)->tt_class == httphdrtag_class) /** Test if tag type marks a HTTP header string. @HIDE */ #define HTTPTAG_STR_P(tt) ((tt)->tt_class == httpstrtag_class) /** Test if tag type marks a HTTP header structure. @HIDE */ #define HTTPTAG_HTTP_P(tt) ((tt)->tt_class == httpmsgtag_class) /** Test if tag item contains http_t structure. @HIDE */ #define HTTPTAGI_P(t) (HTTPTAG_P((t)->t_tag)) /** Test if tag item contains a HTTP header string. @HIDE */ #define HTTPTAGI_STR_P(t) (HTTPTAG_STR_P((t)->t_tag)) /** Test if tag item contains a HTTP header structure. @HIDE */ #define HTTPTAGI_HTTP_P(t) (HTTPTAG_HTTP_P((t)->t_tag)) SOFIAPUBVAR tag_class_t httphdrtag_class[1]; SOFIAPUBVAR tag_class_t httpstrtag_class[1]; SOFIAPUBVAR tag_class_t httpmsgtag_class[1]; /** Filter tag matching any http tag. */ #define HTTPTAG_ANY() httptag_any, ((tag_value_t)0) SOFIAPUBVAR tag_typedef_t httptag_any; /**Tag list item for @c http_t object. * * The HTTPTAG_HTTP() macro is used to include a tag item for a http_t object * in the tag list. * * @param x pointer to a http_t message object, or NULL. * * @HIDE */ #define HTTPTAG_HTTP(x) httptag_http, httptag_http_v((x)) /** Tag for @c http_t */ SOFIAPUBVAR tag_typedef_t httptag_http; #define HTTPTAG_HTTP_REF(x) httptag_http_ref, httptag_http_vr(&(x)) SOFIAPUBVAR tag_typedef_t httptag_http_ref; #if SU_INLINE_TAG_CAST su_inline tag_value_t httptag_http_v(http_t const *v) { return (tag_value_t)v; } su_inline tag_value_t httptag_http_vr(http_t const **vp) { return (tag_value_t)vp; } #else #define httptag_http_v(v) (tag_value_t)(v) #define httptag_http_vr(vp) (tag_value_t)(vp) #endif /**Tag list item for http protocol version. * * The HTTPTAG_VERSION() macro is used to include a tag item for a HTTP * protocol version in the tag list. * * @param x pointer to a http_t message object, or NULL. */ #define HTTPTAG_VERSION(x) httptag_http, (tag_value_t)x extern tag_typedef_t httptag_version; /** Reference to HTTPTAG_VERSION */ #define HTTPTAG_VERSION_REF(x) httptag_http_ref, (tag_value_t)&(x) extern tag_typedef_t httptag_version_ref; /**Tag list item for header string. * * The HTTPTAG_HEADER() macro is used to include a tag item containing an * unknown HTTP header in the tag list, e.g., * @code * http_header_t *hdr; * * HTTPTAG_HEADER(hdr). * @endcode * * @param x pointer to a header structure, or NULL. * * @HIDE */ #define HTTPTAG_HEADER(x) httptag_header, httptag_header_v((x)) /** Tag for header string */ SOFIAPUBVAR tag_typedef_t httptag_header; #define HTTPTAG_HEADER_REF(x) httptag_header_ref, httptag_header_vr(&(x)) SOFIAPUBVAR tag_typedef_t httptag_header_ref; #if SU_INLINE_TAG_CAST su_inline tag_value_t httptag_header_v(http_header_t const *v) { return (tag_value_t)v; } su_inline tag_value_t httptag_header_vr(http_header_t const **vp) { return (tag_value_t)vp; } #else #define httptag_header_v(v) (tag_value_t)(v) #define httptag_header_vr(vp) (tag_value_t)(vp) #endif /**Tag list item for header string. * * The HTTPTAG_HEADER_STR() macro is used to include a tag item containing a * header string in the tag list. * * @param x pointer to a string, or NULL. * * @HIDE */ #define HTTPTAG_HEADER_STR(x) httptag_header_str, tag_str_v((x)) /** Tag for header string */ SOFIAPUBVAR tag_typedef_t httptag_header_str; #define HTTPTAG_HEADER_STR_REF(x) httptag_header_str_ref, tag_str_vr(&(x)) SOFIAPUBVAR tag_typedef_t httptag_header_str_ref; /**@ingroup http_#xxxxxx# * * Tag list item for pointer to a #xxxxxxx_xxxxxxx# object. * * The HTTPTAG_#XXXXXX#() macro is used to include a tag item with a * pointer to a http_#xxxxxx#_t object in a tag list. * * @param x pointer to a http_#xxxxxx#_t header structure, or NULL. * * @HIDE */ #define HTTPTAG_#XXXXXX#(x) HTTPTAG(#xxxxxx#, x) SOFIAPUBVAR tag_typedef_t httptag_#xxxxxx#; /**@ingroup http_#xxxxxx# * * Tag list item for string with #xxxxxxx_xxxxxxx# value. * * The HTTPTAG_#XXXXXX#_STR() macro is used to include a tag item with a * string containing value of a http_#xxxxxx#_t header in a tag list. * * @param s pointer to a string containing http_#xxxxxx#_t value, or NULL. * * The HTTPTAG_#XXXXXX#_STR string can be converted to a * http_#xxxxxx#_t header structure by giving the string @a s has * second argument to function http_#xxxxxx#_make(). * * @HIDE */ #define HTTPTAG_#XXXXXX#_STR(s) HTTPTAG_STR(#xxxxxx#, s) SOFIAPUBVAR tag_typedef_t httptag_#xxxxxx#_str; #define HTTPTAG_#XXXXXX#_REF(x) HTTPTAG_REF(#xxxxxx#, x) SOFIAPUBVAR tag_typedef_t httptag_#xxxxxx#_ref; #define HTTPTAG_#XXXXXX#_STR_REF(x) HTTPTAG_STR_REF(#xxxxxx#, x) SOFIAPUBVAR tag_typedef_t httptag_#xxxxxx#_str_ref; #if SU_INLINE_TAG_CAST su_inline tag_value_t httptag_#xxxxxx#_v(http_#xxxxxx#_t const *v) { return (tag_value_t)v; } su_inline tag_value_t httptag_#xxxxxx#_vr(http_#xxxxxx#_t const **vp) { return (tag_value_t)vp; } #else #define httptag_#xxxxxx#_v(v) (tag_value_t)(v) #define httptag_#xxxxxx#_vr(vp) (tag_value_t)(vp) #endif SOFIA_END_DECLS #endif /* !defined(HTTP_TAG_H) */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/http/sofia-sip/http_tag_class.h000066400000000000000000000041671223300710500256030ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef HTTP_TAG_CLASS_H /**Defined when http_tag_class.h have been included*/ #define HTTP_TAG_CLASS_H /**@file sofia-sip/http_tag_class.h * @brief Tag classes for HTTP headers. * * @author Pekka Pessi * * @date Created: Wed Feb 21 11:01:45 2001 ppessi */ #ifndef SU_TAG_CLASS_H #include #endif #ifndef MSG_TAG_CLASS_H #include #endif SOFIA_BEGIN_DECLS /** Define a named tag type for HTTP header @a t. */ #define HTTPHDRTAG_NAMED_TYPEDEF(n, t) \ {{ TAG_NAMESPACE, #n, httphdrtag_class, \ (tag_value_t)http_##t##_class }} /** Define a tag type for HTTP header @a t. */ #define HTTPHDRTAG_TYPEDEF(t) HTTPHDRTAG_NAMED_TYPEDEF(t, t) /** Define a string tag type for HTTP header @a t. */ #define HTTPSTRTAG_TYPEDEF(t) \ {{ TAG_NAMESPACE, #t "_str", httpstrtag_class, \ (tag_value_t)http_##t##_class }} /** Define a tag type for HTTP message @a t. */ #define HTTPMSGTAG_TYPEDEF(t) \ {{ TAG_NAMESPACE, #t, httpmsgtag_class, \ (tag_value_t)HTTP_PROTOCOL_TAG }} /**@internal Filter HTTP header tag items. */ SOFIAPUBFUN tagi_t *httptag_filter(tagi_t *dst, tagi_t const f[], tagi_t const *src, void **bb); SOFIA_END_DECLS #endif /* !defined(HTTP_TAG_CLASS_H) */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/http/test_http.c000066400000000000000000001302641223300710500227210ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE test_http.c * * Testing functions for HTTP parser. * * @author Pekka Pessi * * @date Created: Tue Mar 6 18:33:42 2001 ppessi */ #include "config.h" /* Avoid casting http_t to msg_pub_t and http_header_t to msg_header_t */ #define MSG_PUB_T struct http_s #define MSG_HDR_T union http_header_u #include #include #include #include #include #include #include #include #include #include #define TSTFLAGS tstflags #include #include #include #include #include #include char const *name = "test_http"; static int tag_test(void); static int tag_test2(void); static int http_header_handling_test(void); static int http_header_test(void); static int http_parser_test(void); static int test_http_encoding(void); static int http_chunk_test(void); static int http_tag_test(void); static int test_query_parser(void); static msg_t *read_message(char const string[]); msg_mclass_t const *test_mclass = NULL; char *lastpart(char *path) { if (strchr(path, '/')) return strrchr(path, '/') + 1; else return path; } int tstflags; void usage(int exitcode) { fprintf(stderr, "usage: %s [-v] [-a]\n", name); exit(exitcode); } int main(int argc, char *argv[]) { int retval = 0; int i; name = lastpart(argv[0]); /* Set our name */ for (i = 1; argv[i]; i++) { if (strcmp(argv[i], "-v") == 0) tstflags |= tst_verbatim; else if (strcmp(argv[i], "-a") == 0) tstflags |= tst_abort; else usage(1); } #if HAVE_OPEN_C tstflags |= tst_verbatim; #endif if (!test_mclass) test_mclass = http_default_mclass(); retval |= tag_test(); fflush(stdout); retval |= tag_test2(); fflush(stdout); retval |= http_header_handling_test(); fflush(stdout); retval |= http_header_test(); fflush(stdout); retval |= http_tag_test(); fflush(stdout); retval |= http_parser_test(); fflush(stdout); retval |= test_http_encoding(); fflush(stdout); retval |= http_chunk_test(); fflush(stdout); retval |= test_query_parser(); fflush(stdout); #if HAVE_OPEN_C sleep(5); #endif return retval; } msg_t *read_message(char const buffer[]) { int i, n, m; msg_t *msg; msg_iovec_t iovec[2]; n = strlen(buffer); if (n == 0) return NULL; msg = msg_create(test_mclass, MSG_DO_EXTRACT_COPY); for (i = 0; i < n;) { if (msg_recv_iovec(msg, iovec, 2, 10, 0) < 0) { perror("msg_recv_iovec"); return NULL; } *(char *)(iovec->mv_base) = buffer[i++]; msg_recv_commit(msg, 1, i == n); m = msg_extract(msg); if (m < 0) { fprintf(stderr, "test_http: parsing error\n"); return NULL; } if (m > 0) break; } if (i != n) { fprintf(stderr, "test_http: parser error (len=%u, read=%u)\n", n, i); msg_destroy(msg), msg = NULL; } return msg; } /* Read message byte-by-byte */ msg_t *read_message_byte_by_byte(char const buffer[]) { int i, n, m; msg_t *msg; msg_iovec_t iovec[msg_n_fragments]; n = strlen(buffer); if (n == 0) return NULL; msg = msg_create(test_mclass, MSG_DO_EXTRACT_COPY); for (i = 0; i < n;) { /* This prevent msg_recv_iovec() from allocating extra slack */ int msg_buf_exact(msg_t *, int); msg_buf_exact(msg, 10 + 1); if (msg_recv_iovec(msg, iovec, msg_n_fragments, 10, 0) < 0) { perror("msg_recv_iovec"); return NULL; } assert(iovec->mv_len > 0); *(char *)(iovec->mv_base) = buffer[i++]; msg_recv_commit(msg, 1, i == n); m = msg_extract(msg); if (m < 0) { fprintf(stderr, "test_http: parsing error\n"); return NULL; } if (m > 0) break; } if (i != n) { fprintf(stderr, "test_http: parser error (len=%u, read=%u)\n", n, i); msg_destroy(msg), msg = NULL; } return msg; } static int header_size(http_header_t *h) { int offset = 0; for (; h; h = h->sh_next) { offset += SU_ALIGN(offset) + h->sh_class->hc_size; offset = h->sh_class->hc_dxtra(h, offset); } return offset; } #define XTRA(xtra, h) SU_ALIGN(xtra) + header_size((http_header_t*)h) /** Test header filtering and duplicating */ static int tag_test(void) { su_home_t *home = su_home_new(sizeof *home); http_request_t *request = http_request_make(home, "GET /test/path HTTP/1.1"); http_via_t *via = http_via_make(home, "1.1 http.example.com, 1.0 fred"); http_host_t *host = http_host_make(home, "http.example.com:8080"); http_max_forwards_t *mf = http_max_forwards_make(home, "16"); url_t *url = url_hdup(home, (url_t *)"http://host:80/test/path"); tagi_t *lst, *dup; int xtra; BEGIN(); su_home_check(home); TEST_1(home); TEST_1(request); TEST_1(host); TEST_1(via); TEST_1(via->v_next); lst = tl_list(HTTPTAG_REQUEST(request), HTTPTAG_HOST(host), HTTPTAG_VIA(via), HTTPTAG_MAX_FORWARDS(mf), URLTAG_URL(url), TAG_NULL()); xtra = 0; xtra += XTRA(xtra, request); xtra += XTRA(xtra, host); xtra += XTRA(xtra, via); xtra += XTRA(xtra, mf); xtra += SU_ALIGN(xtra) + sizeof(*url) + url_xtra(url); TEST_SIZE(tl_xtra(lst, 0), xtra); TEST_SIZE(tl_len(lst), 6 * sizeof(tagi_t)); dup = tl_adup(NULL, lst); TEST_1(dup != NULL); TEST_SIZE(tl_len(dup), 6 * sizeof(tagi_t)); TEST_SIZE(tl_xtra(dup, 0), xtra); if (tstflags & tst_verbatim) tl_print(stdout, "dup:\n", dup); su_free(NULL, dup); tl_vfree(lst); su_home_unref(home); END(); } /** Test advanced tag features */ static int tag_test2(void) { BEGIN(); #if 0 tagi_t *lst, *dup, *filter1, *filter2, *filter3, *filter4, *b1, *b2, *b3, *b4; msg_t *msg; http_t *http; su_home_t *home; int xtra; home = su_home_new(sizeof *home); msg = read_message("HTTP/2.0 401 Unauthorized\r\n" "Content-Length: 0\r\n" "\r\n"); http = msg_object(msg); TEST_1(home && msg && http); TEST_1(http_status_p((http_header_t *)http->http_status)); TEST_1(http_content_length_p((http_header_t *)http->http_content_length)); lst = tl_list(HTTPTAG_VIA(http->http_via), HTTPTAG_RECORD_ROUTE(http->http_record_route), TAG_SKIP(2), HTTPTAG_CSEQ(http->http_cseq), HTTPTAG_PAYLOAD(http->http_payload), TAG_NULL()); filter1 = tl_list(HTTPTAG_VIA(0), TAG_NULL()); filter2 = tl_list(HTTPTAG_CALL_ID(0), HTTPTAG_FROM(0), HTTPTAG_ROUTE(0), HTTPTAG_CSEQ(0), TAG_NULL()); filter3 = tl_list(HTTPTAG_CSEQ(0), HTTPTAG_CONTENT_LENGTH(0), TAG_NULL()); filter4 = tl_list(HTTPTAG_STATUS(0), HTTPTAG_VIA(0), HTTPTAG_RECORD_ROUTE(0), HTTPTAG_FROM(0), HTTPTAG_TO(0), HTTPTAG_CALL_ID(0), HTTPTAG_CSEQ(0), HTTPTAG_WWW_AUTHENTICATE(0), HTTPTAG_PROXY_AUTHENTICATE(0), HTTPTAG_CONTENT_LENGTH(0), TAG_NULL()); TEST_1(lst && filter1 && filter2 && filter3 && filter4); b1 = tl_afilter(home, filter1, lst); TEST(tl_len(b1), 2 * sizeof(tagi_t)); TEST_1(((http_via_t *)b1->t_value)->v_next); xtra = http_header_size((http_header_t *)http->http_via); xtra += SU_ALIGN(xtra); xtra += http_header_size((http_header_t *)http->http_via->v_next); TEST(tl_xtra(b1, 0), xtra); dup = tl_adup(home, lst); TEST(tl_len(dup), tl_len(lst)); TEST(tl_xtra(dup, 0), tl_xtra(lst, 0)); tl_vfree(lst); lst = tl_list(HTTPTAG_HTTP(http), TAG_NULL()); b2 = tl_afilter(home, filter2, lst); TEST(tl_len(b2), 4 * sizeof(tagi_t)); xtra = 0; xtra += XTRA(xtra, http->http_call_id); xtra += XTRA(xtra, http->http_from); xtra += XTRA(xtra, http->http_cseq); TEST(tl_xtra(b2, 0), xtra); b3 = tl_afilter(home, filter3, lst); TEST(tl_len(b3), 3 * sizeof(tagi_t)); TEST(tl_xtra(b3, 0), sizeof(http_content_length_t) + sizeof(http_cseq_t)); b4 = tl_afilter(home, filter4, lst); TEST(tl_len(b4), 11 * sizeof(tagi_t)); xtra = 0; xtra += XTRA(xtra, http->http_status); xtra += XTRA(xtra, http->http_via); xtra += XTRA(xtra, http->http_via->v_next); xtra += XTRA(xtra, http->http_record_route); xtra += XTRA(xtra, http->http_from); xtra += XTRA(xtra, http->http_to); xtra += XTRA(xtra, http->http_call_id); xtra += XTRA(xtra, http->http_cseq); xtra += XTRA(xtra, http->http_www_authenticate); xtra += XTRA(xtra, http->http_proxy_authenticate); xtra += XTRA(xtra, http->http_content_length); TEST(tl_xtra(b4, 0), xtra); tl_vfree(filter1); tl_vfree(filter2); tl_vfree(filter3); tl_vfree(filter4); tl_vfree(lst); su_home_check(home); su_free(home, b4); su_free(home, b3); su_free(home, b2); su_free(home, dup); su_free(home, b1); su_home_check(home); su_home_unref(home); #endif END(); } /** Test parser and header manipulation */ static int http_header_handling_test(void) { msg_t *msg; http_t *http; su_home_t *home; http_request_t http_request[1]; http_status_t http_status[1]; http_unknown_t http_unknown[1]; http_separator_t http_separator[1]; http_payload_t http_payload[1]; http_via_t http_via[1]; http_host_t http_host[1]; http_from_t http_from[1]; http_referer_t http_referer[1]; http_connection_t http_connection[1]; http_accept_t http_accept[1]; http_accept_charset_t http_accept_charset[1]; http_accept_encoding_t http_accept_encoding[1]; http_accept_language_t http_accept_language[1]; http_accept_ranges_t http_accept_ranges[1]; http_allow_t http_allow[1]; http_te_t http_te[1]; http_authorization_t http_authorization[1]; http_www_authenticate_t http_www_authenticate[1]; http_proxy_authenticate_t http_proxy_authenticate[1]; http_proxy_authorization_t http_proxy_authorization[1]; http_age_t http_age[1]; http_cache_control_t http_cache_control[1]; http_date_t http_date[1]; http_expires_t http_expires[1]; http_if_match_t http_if_match[1]; http_if_modified_since_t http_if_modified_since[1]; http_if_none_match_t http_if_none_match[1]; http_if_range_t http_if_range[1]; http_if_unmodified_since_t http_if_unmodified_since[1]; http_etag_t http_etag[1]; http_expect_t http_expect[1]; http_last_modified_t http_last_modified[1]; http_location_t http_location[1]; http_max_forwards_t http_max_forwards[1]; http_pragma_t http_pragma[1]; http_range_t http_range[1]; http_retry_after_t http_retry_after[1]; http_trailer_t http_trailer[1]; http_upgrade_t http_upgrade[1]; http_vary_t http_vary[1]; http_warning_t http_warning[1]; http_user_agent_t http_user_agent[1]; http_server_t http_server[1]; http_mime_version_t http_mime_version[1]; http_content_language_t http_content_language[1]; http_content_location_t http_content_location[1]; http_content_md5_t http_content_md5[1]; http_content_range_t http_content_range[1]; http_content_encoding_t http_content_encoding[1]; http_transfer_encoding_t http_transfer_encoding[1]; http_content_type_t http_content_type[1]; http_content_length_t http_content_length[1]; BEGIN(); http_request_init(http_request); http_status_init(http_status); http_unknown_init(http_unknown); http_separator_init(http_separator); http_payload_init(http_payload); http_via_init(http_via); http_host_init(http_host); http_from_init(http_from); http_referer_init(http_referer); http_connection_init(http_connection); http_accept_init(http_accept); http_accept_charset_init(http_accept_charset); http_accept_encoding_init(http_accept_encoding); http_accept_language_init(http_accept_language); http_accept_ranges_init(http_accept_ranges); http_allow_init(http_allow); http_te_init(http_te); http_authorization_init(http_authorization); http_www_authenticate_init(http_www_authenticate); http_proxy_authenticate_init(http_proxy_authenticate); http_proxy_authorization_init(http_proxy_authorization); http_age_init(http_age); http_cache_control_init(http_cache_control); http_date_init(http_date); http_expires_init(http_expires); http_if_match_init(http_if_match); http_if_modified_since_init(http_if_modified_since); http_if_none_match_init(http_if_none_match); http_if_range_init(http_if_range); http_if_unmodified_since_init(http_if_unmodified_since); http_etag_init(http_etag); http_expect_init(http_expect); http_last_modified_init(http_last_modified); http_location_init(http_location); http_max_forwards_init(http_max_forwards); http_pragma_init(http_pragma); http_range_init(http_range); http_retry_after_init(http_retry_after); http_trailer_init(http_trailer); http_upgrade_init(http_upgrade); http_vary_init(http_vary); http_warning_init(http_warning); http_user_agent_init(http_user_agent); http_server_init(http_server); http_mime_version_init(http_mime_version); http_content_language_init(http_content_language); http_content_location_init(http_content_location); http_content_md5_init(http_content_md5); http_content_range_init(http_content_range); http_content_encoding_init(http_content_encoding); http_transfer_encoding_init(http_transfer_encoding); http_content_type_init(http_content_type); http_content_length_init(http_content_length); home = su_home_new(sizeof *home); { int i; struct { http_method_t number; char const *name; } methods[] = { { http_method_get, "GET" }, { http_method_post, "POST" }, { http_method_head, "HEAD" }, { http_method_options, "OPTIONS" }, { http_method_put, "PUT" }, { http_method_delete, "DELETE" }, { http_method_trace, "TRACE" }, { http_method_connect, "CONNECT" }, { 0, NULL } }; for (i = 0; methods[i].name; i++) { TEST_1(strcmp(methods[i].name, http_method_name(methods[i].number, "")) == 0); } } msg = read_message( "PUT /Foo HTTP/1.1\r\n" "Host: [::1]:8080\r\n" "From: webmaster@w3.org\r\n" "Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)\r\n" "Referer: http://www.w3.org/hypertext/DataSources/Overview.html\r\n" "Connection: close\r\n" "Accept: audio/*; q=0.2, audio/basic\r\n" "Accept-Charset: iso-8859-5, unicode-1-1;q=0.8\r\n" "Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0\r\n" "Accept-Language: da, en-gb;q=0.8, en;q=0.7\r\n" "Accept-Ranges: bytes\r\n" "Age: 212\r\n" "Allow: GET, HEAD, PUT\r\n" "Cache-Control: private, community=\"UCI\"\r\n" "Content-Encoding: identity\r\n" "Content-Language: da\r\n" "Content-Type: text/html\r\n" "Content-Location: http://localhost/Foo\r\n" "Content-Length: 28\r\n" "Content-MD5: f48BLMCjkX5M5PgWoelogA==\r\n" "Content-Range: bytes 0-27/*\r\n" "\r\n" "\r\n"); http = msg_object(msg); TEST_1(home && msg && http); TEST_1(http_is_request((http_header_t *)http->http_request)); TEST_1(http->http_via); TEST_1(http->http_via->v_next); TEST_1(http->http_via->v_next->v_next == NULL); TEST_1(http->http_host); TEST_1(http->http_from); TEST_1(http->http_referer); TEST_1(http->http_connection); TEST_1(http->http_accept); TEST_1(http->http_accept_charset); TEST_1(http->http_accept_encoding); TEST_1(http->http_accept_language); TEST_1(http->http_accept_ranges); TEST_1(http->http_age); TEST_1(http->http_allow); TEST_1(http->http_cache_control); TEST_1(http->http_content_encoding); TEST_1(http->http_content_language); TEST_1(http->http_content_type); TEST_1(http->http_content_location); TEST_1(http->http_content_length); TEST_1(http->http_content_md5); TEST_1(http->http_content_range); /* Quiet lots of warnings */ #define _msg_header_offset msg_header_offset #define msg_header_offset(msg, http, h) \ _msg_header_offset(msg, http, (http_header_t *)h) TEST_P(msg_header_offset(msg, http, http_request), &http->http_request); TEST_P(msg_header_offset(msg, http, http_status), &http->http_status); TEST_P(msg_header_offset(msg, http, http_unknown), &http->http_unknown); TEST_P(msg_header_offset(msg, http, http_separator), &http->http_separator); TEST_P(msg_header_offset(msg, http, http_payload), &http->http_payload); TEST_P(msg_header_offset(msg, http, http_via), &http->http_via); TEST_P(msg_header_offset(msg, http, http_via), &http->http_via); TEST_P(msg_header_offset(msg, http, http_host), &http->http_host); TEST_P(msg_header_offset(msg, http, http_from), &http->http_from); TEST_P(msg_header_offset(msg, http, http_referer), &http->http_referer); TEST_P(msg_header_offset(msg, http, http_connection), &http->http_connection); TEST_P(msg_header_offset(msg, http, http_accept), &http->http_accept); TEST_P(msg_header_offset(msg, http, http_accept_charset), &http->http_accept_charset); TEST_P(msg_header_offset(msg, http, http_accept_encoding), &http->http_accept_encoding); TEST_P(msg_header_offset(msg, http, http_accept_language), &http->http_accept_language); TEST_P(msg_header_offset(msg, http, http_accept_ranges), &http->http_accept_ranges); TEST_P(msg_header_offset(msg, http, http_allow), &http->http_allow); TEST_P(msg_header_offset(msg, http, http_te), &http->http_te); TEST_P(msg_header_offset(msg, http, http_authorization), &http->http_authorization); TEST_P(msg_header_offset(msg, http, http_www_authenticate), &http->http_www_authenticate); TEST_P(msg_header_offset(msg, http, http_proxy_authenticate), &http->http_proxy_authenticate); TEST_P(msg_header_offset(msg, http, http_proxy_authorization), &http->http_proxy_authorization); TEST_P(msg_header_offset(msg, http, http_age), &http->http_age); TEST_P(msg_header_offset(msg, http, http_cache_control), &http->http_cache_control); TEST_P(msg_header_offset(msg, http, http_date), &http->http_date); TEST_P(msg_header_offset(msg, http, http_expires), &http->http_expires); TEST_P(msg_header_offset(msg, http, http_if_match), &http->http_if_match); TEST_P(msg_header_offset(msg, http, http_if_modified_since), &http->http_if_modified_since); TEST_P(msg_header_offset(msg, http, http_if_none_match), &http->http_if_none_match); TEST_P(msg_header_offset(msg, http, http_if_range), &http->http_if_range); TEST_P(msg_header_offset(msg, http, http_if_unmodified_since), &http->http_if_unmodified_since); TEST_P(msg_header_offset(msg, http, http_etag), &http->http_etag); TEST_P(msg_header_offset(msg, http, http_expect), &http->http_expect); TEST_P(msg_header_offset(msg, http, http_last_modified), &http->http_last_modified); TEST_P(msg_header_offset(msg, http, http_location), &http->http_location); TEST_P(msg_header_offset(msg, http, http_max_forwards), &http->http_max_forwards); TEST_P(msg_header_offset(msg, http, http_pragma), &http->http_pragma); TEST_P(msg_header_offset(msg, http, http_range), &http->http_range); TEST_P(msg_header_offset(msg, http, http_retry_after), &http->http_retry_after); TEST_P(msg_header_offset(msg, http, http_trailer), &http->http_trailer); TEST_P(msg_header_offset(msg, http, http_upgrade), &http->http_upgrade); TEST_P(msg_header_offset(msg, http, http_vary), &http->http_vary); TEST_P(msg_header_offset(msg, http, http_warning), &http->http_warning); TEST_P(msg_header_offset(msg, http, http_user_agent), &http->http_user_agent); TEST_P(msg_header_offset(msg, http, http_server), &http->http_server); TEST_P(msg_header_offset(msg, http, http_mime_version), &http->http_mime_version); TEST_P(msg_header_offset(msg, http, http_content_language), &http->http_content_language); TEST_P(msg_header_offset(msg, http, http_content_location), &http->http_content_location); TEST_P(msg_header_offset(msg, http, http_content_md5), &http->http_content_md5); TEST_P(msg_header_offset(msg, http, http_content_range), &http->http_content_range); TEST_P(msg_header_offset(msg, http, http_content_encoding), &http->http_content_encoding); TEST_P(msg_header_offset(msg, http, http_transfer_encoding), &http->http_transfer_encoding); TEST_P(msg_header_offset(msg, http, http_content_type), &http->http_content_type); TEST_P(msg_header_offset(msg, http, http_content_length), &http->http_content_length); TEST_SIZE(http_via_class->hc_params, offsetof(http_via_t, v_common)); TEST_SIZE(http_host_class->hc_params, offsetof(http_host_t, h_common)); TEST_SIZE(http_from_class->hc_params, offsetof(http_from_t, g_common)); TEST_SIZE(http_referer_class->hc_params, offsetof(http_referer_t, loc_common)); TEST_SIZE(http_connection_class->hc_params, offsetof(http_connection_t, k_items)); TEST_SIZE(http_accept_class->hc_params, offsetof(http_accept_t, ac_params)); TEST_SIZE(http_accept_charset_class->hc_params, offsetof(http_accept_charset_t, aa_params)); TEST_SIZE(http_accept_encoding_class->hc_params, offsetof(http_accept_encoding_t, aa_params)); TEST_SIZE(http_accept_language_class->hc_params, offsetof(http_accept_language_t, aa_params)); TEST_SIZE(http_accept_ranges_class->hc_params, offsetof(http_accept_ranges_t, k_items)); TEST_SIZE(http_allow_class->hc_params, offsetof(http_allow_t, k_items)); TEST_SIZE(http_te_class->hc_params, offsetof(http_te_t, te_params)); TEST_SIZE(http_authorization_class->hc_params, offsetof(http_authorization_t, au_params)); TEST_SIZE(http_www_authenticate_class->hc_params, offsetof(http_www_authenticate_t, au_params)); TEST_SIZE(http_proxy_authenticate_class->hc_params, offsetof(http_proxy_authenticate_t, au_params)); TEST_SIZE(http_proxy_authorization_class->hc_params, offsetof(http_proxy_authorization_t, au_params)); TEST_SIZE(http_age_class->hc_params, offsetof(http_age_t, x_common)); TEST_SIZE(http_cache_control_class->hc_params, offsetof(http_cache_control_t, k_items)); TEST_SIZE(http_date_class->hc_params, offsetof(http_date_t, d_common)); TEST_SIZE(http_expires_class->hc_params, offsetof(http_expires_t, d_common)); TEST_SIZE(http_if_match_class->hc_params, offsetof(http_if_match_t, k_items)); TEST_SIZE(http_if_modified_since_class->hc_params, offsetof(http_if_modified_since_t, d_common)); TEST_SIZE(http_if_none_match_class->hc_params, offsetof(http_if_none_match_t, k_items)); TEST_SIZE(http_if_range_class->hc_params, offsetof(http_if_range_t, ifr_common)); TEST_SIZE(http_if_unmodified_since_class->hc_params, offsetof(http_if_unmodified_since_t, d_common)); TEST_SIZE(http_etag_class->hc_params, offsetof(http_etag_t, g_common)); TEST_SIZE(http_expect_class->hc_params, offsetof(http_expect_t, g_common)); TEST_SIZE(http_last_modified_class->hc_params, offsetof(http_last_modified_t, d_common)); TEST_SIZE(http_location_class->hc_params, offsetof(http_location_t, loc_common)); TEST_SIZE(http_max_forwards_class->hc_params, offsetof(http_max_forwards_t, mf_common)); TEST_SIZE(http_pragma_class->hc_params, offsetof(http_pragma_t, k_items)); TEST_SIZE(http_range_class->hc_params, offsetof(http_range_t, rng_specs)); TEST_SIZE(http_retry_after_class->hc_params, offsetof(http_retry_after_t, ra_common)); TEST_SIZE(http_trailer_class->hc_params, offsetof(http_trailer_t, k_items)); TEST_SIZE(http_upgrade_class->hc_params, offsetof(http_upgrade_t, k_items)); TEST_SIZE(http_vary_class->hc_params, offsetof(http_vary_t, k_items)); TEST_SIZE(http_warning_class->hc_params, offsetof(http_warning_t, w_common)); TEST_SIZE(http_user_agent_class->hc_params, offsetof(http_user_agent_t, g_common)); TEST_SIZE(http_server_class->hc_params, offsetof(http_server_t, g_common)); TEST_SIZE(http_mime_version_class->hc_params, offsetof(http_mime_version_t, g_common)); TEST_SIZE(http_content_language_class->hc_params, offsetof(http_content_language_t, k_items)); TEST_SIZE(http_content_location_class->hc_params, offsetof(http_content_location_t, g_common)); TEST_SIZE(http_content_md5_class->hc_params, offsetof(http_content_md5_t, g_common)); TEST_SIZE(http_content_range_class->hc_params, offsetof(http_content_range_t, cr_common)); TEST_SIZE(http_content_encoding_class->hc_params, offsetof(http_content_encoding_t, k_items)); TEST_SIZE(http_transfer_encoding_class->hc_params, offsetof(http_transfer_encoding_t, k_items)); TEST_SIZE(http_content_type_class->hc_params, offsetof(http_content_type_t, c_params)); TEST_SIZE(http_content_length_class->hc_params, offsetof(http_content_length_t, l_common)); su_home_unref(home); END(); } int count(msg_common_t *h) { http_header_t *sh = (http_header_t *)h; unsigned n; for (n = 0; sh; sh = sh->sh_next) n++; return n; } int len(msg_common_t *h) { msg_header_t *sh = (msg_header_t *)h; unsigned n; for (n = 0; sh; sh = sh->sh_next) { if (n) n +=2; n += msg_header_field_e(NULL, 0, sh, 0); } return n; } static int http_header_test(void) { su_home_t home[1] = { SU_HOME_INIT(home) }; BEGIN(); { http_request_t *rq; TEST_1(rq = http_request_make(home, "GET / HTTP/1.0")); TEST(rq->rq_method, http_method_get); TEST_S(rq->rq_method_name, "GET"); TEST_S(rq->rq_url->url_path, ""); TEST_1(rq->rq_url->url_root); TEST_S(url_as_string(home, rq->rq_url), "/"); TEST_P(rq->rq_version, http_version_1_0); TEST_1(rq = http_request_make(home, "GET / HTTP/1.2")); TEST(rq->rq_method, http_method_get); TEST_S(rq->rq_method_name, "GET"); TEST_S(rq->rq_url->url_path, ""); TEST_1(rq->rq_url->url_root); TEST_S(url_as_string(home, rq->rq_url), "/"); TEST_S(rq->rq_version, "HTTP/1.2"); TEST_1(rq = http_request_make(home, "GET /foo")); TEST(rq->rq_method, http_method_get); TEST_S(rq->rq_method_name, "GET"); TEST_S(rq->rq_url->url_path, "foo"); TEST_1(rq->rq_url->url_root); TEST_S(url_as_string(home, rq->rq_url), "/foo"); TEST_S(rq->rq_version, ""); TEST_P(rq->rq_version, http_version_0_9); } { http_status_t *st; st = http_status_make(home, "HTTP/1.0 100 Continue"); TEST_1(st); TEST_S(st->st_version, "HTTP/1.0"); TEST_P(st->st_version, http_version_1_0); TEST(st->st_status, 100); TEST_S(st->st_phrase, "Continue"); st = http_status_make(home, "HTTP/1.1 200"); TEST_1(st); TEST_S(st->st_version, "HTTP/1.1"); TEST(st->st_status, 200); TEST_S(st->st_phrase, ""); st = http_status_make(home, "HTTP/1.1 200 Ok"); TEST_1(st); TEST_S(st->st_version, "HTTP/1.1"); TEST_P(st->st_version, http_version_1_1); TEST(st->st_status, 200); TEST_S(st->st_phrase, "Ok"); st = http_status_make(home, "HTTP 99 Ok "); TEST_1(st); TEST_S(st->st_version, "HTTP"); TEST(st->st_status, 99); TEST_S(st->st_phrase, "Ok"); st = http_status_make(home, "HTTP/1.2 200 Ok"); TEST_1(st); TEST_S(st->st_version, "HTTP/1.2"); TEST(st->st_status, 200); TEST_S(st->st_phrase, "Ok"); } { http_content_range_t *cr; cr = http_content_range_make(home, "bytes 0 - 499 / *"); TEST_1(cr); TEST64(cr->cr_first, 0); TEST64(cr->cr_last, 499); TEST64(cr->cr_length, (http_off_t)-1); cr = http_content_range_make(home, "bytes 500-999/9913133"); TEST_1(cr); TEST64(cr->cr_first, 500); TEST64(cr->cr_last, 999); TEST64(cr->cr_length, 9913133); TEST_1(!http_content_range_make(home, "bytes = 0 - 499 / *,")); } { http_cookie_t *c; c = http_cookie_make(home, "$Version=1;" "foo=bar;$Domain=.nokia.com;$Path=\"\""); TEST_1(c); TEST_1(c->c_params); TEST_S(c->c_version, "1"); TEST_S(c->c_name, "foo=bar"); TEST_S(c->c_domain, ".nokia.com"); TEST_S(c->c_path, "\"\""); c = http_cookie_make(home, "$Version=1;" "foo=bar;$Domain=.nokia.com;$Path=\"\", , " "bar=bazzz;$Domain=.research.nokia.com;$Path=\"\";" "hum=ham;$Domain=.nokia.fi;$Path=\"/sofia\"" ); TEST_1(c); TEST_1(c->c_params); TEST_S(c->c_version, "1"); TEST_S(c->c_name, "foo=bar"); TEST_S(c->c_domain, ".nokia.com"); TEST_S(c->c_path, "\"\""); c = http_cookie_make(home, "foo=bar=baz1"); TEST_1(c); TEST_1(c->c_params); TEST_S(c->c_params[0], "foo=bar=baz1"); } { http_set_cookie_t *sc; sc = http_set_cookie_make(home, "foo=bar;Domain=.nokia.com;Path=\"\"" ";Foo=bar;Version=1;Secure;Max-age=1212;" "Comment=\"Jummi Jammmi\""); TEST_1(sc); TEST_1(sc->sc_params); TEST_S(sc->sc_name, "foo=bar"); TEST_S(sc->sc_version, "1"); TEST_S(sc->sc_domain, ".nokia.com"); TEST_S(sc->sc_max_age, "1212"); TEST_S(sc->sc_path, "\"\""); TEST_S(sc->sc_comment, "\"Jummi Jammmi\""); TEST(sc->sc_secure, 1); sc = http_set_cookie_make(home, "foo=bar;Domain=.nokia.com;Path=\"\"" ";Foo=bar;Version=1"); TEST_1(sc); TEST_1(sc->sc_params); TEST_S(sc->sc_name, "foo=bar"); TEST_S(sc->sc_version, "1"); TEST_S(sc->sc_domain, ".nokia.com"); TEST_P(sc->sc_max_age, NULL); TEST_S(sc->sc_path, "\"\""); TEST_S(sc->sc_comment, NULL); TEST(sc->sc_secure, 0); sc = http_set_cookie_make(home, "CUSTOMER=WILE_E_COYOTE; " "path=/; " "expires=Wednesday, 09-Nov-99 23:12:40 GMT"); TEST_1(sc); TEST_1(sc->sc_params); TEST_S(sc->sc_name, "CUSTOMER=WILE_E_COYOTE"); TEST_S(sc->sc_version, NULL); TEST_S(sc->sc_domain, NULL); TEST_S(sc->sc_max_age, NULL); TEST_S(sc->sc_path, "/"); TEST_S(sc->sc_comment, NULL); TEST(sc->sc_secure, 0); } { http_range_t *rng; rng = http_range_make(home, "bytes = 0 - 499"); TEST_1(rng); TEST_S(rng->rng_unit, "bytes"); TEST_1(rng->rng_specs); TEST_S(rng->rng_specs[0], "0-499"); TEST_P(rng->rng_specs[1], NULL); rng = http_range_make(home, "bytes=,500 - 999"); TEST_1(rng); TEST_S(rng->rng_unit, "bytes"); TEST_1(rng->rng_specs); TEST_S(rng->rng_specs[0], "500-999"); TEST_P(rng->rng_specs[1], NULL); rng = http_range_make(home, "bytes= - 500"); TEST_1(rng); TEST_S(rng->rng_unit, "bytes"); TEST_1(rng->rng_specs); TEST_S(rng->rng_specs[0], "-500"); TEST_P(rng->rng_specs[1], NULL); rng = http_range_make(home, "bytes=9500-"); TEST_1(rng); TEST_S(rng->rng_unit, "bytes"); TEST_1(rng->rng_specs); TEST_S(rng->rng_specs[0], "9500-"); TEST_P(rng->rng_specs[1], NULL); rng = http_range_make(home, "bytes=0- 0 , - 1"); TEST_1(rng); TEST_S(rng->rng_unit, "bytes"); TEST_1(rng->rng_specs); TEST_S(rng->rng_specs[0], "0-0"); TEST_S(rng->rng_specs[1], "-1"); TEST_P(rng->rng_specs[2], NULL); rng = http_range_make(home, "bytes=500-600 , 601 - 999 ,,"); TEST_1(rng); TEST_S(rng->rng_unit, "bytes"); TEST_1(rng->rng_specs); TEST_S(rng->rng_specs[0], "500-600"); TEST_S(rng->rng_specs[1], "601-999"); TEST_P(rng->rng_specs[2], NULL); rng = http_range_make(home, "bytes=500-700,601-999"); TEST_1(rng); TEST_S(rng->rng_unit, "bytes"); TEST_1(rng->rng_specs); TEST_S(rng->rng_specs[0], "500-700"); TEST_S(rng->rng_specs[1], "601-999"); TEST_P(rng->rng_specs[2], NULL); } { http_date_t *d; char const *s; char b[64]; d = http_date_make(home, s = "Wed, 15 Nov 1995 06:25:24 GMT"); TEST_1(d); TEST(d->d_time, 2208988800UL + 816416724); TEST_1(http_date_e(b, sizeof b, (msg_header_t*)d, 0) > 0); TEST_S(b, s); d = http_date_make(home, s = "Wed, 15 Nov 1995 04:58:08 GMT"); TEST_1(d); TEST(d->d_time, 2208988800UL + 816411488); TEST_1(http_date_e(b, sizeof b, (msg_header_t*)d, 0) > 0); TEST_S(b, s); d = http_date_make(home, s = "Tue, 15 Nov 1994 08:12:31 GMT"); TEST_1(d); TEST(d->d_time, 2208988800UL + 784887151); TEST_1(http_date_e(b, sizeof b, (msg_header_t*)d, 0) > 0); TEST_S(b, s); d = http_date_make(home, "Fri Jan 30 12:21:09 2004"); TEST_1(d); TEST(d->d_time, 2208988800UL + 1075465269); d = http_date_make(home, "Fri Jan 1 12:21:09 2004"); TEST_1(d); TEST(d->d_time, 2208988800UL + 1072959669); d = http_date_make(home, "Tuesday, 15-Nov-94 08:12:31 GMT"); TEST_1(d); TEST(d->d_time, 2208988800UL + 784887151); } { http_retry_after_t *ra; char const *s; char b[64]; ra = http_retry_after_make(home, s = "Wed, 15 Nov 1995 06:25:24 GMT"); TEST_1(ra); TEST(ra->ra_date + ra->ra_delta, 2208988800UL + 816416724); TEST_1(http_retry_after_e(b, sizeof b, (msg_header_t*)ra, 0) > 0); TEST_S(b, s); ra = http_retry_after_make(home, s = "Wed, 15 Nov 1995 04:58:08 GMT"); TEST_1(ra); TEST(ra->ra_date + ra->ra_delta, 2208988800UL + 816411488); TEST_1(http_retry_after_e(b, sizeof b, (msg_header_t*)ra, 0) > 0); TEST_S(b, s); ra = http_retry_after_make(home, s = "Tue, 15 Nov 1994 08:12:31 GMT"); TEST_1(ra); TEST(ra->ra_date + ra->ra_delta, 2208988800UL + 784887151); TEST_1(http_retry_after_e(b, sizeof b, (msg_header_t*)ra, 0) > 0); TEST_S(b, s); ra = http_retry_after_make(home, "Fri Jan 30 12:21:09 2004"); TEST_1(ra); TEST(ra->ra_date + ra->ra_delta, 2208988800UL + 1075465269); ra = http_retry_after_make(home, "Fri Jan 1 12:21:09 2004"); TEST_1(ra); TEST(ra->ra_date + ra->ra_delta, 2208988800UL + 1072959669); ra = http_retry_after_make(home, "Tuesday, 15-Nov-94 08:12:31 GMT"); TEST_1(ra); TEST(ra->ra_date + ra->ra_delta, 2208988800UL + 784887151); ra = http_retry_after_make(home, "121"); TEST_1(ra); TEST(ra->ra_date, 0); TEST(ra->ra_delta, 121); } { http_location_t *l; TEST_1(l = http_location_make(home, "http://www.google.fi/cxfer?c=PREF%3D:TM%3D1105378671:S%3DfoewuOwfszMIFJbP&prev=/")); } su_home_deinit(home); END(); } static int http_parser_test(void) { msg_t *msg; http_t *http; BEGIN(); { char data[] = "HTTP/1.1 200\r\n" "Server: Apache/1.3.11 (Unix) tomcat/1.0\r\n" "Transfer-Encoding: chunked, gzip\r\n" "Transfer-Encoding: deflate\r\n" "TE: chunked, gzip\r\n" "TE: deflate\r\n" "Content-Encoding: identity, gzip\r\n" "Content-Type: text/html\r\n" "Content-Encoding: deflate\r\n" "Set-Cookie: PREF=ID=1eab07c269cd7e5a:LD=fi:TM=1094601448:LM=1094601448:S=Ik6IEs3W3vamd8Xu; " "expires=Sun, 17-Jan-2038 19:14:07 GMT ; path=/; domain=.google.fi\r\n" "Set-Cookie: CUSTOMER=WILE_E_COYOTE; " "path=/; " "expires=Wednesday, 09-Nov-99 23:12:40 GMT\r\n" "\r\n" "4c\r\n" "\r\n" "\r\n" "\r\n" "\r\n" "\r\n9\r\n" "\r\n" "\r\n0\r\n" "Date: Mon, 21 Oct 2002 13:10:41 GMT\r\n" "\n"; TEST_1(msg = read_message_byte_by_byte(data)); http = msg_object(msg); TEST_1(http); TEST_1(http->http_status); TEST_1(http->http_payload); TEST_1(http->http_payload->pl_next); TEST_1(http->http_date); TEST_1(http->http_te); TEST_1(http->http_transfer_encoding); TEST_1(http->http_transfer_encoding->k_items); TEST_1(http->http_content_encoding); TEST_1(http->http_content_encoding->k_items); TEST_1(http->http_content_encoding->k_items); TEST_S(http->http_content_encoding->k_items[0], "identity"); TEST_S(http->http_content_encoding->k_items[1], "gzip"); TEST_S(http->http_content_encoding->k_items[2], "deflate"); TEST_P(http->http_content_encoding->k_items[3], NULL); TEST_1(http->http_set_cookie); TEST_1(http->http_set_cookie->sc_next); msg_destroy(msg); } END(); } static int test_http_encoding(void) { http_header_t *h, *h1; msg_t *msg; http_t *http; su_home_t *home; char b[160]; size_t n; BEGIN(); TEST_1(home = su_home_new(sizeof *home)); msg = read_message( "GET http://bar.com/foo/ HTTP/1.1\r\n" "Accept: text/html\r\n" "Accept-Charset: iso-8859-1\r\n" "Accept-Encoding: gzip\r\n" "Accept-Language: fi\r\n" "Authorization: Basic dXNlcjE6c2VjcmV0\r\n" "Expect: 100-continue\r\n" "From: user@nokia.com\r\n" "Host: www.nokia.com:80\r\n" "If-Match: \"entity_tag001\"\r\n" "If-Modified-Since: Tue, 11 Jul 2000 18:23:51 GMT\r\n" "If-None-Match: \"entity_tag001\", \"tag02\"\r\n" "If-Range: Tue, 11 Jul 2000 18:23:51 GMT\r\n" "If-Unmodified-Since: Tue, 11 Jul 2000 18:23:51 GMT\r\n" "Location: a+a+://\r\n" "Max-Forwards: 3\r\n" "Proxy-Authorization: Basic dXNlcjE6c2VjcmV0\r\n" "Range: bytes=100-599\r\n" "Referer: http://www.microsoft.com/resources.asp\r\n" "TE: trailers\r\n" "User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)\r\n" "Cookie: $Version=\"1\";user=\"WILE_E_COYOTE\";$Path=\"/acme\"\r\n" "Cache-Control: max-age=10\r\n" "Pragma: no-cache\r\n" "Transfer-Encoding: chunked, deflate\r\n" "Upgrade: SHTTP/1.3, TLS/1.0\r\n" "Via: HTTP/1.1 Proxy1\r\n" "Proxy-Connection: keep-alive\r\n" "Connection: close\r\n" "Date: Tue, 11 Jul 2000 18:23:51 GMT\r\n" "Trailer: Date, Connection\r\n" "Warning: 2112 www.nokia.com \"Disconnected Operation\"\r\n" /* This is here just because we cannot include two Retry-After headers in a single message */ "Retry-After: 60\r\n" "\r\n" ); http = http_object(msg); TEST_1(msg); TEST_1(http); TEST_1(!http->http_error); for (h = (http_header_t *)http->http_request; h; h = h->sh_succ) { if (h == (http_header_t*)http->http_payload) break; TEST_1(h1 = msg_header_dup(home, h)); n = msg_header_e(b, sizeof b, h1, 0); if (n != h->sh_len) TEST_SIZE(n, h->sh_len); TEST_M(b, h->sh_data, n); su_free(home, h1); } msg_destroy(msg), msg = NULL; msg = read_message( "HTTP/1.1 200 Ok\r\n" "Accept-Ranges: none\r\n" "Age: 2147483648\r\n" "ETag: \"b38b9-17dd-367c5dcd\"\r\n" "Location: http://localhost/redirecttarget.asp\r\n" "Proxy-Authenticate: Basic realm=\"Nokia Internet Proxy\"\r\n" "Retry-After: Tue, 11 Jul 2000 18:23:51 GMT\r\n" "Server: Microsoft-IIS/5.0\r\n" "Vary: Date\r\n" "WWW-Authenticate: Digest realm=\"Nokia Intranet\", nonce=\"3wWGOvaWn3n+hFv8PK2ABQ==\", opaque=\"+GNywA==\", algorithm=MD5, qop=\"auth-int\"\r\n" "Set-Cookie: user=\"WILE_E_COYOTE\";Version=\"1\";Path=\"/acme\"\r\n" "Allow: GET, HEAD\r\n" /* This is here just because we cannot include two If-Range headers in a single message */ "If-Range: \"tag02\"\r\n" "Content-Encoding: gzip\r\n" "Content-Language: en\r\n" "Content-Length: 70\r\n" "Content-Location: http://localhost/page.asp\r\n" "Content-MD5: LLO7gLaGqGt4BI6HouiWng==\r\n" "Content-Range: bytes 2543-4532/7898\r\n" "Content-Type: text/html\r\n" "Expires: Tue, 11 Jul 2000 18:23:51 GMT\r\n" "Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT\r\n" "\r\n" "Heippa!Heippa!" "\r\n"); http = http_object(msg); TEST_1(msg); TEST_1(http); TEST_1(!http->http_error); for (h = (http_header_t *)http->http_status; h; h = h->sh_succ) { if (h == (http_header_t*)http->http_payload) break; TEST_1(h1 = msg_header_dup(home, h)); n = msg_header_e(b, sizeof b, h1, 0); TEST_SIZE(n, h->sh_len); TEST_M(b, h->sh_data, n); su_free(home, h1); } msg_destroy(msg), msg = NULL; su_home_check(home); su_home_zap(home); END(); } static int http_chunk_test(void) { msg_t *msg; http_t *http; BEGIN(); { char data[] = "\nHTTP/1.1 200 OK\r\n" "Server: Apache/1.3.11 (Unix) tomcat/1.0\r\n" "Transfer-Encoding: chunked\r\n" "Content-Type: text/html\r\n" "\r\n" "4c\r\n" "\r\n" "\r\n" "\r\n" "\r\n" "\r\n9\r\n" "\r\n" "\r\n0\r\n" "Date: Mon, 21 Oct 2002 13:10:41 GMT\r\n" "\n"; TEST_1(msg = read_message_byte_by_byte(data)); http = msg_object(msg); TEST_1(http); TEST_1(http->http_status); TEST_1(http->http_payload); TEST_1(http->http_payload->pl_next); TEST_1(http->http_date); msg_destroy(msg); } { /* Use LF only as line delimiter */ char data[] = "HTTP/1.1 200 OK\n" "Server: Apache/1.3.11 (Unix) tomcat/1.0\n" "Transfer-Encoding: chunked\n" "Content-Type: text/html\n" "\n" "48\n" "\n" "\n" "\n" "\n" "\n8\n" "\n" "\n0\n" "Date: Mon, 21 Oct 2002 13:10:41 GMT\n" "\n"; TEST_1(msg = read_message_byte_by_byte(data)); http = msg_object(msg); TEST_1(http); TEST_1(http->http_status); TEST_1(http->http_payload); TEST_1(http->http_payload->pl_next); TEST_1(http->http_date); msg_destroy(msg); } { /* Use CR only as line delimiter */ char data[] = "HTTP/1.1 200 OK\r" "Server: Apache/1.3.11 (Unix) tomcat/1.0\r" "Transfer-Encoding: chunked\r" "Content-Type: text/html\r" "\r" "48\r" "\r" "\r" "\r" "\r" "\r8\r" "\r" "\r0\r" "Date: Mon, 21 Oct 2002 13:10:41 GMT\r" "\r"; TEST_1(msg = read_message_byte_by_byte(data)); http = msg_object(msg); TEST_1(http); TEST_1(http->http_status); TEST_1(http->http_payload); TEST_1(http->http_payload->pl_next); TEST_1(http->http_date); msg_destroy(msg); } END(); } static int http_tag_test(void) { BEGIN(); { msg_t *msg; http_t *http; http_referer_t *r; http_upgrade_t *u; char data[] = "HTTP/1.1 200 OK\r\n" "Server: Apache/1.3.11 (Unix) tomcat/1.0\r\n" "\r\n"; TEST_1(msg = read_message_byte_by_byte(data)); http = msg_object(msg); TEST_1(http); TEST_1(http->http_status); TEST_1(http->http_server); r = http_referer_make(NULL, "ftp://ftp.funet.fi"); TEST_1(r); u = http_upgrade_make(NULL, "HTTP/1.1, TLS/1.1"); TEST_1(u); TEST_1(u->k_items); TEST_S(u->k_items[0], "HTTP/1.1"); TEST_S(u->k_items[1], "TLS/1.1"); TEST_1(!u->k_items[2]); TEST(http_add_tl(msg, http, HTTPTAG_SERVER(HTTP_NONE->sh_server), HTTPTAG_USER_AGENT_STR(NULL), HTTPTAG_USER_AGENT(NULL), HTTPTAG_REFERER(r), HTTPTAG_MAX_FORWARDS_STR("1"), HTTPTAG_HEADER((http_header_t*)u), HTTPTAG_HEADER_STR("Vary: *\r\n\r\nfoo"), TAG_END()), 5); TEST_P(http->http_server, NULL); TEST_1(http->http_referer); TEST_1(http->http_max_forwards); TEST_1(http->http_upgrade); TEST_1(http->http_vary); TEST_1(http->http_payload); msg_destroy(msg); } END(); } static int test_query_parser(void) { BEGIN(); { char query[] = "foo=bar&bar=baz"; char *foo = NULL, *bar = NULL, *baz = "default"; TEST_SIZE(http_query_parse(NULL, NULL), -1); TEST_SIZE(http_query_parse(query, "foo=", &foo, "bar=", &bar, "baz=", &baz, NULL), 2); TEST_S(foo, "bar"); TEST_S(bar, "baz"); TEST_S(baz, "default"); } { char q2[] = "f%6fo=b%61r&bar=baz&bazibazuki"; char *foo = NULL, *bar = NULL, *baz = NULL; TEST_SIZE(http_query_parse(q2, "foo=", &foo, "bar=", &bar, "baz", &baz, NULL), 3); TEST_S(foo, "bar"); TEST_S(bar, "baz"); TEST_S(baz, "ibazuki"); } END(); } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/ipt/000077500000000000000000000000001223300710500203465ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/ipt/ChangeLog000066400000000000000000000006071223300710500221230ustar00rootroot000000000000002005-10-27 Pekka Pessi * Fixed token64_e() prototype in ipt/token64.[hc]. M ./libsofia-sip-ua/ipt/token64.c -1 +1 M ./libsofia-sip-ua/ipt/token64.h -1 +1 2005-07-24 Pekka Pessi * sha1.c: Added RFC 3174 copyright notice. 2005-07-18 Kai Vehmanen * Initial import of the module to Sofia-SIP tree. sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/ipt/Doxyfile.in000066400000000000000000000006331223300710500224630ustar00rootroot00000000000000PROJECT_NAME = "ipt" OUTPUT_DIRECTORY = ../docs/html/ipt INPUT = @srcdir@/ipt.docs INPUT += @srcdir@/sofia-sip/base64.h @srcdir@/base64.c INPUT += @srcdir@/sofia-sip/token64.h @srcdir@/token64.c @INCLUDE_PATH = . @srcdir@ @INCLUDE = ../docs/Doxyfile.conf TAGFILES += ../docs/su.doxytags=../su GENERATE_TAGFILE = ../docs/ipt.doxytags ALIASES += sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/ipt/Makefile.am000066400000000000000000000024141223300710500224030ustar00rootroot00000000000000# # Makefile.am for ipt module # # Copyright (C) 2005,2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # ---------------------------------------------------------------------- # Header paths INCLUDES = -I$(srcdir)/../su -I../su # ---------------------------------------------------------------------- # Build targets noinst_LTLIBRARIES = libipt.la check_PROGRAMS = torture_base64 TESTS = torture_base64 # ---------------------------------------------------------------------- # Rules for building the targets nobase_include_sofia_HEADERS = \ sofia-sip/base64.h \ sofia-sip/token64.h \ sofia-sip/uniqueid.h libipt_la_SOURCES = base64.c token64.c EXTRA_DIST = sofia-sip/utf8.h \ sofia-sip/rc4.h \ utf8internal.h \ utf8.c ucs2.c ucs4.c rc4.c \ utf8test.c COVERAGE_INPUT = $(libipt_la_SOURCES) $(include_sofia_HEADERS) LDADD = libipt.la \ ../sresolv/libsresolv.la \ ../su/libsu.la torture_base64_LDFLAGS = -static # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST += ipt.docs # ---------------------------------------------------------------------- # Sofia specific rules include $(top_srcdir)/rules/sofia.am sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/ipt/Makefile.in000066400000000000000000001322261223300710500224210ustar00rootroot00000000000000# Makefile.in generated by automake 1.14 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 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 ipt module # # Copyright (C) 2005,2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # ---------------------------------------------------------------------- # Header paths # common Makefile targets for libsofia-sip-ua(-glib) modules # ---------------------------------------------------------- # # run tests with valgrind # # Copyright (C) 2007 Nokia Corporation. # 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 file contains free software from Makefile.in by the Free Software # Foundation: # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 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. # # Generate lcov output # # # Copyright (C) 2007 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # # Silent compilation w/ Automake 1.9 or 1.10 # ---------------------------------------------------------- # Automake 1.9.6 is not clever enough to override suffix rules within if # if SOFIA_COMPILE_SILENT VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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@ check_PROGRAMS = torture_base64$(EXEEXT) TESTS = torture_base64$(EXEEXT) DIST_COMMON = $(top_srcdir)/rules/sofia.am \ $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am \ $(top_srcdir)/rules/silent.am $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(srcdir)/Doxyfile.in \ $(top_srcdir)/depcomp $(nobase_include_sofia_HEADERS) \ $(top_srcdir)/test-driver ChangeLog # Use with --enable-ndebug @NDEBUG_TRUE@am__append_1 = -DNDEBUG @HAVE_GENPNG_TRUE@@HAVE_LCOV_TRUE@am__append_2 = --frames @HAVE_LCOV_TRUE@am__append_3 = lcov lcov-report lcov-rerun clean-lcov covcheck uncovered subdir = libsofia-sip-ua/ipt ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(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)/m4/sac-coverage.m4 \ $(top_srcdir)/m4/sac-general.m4 \ $(top_srcdir)/m4/sac-openssl.m4 \ $(top_srcdir)/m4/sac-pkg-config.m4 $(top_srcdir)/m4/sac-su2.m4 \ $(top_srcdir)/m4/sac-tport.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libsofia-sip-ua/su/sofia-sip/su_configure.h CONFIG_CLEAN_FILES = Doxyfile CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libipt_la_LIBADD = am_libipt_la_OBJECTS = base64.lo token64.lo libipt_la_OBJECTS = $(am_libipt_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 = torture_base64_SOURCES = torture_base64.c torture_base64_OBJECTS = torture_base64.$(OBJEXT) torture_base64_LDADD = $(LDADD) am__DEPENDENCIES_1 = torture_base64_DEPENDENCIES = libipt.la ../sresolv/libsresolv.la \ ../su/libsu.la $(am__DEPENDENCIES_1) torture_base64_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(torture_base64_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) -I$(top_builddir)/libsofia-sip-ua/su/sofia-sip depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f 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) 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 = $(libipt_la_SOURCES) torture_base64.c DIST_SOURCES = $(libipt_la_SOURCES) torture_base64.c 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)$(include_sofiadir)" HEADERS = $(nobase_include_sofia_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)` 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=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ 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_DRIVER = $(SHELL) $(top_srcdir)/test-driver 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) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CHECK_CFLAGS = @CHECK_CFLAGS@ CHECK_LIBS = @CHECK_LIBS@ COVERAGE_FLAGS = @COVERAGE_FLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CWFLAG = @CWFLAG@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV = @GCOV@ GENHTML = @GENHTML@ GENPNG = @GENPNG@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GLIB_VERSION = @GLIB_VERSION@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVER_SOFIA_SIP_UA_AGE = @LIBVER_SOFIA_SIP_UA_AGE@ LIBVER_SOFIA_SIP_UA_CUR = @LIBVER_SOFIA_SIP_UA_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_AGE = @LIBVER_SOFIA_SIP_UA_GLIB_AGE@ LIBVER_SOFIA_SIP_UA_GLIB_CUR = @LIBVER_SOFIA_SIP_UA_GLIB_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_REV = @LIBVER_SOFIA_SIP_UA_GLIB_REV@ LIBVER_SOFIA_SIP_UA_GLIB_SOVER = @LIBVER_SOFIA_SIP_UA_GLIB_SOVER@ LIBVER_SOFIA_SIP_UA_REV = @LIBVER_SOFIA_SIP_UA_REV@ LIBVER_SOFIA_SIP_UA_SOVER = @LIBVER_SOFIA_SIP_UA_SOVER@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MINGW_ENVIRONMENT = @MINGW_ENVIRONMENT@ MKDIR_P = @MKDIR_P@ MOSTLYCLEANFILES = @MOSTLYCLEANFILES@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ RANLIB = @RANLIB@ REPLACE_LIBADD = @REPLACE_LIBADD@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ SOFIA_GLIB_CFLAGS = @SOFIA_GLIB_CFLAGS@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ SOFIA_PLAT_CFLAGS = @SOFIA_PLAT_CFLAGS@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ VERSION = @VERSION@ VER_LIBSOFIA_SIP_UA_MAJOR_MINOR = @VER_LIBSOFIA_SIP_UA_MAJOR_MINOR@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ include_sofiadir = @include_sofiadir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ openssl_CFLAGS = @openssl_CFLAGS@ openssl_LIBS = @openssl_LIBS@ 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@ INCLUDES = -I$(srcdir)/../su -I../su # ---------------------------------------------------------------------- # Build targets noinst_LTLIBRARIES = libipt.la # ---------------------------------------------------------------------- # Rules for building the targets nobase_include_sofia_HEADERS = \ sofia-sip/base64.h \ sofia-sip/token64.h \ sofia-sip/uniqueid.h libipt_la_SOURCES = base64.c token64.c # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST = sofia-sip/utf8.h sofia-sip/rc4.h utf8internal.h utf8.c \ ucs2.c ucs4.c rc4.c utf8test.c ipt.docs COVERAGE_INPUT = $(libipt_la_SOURCES) $(include_sofia_HEADERS) LDADD = libipt.la ../sresolv/libsresolv.la ../su/libsu.la \ $(openssl_LIBS) torture_base64_LDFLAGS = -static sofiasrcdir = ${top_srcdir}/libsofia-sip-ua sofiabuilddir = ${top_builddir}/libsofia-sip-ua AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(SOFIA_CFLAGS) \ $(openssl_CFLAGS) $(SOFIA_PLAT_CFLAGS) $(am__append_1) SOFIA_COVERAGE = $(COVERAGE_FLAGS) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files TAG_AWK = ${sofiasrcdir}/su/tag_dll.awk SUFFIXES = _tag_ref.c _tag.c INTERNAL_INCLUDES = \ -I${sofiasrcdir}/features -I${sofiabuilddir}/features \ -I${sofiasrcdir}/ipt -I${sofiabuilddir}/ipt \ -I${sofiasrcdir}/iptsec -I${sofiabuilddir}/iptsec \ -I${sofiasrcdir}/bnf -I${sofiabuilddir}/bnf \ -I${sofiasrcdir}/http -I${sofiabuilddir}/http \ -I${sofiasrcdir}/msg -I${sofiabuilddir}/msg \ -I${sofiasrcdir}/nth -I${sofiabuilddir}/nth \ -I${sofiasrcdir}/nta -I${sofiabuilddir}/nta \ -I${sofiasrcdir}/nea -I${sofiabuilddir}/nea \ -I${sofiasrcdir}/nua -I${sofiabuilddir}/nua \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sdp -I${sofiabuilddir}/sdp \ -I${sofiasrcdir}/sip -I${sofiabuilddir}/sip \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sresolv -I${sofiabuilddir}/sresolv \ -I${sofiasrcdir}/tport -I${sofiabuilddir}/tport \ -I${sofiasrcdir}/stun -I${sofiabuilddir}/stun \ -I${sofiasrcdir}/url -I${sofiabuilddir}/url \ -I${sofiasrcdir}/su -I${sofiabuilddir}/su PHONY = built-sources clean-built-sources $(am__append_3) VALGRIND = valgrind VALGRINDFLAGS = --tool=memcheck # Scripts @HAVE_LCOV_TRUE@LCOV_UNCOVERED = ${top_srcdir}/scripts/uncovered @HAVE_LCOV_TRUE@LCOV_REPORT = ${top_srcdir}/scripts/lcov-report # Report directory @HAVE_LCOV_TRUE@lcovdir = ${top_builddir}/lcov # Options @HAVE_LCOV_TRUE@GENHTML_OPTIONS = --show-details --legend \ @HAVE_LCOV_TRUE@ $(am__append_2) # Fancy shell command that expands to directory relative to top_builddir @HAVE_LCOV_TRUE@expand_subdir = `pwd|sed "s'\`cd ${top_builddir};pwd\`''"` SOFIA_SILENT = @ LIBTOOL_FLAGS = --silent # From Automake 1.9.6 - LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(LIBTOOL_FLAGS) \ $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) LINK = ${SOFIA_SILENT}test "${SOFIA_SILENT}" != @ || echo ' LINK $@'; \ $(LIBTOOL) --tag=CC --mode=link $(LIBTOOL_FLAGS) \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ all: all-am .SUFFIXES: .SUFFIXES: _tag_ref.c _tag.c .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.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 libsofia-sip-ua/ipt/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu libsofia-sip-ua/ipt/Makefile .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.am: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): Doxyfile: $(top_builddir)/config.status $(srcdir)/Doxyfile.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ 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}; \ } libipt.la: $(libipt_la_OBJECTS) $(libipt_la_DEPENDENCIES) $(EXTRA_libipt_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libipt_la_OBJECTS) $(libipt_la_LIBADD) $(LIBS) 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 torture_base64$(EXEEXT): $(torture_base64_OBJECTS) $(torture_base64_DEPENDENCIES) $(EXTRA_torture_base64_DEPENDENCIES) @rm -f torture_base64$(EXEEXT) $(AM_V_CCLD)$(torture_base64_LINK) $(torture_base64_OBJECTS) $(torture_base64_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/base64.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/token64.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/torture_base64.Po@am__quote@ .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.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) '$<'` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-nobase_include_sofiaHEADERS: $(nobase_include_sofia_HEADERS) @$(NORMAL_INSTALL) @list='$(nobase_include_sofia_HEADERS)'; test -n "$(include_sofiadir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(include_sofiadir)'"; \ $(MKDIR_P) "$(DESTDIR)$(include_sofiadir)" || exit 1; \ fi; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo " $(MKDIR_P) '$(DESTDIR)$(include_sofiadir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(include_sofiadir)/$$dir"; }; \ echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(include_sofiadir)/$$dir'"; \ $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(include_sofiadir)/$$dir" || exit $$?; }; \ done uninstall-nobase_include_sofiaHEADERS: @$(NORMAL_UNINSTALL) @list='$(nobase_include_sofia_HEADERS)'; test -n "$(include_sofiadir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ dir='$(DESTDIR)$(include_sofiadir)'; $(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; \ else \ 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 $(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 $$? torture_base64.log: torture_base64$(EXEEXT) @p='torture_base64$(EXEEXT)'; \ b='torture_base64'; \ $(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: $(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) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(include_sofiadir)"; 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 "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) -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: 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) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." @HAVE_LCOV_FALSE@clean-local: clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libtool clean-local \ clean-noinstLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -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-nobase_include_sofiaHEADERS 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 -rf ./$(DEPDIR) -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-nobase_include_sofiaHEADERS .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libtool clean-local \ 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-nobase_include_sofiaHEADERS 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 \ uninstall-nobase_include_sofiaHEADERS built-sources: $(BUILT_SOURCES) clean-built-sources: -rm -rf $(BUILT_SOURCES) $(BUILT_SOURCES:%=$(srcdir)/%) *_tag_ref.c: $(TAG_AWK) _tag.c_tag_ref.c: $(AWK) -f $(TAG_AWK) NODLL=1 $(TAG_DLL_FLAGS) REF=$@ $< ../bnf/libbnf.la ../http/libhttp.la ../ipt/libipt.la ../iptsec/libiptsec.la \ ../msg/libmsg.la ../nea/libnea.la ../nta/libnta.la ../nth/libnth.la \ ../nua/libnua.la ../sdp/libsdp.la ../sip/libsip.la ../soa/libsoa.la \ ../sresolv/libsresolv.la ../stun/libstun.la ../su/libsu.la \ ../tport/libtport.la ../url/liburl.la: cd $(@D) && $(MAKE) $(@F) checklib: $(noinst_LTLIBRARIES) $(check_LTLIBRARIES) valcheck: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) valcheck-am valcheck-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS # Run tests with valgrind in valcheck-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ list='$(TESTS)'; \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ if case $$tst in \ run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ $${dir}$$tst ;; \ esac ; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ echo "XPASS: $$tst"; \ ;; \ *) \ echo "PASS: $$tst"; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xfail=`expr $$xfail + 1`; \ echo "XFAIL: $$tst"; \ ;; \ *) \ failed=`expr $$failed + 1`; \ echo "FAIL: $$tst"; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ echo "SKIP: $$tst"; \ fi; \ done; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="All $$all tests passed"; \ else \ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all tests failed"; \ else \ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ skipped="($$skip tests were not run)"; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ report=""; \ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ report="Please report to $(PACKAGE_BUGREPORT)"; \ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ echo "$$dashes"; \ echo "$$banner"; \ test -z "$$skipped" || echo "$$skipped"; \ test -z "$$report" || echo "$$report"; \ echo "$$dashes"; \ test "$$failed" -eq 0; \ else :; fi # # Generate pretty coverage report (unless it has been already done) # @HAVE_LCOV_TRUE@lcov: @HAVE_LCOV_TRUE@ @-test -r ${lcovdir}${expand_subdir}/lcov.info \ @HAVE_LCOV_TRUE@ || make lcov-report # Generate pretty coverage report based on current coverage data @HAVE_LCOV_TRUE@lcov-report: @HAVE_LCOV_TRUE@ sub=${expand_subdir} odir=${lcovdir}$$sub ; \ @HAVE_LCOV_TRUE@ rm -rf $$odir ; mkdir -p $$odir && \ @HAVE_LCOV_TRUE@ ${LCOV_REPORT} ${GENHTML_OPTIONS} \ @HAVE_LCOV_TRUE@ --title "${PACKAGE_NAME}-${PACKAGE_VERSION}$$sub" \ @HAVE_LCOV_TRUE@ --srcdir=${srcdir} -o $$odir # Rerun checks before generating report @HAVE_LCOV_TRUE@lcov-rerun: clean-lcov @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) lcov-report # Show all uncovered lines as errors @HAVE_LCOV_TRUE@uncovered: @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} # Run check in current dir and show all uncovered lines as errors @HAVE_LCOV_TRUE@covcheck: @HAVE_LCOV_TRUE@ -find . -name "*.gcda" | xargs rm -rf @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} @HAVE_LCOV_TRUE@clean-local:: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true @HAVE_LCOV_TRUE@clean-lcov: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true # Rules from depend2.am (GENERIC = TRUE, SUBDIROBJ = FALSE, %FASTDEP% = am_fastdepCC) silenced. .c.o: @test "${SOFIA_SILENT}" != @ || echo ' COMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(COMPILE) -c -o $@ $< .c.lo: @test "${SOFIA_SILENT}" != @ || echo ' LTCOMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(LTCOMPILE) -c -o $@ $< # endif # ---------------------------------------------------------------------- # Sofia specific rules # 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: sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/ipt/base64.c000066400000000000000000000146531223300710500216070ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE base64.c * * Implementation of BASE64 encoding and decoding functions. * * @author Pekka Pessi * */ #include "config.h" #include #include #include "sofia-sip/base64.h" static unsigned char const code[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; #define B64NOP 128 #define B64EOF 64 /**Decode a BASE64-encoded string. * * The function base64_d() decodes a string @a b64s encoded with BASE64. It * stores the result in the buffer @a buf of @a bsiz bytes. * * If the @a buf is NULL, the function just returns the length of decoded * data. In any case, no decoded data is stored in @a buf beyond @a bsiz. * The function always returns the full length of decodable data. * * @param buf Buffer to store decoded data * @param bsiz Size of @a buf * @param b64s Base64-encoded string. * * @return Length of data that can be decoded in bytes. * * @sa RFC 2045, * "Multipurpose Internet Mail Extensions (MIME) Part One: * Format of Internet Message Bodies", * N. Freed, N. Borenstein, November 1996. * * @par Example * The following example code decodes a string of BASE64 data into a * memory area allocated from heap: * @code * int decoder(char const *encoded, void **return_decoded) * { * int len = base64_d(NULL, 0, encoded); * void *decoded = malloc(len); * base64_d(decoded, len, encoded); * *return_decoded = decoded; * return len; * } * @endcode */ isize_t base64_d(char buf[], isize_t bsiz, char const *b64s) { static unsigned char decode[256] = ""; unsigned char const *s = (unsigned char const *)b64s; unsigned char c, b1, b2 = B64EOF, b3 = B64EOF, b4 = B64EOF; unsigned long w; isize_t i, len = 0, total_len = 0; if (b64s == NULL) return 0; if (decode['\0'] != B64EOF) { /* Prepare decoding table */ for (i = 1; i < 256; i++) decode[i] = B64NOP; for (i = 0; i < 64; i++) { decode[code[i]] = (unsigned char)i; } decode['='] = B64EOF; decode['\0'] = B64EOF; } /* Calculate length */ while ((c = decode[*s++]) != B64EOF) { if (c != B64NOP) len++; } total_len = len = len * 3 / 4; if (buf == NULL || bsiz == 0) return total_len; if (len > bsiz) len = bsiz; for (i = 0, s = (unsigned char const *)b64s; i < len; ) { while ((b1 = decode[*s++]) == B64NOP) ; if (b1 != B64EOF) while ((b2 = decode[*s++]) == B64NOP) ; if (b2 != B64EOF) while ((b3 = decode[*s++]) == B64NOP) ; if (b3 != B64EOF) while ((b4 = decode[*s++]) == B64NOP) ; if (((b1 | b2 | b3 | b4) & (B64NOP|B64EOF)) == 0) { /* Normal case, 4 B64 chars to 3 data bytes */ w = (b1 << 18) | (b2 << 12) | (b3 << 6) | b4; buf[i++] = (unsigned char)(w >> 16); buf[i++] = (unsigned char)(w >> 8); buf[i++] = (unsigned char)(w); continue; } else { /* EOF */ if ((b1 | b2) & B64EOF) { /* fputs("base64dec: strange eof ===\n", stderr); */ break; } buf[i++] = (b1 << 2) | (b2 >> 4); if (b3 != B64EOF) { buf[i++] = ((b2 & 15) << 4) | ((b3 >> 2) & 15); if (b4 != B64EOF) { buf[i++] = ((b3 & 3) << 6) | b4; } } break; } } #if 0 printf("base64_d returns, decoded %d bytes\n", total_len); for (i = 0; i < len; i++) printf("%02x", buf[i]); printf("\n"); #endif return total_len; } /**Encode data with BASE64. * * The function base64_e() encodes @a dsiz bytes of @a data into @a buf. * * @note The function base64_e() uses at most @a bsiz bytes from @a buf. * * If @a bsiz is zero, the function just returns the length of BASE64 * encoding, excluding the final @c NUL. * * If encoded string is longer than that @a bsiz, the function terminates * string with @c NUL at @a buf[bsiz-1], but returns the length of encoding as * usual. * * @param buf buffer for encoded data * @param bsiz size of @a buffer * @param data data to be encoded * @param dsiz size of @a data * * @return The function base64_e() return length of encoded string, * excluding the final NUL. * * @sa RFC 2045, * "Multipurpose Internet Mail Extensions (MIME) Part One: * Format of Internet Message Bodies", * N. Freed, N. Borenstein, November 1996. * */ isize_t base64_e(char buf[], isize_t bsiz, void *data, isize_t dsiz) { unsigned char *s = (unsigned char *)buf; unsigned char *b = (unsigned char *)data; unsigned long w; isize_t i, n, slack = (unsigned)dsiz % 3; isize_t dsize = dsiz - slack, bsize = bsiz; if (bsize == 0) s = NULL; for (i = 0, n = 0; i < dsize; i += 3, n += 4) { w = (b[i] << 16) | (b[i+1] << 8) | b[i+2]; if (s) { if (n + 4 < bsize) { s[n + 0] = code[(w >> 18) & 63]; s[n + 1] = code[(w >> 12) & 63]; s[n + 2] = code[(w >> 6) & 63]; s[n + 3] = code[(w) & 63]; } else { if (n + 1 < bsize) s[n + 0] = code[(w >> 18) & 63]; if (n + 2 < bsize) s[n + 1] = code[(w >> 12) & 63]; if (n + 3 < bsize) s[n + 2] = code[(w >> 6) & 63]; s[bsize - 1] = '\0'; s = NULL; } } } if (slack) { if (s) { if (slack == 2) w = (b[i] << 16) | (b[i+1] << 8); else w = (b[i] << 16); if (n + 1 < bsize) s[n + 0] = code[(w >> 18) & 63]; if (n + 2 < bsize) s[n + 1] = code[(w >> 12) & 63]; if (n + 3 < bsize) s[n + 2] = (slack == 2) ? code[(w >> 6) & 63] : '='; if (n + 3 < bsize) s[n + 3] = '='; if (n + 4 >= bsize) s[bsize - 1] = '\0', s = NULL; } n += 4; } if (s) s[n] = '\0'; return n; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/ipt/ipt.docs000066400000000000000000000007721223300710500220220ustar00rootroot00000000000000/* -*- c -*- */ /**@MODULEPAGE "ipt" - Utility Module * * @section ipt_meta Module Meta Information * * Utility library for IP Telephony applications. * * @CONTACT Pekka Pessi * * @STATUS @SofiaSIP Core library * * @LICENSE LGPL * * @section ipt_overview Overview * * This module contain some routines useful for IPT applications, like * - BASE64 encoding/decoding, and * - encoding/decoding binary as SIP/HTTP token. */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/ipt/rc4.c000066400000000000000000000247501223300710500212120ustar00rootroot00000000000000/**@CFILE rc4.c Arcfour pseudorandom generator. * * @author Pekka Pessi * * Copyright (c) 1996 Pekka Pessi. All rights reserved. * * This source code is provided for unrestricted use. Users may copy or * modify this source code without charge. * * THIS SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND * INCLUDING THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A * PARTICULAR PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE * PRACTICE. * * This source code is provided with no support and without any obligation * on the part of author to assist in its use, correction, modification or * enhancement. * * AUTHOR SHALL HAVE NO LIABILITY WITH RESPECT TO THE INFRINGEMENT OF * COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE OR ANY PART * THEREOF. * * In no event will author be liable for any lost revenue or profits or * other special, indirect and consequential damages, even if author has * been advised of the possibility of such damages. * * @date Created: Sun Jun 9 12:43:17 1996 ppessi */ #include "config.h" #include "sofia-sip/rc4.h" void rc4_init(const void *vseed, isize_t seed_len, rc4_t *state) { short i; rc4_u8 j; rc4_u8 k; const rc4_u8 *seed = (const rc4_u8 *)vseed; rc4_u8 *array = state->rc4_array; state->rc4_i = 0; state->rc4_j = 0; for (i = 0; i < 256; i++) array[i] = (rc4_u8) i; for (i = 0, j = 0, k = 0; i < 256; i++, k++, k >= seed_len ? k = 0 : 0) { rc4_u8 a = array[i]; rc4_u8 b = array[j += a + seed[k]]; array[i] = b; array[j] = a; } } void rc4(void *buffer, isize_t len, rc4_t *state) { rc4_u8 *buf = (rc4_u8 *)buffer; rc4_u8 *array = state->rc4_array; rc4_u8 i = state->rc4_i; rc4_u8 j = state->rc4_j; while (len-- > 0) { rc4_u8 a = array[++i]; rc4_u8 b = array[j += a]; array[i] = b; array[j] = a; *buf++ ^= array[(a + b) & 255]; } state->rc4_i = i; state->rc4_j = j; } #ifdef RC4_TESTING rc4_u8 key_0[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}; rc4_u8 input_0[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }; rc4_u8 output_0[] = { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 }; rc4_u8 key_1[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, }; rc4_u8 input_1[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; rc4_u8 output_1[] = { 0x74, 0x94, 0xc2, 0xe7, 0x10, 0x4b, 0x08, 0x79, }; rc4_u8 key_2[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; rc4_u8 input_2[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; rc4_u8 output_2[] = { 0xde, 0x18, 0x89, 0x41, 0xa3, 0x37, 0x5d, 0x3a, }; rc4_u8 key_3[] = { 0xef, 0x01, 0x23, 0x45, }; rc4_u8 input_3[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; rc4_u8 output_3[] = { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf, 0xbd, 0x61, }; rc4_u8 key_4[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, }; rc4_u8 input_4[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, }; rc4_u8 output_4[] = { 0x75, 0x95, 0xc3, 0xe6, 0x11, 0x4a, 0x09, 0x78, 0x0c, 0x4a, 0xd4, 0x52, 0x33, 0x8e, 0x1f, 0xfd, 0x9a, 0x1b, 0xe9, 0x49, 0x8f, 0x81, 0x3d, 0x76, 0x53, 0x34, 0x49, 0xb6, 0x77, 0x8d, 0xca, 0xd8, 0xc7, 0x8a, 0x8d, 0x2b, 0xa9, 0xac, 0x66, 0x08, 0x5d, 0x0e, 0x53, 0xd5, 0x9c, 0x26, 0xc2, 0xd1, 0xc4, 0x90, 0xc1, 0xeb, 0xbe, 0x0c, 0xe6, 0x6d, 0x1b, 0x6b, 0x1b, 0x13, 0xb6, 0xb9, 0x19, 0xb8, 0x47, 0xc2, 0x5a, 0x91, 0x44, 0x7a, 0x95, 0xe7, 0x5e, 0x4e, 0xf1, 0x67, 0x79, 0xcd, 0xe8, 0xbf, 0x0a, 0x95, 0x85, 0x0e, 0x32, 0xaf, 0x96, 0x89, 0x44, 0x4f, 0xd3, 0x77, 0x10, 0x8f, 0x98, 0xfd, 0xcb, 0xd4, 0xe7, 0x26, 0x56, 0x75, 0x00, 0x99, 0x0b, 0xcc, 0x7e, 0x0c, 0xa3, 0xc4, 0xaa, 0xa3, 0x04, 0xa3, 0x87, 0xd2, 0x0f, 0x3b, 0x8f, 0xbb, 0xcd, 0x42, 0xa1, 0xbd, 0x31, 0x1d, 0x7a, 0x43, 0x03, 0xdd, 0xa5, 0xab, 0x07, 0x88, 0x96, 0xae, 0x80, 0xc1, 0x8b, 0x0a, 0xf6, 0x6d, 0xff, 0x31, 0x96, 0x16, 0xeb, 0x78, 0x4e, 0x49, 0x5a, 0xd2, 0xce, 0x90, 0xd7, 0xf7, 0x72, 0xa8, 0x17, 0x47, 0xb6, 0x5f, 0x62, 0x09, 0x3b, 0x1e, 0x0d, 0xb9, 0xe5, 0xba, 0x53, 0x2f, 0xaf, 0xec, 0x47, 0x50, 0x83, 0x23, 0xe6, 0x71, 0x32, 0x7d, 0xf9, 0x44, 0x44, 0x32, 0xcb, 0x73, 0x67, 0xce, 0xc8, 0x2f, 0x5d, 0x44, 0xc0, 0xd0, 0x0b, 0x67, 0xd6, 0x50, 0xa0, 0x75, 0xcd, 0x4b, 0x70, 0xde, 0xdd, 0x77, 0xeb, 0x9b, 0x10, 0x23, 0x1b, 0x6b, 0x5b, 0x74, 0x13, 0x47, 0x39, 0x6d, 0x62, 0x89, 0x74, 0x21, 0xd4, 0x3d, 0xf9, 0xb4, 0x2e, 0x44, 0x6e, 0x35, 0x8e, 0x9c, 0x11, 0xa9, 0xb2, 0x18, 0x4e, 0xcb, 0xef, 0x0c, 0xd8, 0xe7, 0xa8, 0x77, 0xef, 0x96, 0x8f, 0x13, 0x90, 0xec, 0x9b, 0x3d, 0x35, 0xa5, 0x58, 0x5c, 0xb0, 0x09, 0x29, 0x0e, 0x2f, 0xcd, 0xe7, 0xb5, 0xec, 0x66, 0xd9, 0x08, 0x4b, 0xe4, 0x40, 0x55, 0xa6, 0x19, 0xd9, 0xdd, 0x7f, 0xc3, 0x16, 0x6f, 0x94, 0x87, 0xf7, 0xcb, 0x27, 0x29, 0x12, 0x42, 0x64, 0x45, 0x99, 0x85, 0x14, 0xc1, 0x5d, 0x53, 0xa1, 0x8c, 0x86, 0x4c, 0xe3, 0xa2, 0xb7, 0x55, 0x57, 0x93, 0x98, 0x81, 0x26, 0x52, 0x0e, 0xac, 0xf2, 0xe3, 0x06, 0x6e, 0x23, 0x0c, 0x91, 0xbe, 0xe4, 0xdd, 0x53, 0x04, 0xf5, 0xfd, 0x04, 0x05, 0xb3, 0x5b, 0xd9, 0x9c, 0x73, 0x13, 0x5d, 0x3d, 0x9b, 0xc3, 0x35, 0xee, 0x04, 0x9e, 0xf6, 0x9b, 0x38, 0x67, 0xbf, 0x2d, 0x7b, 0xd1, 0xea, 0xa5, 0x95, 0xd8, 0xbf, 0xc0, 0x06, 0x6f, 0xf8, 0xd3, 0x15, 0x09, 0xeb, 0x0c, 0x6c, 0xaa, 0x00, 0x6c, 0x80, 0x7a, 0x62, 0x3e, 0xf8, 0x4c, 0x3d, 0x33, 0xc1, 0x95, 0xd2, 0x3e, 0xe3, 0x20, 0xc4, 0x0d, 0xe0, 0x55, 0x81, 0x57, 0xc8, 0x22, 0xd4, 0xb8, 0xc5, 0x69, 0xd8, 0x49, 0xae, 0xd5, 0x9d, 0x4e, 0x0f, 0xd7, 0xf3, 0x79, 0x58, 0x6b, 0x4b, 0x7f, 0xf6, 0x84, 0xed, 0x6a, 0x18, 0x9f, 0x74, 0x86, 0xd4, 0x9b, 0x9c, 0x4b, 0xad, 0x9b, 0xa2, 0x4b, 0x96, 0xab, 0xf9, 0x24, 0x37, 0x2c, 0x8a, 0x8f, 0xff, 0xb1, 0x0d, 0x55, 0x35, 0x49, 0x00, 0xa7, 0x7a, 0x3d, 0xb5, 0xf2, 0x05, 0xe1, 0xb9, 0x9f, 0xcd, 0x86, 0x60, 0x86, 0x3a, 0x15, 0x9a, 0xd4, 0xab, 0xe4, 0x0f, 0xa4, 0x89, 0x34, 0x16, 0x3d, 0xdd, 0xe5, 0x42, 0xa6, 0x58, 0x55, 0x40, 0xfd, 0x68, 0x3c, 0xbf, 0xd8, 0xc0, 0x0f, 0x12, 0x12, 0x9a, 0x28, 0x4d, 0xea, 0xcc, 0x4c, 0xde, 0xfe, 0x58, 0xbe, 0x71, 0x37, 0x54, 0x1c, 0x04, 0x71, 0x26, 0xc8, 0xd4, 0x9e, 0x27, 0x55, 0xab, 0x18, 0x1a, 0xb7, 0xe9, 0x40, 0xb0, 0xc0, }; #include void printout(const char *title, rc4_u8 *data, int len) { int i; puts(title); for (i = 0; i < len; i++) { printf("0x%02x ", data[i]); } putchar('\n'); } int main() { int failed = 0; rc4_t state[1]; rc4_init(key_0, sizeof key_0, state); rc4(input_0, sizeof input_0, state); if (memcmp(input_0, output_0, sizeof input_0)) { printout("Test 0 output", input_0, sizeof input_0); failed = 1; } if (!failed) { puts("RC4 seems to work\n"); } rc4_prepare_key(key_1, sizeof key_1, state); rc4(input_1, sizeof input_1, state); if (memcmp(input_1, output_1, sizeof input_1)) { printout("Test 1 output", input_1, sizeof input_1); failed = 1; } rc4_prepare_key(key_2, sizeof key_2, state); rc4(input_2, sizeof input_2, state); if (memcmp(input_2, output_2, sizeof input_2)) { printout("Test 2 output", input_2, sizeof input_2); failed = 1; } rc4_prepare_key(key_3, sizeof key_3, state); rc4(input_3, sizeof input_3, state); if (memcmp(input_3, output_3, sizeof input_3)) { printout("Test 3 output", input_3, sizeof input_3); failed = 1; } rc4_prepare_key(key_4, sizeof key_4, state); rc4(input_4, sizeof input_4, state); if (memcmp(input_4, output_4, sizeof input_4)) { printout("Test 4 output", input_4, sizeof input_4); failed = 1; } exit(failed); } #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/ipt/sofia-sip/000077500000000000000000000000001223300710500222405ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/ipt/sofia-sip/base64.h000066400000000000000000000041201223300710500234720ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef BASE64_H #define BASE64_H /**@file sofia-sip/base64.h * * @brief Base64 encoding and decoding functions. * * This module contains base64 encoding and decoding functions. Base64 * encodes arbitrary octet strings as strings containing characters @c * [A-Za-z0-9+/=]. Base64 is defined as part of MIME mail format, but it is * used widely by other text-based protocols as well. * * @sa RFC 2045, * "Multipurpose Internet Mail Extensions (MIME) Part One: * Format of Internet Message Bodies", * N. Freed, N. Borenstein, * November 1996. * * @author Pekka Pessi */ #ifndef SU_TYPES_H #include #endif SOFIA_BEGIN_DECLS /** Decode a BASE64-encoded string. */ SOFIAPUBFUN isize_t base64_d(char buf[], isize_t bsiz, char const *b64s); /** Encode data with BASE64. */ SOFIAPUBFUN isize_t base64_e(char buf[], isize_t bsiz, void *data, isize_t dsiz); /** Calculate size of n bytes encoded in base64 */ #define BASE64_SIZE(n) ((((n) + 2) / 3) * 4) /** Calculate size of n bytes encoded in base64 sans trailing =. @NEW_1_12_5. */ #define BASE64_MINSIZE(n) ((n * 4 + 2) / 3) SOFIA_END_DECLS #endif /* !BASE_64 */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/ipt/sofia-sip/rc4.h000066400000000000000000000033351223300710500231050ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef RC4_H /** Defined when has been included. */ #define RC4_H /**@file sofia-sip/rc4.h * @brief Arcfour random number generator. * * @author Pekka Pessi * * @date Created: Sun Jun 9 14:32:58 1996 ppessi */ #if defined(__cplusplus) extern "C" { #endif #ifndef SU_TYPES_H #include #endif /** Byte. */ typedef uint8_t rc4_u8; /** RC4 context. * * The RC4 context is accessed and modified through rc4_init() and rc4() * functions only. */ typedef struct { uint8_t rc4_i; uint8_t rc4_j; uint8_t rc4_array[256]; } rc4_t; /** Key RC4 context. */ SOFIAPUBFUN void rc4_init(const void *seed, isize_t seed_len, rc4_t *state); /** Generate RC4 stream. */ SOFIAPUBFUN void rc4(void *buffer, isize_t len, rc4_t *state); #if defined(__cplusplus) } #endif #endif /* !defined RC4_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/ipt/sofia-sip/token64.h000066400000000000000000000027201223300710500237040ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef TOKEN64_H #define TOKEN64_H /**@file sofia-sip/token64.h * * @brief Token64 encoding. * * This module contains token64 encoding functions. Token64 encodes * arbitrary octet strings as http header tokens containing only characters * in range @c [-+A-Za-z0-9]. * */ #ifndef SU_TYPES_H #include #endif SOFIA_BEGIN_DECLS SOFIAPUBFUN isize_t token64_e(char b[], isize_t bsiz, void const *data, isize_t dlen); /** Calculate size of n bytes encoded in token-64 */ #define TOKEN64_SIZE(n) (((n + 2) / 3) * 4) SOFIA_END_DECLS #endif /* !TOKEN64_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/ipt/sofia-sip/uniqueid.h000066400000000000000000000027431223300710500242420ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef UNIQUEID_H /** Defined when has been included. */ #define UNIQUEID_H /**@file sofia-sip/uniqueid.h * * Compatibility functions to handle GloballyUniqueID. * * This file just includes . * * @author Pekka Pessi * * @date Created: Tue Apr 15 06:31:41 1997 pessi */ /* Compatibility functionality */ #define guid_t su_guid_t #define guid_generate su_guid_generate #define guid_sprintf su_guid_sprintf #define guid_strlen su_guid_strlen #define randint su_randint #define randmem su_randmem #include #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/ipt/sofia-sip/utf8.h000066400000000000000000000142161223300710500233030ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@file sofia-sip/utf8.h * Encoding/Decoding Functions for UCS Transformation Format UTF-8. * * UTF-8 encoding codes the ISO 10646 (Unicode, UCS2 and UCS4) characters as * variable length (1 - 6 bytes) strings of 8-bit characters. * * @author Pekka Pessi * * @date Created: Tue Apr 21 15:32:38 1998 pessi * @sa RFC 2279, * "UTF-8, a transformation format of ISO 10646", * F. Yergeau. January 1998. * */ #ifndef UTF8_H /** Defined when has been included */ #define UTF8_H #ifndef SU_TYPES_H #include #endif SOFIA_BEGIN_DECLS typedef unsigned char utf8; typedef unsigned short utf16; typedef unsigned char ucs1; typedef unsigned short ucs2; typedef unsigned int ucs4; SOFIAPUBFUN size_t utf8_width(const utf8 *); /* Latin-1 encoding/decoding */ SOFIAPUBFUN size_t ucs18decode(char *dst, size_t dst_size, const utf8 *s); SOFIAPUBFUN size_t ucs1encode(utf8 *dst, const ucs1 *s, size_t n, const char quote[128]); SOFIAPUBFUN size_t ucs1declen(const utf8 *s); SOFIAPUBFUN size_t ucs1enclen(const ucs1 *s, size_t n, const char quote[128]); /* UCS2 (BMP) encoding/decoding */ size_t ucs2decode(ucs2 *dst, size_t dst_size, const utf8 *s); size_t ucs2encode(utf8 *dst, const ucs2 *s, size_t n, const char quote[128]); size_t ucs2declen(const utf8 *s); size_t ucs2enclen(const ucs2 *s, size_t n, const char quote[128]); size_t ucs4decode(ucs4 *dst, size_t dst_size, const utf8 *s); size_t ucs4encode(utf8 *dst, const ucs4 *s, size_t n, const char quote[128]); size_t ucs4declen(const utf8 *s); size_t ucs4enclen(const ucs4 *s, size_t n, const char quote[128]); size_t ucs2len(ucs2 const *s); int ucs2cmp(ucs2 const *s1, ucs2 const *s2); int ucs2ncmp(ucs2 const *s1, ucs2 const *s2, size_t n); size_t ucs4len(ucs4 const *s); int ucs4cmp(ucs4 const *s1, ucs4 const *s2); int ucs4ncmp(ucs4 const *s1, ucs4 const *s2, size_t n); /* * IS_UCS4_n tests whether UCS4 character should be represented * with 'n' byte utf8 string */ #define IS_UCS4_1(x) ((ucs4)(x) <= 0x7fu) #define IS_UCS4_2(x) (0x80u <= (ucs4)(x) && (ucs4)(x) <= 0x7ffu) #define IS_UCS4_3(x) (0x800u <= (ucs4)(x) && (ucs4)(x) <= 0xffffu) #define IS_UCS4_4(x) (0x10000u <= (ucs4)(x) && (ucs4)(x) <= 0x1fFFFFu) #define IS_UCS4_5(x) (0x200000u <= (ucs4)(x) && (ucs4)(x) <= 0x3ffFFFFu) #define IS_UCS4_6(x) (0x4000000u <= (ucs4)(x) && (ucs4)(x) <= 0x7fffFFFFu) /* Special test for ISO-8859-1 characters */ #define IS_UCS4_I(x) (0x80u <= (ucs4)(x) && (ucs4)(x) <= 0xffu) /* Length of an UCS4 character in UTF8 encoding */ #define UTF8_LEN4(x) (IS_UCS4_1(x) || IS_UCS4_2(x) && 2 || \ IS_UCS4_3(x) && 3 || IS_UCS4_4(x) && 4 || \ IS_UCS4_5(x) && 5 || IS_UCS4_6(x) && 6) /* Length of an UCS2 character in UTF8 encoding */ #define UTF8_LEN2(x) (IS_UCS4_1(x) || IS_UCS4_2(x) && 2 || IS_UCS4_3(x) && 3) /* * IS_UTF8_n tests the length of the next wide character */ #define IS_UTF8_1(c) (0x00 == ((c) & 0x80)) #define IS_UTF8_2(c) (0xc0 == ((c) & 0xe0)) #define IS_UTF8_3(c) (0xe0 == ((c) & 0xf0)) #define IS_UTF8_4(c) (0xf0 == ((c) & 0xf8)) #define IS_UTF8_5(c) (0xf8 == ((c) & 0xfc)) #define IS_UTF8_6(c) (0xfc == ((c) & 0xfe)) /* Extension byte? */ #define IS_UTF8_X(c) (0x80 == ((c) & 0xc0)) /* ISO-8859-1 character? */ #define IS_UTF8_I(c) (0xc0 == ((c) & 0xfc)) #define IS_UTF8_S1(s) \ (IS_UTF8_1(s[0])) #define IS_UTF8_S2(s) \ (IS_UTF8_2(s[0])&&((s)[1]&192)==128) #define IS_UTF8_SI(s) \ (IS_UTF8_I(s[0])&&((s)[1]&192)==128) #define IS_UTF8_S3(s) \ (IS_UTF8_3(s[0])&& ((s)[1]&192)==128&&((s)[2]&192)==128) #define IS_UTF8_S4(s) \ (IS_UTF8_4(s[0])&& ((s)[1]&192)==128&&((s)[2]&192)==128&&((s)[3]&192)==128) #define IS_UTF8_S5(s) \ (IS_UTF8_5(s[0])&& ((s)[1]&192)==128&&((s)[2]&192)==128&&\ ((s)[3]&192)==128&&((s)[4]&192)==128) #define IS_UTF8_S6(s) \ (IS_UTF8_6(s[0])&& ((s)[1]&192)==128&&((s)[2]&192)==128&&((s)[3]&192)==128&&\ ((s)[4]&192)==128&&((s)[5]&192)==128) #define UCS4_S1(s) ((ucs4)(s[0])) #define UCS4_S2(s) ((ucs4)\ (((s[0])&31)<<6)|((s[1])&63)) #define UCS4_S3(s) ((ucs4)\ (((s[0])&15)<<12)|(((s[1])&63)<<6)|((s[2])&63)) #define UCS4_S4(s) ((ucs4)\ (((s[0])&7)<<18)|(((s[1])&63)<<12)|(((s[2])&63)<<6)|\ ((s[3])&63)) #define UCS4_S5(s) ((ucs4)\ (((s[0])&3)<<24)|(((s[1])&63)<<18)|(((s[2])&63)<<12)|\ (((s[3])&63)<<6)|((s[4])&63)) #define UCS4_S6(s) ((ucs4)\ (((s[0])&1)<<30)|(((s[1])&63)<<24)|(((s[2])&63)<<18)|\ (((s[3])&63)<<12)|(((s[4])&63)<<6)|((s[5])&63)) #define UTF8_S1(s,c) ((s)[0]=(c)) #define UTF8_S2(s,c) ((s)[0]=(((c)>>6)&31)|0xc0,\ (s)[1]=((c)&63)|128) #define UTF8_S3(s,c) ((s)[0]=(((c)>>12)&15)|0xe0,\ (s)[1]=((c>>6)&63)|128,\ (s)[2]=((c)&63)|128) #define UTF8_S4(s,c) ((s)[0]=(((c)>>18)&7)|0xf0,\ (s)[1]=((c>>12)&63)|128,\ (s)[2]=((c>>6)&63)|128,\ (s)[3]=((c)&63)|128) #define UTF8_S5(s,c) ((s)[0]=(((c)>>24)&3)|0xf8,\ (s)[1]=((c>>18)&63)|128,\ (s)[2]=((c>>12)&63)|128,\ (s)[3]=((c>>6)&63)|128,\ (s)[4]=((c)&63)|128) #define UTF8_S6(s,c) ((s)[0]=(((c)>>30)&1)|0xfc,\ (s)[1]=((c>>24)&63)|128,\ (s)[2]=((c>>18)&63)|128,\ (s)[3]=((c>>12)&63)|128,\ (s)[4]=((c>>6)&63)|128,\ (s)[5]=((c)&63)|128) SOFIA_END_DECLS #endif /* UTF8_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/ipt/token64.c000066400000000000000000000046251223300710500220130ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@internal @file token64.c * * Token encoding. * * @author Pekka Pessi * * @date Created: Wed Apr 3 10:45:47 2002 ppessi */ #include "config.h" #include #include #include #include "sofia-sip/token64.h" static const char code[65] = "0123456789-abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ"; /** Encode data as a SIP/HTTP token. * * @note * A token is case-independent, so this is really not a good idea. * Use msg_random_token() instead. */ isize_t token64_e(char b[], isize_t bsiz, void const *data, isize_t dlen) { size_t i, n, slack; unsigned char const *h = data; char *s = b, *end = b + bsiz; long w; if (dlen <= 0) { if (bsiz && b) *b = '\0'; return 0; } n = (8 * dlen + 5) / 6; if (bsiz == 0 || b == NULL) return n; if (b + n >= end) dlen = 6 * bsiz / 8; else end = b + n + 1; slack = dlen % 3; dlen -= slack; for (i = 0; i < dlen; i += 3, s += 4) { unsigned char h0 = h[i], h1 = h[i + 1], h2 = h[i + 2]; s[0] = code[h0 >> 2]; s[1] = code[((h0 << 4)|(h1 >> 4)) & 63]; s[2] = code[((h1 << 4)|(h2 >> 6)) & 63]; s[3] = code[(h2) & 63]; } if (slack) { if (slack == 2) w = (h[i] << 16) | (h[i+1] << 8); else w = (h[i] << 16); if (s < end) *s++ = code[(w >> 18) & 63]; if (s < end) *s++ = code[(w >> 12) & 63]; if (s < end && slack == 2) *s++ = code[(w >> 6) & 63]; } if (s < end) *s++ = '\0'; else end[-1] = '\0'; assert(end == s); return n; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/ipt/torture_base64.c000066400000000000000000000111411223300710500233600ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /** * @file torture_base64.c * @brief Test BASE64 encoding/decoding * * @author Pekka Pessi \n * * @date Created: Tue Feb 1 13:29:09 EET 2005 ppessi * */ #include "config.h" #include #include #include #include #include #include #include "sofia-sip/base64.h" int tstflags = 0; #define TSTFLAGS tstflags char const *name = "torture_base64"; #include char const constant[] = "not changed"; int test_encoding(void) { char buffer[32]; BEGIN(); TEST_SIZE(base64_e(buffer, sizeof buffer, "\0\020\203", 3), 4); TEST_S(buffer, "ABCD"); strcpy(buffer + 5, "not changed"); TEST_SIZE(base64_e(buffer, 5, "\0\020\203", 3), 4); TEST_S(buffer + 5, "not changed"); TEST_S(buffer, "ABCD"); strcpy(buffer + 4, "not changed"); TEST_SIZE(base64_e(buffer, 4, "\0\020\203", 3), 4); TEST_S(buffer + 4, "not changed"); TEST_S(buffer, "ABC"); strcpy(buffer + 3, "not changed"); TEST_SIZE(base64_e(buffer, 3, "\0\020\203", 3), 4); TEST_S(buffer + 3, "not changed"); TEST_S(buffer, "AB"); strcpy(buffer + 2, "not changed"); TEST_SIZE(base64_e(buffer, 2, "\0\020\203", 3), 4); TEST_S(buffer + 2, "not changed"); TEST_S(buffer, "A"); strcpy(buffer + 1, "not changed"); TEST_SIZE(base64_e(buffer, 1, "\0\020\203", 3), 4); TEST_S(buffer + 1, "not changed"); TEST_S(buffer, ""); strcpy(buffer + 5, "not changed"); TEST_SIZE(base64_e(buffer, 5, "\0\020", 2), 4); TEST_S(buffer + 5, "not changed"); TEST_S(buffer, "ABA="); strcpy(buffer + 4, "not changed"); TEST_SIZE(base64_e(buffer, 4, "\0\020", 2), 4); TEST_S(buffer + 4, "not changed"); TEST_S(buffer, "ABA"); strcpy(buffer + 3, "not changed"); TEST_SIZE(base64_e(buffer, 3, "\0\020", 2), 4); TEST_S(buffer + 3, "not changed"); TEST_S(buffer, "AB"); strcpy(buffer + 2, "not changed"); TEST_SIZE(base64_e(buffer, 2, "\0\020", 2), 4); TEST_S(buffer + 2, "not changed"); TEST_S(buffer, "A"); strcpy(buffer + 1, "not changed"); TEST_SIZE(base64_e(buffer, 1, "\0\020", 2), 4); TEST_S(buffer + 1, "not changed"); TEST_S(buffer, ""); strcpy(buffer + 5, "not changed"); TEST_SIZE(base64_e(buffer, 5, "\0", 1), 4); TEST_S(buffer + 5, "not changed"); TEST_S(buffer, "AA=="); strcpy(buffer + 4, "not changed"); TEST_SIZE(base64_e(buffer, 4, "\0", 1), 4); TEST_S(buffer + 4, "not changed"); TEST_S(buffer, "AA="); strcpy(buffer + 3, "not changed"); TEST_SIZE(base64_e(buffer, 3, "\0", 1), 4); TEST_S(buffer + 3, "not changed"); TEST_S(buffer, "AA"); strcpy(buffer + 2, "not changed"); TEST_SIZE(base64_e(buffer, 2, "\0", 1), 4); TEST_S(buffer + 2, "not changed"); TEST_S(buffer, "A"); strcpy(buffer + 1, "not changed"); TEST_SIZE(base64_e(buffer, 1, "\0", 1), 4); TEST_S(buffer + 1, "not changed"); TEST_S(buffer, ""); END(); } int test_decoding(void) { char buffer[32]; BEGIN(); strcpy(buffer + 0, "not changed"); TEST_SIZE(base64_d((void *)buffer, 0, "ABCD"), 3); TEST_S(buffer + 0, "not changed"); TEST_SIZE(base64_d((void *)buffer, 3, "ABCD"), 3); TEST_M(buffer, "\0\020\203", 3); TEST_SIZE(base64_d(NULL, 3, "ABCD"), 3); TEST_SIZE(base64_d((void *)buffer, 3, "A B C D !!"), 3); TEST_M(buffer, "\0\020\203", 3); END(); } void usage(int exitcode) { fprintf(stderr, "usage: %s [-v] [-a]\n", name); exit(exitcode); } int main(int argc, char *argv[]) { int retval = 0; int i; for (i = 1; argv[i]; i++) { if (strcmp(argv[i], "-v") == 0) tstflags |= tst_verbatim; else if (strcmp(argv[i], "-a") == 0) tstflags |= tst_abort; else usage(1); } retval |= test_encoding(); fflush(stdout); retval |= test_decoding(); fflush(stdout); return retval; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/ipt/ucs2.c000066400000000000000000000073211223300710500213710ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE ucs2.c UCS2 (Unicode, ISO Basic Multilingual Plane) string handling. * * @author Pekka Pessi * * @date Created: Tue Apr 21 15:32:02 1998 pessi * */ #include "config.h" #include #include "utf8internal.h" /* * Decode utf8 string into ucs2 string, * return number of ucs2 characters decoded */ size_t ucs2decode(ucs2 *dst, size_t dst_size, const utf8 *s) { ucs2 v, *d = dst; if (s) do { if (dst_size == 0) break; if (IS_UTF8_S1(s)) v = UCS4_S1(s), s += 1; else if (IS_UTF8_S2(s)) v = UCS4_S2(s), s += 2; else if (IS_UTF8_S3(s)) v = UCS4_S3(s), s += 3; else { s++; continue; /* skip illegal characters */ } *d++ = v; dst_size--; } while (*s); if (dst_size) *d = 0; return d - dst; } /* * Encode ucs2 string into utf8 string, * return number of utf8 bytes encoded including final zero * * 'quote' may contain an optional quoting table containing * non-zero for all ASCII characters to quote * */ size_t ucs2encode(utf8 *dst, const ucs2 *s, size_t n, const char quote[128]) { utf8 *d = dst; ucs2 c; if (s) while (n-- > 0) { c = *s++; if (IS_UCS4_1(c)) { if (quote && quote[c]) { UTF8_S2(d, c); d += 2; } else { if (!c) /* zero must be represented as UTF8_2 */ break; UTF8_S1(d, (utf8) c); d += 1; } } else if (IS_UCS4_2(c)) { UTF8_S2(d, c); d += 2; } else /* if (IS_UCS4_3(c)) */ { UTF8_S3(d, c); d += 3; } } *d++ = 0; return d - dst; } /* * Length of UCS2 (BMP, Unicode) string decoded from UTF8 */ size_t ucs2declen(const utf8 *s) { size_t len = 0; size_t errors = 0; /* errors */ UTF8_ANALYZE(s, len, len, len, errors, errors); if (errors) return 0; return len; } /* * Length of UTF8 encoding of a UCS2 string, including final zero */ size_t ucs2enclen(const ucs2 *s, size_t n, const char quote[128]) { size_t len = 1; ucs2 c; while (n-- > 0) { c = *s++; if (c < 0x80u) if (quote && quote[c]) len += 2; else { if (!c) break; len += 1; } else if (c < 0x800u) len += 2; else /* if (c < 0x10000u) */ len += 3; } return len; } /* * Length of UCS2 string (number of non-zero UCS2 characters before zero) */ size_t ucs2len(ucs2 const *s) { size_t len = 0; if (s) while (*s++) len++; return len; } /* * Compare UCS2 (BMP, Unicode) string */ int ucs2cmp(ucs2 const *s1, ucs2 const *s2) { int retval = s1 - s2; if (s1 && s2) while ((retval = (*s1 - *s2)) && (*s1++) && (*s2++)) ; return retval; } /* * Compare UCS2 (BMP, Unicode) string */ int ucs2ncmp(ucs2 const *s1, ucs2 const *s2, size_t n) { int retval = 0; if (s1 && s2) while (n-- > 0 && (retval = (*s1 - *s2)) && (*s1++) && (*s2++)) ; return retval; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/ipt/ucs4.c000066400000000000000000000101701223300710500213670ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE ucs4.c UCS-4 routines * * @author Pekka Pessi * * @date Created: Tue Apr 21 15:32:02 1998 pessi */ #include "config.h" #include #include "utf8internal.h" /* * Decode utf8 string into ucs4 string, * return number of ucs4 characters decoded */ size_t ucs4decode(ucs4 *dst, size_t dst_size, const utf8 *s) { ucs4 v, *d = dst; if (s) while (*s) { if (dst_size == 0) break; if (IS_UTF8_S1(s)) v = UCS4_S1(s), s += 1; else if (IS_UTF8_S2(s)) v = UCS4_S2(s), s += 2; else if (IS_UTF8_S3(s)) v = UCS4_S3(s), s += 3; else if (IS_UTF8_S4(s)) v = UCS4_S4(s), s += 4; else if (IS_UTF8_S5(s)) v = UCS4_S5(s), s += 5; else if (IS_UTF8_S6(s)) v = UCS4_S6(s), s += 6; else { s++; continue; /* skip illegal characters */ } *d++ = v; dst_size--; }; if (dst_size) *d = 0; return d - dst; } /* * Encode ucs4 string into utf8 string, * return number of utf8 bytes encoded including final zero * * 'quote' may contain an optional quoting table containing * non-zero for all ASCII characters to quote * */ size_t ucs4encode(utf8 *dst, const ucs4 *s, size_t n, const char quote[128]) { utf8 *d = dst; ucs4 c; if (s) while (n-- > 0) { c = *s++; if (IS_UCS4_1(c)) { if (quote && quote[c]) { UTF8_S2(d, c); d += 2; } else { if (!c) /* zero must be represented as UTF8_2 */ break; UTF8_S1(d, c); d += 1; } } else if (IS_UCS4_2(c)) { UTF8_S2(d, c); d += 2; } else if (IS_UCS4_3(c)) { UTF8_S3(d, c); d += 3; } else if (IS_UCS4_4(c)) { UTF8_S4(d, c); d += 4; } else if (IS_UCS4_5(c)) { UTF8_S5(d, c); d += 5; } else if (IS_UCS4_6(c)) { UTF8_S6(d, c); d += 6; } else { /* skip illegal (negative) characters */ } } *d++ = 0; return d - dst; } /* * Length of UCS4 string decoded from UTF8 */ size_t ucs4declen(const utf8 *s) { size_t len = 0; size_t errors = 0; /* errors */ UTF8_ANALYZE(s, len, len, len, len, errors); if (errors) return 0; return len; } /* * Length of UTF8 encoding of a UCS4 string, including final zero */ size_t ucs4enclen(const ucs4 *s, size_t n, const char quote[128]) { size_t len = 1; ucs4 c; while (n-- > 0) { c = *s++; if (c < 0x80u) if (quote && quote[c]) len += 2; else { if (!c) break; len += 1; } else if (c < 0x800u) len += 2; else if (c < 0x10000u) len += 3; else if (c < 0x200000u) len += 4; else if (c < 0x4000000u) len += 5; else if (c < 0x80000000u) len += 6; } return len; } /* * Length of UCS4 string (number of non-zero UCS4 characters before zero) */ size_t ucs4len(ucs4 const *s) { size_t len = 0; if (s) while (*s++) len++; return len; } /* * Compare UCS4 string */ int ucs4cmp(ucs4 const *s1, ucs4 const *s2) { int retval; while ((retval = (*s1 - *s2)) && (*s1++) && (*s2++)) ; return retval; } /* * Compare UCS4 string prefix */ int ucs4ncmp(ucs4 const *s1, ucs4 const *s2, size_t n) { int retval = 0; while (n-- > 0 && (retval = (*s1 - *s2)) && (*s1++) && (*s2++)) ; return retval; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/ipt/utf8.c000066400000000000000000000042021223300710500213760ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE utf8.c * * utf8 string handling. * * @author Pekka Pessi * * @date Created: Tue Apr 21 15:32:02 1998 pessi */ #include "config.h" #include #include "utf8internal.h" #ifndef _WIN32 #include #endif /** Width of an UTF8 character cell (1, 2 or 4 bytes) */ size_t utf8_width(const utf8 *s) { size_t w8 = 0, w16 = 0, w32 = 0; size_t errors = 0; /* errors */ UTF8_ANALYZE(s, w8, w8, w16, w32, errors); if (errors) return 0; return w32 ? 4 : (w16 ? 2 : 1); } /** Convert UTF8 string @a s to ISO-Latin-1 string @a dst. */ size_t ucs18decode(char *dst, size_t dst_size, const utf8 *s) { #ifndef _WIN32 assert(!"implemented"); #endif return 0; } /** Convert ISO-Latin-1 string @a s to UTF8 string in @a dst. */ size_t ucs1encode(utf8 *dst, const ucs1 *s, size_t n, const char quote[128]) { #ifndef _WIN32 assert(!"implemented"); #endif return 0; } /** Calculate number of characters in UTF8 string @a s. */ size_t ucs1declen(const utf8 *s) { #ifndef _WIN32 assert(!"implemented"); #endif return 0; } /** Calculate length of UTF8 encoding of string @a s. */ size_t ucs1enclen(const ucs1 *s, size_t n, const char quote[128]) { #ifndef _WIN32 assert(!"implemented"); #endif return 0; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/ipt/utf8internal.h000066400000000000000000000042631223300710500231470ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef UTF8INTERNAL_H #define UTF8INTERNAL_H /**@IFILE utf8internal.h * UTF-8 macros. * * @author Pekka Pessi * * @date Created: Tue Apr 21 15:32:02 1998 pessi */ #define UTF8_ANALYZE(s, ascii, latin1, ucs2, ucs4, errors) \ do { \ if (s) while (*s) { \ utf8 c = *s++; \ if (IS_UTF8_1(c)) \ ascii++; \ else if (IS_UTF8_I(c)) { \ if (IS_UTF8_X(s[0])) \ latin1++, s++; \ else \ errors++; \ } \ else if (IS_UTF8_2(c)) { \ if (IS_UTF8_X(s[0])) \ ucs2++, s++; \ else \ errors++; \ } \ else if (IS_UTF8_3(c)) { \ if (IS_UTF8_X(s[0]) && IS_UTF8_X(s[1])) \ ucs2++, s++, s++; \ else \ errors++; \ } \ else if (IS_UTF8_4(c)) { \ if (IS_UTF8_X(s[0]) && IS_UTF8_X(s[1]) && IS_UTF8_X(s[2])) \ ucs4++, s++, s++, s++; \ else \ errors++; \ } \ else if (IS_UTF8_5(c)) { \ if (IS_UTF8_X(s[0]) && IS_UTF8_X(s[1]) && \ IS_UTF8_X(s[2]) && IS_UTF8_X(s[3])) \ ucs4++, s++, s++, s++, s++; \ else \ errors++; \ } \ else if (IS_UTF8_6(c)) { \ if (IS_UTF8_X(s[0]) && IS_UTF8_X(s[1]) && \ IS_UTF8_X(s[2]) && IS_UTF8_X(s[3]) && IS_UTF8_X(s[4])) \ ucs4++, s++, s++, s++, s++, s++; \ else \ errors++; \ } \ else \ errors++; \ } \ } while(0) #endif /* UTF8INTERNAL_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/ipt/utf8test.c000066400000000000000000000110761223300710500223050ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@internal * @CFILE utf8test.c UTF8 encoding - decoding tests * * @author Pekka Pessi * * @date Created: Tue Apr 21 15:32:38 1998 pessi */ #include "config.h" #include #include #include int main(int argc, char *argv[]) { static ucs4 ucs4test0[] = { 0x41u, 0xC1u, 0x841u, 0x10041u, 0x200041u, 0x4000041u, 0 }; static utf8 ucs4test1[] = "A" "\303\201" "\340\241\201" "\360\220\201\201" "\370\210\200\201\201" "\374\204\200\200\201\201"; static ucs2 ucs2test0[] = { 0x41u, 0xC1u, 0x841u, 0 }; static utf8 ucs2test1[] = "A" "\303\201" "\340\241\201"; ucs4 ucs4s[1024] = { 0 }; ucs2 ucs2s[1024] = { 0 }; utf8 utf8s[1024] = { 0 }; size_t len; int result = 0; int i; puts("testing ucs4len(ucs4test0)"); len = ucs4len(ucs4test0); if (len != 6) { printf("ucs4len(ucs4test0) returns %u\n", len); result = 1; } else puts("OK"); puts("testing ucs4declen(ucs4test1)"); len = ucs4declen(ucs4test1); if (len != 6) { printf("ucs4declen(ucs4test1) returns %u\n", len); result = 1; } else puts("OK"); puts("testing ucs4enclen(ucs4test0, 6, NULL)"); len = ucs4enclen(ucs4test0, 6, NULL); if (len != 22) { printf("ucs4enclen(ucs4test0, 6, NULL) returns %u\n", len); result = 1; } else puts("OK"); puts("testing ucs4enclen(ucs4test0, 5, NULL)"); len = ucs4enclen(ucs4test0, 5, NULL); if (len != 16) { printf("ucs4enclen(ucs4test0, 5, NULL) returns %u\n", len); result = 1; } else puts("OK"); puts("testing ucs4encode(utf8s, ucs4test0, 6, NULL)"); if (ucs4encode(utf8s, ucs4test0, 6, NULL) != 22 || strcmp((char *)utf8s, (char*)ucs4test1)) { printf("ucs4encode(utf8s, ucs4test0, 6, NULL) fails\n"); result = 1; printf("\tutf8s=\"%s\"\n", utf8s); } else puts("OK"); puts("testing ucs4decode(ucs4s, sizeof(ucs4s), ucs4test1)"); if (ucs4decode(ucs4s, sizeof(ucs4s)/sizeof(*ucs4s), ucs4test1) != 6 || ucs4cmp(ucs4s, ucs4test0)) { printf("ucs4decode(ucs4s, sizeof(ucs4s), ucs4test1) fails\n"); result = 1; for (i = 0; i < 8; i++) { printf("\tucs4s[%d]=0x%x\n", i, ucs4s[i]); } } else puts("OK"); /* UCS2 */ puts("testing ucs2len(ucs2test0)"); len = ucs2len(ucs2test0); if (len != 3) { printf("ucs2len(ucs2test0) returns %u\n", len); result = 1; } else puts("OK"); puts("testing ucs2declen(ucs2test1)"); len = ucs2declen(ucs2test1); if (len != 3) { printf("ucs2declen(ucs2test1) returns %u\n", len); result = 1; } else puts("OK"); puts("testing ucs2enclen(ucs2test0, 3, NULL)"); len = ucs2enclen(ucs2test0, 3, NULL); if (len != 7) { printf("ucs2enclen(ucs2test1, 3, NULL) returns %u\n", len); result = 1; } else puts("OK"); puts("testing ucs2enclen(ucs2test0, 2, NULL)"); len = ucs2enclen(ucs2test0, 2, NULL); if (len != 4) { printf("ucs2enclen(ucs2test1, NULL) returns %u\n", len); result = 1; } else puts("OK"); puts("testing ucs2encode(utf8s, ucs2test0, 3, NULL)"); if (ucs2encode(utf8s, ucs2test0, 3, NULL) != 7 || strcmp((char *)utf8s, (char*)ucs2test1)) { printf("ucs2encode(utf8s, ucs2test0, 3, NULL) fails\n"); result = 1; printf("\tutf8s=\"%s\"\n", utf8s); } else puts("OK"); puts("testing ucs2decode(ucs2s, sizeof(ucs2s)/sizeof(*ucs2s), ucs2test1)"); if (ucs2decode(ucs2s, sizeof(ucs2s)/sizeof(*ucs2s), ucs2test1) != 3 || ucs2cmp(ucs2s, ucs2test0)) { printf("ucs2decode(ucs2s, sizeof(ucs2s)/sizeof(*ucs2s), ucs2test1) fails\n"); result = 1; for (i = 0; i < 8; i++) { printf("\tucs2s[%d]=0x%x\n", i, ucs2s[i]); } } else puts("OK"); return result; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/000077500000000000000000000000001223300710500210415ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/ChangeLog000066400000000000000000000012531223300710500226140ustar00rootroot000000000000002005-11-08 Pekka Pessi * Renamed auth_digest_test.c as test_auth_digest.c. 2005-10-21 Pekka Pessi * Generate opaque only if opaque parameter has value "*". M ./libsofia-sip-ua/iptsec/auth_module.c -14 +20 2005-09-06 Pekka Pessi * auth_digest_test.c: Using opaque to match credentials (as per auth_digest_credentials()). * auth_plugin.h, auth_module.c: Added auth_digest_credentials. 2005-08-10 Pekka Pessi * auth_module.c: Using unsigned as type of hash! 2005-07-18 Kai Vehmanen * Initial import of the module to Sofia-SIP tree. sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/Doxyfile.in000066400000000000000000000016001223300710500231510ustar00rootroot00000000000000PROJECT_NAME = "iptsec" OUTPUT_DIRECTORY = ../docs/html/iptsec INPUT = @srcdir@/iptsec.docs @srcdir@/sofia-sip @srcdir@ . @INCLUDE_PATH = . @srcdir@ @INCLUDE = ../docs/Doxyfile.conf @INCLUDE = ../sip/sip.doxyaliases TAGFILES += ../docs/su.doxytags=../su TAGFILES += ../docs/ipt.doxytags=../ipt TAGFILES += ../docs/bnf.doxytags=../bnf TAGFILES += ../docs/url.doxytags=../url TAGFILES += ../docs/msg.doxytags=../msg TAGFILES += ../docs/sip.doxytags=../sip TAGFILES += ../docs/http.doxytags=../http TAGFILES += ../docs/sresolv.doxytags=../sresolv TAGFILES += ../docs/tport.doxytags=../tport TAGFILES += ../docs/nta.doxytags=../nta GENERATE_TAGFILE = ../docs/iptsec.doxytags ALIASES += "iptsec=@ref index \"iptsec\"" PREDEFINED += SOFIA_EXTEND_AUTH_CLIENT=1 sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/Makefile.am000066400000000000000000000043411223300710500230770ustar00rootroot00000000000000# # Makefile.am for iptsec module # # Copyright (C) 2005,2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # ---------------------------------------------------------------------- # Header paths INCLUDES = -I$(srcdir)/../bnf -I../bnf \ -I$(srcdir)/../ipt -I../ipt \ -I$(srcdir)/../http -I../http \ -I$(srcdir)/../msg -I../msg \ -I$(srcdir)/../nta -I../nta \ -I$(srcdir)/../sip -I../sip \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su # ---------------------------------------------------------------------- # Build targets noinst_LTLIBRARIES = libiptsec.la check_PROGRAMS = test_auth_digest TESTS = test_auth_digest # ---------------------------------------------------------------------- # Rules for building the targets BUILT_SOURCES = auth_tag_ref.c nobase_include_sofia_HEADERS = \ sofia-sip/auth_common.h \ sofia-sip/auth_client.h sofia-sip/auth_digest.h \ sofia-sip/auth_module.h sofia-sip/auth_plugin.h \ sofia-sip/auth_client_plugin.h libiptsec_la_SOURCES = iptsec_debug.h \ auth_client.c auth_common.c auth_digest.c \ auth_module.c auth_tag.c auth_tag_ref.c \ auth_plugin.c auth_plugin_delayed.c \ auth_module_sip.c \ iptsec_debug.c COVERAGE_INPUT = $(libiptsec_la_SOURCES) $(include_sofia_HEADERS) LDADD = libiptsec.la \ ../nta/libnta.la \ ../sip/libsip.la \ ../msg/libmsg.la \ ../url/liburl.la \ ../bnf/libbnf.la \ ../ipt/libipt.la \ ../su/libsu.la test_auth_digest_LDFLAGS = -static if HAVE_NTLM nobase_include_sofia_HEADERS += $(NTLM_HEADER) libiptsec_la_SOURCES += $(NTLM_SOURCE) endif if HAVE_NTH libiptsec_la_SOURCES += $(HTTP_SOURCE) LDADD += ../http/libhttp.la endif HTTP_SOURCE = auth_module_http.c NTLM_HEADER = sofia-sip/auth_ntlm.h NTLM_SOURCE = auth_ntlm.c auth_client_ntlm.c auth_plugin_ntlm.c EXTRA_libiptsec_la_SOURCES = \ $(NTLM_HEADER) $(NTLM_SOURCE) $(HTTP_SOURCE) # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST = iptsec.docs testpasswd $(BUILT_SOURCES) # ---------------------------------------------------------------------- # Sofia specific rules include $(top_srcdir)/rules/sofia.am sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/Makefile.in000066400000000000000000001406211223300710500231120ustar00rootroot00000000000000# Makefile.in generated by automake 1.14 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 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 iptsec module # # Copyright (C) 2005,2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # ---------------------------------------------------------------------- # Header paths # common Makefile targets for libsofia-sip-ua(-glib) modules # ---------------------------------------------------------- # # run tests with valgrind # # Copyright (C) 2007 Nokia Corporation. # 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 file contains free software from Makefile.in by the Free Software # Foundation: # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 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. # # Generate lcov output # # # Copyright (C) 2007 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # # Silent compilation w/ Automake 1.9 or 1.10 # ---------------------------------------------------------- # Automake 1.9.6 is not clever enough to override suffix rules within if # if SOFIA_COMPILE_SILENT VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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@ check_PROGRAMS = test_auth_digest$(EXEEXT) TESTS = test_auth_digest$(EXEEXT) @HAVE_NTLM_TRUE@am__append_1 = $(NTLM_HEADER) @HAVE_NTLM_TRUE@am__append_2 = $(NTLM_SOURCE) @HAVE_NTH_TRUE@am__append_3 = $(HTTP_SOURCE) @HAVE_NTH_TRUE@am__append_4 = ../http/libhttp.la DIST_COMMON = $(top_srcdir)/rules/sofia.am \ $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am \ $(top_srcdir)/rules/silent.am $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(srcdir)/Doxyfile.in \ $(top_srcdir)/depcomp $(am__nobase_include_sofia_HEADERS_DIST) \ $(top_srcdir)/test-driver ChangeLog # Use with --enable-ndebug @NDEBUG_TRUE@am__append_5 = -DNDEBUG @HAVE_GENPNG_TRUE@@HAVE_LCOV_TRUE@am__append_6 = --frames @HAVE_LCOV_TRUE@am__append_7 = lcov lcov-report lcov-rerun clean-lcov covcheck uncovered subdir = libsofia-sip-ua/iptsec ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(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)/m4/sac-coverage.m4 \ $(top_srcdir)/m4/sac-general.m4 \ $(top_srcdir)/m4/sac-openssl.m4 \ $(top_srcdir)/m4/sac-pkg-config.m4 $(top_srcdir)/m4/sac-su2.m4 \ $(top_srcdir)/m4/sac-tport.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libsofia-sip-ua/su/sofia-sip/su_configure.h CONFIG_CLEAN_FILES = Doxyfile CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libiptsec_la_LIBADD = am__libiptsec_la_SOURCES_DIST = iptsec_debug.h auth_client.c \ auth_common.c auth_digest.c auth_module.c auth_tag.c \ auth_tag_ref.c auth_plugin.c auth_plugin_delayed.c \ auth_module_sip.c iptsec_debug.c auth_ntlm.c \ auth_client_ntlm.c auth_plugin_ntlm.c auth_module_http.c am__objects_1 = auth_ntlm.lo auth_client_ntlm.lo auth_plugin_ntlm.lo @HAVE_NTLM_TRUE@am__objects_2 = $(am__objects_1) am__objects_3 = auth_module_http.lo @HAVE_NTH_TRUE@am__objects_4 = $(am__objects_3) am_libiptsec_la_OBJECTS = auth_client.lo auth_common.lo auth_digest.lo \ auth_module.lo auth_tag.lo auth_tag_ref.lo auth_plugin.lo \ auth_plugin_delayed.lo auth_module_sip.lo iptsec_debug.lo \ $(am__objects_2) $(am__objects_4) libiptsec_la_OBJECTS = $(am_libiptsec_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_auth_digest_SOURCES = test_auth_digest.c test_auth_digest_OBJECTS = test_auth_digest.$(OBJEXT) test_auth_digest_LDADD = $(LDADD) am__DEPENDENCIES_1 = test_auth_digest_DEPENDENCIES = libiptsec.la ../nta/libnta.la \ ../sip/libsip.la ../msg/libmsg.la ../url/liburl.la \ ../bnf/libbnf.la ../ipt/libipt.la ../su/libsu.la \ $(am__append_4) $(am__DEPENDENCIES_1) test_auth_digest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(test_auth_digest_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) -I$(top_builddir)/libsofia-sip-ua/su/sofia-sip depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f 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) 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 = $(libiptsec_la_SOURCES) $(EXTRA_libiptsec_la_SOURCES) \ test_auth_digest.c DIST_SOURCES = $(am__libiptsec_la_SOURCES_DIST) \ $(EXTRA_libiptsec_la_SOURCES) test_auth_digest.c am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__nobase_include_sofia_HEADERS_DIST = sofia-sip/auth_common.h \ sofia-sip/auth_client.h sofia-sip/auth_digest.h \ sofia-sip/auth_module.h sofia-sip/auth_plugin.h \ sofia-sip/auth_client_plugin.h sofia-sip/auth_ntlm.h 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)$(include_sofiadir)" HEADERS = $(nobase_include_sofia_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)` 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=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ 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_DRIVER = $(SHELL) $(top_srcdir)/test-driver 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) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CHECK_CFLAGS = @CHECK_CFLAGS@ CHECK_LIBS = @CHECK_LIBS@ COVERAGE_FLAGS = @COVERAGE_FLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CWFLAG = @CWFLAG@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV = @GCOV@ GENHTML = @GENHTML@ GENPNG = @GENPNG@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GLIB_VERSION = @GLIB_VERSION@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVER_SOFIA_SIP_UA_AGE = @LIBVER_SOFIA_SIP_UA_AGE@ LIBVER_SOFIA_SIP_UA_CUR = @LIBVER_SOFIA_SIP_UA_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_AGE = @LIBVER_SOFIA_SIP_UA_GLIB_AGE@ LIBVER_SOFIA_SIP_UA_GLIB_CUR = @LIBVER_SOFIA_SIP_UA_GLIB_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_REV = @LIBVER_SOFIA_SIP_UA_GLIB_REV@ LIBVER_SOFIA_SIP_UA_GLIB_SOVER = @LIBVER_SOFIA_SIP_UA_GLIB_SOVER@ LIBVER_SOFIA_SIP_UA_REV = @LIBVER_SOFIA_SIP_UA_REV@ LIBVER_SOFIA_SIP_UA_SOVER = @LIBVER_SOFIA_SIP_UA_SOVER@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MINGW_ENVIRONMENT = @MINGW_ENVIRONMENT@ MKDIR_P = @MKDIR_P@ MOSTLYCLEANFILES = @MOSTLYCLEANFILES@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ RANLIB = @RANLIB@ REPLACE_LIBADD = @REPLACE_LIBADD@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ SOFIA_GLIB_CFLAGS = @SOFIA_GLIB_CFLAGS@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ SOFIA_PLAT_CFLAGS = @SOFIA_PLAT_CFLAGS@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ VERSION = @VERSION@ VER_LIBSOFIA_SIP_UA_MAJOR_MINOR = @VER_LIBSOFIA_SIP_UA_MAJOR_MINOR@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ include_sofiadir = @include_sofiadir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ openssl_CFLAGS = @openssl_CFLAGS@ openssl_LIBS = @openssl_LIBS@ 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@ INCLUDES = -I$(srcdir)/../bnf -I../bnf \ -I$(srcdir)/../ipt -I../ipt \ -I$(srcdir)/../http -I../http \ -I$(srcdir)/../msg -I../msg \ -I$(srcdir)/../nta -I../nta \ -I$(srcdir)/../sip -I../sip \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su # ---------------------------------------------------------------------- # Build targets noinst_LTLIBRARIES = libiptsec.la # ---------------------------------------------------------------------- # Rules for building the targets BUILT_SOURCES = auth_tag_ref.c nobase_include_sofia_HEADERS = sofia-sip/auth_common.h \ sofia-sip/auth_client.h sofia-sip/auth_digest.h \ sofia-sip/auth_module.h sofia-sip/auth_plugin.h \ sofia-sip/auth_client_plugin.h $(am__append_1) libiptsec_la_SOURCES = iptsec_debug.h auth_client.c auth_common.c \ auth_digest.c auth_module.c auth_tag.c auth_tag_ref.c \ auth_plugin.c auth_plugin_delayed.c auth_module_sip.c \ iptsec_debug.c $(am__append_2) $(am__append_3) COVERAGE_INPUT = $(libiptsec_la_SOURCES) $(include_sofia_HEADERS) LDADD = libiptsec.la ../nta/libnta.la ../sip/libsip.la \ ../msg/libmsg.la ../url/liburl.la ../bnf/libbnf.la \ ../ipt/libipt.la ../su/libsu.la $(am__append_4) \ $(openssl_LIBS) test_auth_digest_LDFLAGS = -static HTTP_SOURCE = auth_module_http.c NTLM_HEADER = sofia-sip/auth_ntlm.h NTLM_SOURCE = auth_ntlm.c auth_client_ntlm.c auth_plugin_ntlm.c EXTRA_libiptsec_la_SOURCES = \ $(NTLM_HEADER) $(NTLM_SOURCE) $(HTTP_SOURCE) # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST = iptsec.docs testpasswd $(BUILT_SOURCES) sofiasrcdir = ${top_srcdir}/libsofia-sip-ua sofiabuilddir = ${top_builddir}/libsofia-sip-ua AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(SOFIA_CFLAGS) \ $(openssl_CFLAGS) $(SOFIA_PLAT_CFLAGS) $(am__append_5) SOFIA_COVERAGE = $(COVERAGE_FLAGS) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files TAG_AWK = ${sofiasrcdir}/su/tag_dll.awk SUFFIXES = _tag_ref.c _tag.c INTERNAL_INCLUDES = \ -I${sofiasrcdir}/features -I${sofiabuilddir}/features \ -I${sofiasrcdir}/ipt -I${sofiabuilddir}/ipt \ -I${sofiasrcdir}/iptsec -I${sofiabuilddir}/iptsec \ -I${sofiasrcdir}/bnf -I${sofiabuilddir}/bnf \ -I${sofiasrcdir}/http -I${sofiabuilddir}/http \ -I${sofiasrcdir}/msg -I${sofiabuilddir}/msg \ -I${sofiasrcdir}/nth -I${sofiabuilddir}/nth \ -I${sofiasrcdir}/nta -I${sofiabuilddir}/nta \ -I${sofiasrcdir}/nea -I${sofiabuilddir}/nea \ -I${sofiasrcdir}/nua -I${sofiabuilddir}/nua \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sdp -I${sofiabuilddir}/sdp \ -I${sofiasrcdir}/sip -I${sofiabuilddir}/sip \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sresolv -I${sofiabuilddir}/sresolv \ -I${sofiasrcdir}/tport -I${sofiabuilddir}/tport \ -I${sofiasrcdir}/stun -I${sofiabuilddir}/stun \ -I${sofiasrcdir}/url -I${sofiabuilddir}/url \ -I${sofiasrcdir}/su -I${sofiabuilddir}/su PHONY = built-sources clean-built-sources $(am__append_7) VALGRIND = valgrind VALGRINDFLAGS = --tool=memcheck # Scripts @HAVE_LCOV_TRUE@LCOV_UNCOVERED = ${top_srcdir}/scripts/uncovered @HAVE_LCOV_TRUE@LCOV_REPORT = ${top_srcdir}/scripts/lcov-report # Report directory @HAVE_LCOV_TRUE@lcovdir = ${top_builddir}/lcov # Options @HAVE_LCOV_TRUE@GENHTML_OPTIONS = --show-details --legend \ @HAVE_LCOV_TRUE@ $(am__append_6) # Fancy shell command that expands to directory relative to top_builddir @HAVE_LCOV_TRUE@expand_subdir = `pwd|sed "s'\`cd ${top_builddir};pwd\`''"` SOFIA_SILENT = @ LIBTOOL_FLAGS = --silent # From Automake 1.9.6 - LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(LIBTOOL_FLAGS) \ $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) LINK = ${SOFIA_SILENT}test "${SOFIA_SILENT}" != @ || echo ' LINK $@'; \ $(LIBTOOL) --tag=CC --mode=link $(LIBTOOL_FLAGS) \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: _tag_ref.c _tag.c .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.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 libsofia-sip-ua/iptsec/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu libsofia-sip-ua/iptsec/Makefile .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.am: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): Doxyfile: $(top_builddir)/config.status $(srcdir)/Doxyfile.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ 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}; \ } libiptsec.la: $(libiptsec_la_OBJECTS) $(libiptsec_la_DEPENDENCIES) $(EXTRA_libiptsec_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libiptsec_la_OBJECTS) $(libiptsec_la_LIBADD) $(LIBS) 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_auth_digest$(EXEEXT): $(test_auth_digest_OBJECTS) $(test_auth_digest_DEPENDENCIES) $(EXTRA_test_auth_digest_DEPENDENCIES) @rm -f test_auth_digest$(EXEEXT) $(AM_V_CCLD)$(test_auth_digest_LINK) $(test_auth_digest_OBJECTS) $(test_auth_digest_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_client.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_client_ntlm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_digest.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_module.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_module_http.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_module_sip.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_ntlm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_plugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_plugin_delayed.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_plugin_ntlm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_tag.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_tag_ref.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iptsec_debug.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_auth_digest.Po@am__quote@ .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.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) '$<'` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-nobase_include_sofiaHEADERS: $(nobase_include_sofia_HEADERS) @$(NORMAL_INSTALL) @list='$(nobase_include_sofia_HEADERS)'; test -n "$(include_sofiadir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(include_sofiadir)'"; \ $(MKDIR_P) "$(DESTDIR)$(include_sofiadir)" || exit 1; \ fi; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo " $(MKDIR_P) '$(DESTDIR)$(include_sofiadir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(include_sofiadir)/$$dir"; }; \ echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(include_sofiadir)/$$dir'"; \ $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(include_sofiadir)/$$dir" || exit $$?; }; \ done uninstall-nobase_include_sofiaHEADERS: @$(NORMAL_UNINSTALL) @list='$(nobase_include_sofia_HEADERS)'; test -n "$(include_sofiadir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ dir='$(DESTDIR)$(include_sofiadir)'; $(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; \ else \ 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 $(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_auth_digest.log: test_auth_digest$(EXEEXT) @p='test_auth_digest$(EXEEXT)'; \ b='test_auth_digest'; \ $(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: $(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: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(include_sofiadir)"; 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: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) -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: 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) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) 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) @HAVE_LCOV_FALSE@clean-local: clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libtool clean-local \ clean-noinstLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -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-nobase_include_sofiaHEADERS 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 -rf ./$(DEPDIR) -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-nobase_include_sofiaHEADERS .MAKE: all check check-am install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libtool clean-local \ 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-nobase_include_sofiaHEADERS 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 \ uninstall-nobase_include_sofiaHEADERS built-sources: $(BUILT_SOURCES) clean-built-sources: -rm -rf $(BUILT_SOURCES) $(BUILT_SOURCES:%=$(srcdir)/%) *_tag_ref.c: $(TAG_AWK) _tag.c_tag_ref.c: $(AWK) -f $(TAG_AWK) NODLL=1 $(TAG_DLL_FLAGS) REF=$@ $< ../bnf/libbnf.la ../http/libhttp.la ../ipt/libipt.la ../iptsec/libiptsec.la \ ../msg/libmsg.la ../nea/libnea.la ../nta/libnta.la ../nth/libnth.la \ ../nua/libnua.la ../sdp/libsdp.la ../sip/libsip.la ../soa/libsoa.la \ ../sresolv/libsresolv.la ../stun/libstun.la ../su/libsu.la \ ../tport/libtport.la ../url/liburl.la: cd $(@D) && $(MAKE) $(@F) checklib: $(noinst_LTLIBRARIES) $(check_LTLIBRARIES) valcheck: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) valcheck-am valcheck-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS # Run tests with valgrind in valcheck-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ list='$(TESTS)'; \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ if case $$tst in \ run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ $${dir}$$tst ;; \ esac ; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ echo "XPASS: $$tst"; \ ;; \ *) \ echo "PASS: $$tst"; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xfail=`expr $$xfail + 1`; \ echo "XFAIL: $$tst"; \ ;; \ *) \ failed=`expr $$failed + 1`; \ echo "FAIL: $$tst"; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ echo "SKIP: $$tst"; \ fi; \ done; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="All $$all tests passed"; \ else \ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all tests failed"; \ else \ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ skipped="($$skip tests were not run)"; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ report=""; \ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ report="Please report to $(PACKAGE_BUGREPORT)"; \ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ echo "$$dashes"; \ echo "$$banner"; \ test -z "$$skipped" || echo "$$skipped"; \ test -z "$$report" || echo "$$report"; \ echo "$$dashes"; \ test "$$failed" -eq 0; \ else :; fi # # Generate pretty coverage report (unless it has been already done) # @HAVE_LCOV_TRUE@lcov: @HAVE_LCOV_TRUE@ @-test -r ${lcovdir}${expand_subdir}/lcov.info \ @HAVE_LCOV_TRUE@ || make lcov-report # Generate pretty coverage report based on current coverage data @HAVE_LCOV_TRUE@lcov-report: @HAVE_LCOV_TRUE@ sub=${expand_subdir} odir=${lcovdir}$$sub ; \ @HAVE_LCOV_TRUE@ rm -rf $$odir ; mkdir -p $$odir && \ @HAVE_LCOV_TRUE@ ${LCOV_REPORT} ${GENHTML_OPTIONS} \ @HAVE_LCOV_TRUE@ --title "${PACKAGE_NAME}-${PACKAGE_VERSION}$$sub" \ @HAVE_LCOV_TRUE@ --srcdir=${srcdir} -o $$odir # Rerun checks before generating report @HAVE_LCOV_TRUE@lcov-rerun: clean-lcov @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) lcov-report # Show all uncovered lines as errors @HAVE_LCOV_TRUE@uncovered: @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} # Run check in current dir and show all uncovered lines as errors @HAVE_LCOV_TRUE@covcheck: @HAVE_LCOV_TRUE@ -find . -name "*.gcda" | xargs rm -rf @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} @HAVE_LCOV_TRUE@clean-local:: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true @HAVE_LCOV_TRUE@clean-lcov: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true # Rules from depend2.am (GENERIC = TRUE, SUBDIROBJ = FALSE, %FASTDEP% = am_fastdepCC) silenced. .c.o: @test "${SOFIA_SILENT}" != @ || echo ' COMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(COMPILE) -c -o $@ $< .c.lo: @test "${SOFIA_SILENT}" != @ || echo ' LTCOMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(LTCOMPILE) -c -o $@ $< # endif # ---------------------------------------------------------------------- # Sofia specific rules # 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: sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/auth_client.c000066400000000000000000001005241223300710500235060ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE auth_client.c Authenticators for SIP client * * @author Pekka Pessi * * @date Created: Wed Feb 14 18:32:58 2001 ppessi */ #include "config.h" #define SOFIA_EXTEND_AUTH_CLIENT 1 #include #include #include "sofia-sip/auth_common.h" #include "sofia-sip/auth_client.h" #include "sofia-sip/auth_client_plugin.h" #include #include #include #include #include #include #include #include #include #include #include #include static auth_client_t *ca_create(su_home_t *home, char const *scheme, char const *realm); static void ca_destroy(su_home_t *home, auth_client_t *ca); static int ca_challenge(auth_client_t *ca, msg_auth_t const *auth, msg_hclass_t *credential_class, char const *scheme, char const *realm); static int ca_info(auth_client_t *ca, msg_auth_info_t const *ai, msg_hclass_t *credential_class); static int ca_credentials(auth_client_t *ca, char const *scheme, char const *realm, char const *user, char const *pass); static int ca_clear_credentials(auth_client_t *ca); static int ca_has_authorization(auth_client_t const *ca); /** Initialize authenticators. * * The function auc_challenge() merges the challenge @a ch to the list of * authenticators @a auc_list. * * @param[in,out] auc_list list of authenticators to be updated * @param[in,out] home memory home used for allocating authenticators * @param[in] ch challenge to be processed * @param[in] crcl credential class * * @retval 1 when at least one challenge was updated * @retval 0 when there was no new challenges * @retval -1 upon an error */ int auc_challenge(auth_client_t **auc_list, su_home_t *home, msg_auth_t const *ch, msg_hclass_t *crcl) { auth_client_t **cca; int retval = 0; /* Go through each challenge in Authenticate or Proxy-Authenticate headers */ for (; ch; ch = ch->au_next) { char const *scheme = ch->au_scheme; char const *realm = msg_header_find_param(ch->au_common, "realm="); int matched = 0, updated; if (!scheme || !realm) continue; /* Update matching authenticator */ for (cca = auc_list; (*cca); cca = &(*cca)->ca_next) { updated = ca_challenge((*cca), ch, crcl, scheme, realm); if (updated < 0) return -1; if (updated == 0) continue; /* No match, next */ matched = 1; if (updated > 1) retval = 1; /* Updated authenticator */ } if (!matched) { /* There was no matching authenticator, create a new one */ *cca = ca_create(home, scheme, realm); if (*cca == NULL) { return -1; } else if (ca_challenge((*cca), ch, crcl, scheme, realm) < 0) { ca_destroy(home, *cca), *cca = NULL; return -1; } /* XXX - case w/ unknown authentication scheme */ else retval = 1; /* Updated authenticator */ } } return retval; } /** Update authentication client. * * @retval -1 upon an error * @retval 0 when challenge did not match * @retval 1 when challenge did match but was not updated * @retval 2 when challenge did match and updated client */ static int ca_challenge(auth_client_t *ca, msg_auth_t const *ch, msg_hclass_t *credential_class, char const *scheme, char const *realm) { int stale = 0; assert(ca); assert(ch); if (!ca || !ch) return -1; if (!su_casematch(ca->ca_scheme, scheme)) return 0; if (!su_strmatch(ca->ca_realm, realm)) return 0; if (ca->ca_credential_class && ca->ca_credential_class != credential_class) return 0; if (!ca->ca_auc) { ca->ca_credential_class = credential_class; return 1; } if (ca->ca_auc->auc_challenge) stale = ca->ca_auc->auc_challenge(ca, ch); if (stale < 0) return -1; if (!ca->ca_credential_class) stale = 2, ca->ca_credential_class = credential_class; return stale > 1 ? 2 : 1; } /** Store authentication info to authenticators. * * The function auc_info() feeds the authentication data from the @b * Authentication-Info header @a info to the list of authenticators @a * auc_list. * * @param[in,out] auc_list list of authenticators to be updated * @param[in] info info header to be processed * @param[in] credential_class corresponding credential class * * The authentication info can be in either @AuthenticationInfo or in * @ProxyAuthenticationInfo headers. If the header is @AuthenticationInfo, * the @a credential_class should be #sip_authorization_class or * #http_authorization_class. Likewise, If the header is * @ProxyAuthenticationInfo, the @a credential_class should be * #sip_proxy_authorization_class or #http_proxy_authorization_class. * The authentication into header usually contains next nonce or mutual * authentication information. Currently, only the nextnonce parameter is * processed. * * @bug * In principle, SIP allows more than one challenge for a single request. * For example, there can be multiple proxies that each challenge the * client. The result of storing authentication info can be quite unexpected * if there are more than one authenticator with the given type (specified * by @a credential_class). * * @retval number of challenges to updated * @retval 0 when there was no challenge to update * @retval -1 upon an error * * @NEW_1_12_5. */ int auc_info(auth_client_t **auc_list, msg_auth_info_t const *info, msg_hclass_t *credential_class) { auth_client_t *ca; int retval = 0; /* Go through each challenge in Authenticate or Proxy-Authenticate headers */ /* Update matching authenticator */ for (ca = *auc_list; ca; ca = ca->ca_next) { int updated = ca_info(ca, info, credential_class); if (updated < 0) return -1; if (updated >= 1) retval = 1; /* Updated authenticator */ } return retval; } /** Update authentication client with authentication info. * * @retval -1 upon an error * @retval 0 when challenge did not match * @retval 1 when challenge did match but was not updated * @retval 2 when challenge did match and updated client */ static int ca_info(auth_client_t *ca, msg_auth_info_t const *info, msg_hclass_t *credential_class) { assert(ca); assert(info); if (!ca || !info) return -1; if (!ca->ca_credential_class) return 0; if (ca->ca_credential_class != credential_class) return 0; if (!ca->ca_auc || (size_t)ca->ca_auc->auc_plugin_size <= offsetof(auth_client_plugin_t, auc_info) || !ca->ca_auc->auc_info) return 0; return ca->ca_auc->auc_info(ca, info); } /**Feed authentication data to the authenticator. * * The function auc_credentials() is used to provide the authenticators in * with authentication data (user name, secret). * * The authentication data has format as follows: * * scheme:"realm":user:pass * * For instance, @c Basic:"nokia-proxy":ppessi:verysecret * * For Digest authentication scheme, it is possible to provide hashed * password instead. The scheme and hashed password should have prefix * "HA1+". For instance, * @c HA1+Digest:"realm":user1:HA1+c0890ff7a4fadc50c45f392ec4312965 * * @todo The authentication data format sucks. * * @param[in,out] auc_list list of authenticators * @param[in,out] home memory home used for allocations * @param[in] data colon-separated authentication data * * @retval >0 when successful * @retval 0 if not authenticator matched with @a data * @retval -1 upon an error */ int auc_credentials(auth_client_t **auc_list, su_home_t *home, char const *data) { int retval = 0, match; char *s0, *s; char *scheme = NULL, *user = NULL, *pass = NULL, *realm = NULL; s0 = s = su_strdup(NULL, data); /* Parse authentication data */ /* Data is string like "Basic:\"agni\":user1:secret" or "Basic:\"[fe80::204:23ff:fea7:d60a]\":user1:secret" (IPv6) or "Basic:\"Use \\\"interesting\\\" username and password here:\"\ :user1:secret" */ if (s && (s = strchr(scheme = s, ':'))) *s++ = 0; if (s) { if (*s == '"') { realm = s; s += span_quoted(s); if (*s == ':') *s++ = 0; else realm = NULL, s = NULL; } else s = NULL; } if (s && (s = strchr(user = s, ':'))) *s++ = 0; if (s && (s = strchr(pass = s, ':'))) *s++ = 0; if (scheme && realm && user && pass) { for (; *auc_list; auc_list = &(*auc_list)->ca_next) { match = ca_credentials(*auc_list, scheme, realm, user, pass); if (match < 0) { retval = -1; break; } if (match) retval++; } } su_free(NULL, s0); return retval; } /**Feed authentication data to the authenticators. * * The function auc_credentials() is used to provide the authenticators in * with authentication tuple (scheme, realm, user name, secret). * * For @b Digest authentication scheme, it is possible to provide hashed * password instead. The @a scheme should contain "HA1+Digest", and the * @a password should be in hashed format prefixed with "HA1+". * * @param[in,out] auc_list list of authenticators * @param[in] scheme scheme to use (NULL, if any) * @param[in] realm realm to use (NULL, if any) * @param[in] user username * @param[in] pass password * * @retval >0 or number of updated clients when successful * @retval 0 when no client was updated * @retval -1 upon an error */ int auc_all_credentials(auth_client_t **auc_list, char const *scheme, char const *realm, char const *user, char const *pass) { int retval = 0, match; #if HAVE_SC_CRED_H /* XXX: add */ #endif if (user && pass) { for (; *auc_list; auc_list = &(*auc_list)->ca_next) { match = ca_credentials(*auc_list, scheme, realm, user, pass); if (match < 0) return -1; if (match) retval++; } } return retval; } int ca_credentials(auth_client_t *ca, char const *scheme, char const *realm, char const *user, char const *pass) { int (*save)(auth_client_t *ca, char const *scheme, char const *realm, char const *user, char const *pass); if (!ca || !ca->ca_scheme || !ca->ca_realm) return -1; save = AUTH_CLIENT_SAVE_CREDENTIALS(ca); if (save) return (*save)(ca, scheme, realm, user, pass); else return auth_client_save_credentials(ca, scheme, realm, user, pass); } /**Save authentication data to an authenticator. * * Function saves the authentication data in the authentication client, * if the scheme and the realm match. * * @param[in] ca client authenticator * @param[in] scheme scheme to use (NULL, if any) * @param[in] realm realm to use (NULL, if any) * @param[in] user username * @param[in] pass password * * @retval 1 if successful * @retval 0 data did not match * @retval -1 upon an error * * @NEW_1_12_11 */ int auth_client_save_credentials(auth_client_t *ca, char const *scheme, char const *realm, char const *user, char const *pass) { char *new_user, *new_pass; char *old_user, *old_pass; if (!ca || !ca->ca_scheme || !ca->ca_realm) return -1; if (scheme != NULL && !su_casematch(scheme, ca->ca_scheme)) return 0; if (realm != NULL && !su_strmatch(realm, ca->ca_realm)) return 0; old_user = ca->ca_user, old_pass = ca->ca_pass; if (su_strmatch(user, old_user) && su_strmatch(pass, old_pass)) return 0; new_user = su_strdup(ca->ca_home, user); new_pass = su_strdup(ca->ca_home, pass); if (!new_user || !new_pass) return -1; ca->ca_user = new_user, ca->ca_pass = new_pass; if (AUTH_CLIENT_IS_EXTENDED(ca)) ca->ca_clear = 0; su_free(ca->ca_home, old_user); su_free(ca->ca_home, old_pass); return 1; } /** Copy authentication data from @a src to @a dst. * * @param[in,out] dst destination list of authenticators * @param[in] src source list of authenticators * * @retval >0 if credentials were copied * @retval 0 if there was no credentials to copy * @retval <0 if an error occurred. */ int auc_copy_credentials(auth_client_t **dst, auth_client_t const *src) { int retval = 0; if (!dst) return -1; for (;*dst; dst = &(*dst)->ca_next) { auth_client_t *d = *dst; auth_client_t const *ca; for (ca = src; ca; ca = ca->ca_next) { int (*copy)(auth_client_t *d, auth_client_t const *s); int result; if (!ca->ca_user || !ca->ca_pass) continue; if (AUTH_CLIENT_IS_EXTENDED(ca) && ca->ca_clear) continue; copy = AUTH_CLIENT_COPY_CREDENTIALS(d); if (copy != NULL) result = (*copy)(d, src); else result = auth_client_copy_credentials(d, src); if (result < 0) return result; else if (result == 0) continue; else retval++; break; } } return retval; } /**Copy authentication data from a matching client in @a src to @a d. * * @retval 1 if credentials were copied * @retval 0 clients did not match * @retval -1 if an error occurred. * * @NEW_1_12_11 */ int auth_client_copy_credentials(auth_client_t *d, auth_client_t const *s) { char *u, *p; if (d == NULL || s == NULL) return -1; if (!s->ca_scheme[0] || !su_casematch(s->ca_scheme, d->ca_scheme)) return 0; if (!s->ca_realm || !su_strmatch(s->ca_realm, d->ca_realm)) return 0; if (!(AUTH_CLIENT_IS_EXTENDED(d) && d->ca_clear) && su_strmatch(d->ca_user, s->ca_user) && su_strmatch(d->ca_pass, s->ca_pass)) return 1; u = su_strdup(d->ca_home, s->ca_user); p = su_strdup(d->ca_home, s->ca_pass); if (!u || !p) return -1; su_free(d->ca_home, (void *)d->ca_user); su_free(d->ca_home, (void *)d->ca_pass); d->ca_user = u; d->ca_pass = p; if (AUTH_CLIENT_IS_EXTENDED(d)) d->ca_clear = 0; return 1; } /**Clear authentication data from the authenticator. * * The function auc_clear_credentials() is used to remove the credentials * from the authenticators. * * @param[in,out] auc_list list of authenticators * @param[in] scheme scheme (if non-null, remove only matching credentials) * @param[in] realm realm (if non-null, remove only matching credentials) * * @retval 0 when successful * @retval -1 upon an error */ int auc_clear_credentials(auth_client_t **auc_list, char const *scheme, char const *realm) { int retval = 0; int match; for (; *auc_list; auc_list = &(*auc_list)->ca_next) { auth_client_t *ca = *auc_list; if (!AUTH_CLIENT_IS_EXTENDED(ca)) continue; if ((scheme != NULL && !su_casematch(scheme, ca->ca_scheme)) || (realm != NULL && !su_strmatch(realm, ca->ca_realm))) continue; match = ca->ca_auc->auc_clear(*auc_list); if (match < 0) { retval = -1; break; } if (match) retval++; } return retval; } static int ca_clear_credentials(auth_client_t *ca) { assert(ca); assert(ca->ca_home->suh_size >= (int)(sizeof *ca)); if (!ca) return -1; ca->ca_clear = 1; return 1; } /** Check if there are credentials for all challenges. * * @retval 1 when authorization can proceed * @retval 0 when there is not enough credentials * * @NEW_1_12_5. */ int auc_has_authorization(auth_client_t **auc_list) { auth_client_t const *ca, *other; if (auc_list == NULL) return 0; for (ca = *auc_list; ca; ca = ca->ca_next) { if (!ca_has_authorization(ca)) { /* * Check if we have another challenge with same realm but different * scheme */ for (other = *auc_list; other; other = other->ca_next) { if (ca == other) continue; if (ca->ca_credential_class == other->ca_credential_class && su_strcmp(ca->ca_realm, other->ca_realm) == 0 && ca_has_authorization(other)) break; } if (!other) return 0; } } return 1; } static int ca_has_authorization(auth_client_t const *ca) { return ca->ca_credential_class && ca->ca_auc && ca->ca_user && ca->ca_pass && !(AUTH_CLIENT_IS_EXTENDED(ca) && ca->ca_clear); } /**Authorize a request. * * The function auc_authorization() is used to add correct authentication * headers to a request. The authentication headers will contain the * credentials generated by the list of authenticators. * * @param[in,out] auc_list list of authenticators * @param[out] msg message to be authenticated * @param[out] pub headers of the message * @param[in] method request method * @param[in] url request URI * @param[in] body message body (NULL if empty) * * @retval 1 when successful * @retval 0 when there is not enough credentials * @retval -1 upon an error */ int auc_authorization(auth_client_t **auc_list, msg_t *msg, msg_pub_t *pub, char const *method, url_t const *url, msg_payload_t const *body) { auth_client_t *ca; msg_mclass_t const *mc = msg_mclass(msg); if (auc_list == NULL || msg == NULL) return -1; if (!auc_has_authorization(auc_list)) return 0; if (pub == NULL) pub = msg_object(msg); /* Remove existing credential headers */ for (ca = *auc_list; ca; ca = ca->ca_next) { msg_header_t **hh = msg_hclass_offset(mc, pub, ca->ca_credential_class); while (hh && *hh) msg_header_remove(msg, pub, *hh); } /* Insert new credential headers */ for (; *auc_list; auc_list = &(*auc_list)->ca_next) { su_home_t *home = msg_home(msg); msg_header_t *h = NULL; ca = *auc_list; if (!ca->ca_auc) continue; if (!ca_has_authorization(ca)) continue; if (ca->ca_auc->auc_authorize(ca, home, method, url, body, &h) < 0) return -1; if (h == NULL) continue; if (msg_header_insert(msg, pub, h) < 0) return -1; } return 1; } /**Generate headers authorizing a request. * * The function auc_authorization_headers() is used to generate * authentication headers for a request. The list of authentication headers * will contain the credentials generated by the list of authenticators. * * @param[in] auc_list list of authenticators * @param[in] home memory home used to allocate headers * @param[in] method request method * @param[in] url request URI * @param[in] body message body (NULL if empty) * @param[out] return_headers authorization headers return value * * @retval 1 when successful * @retval 0 when there is not enough credentials * @retval -1 upon an error */ int auc_authorization_headers(auth_client_t **auc_list, su_home_t *home, char const *method, url_t const *url, msg_payload_t const *body, msg_header_t **return_headers) { auth_client_t *ca; /* Make sure every challenge has credentials */ if (!auc_has_authorization(auc_list)) return 0; /* Create new credential headers */ for (; *auc_list; auc_list = &(*auc_list)->ca_next) { msg_header_t *h = NULL; ca = *auc_list; if (!ca->ca_auc) continue; if (!ca_has_authorization(ca)) continue; if (ca->ca_auc->auc_authorize(ca, home, method, url, body, &h) < 0) return -1; *return_headers = h; while (*return_headers) return_headers = &(*return_headers)->sh_next; } return 1; } /* ---------------------------------------------------------------------- */ /* Basic scheme */ static int auc_basic_authorization(auth_client_t *ca, su_home_t *h, char const *method, url_t const *url, msg_payload_t const *body, msg_header_t **); static const auth_client_plugin_t ca_basic_plugin = { /* auc_plugin_size: */ sizeof ca_basic_plugin, /* auc_size: */ sizeof (auth_client_t), /* auc_name: */ "Basic", /* auc_challenge: */ NULL, /* auc_authorize: */ auc_basic_authorization, /* auc_info: */ NULL, /* auc_clear: */ ca_clear_credentials }; /**Create a basic authorization header. * * The function auc_basic_authorization() creates a basic authorization * header from username @a user and password @a pass. The authorization * header type is determined by @a hc - it can be sip_authorization_class, * sip_proxy_authorization_class, http_authorization_class, or * http_proxy_authorization_class, for instance. * * @param home memory home used to allocate memory for the new header * @param hc header class for the header to be created * @param user user name * @param pass password * * @return * The function auc_basic_authorization() returns a pointer to newly created * authorization header, or NULL upon an error. */ int auc_basic_authorization(auth_client_t *ca, su_home_t *home, char const *method, url_t const *url, msg_payload_t const *body, msg_header_t **return_headers) { msg_hclass_t *hc = ca->ca_credential_class; char const *user = ca->ca_user; char const *pass = ca->ca_pass; size_t ulen, plen, uplen, b64len, basiclen; char *basic, *base64, *userpass; char buffer[71]; if (user == NULL || pass == NULL) return -1; if (AUTH_CLIENT_IS_EXTENDED(ca) && ca->ca_clear) return 0; ulen = strlen(user), plen = strlen(pass), uplen = ulen + 1 + plen; b64len = BASE64_SIZE(uplen); basiclen = strlen("Basic ") + b64len; if (sizeof(buffer) > basiclen + 1) basic = buffer; else basic = malloc(basiclen + 1); if (basic == NULL) return -1; /* * Basic authentication consists of username and password separated by * colon and then base64 encoded. */ strcpy(basic, "Basic "); base64 = basic + strlen("Basic "); userpass = base64 + b64len - uplen; memcpy(userpass, user, ulen); userpass[ulen] = ':'; memcpy(userpass + ulen + 1, pass, plen); userpass[uplen] = '\0'; base64_e(base64, b64len + 1, userpass, uplen); base64[b64len] = '\0'; *return_headers = msg_header_make(home, hc, basic); if (buffer != basic) free(basic); return *return_headers ? 0 : -1; } /* ---------------------------------------------------------------------- */ /* Digest scheme */ typedef struct auth_digest_client_s { auth_client_t cda_client; int cda_ncount; char const *cda_cnonce; auth_challenge_t cda_ac[1]; } auth_digest_client_t; static int auc_digest_challenge(auth_client_t *ca, msg_auth_t const *ch); static int auc_digest_authorization(auth_client_t *ca, su_home_t *h, char const *method, url_t const *url, msg_payload_t const *body, msg_header_t **); static int auc_digest_info(auth_client_t *ca, msg_auth_info_t const *info); static int auc_digest_save_credentials(auth_client_t *ca, char const *scheme, char const *realm, char const *user, char const *pass); static int auc_digest_copy_credentials(auth_client_t *ca, auth_client_t const *src); static const auth_client_plugin_t ca_digest_plugin = { /* auc_plugin_size: */ sizeof ca_digest_plugin, /* auc_size: */ sizeof (auth_digest_client_t), /* auc_name: */ "Digest", /* auc_challenge: */ auc_digest_challenge, /* auc_authorize: */ auc_digest_authorization, /* auc_info: */ auc_digest_info, /* auc_clear: */ ca_clear_credentials, /* auc_save_credentials: */ auc_digest_save_credentials, /* auc_copy_credentials: */ auc_digest_copy_credentials, }; /** Store a digest authorization challenge. * * @retval 2 if credentials need to be (re)sent * @retval 1 if challenge was updated * @retval -1 upon an error */ static int auc_digest_challenge(auth_client_t *ca, msg_auth_t const *ch) { su_home_t *home = ca->ca_home; auth_digest_client_t *cda = (auth_digest_client_t *)ca; auth_challenge_t ac[1] = {{ sizeof ac }}; int stale; if (auth_digest_challenge_get(home, ac, ch->au_params) < 0) goto error; /* Check that we can handle the challenge */ if (!ac->ac_md5 && !ac->ac_md5sess) goto error; if (ac->ac_qop && !ac->ac_auth && !ac->ac_auth_int) goto error; stale = ac->ac_stale || cda->cda_ac->ac_nonce == NULL; if (ac->ac_qop && (cda->cda_cnonce == NULL || ac->ac_stale)) { su_guid_t guid[1]; char *cnonce; size_t b64len = BASE64_MINSIZE(sizeof(guid)) + 1; if (cda->cda_cnonce != NULL) /* Free the old one if we are updating after stale=true */ su_free(home, (void *)cda->cda_cnonce); su_guid_generate(guid); cda->cda_cnonce = cnonce = su_alloc(home, b64len); base64_e(cnonce, b64len, guid, sizeof(guid)); cda->cda_ncount = 0; } auth_digest_challenge_free_params(home, cda->cda_ac); *cda->cda_ac = *ac; return stale ? 2 : 1; error: auth_digest_challenge_free_params(home, ac); return -1; } static int auc_digest_info(auth_client_t *ca, msg_auth_info_t const *info) { auth_digest_client_t *cda = (auth_digest_client_t *)ca; su_home_t *home = ca->ca_home; char const *nextnonce = NULL; issize_t n; n = auth_get_params(home, info->ai_params, "nextnonce=", &nextnonce, NULL); if (n <= 0) return n; cda->cda_ac->ac_nonce = nextnonce; return 1; } /**Create a digest authorization header. * * Creates a digest authorization header from username @a user and password * @a pass, client nonce @a cnonce, client nonce count @a nc, request method * @a method, request URI @a uri and message body @a data. The authorization * header type is determined by @a hc - it can be either * sip_authorization_class or sip_proxy_authorization_class, as well as * http_authorization_class or http_proxy_authorization_class. * * @retval 1 when authorization headers has been created * @retval 0 when there is no credentials * @retval -1 upon an error */ static int auc_digest_authorization(auth_client_t *ca, su_home_t *home, char const *method, url_t const *url, msg_payload_t const *body, msg_header_t **return_headers) { auth_digest_client_t *cda = (auth_digest_client_t *)ca; msg_hclass_t *hc = ca->ca_credential_class; char const *user = ca->ca_user; char const *pass = ca->ca_pass; auth_challenge_t const *ac = cda->cda_ac; char const *cnonce = cda->cda_cnonce; unsigned nc = ++cda->cda_ncount; void const *data = body ? body->pl_data : ""; usize_t dlen = body ? body->pl_len : 0; char *uri; msg_header_t *h; char const *ha1; auth_hexmd5_t sessionkey, response; auth_response_t ar[1] = {{ 0 }}; char ncount[17]; if (!user || !pass || (AUTH_CLIENT_IS_EXTENDED(ca) && ca->ca_clear)) return 0; if (!su_casenmatch(pass, "HA1+", 4)) return 0; ha1 = pass + 4; ar->ar_size = sizeof(ar); ar->ar_username = user; ar->ar_realm = ac->ac_realm; ar->ar_nonce = ac->ac_nonce; ar->ar_algorithm = NULL; ar->ar_md5 = ac->ac_md5; ar->ar_md5sess = ac->ac_md5sess; ar->ar_opaque = ac->ac_opaque; ar->ar_qop = NULL; ar->ar_auth = ac->ac_auth; ar->ar_auth_int = ac->ac_auth_int; ar->ar_uri = uri = url_as_string(home, url); if (ar->ar_uri == NULL) return -1; /* If there is no qop, we MUST NOT include cnonce or nc */ if (!ar->ar_auth && !ar->ar_auth_int) cnonce = NULL; if (cnonce) { snprintf(ncount, sizeof(ncount), "%08x", nc); ar->ar_cnonce = cnonce; ar->ar_nc = ncount; } if (ar->ar_md5sess) { ar->ar_algorithm = "MD5-sess"; auth_digest_a1sess(ar, sessionkey, ha1); ha1 = sessionkey; } else { ar->ar_algorithm = "MD5"; } auth_digest_response(ar, response, ha1, method, data, dlen); h = msg_header_format(home, hc, "Digest " "username=\"%s\", " "realm=\"%s\", " "nonce=\"%s" "%s%s" "%s%s" "%s%s, " "uri=\"%s\", " "response=\"%s\"" "%s%s" "%s%s", ar->ar_username, ar->ar_realm, ar->ar_nonce, cnonce ? "\", cnonce=\"" : "", cnonce ? cnonce : "", ar->ar_opaque ? "\", opaque=\"" : "", ar->ar_opaque ? ar->ar_opaque : "", ar->ar_algorithm ? "\", algorithm=" : "", ar->ar_algorithm ? ar->ar_algorithm : "", ar->ar_uri, response, ar->ar_auth || ar->ar_auth_int ? ", qop=" : "", ar->ar_auth_int ? "auth-int" : (ar->ar_auth ? "auth" : ""), cnonce ? ", nc=" : "", cnonce ? ncount : ""); su_free(home, uri); if (!h) return -1; *return_headers = h; return 0; } static int auc_digest_save_credentials(auth_client_t *ca, char const *scheme, char const *realm, char const *user, char const *pass) { char prefixed[4 + sizeof (auth_hexmd5_t)]; /* "HA1+" and hex */ if (!ca) return -1; if (realm != NULL && !su_strmatch(realm, ca->ca_realm)) return 0; if (scheme == NULL || su_casematch(scheme, "Digest")) { strcpy(prefixed, "HA1+"); auth_digest_ha1(prefixed + strlen("HA1+"), user, ca->ca_realm, pass); pass = prefixed; } else if (su_strmatch(scheme, "HA1+Digest") && su_casenmatch(pass, "HA1+", 4)) pass = pass; else return 0; return auth_client_save_credentials(ca, NULL, NULL, user, pass); } static int auc_digest_copy_credentials(auth_client_t *ca, auth_client_t const *src) { return auth_client_copy_credentials(ca, src); } /* ---------------------------------------------------------------------- */ #define MAX_AUC 20 static auth_client_plugin_t const *ca_plugins[MAX_AUC] = { &ca_digest_plugin, &ca_basic_plugin, NULL }; /** Register an authentication client plugin */ int auc_register_plugin(auth_client_plugin_t const *plugin) { int i; if (plugin == NULL || plugin->auc_name == NULL || plugin->auc_authorize == NULL) return errno = EFAULT, -1; if (plugin->auc_size < (int) sizeof (auth_client_t)) return errno = EINVAL, -1; for (i = 0; i < MAX_AUC; i++) { if (ca_plugins[i] == NULL || su_strmatch(plugin->auc_name, ca_plugins[i]->auc_name) == 0) { ca_plugins[i] = plugin; return 0; } } return errno = ENOMEM, -1; } /** Allocate an (possibly extended) auth_client_t structure. */ static auth_client_t *ca_create(su_home_t *home, char const *scheme, char const *realm) { auth_client_plugin_t const *auc = NULL; auth_client_t *ca; size_t aucsize = (sizeof *ca), realmlen, size; char *s; int i; if (scheme == NULL || realm == NULL) return (void)(errno = EFAULT), NULL; realmlen = strlen(realm) + 1; for (i = 0; i < MAX_AUC; i++) { auc = ca_plugins[i]; if (!auc || su_casematch(auc->auc_name, scheme)) break; } /* XXX - should report error if the auth scheme is not known? */ aucsize = auc ? (size_t)auc->auc_size : (sizeof *ca); size = aucsize + realmlen; if (!auc) size += strlen(scheme) + 1; ca = su_home_clone(home, (isize_t)size); if (!ca) return ca; s = (char *)ca + aucsize; ca->ca_auc = auc; ca->ca_realm = strcpy(s, realm); ca->ca_scheme = auc ? auc->auc_name : strcpy(s + realmlen, scheme); return ca; } void ca_destroy(su_home_t *home, auth_client_t *ca) { su_free(home, ca); } #if HAVE_SOFIA_SIP #include /**Authorize a SIP request. * * The function auc_authorize() is used to add correct authentication * headers to a SIP request. The authentication headers will contain the * credentials generated by the list of authenticators. * * @param[in,out] auc_list list of authenticators * @param[in,out] msg message to be authenticated * @param[in,out] sip sip headers of the message * * @retval 1 when successful * @retval 0 when there is not enough credentials * @retval -1 upon an error */ int auc_authorize(auth_client_t **auc_list, msg_t *msg, sip_t *sip) { sip_request_t *rq = sip ? sip->sip_request : NULL; if (!rq) return 0; return auc_authorization(auc_list, msg, (msg_pub_t *)sip, rq->rq_method_name, /* RFC 3261 defines the protection domain based only on realm, so we do not bother get a correct URI to auth module. */ rq->rq_url, sip->sip_payload); } #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/auth_client_ntlm.c000066400000000000000000000150071223300710500245410ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE auth_client_ntlm.c NTLM authenticator for SIP client * * @author Pekka Pessi * * @date Created: Wed May 24 21:44:39 EEST 2006 */ #include "config.h" #include #include #include "sofia-sip/auth_ntlm.h" #include "sofia-sip/auth_client.h" #include "sofia-sip/auth_client_plugin.h" #include #include #include #include #include #include #include #include #include #include typedef struct auth_ntlm_client_s { auth_client_t ntlm_client; int ntlm_ncount; char const *ntlm_cnonce; auth_challenge_t ntlm_ac[1]; } auth_ntlm_client_t; static int auc_ntlm_challenge(auth_client_t *ca, msg_auth_t const *ch); static int auc_ntlm_authorization(auth_client_t *ca, su_home_t *h, char const *method, url_t const *url, msg_payload_t const *body, msg_header_t **); auth_client_plugin_t const _ntlm_client_plugin = { sizeof ca_ntlm_plugin, sizeof (auth_ntlm_client_t), "NTLM", auc_ntlm_challenge, auc_ntlm_authorization }; auth_client_plugin_t const * const ntlm_client_plugin = _ntlm_client_plugin; /** Store a ntlm authorization challenge. */ static int auc_ntlm_challenge(auth_client_t *ca, msg_auth_t const *ch) { su_home_t *home = ca->ca_home; auth_ntlm_client_t *ntlm = (auth_ntlm_client_t *)ca; auth_challenge_t ac[1] = {{ sizeof ac }}; int stale; if (auth_ntlm_challenge_get(home, ac, ch->au_params) < 0) goto error; /* Check that we can handle the challenge */ if (!ac->ac_md5 && !ac->ac_md5sess) goto error; if (ac->ac_qop && !ac->ac_auth && !ac->ac_auth_int) goto error; stale = ac->ac_stale || str0cmp(ac->ac_nonce, ntlm->ntlm_ac->ac_nonce); if (ac->ac_qop && (ntlm->ntlm_cnonce == NULL || ac->ac_stale)) { su_guid_t guid[1]; char *cnonce; if (ntlm->ntlm_cnonce != NULL) /* Free the old one if we are updating after stale=true */ su_free(home, (void *)ntlm->ntlm_cnonce); su_guid_generate(guid); ntlm->ntlm_cnonce = cnonce = su_alloc(home, BASE64_SIZE(sizeof(guid)) + 1); base64_e(cnonce, BASE64_SIZE(sizeof(guid)) + 1, guid, sizeof(guid)); ntlm->ntlm_ncount = 0; } auth_ntlm_challenge_free_params(home, ntlm->ntlm_ac); *ntlm->ntlm_ac = *ac; return stale ? 2 : 1; error: auth_ntlm_challenge_free_params(home, ac); return -1; } /**Create a NTLM authorization header. * * Creates a ntlm authorization header from username @a user and password * @a pass, client nonce @a cnonce, client nonce count @a nc, request method * @a method, request URI @a uri and message body @a data. The authorization * header type is determined by @a hc - it can be either * sip_authorization_class or sip_proxy_authorization_class, as well as * http_authorization_class or http_proxy_authorization_class. * * @param home memory home used to allocate memory for the new header * @param hc header class for the header to be created * @param user user name * @param pass password * @param ac challenge structure * @param cnonce client nonce * @param nc client nonce count * @param method request method * @param uri request uri * @param data message body * @param dlen length of message body * * @return * Returns a pointer to newly created authorization header, or NULL upon an * error. */ int auc_ntlm_authorization(auth_client_t *ca, su_home_t *home, char const *method, url_t const *url, msg_payload_t const *body, msg_header_t **return_headers) { auth_ntlm_client_t *ntlm = (auth_ntlm_client_t *)ca; msg_hclass_t *hc = ca->ca_credential_class; char const *user = ca->ca_user; char const *pass = ca->ca_pass; auth_challenge_t const *ac = ntlm->ntlm_ac; char const *cnonce = ntlm->ntlm_cnonce; unsigned nc = ++ntlm->ntlm_ncount; char *uri = url_as_string(home, url); void const *data = body ? body->pl_data : ""; int dlen = body ? body->pl_len : 0; msg_header_t *h; auth_hexmd5_t sessionkey, response; auth_response_t ar[1] = {{ 0 }}; char ncount[17]; ar->ar_size = sizeof(ar); ar->ar_username = user; ar->ar_realm = ac->ac_realm; ar->ar_nonce = ac->ac_nonce; ar->ar_algorithm = NULL; ar->ar_md5 = ac->ac_md5; ar->ar_md5sess = ac->ac_md5sess; ar->ar_opaque = ac->ac_opaque; ar->ar_qop = NULL; ar->ar_auth = ac->ac_auth; ar->ar_auth_int = ac->ac_auth_int; ar->ar_uri = uri; /* If there is no qop, we MUST NOT include cnonce or nc */ if (!ar->ar_auth && !ar->ar_auth_int) cnonce = NULL; if (cnonce) { snprintf(ncount, sizeof(ncount), "%08x", nc); ar->ar_cnonce = cnonce; ar->ar_nc = ncount; } auth_ntlm_sessionkey(ar, sessionkey, pass); auth_ntlm_response(ar, response, sessionkey, method, data, dlen); h = msg_header_format(home, hc, "NTLM " "username=\"%s\", " "realm=\"%s\", " "nonce=\"%s" "%s%s" "%s%s" "%s%s, " "uri=\"%s\", " "response=\"%s\"" "%s%s" "%s%s", ar->ar_username, ar->ar_realm, ar->ar_nonce, cnonce ? "\", cnonce=\"" : "", cnonce ? cnonce : "", ar->ar_opaque ? "\", opaque=\"" : "", ar->ar_opaque ? ar->ar_opaque : "", ar->ar_algorithm ? "\", algorithm=" : "", ar->ar_algorithm ? ar->ar_algorithm : "", ar->ar_uri, response, ar->ar_auth || ar->ar_auth_int ? ", qop=" : "", ar->ar_auth_int ? "auth-int" : (ar->ar_auth ? "auth" : ""), cnonce ? ", nc=" : "", cnonce ? ncount : ""); su_free(home, uri); if (!h) return -1; *return_headers = h; return 0; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/auth_common.c000066400000000000000000000112251223300710500235170ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE auth_common.c * * Functions common to both client and server authentication. * * @author Pekka Pessi * * @date Original Created: Thu Feb 22 12:10:37 2001 ppessi * @date Created: Wed May 17 13:37:50 EEST 2006 ppessi */ #include "config.h" #include "sofia-sip/auth_common.h" #include "sofia-sip/msg_header.h" #include #include #include #include #include su_inline int has_token(char const *qstring, char const *token); /** * Parse authentication parameters. * * The function auth_get_params() searches for the authentication parameters * in @a params. The parameter list @a params is seached for each parameter * given in in vararg section, and if it is found, its value is assigned to * the given address. * * @note The field name should contain the equal ("=") sign. * * @return * The function auth_get_params() returns number of parameters found in * params, or -1 upon an error. */ issize_t auth_get_params(su_home_t *home, char const * const params[], ... /* char const *fmt, char const **return_value */) { int n, j; size_t len, namelen; char const *fmt, *expected; char const *value, *p, **return_value; va_list(ap); assert(params); if (!params) return -1; va_start(ap, params); for (n = 0; (fmt = va_arg(ap, char const *));) { return_value = va_arg(ap, char const **); len = strlen(fmt); if (!len) continue; namelen = strcspn(fmt, "="); expected = fmt + namelen + 1; value = NULL; if (expected[0]) { /* value match: format is name=expected, if expected is found in parameter value, return non-NULL pointer in *return_value */ for (j = 0; (p = params[j++]);) { if (su_casematch(p, fmt)) { /* Matched the whole parameter with fmt name=expected */ value = p; break; } else if (!su_casenmatch(p, fmt, namelen) || p[namelen] != '=') continue; p = p + namelen + 1; if (p[0] == '"' && has_token(p, expected)) { /* Quoted parameter value has expected value, * e.g., qop=auth matches qop="auth,auth-int" */ value = p; break; } else if (su_casematch(p, expected)) { /* Parameter value matches with extected value * e.g., qop=auth matches qop=auth */ value = p; break; } } } else { /* format is name= , return unquoted parameter value after = */ for (j = 0; (p = params[j++]);) { if (!su_casenmatch(p, fmt, len)) continue; if (p[len] == '"') value = msg_unquote_dup(home, p + len); else value = su_strdup(home, p + len); if (value == NULL) { va_end(ap); return -1; } break; } } if (value) { *return_value = value; n++; } } va_end(ap); return n; } int auth_struct_copy(void *dst, void const *src, isize_t s_size) { int d_size = *(int *)dst; if (d_size < 0) return -1; if ((size_t)d_size > s_size) { memcpy(dst, src, s_size); memset((char *)dst + s_size, 0, d_size - s_size); } else { memcpy(dst, src, d_size); *(int *)dst = d_size; } return 0; } su_inline int has_token(char const *qstring, char const *token) { size_t n = strlen(token); char const *q; q = su_strcasestr(qstring, token); return (q && (q[n] == 0 || strchr("\", \t", q[n])) && (q == qstring || strchr("\", \t", q[-1]))); } /** Compare two strings, even if they are quoted */ int auth_strcmp(char const *quoted, char const *unquoted) { size_t i, j; if (quoted[0] != '"') return strcmp(quoted, unquoted); /* Compare quoted with unquoted */ for (i = 1, j = 0; ; i++, j++) { char q = quoted[i], u = unquoted[j]; if (q == '"') q = '\0'; else if (q == '\\' && u != '\0') q = quoted[i++]; if (q - u) return q - u; if (q == '\0') return 0; } } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/auth_digest.c000066400000000000000000000225641223300710500235160ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE auth_digest.c * * Implementation for digest authentication. * * @author Pekka Pessi * * @date Created: Thu Feb 22 12:10:37 2001 ppessi */ #include "config.h" #include #include "sofia-sip/auth_common.h" #include "sofia-sip/auth_digest.h" #include "sofia-sip/msg_header.h" #include "sofia-sip/auth_common.h" #include "iptsec_debug.h" #include #include #include #include #include /**Get digest-challenge parameters. * * The function digest_challenge_get() searches for the digest authentication * parameters in @a params. The parameters are assigned to the appropriate * fields in @a ac structure. * * @return * * The function digest_challenge_get() returns number of parameters * found, or -1 upon an error. */ issize_t auth_digest_challenge_get(su_home_t *home, auth_challenge_t *ac0, char const * const params[]) { ssize_t n; auth_challenge_t ac[1] = {{ 0 }}; char const *md5 = NULL, *md5sess = NULL, *sha1 = NULL, *stale = NULL, *qop_auth = NULL, *qop_auth_int = NULL; ac->ac_size = sizeof(ac); assert(ac0); assert(ac0->ac_size >= (int) sizeof(*ac)); if (ac0 == NULL || params == NULL) return -1; n = auth_get_params(home, params, "realm=", &ac->ac_realm, "domain=", &ac->ac_domain, "nonce=", &ac->ac_nonce, "opaque=", &ac->ac_opaque, "algorithm=", &ac->ac_algorithm, "qop=", &ac->ac_qop, "algorithm=md5", &md5, "algorithm=md5-sess", &md5sess, "algorithm=sha1", &sha1, "stale=true", &stale, "qop=auth", &qop_auth, "qop=auth-int", &qop_auth_int, NULL); if (n < 0) return n; ac->ac_stale = stale != NULL; ac->ac_md5 = md5 != NULL || ac->ac_algorithm == NULL; ac->ac_md5sess = md5sess != NULL; ac->ac_sha1 = sha1 != NULL; ac->ac_auth = qop_auth != NULL; ac->ac_auth_int = qop_auth_int != NULL; auth_struct_copy(ac0, ac, sizeof(ac)); SU_DEBUG_5(("%s(): got "MOD_ZD"\n", "auth_digest_challenge_get", n)); return n; } /** Free challenge parameters */ void auth_digest_challenge_free_params(su_home_t *home, auth_challenge_t *ac) { if (ac->ac_realm) su_free(home, (void *)ac->ac_realm), ac->ac_realm = NULL; if (ac->ac_domain) su_free(home, (void *)ac->ac_domain), ac->ac_domain = NULL; if (ac->ac_nonce) su_free(home, (void *)ac->ac_nonce), ac->ac_nonce = NULL; if (ac->ac_opaque) su_free(home, (void *)ac->ac_opaque), ac->ac_opaque = NULL; if (ac->ac_algorithm) su_free(home, (void *)ac->ac_algorithm), ac->ac_algorithm = NULL; if (ac->ac_qop) su_free(home, (void *)ac->ac_qop), ac->ac_qop = NULL; } /**Get digest-response parameters. * * The function auth_response_get() searches for the digest authentication * parameters in @a params. The parameters are assigned to the appropriate * fields in @a ar structure. * * @return * * The function auth_response_get() returns number of parameters * found, or -1 upon an error. */ issize_t auth_digest_response_get(su_home_t *home, auth_response_t *ar0, char const *const params[]) { ssize_t n; auth_response_t ar[1] = {{ 0 }}; char const *md5 = NULL, *md5sess = NULL, *sha1 = NULL, *qop_auth = NULL, *qop_auth_int = NULL; ar->ar_size = sizeof(ar); assert(ar0); assert(params); assert(ar0->ar_size >= (int) sizeof(ar)); if (ar0 == NULL || params == NULL) return -1; n = auth_get_params(home, params, "username=", &ar->ar_username, "realm=", &ar->ar_realm, "nonce=", &ar->ar_nonce, "uri=", &ar->ar_uri, "response=", &ar->ar_response, "algorithm=", &ar->ar_algorithm, "opaque=", &ar->ar_opaque, "cnonce=", &ar->ar_cnonce, "qop=", &ar->ar_qop, "nc=", &ar->ar_nc, "algorithm=md5", &md5, "algorithm=md5-sess", &md5sess, "algorithm=sha1", &sha1, "qop=auth", &qop_auth, "qop=auth-int", &qop_auth_int, NULL); if (n < 0) return n; ar->ar_md5 = md5 != NULL || ar->ar_algorithm == NULL; ar->ar_md5sess = md5sess != NULL; ar->ar_sha1 = sha1 != NULL; ar->ar_auth = qop_auth != NULL; ar->ar_auth_int = qop_auth_int != NULL; auth_struct_copy(ar0, ar, sizeof(ar)); SU_DEBUG_7(("%s: "MOD_ZD"\n", "auth_digest_response_get", n)); return n; } static void unquote_update(su_md5_t md5[1], char const *quoted) { if (!quoted) /*xyzzy*/; else if (quoted[0] == '"') { char const *q; size_t n; for (q = quoted + 1; *q; q += n + 2) { n = strcspn(q, "\"\\"); su_md5_update(md5, q, n); if (q[n] == '"' || q[n] == '\0') break; su_md5_update(md5, q + n + 1, 1); } } else su_md5_strupdate(md5, quoted); } /** Generate the hex A1 hash for digest authentication. @NEW_1_12_11 */ int auth_digest_ha1(auth_hexmd5_t ha1, char const *username, char const *realm, char const *secret) { su_md5_t md5[1]; /* Calculate A1 */ su_md5_init(md5); su_md5_strupdate(md5, username); su_md5_update(md5, ":", 1); unquote_update(md5, realm); su_md5_update(md5, ":", 1); su_md5_strupdate(md5, secret); su_md5_hexdigest(md5, ha1); SU_DEBUG_5(("auth_digest_ha1() has A1 = MD5(%s:%s:%s) = %s\n", username, realm, "*******", ha1)); return 0; } /** Generate A1 hash for digest authentication. */ int auth_digest_a1(auth_response_t *ar, auth_hexmd5_t ha1, char const *secret) { return auth_digest_ha1(ha1, ar->ar_username, ar->ar_realm, secret); } int auth_digest_a1sess(auth_response_t *ar, auth_hexmd5_t ha1sess, char const *ha1) { su_md5_t md5[1]; su_md5_init(md5); su_md5_strupdate(md5, ha1); su_md5_update(md5, ":", 1); unquote_update(md5, ar->ar_nonce); su_md5_update(md5, ":", 1); unquote_update(md5, ar->ar_cnonce); su_md5_hexdigest(md5, ha1sess); SU_DEBUG_5(("auth_sessionkey has A1' = MD5(%s:%s:%s) = %s\n", ha1, ar->ar_nonce, ar->ar_cnonce, ha1sess)); return 0; } /** Generate MD5 session key for digest authentication. */ int auth_digest_sessionkey(auth_response_t *ar, auth_hexmd5_t ha1, char const *secret) { if (ar->ar_md5sess) ar->ar_algorithm = "MD5-sess"; else if (ar->ar_md5) ar->ar_algorithm = "MD5"; else return -1; if (ar->ar_md5sess) { auth_hexmd5_t base_ha1; auth_digest_a1(ar, base_ha1, secret); auth_digest_a1sess(ar, ha1, base_ha1); } else { auth_digest_a1(ar, ha1, secret); } return 0; } /** Generate response for digest authentication. * */ int auth_digest_response(auth_response_t *ar, auth_hexmd5_t response, auth_hexmd5_t const ha1, char const *method_name, void const *data, isize_t dlen) { su_md5_t md5[1]; auth_hexmd5_t Hentity, HA2; if (ar->ar_auth_int) ar->ar_qop = "auth-int"; else if (ar->ar_auth) ar->ar_qop = "auth"; else ar->ar_qop = NULL; /* Calculate Hentity */ if (ar->ar_auth_int) { if (data && dlen) { su_md5_init(md5); su_md5_update(md5, data, dlen); su_md5_hexdigest(md5, Hentity); } else { strcpy(Hentity, "d41d8cd98f00b204e9800998ecf8427e"); } } /* Calculate A2 */ su_md5_init(md5); su_md5_strupdate(md5, method_name); su_md5_update(md5, ":", 1); unquote_update(md5, ar->ar_uri); if (ar->ar_auth_int) { su_md5_update(md5, ":", 1); su_md5_update(md5, Hentity, sizeof(Hentity) - 1); } su_md5_hexdigest(md5, HA2); SU_DEBUG_5(("A2 = MD5(%s:%s%s%s)\n", method_name, ar->ar_uri, ar->ar_auth_int ? ":" : "", ar->ar_auth_int ? Hentity : "")); /* Calculate response */ su_md5_init(md5); su_md5_update(md5, ha1, 32); su_md5_update(md5, ":", 1); unquote_update(md5, ar->ar_nonce); if (ar->ar_auth || ar->ar_auth_int) { su_md5_update(md5, ":", 1); su_md5_strupdate(md5, ar->ar_nc); su_md5_update(md5, ":", 1); unquote_update(md5, ar->ar_cnonce); su_md5_update(md5, ":", 1); su_md5_strupdate(md5, ar->ar_qop); } su_md5_update(md5, ":", 1); su_md5_update(md5, HA2, 32); su_md5_hexdigest(md5, response); SU_DEBUG_5(("auth_response: %s = MD5(%s:%s%s%s%s%s%s%s:%s) (qop=%s)\n", response, ha1, ar->ar_nonce, ar->ar_auth || ar->ar_auth_int ? ":" : "", ar->ar_auth || ar->ar_auth_int ? ar->ar_nc : "", ar->ar_auth || ar->ar_auth_int ? ":" : "", ar->ar_auth || ar->ar_auth_int ? ar->ar_cnonce : "", ar->ar_auth || ar->ar_auth_int ? ":" : "", ar->ar_auth || ar->ar_auth_int ? ar->ar_qop : "", HA2, ar->ar_qop ? ar->ar_qop : "NONE")); return 0; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/auth_module.c000066400000000000000000001147461223300710500235300ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE auth_module.c * @brief Authentication verification module * * The authentication module provides server or proxy-side authentication * verification for network elements like registrars, presence servers, and * proxies. * * @author Pekka Pessi . * * @date Created: Wed Apr 11 15:14:03 2001 ppessi */ #include "config.h" #include #include #include #include #include #include #include #include #include #include "iptsec_debug.h" #if HAVE_FUNC #elif HAVE_FUNCTION #define __func__ __FUNCTION__ #else static char const __func__[] = "auth_mod"; #endif #include #include #include #include #include #include #include #include #include #include "sofia-sip/auth_module.h" #include "sofia-sip/auth_plugin.h" #define APW_HASH(apw) ((apw)->apw_index) char const auth_internal_server_error[] = "Internal server error"; static void auth_call_scheme_destructor(void *); static void auth_md5_hmac_key(auth_mod_t *am); HTABLE_PROTOS_WITH(auth_htable, aht, auth_passwd_t, usize_t, unsigned); HTABLE_BODIES_WITH(auth_htable, aht, auth_passwd_t, APW_HASH, usize_t, unsigned); /**Allocate an authentication module instance. * * The function auth_mod_alloc() allocates an authentication module object. * */ auth_mod_t *auth_mod_alloc(auth_scheme_t *scheme, tag_type_t tag, tag_value_t value, ...) { auth_mod_t *am = NULL; if ((am = su_home_new(scheme->asch_size))) { am->am_scheme = scheme; su_home_destructor(am->am_home, auth_call_scheme_destructor); } return am; } /**Initialize an authentication module instance. * * The function auth_mod_init_default() initializes an authentication module * object used to authenticate the requests. * * @param am * @param base * @param root * @param tag,value,... tagged argument list * * @TAGS * AUTHTAG_REALM(), AUTHTAG_OPAQUE(), AUTHTAG_DB(), AUTHTAG_QOP(), * AUTHTAG_ALGORITHM(), AUTHTAG_EXPIRES(), AUTHTAG_NEXT_EXPIRES(), * AUTHTAG_BLACKLIST(), AUTHTAG_FORBIDDEN(), AUTHTAG_ANONYMOUS(), * AUTHTAG_FAKE(), AUTHTAG_ALLOW(), AUTHTAG_REMOTE(), and * AUTHTAG_MASTER_KEY(). * * @return 0 if successful * @return -1 upon an error */ int auth_init_default(auth_mod_t *am, auth_scheme_t *base, su_root_t *root, tag_type_t tag, tag_value_t value, ...) { int retval = 0; ta_list ta; char const *realm = NULL, *opaque = NULL, *db = NULL, *allows = NULL; char const *qop = NULL, *algorithm = NULL; unsigned expires = 60 * 60, next_expires = 5 * 60; unsigned max_ncount = 0; unsigned blacklist = 5; int forbidden = 0; int anonymous = 0; int fake = 0; url_string_t const *remote = NULL; char const *master_key = "fish"; char *s; ta_start(ta, tag, value); /* Authentication stuff */ tl_gets(ta_args(ta), AUTHTAG_REALM_REF(realm), AUTHTAG_OPAQUE_REF(opaque), AUTHTAG_DB_REF(db), AUTHTAG_QOP_REF(qop), AUTHTAG_ALGORITHM_REF(algorithm), AUTHTAG_EXPIRES_REF(expires), AUTHTAG_NEXT_EXPIRES_REF(next_expires), AUTHTAG_MAX_NCOUNT_REF(max_ncount), AUTHTAG_BLACKLIST_REF(blacklist), AUTHTAG_FORBIDDEN_REF(forbidden), AUTHTAG_ANONYMOUS_REF(anonymous), AUTHTAG_FAKE_REF(fake), AUTHTAG_ALLOW_REF(allows), AUTHTAG_REMOTE_REF(remote), AUTHTAG_MASTER_KEY_REF(master_key), TAG_NULL()); if (!realm) realm = "*"; if (!allows) allows = "ACK, BYE, CANCEL"; am->am_realm = su_strdup(am->am_home, realm); am->am_opaque = su_strdup(am->am_home, opaque); am->am_db = su_strdup(am->am_home, db); s = su_strdup(am->am_home, allows); if (s) msg_commalist_d(am->am_home, &s, &am->am_allow, NULL); am->am_expires = expires; am->am_next_exp = next_expires; am->am_max_ncount = max_ncount; am->am_blacklist = blacklist; am->am_forbidden = forbidden; am->am_anonymous = anonymous; am->am_fake = fake; am->am_remote = url_hdup(am->am_home, (url_t *)remote); am->am_algorithm = algorithm ? su_strdup(am->am_home, algorithm) : "MD5"; am->am_nextnonce = !algorithm || su_casematch(algorithm, "MD5"); if (next_expires == 0) am->am_nextnonce = 0; am->am_qop = su_strdup(am->am_home, qop); if (master_key) { su_md5_t md5[1]; su_md5_init(md5); su_md5_strupdate(md5, master_key); su_md5_strupdate(md5, "70P 53KR37"); su_md5_digest(md5, am->am_master_key); } auth_md5_hmac_key(am); /* Make sure that we have something that can be used to identify credentials */ if (am->am_opaque && strcmp(am->am_opaque, "*") == 0) { #ifndef HOST_NAME_MAX #define HOST_NAME_MAX 255 #endif char hostname[HOST_NAME_MAX + 1]; su_md5_t md5[1]; uint8_t hmac[6]; gethostname(hostname, sizeof hostname); auth_md5_hmac_init(am, md5); su_md5_strupdate(md5, hostname); su_md5_update(md5, ":", 1); if (am->am_remote) url_update(md5, am->am_remote); auth_md5_hmac_digest(am, md5, hmac, sizeof hmac); base64_e(hostname, sizeof hostname, hmac, sizeof hmac); am->am_opaque = su_strdup(am->am_home, hostname); if (!am->am_opaque) { retval = -1; SU_DEBUG_1(("%s: cannot create unique identifier\n", __func__)); } } if (retval < 0) ; else if (db) { retval = auth_readdb(am); if (retval == -1) { int err = errno; SU_DEBUG_1(("auth-module: %s: %s\n", am->am_db, strerror(err))); errno = err; } } else { retval = auth_htable_resize(am->am_home, am->am_users, 0); } ta_end(ta); return retval; } /** Destroy (a reference to) an authentication module. */ void auth_mod_destroy(auth_mod_t *am) { su_home_unref(am->am_home); } /** Call scheme-specific destructor function. */ static void auth_call_scheme_destructor(void *arg) { auth_mod_t *am = arg; am->am_scheme->asch_destroy(am); } /** Do-nothing destroy function. * * The auth_destroy_default() is the default member function called by * auth_mod_destroy(). */ void auth_destroy_default(auth_mod_t *am) { } /** Create a new reference to authentication module. */ auth_mod_t *auth_mod_ref(auth_mod_t *am) { return (auth_mod_t *)su_home_ref(am->am_home); } /** Destroy a reference to an authentication module. */ void auth_mod_unref(auth_mod_t *am) { su_home_unref(am->am_home); } /** Get authenticatin module name. @NEW_1_12_4. */ char const *auth_mod_name(auth_mod_t *am) { return am ? am->am_scheme->asch_method : ""; } /** Initialize a auth_status_t stucture. * * @retval NULL upon an error * @relates auth_status_t */ auth_status_t *auth_status_init(void *p, isize_t size) { return auth_status_init_with(p, size, 500, auth_internal_server_error); } /** Initialize a auth_status_t stucture. * * @retval NULL upon an error * @relates auth_status_t */ auth_status_t *auth_status_init_with(void *p, isize_t size, int status, char const *phrase) { auth_status_t *as; if (!p || size < (sizeof *as)) return NULL; if (size > INT_MAX) size = INT_MAX; as = memset(p, 0, size); as->as_home->suh_size = (int)size; /* su_home_init(as->as_home); */ as->as_status = status, as->as_phrase = phrase; return as; } /** Allocate a new auth_status_t structure. @relates auth_status_t */ auth_status_t *auth_status_new(su_home_t *home) { auth_status_t *as = su_home_clone(home, (sizeof *as)); if (as) { as->as_status = 500; as->as_phrase = auth_internal_server_error; } return as; } /** Create a new reference to an auth_status_t structure. * @relates auth_status_t */ auth_status_t *auth_status_ref(auth_status_t *as) { return (auth_status_t *)su_home_ref(as->as_home); } /** Destroy (a reference to) an auth_status_t structure. @relates auth_status_t */ void auth_status_unref(auth_status_t *as) { su_home_unref(as->as_home); } /** Authenticate user. * * The function auth_mod_method() invokes scheme-specific authentication * operation where the user's credentials are checked using scheme-specific * method. The authentication result along with an optional challenge header * is stored in the @a as structure. * * @param am pointer to authentication module object [in] * @param as pointer to authentication status structure [in/out] * @param credentials pointer to a header with user's credentials [in] * @param ach pointer to a structure describing challenge [in] * * The @a ach structure defines what kind of response and challenge header * is returned to the user. For example, a server authentication is * implemented with 401 response code and phrase along with WWW-Authenticate * header template in the @a ach structure. * * The auth_mod_method() returns the authentication result in the * #auth_mod_t @a as structure. The @a as->as_status describes the result * as follows: * - as->as_status == 0 authentication is successful * - as->as_status == 100 authentication is pending * - as->as_status >= 400 authentication fails, * return as_status as an error code to client * * When the authentication is left pending, the client must set the * as_callback pointer in @a as structure to an appropriate callback * function. The callback is invoked when the authentication is completed, * either successfully or with an error. * * Note that the authentication module may generate a new challenge each * time authentication is used (e.g., Digest using MD5 algorithm). Such a * challenge header is stored in the @a as->as_response return-value field. * * @note The authentication plugin may use the given reference to @a as, @a * credentials and @a ach structures until the asynchronous authentication * completes. Therefore, they should not be allocated from stack unless * application uses strictly synchronous authentication schemes only (Basic * and Digest). * * @note This function should be called auth_mod_check(). */ void auth_mod_verify(auth_mod_t *am, auth_status_t *as, msg_auth_t *credentials, auth_challenger_t const *ach) { char const *wildcard, *host; if (!am || !as || !ach) return; wildcard = strchr(am->am_realm, '*'); host = as->as_domain; /* Initialize per-request realm */ if (as->as_realm) ; else if (!wildcard) { as->as_realm = am->am_realm; } else if (!host) { return; /* Internal error */ } else if (strcmp(am->am_realm, "*") == 0) { as->as_realm = host; } else { /* Replace * with hostpart */ as->as_realm = su_sprintf(as->as_home, "%.*s%s%s", (int)(wildcard - am->am_realm), am->am_realm, host, wildcard + 1); } am->am_scheme->asch_check(am, as, credentials, ach); } /** Make a challenge header. * * This function invokes plugin-specific member function generating a * challenge header. Client uses the challenge header contents when * prompting the user for a username and password then generates its * credential header using the parameters given in the challenge header. * * @param am pointer to authentication module object * @param as pointer to authentication status structure (return-value) * @param ach pointer to a structure describing challenge * * The auth_mod_challenge() returns the challenge header, appropriate * response code and reason phrase in the #auth_status_t structure. The * auth_mod_challenge() is currently always synchronous function. */ void auth_mod_challenge(auth_mod_t *am, auth_status_t *as, auth_challenger_t const *ach) { if (am && as && ach) am->am_scheme->asch_challenge(am, as, ach); } /** Cancel asynchronous authentication. * * The auth_mod_cancel() function cancels a pending authentication. * Application can reclaim the authentication status, credential and * challenger objects by using auth_mod_cancel(). */ void auth_mod_cancel(auth_mod_t *am, auth_status_t *as) { if (am && as) am->am_scheme->asch_cancel(am, as); } /** Do-nothing cancel function. * * The auth_cancel_default() is the default member function called by * auth_mod_cancel(). */ void auth_cancel_default(auth_mod_t *am, auth_status_t *as) { } /* ====================================================================== */ /* Basic authentication scheme */ static void auth_method_basic_x(auth_mod_t *am, auth_status_t *as, msg_auth_t *au, auth_challenger_t const *ach); auth_scheme_t auth_scheme_basic[1] = {{ "Basic", /* asch_method */ sizeof (auth_mod_t), /* asch_size */ auth_init_default, /* asch_init */ auth_method_basic_x, /* asch_check */ auth_challenge_basic, /* asch_challenge */ auth_cancel_default, /* asch_cancel */ auth_destroy_default /* asch_destroy */ }}; /**Authenticate a request with @b Basic authentication. * * This function reads user database before authentication, if needed. */ static void auth_method_basic_x(auth_mod_t *am, auth_status_t *as, msg_auth_t *au, auth_challenger_t const *ach) { if (am) { auth_readdb_if_needed(am); auth_method_basic(am, as, au, ach); } } /** Authenticate a request with @b Basic authentication scheme. * */ void auth_method_basic(auth_mod_t *am, auth_status_t *as, msg_auth_t *au, auth_challenger_t const *ach) { char *userpass, buffer[128]; size_t n, upsize; char *pass; auth_passwd_t *apw; if (!as->as_realm) return; userpass = buffer, upsize = sizeof buffer; for (au = auth_mod_credentials(au, "Basic", NULL); au; au = auth_mod_credentials(au->au_next, "Basic", NULL)) { if (!au->au_params) continue; n = base64_d(userpass, upsize - 1, au->au_params[0]); if (n >= INT_MAX) continue; if (n >= upsize) { void *b = realloc(userpass == buffer ? NULL : userpass, upsize = n + 1); if (b == NULL) break; base64_d(userpass = b, upsize - 1, au->au_params[0]); } userpass[n] = 0; if (!(pass = strchr(userpass, ':'))) continue; *pass++ = '\0'; SU_DEBUG_5(("auth_method_basic: %s => %s:%s\n", au->au_params[0], userpass, pass)); if (!(apw = auth_mod_getpass(am, userpass, as->as_realm))) continue; if (strcmp(apw->apw_pass, pass)) continue; as->as_user = apw->apw_user; as->as_anonymous = apw == am->am_anon_user; as->as_ident = apw->apw_ident; as->as_match = (msg_header_t *)au; as->as_status = 0; /* Successful authentication! */ break; } if (userpass != buffer) free(userpass); if (au) return; if (auth_allow_check(am, as)) auth_challenge_basic(am, as, ach); } /** Construct a challenge header for @b Basic authentication scheme. */ void auth_challenge_basic(auth_mod_t *am, auth_status_t *as, auth_challenger_t const *ach) { as->as_status = ach->ach_status; as->as_phrase = ach->ach_phrase; as->as_response = msg_header_format(as->as_home, ach->ach_header, "Basic realm=\"%s\"", as->as_realm); } /* ====================================================================== */ /* Digest authentication scheme */ static void auth_method_digest_x(auth_mod_t *am, auth_status_t *as, msg_auth_t *au, auth_challenger_t const *ach); auth_scheme_t auth_scheme_digest[1] = {{ "Digest", /* asch_method */ sizeof (auth_mod_t), /* asch_size */ auth_init_default, /* asch_init */ auth_method_digest_x, /* asch_check */ auth_challenge_digest, /* asch_challenge */ auth_cancel_default, /* asch_cancel */ auth_destroy_default /* asch_destroy */ }}; struct nonce { msg_time_t issued; uint32_t count; uint16_t nextnonce; uint8_t digest[6]; }; #define AUTH_DIGEST_NONCE_LEN (BASE64_MINSIZE(sizeof (struct nonce)) + 1) /** Authenticate a request with @b Digest authentication scheme. * * This function reads user database before authentication, if needed. */ static void auth_method_digest_x(auth_mod_t *am, auth_status_t *as, msg_auth_t *au, auth_challenger_t const *ach) { if (am) { auth_readdb_if_needed(am); auth_method_digest(am, as, au, ach); } } /** Authenticate a request with @b Digest authentication scheme. */ void auth_method_digest(auth_mod_t *am, auth_status_t *as, msg_auth_t *au, auth_challenger_t const *ach) { as->as_allow = as->as_allow || auth_allow_check(am, as) == 0; if (as->as_realm) au = auth_digest_credentials(au, as->as_realm, am->am_opaque); else au = NULL; if (as->as_allow) { SU_DEBUG_5(("%s: allow unauthenticated %s\n", __func__, as->as_method)); as->as_status = 0, as->as_phrase = NULL; as->as_match = (msg_header_t *)au; return; } if (au) { auth_response_t ar[1] = {{ sizeof(ar) }}; auth_digest_response_get(as->as_home, ar, au->au_params); as->as_match = (msg_header_t *)au; auth_check_digest(am, as, ar, ach); } else { /* There was no matching credentials, send challenge */ SU_DEBUG_5(("%s: no credentials matched\n", __func__)); auth_challenge_digest(am, as, ach); } } /** Verify digest authentication */ void auth_check_digest(auth_mod_t *am, auth_status_t *as, auth_response_t *ar, auth_challenger_t const *ach) { char const *a1; auth_hexmd5_t a1buf, response; auth_passwd_t *apw; char const *phrase; msg_time_t now = msg_now(); if (am == NULL || as == NULL || ar == NULL || ach == NULL) { if (as) { as->as_status = 500, as->as_phrase = "Internal Server Error"; as->as_response = NULL; } return; } phrase = "Bad authorization"; #define PA "Authorization missing " if ((!ar->ar_username && (phrase = PA "username")) || (!ar->ar_nonce && (phrase = PA "nonce")) || (!ar->ar_uri && (phrase = PA "URI")) || (!ar->ar_response && (phrase = PA "response")) || /* (!ar->ar_opaque && (phrase = PA "opaque")) || */ /* Check for qop */ (ar->ar_qop && ((ar->ar_auth && !su_casematch(ar->ar_qop, "auth") && !su_casematch(ar->ar_qop, "\"auth\"")) || (ar->ar_auth_int && !su_casematch(ar->ar_qop, "auth-int") && !su_casematch(ar->ar_qop, "\"auth-int\""))) && (phrase = PA "has invalid qop"))) { assert(phrase); SU_DEBUG_5(("auth_method_digest: 400 %s\n", phrase)); as->as_status = 400, as->as_phrase = phrase; as->as_response = NULL; return; } if (as->as_nonce_issued == 0 /* Already validated nonce */ && auth_validate_digest_nonce(am, as, ar, now) < 0) { as->as_blacklist = am->am_blacklist; auth_challenge_digest(am, as, ach); return; } if (as->as_stale) { auth_challenge_digest(am, as, ach); return; } apw = auth_mod_getpass(am, ar->ar_username, ar->ar_realm); if (apw && apw->apw_hash) a1 = apw->apw_hash; else if (apw && apw->apw_pass) auth_digest_a1(ar, a1buf, apw->apw_pass), a1 = a1buf; else auth_digest_a1(ar, a1buf, "xyzzy"), a1 = a1buf, apw = NULL; if (ar->ar_md5sess) auth_digest_a1sess(ar, a1buf, a1), a1 = a1buf; auth_digest_response(ar, response, a1, as->as_method, as->as_body, as->as_bodylen); if (!apw || strcmp(response, ar->ar_response)) { if (am->am_forbidden) { as->as_status = 403, as->as_phrase = "Forbidden"; as->as_response = NULL; as->as_blacklist = am->am_blacklist; } else { auth_challenge_digest(am, as, ach); as->as_blacklist = am->am_blacklist; } SU_DEBUG_5(("auth_method_digest: response did not match\n")); return; } assert(apw); as->as_user = apw->apw_user; as->as_anonymous = apw == am->am_anon_user; as->as_ident = apw->apw_ident; if (am->am_nextnonce || am->am_mutual) auth_info_digest(am, as, ach); if (am->am_challenge) auth_challenge_digest(am, as, ach); SU_DEBUG_7(("auth_method_digest: successful authentication\n")); as->as_status = 0; /* Successful authentication! */ as->as_phrase = ""; } /** Construct a challenge header for @b Digest authentication scheme. */ void auth_challenge_digest(auth_mod_t *am, auth_status_t *as, auth_challenger_t const *ach) { char const *u, *d; char nonce[AUTH_DIGEST_NONCE_LEN]; auth_generate_digest_nonce(am, nonce, sizeof nonce, 0, msg_now()); u = as->as_uri; d = as->as_pdomain; as->as_response = msg_header_format(as->as_home, ach->ach_header, "Digest" " realm=\"%s\"," "%s%s%s" "%s%s%s" " nonce=\"%s\"," "%s%s%s" "%s" /* stale */ " algorithm=%s" "%s%s%s", as->as_realm, u ? " uri=\"" : "", u ? u : "", u ? "\"," : "", d ? " domain=\"" : "", d ? d : "", d ? "\"," : "", nonce, am->am_opaque ? " opaque=\"" : "", am->am_opaque ? am->am_opaque : "", am->am_opaque ? "\"," : "", as->as_stale ? " stale=true," : "", am->am_algorithm, am->am_qop ? ", qop=\"" : "", am->am_qop ? am->am_qop : "", am->am_qop ? "\"" : ""); if (!as->as_response) as->as_status = 500, as->as_phrase = auth_internal_server_error; else as->as_status = ach->ach_status, as->as_phrase = ach->ach_phrase; } /** Construct a info header for @b Digest authentication scheme. */ void auth_info_digest(auth_mod_t *am, auth_status_t *as, auth_challenger_t const *ach) { if (!ach->ach_info) return; if (am->am_nextnonce) { char nonce[AUTH_DIGEST_NONCE_LEN]; auth_generate_digest_nonce(am, nonce, sizeof nonce, 1, msg_now()); as->as_info = msg_header_format(as->as_home, ach->ach_info, "nextnonce=\"%s\"", nonce); } } /* ====================================================================== */ /* Password database */ su_inline void auth_htable_append_local(auth_htable_t *pr, auth_passwd_t *apw); /** Get an passwd entry for user. */ auth_passwd_t *auth_mod_getpass(auth_mod_t *am, char const *user, char const *realm) { auth_passwd_t *apw, **slot; unsigned hash; if (am == NULL || user == NULL) return NULL; hash = msg_hash_string(user); for (slot = auth_htable_hash(am->am_users, hash); (apw = *slot); slot = auth_htable_next(am->am_users, slot)) { if (hash != apw->apw_index) continue; if (strcmp(user, apw->apw_user)) continue; if (realm && apw->apw_realm[0] && strcmp(realm, apw->apw_realm)) continue; break; /* Found it */ } return apw; } /** Add a password entry. */ auth_passwd_t *auth_mod_addpass(auth_mod_t *am, char const *user, char const *realm) { auth_passwd_t *apw, **slot; unsigned index; if (am == NULL || user == NULL) return NULL; index = msg_hash_string(user); for (slot = auth_htable_hash(am->am_users, index); (apw = *slot); slot = auth_htable_next(am->am_users, slot)) { if (index != apw->apw_index) continue; if (strcmp(user, apw->apw_user)) continue; if (realm && strcmp(realm, apw->apw_realm)) continue; break; /* Found it */ } if (realm == NULL) realm = ""; if (!apw) { size_t ulen = strlen(user) + 1, rlen = strlen(realm) + 1; size_t size = sizeof *apw + ulen + rlen; apw = su_alloc(am->am_home, size); if (apw) { memset(apw, 0, sizeof *apw); apw->apw_index = index; apw->apw_user = memcpy((char *)(apw + 1), user, ulen); apw->apw_realm = memcpy((char *)apw->apw_user + ulen, realm, rlen); if (!auth_htable_is_full(am->am_users)) { *slot = apw, am->am_users->aht_used++; } else { if (auth_htable_resize(am->am_home, am->am_users, 0) < 0) su_free(am->am_home, apw), apw = NULL; else auth_htable_append(am->am_users, apw); } } } return apw; } static ssize_t readfile(su_home_t *, FILE *, void **contents, int add_trailing_lf); static int auth_readdb_internal(auth_mod_t *am, int always); /** Read authentication database */ int auth_readdb(auth_mod_t *am) { return auth_readdb_internal(am, 1); } /** Read authentication database only when needed */ int auth_readdb_if_needed(auth_mod_t *am) { struct stat st[1]; if (!am->am_stat || !am->am_db) return 0; if (stat(am->am_db, st) != -1 && st->st_dev == am->am_stat->st_dev && st->st_ino == am->am_stat->st_ino && st->st_size == am->am_stat->st_size && memcmp(&st->st_mtime, &am->am_stat->st_mtime, (sizeof st->st_mtime)) == 0) /* Nothing has changed or passwd file is removed */ return 0; return auth_readdb_internal(am, 0); } #if HAVE_FLOCK #include #endif /* This is just a magic value */ #define auth_apw_local ((void *)(intptr_t)auth_readdb_internal) /** Read authentication database */ static int auth_readdb_internal(auth_mod_t *am, int always) { FILE *f; char *data, *s; ssize_t len; size_t i, n, N; auth_passwd_t *apw; if (!am->am_stat) am->am_stat = su_zalloc(am->am_home, sizeof (*am->am_stat)); f = fopen(am->am_db, "rb"); if (f) { void *buffer = NULL; auth_passwd_t *fresh = NULL; #if HAVE_FLOCK int locked; /* Obtain shared lock on the database file */ if (flock(fileno(f), LOCK_SH | (always ? 0 : LOCK_NB)) == 0) { locked = 1; } else { locked = 0; if (errno == ENOLCK) { ; } else if (errno == EWOULDBLOCK) { SU_DEBUG_3(("auth(%s): user file \"%s\" is busy, trying again later\n", am->am_scheme->asch_method, am->am_db)); fclose(f); return always ? -1 : 0; } else { SU_DEBUG_3(("auth(%s): flock(\"%s\"): %s (%u)\n", am->am_scheme->asch_method, am->am_db, strerror(errno), errno)); fclose(f); return always ? -1 : 0; } } #endif if (am->am_stat) stat(am->am_db, am->am_stat); /* too bad if this fails */ len = readfile(am->am_home, f, &buffer, 1); #if HAVE_FLOCK /* Release shared lock on the database file */ if (locked && flock(fileno(f), LOCK_UN) == -1) { SU_DEBUG_0(("auth(%s): un-flock(\"%s\"): %s (%u)\n", am->am_scheme->asch_method, am->am_db, strerror(errno), errno)); fclose(f); return -1; } #endif fclose(f); if (len == -1) return -1; /* Count number of entries in new buffer */ for (i = am->am_anonymous, s = data = buffer; s < data + len; s += n + strspn(s + n, "\r\n")) { n = strcspn(s, "\r\n"); if (*s != '#' && *s != '\n' && *s != '\r') i++; } N = i, i = 0; if (N > 0) { size_t size = (N * 5 + 3) / 4; if (auth_htable_resize(am->am_home, am->am_users, size) < 0 || !(fresh = su_zalloc(am->am_home, sizeof(*fresh) * N))) { su_free(am->am_home, buffer); return -1; } } if (am->am_anonymous) { assert(i < N); apw = fresh + i++; apw->apw_index = msg_hash_string("anonymous"); apw->apw_user = "anonymous"; apw->apw_pass = ""; apw->apw_realm = ""; am->am_anon_user = apw; if (auth_htable_is_full(am->am_users)) auth_htable_resize(am->am_home, am->am_users, 0); auth_htable_append_local(am->am_users, apw); } apw = NULL; for (data = buffer, s = data; s < data + len && i < N; s += n + strspn(s + n, "\r\n")) { char *user, *pass, *realm, *ident; n = strcspn(s, "\r\n"); if (*s == '#') continue; user = s; s[n++] = '\0'; if (!(pass = strchr(user, ':'))) continue; *pass++ = '\0'; if (!*pass || !*user) continue; if ((realm = strchr(pass, ':'))) *realm++ = '\0'; else realm = ""; if ((ident = strchr(realm, ':'))) *ident++ = '\0'; else ident = ""; apw = fresh + i++; apw->apw_index = msg_hash_string(user); apw->apw_user = user; apw->apw_ident = ident; /* Check for htdigest format */ if (span_hexdigit(realm) == 32 && realm[32] == '\0') { apw->apw_realm = pass; apw->apw_hash = realm; } else { apw->apw_pass = pass; apw->apw_realm = realm; } if (auth_htable_is_full(am->am_users)) auth_htable_resize(am->am_home, am->am_users, 0); auth_htable_append_local(am->am_users, apw); } assert(i <= N); N = i; /* Remove from hash those entries that were read from old passwd file */ for (i = 0; i < am->am_local_count; i++) { if (am->am_locals[i].apw_type == auth_apw_local) auth_htable_remove(am->am_users, &am->am_locals[i]); } if (am->am_locals) su_free(am->am_home, am->am_locals); /* Free old entries */ if (am->am_buffer) su_free(am->am_home, am->am_buffer); /* Free old passwd file contents */ SU_DEBUG_5(("auth(%s): read %u entries from \"%s\"\n", am->am_scheme->asch_method, (unsigned)N, am->am_db)); am->am_locals = fresh; am->am_local_count = N; am->am_buffer = buffer; return 0; } return -1; } /** Append to hash, remove existing local user */ su_inline void auth_htable_append_local(auth_htable_t *aht, auth_passwd_t *apw) { auth_passwd_t **slot; apw->apw_type = auth_apw_local; /* Append to hash */ for (slot = auth_htable_hash(aht, apw->apw_index); *slot; slot = auth_htable_next(aht, slot)) { if (strcmp((*slot)->apw_user, apw->apw_user) == 0) { if ((*slot)->apw_type == auth_apw_local) { (*slot)->apw_type = NULL; assert(aht->aht_used > 0); aht->aht_used--; apw->apw_extended = (*slot)->apw_extended; *slot = NULL; break; } else { /* We insert local before external entry */ auth_passwd_t *swap = apw; apw = *slot; *slot = swap; } } } aht->aht_used++; assert(aht->aht_used <= aht->aht_size); *slot = apw; } static ssize_t readfile(su_home_t *home, FILE *f, void **contents, int add_trailing_lf) { /* Read in whole (binary!) file */ char *buffer = NULL; long size; size_t len; /* Read whole file in */ if (fseek(f, 0, SEEK_END) < 0 || (size = ftell(f)) < 0 || fseek(f, 0, SEEK_SET) < 0 || (long)(len = (size_t)size) != size || size + 2 > SSIZE_MAX) { SU_DEBUG_1(("%s: unable to determine file size (%s)\n", __func__, strerror(errno))); return -1; } if (!(buffer = su_alloc(home, len + 2)) || fread(buffer, 1, len, f) != len) { SU_DEBUG_1(("%s: unable to read file (%s)\n", __func__, strerror(errno))); if (buffer) su_free(home, buffer); return -1; } if (add_trailing_lf) { /* Make sure that the buffer has trailing newline */ if (len == 0 || buffer[len - 1] != '\n') buffer[len++] = '\n'; } buffer[len] = '\0'; *contents = buffer; return len; } /* ====================================================================== */ /* Helper functions */ /** Check if request method is on always-allowed list. * * @return 0 if allowed * @return 1 otherwise */ int auth_allow_check(auth_mod_t *am, auth_status_t *as) { char const *method = as->as_method; int i; if (method && strcmp(method, "ACK") == 0) /* Hack */ return as->as_status = 0; if (!method || !am->am_allow) return 1; if (am->am_allow[0] && strcmp(am->am_allow[0], "*") == 0) return as->as_status = 0; for (i = 0; am->am_allow[i]; i++) if (strcmp(am->am_allow[i], method) == 0) return as->as_status = 0; return 1; } /** Find a credential header with matching scheme and realm. */ msg_auth_t *auth_mod_credentials(msg_auth_t *auth, char const *scheme, char const *realm) { char const *arealm; for (;auth; auth = auth->au_next) { if (!su_casematch(auth->au_scheme, scheme)) continue; if (!realm) return auth; arealm = msg_header_find_param(auth->au_common, "realm="); if (!arealm) continue; if (arealm[0] == '"') { /* Compare quoted arealm with unquoted realm */ int i, j; for (i = 1, j = 0; arealm[i] != 0; i++, j++) { if (arealm[i] == '"' && realm[j] == 0) return auth; if (arealm[i] == '\\' && arealm[i + 1] != '\0') i++; if (arealm[i] != realm[j]) break; } } else { if (strcmp(arealm, realm) == 0) return auth; } } return NULL; } /** Find a Digest credential header with matching realm and opaque. */ msg_auth_t *auth_digest_credentials(msg_auth_t *auth, char const *realm, char const *opaque) { char const *arealm, *aopaque; for (;auth; auth = auth->au_next) { if (!su_casematch(auth->au_scheme, "Digest")) continue; if (realm) { int cmp = 1; arealm = msg_header_find_param(auth->au_common, "realm="); if (!arealm) continue; if (arealm[0] == '"') { /* Compare quoted arealm with unquoted realm */ int i, j; for (i = 1, j = 0, cmp = 1; arealm[i] != 0; i++, j++) { if (arealm[i] == '"' && realm[j] == 0) { cmp = 0; break; } if (arealm[i] == '\\' && arealm[i + 1] != '\0') i++; if (arealm[i] != realm[j]) break; } } else { cmp = strcmp(arealm, realm); } if (cmp) continue; } if (opaque) { int cmp = 1; aopaque = msg_header_find_param(auth->au_common, "opaque="); if (!aopaque) continue; if (aopaque[0] == '"') { /* Compare quoted aopaque with unquoted opaque */ int i, j; for (i = 1, j = 0, cmp = 1; aopaque[i] != 0; i++, j++) { if (aopaque[i] == '"' && opaque[j] == 0) { cmp = 0; break; } if (aopaque[i] == '\\' && aopaque[i + 1] != '\0') i++; if (aopaque[i] != opaque[j]) break; } } else { cmp = strcmp(aopaque, opaque); } if (cmp) continue; } return auth; } return NULL; } /** Generate nonce parameter. * * @param am pointer to authentication module object * @param buffer string buffer for nonce [OUT] * @param bsize size of buffer [IN] * @param nextnonce true if this is a "nextnonce" [IN] * @param now current time [IN] */ isize_t auth_generate_digest_nonce(auth_mod_t *am, char buffer[], size_t bsize, int nextnonce, msg_time_t now) { struct nonce nonce[1] = {{ 0 }}; su_md5_t md5[1]; am->am_count += 3730029547U; /* 3730029547 is a prime */ nonce->issued = now; nonce->count = am->am_count; nonce->nextnonce = nextnonce != 0; /* Calculate HMAC of nonce data */ auth_md5_hmac_init(am, md5); su_md5_update(md5, nonce, offsetof(struct nonce, digest)); auth_md5_hmac_digest(am, md5, nonce->digest, sizeof nonce->digest); return base64_e(buffer, bsize, nonce, sizeof(nonce)); } /** Validate nonce parameter. * * @param am pointer to authentication module object * @param as authentication status structure [OUT] * @param ar decoded authentication response from client [IN] * @param now current time [IN] */ int auth_validate_digest_nonce(auth_mod_t *am, auth_status_t *as, auth_response_t *ar, msg_time_t now) { struct nonce nonce[1] = {{ 0 }}; su_md5_t md5[1]; uint8_t hmac[sizeof nonce->digest]; unsigned expires; /* Check nonce */ if (!ar->ar_nonce) { SU_DEBUG_5(("auth_method_digest: no nonce\n")); return -1; } if (base64_d((void*)nonce, (sizeof nonce), ar->ar_nonce) != (sizeof nonce)) { SU_DEBUG_5(("auth_method_digest: too short nonce\n")); return -1; } /* Calculate HMAC over decoded nonce data */ auth_md5_hmac_init(am, md5); su_md5_update(md5, nonce, offsetof(struct nonce, digest)); auth_md5_hmac_digest(am, md5, hmac, sizeof hmac); if (memcmp(nonce->digest, hmac, sizeof nonce->digest)) { SU_DEBUG_5(("auth_method_digest: bad nonce\n")); return -1; } as->as_nonce_issued = nonce->issued; as->as_nextnonce = nonce->nextnonce != 0; expires = nonce->nextnonce ? am->am_next_exp : am->am_expires; if (nonce->issued > now || (expires && nonce->issued + expires < now)) { SU_DEBUG_5(("auth_method_digest: nonce expired %lu seconds ago " "(lifetime %u)\n", now - (nonce->issued + expires), expires)); as->as_stale = 1; } if (am->am_max_ncount && ar->ar_nc) { unsigned long nc = strtoul(ar->ar_nc, NULL, 10); if (nc == 0 || nc > am->am_max_ncount) { SU_DEBUG_5(("auth_method_digest: nonce used %s times, max %u\n", ar->ar_nc, am->am_max_ncount)); as->as_stale = 1; } } /* We should also check cnonce, nc... */ return 0; } /* ====================================================================== */ /* HMAC routines */ static void auth_md5_hmac_key(auth_mod_t *am) { size_t i; uint8_t ipad[SU_MD5_DIGEST_SIZE]; uint8_t opad[SU_MD5_DIGEST_SIZE]; assert(SU_MD5_DIGEST_SIZE == sizeof am->am_master_key); /* Derive HMAC ipad and opad from master key */ for (i = 0; i < sizeof am->am_master_key; i++) { ipad[i] = am->am_master_key[i] ^ 0x36; opad[i] = am->am_master_key[i] ^ 0x5C; } /* Pre-calculate sum of ipad */ su_md5_init(&am->am_hmac_ipad); su_md5_update(&am->am_hmac_ipad, ipad, sizeof ipad); /* Pre-calculate sum of opad */ su_md5_init(&am->am_hmac_opad); su_md5_update(&am->am_hmac_opad, opad, sizeof opad); } void auth_md5_hmac_init(auth_mod_t *am, struct su_md5_t *imd5) { *imd5 = am->am_hmac_ipad; } void auth_md5_hmac_digest(auth_mod_t *am, struct su_md5_t *imd5, void *hmac, size_t size) { uint8_t digest[SU_MD5_DIGEST_SIZE]; su_md5_t omd5[1]; /* inner sum */ su_md5_digest(imd5, digest); *omd5 = am->am_hmac_opad; su_md5_update(omd5, digest, sizeof *digest); /* outer sum */ if (size == sizeof digest) { su_md5_digest(omd5, hmac); } else { su_md5_digest(omd5, digest); if (size > sizeof digest) { memset((char *)hmac + (sizeof digest), 0, size - sizeof digest); size = sizeof digest; } memcpy(hmac, digest, size); } } /* ====================================================================== */ /* Compatibility interface */ void auth_mod_method(auth_mod_t *am, auth_status_t *as, msg_auth_t *credentials, auth_challenger_t const *ach) { auth_mod_verify(am, as, credentials, ach); } void auth_mod_check_client(auth_mod_t *am, auth_status_t *as, msg_auth_t *credentials, auth_challenger_t const *ach) { auth_mod_verify(am, as, credentials, ach); } void auth_mod_challenge_client(auth_mod_t *am, auth_status_t *as, auth_challenger_t const *ach) { auth_mod_challenge(am, as, ach); } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/auth_module_http.c000066400000000000000000000045771223300710500245670ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@internal * @file auth_module_http.c * @brief Authenticate HTTP request * * @author Pekka Pessi * @author Jari Urpalainen * * @date Created: Thu Jan 15 17:23:21 2004 ppessi */ #include "config.h" #include #include #include #include #include #include static auth_challenger_t http_server_challenger[] = {{ HTTP_401_UNAUTHORIZED, http_www_authenticate_class }}; static auth_challenger_t http_proxy_challenger[] = {{ HTTP_407_PROXY_AUTH, http_proxy_authenticate_class }}; const char *auth_mod_check_http(auth_mod_t *am, auth_status_t *as, http_t const *http, auth_kind_t proxy) { msg_auth_t *credentials = proxy ? http->http_proxy_authorization : http->http_authorization; auth_challenger_t const *challenger = proxy ? http_proxy_challenger : http_server_challenger; if (http->http_request) { if (!as->as_method) as->as_method = http->http_request->rq_method_name; #if 0 if (!as->as_uri) as->as_uri = http->http_request->rq_url; #endif } if (http->http_payload && !as->as_body) as->as_body = http->http_payload->pl_data, as->as_bodylen = http->http_payload->pl_len; /* Call real authentication method */ auth_mod_check_client(am, as, credentials, challenger); if (as->as_status) return NULL; else return as->as_user; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/auth_module_sip.c000066400000000000000000000051741223300710500243750ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@internal * @file auth_module_sip.c * @brief Authenticate SIP request * * @author Pekka Pessi * @author Jari Urpalainen * * @date Created: Thu Jan 15 17:23:21 2004 ppessi */ #include "config.h" #include #include #include #include #include #include #include static auth_challenger_t sip_server_challenger[] = {{ SIP_401_UNAUTHORIZED, sip_www_authenticate_class, sip_authentication_info_class }}; static auth_challenger_t sip_proxy_challenger[] = {{ SIP_407_PROXY_AUTH_REQUIRED, sip_proxy_authenticate_class }}; /** Authenticate an incoming SIP request. * * The function auth_mod_check() completes the @a as structure and calls the * scheme-specific authentication method performing the actual * authentication. * * A successful authentication is indicated by setting @a as->as_status to * 0. The authentication module sets @a as->as_match as the matching * credential header. */ void auth_mod_check(auth_mod_t *am, auth_status_t *as, sip_t const *sip, auth_kind_t proxy) { msg_auth_t *credentials; auth_challenger_t const *challenger; if (as == NULL || sip == NULL) return; if (am == NULL) { as->as_status = 0; return; } credentials = proxy ? sip->sip_proxy_authorization : sip->sip_authorization; challenger = proxy ? sip_proxy_challenger : sip_server_challenger; if (sip->sip_request) as->as_method = sip->sip_request->rq_method_name; if (sip->sip_payload) as->as_body = sip->sip_payload->pl_data, as->as_bodylen = sip->sip_payload->pl_len; auth_mod_method(am, as, credentials, challenger); } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/auth_ntlm.c000066400000000000000000000201511223300710500231770ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE auth_ntlm.c * * Implementation for digest authentication. * * @author Pekka Pessi * * @date Created: Thu Feb 22 12:10:37 2001 ppessi */ #include "config.h" #include #include #include #include #include "sofia-sip/auth_digest.h" #include "sofia-sip/auth_ntlm.h" #include "iptsec_debug.h" su_inline int has_token(char const *qstring, char const *token); /**Get ntlm-challenge parameters. * * The function ntlm_challenge_get() searches for the ntlm authentication * parameters in @a params. The parameters are assigned to the appropriate * fields in @a ac structure. * * @return * * The function ntlm_challenge_get() returns number of parameters * found, or -1 upon an error. */ issize_t auth_ntlm_challenge_get(su_home_t *home, auth_challenge_t *ac0, char const * const params[]) { ssize_t n; auth_challenge_t ac[1] = {{ 0 }}; char const *md5 = NULL, *md5sess = NULL, *sha1 = NULL, *qop_auth = NULL, *qop_auth_int = NULL; ac->ac_size = sizeof(ac); assert(ac0); assert(ac0->ac_size >= sizeof(*ac)); if (ac0 == NULL || params == NULL) return -1; n = auth_get_params(home, params, "realm=", &ac->ac_realm, "domain=", &ac->ac_domain, "nonce=", &ac->ac_nonce, "opaque=", &ac->ac_opaque, "stale=", &ac->ac_stale, "algorithm=", &ac->ac_algorithm, "qop=", &ac->ac_qop, "algorithm=md5", &md5, "algorithm=md5-sess", &md5sess, "algorithm=sha1", &sha1, "qop=auth", &qop_auth, "qop=auth-int", &qop_auth_int, NULL); if (n < 0) return n; if (ac->ac_stale && !su_casematch(ac->ac_stale, "true")) ac->ac_stale = NULL; ac->ac_md5 = md5 != NULL || ac->ac_algorithm == NULL; ac->ac_md5sess = md5sess != NULL; ac->ac_sha1 = sha1 != NULL; ac->ac_auth = qop_auth != NULL; ac->ac_auth_int = qop_auth_int != NULL; auth_struct_copy(ac0, ac, sizeof(ac)); SU_DEBUG_5(("%s(): got %d\n", "auth_ntlm_challenge_get", n)); return n; } /**Get ntlm-response parameters. * * The function auth_response_get() searches for the ntlm authentication * parameters in @a params. The parameters are assigned to the appropriate * fields in @a ar structure. * * @return * * The function auth_response_get() returns number of parameters * found, or -1 upon an error. */ issize_t auth_ntlm_response_get(su_home_t *home, auth_response_t *ar0, char const *const params[]) { ssize_t n; auth_response_t ar[1] = {{ 0 }}; char const *md5 = NULL, *md5sess = NULL, *sha1 = NULL, *qop_auth = NULL, *qop_auth_int = NULL; ar->ar_size = sizeof(ar); assert(ar0); assert(params); assert(ar0->ar_size >= sizeof(ar)); if (ar0 == NULL || params == NULL) return -1; n = auth_get_params(home, params, "username=", &ar->ar_username, "realm=", &ar->ar_realm, "nonce=", &ar->ar_nonce, "uri=", &ar->ar_uri, "response=", &ar->ar_response, "algorithm=", &ar->ar_algorithm, "opaque=", &ar->ar_opaque, "cnonce=", &ar->ar_cnonce, "qop=", &ar->ar_qop, "nc=", &ar->ar_nc, "algorithm=md5", &md5, "algorithm=md5-sess", &md5sess, "algorithm=sha1", &sha1, "qop=auth", &qop_auth, "qop=auth-int", &qop_auth_int, NULL); if (n < 0) return n; ar->ar_md5 = md5 != NULL || ar->ar_algorithm == NULL; ar->ar_md5sess = md5sess != NULL; ar->ar_sha1 = sha1 != NULL; ar->ar_auth = qop_auth != NULL; ar->ar_auth_int = qop_auth_int != NULL; auth_struct_copy(ar0, ar, sizeof(ar)); SU_DEBUG_7(("%s: %d\n", "auth_ntlm_response_get", n)); return n; } #if 0 /** Generate A1 hash for digest authentication. */ int auth_digest_a1(auth_response_t *ar, auth_hexmd5_t ha1, char const *secret) { su_md5_t md5[1]; /* Calculate A1 */ su_md5_init(md5); su_md5_strupdate(md5, ar->ar_username); su_md5_update(md5, ":", 1); unquote_update(md5, ar->ar_realm); su_md5_update(md5, ":", 1); su_md5_strupdate(md5, secret); su_md5_hexdigest(md5, ha1); SU_DEBUG_5(("auth_digest_a1() has A1 = MD5(%s:%s:%s) = %s\n", ar->ar_username, ar->ar_realm, secret, ha1)); return 0; } int auth_digest_a1sess(auth_response_t *ar, auth_hexmd5_t ha1sess, char const *ha1) { su_md5_t md5[1]; su_md5_init(md5); su_md5_strupdate(md5, ha1); su_md5_update(md5, ":", 1); unquote_update(md5, ar->ar_nonce); su_md5_update(md5, ":", 1); unquote_update(md5, ar->ar_cnonce); su_md5_hexdigest(md5, ha1sess); SU_DEBUG_5(("auth_sessionkey has A1' = MD5(%s:%s:%s) = %s\n", ha1, ar->ar_nonce, ar->ar_cnonce, ha1sess)); return 0; } /** Generate MD5 session key for digest authentication. */ int auth_digest_sessionkey(auth_response_t *ar, auth_hexmd5_t ha1, char const *secret) { if (ar->ar_md5sess) ar->ar_algorithm = "MD5-sess"; else if (ar->ar_md5) ar->ar_algorithm = "MD5"; else return -1; if (ar->ar_md5sess) { auth_hexmd5_t base_ha1; auth_digest_a1(ar, base_ha1, secret); auth_digest_a1sess(ar, ha1, base_ha1); } else { auth_digest_a1(ar, ha1, secret); } return 0; } #endif /* 0 */ #if 0 /** Generate response for digest authentication. * */ int auth_digest_response(auth_response_t *ar, auth_hexmd5_t response, auth_hexmd5_t const ha1, char const *method_name, void const *data, issize_t dlen) { su_md5_t md5[1]; auth_hexmd5_t Hentity, HA2; if (ar->ar_auth_int) ar->ar_qop = "auth-int"; else if (ar->ar_auth) ar->ar_qop = "auth"; else ar->ar_qop = NULL; /* Calculate Hentity */ if (ar->ar_auth_int) { if (data && dlen) { su_md5_init(md5); su_md5_update(md5, data, dlen); su_md5_hexdigest(md5, Hentity); } else { strcpy(Hentity, "d41d8cd98f00b204e9800998ecf8427e"); } } /* Calculate A2 */ su_md5_init(md5); su_md5_strupdate(md5, method_name); su_md5_update(md5, ":", 1); unquote_update(md5, ar->ar_uri); if (ar->ar_auth_int) { su_md5_update(md5, ":", 1); su_md5_update(md5, Hentity, sizeof(Hentity) - 1); } su_md5_hexdigest(md5, HA2); SU_DEBUG_5(("A2 = MD5(%s:%s%s%s)\n", method_name, ar->ar_uri, ar->ar_auth_int ? ":" : "", ar->ar_auth_int ? Hentity : "")); /* Calculate response */ su_md5_init(md5); su_md5_update(md5, ha1, 32); su_md5_update(md5, ":", 1); unquote_update(md5, ar->ar_nonce); if (ar->ar_auth || ar->ar_auth_int) { su_md5_update(md5, ":", 1); su_md5_strupdate(md5, ar->ar_nc); su_md5_update(md5, ":", 1); unquote_update(md5, ar->ar_cnonce); su_md5_update(md5, ":", 1); su_md5_strupdate(md5, ar->ar_qop); } su_md5_update(md5, ":", 1); su_md5_update(md5, HA2, 32); su_md5_hexdigest(md5, response); SU_DEBUG_5(("auth_response: %s = MD5(%s:%s%s%s%s%s%s%s:%s) (qop=%s)\n", response, ha1, ar->ar_nonce, ar->ar_auth || ar->ar_auth_int ? ":" : "", ar->ar_auth || ar->ar_auth_int ? ar->ar_nc : "", ar->ar_auth || ar->ar_auth_int ? ":" : "", ar->ar_auth || ar->ar_auth_int ? ar->ar_cnonce : "", ar->ar_auth || ar->ar_auth_int ? ":" : "", ar->ar_auth || ar->ar_auth_int ? ar->ar_qop : "", HA2, ar->ar_qop ? ar->ar_qop : "NONE")); return 0; } #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/auth_plugin.c000066400000000000000000000071411223300710500235270ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@internal * @file auth_plugin.c * @brief Plugin interface for authentication verification modules. * * @author Pekka Pessi * * @date Created: Tue Apr 27 15:23:31 2004 ppessi */ #include "config.h" #include #include #include #include #include #include #if HAVE_FUNC #elif HAVE_FUNCTION #define __func__ __FUNCTION__ #else static char const __func__[] = "auth_plugin"; #endif #include #include #include #include #include #include "sofia-sip/auth_module.h" #include "sofia-sip/auth_plugin.h" extern auth_scheme_t auth_scheme_basic[]; extern auth_scheme_t auth_scheme_digest[]; extern auth_scheme_t auth_scheme_delayed[]; enum { N = 32 }; static auth_scheme_t *schemes[N] = { auth_scheme_basic, auth_scheme_digest, auth_scheme_delayed }; /** Register an authentication plugin. * * @retval 0 when successful * @retval -1 upon an error */ int auth_mod_register_plugin(auth_scheme_t *asch) { int i; for (i = 0; schemes[i]; i++) { if (i == N) return -1; } schemes[i] = asch; return 0; } /**Create an authentication plugin module. * * The function auth_mod_create() creates a module used to authenticate the * requests. * * @param root pointer to a su_root_t object * @param tag,value,... tagged argument list * * @TAGS * AUTHTAG_METHOD(), AUTHTAG_REALM(), AUTHTAG_DB(), AUTHTAG_ALLOW(), * AUTHTAG_QOP(), AUTHTAG_ALGORITHM(), AUTHTAG_EXPIRES(), * AUTHTAG_BLACKLIST(), AUTHTAG_FORBIDDEN(), AUTHTAG_ANONYMOUS(), * AUTHTAG_REMOTE(). */ auth_mod_t *auth_mod_create(su_root_t *root, tag_type_t tag, tag_value_t value, ...) { auth_mod_t *am = NULL; ta_list ta; char const *method = NULL; ta_start(ta, tag, value); tl_gets(ta_args(ta), AUTHTAG_METHOD_REF(method), TAG_NULL()); if (method) { auth_scheme_t *bscheme = NULL; char const *base; size_t len; base = strrchr(method, '+'); if (base) len = base++ - method; else len = strlen(method); if (base == NULL) ; else if (su_casematch(base, "Basic")) bscheme = auth_scheme_basic; else if (su_casematch(base, "Digest")) bscheme = auth_scheme_digest; if (base == NULL || bscheme) { int i; for (i = 0; schemes[i] && i < N; i++) { if (su_casenmatch(schemes[i]->asch_method, method, len) && schemes[i]->asch_method[len] == 0) { am = auth_mod_alloc(schemes[i], ta_tags(ta)); if (schemes[i]->asch_init(am, bscheme, root, ta_tags(ta)) == -1) { auth_mod_destroy(am), am = NULL; } break; } } } } ta_end(ta); return am; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/auth_plugin_delayed.c000066400000000000000000000131441223300710500252160ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE auth_plugin_delayed.c * * @brief Plugin for delayed authentication. * * This authentication plugin provides authentication operation that is * intentionally delayed. It serves as an example of server-side * authentication plugins. * * @author Pekka Pessi . * * @date Created: Wed Apr 11 15:14:03 2001 ppessi */ #include "config.h" #include #include #include #include #include #define SU_MSG_ARG_T struct auth_splugin_t #if HAVE_FUNC #elif HAVE_FUNCTION #define __func__ __FUNCTION__ #else static char const __func__[] = "auth_plugin_delayed"; #endif #include #include #include #include #include "sofia-sip/auth_module.h" #include "sofia-sip/auth_plugin.h" struct auth_plugin_t { su_root_t *ap_root; auth_scheme_t *ap_base; auth_splugin_t *ap_list; auth_splugin_t**ap_tail; }; /* Digest (or Basic) with delay */ static int delayed_auth_init(auth_mod_t *am, auth_scheme_t *base, su_root_t *root, tag_type_t tag, tag_value_t value, ...); static void delayed_auth_method(auth_mod_t *am, auth_status_t *as, msg_auth_t *auth, auth_challenger_t const *ach); static void delayed_auth_challenge(auth_mod_t *am, auth_status_t *as, auth_challenger_t const *ach); static void delayed_auth_cancel(auth_mod_t *am, auth_status_t *as); static void delayed_auth_destroy(auth_mod_t *am); auth_scheme_t auth_scheme_delayed[1] = {{ "Delayed", sizeof (struct { auth_mod_t mod[1]; auth_plugin_t plug[1]; }), delayed_auth_init, delayed_auth_method, delayed_auth_challenge, delayed_auth_cancel, delayed_auth_destroy }}; static int delayed_auth_init(auth_mod_t *am, auth_scheme_t *base, su_root_t *root, tag_type_t tag, tag_value_t value, ...) { auth_plugin_t *ap = AUTH_PLUGIN(am); int retval = -1; ta_list ta; ta_start(ta, tag, value); if (root && base && auth_init_default(am, base, root, ta_tags(ta)) != -1) { ap->ap_root = root; ap->ap_base = base; ap->ap_tail = &ap->ap_list; retval = 0; } ta_end(ta); return retval; } struct auth_splugin_t { void const *asp_cookie; auth_splugin_t *asp_next; auth_splugin_t **asp_prev; auth_mod_t *asp_am; auth_status_t *asp_as; msg_auth_t *asp_header; auth_challenger_t const *asp_ach; int asp_canceled; }; /* This is unique identifier */ #define delayed_asp_cookie ((void const *)(intptr_t)delayed_auth_cancel) static void delayed_auth_method_recv(su_root_magic_t *rm, su_msg_r msg, auth_splugin_t *u); static void delayed_auth_method(auth_mod_t *am, auth_status_t *as, msg_auth_t *auth, auth_challenger_t const *ach) { auth_plugin_t *ap = AUTH_PLUGIN(am); su_msg_r mamc = SU_MSG_R_INIT; auth_splugin_t *asp; if (su_msg_create(mamc, su_root_task(ap->ap_root), su_root_task(ap->ap_root), delayed_auth_method_recv, sizeof *asp) == SU_FAILURE) { as->as_status = 500; as->as_phrase = "Asynchronous authentication failure"; return; } asp = su_msg_data(mamc); assert(asp); asp->asp_cookie = delayed_asp_cookie; asp->asp_am = am; asp->asp_as = as; asp->asp_header = auth; asp->asp_ach = ach; asp->asp_canceled = 0; if (su_msg_send(mamc) == SU_FAILURE) { su_msg_destroy(mamc); as->as_status = 500; as->as_phrase = "Asynchronous authentication failure"; return; } as->as_plugin = asp; as->as_status = 100; as->as_phrase = "Trying"; return; } static void delayed_auth_method_recv(su_root_magic_t *rm, su_msg_r msg, auth_splugin_t *asp) { auth_mod_t *am = asp->asp_am; auth_plugin_t *ap = AUTH_PLUGIN(am); if (asp->asp_canceled) return; ap->ap_base->asch_check(am, asp->asp_as, asp->asp_header, asp->asp_ach); if (asp->asp_as->as_callback) asp->asp_as->as_callback(asp->asp_as->as_magic, asp->asp_as); } static void delayed_auth_challenge(auth_mod_t *am, auth_status_t *as, auth_challenger_t const *ach) { auth_plugin_t *ap = AUTH_PLUGIN(am); /* Invoke member function of base scheme */ ap->ap_base->asch_challenge(am, as, ach); } static void delayed_auth_cancel(auth_mod_t *am, auth_status_t *as) { auth_plugin_t *ap = AUTH_PLUGIN(am); (void)ap; /* xyzzy */ if (as->as_plugin && as->as_plugin->asp_cookie == delayed_asp_cookie) as->as_plugin->asp_canceled = 1; as->as_status = 500, as->as_phrase = "Authentication canceled"; } static void delayed_auth_destroy(auth_mod_t *am) { auth_plugin_t *ap = AUTH_PLUGIN(am); /* Invoke member function of base scheme */ ap->ap_base->asch_destroy(am); } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/auth_plugin_ntlm.c000066400000000000000000000241711223300710500245630ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE auth_plugin_ntlm.c * * @brief Plugin for delayed authentication. * * This authentication plugin provides authentication operation that is * intentionally delayed. It serves as an example of server-side * authentication plugins. * * @author Pekka Pessi . * * @date Created: Wed Apr 11 15:14:03 2001 ppessi */ #include "config.h" #include #include #include #include #include #include #include #include #include #include "sofia-sip/auth_module.h" #include "sofia-sip/auth_plugin.h" #include "sofia-sip/auth_ntlm.h" #if HAVE_FUNC #elif HAVE_FUNCTION #define __func__ __FUNCTION__ #else static char const __func__[] = "auth_plugin_ntml"; #endif /* ====================================================================== */ /* NTLM authentication scheme */ static int auth_init_ntlm(auth_mod_t *am, auth_scheme_t *base, su_root_t *root, tag_type_t tag, tag_value_t value, ...); static void auth_method_ntlm_x(auth_mod_t *am, auth_status_t *as, msg_auth_t *au, auth_challenger_t const *ach); auth_scheme_t auth_scheme_ntlm[1] = {{ "NTLM", /* asch_method */ sizeof (auth_mod_t), /* asch_size */ auth_init_default, /* asch_init */ auth_method_ntlm_x, /* asch_check */ auth_challenge_ntlm, /* asch_challenge */ auth_cancel_default, /* asch_cancel */ auth_destroy_default /* asch_destroy */ }}; #define AUTH_NTLM_NONCE_LEN (BASE64_SIZE(sizeof (struct nonce)) + 1) static int auth_init_ntlm(auth_mod_t *am, auth_scheme_t *base, su_root_t *root, tag_type_t tag, tag_value_t value, ...) { auth_plugin_t *ap = AUTH_PLUGIN(am); int retval = -1; ta_list ta; ta_start(ta, tag, value); if (auth_init_default(am, NULL, root, ta_tags(ta)) != -1) { retval = 0; } ta_end(ta); return retval; } /** Authenticate a request with @b NTLM authentication scheme. * * This function reads user database before authentication, if needed. */ static void auth_method_ntlm_x(auth_mod_t *am, auth_status_t *as, msg_auth_t *au, auth_challenger_t const *ach) { if (am) { auth_readdb_if_needed(am); auth_method_ntlm(am, as, au, ach); } } /** Authenticate a request with @b Ntlm authentication scheme. */ void auth_method_ntlm(auth_mod_t *am, auth_status_t *as, msg_auth_t *au, auth_challenger_t const *ach) { as->as_allow = as->as_allow || auth_allow_check(am, as) == 0; if (as->as_realm) au = auth_ntlm_credentials(au, as->as_realm, am->am_opaque, am->am_gssapi_data, am->am_targetname); else au = NULL; if (as->as_allow) { SU_DEBUG_5(("%s: allow unauthenticated %s\n", __func__, as->as_method)); as->as_status = 0, as->as_phrase = NULL; as->as_match = (msg_header_t *)au; return; } if (au) { auth_response_t ar[1] = {{ sizeof(ar) }}; auth_ntlm_response_get(as->as_home, ar, au->au_params); as->as_match = (msg_header_t *)au; auth_check_ntlm(am, as, ar, ach); } else { /* There was no matching credentials, send challenge */ SU_DEBUG_5(("%s: no credentials matched\n", __func__)); auth_challenge_ntlm(am, as, ach); } } /** Find a NTLM credential header with matching realm and opaque. */ msg_auth_t *auth_ntlm_credentials(msg_auth_t *auth, char const *realm, char const *opaque, char const *gssapidata, char const *targetname) { char const *agssapidata, *atargetname; for (;auth; auth = auth_mod_credentials(auth->au_next)) { if (!su_casematch(auth->au_scheme, "NTLM")) continue; if (gssapidata) { agssapidata = msg_header_find_param(auth->au_common, "gssapi-data="); if (!agssapidata || auth_strcmp(agssapidata, gssapidata)) continue; } if (targetname) { atargetname = msg_header_find_param(auth->au_common, "targetname="); if (!atargetname || auth_strcmp(atargetname, targetname)) continue; } return auth; } return NULL; } /** Check ntlm authentication */ void auth_check_ntlm(auth_mod_t *am, auth_status_t *as, auth_response_t *ar, auth_challenger_t const *ach) { char const *a1; auth_hexmd5_t a1buf, response; auth_passwd_t *apw; char const *phrase; msg_time_t now = msg_now(); if (am == NULL || as == NULL || ar == NULL || ach == NULL) { if (as) { as->as_status = 500, as->as_phrase = "Internal Server Error"; as->as_response = NULL; } return; } phrase = "Bad authorization"; #define PA "Authorization missing " if ((!ar->ar_username && (phrase = PA "username")) || (!ar->ar_nonce && (phrase = PA "nonce")) || (!ar->ar_uri && (phrase = PA "URI")) || (!ar->ar_response && (phrase = PA "response")) || /* (!ar->ar_opaque && (phrase = PA "opaque")) || */ /* Check for qop */ (ar->ar_qop && ((ar->ar_auth && !su_casematch(ar->ar_qop, "auth") && !su_casematch(ar->ar_qop, "\"auth\"")) || (ar->ar_auth_int && !su_casematch(ar->ar_qop, "auth-int") && !su_casematch(ar->ar_qop, "\"auth-int\""))) && (phrase = PA "has invalid qop"))) { assert(phrase); SU_DEBUG_5(("auth_method_ntlm: 400 %s\n", phrase)); as->as_status = 400, as->as_phrase = phrase; as->as_response = NULL; return; } /* XXX - replace */ #if 0 if (as->as_nonce_issued == 0 /* Already validated nonce */ && auth_validate_ntlm_nonce(am, as, ar, now) < 0) { #else if (as->as_nonce_issued == 0 /* Already validated nonce */ && auth_validate_digest_nonce(am, as, ar, now) < 0) { #endif as->as_blacklist = am->am_blacklist; auth_challenge_ntlm(am, as, ach); return; } if (as->as_stale) { auth_challenge_ntlm(am, as, ach); return; } apw = auth_mod_getpass(am, ar->ar_username, ar->ar_realm); #if 0 if (apw && apw->apw_hash) a1 = apw->apw_hash; else if (apw && apw->apw_pass) auth_ntlm_a1(ar, a1buf, apw->apw_pass), a1 = a1buf; else auth_ntlm_a1(ar, a1buf, "xyzzy"), a1 = a1buf, apw = NULL; if (ar->ar_md5sess) auth_ntlm_a1sess(ar, a1buf, a1), a1 = a1buf; #else if (apw && apw->apw_hash) a1 = apw->apw_hash; else if (apw && apw->apw_pass) auth_digest_a1(ar, a1buf, apw->apw_pass), a1 = a1buf; else auth_digest_a1(ar, a1buf, "xyzzy"), a1 = a1buf, apw = NULL; if (ar->ar_md5sess) auth_digest_a1sess(ar, a1buf, a1), a1 = a1buf; #endif /* XXX - replace with auth_ntlm_response */ #if 0 auth_ntlm_response(ar, response, a1, as->as_method, as->as_body, as->as_bodylen); #else auth_digest_response(ar, response, a1, as->as_method, as->as_body, as->as_bodylen); #endif if (!apw || strcmp(response, ar->ar_response)) { if (am->am_forbidden) { as->as_status = 403, as->as_phrase = "Forbidden"; as->as_blacklist = am->am_blacklist; as->as_response = NULL; } else { auth_challenge_ntlm(am, as, ach); as->as_blacklist = am->am_blacklist; } SU_DEBUG_5(("auth_method_ntlm: response did not match\n")); return; } assert(apw); as->as_user = apw->apw_user; as->as_anonymous = apw == am->am_anon_user; if (am->am_nextnonce || am->am_mutual) auth_info_ntlm(am, as, ach); if (am->am_challenge) auth_challenge_ntlm(am, as, ach); SU_DEBUG_7(("auth_method_ntlm: successful authentication\n")); as->as_status = 0; /* Successful authentication! */ as->as_phrase = ""; } /** Construct a challenge header for @b Ntlm authentication scheme. */ void auth_challenge_ntlm(auth_mod_t *am, auth_status_t *as, auth_challenger_t const *ach) { char const *u, *d; char nonce[AUTH_NTLM_NONCE_LEN]; #if 0 auth_generate_ntlm_nonce(am, nonce, sizeof nonce, 0, msg_now()); #else auth_generate_digest_nonce(am, nonce, sizeof nonce, 0, msg_now()); #endif u = as->as_uri; d = as->as_pdomain; as->as_response = msg_header_format(as->as_home, ach->ach_header, "Ntlm" " realm=\"%s\"," "%s%s%s" "%s%s%s" " nonce=\"%s\"," "%s%s%s" "%s" /* stale */ " algorithm=%s" "%s%s%s", as->as_realm, u ? " uri=\"" : "", u ? u : "", u ? "\"," : "", d ? " domain=\"" : "", d ? d : "", d ? "\"," : "", nonce, am->am_opaque ? " opaque=\"" : "", am->am_opaque ? am->am_opaque : "", am->am_opaque ? "\"," : "", as->as_stale ? " stale=true," : "", am->am_algorithm, am->am_qop ? ", qop=\"" : "", am->am_qop ? am->am_qop : "", am->am_qop ? "\"" : ""); if (!as->as_response) as->as_status = 500, as->as_phrase = auth_internal_server_error; else as->as_status = ach->ach_status, as->as_phrase = ach->ach_phrase; } /** Construct a info header for @b Ntlm authentication scheme. */ void auth_info_ntlm(auth_mod_t *am, auth_status_t *as, auth_challenger_t const *ach) { if (!ach->ach_info) return; if (am->am_nextnonce) { char nonce[AUTH_NTLM_NONCE_LEN]; /* XXX - replace */ #if 0 auth_generate_ntlm_nonce(am, nonce, sizeof nonce, 1, msg_now()); #else auth_generate_digest_nonce(am, nonce, sizeof nonce, 1, msg_now()); #endif as->as_info = msg_header_format(as->as_home, ach->ach_info, "nextnonce=\"%s\"", nonce); } } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/auth_tag.c000066400000000000000000000177531223300710500230160ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE auth_tag.c * @brief Tags for authentication verification module for NTA servers. * * @author Pekka Pessi . * * @date Created: Wed Apr 11 15:14:03 2001 ppessi */ #include "config.h" #define TAG_NAMESPACE "auth" #include "sofia-sip/auth_module.h" #include #include /**@def AUTHTAG_ANY() * * Filter tag matching any AUTHTAG_*(). */ tag_typedef_t authtag_any = NSTAG_TYPEDEF(*); /**@def AUTHTAG_MODULE() * * Pointer to an authentication server module (auth_mod_t). * * The tag item AUTHTAG_MODULE() contains pointer to an authentication server * module. It is used to pass an already initialized authentication module * to a server object (like web server or registrar object). */ tag_typedef_t authtag_module = PTRTAG_TYPEDEF(module); /**@def AUTHTAG_METHOD() * * Name of the authentication scheme. * * The tag AUTHTAG_METHOD() specifies the authentication module and scheme * to be used by the auth_module. The name can specify a basic * authentication module, like "Digest" or "Basic", or an plugin module, * like "SGMF+Digest". * * @sa See for plugin interface. */ tag_typedef_t authtag_method = STRTAG_TYPEDEF(method); /**@def AUTHTAG_REALM() * * Authentication realm used by authentication server. * * The tag authtag_method specifies the authentication realm used by the @b * auth_module. For servers, the domain name in the request URI is inserted * in the realm returned to the client if the realm string contains an * asterisk @c "*". Only the first asterisk is replaced by request domain * name. * * @p Default Value * "*". */ tag_typedef_t authtag_realm = STRTAG_TYPEDEF(realm); /**@def AUTHTAG_OPAQUE() * * Opaque data used by authentication server. * * The tag authtag_opaque is used to pass opaque data to the @b auth_module. * The opaque data will be included in all the challenges (however, the data * is prefixed with a "." and other opaque data used by the algorithms. * * @p Default Value * "". */ tag_typedef_t authtag_opaque = STRTAG_TYPEDEF(opaque); /**@def AUTHTAG_DB() * * Name of authentication database used by authentication server. * * The tag AUTHTAG_DB() specifies the file name used to store the * authentication data. The file contains triplets as follows: * * @code * user:password:realm * @endcode * * @note * Currently, the passwords are stored as plaintext. */ tag_typedef_t authtag_db = STRTAG_TYPEDEF(db); /**@def AUTHTAG_QOP() * * Quality-of-protection used by Digest authentication. * * The tag AUTHTAG_QOP() specifies the qop scheme to be used by the * digest authentication. */ tag_typedef_t authtag_qop = STRTAG_TYPEDEF(qop); /**@def AUTHTAG_ALGORITHM() * * Authentication algorithm used by Digest authentication. * * The tag AUTHTAG_ALGORITHM() specifies the qop scheme to be used by the * digest authentication. */ tag_typedef_t authtag_algorithm = STRTAG_TYPEDEF(algorithm); /**@def AUTHTAG_EXPIRES() * * Nonce expiration time for Digest authentication. * * The tag AUTHTAG_EXPIRES() specifies the time in seconds that a nonce is * considered valid. If 0, the nonce lifetime unbounded. The default time is * 3600 seconds. */ tag_typedef_t authtag_expires = UINTTAG_TYPEDEF(expires); /**@def AUTHTAG_NEXT_EXPIRES() * * Next nonce expiration time for Digest authentication. * * The tag AUTHTAG_NEXT_EXPIRES() specifies the time in seconds that a * nextnonce sent in Authentication-Info header is considered valid. If 0, * the nonce lifetime is unbounded. The default time is 3600 seconds. */ tag_typedef_t authtag_next_expires = UINTTAG_TYPEDEF(next_expires); /**@def AUTHTAG_MAX_NCOUNT() * * Max nonce count value. * * The tag AUTHTAG_MAX_NCOUNT() specifies the maximum number of times a * nonce should be used. * * @todo Count actual usages and don't trust "nc" parameter only. */ tag_typedef_t authtag_max_ncount = UINTTAG_TYPEDEF(max_ncount); /**@def AUTHTAG_BLACKLIST() * * Blacklist time. * * The tag AUTHTAG_BLACKLIST() specifies the time the server delays its * response if it is given bad credentials or malformed nonce. The default * time is 5 seconds. * * @todo Implement delayed response. */ tag_typedef_t authtag_blacklist = UINTTAG_TYPEDEF(blacklist); /**@def AUTHTAG_FORBIDDEN() * * Respond with 403 Forbidden. * * When given a true argument, the tag AUTHTAG_FORBIDDEN() specifies that the * server responds with 403 Forbidden (instead of 401/407) when it receives * bad credentials. */ tag_typedef_t authtag_forbidden = BOOLTAG_TYPEDEF(forbidden); /**@def AUTHTAG_ANONYMOUS() * * Allow anonymous access. * * When given a true argument, the tag AUTHTAG_ANONYMOUS() allows * authentication module to accept the account "anonymous" with an empty * password. The auth_status_t::as_anonymous flag is set in auth_status_t * structure after anonymous authentication. */ tag_typedef_t authtag_anonymous = BOOLTAG_TYPEDEF(anonymous); /**@def AUTHTAG_FAKE() * * Fake authentication process. * * When given a true argument, the tag AUTHTAG_FAKE() causes authentication * module to allow access with any password when the username is valid. The * auth_status_t::as_fake flag is set in auth_status_t structure after a * fake authentication. */ tag_typedef_t authtag_fake = BOOLTAG_TYPEDEF(fake); /**@def AUTHTAG_REMOTE() * * Remote authenticator URL. * * The tag AUTHTAG_REMOTE() is used to specify URL for remote authenticator. * The meaning of the URL is specific to the authentication module. The * authentication module is selected by AUTHTAG_METHOD(). */ tag_typedef_t authtag_remote = URLTAG_TYPEDEF(remote); /**@def AUTHTAG_ALLOW() * * Comma-separated list of methods that are not challenged. * * The tag AUTHTAG_ALLOW() takes its argument a string containing a * comma-separated list of methods, for example, * @code * AUTHTAG_ALLOW("ACK, BYE, CANCEL"). * @endcode * * The specified methods are not challenged by the authentication module. * For example, this may include SIP ACK method or SIP methods only used * within an already established dialog. */ tag_typedef_t authtag_allow = STRTAG_TYPEDEF(allow); /**@def AUTHTAG_MASTER_KEY() * * Private master key for the authentication module. * * The tag AUTHTAG_MASTER_KEY() specifies a private master key that can be * used by the authentication module for various purposes (for instance, * validating that nonces are really generated by it). */ tag_typedef_t authtag_master_key = STRTAG_TYPEDEF(master_key); /**@def AUTHTAG_CACHE_USERS() * * Time to cache user data. * * The tag AUTHTAG_CACHE_USERS() specifies how many seconds the user data is * cached locally. Default value is typically 30 minutes. */ tag_typedef_t authtag_cache_users = UINTTAG_TYPEDEF(cache_users); /**@def AUTHTAG_CACHE_ERRORS() * * Time to cache errors. * * The tag AUTHTAG_CACHE_ERRORS() specifies the lifetime in seconds for * errors in the local authentication data cache. Note that the errors * generated locally (e.g., because of connectivity problem with * authentication server) have maximum lifetime of 2 minutes. */ tag_typedef_t authtag_cache_errors = UINTTAG_TYPEDEF(cache_errors); sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/iptsec.docs000066400000000000000000000057171223300710500232140ustar00rootroot00000000000000/* -*- C -*- */ /**@MODULEPAGE "iptsec" - Authentication Module * * @section iptsec_meta Module Meta Information * * The iptsec module currently provides interfaces to HTTP * Basic and Digest authentication, used by HTTP and SIP protocol elements. * There are both * @ref auth_client "client-side" and * @ref auth_module "server-side" * (authentication verification) functionality available. * * @CONTACT Pekka Pessi * * @STATUS @SofiaSIP Core library * * @LICENSE LGPL * * @section auth_module Server Verifying Authentication * * The file defines the interface used by a server * verifying the authentication from client. After the server has created an * @ref auth_mod_t "authentication module", the usual authentication * operation is simple enough: * -# server initializes an #auth_status_t structure with information from * the request * -# server calls auth_mod_method() * -# server checks the status from auth_status_t structure, sends an error * response to the client if authentication fails * -# server proceeds serving the authenticated request. * * If the operation is asynchronous, only a preliminary result is stored in * the auth_status_t structure when the call to auth_mod_method() returns. * In that case, the application can assign a callback function to the * structure. The callback function is invoked when the authentication * operation is completed. An asynchronous authentication operation can be * terminated before its completion by calling auth_mod_cancel(). * * @subsection auth_module_tags Server-Side Authentication Parameters * * When the server creates the authentication module with auth_mod_create(), * it can specify numerous parameters affecting the authentication protocol * and algorithms. The parameter tags are defined in * . The most important parameters include: * * - AUTHTAG_METHOD(), * - AUTHTAG_ALGORITHM(), * - AUTHTAG_QOP(), and * - AUTHTAG_REMOTE(). * * @section auth_client Client Authenticating User * * The file defines the interface used by a client * authenticating a user with a server. Because there may be multiple * servers or proxies requiring authentication, the client-side * authentication information is represented using a list of #auth_client_t * objects. The client-side operation is as follows: * * -# send a request * -# get a response with specific response code (401 or 407) and challenge * -# store the challenge to a list with auc_challenge() * -# prompt user and feed credentials (username and password) to the list * with auc_credentials() or auc_all_credentials() * -# authorize a request (add credential headers to it) with * auc_authorization() and resend the request * * If there are several username/password pairs for multiple authentication * realms required, the application must provide the corresponding realm as * an argument to auc_all_credentials(). */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/iptsec_debug.c000066400000000000000000000037351223300710500236520ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@internal @file iptsec_debug.c * @brief Debug log for IPTSEC module. * * @author Pekka Pessi * * @date Created: Thu Dec 19 15:55:30 2002 ppessi */ #include "config.h" #include #include "iptsec_debug.h" #if DOXYGEN_ONLY /** @defgroup iptsec_env Environment Variables Used by iptsec Module * * @brief Environment variables used by @iptsec module are listed here. * * The #IPTSEC_DEBUG variable sets the debug level. */ /**@ingroup iptsec_env * * Environment variable determining the debug log level for @iptsec * module. * * The IPTSEC_DEBUG environment variable is used to determine the debug * logging level for @iptsec module. The default level is 3. * * @sa , #iptsec_log, #SOFIA_DEBUG */ extern IPTSEC_DEBUG; #endif #ifndef SU_DEBUG #define SU_DEBUG 3 #endif /** Common log for client and server components. * * The iptsec_log is the log object used by @iptsec module. The level of * #iptsec_log is set using #IPTSEC_DEBUG environment variable. */ su_log_t iptsec_log[] = { SU_LOG_INIT("iptsec", "IPTSEC_DEBUG", SU_DEBUG) }; sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/iptsec_debug.h000066400000000000000000000026311223300710500236510ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef IPTSEC_DEBUG_H /** Defined when has been included. */ #define IPTSEC_DEBUG_H /**@internal * @file iptsec_debug.h * @brief Debug log for IPTSEC module. * * @author Pekka Pessi * * @date Created: Thu Dec 19 15:56:35 2002 ppessi */ #include SOFIA_BEGIN_DECLS /** Common log for client and server components. */ SOFIAPUBVAR su_log_t iptsec_log[]; SOFIA_END_DECLS #define SU_LOG (iptsec_log) #include #endif /* !defined IPTSEC_DEBUG_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/sofia-sip/000077500000000000000000000000001223300710500227335ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/sofia-sip/auth_client.h000066400000000000000000000053711223300710500254110ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef AUTH_CLIENT_H /** Defined when has been included. */ #define AUTH_CLIENT_H /**@file sofia-sip/auth_client.h * * @brief Client-side authenticator library. * * @author Pekka Pessi * * @date Created: Wed Feb 14 17:09:44 2001 ppessi */ #ifndef MSG_TYPES_H #include #endif #ifndef URL_H #include #endif SOFIA_BEGIN_DECLS /** Authenticator object. */ typedef struct auth_client_s auth_client_t; SOFIAPUBFUN int auc_challenge(auth_client_t **auc, su_home_t *home, msg_auth_t const *auth, msg_hclass_t *crcl); SOFIAPUBFUN int auc_credentials(auth_client_t **auc, su_home_t *home, char const *data); SOFIAPUBFUN int auc_info(auth_client_t **auc_list, msg_auth_info_t const *ai, msg_hclass_t *credential_class); SOFIAPUBFUN int auc_all_credentials(auth_client_t **auc_list, char const *scheme, char const *realm, char const *user, char const *pass); SOFIAPUBFUN int auc_clear_credentials(auth_client_t **auc_list, char const *scheme, char const *realm); SOFIAPUBFUN int auc_copy_credentials(auth_client_t **dst, auth_client_t const *src); SOFIAPUBFUN int auc_has_authorization(auth_client_t **auc_list); SOFIAPUBFUN int auc_authorization(auth_client_t **auc_list, msg_t *msg, msg_pub_t *pub, char const *method, url_t const *url, msg_payload_t const *body); SOFIAPUBFUN int auc_authorization_headers(auth_client_t **auc_list, su_home_t *home, char const *method, url_t const *url, msg_payload_t const *body, msg_header_t **return_headers); struct sip_s; SOFIAPUBFUN int auc_authorize(auth_client_t **auc, msg_t *msg, struct sip_s *sip); typedef struct auth_client_plugin auth_client_plugin_t; SOFIAPUBFUN int auc_register_plugin(auth_client_plugin_t const *plugin); SOFIA_END_DECLS #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/sofia-sip/auth_client_plugin.h000066400000000000000000000103021223300710500267550ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef AUTH_CLIENT_PLUGIN_H /** Defined when has been included. */ #define AUTH_CLIENT_PLUGIN_H /**@file sofia-sip/auth_client_plugin.h * @brief Client-side plugin interface for authentication * * @note For extensions in 1.12.6 or later, * you have to define SOFIA_EXTEND_AUTH_CLIENT to 1 * before including this file. * * @author Pekka Pessi * * @date Created: Fri May 19 16:18:21 EEST 2006 */ #ifndef AUTH_CLIENT_H #include "sofia-sip/auth_client.h" #endif #ifndef MSG_HEADER_H #include #endif SOFIA_BEGIN_DECLS /* ====================================================================== */ struct auth_client_s { su_home_t ca_home[1]; auth_client_plugin_t const *ca_auc; auth_client_t *ca_next; char const *ca_scheme; char const *ca_realm; char *ca_user; char *ca_pass; msg_hclass_t *ca_credential_class; #if SOFIA_EXTEND_AUTH_CLIENT int ca_clear; #endif }; struct auth_client_plugin { int auc_plugin_size; /* Size of this structure */ int auc_size; /* Size of the client structure */ char const *auc_name; /* Name of the autentication scheme */ /** Store challenge */ int (*auc_challenge)(auth_client_t *ca, msg_auth_t const *ch); /** Authorize request. */ int (*auc_authorize)(auth_client_t *ca, su_home_t *h, char const *method, url_t const *url, msg_payload_t const *body, msg_header_t **return_headers); /** Store nextnonce from Authentication-Info or Proxy-Authentication-Info. */ int (*auc_info)(auth_client_t *ca, msg_auth_info_t const *ai); #if SOFIA_EXTEND_AUTH_CLIENT /** Clear credentials (user/pass). @NEW_1_12_6. */ int (*auc_clear)(auth_client_t *ca); /** Save credentials. @NEW_1_12_11. */ int (*auc_save_credentials)(auth_client_t *ca, char const *scheme, char const *realm, char const *user, char const *pass); /** Copy credentials. @NEW_1_12_11. */ int (*auc_copy_credentials)(auth_client_t *dst, auth_client_t const *src); #endif }; /** Check if authentication client has been extended. @NEW_1_12_6. */ #define AUTH_CLIENT_IS_EXTENDED(ca) \ ((ca)->ca_auc && \ (ca)->ca_auc->auc_plugin_size > \ (int)offsetof(auth_client_plugin_t, auc_clear) \ && (ca)->ca_auc->auc_clear != NULL) /** Return auc_save_credentials method from authentication client. * @NEW_1_12_11. */ #define AUTH_CLIENT_SAVE_CREDENTIALS(ca) \ ((ca)->ca_auc && \ (ca)->ca_auc->auc_plugin_size > \ (int)offsetof(auth_client_plugin_t, auc_save_credentials) \ ? (ca)->ca_auc->auc_save_credentials : NULL) SOFIAPUBFUN int auth_client_save_credentials(auth_client_t *ac, char const *scheme, char const *realm, char const *user, char const *pass); /** Return auc_copy_credentials method from authentication client. * @NEW_1_12_11. */ #define AUTH_CLIENT_COPY_CREDENTIALS(ca) \ ((ca)->ca_auc && \ (ca)->ca_auc->auc_plugin_size > \ (int)offsetof(auth_client_plugin_t, auc_copy_credentials) \ ? (ca)->ca_auc->auc_copy_credentials : NULL) SOFIAPUBFUN int auth_client_copy_credentials(auth_client_t *ac, auth_client_t const *src); SOFIA_END_DECLS #endif /* !defined AUTH_CLIENT_PLUGIN_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/sofia-sip/auth_common.h000066400000000000000000000031201223300710500254110ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef AUTH_COMMON_H /** Defined when has been included. */ #define AUTH_COMMON_H /**@file sofia-sip/auth_common.h * * Functions common for client/server. * * @author Pekka Pessi * * @date Created: Fri May 19 15:54:08 EEST 2006 ppessi */ #ifndef SU_ALLOC_H #include #endif SOFIA_BEGIN_DECLS SOFIAPUBFUN issize_t auth_get_params(su_home_t *home, char const * const params[], ... /* char const * name, char const **return_value */); SOFIAPUBFUN int auth_struct_copy(void *dst, void const *src, isize_t s_size); SOFIAPUBFUN int auth_strcmp(char const *quoted, char const *unquoted); SOFIA_END_DECLS #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/sofia-sip/auth_digest.h000066400000000000000000000140011223300710500254000ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef AUTH_DIGEST_H /** Defined when has been included. */ #define AUTH_DIGEST_H /**@file sofia-sip/auth_digest.h * Datatypes and functions for Digest authentication. * * The structures and functions here follow the RFC 2617. * * @sa @RFC2617, * "HTTP Authentication: Basic and Digest Access Authentication", * J. Franks et al, * June 1999. * * @sa @RFC3261 section 22 * * @author Pekka Pessi * * @date Created: Thu Feb 22 12:25:55 2001 ppessi */ #ifndef SU_ALLOC_H #include #endif SOFIA_BEGIN_DECLS /** Parameters for digest-challenge. * * The digest-challenge is sent by server or proxy to client. It can be * included in, e.g, WWW-Authenticate or Proxy-Authenticate headers. * * @code * challenge = "Digest" digest-challenge * digest-challenge = 1#( realm | [domain] | nonce | * [opaque] | [stale] | [algorithm] | * [qop-options] | [auth-param] ) * domain = "domain" "=" <"> URI ( 1*SP URI ) <"> * URI = absoluteURI | abs_path * nonce = "nonce" "=" nonce-value * nonce-value = quoted-string * opaque = "opaque" "=" quoted-string * stale = "stale" "=" ( "true" | "false" ) * algorithm = "algorithm" "=" ( "MD5" | "MD5-sess" | token ) * qop-options = "qop" "=" <"> 1#qop-value <"> * qop-value = "auth" | "auth-int" | token * @endcode * * @sa @RFC2617 */ typedef struct { int ac_size; char const *ac_realm; /**< realm */ char const *ac_domain; /**< domain */ char const *ac_nonce; /**< nonce */ char const *ac_opaque; /**< opaque */ char const *ac_algorithm; /**< algorithm */ char const *ac_qop; /**< qop */ unsigned ac_stale : 1; /**< stale=true */ unsigned ac_md5 : 1; /**< algorithm=MS5 (or missing) */ unsigned ac_md5sess : 1; /**< algorithm=MD5-sess */ unsigned ac_sha1 : 1; /**< algorithm=sha1 (SSA Hash) */ unsigned ac_auth : 1; /**< qop=auth */ unsigned ac_auth_int : 1; /**< qop=auth-int */ unsigned : 0; } auth_challenge_t; /** Digest parameters for digest-response in Authorize. * * The digest-response is sent by the client to a server or a proxy. It can * be included in, e.g., Authorization or Proxy-Authorization headers. * * @code * credentials = "Digest" digest-response * digest-response = 1#( username | realm | nonce | digest-uri | * response | [ algorithm ] | [cnonce] | [opaque] | * [message-qop] | [nonce-count] | [auth-param] ) * username = "username" "=" username-value * username-value = quoted-string * digest-uri = "uri" "=" digest-uri-value * digest-uri-value = request-uri ; As specified by HTTP/1.1 * message-qop = "qop" "=" qop-value * cnonce = "cnonce" "=" cnonce-value * cnonce-value = nonce-value * nonce-count = "nc" "=" nc-value * nc-value = 8LHEX * response = "response" "=" request-digest * request-digest = <"> 32LHEX <"> * LHEX = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | * "8" | "9" | "a" | "b" | "c" | "d" | "e" | "f" * @endcode */ typedef struct { int ar_size; char const *ar_username; char const *ar_realm; /**< realm */ char const *ar_nonce; /**< nonce */ char const *ar_uri; /**< uri */ char const *ar_response; /**< response */ char const *ar_algorithm; /**< algorithm */ char const *ar_cnonce; /**< cnonce */ char const *ar_opaque; /**< opaque */ char const *ar_qop; /**< qop */ char const *ar_nc; /**< nonce count */ unsigned ar_md5 : 1; /**< MS5 algorithm */ unsigned ar_md5sess : 1; /**< MD5-sess algorithm */ unsigned ar_sha1 : 1; /**< SHA1 algorithm */ unsigned ar_auth : 1; /**< qop=auth */ unsigned ar_auth_int : 1; /**< qop=auth-int */ unsigned : 0; } auth_response_t; typedef char auth_hexmd5_t[33]; SOFIAPUBFUN issize_t auth_digest_challenge_get(su_home_t *, auth_challenge_t *, char const * const params[]); SOFIAPUBFUN void auth_digest_challenge_free_params(su_home_t *home, auth_challenge_t *ac); SOFIAPUBFUN issize_t auth_digest_response_get(su_home_t *, auth_response_t *, char const * const params[]); SOFIAPUBFUN int auth_digest_ha1(auth_hexmd5_t ha1, char const *username, char const *realm, char const *secret); SOFIAPUBFUN int auth_digest_a1(auth_response_t *ar, auth_hexmd5_t ha1, char const *secret); SOFIAPUBFUN int auth_digest_a1sess(auth_response_t *ar, auth_hexmd5_t ha1sess, char const *ha1); SOFIAPUBFUN int auth_digest_sessionkey(auth_response_t *, auth_hexmd5_t ha1, char const *secret); SOFIAPUBFUN int auth_digest_response(auth_response_t *, auth_hexmd5_t response, auth_hexmd5_t const ha1, char const *method_name, void const *data, isize_t dlen); SOFIAPUBFUN int auth_struct_copy(void *dst, void const *src, isize_t s_size); SOFIAPUBFUN int auth_strcmp(char const *quoted, char const *unquoted); SOFIA_END_DECLS #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/sofia-sip/auth_module.h000066400000000000000000000336271223300710500254250ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef AUTH_MODULE_H /** Defined when has been included. */ #define AUTH_MODULE_H /**@file sofia-sip/auth_module.h * @brief Authentication verification interface. * * @author Pekka Pessi . * * @date Created: Mon Jul 23 19:21:24 2001 ppessi */ #ifndef SU_TAG_H #include #endif #ifndef SU_WAIT_H #include #endif #ifndef MSG_TYPES_H #include #endif #ifndef URL_H #include #endif #ifndef URL_TAG_H #include #endif SOFIA_BEGIN_DECLS typedef struct auth_mod_t auth_mod_t; /** Authentication operation. */ typedef struct auth_status_t auth_status_t; #ifdef AUTH_MAGIC_T typedef AUTH_MAGIC_T auth_magic_t; #else typedef void auth_magic_t; #endif /** Virtual table for authentication plugin. */ typedef struct auth_scheme const auth_scheme_t; /** Opaque data used by authentication plugin module. */ typedef struct auth_plugin_t auth_plugin_t; /** Opaque user data used by plugin module. */ typedef struct auth_splugin_t auth_splugin_t; /** Opaque authentication operation data used by plugin module. */ typedef struct auth_uplugin_t auth_uplugin_t; /** Callback from completeted asynchronous authentication operation. */ typedef void auth_callback_t(auth_magic_t *, auth_status_t *); /**Authentication operation result. * * The auth_status_t structure is used to store the status of the * authentication operation and all the related data. The application * verifying the authentication fills the auth_status_t structure, then * calls auth_mod_method() (or auth_mod_challenge()). The operation result * is stored in the structure. * * If the operation is asynchronous, only a preliminary result is stored in * the auth_status_t structure when the call to auth_mod_method() returns. * In that case, the application @b must assign a callback function to the * structure. The callback function is invoked when the authentication * operation is completed. * * It is recommended that the auth_status_t structure is allocated with * auth_status_new() or initialized with auth_status_init() or * auth_status_init_with() functions. */ struct auth_status_t { su_home_t as_home[1]; /**< Memory home for authentication */ int as_status; /**< Return authorization status [out] */ char const *as_phrase; /**< Return response phrase [out] */ char const *as_user; /**< Authenticated username [in/out] */ char const *as_display; /**< Return user's real name [in/out] */ url_t const *as_user_uri; /* Return user's identity [in/out] */ char const *as_ident; /**< Identities [out] */ unsigned as_profile; /**< User profile (group) [out] */ su_addrinfo_t *as_source; /**< Source address [in] */ char const *as_realm; /**< Authentication realm [in] */ char const *as_domain; /**< Hostname [in] */ char const *as_uri; /**< Request-URI [in] */ char const *as_pdomain; /**< Domain parameter [in] (ignored). */ char const *as_method; /**< Method name to authenticate [in] */ void const *as_body; /**< Message body to protect [in] */ isize_t as_bodylen; /**< Length of message body [in] */ msg_time_t as_nonce_issued; /**< Nonce issue time [out] */ unsigned as_blacklist; /**< Blacklist time [out] */ unsigned as_anonymous:1;/**< Return true if user is anonymous [out] */ unsigned as_stale:1; /**< Credentials were stale [out] */ unsigned as_allow:1; /**< Method cannot be challenged [out] */ unsigned as_nextnonce:1; /**< Client used nextnonce [out] */ unsigned :0; msg_header_t *as_response; /**< Authentication challenge [out] */ msg_header_t *as_info; /**< Authentication-Info [out] */ msg_header_t *as_match; /**< Used authentication header [out] */ /** @defgroup Callback information for asynchronous operation. */ /** @{ */ auth_magic_t *as_magic; /**< Application data [in] */ auth_callback_t*as_callback; /**< Completion callback [in] */ /** @} */ /** Pointer to extended state, used exclusively by plugin modules. */ auth_splugin_t *as_plugin; }; /** Authentication challenge. * * This structure defines what kind of response and challenge header is * returned to the user. For example, a server authentication is implemented * with 401 response code and phrase along with header class for * @b WWW-Authenticate header in the @a ach structure. */ typedef struct auth_challenger { int ach_status; /**< Response status for challenge response */ char const *ach_phrase; /**< Response phrase for challenge response */ msg_hclass_t *ach_header; /**< Header class for challenge header */ msg_hclass_t *ach_info; } auth_challenger_t; SOFIAPUBVAR char const auth_internal_server_error[]; #define AUTH_STATUS_INIT \ {{ SU_HOME_INIT(auth_status_t) }, 500, auth_internal_server_error, NULL } #define AUTH_STATUS_DEINIT(as) \ su_home_deinit(as->as_home) #define AUTH_RESPONSE_INIT(as) AUTH_STATUS_INIT #define AUTH_RESPONSE_DEINIT(as) AUTH_STATUS_DEINIT(as) SOFIAPUBFUN int auth_mod_register_plugin(auth_scheme_t *asch); SOFIAPUBFUN auth_mod_t *auth_mod_create(su_root_t *root, tag_type_t, tag_value_t, ...); SOFIAPUBFUN void auth_mod_destroy(auth_mod_t *); SOFIAPUBFUN auth_mod_t *auth_mod_ref(auth_mod_t *am); SOFIAPUBFUN void auth_mod_unref(auth_mod_t *am); SOFIAPUBFUN char const *auth_mod_name(auth_mod_t *am); SOFIAPUBFUN auth_status_t *auth_status_init(void *, isize_t size); SOFIAPUBFUN auth_status_t *auth_status_init_with(void *, isize_t size, int status, char const *phrase); SOFIAPUBFUN auth_status_t *auth_status_new(su_home_t *); SOFIAPUBFUN auth_status_t *auth_status_ref(auth_status_t *as); SOFIAPUBFUN void auth_status_unref(auth_status_t *as); SOFIAPUBFUN void auth_mod_verify(auth_mod_t *am, auth_status_t *as, msg_auth_t *credentials, auth_challenger_t const *ach); SOFIAPUBFUN void auth_mod_challenge(auth_mod_t *am, auth_status_t *as, auth_challenger_t const *ach); SOFIAPUBFUN void auth_mod_authorize(auth_mod_t *am, auth_status_t *as, auth_challenger_t const *ach); SOFIAPUBFUN void auth_mod_cancel(auth_mod_t *am, auth_status_t *as); /* ====================================================================== */ /* Deprecated functions */ typedef enum { auth_server, auth_proxy, auth_proxy_consume, auth_consume } auth_kind_t; SOFIAPUBFUN void auth_mod_method(auth_mod_t *am, auth_status_t *as, msg_auth_t *credentials, auth_challenger_t const *ach); SOFIAPUBFUN void auth_mod_check_client(auth_mod_t *am, auth_status_t *as, msg_auth_t *credentials, auth_challenger_t const *ach); SOFIAPUBFUN void auth_mod_challenge_client(auth_mod_t *am, auth_status_t *as, auth_challenger_t const *ach); #ifdef SIP_H SOFIAPUBFUN void auth_mod_check(auth_mod_t *am, auth_status_t *as, sip_t const *sip, auth_kind_t proxy); #endif #ifdef HTTP_H SOFIAPUBFUN const char *auth_mod_check_http(auth_mod_t *am, auth_status_t *as, http_t const *http, auth_kind_t proxy); #endif /* ====================================================================== */ /* Tags */ #define AUTHTAG_ANY() authtag_any, ((tag_value_t)0) SOFIAPUBVAR tag_typedef_t authtag_any; /** Pointer to an authentication server (auth_mod_t). */ #define AUTHTAG_MODULE(x) authtag_module, authtag_module_v((x)) SOFIAPUBVAR tag_typedef_t authtag_module; #define AUTHTAG_MODULE_REF(x) authtag_module_ref, authtag_module_vr((&x)) SOFIAPUBVAR tag_typedef_t authtag_module_ref; #if SU_INLINE_TAG_CAST su_inline tag_value_t authtag_module_v(auth_mod_t *v) { return (tag_value_t)v; } su_inline tag_value_t authtag_module_vr(auth_mod_t **vp) { return (tag_value_t)vp; } #else #define authtag_module_v(v) ((tag_value_t)(v)) #define authtag_module_vr(v) ((tag_value_t)(v)) #endif /** Authentication scheme used by authentication module. */ #define AUTHTAG_METHOD(x) authtag_method, tag_str_v((x)) SOFIAPUBVAR tag_typedef_t authtag_method; #define AUTHTAG_METHOD_REF(x) authtag_method_ref, tag_str_vr((&x)) SOFIAPUBVAR tag_typedef_t authtag_method_ref; /** Authentication realm used by authentication server. */ #define AUTHTAG_REALM(x) authtag_realm, tag_str_v((x)) SOFIAPUBVAR tag_typedef_t authtag_realm; #define AUTHTAG_REALM_REF(x) authtag_realm_ref, tag_str_vr((&x)) SOFIAPUBVAR tag_typedef_t authtag_realm_ref; /** Opaque authentication data always included in challenge. */ #define AUTHTAG_OPAQUE(x) authtag_opaque, tag_str_v((x)) SOFIAPUBVAR tag_typedef_t authtag_opaque; #define AUTHTAG_OPAQUE_REF(x) authtag_opaque_ref, tag_str_vr((&x)) SOFIAPUBVAR tag_typedef_t authtag_opaque_ref; /** Name of authentication database used by authentication server. */ #define AUTHTAG_DB(x) authtag_db, tag_str_v((x)) SOFIAPUBVAR tag_typedef_t authtag_db; #define AUTHTAG_DB_REF(x) authtag_db_ref, tag_str_vr((&x)) SOFIAPUBVAR tag_typedef_t authtag_db_ref; /** Quality-of-protection used by digest authentication. */ #define AUTHTAG_QOP(x) authtag_qop, tag_str_v((x)) SOFIAPUBVAR tag_typedef_t authtag_qop; #define AUTHTAG_QOP_REF(x) authtag_qop_ref, tag_str_vr((&x)) SOFIAPUBVAR tag_typedef_t authtag_qop_ref; /** Algorithm used by digest authentication. */ #define AUTHTAG_ALGORITHM(x) authtag_algorithm, tag_str_v((x)) SOFIAPUBVAR tag_typedef_t authtag_algorithm; #define AUTHTAG_ALGORITHM_REF(x) authtag_algorithm_ref, tag_str_vr((&x)) SOFIAPUBVAR tag_typedef_t authtag_algorithm_ref; /** Nonce lifetime. */ #define AUTHTAG_EXPIRES(x) authtag_expires, tag_uint_v((x)) SOFIAPUBVAR tag_typedef_t authtag_expires; #define AUTHTAG_EXPIRES_REF(x) authtag_expires_ref, tag_uint_vr((&x)) SOFIAPUBVAR tag_typedef_t authtag_expires_ref; /** Lifetime for nextnonce, 0 disables nextnonce. */ #define AUTHTAG_NEXT_EXPIRES(x) authtag_next_expires, tag_uint_v((x)) SOFIAPUBVAR tag_typedef_t authtag_next_expires; #define AUTHTAG_NEXT_EXPIRES_REF(x) \ authtag_next_expires_ref, tag_uint_vr((&x)) SOFIAPUBVAR tag_typedef_t authtag_next_expires_ref; /** Maximum nonce count allowed. */ #define AUTHTAG_MAX_NCOUNT(x) authtag_max_ncount, tag_uint_v((x)) SOFIAPUBVAR tag_typedef_t authtag_max_ncount; #define AUTHTAG_MAX_NCOUNT_REF(x) authtag_max_ncount_ref, tag_uint_vr((&x)) SOFIAPUBVAR tag_typedef_t authtag_max_ncount_ref; /** Extra delay when responding if provided invalid credentials or nonce. */ #define AUTHTAG_BLACKLIST(x) authtag_blacklist, tag_uint_v((x)) SOFIAPUBVAR tag_typedef_t authtag_blacklist; #define AUTHTAG_BLACKLIST_REF(x) authtag_blacklist_ref, tag_uint_vr((&x)) SOFIAPUBVAR tag_typedef_t authtag_blacklist_ref; /** Respond with 403 Forbidden if given invalid credentials. */ #define AUTHTAG_FORBIDDEN(x) authtag_forbidden, tag_bool_v((x)) SOFIAPUBVAR tag_typedef_t authtag_forbidden; #define AUTHTAG_FORBIDDEN_REF(x) authtag_forbidden_ref, tag_bool_vr((&x)) SOFIAPUBVAR tag_typedef_t authtag_forbidden_ref; /** Allow anonymous access. */ #define AUTHTAG_ANONYMOUS(x) authtag_anonymous, tag_bool_v((x)) SOFIAPUBVAR tag_typedef_t authtag_anonymous; #define AUTHTAG_ANONYMOUS_REF(x) authtag_anonymous_ref, tag_bool_vr((&x)) SOFIAPUBVAR tag_typedef_t authtag_anonymous_ref; /** HSS client structure. */ #define AUTHTAG_HSS(x) authtag_hss, tag_ptr_v((x)) SOFIAPUBVAR tag_typedef_t authtag_hss; #define AUTHTAG_HSS_REF(x) authtag_hss_ref, tag_ptr_vr((&x), (x)) SOFIAPUBVAR tag_typedef_t authtag_hss_ref; /** Remote authenticator URL. */ #define AUTHTAG_REMOTE(x) authtag_remote, urltag_url_v((x)) SOFIAPUBVAR tag_typedef_t authtag_remote; #define AUTHTAG_REMOTE_REF(x) authtag_remote_ref, urltag_url_vr((&x)) SOFIAPUBVAR tag_typedef_t authtag_remote_ref; /** Comma-separated list of methods never challenged. */ #define AUTHTAG_ALLOW(x) authtag_allow, tag_str_v((x)) SOFIAPUBVAR tag_typedef_t authtag_allow; #define AUTHTAG_ALLOW_REF(x) authtag_allow_ref, tag_str_vr((&x)) SOFIAPUBVAR tag_typedef_t authtag_allow_ref; /** Check that user exists, don't do authentication. */ #define AUTHTAG_FAKE(x) authtag_fake, tag_bool_v((x)) SOFIAPUBVAR tag_typedef_t authtag_fake; #define AUTHTAG_FAKE_REF(x) authtag_fake_ref, tag_bool_vr((&x)) SOFIAPUBVAR tag_typedef_t authtag_fake_ref; /** Master key in base64 for the authentication module. */ #define AUTHTAG_MASTER_KEY(x) authtag_master_key, tag_str_v((x)) SOFIAPUBVAR tag_typedef_t authtag_master_key; #define AUTHTAG_MASTER_KEY_REF(x) authtag_master_key_ref, tag_str_vr((&x)) SOFIAPUBVAR tag_typedef_t authtag_master_key_ref; /** Cache time for authentication data. */ #define AUTHTAG_CACHE_USERS(x) authtag_cache_users, tag_uint_v((x)) SOFIAPUBVAR tag_typedef_t authtag_cache_users; #define AUTHTAG_CACHE_USERS_REF(x) authtag_cache_users_ref, tag_uint_vr((&x)) SOFIAPUBVAR tag_typedef_t authtag_cache_users_ref; /** Cache time for errors. */ #define AUTHTAG_CACHE_ERRORS(x) authtag_cache_errors, tag_uint_v((x)) SOFIAPUBVAR tag_typedef_t authtag_cache_errors; #define AUTHTAG_CACHE_ERRORS_REF(x) authtag_cache_errors_ref, tag_uint_vr((&x)) SOFIAPUBVAR tag_typedef_t authtag_cache_errors_ref; SOFIA_END_DECLS #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/sofia-sip/auth_ntlm.h000066400000000000000000000063411223300710500251030ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef AUTH_NTLM_H /** Defined when has been included. */ #define AUTH_NTLM_H /**@file sofia-sip/auth_ntlm.h * Datatypes and functions for Ntlm authentication. * * The structures and functions here follow the RFC 2617. * * @sa * RFC 2617, * "HTTP Authentication: Basic and Ntlm Access Authentication", * J. Franks et al, * June 1999. * * @sa Section 19 from * #endif #ifndef SU_MD5_H #include #endif #include SOFIA_BEGIN_DECLS /* ====================================================================== */ /* Plugin interface for authentication */ /** Authentication scheme */ struct auth_scheme { /** Name */ char const *asch_method; /** Size of module object */ usize_t asch_size; /** Initialize module. Invoked by auth_mod_create(). */ int (*asch_init)(auth_mod_t *am, auth_scheme_t *base, su_root_t *root, tag_type_t tag, tag_value_t value, ...); /** Check authentication. Invoked by auth_mod_method(). */ void (*asch_check)(auth_mod_t *am, auth_status_t *as, msg_auth_t *auth, auth_challenger_t const *ch); /** Create a challenge. Invoked by auth_mod_challenge(). */ void (*asch_challenge)(auth_mod_t *am, auth_status_t *as, auth_challenger_t const *ch); /** Cancel an asynchronous authentication request. * Invoked by auth_mod_cancel(). */ void (*asch_cancel)(auth_mod_t *am, auth_status_t *as); /** Reclaim resources an authentication module. * * Invoked by auth_mod_destroy()/auth_mod_unref(). */ void (*asch_destroy)(auth_mod_t *am); }; /** User data structure */ typedef struct { unsigned apw_index; /**< Key to hash table */ void const *apw_type; /**< Magic identifier */ char const *apw_user; /**< Username */ char const *apw_realm; /**< Realm */ char const *apw_pass; /**< Password */ char const *apw_hash; /**< MD5 of the username, realm and pass */ char const *apw_ident; /**< Identity information */ auth_uplugin_t *apw_extended; /**< Method-specific extension */ } auth_passwd_t; HTABLE_DECLARE_WITH(auth_htable, aht, auth_passwd_t, usize_t, unsigned); struct stat; /** Common data for authentication module */ struct auth_mod_t { su_home_t am_home[1]; unsigned _am_refcount; /**< Not used */ /* User database / cache */ char const *am_db; /**< User database file name */ struct stat *am_stat; /**< State of user file when read */ auth_htable_t am_users[1]; /**< Table of users */ void *am_buffer; /**< Buffer for database */ auth_passwd_t *am_locals; /**< Entries from local user file */ size_t am_local_count; /**< Number of entries from local user file */ auth_passwd_t *am_anon_user; /**< Special entry for anonymous user */ /* Attributes */ url_t *am_remote; /**< Remote authenticator */ char const *am_realm; /**< Our realm */ char const *am_opaque; /**< Opaque identification data */ char const *am_gssapi_data; /**< NTLM data */ char const *am_targetname; /**< NTLM target name */ auth_scheme_t *am_scheme; /**< Authentication scheme (Digest, Basic). */ char const **am_allow; /**< Methods to allow without authentication */ msg_param_t am_algorithm; /**< Defauilt algorithm */ msg_param_t am_qop; /**< Default qop (quality-of-protection) */ unsigned am_expires; /**< Nonce lifetime */ unsigned am_next_exp; /**< Next nonce lifetime */ unsigned am_blacklist; /**< Extra delay if bad credentials. */ unsigned am_forbidden:1;/**< Respond with 403 if bad credentials */ unsigned am_anonymous:1;/**< Allow anonymous access */ unsigned am_challenge:1;/**< Challenge even if successful */ unsigned am_nextnonce:1;/**< Send next nonce in responses */ unsigned am_mutual:1; /**< Mutual authentication */ unsigned am_fake:1; /**< Fake authentication */ unsigned :0; /**< Pad */ unsigned am_count; /**< Nonce counter */ uint8_t am_master_key[16]; /**< Private master key */ su_md5_t am_hmac_ipad; /**< MD5 with inner pad */ su_md5_t am_hmac_opad; /**< MD5 with outer pad */ unsigned am_max_ncount:1; /**< If nonzero, challenge with new nonce after ncount */ }; SOFIAPUBFUN auth_passwd_t *auth_mod_getpass(auth_mod_t *am, char const *user, char const *realm); SOFIAPUBFUN auth_passwd_t *auth_mod_addpass(auth_mod_t *am, char const *user, char const *realm); SOFIAPUBFUN int auth_readdb_if_needed(auth_mod_t *am); SOFIAPUBFUN int auth_readdb(auth_mod_t *am); SOFIAPUBFUN msg_auth_t *auth_mod_credentials(msg_auth_t *auth, char const *scheme, char const *realm); SOFIAPUBFUN auth_mod_t *auth_mod_alloc(auth_scheme_t *scheme, tag_type_t, tag_value_t, ...); #define AUTH_PLUGIN(am) (auth_plugin_t *)((am) + 1) SOFIAPUBFUN int auth_init_default(auth_mod_t *am, auth_scheme_t *base, su_root_t *root, tag_type_t tag, tag_value_t value, ...); /** Default cancel method */ SOFIAPUBFUN void auth_cancel_default(auth_mod_t *am, auth_status_t *as); /** Default destroy method */ SOFIAPUBFUN void auth_destroy_default(auth_mod_t *am); /** Basic scheme */ SOFIAPUBFUN void auth_method_basic(auth_mod_t *am, auth_status_t *as, msg_auth_t *auth, auth_challenger_t const *ach); SOFIAPUBFUN void auth_challenge_basic(auth_mod_t *am, auth_status_t *as, auth_challenger_t const *ach); /** Digest scheme */ SOFIAPUBFUN msg_auth_t *auth_digest_credentials(msg_auth_t *auth, char const *realm, char const *opaque); SOFIAPUBFUN void auth_method_digest(auth_mod_t *am, auth_status_t *as, msg_auth_t *au, auth_challenger_t const *ach); SOFIAPUBFUN void auth_info_digest(auth_mod_t *am, auth_status_t *as, auth_challenger_t const *ach); SOFIAPUBFUN void auth_check_digest(auth_mod_t *am, auth_status_t *as, auth_response_t *ar, auth_challenger_t const *ach); SOFIAPUBFUN void auth_challenge_digest(auth_mod_t *am, auth_status_t *as, auth_challenger_t const *ach); SOFIAPUBFUN isize_t auth_generate_digest_nonce(auth_mod_t *am, char buffer[], size_t buffer_len, int nextnonce, msg_time_t now); SOFIAPUBFUN int auth_validate_digest_nonce(auth_mod_t *am, auth_status_t *as, auth_response_t *ar, msg_time_t now); SOFIAPUBFUN int auth_allow_check(auth_mod_t *am, auth_status_t *as); /** Init md5 for MD5-based HMAC */ SOFIAPUBFUN void auth_md5_hmac_init(auth_mod_t *am, su_md5_t *md5); SOFIAPUBFUN void auth_md5_hmac_digest(auth_mod_t *am, su_md5_t *md5, void *hmac, size_t size); SOFIA_END_DECLS #endif /* !defined AUTH_PLUGIN_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/test_auth_digest.c000066400000000000000000001326421223300710500245540ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE test_auth_digest.c * * @brief Test authentication functions for "Digest" scheme. * * @author Pekka Pessi * * @date Created: Thu Feb 22 12:10:37 2001 ppessi */ #include "config.h" #include #include #include #include #if HAVE_SOFIA_SIP #define PROTOCOL "SIP/2.0" #include #include #include #else #define PROTOCOL "HTTP/1.1" #include #include #define sip_authentication_info_class http_authentication_info_class #define sip_authorization http_authorization #define sip_authorization_class http_authorization_class #define sip_authorization_make http_authorization_make #define sip_authorization_t http_authorization_t #define sip_default_mclass http_default_mclass #define sip_object http_object #define sip_payload http_payload #define sip_proxy_authenticate_make http_proxy_authenticate_make #define sip_proxy_authenticate_t http_proxy_authenticate_t #define sip_proxy_authorization_make http_proxy_authorization_make #define sip_proxy_authorization_t http_proxy_authorization_t #define sip_request http_request #define sip_request_t http_request_t #define sip_t http_t #define sip_www_authenticate http_www_authenticate #define sip_www_authenticate_class http_www_authenticate_class #define sip_www_authenticate http_www_authenticate #define sip_www_authenticate_make http_www_authenticate_make #define sip_www_authenticate_t http_www_authenticate_t #endif #include #include #include #include #include int tstflags; char *argv0; #define TSTFLAGS tstflags #include #if defined(_WIN32) #include #endif char const name[] = "test_auth_digest"; /* Fake su_time() implementation */ #include unsigned offset; void offset_time(su_time_t *tv) { tv->tv_sec += offset; } int test_digest(void) { char challenge[] = "Digest " "realm=\"garage.sr.ntc.nokia.com\", " "nonce=\"MjAwMS0wMS0yMSAxNTowODo1OA==\", " "algorithm=MD5, " "qop=\"auth\""; char response[] = "DIGEST USERNAME=\"digest\", " "REALM=\"garage.sr.ntc.nokia.com\", " "NONCE=\"MjAwMS0wMS0yMSAxNTowODo1OA==\", " "RESPONSE=\"d9d7f1ae99a013cb05f319f0f678251d\", " "URI=\"sip:garage.sr.ntc.nokia.com\""; char rfc2617[] = "Digest username=\"Mufasa\", " "realm=\"testrealm@host.com\", " "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", " "cnonce=\"0a4f113b\", " "nc=\"00000001\", " "qop=\"auth\", " "algorithm=\"md5\", " "uri=\"/dir/index.html\""; char indigo[] = "Digest username=\"user1\", " "realm=\"nokia-proxy\", " "nonce=\"0YXwH29PCT4lEz8+YJipQg==\", " "uri=\"sip:nokia@62.254.248.33\", " "response=\"dd22a698b1a9510c4237c52e0e2cbfac\", " "algorithm=MD5, " "cnonce=\"V2VkIEF1ZyAxNSAxNzozNDowNyBHTVQrMDE6MDAgMjAwMVtCQDI0YmZhYQ==\", " "opaque=\"WiMlvw==\", " "qop=auth, " "nc=000000002"; char proxy_authenticate[] = "Digest realm=\"IndigoSw\", " "domain=\"indigosw.com aol.com\", " "nonce=\"V2VkIEF1ZyAxNSAxNzoxNzozNyBCU1QgMjAwMVtCQDE3OWU4Yg==\", " "opaque=\"Nzg5MWU3YjZiNDQ0YzI2Zg==\", " "stale=false, " "algorithm=md5, " "qop=\"auth, auth-int\""; sip_www_authenticate_t *wa; sip_authorization_t *au; sip_proxy_authenticate_t *pa; sip_proxy_authorization_t *pz; auth_challenge_t ac[1] = {{ sizeof(ac) }}; auth_response_t ar[1] = {{ sizeof(ar) }}; su_home_t home[1] = {{ sizeof(home) }}; auth_hexmd5_t sessionkey, hresponse; BEGIN(); TEST0(wa = sip_www_authenticate_make(home, challenge)); TEST_SIZE(auth_digest_challenge_get(home, ac, wa->au_params), 6); TEST_S(ac->ac_realm, "garage.sr.ntc.nokia.com"); TEST_S(ac->ac_nonce, "MjAwMS0wMS0yMSAxNTowODo1OA=="); TEST_S(ac->ac_algorithm, "MD5"); TEST_1(ac->ac_md5); TEST_1(!ac->ac_md5sess); TEST_1(!ac->ac_sha1); TEST_S(ac->ac_qop, "auth"); TEST_1(ac->ac_auth); TEST_1(!ac->ac_auth_int); TEST0(au = sip_authorization_make(home, response)); TEST_SIZE(auth_digest_response_get(home, ar, au->au_params), 5); TEST0(au = sip_authorization_make(home, rfc2617)); TEST_SIZE(auth_digest_response_get(home, ar, au->au_params), 10); TEST0(auth_digest_sessionkey(ar, sessionkey, "Circle Of Life") == 0); if (tstflags & tst_verbatim) printf("%s: sessionkey=\"%s\"\n", name, sessionkey); TEST0(strcmp(sessionkey, "939e7578ed9e3c518a452acee763bce9") == 0); TEST0(auth_digest_response(ar, hresponse, sessionkey, "GET", NULL, 0) == 0); if (tstflags & tst_verbatim) printf("%s: hresponse=\"%s\"\n", name, hresponse); TEST0(strcmp(hresponse, "6629fae49393a05397450978507c4ef1") == 0); TEST0(au = sip_authorization_make(home, indigo)); TEST_SIZE(auth_digest_response_get(home, ar, au->au_params), 12); TEST0(auth_digest_sessionkey(ar, sessionkey, "secret") == 0); TEST0(auth_digest_response(ar, hresponse, sessionkey, "BYE", NULL, 0) == 0); TEST0(strcmp(hresponse, "dd22a698b1a9510c4237c52e0e2cbfac") == 0); TEST0(pa = sip_proxy_authenticate_make(home, proxy_authenticate)); TEST_SIZE(auth_digest_challenge_get(home, ac, pa->au_params), 9); TEST_S(ac->ac_realm, "IndigoSw"); TEST_1(ac->ac_auth); TEST_1(ac->ac_auth_int); { char challenge[] = "Digest realm=\"opera.ntc.nokia.com\", " "nonce=\"InyiWI+qIdvDKkO2jFK7mg==\""; char credentials[] = "Digest username=\"samuel.privat.saturday@opera.ntc.nokia.com\", " "realm=\"opera.ntc.nokia.com\", nonce=\"InyiWI+qIdvDKkO2jFK7mg==\", " "algorithm=MD5, uri=\"sip:opera.ntc.nokia.com\", " "response=\"4b4edab897dafce8d9af4b37abcdc086\""; memset(ac, 0, sizeof(ac)); ac->ac_size = sizeof(ac); memset(ar, 0, sizeof(ar)); ar->ar_size = sizeof(ar); TEST0(pa = sip_www_authenticate_make(home, challenge)); TEST_SIZE(auth_digest_challenge_get(home, ac, pa->au_params), 2); TEST0(pz = sip_proxy_authorization_make(home, credentials)); TEST_SIZE(auth_digest_response_get(home, ar, pz->au_params), 7); ar->ar_md5 = ac->ac_md5 || ac->ac_algorithm == NULL; TEST0(!auth_digest_sessionkey(ar, sessionkey, "1123456789ABCDEF")); TEST0(!auth_digest_response(ar, hresponse, sessionkey, "REGISTER", NULL, 0)); TEST_S(hresponse, "4b4edab897dafce8d9af4b37abcdc086"); } if (0) { /* RFC 2069: that the username for this document is "Mufasa", and the password is "CircleOfLife". The first time the client requests the document, no Authorization header is sent, so the server responds with: HTTP/1.1 401 Unauthorized WWW-Authenticate: Digest realm="testrealm@host.com", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", opaque="5ccc069c403ebaf9f0171e9517f40e41" The client may prompt the user for the username and password, after which it will respond with a new request, including the following Authorization header: Authorization: Digest username="Mufasa", realm="testrealm@host.com", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", uri="/dir/index.html", response="e966c932a9242554e42c8ee200cec7f6", opaque="5ccc069c403ebaf9f0171e9517f40e41" */ char challenge[] = "Digest realm=\"testrealm@host.com\", " "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", " "opaque=\"5ccc069c403ebaf9f0171e9517f40e41\""; char rfc2069_cred[] = "Digest username=\"Mufasa\", " "realm=\"testrealm@host.com\", " "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", " "uri=\"/dir/index.html\", " "response=\"e966c932a9242554e42c8ee200cec7f6\", " "opaque=\"5ccc069c403ebaf9f0171e9517f40e41\""; memset(ac, 0, sizeof(ac)); ac->ac_size = sizeof(ac); memset(ar, 0, sizeof(ar)); ar->ar_size = sizeof(ar); TEST0(pa = sip_www_authenticate_make(home, challenge)); TEST_SIZE(auth_digest_challenge_get(home, ac, pa->au_params), 3); TEST0(pz = sip_proxy_authorization_make(home, rfc2069_cred)); TEST_SIZE(auth_digest_response_get(home, ar, pz->au_params), 6); ar->ar_md5 = ac->ac_md5 || ac->ac_algorithm == NULL; TEST_S(ar->ar_username, "Mufasa"); TEST0(!auth_digest_sessionkey(ar, sessionkey, "CircleOfLife")); TEST0(!auth_digest_response(ar, hresponse, sessionkey, "GET", NULL, 0)); TEST_S(hresponse, "e966c932a9242554e42c8ee200cec7f6"); } { char worldcom_chal[] = "Digest realm=\"WCOM\", nonce=\"ce2292f3f748fbe239bda9e852e8b986\""; char worldcom_cred[] = "Digest realm=\"WCOM\", username=\"jari\", " "nonce=\"ce2292f3f748fbe239bda9e852e8b986\", " "response=\"ea692d202019d41a75c70df4b2401e2f\", " "uri=\"sip:1234@209.132.126.82\""; memset(ac, 0, sizeof(ac)); ac->ac_size = sizeof(ac); memset(ar, 0, sizeof(ar)); ar->ar_size = sizeof(ar); TEST0(pa = sip_proxy_authenticate_make(home, worldcom_chal)); TEST_SIZE(auth_digest_challenge_get(home, ac, pa->au_params), 2); TEST0(pz = sip_proxy_authorization_make(home, worldcom_cred)); TEST_SIZE(auth_digest_response_get(home, ar, pz->au_params), 5); ar->ar_md5 = ac->ac_md5 || ac->ac_algorithm == NULL; TEST0(!auth_digest_sessionkey(ar, sessionkey, "pass")); TEST0(!auth_digest_response(ar, hresponse, sessionkey, "REGISTER", NULL, 0)); TEST_S(hresponse, "ea692d202019d41a75c70df4b2401e2f"); } { char etri_chal[] = "Digest realm=\"nokia-proxy\", domain=\"sip:194.2.188.133\", " "nonce=\"wB7JBwIb/XhtgfGp1VuPoQ==\", opaque=\"wkJxwA==\", " ", algorithm=MD5, qop=\"auth\""; char etri_cred[] = "Digest username=\"myhuh\", realm=\"nokia-proxy\", " "nonce=\"wB7JBwIb/XhtgfGp1VuPoQ==\", uri=\"sip:194.2.188.133\", " "response=\"32960a62bdc202171ca5a294dc229a6d\", " "opaque=\"wkJxwA==\"" /* , qop=\"auth\"" */; memset(ac, 0, sizeof(ac)); ac->ac_size = sizeof(ac); memset(ar, 0, sizeof(ar)); ar->ar_size = sizeof(ar); TEST0(pa = sip_proxy_authenticate_make(home, etri_chal)); TEST_SIZE(auth_digest_challenge_get(home, ac, pa->au_params), 8); TEST0(pz = sip_proxy_authorization_make(home, etri_cred)); TEST_SIZE(auth_digest_response_get(home, ar, pz->au_params), 6 /* 8 */); ar->ar_md5 = ac->ac_md5 || ac->ac_algorithm == NULL; TEST(auth_digest_sessionkey(ar, sessionkey, "myhuh"), 0); TEST(auth_digest_response(ar, hresponse, sessionkey, "REGISTER", NULL, 0), 0); TEST_S(hresponse, "32960a62bdc202171ca5a294dc229a6d"); } { char chal[] = "Digest realm=\"nokia-proxy\", domain=\"sip:10.21.32.63\", " "nonce=\"GjbLsrozHC6Lx95C57vGlw==\", opaque=\"HN22wQ==\", algorithm=MD5"; char cred[] = "digest username=\"test1\",realm=\"nokia-proxy\"," "nonce=\"GjbLsrozHC6Lx95C57vGlw==\",opaque=\"HN22wQ==\"," "uri=\"sip:10.21.32.63\",response=\"e86db25d96713482e35378504caaba6b\"," "algorithm=\"MD5\""; memset(ac, 0, sizeof(ac)); ac->ac_size = sizeof(ac); memset(ar, 0, sizeof(ar)); ar->ar_size = sizeof(ar); TEST0(pa = sip_proxy_authenticate_make(home, chal)); TEST_SIZE(auth_digest_challenge_get(home, ac, pa->au_params), 6); TEST0(pz = sip_proxy_authorization_make(home, cred)); { size_t n = auth_digest_response_get(home, ar, pz->au_params); TEST_SIZE(n, 8); } ar->ar_md5 = ac->ac_md5 || ac->ac_algorithm == NULL; TEST(auth_digest_sessionkey(ar, sessionkey, "test1"), 0); TEST(auth_digest_response(ar, hresponse, sessionkey, "REGISTER", NULL, 0), 0); TEST_S(hresponse, "db41913e8964dde69a1519739f35a302"); } { char challenge[] = "Digest realm=\"nokia-proxy\", domain=\"sip:194.2.188.133\", " "nonce=\"3wWGOvaWn3n+hFv8PK2ABQ==\", opaque=\"+GNywA==\", " "algorithm=MD5, qop=\"auth-int\""; char credentials[] = "Digest username=\"test\", realm=\"nokia-proxy\", " "nonce=\"3wWGOvaWn3n+hFv8PK2ABQ==\", " "cnonce=\"11RkhFg9EdaIRD36w0EMVA==\", opaque=\"+GNywA==\", " "uri=\"sip:3000@194.2.188.133\", algorithm=MD5, " "response=\"26e8b9aaacfca2d68770fab1ec04e2c7\", " "qop=auth-int, nc=00000001"; char data[] = "\n" "\n" "\n" "\n" "
\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "
\n" "
\n" "
\n"; memset(ac, 0, sizeof(ac)); ac->ac_size = sizeof(ac); memset(ar, 0, sizeof(ar)); ar->ar_size = sizeof(ar); TEST0(pa = sip_proxy_authenticate_make(home, challenge)); TEST_SIZE(auth_digest_challenge_get(home, ac, pa->au_params), 8); TEST0(pz = sip_proxy_authorization_make(home, credentials)); TEST_SIZE(auth_digest_response_get(home, ar, pz->au_params), 12); ar->ar_md5 = ac->ac_md5 || ac->ac_algorithm == NULL; TEST0(!auth_digest_sessionkey(ar, sessionkey, "test")); TEST0(!auth_digest_response(ar, hresponse, sessionkey, "REGISTER", data, strlen(data))); TEST_S(hresponse, "26e8b9aaacfca2d68770fab1ec04e2c7"); } su_home_deinit(home); END(); } #include msg_t *read_message(int flags, char const buffer[]) { int n, m; msg_t *msg; msg_iovec_t iovec[2]; n = strlen(buffer); if (n == 0) return NULL; msg = msg_create(sip_default_mclass(), flags); if (msg_recv_iovec(msg, iovec, 2, n, 1) < 0) { perror("msg_recv_iovec"); } memcpy(iovec->mv_base, buffer, n); msg_recv_commit(msg, n, 1); m = msg_extract(msg); if (m < 0) { fprintf(stderr, "test_auth_digest: parsing error\n"); return NULL; } return msg; } #define AUTH_MAGIC_T su_root_t #include static void test_callback(su_root_t *root, auth_status_t *as) { su_root_break(root); } static void init_as(auth_status_t *as) { memset(as, 0, sizeof *as); as->as_home->suh_size = (sizeof *as); su_home_init(as->as_home); as->as_method = "REGISTER"; as->as_status = 500; as->as_phrase = "Infernal Error"; } static void deinit_as(auth_status_t *as) { su_home_deinit(as->as_home); memset(as, 0, sizeof *as); } static void reinit_as(auth_status_t *as) { deinit_as(as); init_as(as); } /* Test digest authentication client and server */ int test_digest_client(void) { BEGIN(); { char challenge[] = PROTOCOL " 401 Unauthorized\r\n" "Call-ID:0e3dc2b2-dcc6-1226-26ac-258b5ce429ab\r\n" "CSeq:32439043 REGISTER\r\n" "From:surf3.ims3.so.noklab.net ;tag=I8hFdg0H3OK\r\n" "To:\r\n" "Via:SIP/2.0/UDP 10.21.36.70:23800;branch=z9hG4bKJjKGu9vIHqf;received=10.21.36.70;rport\r\n" "WWW-Authenticate:DIGEST algorithm=MD5,nonce=\"h7wIpP+atU+/+Zau5UwLMA==\",realm=\"ims3.so.noklab.net\"\r\n" "Content-Length:0\r\n" "Security-Server:digest\r\n" "r\n"; char request[] = "REGISTER sip:ims3.so.noklab.net " PROTOCOL "\r\n" "Via: SIP/2.0/UDP 10.21.36.70:23800;rport;branch=z9hG4bKRE18GFwa3AS\r\n" "Max-Forwards: 80\r\n" "From: surf3.ims3.so.noklab.net ;tag=I8hFdg0H3OK\r\n" "To: \r\n" "Call-ID: 0e3dc2b2-dcc6-1226-26ac-258b5ce429ab\r\n" "CSeq: 32439044 REGISTER\r\n" "Contact: \r\n" "Expires: 3600\r\n" "Supported: timer, 100rel\r\n" "Security-Client: digest\r\n" "Security-Verify: digest;d-ver=\"1234\"\r\n" "Content-Length: 0\r\n" "r\n"; msg_t *m1, *m2; sip_t *sip; auth_client_t *aucs = NULL; sip_request_t *rq; su_home_t *home; su_root_t *root; char *srcdir, *s, *testpasswd; auth_mod_t *am; auth_status_t as[1]; sip_www_authenticate_t *au; auth_challenger_t ach[1] = {{ 401, "Authorization required", sip_www_authenticate_class, sip_authentication_info_class }}; auth_challenger_t pach[1] = {{ 407, "Proxy Authorization required", sip_proxy_authenticate_class, sip_proxy_authentication_info_class }}; TEST_1(home = su_home_new(sizeof(*home))); TEST_1(m1 = read_message(MSG_DO_EXTRACT_COPY, challenge)); TEST_1(sip = sip_object(m1)); TEST_1(aucs == NULL); TEST(auc_challenge(&aucs, home, sip->sip_www_authenticate, sip_authorization_class), 1); TEST_1(aucs != NULL); msg_destroy(m1); TEST(auc_all_credentials(&aucs, "DIGEST", "\"ims3.so.noklab.net\"", "surf3.private@ims3.so.noklab.net", "1234"), 1); TEST_1(m2 = read_message(MSG_DO_EXTRACT_COPY, request)); TEST_1(sip = sip_object(m2)); TEST_P(sip->sip_authorization, NULL); TEST_1(rq = sip->sip_request); TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name, rq->rq_url, sip->sip_payload), 1); TEST_1(sip->sip_authorization); TEST_S(msg_params_find(sip->sip_authorization->au_params, "response="), "\"860f5ecc9990772e16937750ced9594d\""); TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name, (url_t *)"sip:surf3@ims3.so.noklab.net", sip->sip_payload), 1); TEST_1(sip->sip_authorization); TEST_S(msg_params_find(sip->sip_authorization->au_params, "response="), "\"9ce0d6a5869b4e09832d5b705453cbfc\""); srcdir = getenv("srcdir"); if (srcdir == NULL) { srcdir = su_strdup(home, argv0); if ((s = strrchr(srcdir, '/'))) *s = '\0'; else srcdir = "."; } TEST_1(testpasswd = su_sprintf(home, "%s/testpasswd", srcdir)); TEST_1(root = su_root_create(NULL)); TEST_1(am = auth_mod_create(NULL, AUTHTAG_METHOD("Digest"), AUTHTAG_REALM("ims3.so.noklab.net"), AUTHTAG_DB(testpasswd), AUTHTAG_OPAQUE("+GNywA=="), TAG_END())); init_as(as); auth_mod_check_client(am, as, sip->sip_authorization, ach); TEST(as->as_status, 401); TEST_1(au = sip_authorization_make(home, "Digest username=\"user1\", " "nonce=\"3wWGOvaWn3n+hFv8PK2ABQ==\", " "opaque=\"+GNywA==\", " "uri=\"sip:3000@194.2.188.133\", " "response=\"26e8b9aaacfca2d6" "8770fab1ec04e2c7\", " "realm=\"ims3.so.noklab.net\"")); reinit_as(as); auth_mod_check_client(am, as, au, ach); TEST(as->as_status, 401); { char const *username = au->au_params[0]; char const *nonce = au->au_params[1]; char const *opaque = au->au_params[2]; char const *uri = au->au_params[3]; char const *response = au->au_params[4]; char const *realm = au->au_params[5]; TEST_S(username, "username=\"user1\""); TEST_S(nonce, "nonce=\"3wWGOvaWn3n+hFv8PK2ABQ==\""); TEST_S(opaque, "opaque=\"+GNywA==\""); TEST_S(uri, "uri=\"sip:3000@194.2.188.133\""); TEST_S(response, "response=\"26e8b9aaacfca2d68770fab1ec04e2c7\""); TEST(msg_params_remove((msg_param_t *)au->au_params, "username"), 1); reinit_as(as); auth_mod_check_client(am, as, au, ach); TEST(as->as_status, 400); msg_params_add(home, (msg_param_t **)&au->au_params, username); TEST(msg_params_remove((msg_param_t *)au->au_params, "nonce"), 1); reinit_as(as); auth_mod_check_client(am, as, au, ach); TEST(as->as_status, 400); msg_params_add(home, (msg_param_t **) &au->au_params, nonce); TEST(msg_params_remove((msg_param_t *)au->au_params, "opaque"), 1); reinit_as(as); auth_mod_check_client(am, as, au, ach); TEST(as->as_status, 401); /* We use opaque to match authorization */ msg_params_add(home, (msg_param_t **) &au->au_params, opaque); TEST(msg_params_remove((msg_param_t *)au->au_params, "uri"), 1); reinit_as(as); auth_mod_check_client(am, as, au, ach); TEST(as->as_status, 400); msg_params_add(home, (msg_param_t **) &au->au_params, uri); TEST(msg_params_remove((msg_param_t *)au->au_params, "response"), 1); reinit_as(as); auth_mod_check_client(am, as, au, ach); TEST(as->as_status, 400); msg_params_add(home, (msg_param_t **)&au->au_params, response); TEST(msg_params_remove((msg_param_t *)au->au_params, "realm"), 1); reinit_as(as); auth_mod_check_client(am, as, au, ach); TEST(as->as_status, 401); /* au is ignored by auth_module */ msg_params_add(home, (msg_param_t **)&au->au_params, realm); reinit_as(as); auth_mod_check_client(am, as, au, ach); TEST(as->as_status, 401); } as->as_response = (msg_header_t *) sip_www_authenticate_make(as->as_home, "Unknown realm=\"huu haa\""); TEST_1(as->as_response); TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response, sip_authorization_class), 1); aucs = NULL; reinit_as(as); auth_mod_check_client(am, as, NULL, ach); TEST(as->as_status, 401); TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response, sip_authorization_class), 1); reinit_as(as); TEST(auc_all_credentials(&aucs, "Digest", "\"ims3.so.noklab.net\"", "user1", "secret"), 1); msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization); TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name, (url_t *)"sip:surf3@ims3.so.noklab.net", sip->sip_payload), 1); TEST_1(sip->sip_authorization); TEST_1(msg_params_find(sip->sip_authorization->au_params, "cnonce=") == 0); TEST_1(msg_params_find(sip->sip_authorization->au_params, "nc=") == 0); auth_mod_check_client(am, as, sip->sip_authorization, ach); TEST(as->as_status, 0); TEST_1(as->as_info); /* challenge for next round */ auth_mod_destroy(am); aucs = NULL; TEST_1(am = auth_mod_create(NULL, AUTHTAG_METHOD("Digest"), AUTHTAG_REALM("ims3.so.noklab.net"), AUTHTAG_DB(testpasswd), AUTHTAG_ALGORITHM("MD5-sess"), AUTHTAG_QOP("auth"), AUTHTAG_OPAQUE("opaque=="), TAG_END())); reinit_as(as); auth_mod_check_client(am, as, NULL, ach); TEST(as->as_status, 401); { msg_auth_t *au = (msg_auth_t *)as->as_response; int i; char *equal; if (au->au_params) for (i = 0; au->au_params[i]; i++) { if (su_casenmatch(au->au_params[i], "realm=", 6)) continue; equal = strchr(au->au_params[i], '='); if (equal) msg_unquote(equal + 1, equal + 1); } TEST(auc_challenge(&aucs, home, au, sip_authorization_class), 1); reinit_as(as); } TEST(auc_all_credentials(&aucs, "Digest", "\"ims3.so.noklab.net\"", "user1", "secret"), 1); msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization); TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name, (url_t *)"sip:surf3@ims3.so.noklab.net", sip->sip_payload), 1); TEST_1(sip->sip_authorization); auth_mod_check_client(am, as, sip->sip_authorization, ach); TEST(as->as_status, 0); TEST_1(as->as_info == NULL); /* No challenge for next round */ /* Test with changed payload */ reinit_as(as); as->as_body = "foo"; as->as_bodylen = 3; auth_mod_check_client(am, as, sip->sip_authorization, ach); TEST(as->as_status, 0); reinit_as(as); aucs = NULL; /* Test without opaque */ { msg_auth_t *au; char const *opaque; auth_mod_check_client(am, as, NULL, ach); TEST(as->as_status, 401); au = (void *)msg_header_dup(home, as->as_response); TEST_1(au); TEST_1(msg_params_find_slot((msg_param_t *)au->au_params, "opaque")); opaque = *msg_params_find_slot((msg_param_t *)au->au_params, "opaque"); TEST(msg_params_remove((msg_param_t *)au->au_params, "opaque"), 1); TEST(auc_challenge(&aucs, home, au, sip_authorization_class), 1); TEST(auc_all_credentials(&aucs, "Digest", "\"ims3.so.noklab.net\"", "user1", "secret"), 1); msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization); TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name, (url_t *)"sip:surf3@ims3.so.noklab.net", sip->sip_payload), 1); TEST_1(sip->sip_authorization); msg_params_add(home, (msg_param_t **)&sip->sip_authorization->au_params, opaque); reinit_as(as); auth_mod_check_client(am, as, sip->sip_authorization, ach); TEST(as->as_status, 0); } reinit_as(as); auth_mod_destroy(am); aucs = NULL; /* Test without realm */ { msg_auth_t *au; TEST_1(am = auth_mod_create(NULL, AUTHTAG_METHOD("Digest"), AUTHTAG_DB(testpasswd), AUTHTAG_ALGORITHM("MD5-sess"), AUTHTAG_QOP("auth"), AUTHTAG_OPAQUE("opaque=="), TAG_END())); as->as_realm = NULL; auth_mod_check_client(am, as, NULL, ach); TEST(as->as_status, 500); as->as_realm = "ims3.so.noklab.net"; auth_mod_check_client(am, as, NULL, ach); TEST(as->as_status, 401); au = (void *)msg_header_dup(home, as->as_response); TEST_1(au); TEST(auc_challenge(&aucs, home, au, sip_authorization_class), 1); TEST(auc_all_credentials(&aucs, "Digest", "\"ims3.so.noklab.net\"", "user1", "secret"), 1); msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization); TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name, (url_t *)"sip:surf3@ims3.so.noklab.net", sip->sip_payload), 1); TEST_1(sip->sip_authorization); reinit_as(as); as->as_realm = "ims3.so.noklab.net"; auth_mod_check_client(am, as, sip->sip_authorization, ach); TEST(as->as_status, 0); } reinit_as(as); auth_mod_destroy(am); aucs = NULL; /* Test nextnonce */ { char const *nonce1, *nextnonce, *nonce2; TEST_1(am = auth_mod_create(NULL, AUTHTAG_METHOD("Digest"), AUTHTAG_REALM("ims3.so.noklab.net"), AUTHTAG_DB(testpasswd), AUTHTAG_ALGORITHM("MD5"), AUTHTAG_QOP("auth-int"), AUTHTAG_EXPIRES(90), /* Generate nextnonce if NEXT_EXPIRES in nonzero */ AUTHTAG_NEXT_EXPIRES(900), TAG_END())); reinit_as(as); auth_mod_check_client(am, as, NULL, ach); TEST(as->as_status, 401); TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response, sip_authorization_class), 1); TEST(auc_all_credentials(&aucs, "Digest", "\"ims3.so.noklab.net\"", "user1", "secret"), 1); msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization); TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name, (url_t *)"sip:surf3@ims3.so.noklab.net", sip->sip_payload), 1); TEST_1(sip->sip_authorization); TEST_1(nonce1 = msg_header_find_param(sip->sip_authorization->au_common, "nonce")); reinit_as(as); auth_mod_check_client(am, as, sip->sip_authorization, ach); TEST(as->as_status, 0); /* We got authentication-info */ TEST_1(as->as_info); /* It contains nextnonce */ TEST_1(nextnonce = msg_header_find_param(as->as_info->sh_common, "nextnonce")); /* Store it in authenticator */ TEST(auc_info(&aucs, (msg_auth_info_t const *)as->as_info, sip_authorization_class), 1); msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization); TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name, (url_t *)"sip:surf3@ims3.so.noklab.net", sip->sip_payload), 1); TEST_1(sip->sip_authorization); TEST_1(nonce2 = msg_header_find_param(sip->sip_authorization->au_common, "nonce")); /* * Make sure that server-side sends nextnonce in Authentication-info * header, nextnonce differs from nonce sent in Challenge */ TEST_1(strcmp(nonce1, nextnonce)); /* And client-side uses it */ TEST_S(nonce2, nextnonce); auth_mod_destroy(am); aucs = NULL; } TEST_1(am = auth_mod_create(NULL, AUTHTAG_METHOD("Digest"), AUTHTAG_REALM("ims3.so.noklab.net"), AUTHTAG_DB(testpasswd), AUTHTAG_ALGORITHM("MD5-sess"), AUTHTAG_QOP("auth-int"), TAG_END())); reinit_as(as); auth_mod_check_client(am, as, NULL, ach); TEST(as->as_status, 401); TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response, sip_authorization_class), 1); TEST(auc_all_credentials(&aucs, "Digest", "\"ims3.so.noklab.net\"", "user1", "secret"), 1); msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization); TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name, (url_t *)"sip:surf3@ims3.so.noklab.net", sip->sip_payload), 1); TEST_1(sip->sip_authorization); reinit_as(as); auth_mod_check_client(am, as, sip->sip_authorization, ach); TEST(as->as_status, 0); aucs = NULL; /* Test HA1+Digest */ reinit_as(as); auth_mod_check_client(am, as, NULL, ach); TEST(as->as_status, 401); TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response, sip_authorization_class), 1); TEST(auc_all_credentials(&aucs, "HA1+Digest", "\"ims3.so.noklab.net\"", "user1", "HA1+c0890ff7a4fadc50c45f392ec4312965"), 1); msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization); TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name, (url_t *)"sip:surf3@ims3.so.noklab.net", sip->sip_payload), 1); TEST_1(sip->sip_authorization); reinit_as(as); auth_mod_check_client(am, as, sip->sip_authorization, ach); TEST(as->as_status, 0); auth_mod_destroy(am); aucs = NULL; TEST_1(am = auth_mod_create(NULL, AUTHTAG_METHOD("Digest"), AUTHTAG_REALM("ims3.so.noklab.net"), AUTHTAG_DB(testpasswd), AUTHTAG_ALGORITHM("MD5-sess"), AUTHTAG_QOP("auth,auth-int"), AUTHTAG_FORBIDDEN(1), AUTHTAG_ANONYMOUS(1), AUTHTAG_MAX_NCOUNT(1), TAG_END())); reinit_as(as); auth_mod_check_client(am, as, NULL, ach); TEST(as->as_status, 401); TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response, sip_authorization_class), 1); TEST(auc_all_credentials(&aucs, "Digest", "\"ims3.so.noklab.net\"", "user1", "secret"), 1); msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization); TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name, (url_t *)"sip:surf3@ims3.so.noklab.net", sip->sip_payload), 1); TEST_1(sip->sip_authorization); reinit_as(as); auth_mod_check_client(am, as, sip->sip_authorization, ach); TEST(as->as_status, 0); au = (void*)msg_header_copy(msg_home(m2), (void*)sip->sip_authorization); /* Test with invalid qop (bug #2329) */ msg_params_replace(msg_home(m2), (void *)&au->au_params, "qop=\"auth,auth-int\""); reinit_as(as); auth_mod_check_client(am, as, au, ach); TEST(as->as_status, 400); reinit_as(as); as->as_body = "foo"; as->as_bodylen = 3; auth_mod_check_client(am, as, sip->sip_authorization, ach); TEST(as->as_status, 403); reinit_as(as); as->as_body = ""; as->as_bodylen = 0; as->as_method = "OPTIONS"; auth_mod_check_client(am, as, sip->sip_authorization, ach); TEST(as->as_status, 403); /* Test staleness check */ offset = 2 * 3600; reinit_as(as); auth_mod_check_client(am, as, sip->sip_authorization, ach); TEST(as->as_status, 401); TEST_1(au = (void *)as->as_response); TEST_1(au->au_params); TEST_S(msg_params_find(au->au_params, "stale="), "true"); TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response, sip_authorization_class), 1); msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization); TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name, (url_t *)"sip:surf3@ims3.so.noklab.net", sip->sip_payload), 1); TEST_1(sip->sip_authorization); TEST_S(msg_header_find_param(sip->sip_authorization->au_common, "nc="), "00000001"); reinit_as(as); auth_mod_check_client(am, as, sip->sip_authorization, ach); TEST(as->as_status, 0); /* Test nonce count check */ msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization); TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name, (url_t *)"sip:surf3@ims3.so.noklab.net", sip->sip_payload), 1); TEST_1(sip->sip_authorization); TEST_S(msg_header_find_param(sip->sip_authorization->au_common, "nc="), "00000002"); reinit_as(as); auth_mod_check_client(am, as, sip->sip_authorization, ach); TEST(as->as_status, 401); TEST_1(au = (void *)as->as_response); TEST_1(au->au_params); TEST_S(msg_params_find(au->au_params, "stale="), "true"); aucs = NULL; /* Test anonymous operation */ reinit_as(as); auth_mod_check_client(am, as, NULL, ach); TEST(as->as_status, 401); TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response, sip_authorization_class), 1); reinit_as(as); TEST(auc_all_credentials(&aucs, "Digest", "\"ims3.so.noklab.net\"", "anonymous", ""), 1); msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization); TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name, (url_t *)"sip:surf3@ims3.so.noklab.net", sip->sip_payload), 1); TEST_1(sip->sip_authorization); auth_mod_check_client(am, as, sip->sip_authorization, ach); TEST(as->as_status, 0); auth_mod_destroy(am); aucs = NULL; /* Test empty realm */ TEST_1(am = auth_mod_create(root, AUTHTAG_METHOD("Digest"), AUTHTAG_REALM(""), AUTHTAG_DB(testpasswd), TAG_END())); reinit_as(as); auth_mod_check_client(am, as, NULL, ach); TEST(as->as_status, 401); TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response, sip_authorization_class), 1); reinit_as(as); TEST(auc_all_credentials(&aucs, "Digest", "\"\"", "user1", "secret"), 1); msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization); TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name, (url_t *)"sip:surf3@ims3.so.noklab.net", sip->sip_payload), 1); TEST_1(sip->sip_authorization); auth_mod_check_client(am, as, sip->sip_authorization, ach); TEST(as->as_status, 0); aucs = NULL; reinit_as(as); auth_mod_check_client(am, as, NULL, pach); TEST(as->as_status, 407); TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response, sip_proxy_authorization_class), 1); reinit_as(as); TEST(auc_credentials(&aucs, as->as_home, "Digest:\"\":user1:secret"), 1); msg_header_remove(m2, (void *)sip, (void *)sip->sip_proxy_authorization); TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name, (url_t *)"sip:surf3@ims3.so.noklab.net", sip->sip_payload), 1); TEST_1(sip->sip_proxy_authorization); auth_mod_check_client(am, as, sip->sip_proxy_authorization, pach); TEST(as->as_status, 0); auth_mod_destroy(am); aucs = NULL; /* Test Basic authentication scheme */ TEST_1(am = auth_mod_create(root, AUTHTAG_METHOD("Basic"), AUTHTAG_REALM("ims3.so.noklab.net"), AUTHTAG_DB(testpasswd), TAG_END())); reinit_as(as); auth_mod_check_client(am, as, NULL, ach); TEST(as->as_status, 401); TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response, sip_authorization_class), 1); reinit_as(as); TEST(auc_all_credentials(&aucs, "Basic", "\"ims3.so.noklab.net\"", "user1", "secret"), 1); msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization); TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name, (url_t *)"sip:surf3@ims3.so.noklab.net", sip->sip_payload), 1); TEST_1(sip->sip_authorization); auth_mod_check_client(am, as, sip->sip_authorization, ach); TEST(as->as_status, 0); aucs = NULL; reinit_as(as); auth_mod_check_client(am, as, NULL, ach); TEST(as->as_status, 401); TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response, sip_authorization_class), 1); reinit_as(as); TEST(auc_all_credentials(&aucs, "Basic", "\"ims3.so.noklab.net\"", "very-long-user-name-that-surely-exceeds-the-static-buffer", "at-least-when-used-with-the-even-longer-password"), 1); msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization); TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name, (url_t *)"sip:surf3@ims3.so.noklab.net", sip->sip_payload), 1); TEST_1(sip->sip_authorization); auth_mod_check_client(am, as, sip->sip_authorization, ach); TEST(as->as_status, 0); auth_mod_destroy(am); deinit_as(as); aucs = NULL; /* Test client with two challenges */ au = sip_www_authenticate_make( NULL, "Digest realm=\"test-realm\", " "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", " "opaque=\"5ccc069c403ebaf9f0171e9517f40e41\""); au->au_next = sip_www_authenticate_make( NULL, "Not-Digest realm=\"test-realm\", " "zip=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", " "zap=\"5ccc069c403ebaf9f0171e9517f40e41\""); TEST_1(auc_challenge(&aucs, home, (msg_auth_t *)au, sip_authorization_class) >= 1); TEST_1(auc_all_credentials(&aucs, "Digest", "\"test-realm\"", "user", "pass")); msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization); TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name, (url_t *)"sip:surf3@ims3.so.noklab.net", sip->sip_payload), 1); TEST_1(sip->sip_authorization); aucs = NULL; /* Test asynchronous operation */ aucs = NULL; TEST_1(am = auth_mod_create(root, AUTHTAG_METHOD("Delayed+Digest"), AUTHTAG_REALM("ims3.so.noklab.net"), AUTHTAG_DB(testpasswd), AUTHTAG_ALGORITHM("MD5-sess"), AUTHTAG_QOP("auth-int"), AUTHTAG_REMOTE((void *)"http://localhost:9"), TAG_END())); reinit_as(as); as->as_callback = test_callback; as->as_magic = root; auth_mod_check_client(am, as, NULL, ach); TEST(as->as_status, 100); su_root_run(root); TEST(as->as_status, 401); TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response, sip_authorization_class), 1); reinit_as(as); as->as_callback = test_callback; as->as_magic = root; TEST(auc_all_credentials(&aucs, "Digest", "\"ims3.so.noklab.net\"", "user1", "secret"), 1); msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization); TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name, (url_t *)"sip:surf3@ims3.so.noklab.net", sip->sip_payload), 1); TEST_1(sip->sip_authorization); auth_mod_check_client(am, as, sip->sip_authorization, ach); TEST(as->as_status, 100); su_root_run(root); TEST(as->as_status, 0); auth_mod_destroy(am); aucs = NULL; deinit_as(as); msg_destroy(m2); su_root_destroy(root); su_home_unref(home); } END(); } int test_auth_client(void) { BEGIN(); { char challenge[] = PROTOCOL " 401 Unauthorized\r\n" "Call-ID:0e3dc2b2-dcc6-1226-26ac-258b5ce429ab\r\n" "CSeq:32439043 REGISTER\r\n" "From:surf3.ims3.so.noklab.net ;tag=I8hFdg0H3OK\r\n" "To:\r\n" "Via:SIP/2.0/UDP 10.21.36.70:23800;branch=z9hG4bKJjKGu9vIHqf;received=10.21.36.70;rport\r\n" "WWW-Authenticate:DIGEST algorithm=MD5,nonce=\"h7wIpP+atU+/+Zau5UwLMA==\",realm=\"[::1]\"\r\n" "Proxy-Authenticate:DIGEST algorithm=MD5,nonce=\"h7wIpP+atU+/+Zau5UwLMA==\",realm=\"\\\"realm\\\"\"\r\n" "Content-Length:0\r\n" "Security-Server:digest\r\n" "r\n"; su_home_t *home; msg_t *msg; sip_t *sip; auth_client_t *aucs = NULL; TEST_1(home = su_home_new(sizeof(*home))); TEST_1(msg = read_message(MSG_DO_EXTRACT_COPY, challenge)); TEST_1(sip = sip_object(msg)); TEST_1(aucs == NULL); TEST(auc_challenge(&aucs, home, sip->sip_www_authenticate, sip_authorization_class), 1); TEST_1(aucs != NULL); TEST(auc_credentials(&aucs, home, "Digest:\"[::1]\":user:pass"), 1); TEST(auc_challenge(&aucs, home, sip->sip_proxy_authenticate, sip_proxy_authorization_class), 1); TEST(auc_credentials(&aucs, home, "Digest:\"\\\"realm\\\"\":user:pass"), 1); msg_destroy(msg); su_home_unref(home); } END(); } #if HAVE_FLOCK #include #endif #include char tmppasswd[] = "/tmp/test_auth_digest.XXXXXX"; #include static void rmtmp(void) { if (tmppasswd[0]) unlink(tmppasswd); } char const passwd[] = "# Comment\n" "malformed line\n" "user1:secret:\n" /* user2 has password "secret", too */ "user2:realm:4cbc2aff0b5b2b33675c0731c0db1c14\n" /* duplicate user. fun */ "user1:secret:realm\n" /* empty line */ "\n"; /* Test digest authentication client and server */ int test_module_io(void) { auth_mod_t *am, am0[1]; auth_passwd_t *apw, *apw2; int tmpfd; BEGIN(); #ifndef _WIN32 tmpfd = mkstemp(tmppasswd); TEST_1(tmpfd != -1); #else tmpfd = open(tmppasswd, O_WRONLY); TEST_1(tmpfd != -1); #endif atexit(rmtmp); /* Make sure temp file is unlinked */ TEST_SIZE(write(tmpfd, passwd, strlen(passwd)), strlen(passwd)); TEST(close(tmpfd), 0); /* Test file reading operation */ am = auth_mod_create(NULL, AUTHTAG_METHOD("Digest"), AUTHTAG_REALM("realm"), AUTHTAG_DB(tmppasswd), AUTHTAG_ALGORITHM("MD5-sess"), AUTHTAG_QOP("auth-int"), TAG_END()); TEST_1(am); apw = auth_mod_getpass(am, "user1", NULL); TEST_1(apw); TEST_S(apw->apw_realm, "realm"); apw = auth_mod_getpass(am, "user2", NULL); TEST_1(apw); TEST_S(apw->apw_hash, "4cbc2aff0b5b2b33675c0731c0db1c14"); apw2 = apw; *am0 = *am; TEST_1(auth_readdb_if_needed(am) == 0); apw = auth_mod_getpass(am, "user2", NULL); TEST_1(apw); TEST_P(apw, apw2); apw = auth_mod_addpass(am, "user3", "realm"); TEST_1(apw); /* user3 with password fisu */ apw->apw_hash = "056595147630692bb29d1855089bc95b"; { char const user3[] = "user3:realm:7df96b4718bd933af4883c8b73c96318\n"; tmpfd = open(tmppasswd, O_WRONLY|O_APPEND, 0); TEST_1(tmpfd != -1); /* user3 with password fish */ TEST_SIZE(write(tmpfd, user3, strlen(user3)), strlen(user3)); TEST_1(close(tmpfd) == 0); } #if HAVE_FLOCK /* Test flock(). */ tmpfd = open(tmppasswd, O_RDONLY); TEST_1(flock(tmpfd, LOCK_EX) != -1); TEST_1(auth_readdb_if_needed(am) == 0); /* there should be no changes in user table */ apw = auth_mod_getpass(am, "user2", NULL); TEST_1(apw); TEST_P(apw, apw2); TEST_1(flock(tmpfd, LOCK_UN) != -1); #endif TEST_1(auth_readdb_if_needed(am) == 0); apw = auth_mod_getpass(am, "user2", "realm"); TEST_1(apw); TEST_1(apw != apw2); /* Local user3 overrides non-local */ apw = auth_mod_getpass(am, "user3", "realm"); TEST_1(apw); TEST_S(apw->apw_hash, "7df96b4718bd933af4883c8b73c96318"); /* Test truncating */ { char const user1[] = "user1:secret:\n"; tmpfd = open(tmppasswd, O_WRONLY|O_TRUNC, 0); TEST_1(tmpfd != -1); TEST_SIZE(write(tmpfd, user1, strlen(user1)), strlen(user1)); TEST_1(close(tmpfd) == 0); } TEST_1(auth_readdb_if_needed(am) == 0); apw = auth_mod_getpass(am, "user2", "realm"); TEST_1(apw == NULL); /* Non-local user3 is kept in database */ apw = auth_mod_getpass(am, "user3", "realm"); TEST_1(apw); TEST_S(apw->apw_hash, "056595147630692bb29d1855089bc95b"); auth_mod_destroy(am); if (unlink(tmppasswd) == 0) tmppasswd[0] = '\0'; END(); } #include extern su_log_t iptsec_log[]; static void usage(int exitcode) { fprintf(stderr, "usage: %s [-v] [-a] [-l n]\n", name); exit(exitcode); } int main(int argc, char *argv[]) { int retval = 0; int i; extern void (*_su_time)(su_time_t *tv); _su_time = offset_time; argv0 = argv[0]; su_init(); for (i = 1; argv[i]; i++) { if (strcmp(argv[i], "-v") == 0) tstflags |= tst_verbatim; else if (strcmp(argv[i], "-a") == 0) tstflags |= tst_abort; else if (strncmp(argv[i], "-l", 2) == 0) { int level = 3; char *rest = NULL; if (argv[i][2]) level = strtol(argv[i] + 2, &rest, 10); else if (argv[i + 1]) level = strtol(argv[i + 1], &rest, 10), i++; else level = 3, rest = ""; if (rest == NULL || *rest) usage(1); su_log_set_level(iptsec_log, level); } else { usage(1); } } if ((TSTFLAGS & tst_verbatim)) su_log_soft_set_level(iptsec_log, 9); else su_log_soft_set_level(iptsec_log, 0); retval |= test_digest(); retval |= test_digest_client(); retval |= test_auth_client(); retval |= test_module_io(); su_deinit(); return retval; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/iptsec/testpasswd000066400000000000000000000002051223300710500231620ustar00rootroot00000000000000user1:secret: user2:fish: very-long-user-name-that-surely-exceeds-the-static-buffer:at-least-when-used-with-the-even-longer-password:sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/000077500000000000000000000000001223300710500203405ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/ChangeLog000066400000000000000000000026401223300710500221140ustar00rootroot000000000000002006-01-17 Martti Mela * msg_mime.c: defines for Mac OS X (which are lacking EBADMSG). 2005-11-08 Pekka Pessi * Renamed msg_test.c as test_msg.c. * Renamed msg_test_class.[hc] as test_class.[hc], msg_test_protos.h(.in) as test_protos.h(.in), msg_test_table.c(.in) as test_table.c(.in). 2005-10-12 Pekka Pessi * Fixed msg_home() macro. M ./libsofia-sip-ua/msg/msg.h -1 +1 2005-10-10 Pekka Pessi * Dox fix to msg_header_replace(). M ./libsofia-sip-ua/msg/msg_parser.c -2 +3 2005-08-15 Kai Vehmanen * Makefile.am: Do not include msg_test_class.o in libmsg. 2005-08-01 Pekka Pessi * msg_mime.c: Returning -2 from msg_accept_any_d() if the list is empty. * msg_internal.h, msg_mclass.h, msg_mclass.c, msg_parser.awk: Added header-specific flags in parser table for msg_extract_errors(). * msg.h, msg.c: Added msg_extract_errors(). * msg_parser.c: Using header-specific flags to classify parsing errors with msg_extract_errors(). Added support for apndlist headers. * msg_header.h: Added support for apndlist headers. * msg_mime.c: Various Accept* headers are now apndlist meaning that they are printed on single line by default. 2005-07-18 Kai Vehmanen * Initial import of the module to Sofia-SIP tree. sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/Doxyfile.in000066400000000000000000000010731223300710500224540ustar00rootroot00000000000000PROJECT_NAME = "msg" OUTPUT_DIRECTORY = ../docs/html/msg INPUT = @srcdir@/msg.docs @srcdir@/sofia-sip sofia-sip @srcdir@ . @INCLUDE_PATH = . @srcdir@ @INCLUDE = ../docs/Doxyfile.conf @INCLUDE = ../sip/sip.doxyaliases EXCLUDE_PATTERNS += msg_test*.h msg_test*.c TAGFILES += ../docs/ipt.doxytags=../ipt \ ../docs/su.doxytags=../su \ ../docs/sip.doxytags=../sip \ ../docs/nta.doxytags=../nta \ ../docs/http.doxytags=../http GENERATE_TAGFILE = ../docs/msg.doxytags IMAGE_PATH += @srcdir@/../sip/images sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/Makefile.am000066400000000000000000000072351223300710500224030ustar00rootroot00000000000000# # Makefile.am for msg module # # Copyright (C) 2005,2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # ---------------------------------------------------------------------- # Header paths INCLUDES = -I$(srcdir)/../url -I../url \ -I$(srcdir)/../bnf -I../bnf \ -I$(srcdir)/../su -I../su # ---------------------------------------------------------------------- # Build targets noinst_LTLIBRARIES = libmsg.la noinst_LIBRARIES = libtest_msg.a check_PROGRAMS = msg_name_hash test_msg # ---------------------------------------------------------------------- # Rules for building the targets GENERATED_H = sofia-sip/msg_protos.h sofia-sip/msg_mime_protos.h PUBLIC_H = sofia-sip/msg.h sofia-sip/msg_header.h \ sofia-sip/msg_types.h sofia-sip/msg_mclass.h \ sofia-sip/msg_mclass_hash.h sofia-sip/msg_parser.h \ sofia-sip/msg_addr.h sofia-sip/msg_date.h \ sofia-sip/msg_buffer.h sofia-sip/msg_tag_class.h \ sofia-sip/msg_mime.h INTERNAL_H = msg_internal.h test_class.h nobase_include_sofia_HEADERS = \ $(GENERATED_H) $(PUBLIC_H) GENERATED_HC = $(GENERATED_H) msg_mime_table.c test_table.c test_protos.h BUILT_SOURCES = $(GENERATED_HC) libmsg_la_SOURCES = msg_internal.h \ msg.c msg_tag.c msg_inlined.c \ msg_mime.c msg_mime_table.c \ msg_header_copy.c msg_header_make.c \ msg_parser.c msg_mclass.c msg_parser_util.c \ msg_basic.c msg_generic.c msg_date.c msg_auth.c COVERAGE_INPUT = $(libmsg_la_SOURCES) $(include_sofia_HEADERS) libtest_msg_a_SOURCES = test_class.c test_class.h \ test_table.c test_inlined.c test_protos.h LDADD = libtest_msg.a libmsg.la \ ../bnf/libbnf.la \ ../url/liburl.la \ ../ipt/libipt.la \ ../su/libsu.la test_msg_LDFLAGS = -static msg_name_hash_LDFLAGS = -static # ---------------------------------------------------------------------- # Install and distribution rules dist_pkgdata_SCRIPTS = msg_parser.awk EXTRA_DIST = msg.docs \ sofia-sip/msg_mime_protos.h.in \ sofia-sip/msg_protos.h.in \ msg_mime_table.c.in \ test_protos.h.in \ test_table.c.in # ---------------------------------------------------------------------- # Tests TESTS = test_msg # ---------------------------------------------------------------------- # Sofia specific rules include $(top_srcdir)/rules/sofia.am MSG_PARSER_AWK = $(srcdir)/msg_parser.awk AWK_MSG_AWK = LC_ALL=C $(AWK) -f $(MSG_PARSER_AWK) ${GENERATED_HC}: ${MSG_PARSER_AWK} Makefile.am TEST_CLASS_H = ${srcdir}/test_class.h test_protos.h test_table.c: ${TEST_CLASS_H} test_protos.h: ${srcdir}/test_protos.h.in $(AWK_MSG_AWK) module=msg_test NO_MIDDLE=1 NO_LAST=1 \ PR=$@ TEMPLATE=${srcdir}/test_protos.h.in ${TEST_CLASS_H} test_table.c: ${srcdir}/test_table.c.in $(AWK_MSG_AWK) module=msg_test prefix=msg \ MC_HASH_SIZE=127 multipart=msg_multipart \ PT=$@ TEMPLATE=${srcdir}/test_table.c.in ${TEST_CLASS_H} SS_MIME_H = ${srcdir}/sofia-sip/msg_mime.h sofia-sip/msg_protos.h sofia-sip/msg_mime_protos.h: ${SS_MIME_H} msg_mime_table.c: ${SS_MIME_H} sofia-sip/msg_protos.h: ${srcdir}/sofia-sip/msg_protos.h.in @-mkdir sofia-sip 2>/dev/null || true $(AWK_MSG_AWK) module=msg NO_FIRST=1 NO_MIDDLE=1 \ PR=$@ TEMPLATE=${srcdir}/sofia-sip/msg_protos.h.in \ ${SS_MIME_H} sofia-sip/msg_mime_protos.h: ${srcdir}/sofia-sip/msg_mime_protos.h.in @-mkdir sofia-sip 2>/dev/null || true $(AWK_MSG_AWK) module=msg NO_FIRST=1 NO_LAST=1 \ PR=$@ TEMPLATE=${srcdir}/sofia-sip/msg_mime_protos.h.in \ ${SS_MIME_H} msg_mime_table.c: ${srcdir}/msg_mime_table.c.in $(AWK_MSG_AWK) module=msg_multipart \ tprefix=msg prefix=mp MC_HASH_SIZE=127 MC_SHORT_SIZE=26 \ PT=$@ TEMPLATE=${srcdir}/msg_mime_table.c.in \ ${SS_MIME_H} sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/Makefile.in000066400000000000000000001502671223300710500224200ustar00rootroot00000000000000# Makefile.in generated by automake 1.14 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 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 msg module # # Copyright (C) 2005,2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # ---------------------------------------------------------------------- # Header paths # common Makefile targets for libsofia-sip-ua(-glib) modules # ---------------------------------------------------------- # # run tests with valgrind # # Copyright (C) 2007 Nokia Corporation. # 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 file contains free software from Makefile.in by the Free Software # Foundation: # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 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. # # Generate lcov output # # # Copyright (C) 2007 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # # Silent compilation w/ Automake 1.9 or 1.10 # ---------------------------------------------------------- # Automake 1.9.6 is not clever enough to override suffix rules within if # if SOFIA_COMPILE_SILENT VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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@ check_PROGRAMS = msg_name_hash$(EXEEXT) test_msg$(EXEEXT) TESTS = test_msg$(EXEEXT) DIST_COMMON = $(top_srcdir)/rules/sofia.am \ $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am \ $(top_srcdir)/rules/silent.am $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(srcdir)/Doxyfile.in \ $(dist_pkgdata_SCRIPTS) $(top_srcdir)/depcomp \ $(nobase_include_sofia_HEADERS) $(top_srcdir)/test-driver \ ChangeLog # Use with --enable-ndebug @NDEBUG_TRUE@am__append_1 = -DNDEBUG @HAVE_GENPNG_TRUE@@HAVE_LCOV_TRUE@am__append_2 = --frames @HAVE_LCOV_TRUE@am__append_3 = lcov lcov-report lcov-rerun clean-lcov covcheck uncovered subdir = libsofia-sip-ua/msg ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(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)/m4/sac-coverage.m4 \ $(top_srcdir)/m4/sac-general.m4 \ $(top_srcdir)/m4/sac-openssl.m4 \ $(top_srcdir)/m4/sac-pkg-config.m4 $(top_srcdir)/m4/sac-su2.m4 \ $(top_srcdir)/m4/sac-tport.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libsofia-sip-ua/su/sofia-sip/su_configure.h CONFIG_CLEAN_FILES = Doxyfile CONFIG_CLEAN_VPATH_FILES = LIBRARIES = $(noinst_LIBRARIES) ARFLAGS = cru AM_V_AR = $(am__v_AR_@AM_V@) am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@) am__v_AR_0 = @echo " AR " $@; am__v_AR_1 = libtest_msg_a_AR = $(AR) $(ARFLAGS) libtest_msg_a_LIBADD = am_libtest_msg_a_OBJECTS = test_class.$(OBJEXT) test_table.$(OBJEXT) \ test_inlined.$(OBJEXT) libtest_msg_a_OBJECTS = $(am_libtest_msg_a_OBJECTS) LTLIBRARIES = $(noinst_LTLIBRARIES) libmsg_la_LIBADD = am_libmsg_la_OBJECTS = msg.lo msg_tag.lo msg_inlined.lo msg_mime.lo \ msg_mime_table.lo msg_header_copy.lo msg_header_make.lo \ msg_parser.lo msg_mclass.lo msg_parser_util.lo msg_basic.lo \ msg_generic.lo msg_date.lo msg_auth.lo libmsg_la_OBJECTS = $(am_libmsg_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 = msg_name_hash_SOURCES = msg_name_hash.c msg_name_hash_OBJECTS = msg_name_hash.$(OBJEXT) msg_name_hash_LDADD = $(LDADD) am__DEPENDENCIES_1 = msg_name_hash_DEPENDENCIES = libtest_msg.a libmsg.la ../bnf/libbnf.la \ ../url/liburl.la ../ipt/libipt.la ../su/libsu.la \ $(am__DEPENDENCIES_1) msg_name_hash_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(msg_name_hash_LDFLAGS) $(LDFLAGS) -o $@ test_msg_SOURCES = test_msg.c test_msg_OBJECTS = test_msg.$(OBJEXT) test_msg_LDADD = $(LDADD) test_msg_DEPENDENCIES = libtest_msg.a libmsg.la ../bnf/libbnf.la \ ../url/liburl.la ../ipt/libipt.la ../su/libsu.la \ $(am__DEPENDENCIES_1) test_msg_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(test_msg_LDFLAGS) $(LDFLAGS) -o $@ 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)$(pkgdatadir)" \ "$(DESTDIR)$(include_sofiadir)" SCRIPTS = $(dist_pkgdata_SCRIPTS) 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) -I$(top_builddir)/libsofia-sip-ua/su/sofia-sip depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f 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) 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 = $(libtest_msg_a_SOURCES) $(libmsg_la_SOURCES) \ msg_name_hash.c test_msg.c DIST_SOURCES = $(libtest_msg_a_SOURCES) $(libmsg_la_SOURCES) \ msg_name_hash.c test_msg.c am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(nobase_include_sofia_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)` 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=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ 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_DRIVER = $(SHELL) $(top_srcdir)/test-driver 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) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CHECK_CFLAGS = @CHECK_CFLAGS@ CHECK_LIBS = @CHECK_LIBS@ COVERAGE_FLAGS = @COVERAGE_FLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CWFLAG = @CWFLAG@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV = @GCOV@ GENHTML = @GENHTML@ GENPNG = @GENPNG@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GLIB_VERSION = @GLIB_VERSION@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVER_SOFIA_SIP_UA_AGE = @LIBVER_SOFIA_SIP_UA_AGE@ LIBVER_SOFIA_SIP_UA_CUR = @LIBVER_SOFIA_SIP_UA_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_AGE = @LIBVER_SOFIA_SIP_UA_GLIB_AGE@ LIBVER_SOFIA_SIP_UA_GLIB_CUR = @LIBVER_SOFIA_SIP_UA_GLIB_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_REV = @LIBVER_SOFIA_SIP_UA_GLIB_REV@ LIBVER_SOFIA_SIP_UA_GLIB_SOVER = @LIBVER_SOFIA_SIP_UA_GLIB_SOVER@ LIBVER_SOFIA_SIP_UA_REV = @LIBVER_SOFIA_SIP_UA_REV@ LIBVER_SOFIA_SIP_UA_SOVER = @LIBVER_SOFIA_SIP_UA_SOVER@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MINGW_ENVIRONMENT = @MINGW_ENVIRONMENT@ MKDIR_P = @MKDIR_P@ MOSTLYCLEANFILES = @MOSTLYCLEANFILES@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ RANLIB = @RANLIB@ REPLACE_LIBADD = @REPLACE_LIBADD@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ SOFIA_GLIB_CFLAGS = @SOFIA_GLIB_CFLAGS@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ SOFIA_PLAT_CFLAGS = @SOFIA_PLAT_CFLAGS@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ VERSION = @VERSION@ VER_LIBSOFIA_SIP_UA_MAJOR_MINOR = @VER_LIBSOFIA_SIP_UA_MAJOR_MINOR@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ include_sofiadir = @include_sofiadir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ openssl_CFLAGS = @openssl_CFLAGS@ openssl_LIBS = @openssl_LIBS@ 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@ INCLUDES = -I$(srcdir)/../url -I../url \ -I$(srcdir)/../bnf -I../bnf \ -I$(srcdir)/../su -I../su # ---------------------------------------------------------------------- # Build targets noinst_LTLIBRARIES = libmsg.la noinst_LIBRARIES = libtest_msg.a # ---------------------------------------------------------------------- # Rules for building the targets GENERATED_H = sofia-sip/msg_protos.h sofia-sip/msg_mime_protos.h PUBLIC_H = sofia-sip/msg.h sofia-sip/msg_header.h \ sofia-sip/msg_types.h sofia-sip/msg_mclass.h \ sofia-sip/msg_mclass_hash.h sofia-sip/msg_parser.h \ sofia-sip/msg_addr.h sofia-sip/msg_date.h \ sofia-sip/msg_buffer.h sofia-sip/msg_tag_class.h \ sofia-sip/msg_mime.h INTERNAL_H = msg_internal.h test_class.h nobase_include_sofia_HEADERS = \ $(GENERATED_H) $(PUBLIC_H) GENERATED_HC = $(GENERATED_H) msg_mime_table.c test_table.c test_protos.h BUILT_SOURCES = $(GENERATED_HC) libmsg_la_SOURCES = msg_internal.h \ msg.c msg_tag.c msg_inlined.c \ msg_mime.c msg_mime_table.c \ msg_header_copy.c msg_header_make.c \ msg_parser.c msg_mclass.c msg_parser_util.c \ msg_basic.c msg_generic.c msg_date.c msg_auth.c COVERAGE_INPUT = $(libmsg_la_SOURCES) $(include_sofia_HEADERS) libtest_msg_a_SOURCES = test_class.c test_class.h \ test_table.c test_inlined.c test_protos.h LDADD = libtest_msg.a libmsg.la ../bnf/libbnf.la ../url/liburl.la \ ../ipt/libipt.la ../su/libsu.la $(openssl_LIBS) test_msg_LDFLAGS = -static msg_name_hash_LDFLAGS = -static # ---------------------------------------------------------------------- # Install and distribution rules dist_pkgdata_SCRIPTS = msg_parser.awk EXTRA_DIST = msg.docs \ sofia-sip/msg_mime_protos.h.in \ sofia-sip/msg_protos.h.in \ msg_mime_table.c.in \ test_protos.h.in \ test_table.c.in sofiasrcdir = ${top_srcdir}/libsofia-sip-ua sofiabuilddir = ${top_builddir}/libsofia-sip-ua AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(SOFIA_CFLAGS) \ $(openssl_CFLAGS) $(SOFIA_PLAT_CFLAGS) $(am__append_1) SOFIA_COVERAGE = $(COVERAGE_FLAGS) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files TAG_AWK = ${sofiasrcdir}/su/tag_dll.awk SUFFIXES = _tag_ref.c _tag.c INTERNAL_INCLUDES = \ -I${sofiasrcdir}/features -I${sofiabuilddir}/features \ -I${sofiasrcdir}/ipt -I${sofiabuilddir}/ipt \ -I${sofiasrcdir}/iptsec -I${sofiabuilddir}/iptsec \ -I${sofiasrcdir}/bnf -I${sofiabuilddir}/bnf \ -I${sofiasrcdir}/http -I${sofiabuilddir}/http \ -I${sofiasrcdir}/msg -I${sofiabuilddir}/msg \ -I${sofiasrcdir}/nth -I${sofiabuilddir}/nth \ -I${sofiasrcdir}/nta -I${sofiabuilddir}/nta \ -I${sofiasrcdir}/nea -I${sofiabuilddir}/nea \ -I${sofiasrcdir}/nua -I${sofiabuilddir}/nua \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sdp -I${sofiabuilddir}/sdp \ -I${sofiasrcdir}/sip -I${sofiabuilddir}/sip \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sresolv -I${sofiabuilddir}/sresolv \ -I${sofiasrcdir}/tport -I${sofiabuilddir}/tport \ -I${sofiasrcdir}/stun -I${sofiabuilddir}/stun \ -I${sofiasrcdir}/url -I${sofiabuilddir}/url \ -I${sofiasrcdir}/su -I${sofiabuilddir}/su PHONY = built-sources clean-built-sources $(am__append_3) VALGRIND = valgrind VALGRINDFLAGS = --tool=memcheck # Scripts @HAVE_LCOV_TRUE@LCOV_UNCOVERED = ${top_srcdir}/scripts/uncovered @HAVE_LCOV_TRUE@LCOV_REPORT = ${top_srcdir}/scripts/lcov-report # Report directory @HAVE_LCOV_TRUE@lcovdir = ${top_builddir}/lcov # Options @HAVE_LCOV_TRUE@GENHTML_OPTIONS = --show-details --legend \ @HAVE_LCOV_TRUE@ $(am__append_2) # Fancy shell command that expands to directory relative to top_builddir @HAVE_LCOV_TRUE@expand_subdir = `pwd|sed "s'\`cd ${top_builddir};pwd\`''"` SOFIA_SILENT = @ LIBTOOL_FLAGS = --silent # From Automake 1.9.6 - LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(LIBTOOL_FLAGS) \ $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) LINK = ${SOFIA_SILENT}test "${SOFIA_SILENT}" != @ || echo ' LINK $@'; \ $(LIBTOOL) --tag=CC --mode=link $(LIBTOOL_FLAGS) \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ # ---------------------------------------------------------------------- # Sofia specific rules MSG_PARSER_AWK = $(srcdir)/msg_parser.awk AWK_MSG_AWK = LC_ALL=C $(AWK) -f $(MSG_PARSER_AWK) TEST_CLASS_H = ${srcdir}/test_class.h SS_MIME_H = ${srcdir}/sofia-sip/msg_mime.h all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: _tag_ref.c _tag.c .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.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 libsofia-sip-ua/msg/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu libsofia-sip-ua/msg/Makefile .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.am: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): Doxyfile: $(top_builddir)/config.status $(srcdir)/Doxyfile.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) libtest_msg.a: $(libtest_msg_a_OBJECTS) $(libtest_msg_a_DEPENDENCIES) $(EXTRA_libtest_msg_a_DEPENDENCIES) $(AM_V_at)-rm -f libtest_msg.a $(AM_V_AR)$(libtest_msg_a_AR) libtest_msg.a $(libtest_msg_a_OBJECTS) $(libtest_msg_a_LIBADD) $(AM_V_at)$(RANLIB) libtest_msg.a 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}; \ } libmsg.la: $(libmsg_la_OBJECTS) $(libmsg_la_DEPENDENCIES) $(EXTRA_libmsg_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libmsg_la_OBJECTS) $(libmsg_la_LIBADD) $(LIBS) 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 msg_name_hash$(EXEEXT): $(msg_name_hash_OBJECTS) $(msg_name_hash_DEPENDENCIES) $(EXTRA_msg_name_hash_DEPENDENCIES) @rm -f msg_name_hash$(EXEEXT) $(AM_V_CCLD)$(msg_name_hash_LINK) $(msg_name_hash_OBJECTS) $(msg_name_hash_LDADD) $(LIBS) test_msg$(EXEEXT): $(test_msg_OBJECTS) $(test_msg_DEPENDENCIES) $(EXTRA_test_msg_DEPENDENCIES) @rm -f test_msg$(EXEEXT) $(AM_V_CCLD)$(test_msg_LINK) $(test_msg_OBJECTS) $(test_msg_LDADD) $(LIBS) install-dist_pkgdataSCRIPTS: $(dist_pkgdata_SCRIPTS) @$(NORMAL_INSTALL) @list='$(dist_pkgdata_SCRIPTS)'; test -n "$(pkgdatadir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgdatadir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgdatadir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | 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; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$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_SCRIPT) $$files '$(DESTDIR)$(pkgdatadir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(pkgdatadir)$$dir" || exit $$?; \ } \ ; done uninstall-dist_pkgdataSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(dist_pkgdata_SCRIPTS)'; test -n "$(pkgdatadir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(pkgdatadir)'; $(am__uninstall_files_from_dir) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg_auth.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg_basic.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg_date.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg_generic.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg_header_copy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg_header_make.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg_inlined.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg_mclass.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg_mime.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg_mime_table.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg_name_hash.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg_parser.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg_parser_util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg_tag.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_class.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_inlined.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_msg.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_table.Po@am__quote@ .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.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) '$<'` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-nobase_include_sofiaHEADERS: $(nobase_include_sofia_HEADERS) @$(NORMAL_INSTALL) @list='$(nobase_include_sofia_HEADERS)'; test -n "$(include_sofiadir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(include_sofiadir)'"; \ $(MKDIR_P) "$(DESTDIR)$(include_sofiadir)" || exit 1; \ fi; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo " $(MKDIR_P) '$(DESTDIR)$(include_sofiadir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(include_sofiadir)/$$dir"; }; \ echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(include_sofiadir)/$$dir'"; \ $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(include_sofiadir)/$$dir" || exit $$?; }; \ done uninstall-nobase_include_sofiaHEADERS: @$(NORMAL_UNINSTALL) @list='$(nobase_include_sofia_HEADERS)'; test -n "$(include_sofiadir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ dir='$(DESTDIR)$(include_sofiadir)'; $(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; \ else \ 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 $(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_msg.log: test_msg$(EXEEXT) @p='test_msg$(EXEEXT)'; \ b='test_msg'; \ $(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: $(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: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) $(SCRIPTS) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(pkgdatadir)" "$(DESTDIR)$(include_sofiadir)"; 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: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) -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: 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) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) 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) @HAVE_LCOV_FALSE@clean-local: clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libtool clean-local \ clean-noinstLIBRARIES clean-noinstLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -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-dist_pkgdataSCRIPTS \ install-nobase_include_sofiaHEADERS 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 -rf ./$(DEPDIR) -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-dist_pkgdataSCRIPTS \ uninstall-nobase_include_sofiaHEADERS .MAKE: all check check-am install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libtool clean-local \ clean-noinstLIBRARIES 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-dist_pkgdataSCRIPTS install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-nobase_include_sofiaHEADERS 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 \ uninstall-dist_pkgdataSCRIPTS \ uninstall-nobase_include_sofiaHEADERS built-sources: $(BUILT_SOURCES) clean-built-sources: -rm -rf $(BUILT_SOURCES) $(BUILT_SOURCES:%=$(srcdir)/%) *_tag_ref.c: $(TAG_AWK) _tag.c_tag_ref.c: $(AWK) -f $(TAG_AWK) NODLL=1 $(TAG_DLL_FLAGS) REF=$@ $< ../bnf/libbnf.la ../http/libhttp.la ../ipt/libipt.la ../iptsec/libiptsec.la \ ../msg/libmsg.la ../nea/libnea.la ../nta/libnta.la ../nth/libnth.la \ ../nua/libnua.la ../sdp/libsdp.la ../sip/libsip.la ../soa/libsoa.la \ ../sresolv/libsresolv.la ../stun/libstun.la ../su/libsu.la \ ../tport/libtport.la ../url/liburl.la: cd $(@D) && $(MAKE) $(@F) checklib: $(noinst_LTLIBRARIES) $(check_LTLIBRARIES) valcheck: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) valcheck-am valcheck-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS # Run tests with valgrind in valcheck-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ list='$(TESTS)'; \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ if case $$tst in \ run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ $${dir}$$tst ;; \ esac ; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ echo "XPASS: $$tst"; \ ;; \ *) \ echo "PASS: $$tst"; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xfail=`expr $$xfail + 1`; \ echo "XFAIL: $$tst"; \ ;; \ *) \ failed=`expr $$failed + 1`; \ echo "FAIL: $$tst"; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ echo "SKIP: $$tst"; \ fi; \ done; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="All $$all tests passed"; \ else \ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all tests failed"; \ else \ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ skipped="($$skip tests were not run)"; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ report=""; \ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ report="Please report to $(PACKAGE_BUGREPORT)"; \ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ echo "$$dashes"; \ echo "$$banner"; \ test -z "$$skipped" || echo "$$skipped"; \ test -z "$$report" || echo "$$report"; \ echo "$$dashes"; \ test "$$failed" -eq 0; \ else :; fi # # Generate pretty coverage report (unless it has been already done) # @HAVE_LCOV_TRUE@lcov: @HAVE_LCOV_TRUE@ @-test -r ${lcovdir}${expand_subdir}/lcov.info \ @HAVE_LCOV_TRUE@ || make lcov-report # Generate pretty coverage report based on current coverage data @HAVE_LCOV_TRUE@lcov-report: @HAVE_LCOV_TRUE@ sub=${expand_subdir} odir=${lcovdir}$$sub ; \ @HAVE_LCOV_TRUE@ rm -rf $$odir ; mkdir -p $$odir && \ @HAVE_LCOV_TRUE@ ${LCOV_REPORT} ${GENHTML_OPTIONS} \ @HAVE_LCOV_TRUE@ --title "${PACKAGE_NAME}-${PACKAGE_VERSION}$$sub" \ @HAVE_LCOV_TRUE@ --srcdir=${srcdir} -o $$odir # Rerun checks before generating report @HAVE_LCOV_TRUE@lcov-rerun: clean-lcov @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) lcov-report # Show all uncovered lines as errors @HAVE_LCOV_TRUE@uncovered: @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} # Run check in current dir and show all uncovered lines as errors @HAVE_LCOV_TRUE@covcheck: @HAVE_LCOV_TRUE@ -find . -name "*.gcda" | xargs rm -rf @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} @HAVE_LCOV_TRUE@clean-local:: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true @HAVE_LCOV_TRUE@clean-lcov: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true # Rules from depend2.am (GENERIC = TRUE, SUBDIROBJ = FALSE, %FASTDEP% = am_fastdepCC) silenced. .c.o: @test "${SOFIA_SILENT}" != @ || echo ' COMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(COMPILE) -c -o $@ $< .c.lo: @test "${SOFIA_SILENT}" != @ || echo ' LTCOMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(LTCOMPILE) -c -o $@ $< # endif ${GENERATED_HC}: ${MSG_PARSER_AWK} Makefile.am test_protos.h test_table.c: ${TEST_CLASS_H} test_protos.h: ${srcdir}/test_protos.h.in $(AWK_MSG_AWK) module=msg_test NO_MIDDLE=1 NO_LAST=1 \ PR=$@ TEMPLATE=${srcdir}/test_protos.h.in ${TEST_CLASS_H} test_table.c: ${srcdir}/test_table.c.in $(AWK_MSG_AWK) module=msg_test prefix=msg \ MC_HASH_SIZE=127 multipart=msg_multipart \ PT=$@ TEMPLATE=${srcdir}/test_table.c.in ${TEST_CLASS_H} sofia-sip/msg_protos.h sofia-sip/msg_mime_protos.h: ${SS_MIME_H} msg_mime_table.c: ${SS_MIME_H} sofia-sip/msg_protos.h: ${srcdir}/sofia-sip/msg_protos.h.in @-mkdir sofia-sip 2>/dev/null || true $(AWK_MSG_AWK) module=msg NO_FIRST=1 NO_MIDDLE=1 \ PR=$@ TEMPLATE=${srcdir}/sofia-sip/msg_protos.h.in \ ${SS_MIME_H} sofia-sip/msg_mime_protos.h: ${srcdir}/sofia-sip/msg_mime_protos.h.in @-mkdir sofia-sip 2>/dev/null || true $(AWK_MSG_AWK) module=msg NO_FIRST=1 NO_LAST=1 \ PR=$@ TEMPLATE=${srcdir}/sofia-sip/msg_mime_protos.h.in \ ${SS_MIME_H} msg_mime_table.c: ${srcdir}/msg_mime_table.c.in $(AWK_MSG_AWK) module=msg_multipart \ tprefix=msg prefix=mp MC_HASH_SIZE=127 MC_SHORT_SIZE=26 \ PT=$@ TEMPLATE=${srcdir}/msg_mime_table.c.in \ ${SS_MIME_H} # 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: sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/msg.c000066400000000000000000000244261223300710500213020ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@internal @file msg.c Message object implementation. * * @author Pekka Pessi * * @date Created: Thu Jun 8 19:28:55 2000 ppessi */ #include "config.h" #include #include #include #include #include #include #include #include #include /* XXX */ #include #include "msg_internal.h" #include "sofia-sip/msg_parser.h" #include "sofia-sip/msg_mclass.h" /** Increment the reference count. * * @relatesalso msg_s * * Increases the reference count of a message. The message is not freed * until all the references have been destroyed. * * @param msg message of which a reference is created * * @return A pointer to a message */ msg_t *msg_ref(msg_t *msg) { return (msg_t *)su_home_ref(msg->m_home); } static void msg_destructor(void *_msg) { msg_t *msg = _msg; if (msg->m_parent) su_home_unref(msg->m_parent->m_home); } /** Decrease the reference count. * * @relatesalso msg_s * * Decreases the reference count of a message. The message is freed * if the reference count reaches zero. * * @param msg message of which a reference is created * * @return A pointer to a message */ void msg_unref(msg_t *msg) { su_home_unref(msg->m_home); } /** * Create a message. * * @relatesalso msg_s * * @param mc message class * @param flags message control flags */ msg_t *msg_create(msg_mclass_t const *mc, int flags) { msg_t *msg = su_home_new(sizeof(*msg) + mc->mc_msize); if (msg) { if ((flags & MSG_FLG_THRDSAFE) && su_home_threadsafe(msg->m_home) < 0) { su_home_unref(msg->m_home); return NULL; } if (su_home_desctructor(msg->m_home, msg_destructor) < 0) { su_home_unref(msg->m_home); return NULL; } msg->m_refs++; msg->m_tail = &msg->m_chain; msg->m_addrinfo.ai_addrlen = sizeof(msg->m_addr); msg->m_addrinfo.ai_addr = &msg->m_addr->su_sa; msg->m_maxsize = 0; flags &= MSG_FLG_USERMASK; msg->m_class = mc; msg->m_oflags = flags; msg->m_object = (void *)(msg + 1); msg->m_object->msg_size = mc->mc_msize; msg->m_object->msg_flags = mc->mc_flags | flags; msg->m_object->msg_common->h_class = (void *)mc; } return msg; } /**Increment the reference count. * * @relatesalso msg_s * * Increases the reference count of a message. The message is not freed * until all the references have been destroyed. * * @param msg message of which a reference is created * * @return A pointer to a message */ msg_t *msg_ref_create(msg_t *msg) { return (msg_t *)su_home_ref(msg->m_home); } /**Set a message parent. * * @relatesalso msg_s * * Set a parent for a message. The parent message is not destroyed until all * its kids have been destroyed - each kid keeps a reference to its parent * message. * * @param kid child message * @param dad parent message */ void msg_set_parent(msg_t *kid, msg_t *dad) { if (kid) { msg_t *step_dad = kid->m_parent; if (dad && step_dad && step_dad != dad) msg_unref(step_dad); kid->m_parent = msg_ref(dad); } } /** Destroy a reference to a message. * * @relatesalso msg_s * * @param ref pointer to msg object * * @deprecated Use msg_destroy() instead. */ void msg_ref_destroy(msg_t *ref) { msg_unref(ref); } /** Destroy a reference to a message. * * @relatesalso msg_s * * @param msg message to be destroyed */ void msg_destroy(msg_t *msg) { msg_unref(msg); } /* Message object routines */ /**Retrieve public message structure. * * Get a pointer to the public message structure. * * @param msg pointer to msg object * * @returns * A pointer to the public message structure, or NULL if none. */ msg_pub_t *msg_object(msg_t const *msg) { if (msg) return msg->m_object; else return NULL; } /**Retrieve public message structure of given type. * * @relatesalso msg_s * * Get a pointer to the public message structure of the * given protocol. * * @param msg pointer to msg object * @param tag tag of public message structure * * @returns * A pointer to the public message structure, or NULL if there is none or * the message is not for desired protocol. */ msg_pub_t *msg_public(msg_t const *msg, void *tag) { if (msg && msg->m_class->mc_tag == tag) return msg->m_object; else return NULL; } /**Retrieve message class. * * @relatesalso msg_s * * Get a pointer to the message class object * (factory object for the message). * * @param msg pointer to msg object * * @returns * A pointer to the message class, or NULL if none. */ msg_mclass_t const *msg_mclass(msg_t const *msg) { if (msg) return msg->m_class; else return NULL; } /* Address management */ /** Zero the message address. * * @relatesalso msg_s * * Zero the address and addressinfo structures associated with the message. * * @sa msg_addrinfo(), msg_set_address(), msg_get_address(), msg_addr_copy(). */ void msg_addr_zero(msg_t *msg) { memset(&msg->m_addr, 0, sizeof(msg->m_addr)); memset(&msg->m_addrinfo, 0, sizeof(msg->m_addrinfo)); msg->m_addrinfo.ai_addrlen = sizeof(msg->m_addr); msg->m_addrinfo.ai_addr = &msg->m_addr->su_sa; } /** Get pointer to socket address structure. * * @relatesalso msg_s * * @deprecated Use msg_get_address() or msg_set_address() instead. */ su_sockaddr_t *msg_addr(msg_t *msg) { return msg ? msg->m_addr : 0; } /** Get message address. * * @relatesalso msg_s * * Copy the socket address associated with the message to the supplied * socket address struture. * * @param msg pointer to msg object * @param su pointer to socket address structure * @param return_len return parameter value for length * of socket address structure * * @sa msg_addrinfo(), msg_set_address(), msg_addr_zero(), msg_addr_copy(). */ int msg_get_address(msg_t *msg, su_sockaddr_t *su, socklen_t *return_len) { if (msg && return_len && *return_len >= msg->m_addrinfo.ai_addrlen) { *return_len = (socklen_t)msg->m_addrinfo.ai_addrlen; if (su) memcpy(su, msg->m_addr, msg->m_addrinfo.ai_addrlen); return 0; } if (msg) msg->m_errno = EFAULT; return -1; } /** Set message address. * * @relatesalso msg_s * * Copy the supplied socket address to the socket address structure * associated with the message. * * @param msg pointer to msg object * @param su pointer to socket address structure * @param sulen length of socket address structure * * @sa msg_addrinfo(), msg_get_address(), msg_addr_zero(), msg_addr_copy(). */ int msg_set_address(msg_t *msg, su_sockaddr_t const *su, socklen_t sulen) { if (sulen < (sizeof msg->m_addr) && msg && su) { memcpy(msg->m_addr, su, msg->m_addrinfo.ai_addrlen = sulen); msg->m_addrinfo.ai_family = su->su_family; return 0; } if (msg) msg->m_errno = EFAULT; return -1; } /** Get addrinfo structure. * * @relatesalso msg_s * * Get pointer to the addrinfo structure associated with the message. * * @param msg pointer to msg object * * @retval pointer to addrinfo structure * @retval NULL if msg is NULL * * @sa msg_get_address(), msg_set_address(), msg_addr_zero(), msg_addr_copy(). */ su_addrinfo_t *msg_addrinfo(msg_t *msg) { return msg ? &msg->m_addrinfo : 0; } /**Copy message address. * * @relatesalso msg_s * * Copy the addrinfo and socket address structures from @a src to the @a dst * message object. * * @param dst pointer to destination message object * @param src pointer to source message object * * @sa msg_addrinfo(), msg_get_address(), msg_set_address(), msg_addr_zero(). */ void msg_addr_copy(msg_t *dst, msg_t const *src) { dst->m_addrinfo = src->m_addrinfo; dst->m_addrinfo.ai_next = NULL; dst->m_addrinfo.ai_canonname = NULL; memcpy(dst->m_addrinfo.ai_addr = &dst->m_addr->su_sa, src->m_addr, src->m_addrinfo.ai_addrlen); if (dst->m_addrinfo.ai_addrlen < sizeof(dst->m_addr)) memset((char *)dst->m_addr + dst->m_addrinfo.ai_addrlen, 0, sizeof(dst->m_addr) - dst->m_addrinfo.ai_addrlen); } /** Get error classification flags. * * @relatesalso msg_s * * If the message parser fails to parse certain headers in the message, it * sets the corresponding extract error flags. The flags corresponding to * each header are stored in the message parser (msg_mclass_t) structure. * They are set when the header is added to the parser table. * * The SIP flags are defined in . For well-known * SIP headers, the flags for each header are listed in a separate text file * (sip_bad_mask) read by msg_parser.awk. * * The flags can be used directly by NTA (the mask triggering 400 response * is set with NTATAG_BAD_REQ_MASK(), the mask triggering response messages * to be dropped is set with NTATAG_BAD_RESP_MASK()). Alternatively the * application can check them based on the method or required SIP features. * * @sa msg_mclass_insert_with_mask(), NTATAG_BAD_REQ_MASK(), * NTATAG_BAD_RESP_MASK(). */ unsigned msg_extract_errors(msg_t const *msg) { return msg ? msg->m_extract_err : (unsigned)-1; } /** Get error number associated with message. * * @relatesalso msg_s * * @param msg pointer to msg object * */ int msg_errno(msg_t const *msg) { return msg ? msg->m_errno : EINVAL; } /** Set error number associated with message. * * @relatesalso msg_s * * @param msg pointer to msg object * @param err error value (as defined in ). * */ void msg_set_errno(msg_t *msg, int err) { if (msg) msg->m_errno = err; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/msg.docs000066400000000000000000000506141223300710500220060ustar00rootroot00000000000000/* -*- text -*- */ /**@MODULEPAGE "msg" - Message Parser Module @section msg_meta Module Meta Information This module contains parser and functions for manipulating messages and headers for text-based protocols like SIP, HTTP or RTSP. It also provides parsing of MIME headers and MIME multipart messages common to these protocols. @CONTACT Pekka Pessi @STATUS @SofiaSIP Core library @LICENSE LGPL @par Contributor(s): - Pekka Pessi @section msg_contents Contents of msg Module The msg module contains the public header files as follows: - base message interfaces - message and header struct definitions and typedefs - prototypes of header-specific functions for generic headers - function prototypes and macros for manipulating message headers - functions for accessing network addresses and I/O vectors associated with the message - types and functions for handling dates and times - types, function prototypes and macros for MIME headers and @ref msg_multipart "multipart messages" - prototypes of MIME-header-specific functions In addition to this interface, the @ref msg_parser "parser documentation" contains description of the functionality required when an existing parser is extended by a new header or a parser is created for a completely new protocol. It is possible to add new headers to the parser or extend the definition of existing ones. The header files used for constructing these parsers are as follows: - parsing functions, macros - message factory object definition - hashing of header names @section msg_overview Parsers, Messages and Headers The Sofia @b msg module contains interface to the text-based parsers for RFC822-like message, the header and message objects. Currently, there are three parsers defined: SIP, HTTP, and MIME. The C structure corresponding to each header is defined either in a or in a protocol-specific header file. These protocol-specific header files include , , and . For each header, there is defined a @em header @em class structure, some standard functions, and tags for including them in tag lists. As a convention, all the identifiers for SIP headers start with prefix @c sip and all the macros with @c SIP. Same thing holds for HTTP, too: it uses prefix @c http. However, the MIME headers and the functions related to them are defined within the @b msg module and they use prefix @c msg. If a SIP or HTTP header uses a structure defined in , there is a typedef suitable for the particular protocol, for example @b Accept header is defined multiple times: @code typedef struct msg_accept_s sip_accept_t; typedef struct msg_accept_s http_accept_t; @endcode For header @e X of protocol @e NS, there are types, functions, macros and header class as follows: - @c ns_X_t is the structure used to store parsed header, - @c ns_hclass_t @c ns_X_class[] contains the @em header @em class for header X, - @c NS_X_INIT() initializes a static instance of @c ns_X_t, - @c ns_X_init() initializes a dynamic instance of @c ns_X_t, - @c ns_is_X() tests if header object is instance of header X, - @c ns_X_make() creates a header X object by decoding given string, - @c ns_X_format() creates a header X object by decoding given @c printf() list, - @c ns_X_dup() duplicates (deeply copies) the header X, - @c ns_X_copy() copies the header X, - @c NSTAG_X() is used include instance of @c ns_X_t in a tag list, and - @c NSTAG_X_STR() is used to include string containing value header in a tag list. The declarations of header tags and the prototypes for these functions can be imported separately from the type definitions, for instance, the tags related to SIP headers are declared in the include file , and the header-specific functions in . @section parser_intro Parsing Text Messages Sofia text parser follows @em recursive-descent principle. In other words, it is a program that descends the syntax tree top-down recursively. (All syntax trees have root at top and they grow downwards.) In the case of SIP, HTTP and other similar protocols, such a parser is very efficient. The parser can choose between different forms based on each token, as the protocol syntax is carefully designed so that it requires only minimal scan-ahead. It is also easy to extend a recursive-descent parser via a standard API, unlike, for instance, a LALR parser generated by @em Bison. The abstract message module @b msg contains a high-level parser engine that drives the parsing process and invokes the protocol-specific parser for each header. As there is no low-layer framing between the RFC822-style messages, the parser considers any received data, be it a UDP datagram or a TCP stream, as a @em byte @em stream. The protocol-specific parsers controls how a byte stream is split into separate messages or if it consists of a single message only. The parser engine works by separating stream into fragments, then passing the fragment to a suitable parser. A fragment is a piece of message that is parsed during a single step: the first line, each header, the empty line between headers and message body, the message body. (In case of HTTP, the message body can consists of multiple fragments known as chunks.) The parser starts by separating the first line (e.g., request or status line) from the byte stream, then passing the line to the suitable parser. After first line comes the message headers. The parser continues parsing process by extracting headers, each on their own line, from the stream and passing contents of each header to its parser. The message structure is populated based on the parsing results. When an empty line - indicating end of headers - is encountered, the control is passed to the protocol-specific parser. Protocol-specific functions take care of extracting the possible message body from the byte stream. After parsing process is completed, it can be given to the upper layers (typically a protocol state machine). The parser continues processing the stream and feeding the messages to protocol engine until the end of the stream is reached. @image html sip-parser.gif Separating byte stream to messages @image latex sip-parser.eps Separating byte stream to messages When the parsing process has completed, the first line, each header, separator and the message body are all in their own fragment structure. The fragments form a dual-linked list known as @e fragment @e chain as shown in the above figure. The memory buffers for the message, the fragment chain, and a whole lot of other stuff is held by the generic message type, #msg_t, defined in . The internal structure of #msg_t is known only within @b msg module and it is opaque to other modules. The @b msg parser engine also drives the reverse process, invoking the encoding method of each fragment so that the whole outgoing message can be encoded properly. @section msg_header_struct Message Header as a C struct Just separating headers from each other and from the message body is not usually enough. When a header contains structured data, the header contents should be converted to a form that is convenient to use from C programs. For that purpose, the message parser needs a parsing function specific to each individual header. This parsing function divides the contents of the header into semantically meaningful segments and stores the result in the structure specific to each header. The parser engine passes the fragment contents to the parsing function after it has separated the fragment from the rest of the message. The parser engine selects correct @e header @e class either by implication (in case of first line), or it searches for the header class from the hash table using the header name as the hash key. The @e header @e class contains a pointer to the parsing function. The parser has also special header classes for headers with errors and @e unknown headers, header with a name that is not regocnized by the parser. For instance, the Accept header has following syntax: @code Accept = "Accept" ":" #( media-range [ accept-params ] ) media-range = ( "*" "/" "*" | ( type "/" "*" ) | ( type "/" subtype ) ) *( ";" parameter ) accept-params = ";" "q" "=" qvalue *( accept-extension ) accept-extension = ";" token [ "=" ( token | quoted-string ) ] @endcode When an Accept header is parsed, the header parser function (msg_accept_d()) separates the @e type, @e subtype, and each parameter in the list to strings. The parsing result is assigned to a #msg_accept_t structure, which is defined as follows: @code typedef struct msg_accept_s { msg_common_t ac_common[1]; //< Common fragment info msg_accept_t *ac_next; //< Pointer to next Accept header char const *ac_type; //< Pointer to type/subtype char const *ac_subtype; //< Points after first slash in type msg_param_t const *ac_params; //< List of parameters msg_param_t ac_q; //< Value of q parameter } msg_accept_t; @endcode The string containing the @e type is put into the @c ac_type field, the @e subtype after slash in the can be found in the @c ac_subtype field, and the list of @e accept-params (together with media-specific-parameters) is put in the @c ac_params array. If there is a @e q parameter present, a pointer to the @c qvalue is assigned to @c ac_q field. In the beginning of the header structure there are two boilerplate members. The @c ac_common[1] contains information common to all message fragments. The @c ac_next is a pointer to next header field with the same name, in case a message contains multiple @b Accept headers or multiple comma-separated header fields are located in a single line. @section msg_object_example Representing a Message as a C struct It is not enough to represent a message as a list of headers following each other. The programmer also needs a convenient way to access certain headers at the message level, for example, accessing directly the @b Accept header instead of going through all headers and examining their name. The structured view to the message is provided via a message-specific C struct. In general, its type is msg_pub_t (it provides public view to message). The protocol-specific type is #sip_t, #http_t or #msg_multipart_t for SIP, HTTP and MIME, respectively. So, a single message is represented by two objects, first object (#msg_t) is private to the @b msg module and opaque by an application programmer, second (#sip_t, #http_t or #msg_multipart_t) is a public protocol-specific structure accessible by all. @note The application programmer can obtain a pointer to the protocol-specific structure from an #msg_t object using msg_public() function. The msg_public() takes a protocol tag, a well-known identifier, as its argument. The SIP, HTTP and MIME already define a wrapper around msg_public(), for example, a #sip_t structure can be obtained with sip_object() function (or macro). As an example, the #sip_t structure is defined as follows: @code typedef struct sip_s { msg_common_t sip_common[1]; // Used with recursive inclusion msg_pub_t *sip_next; // Ditto void *sip_user; // Application data unsigned sip_size; // Size of the structure with // extension headers int sip_flags; // Parser flags sip_error_t *sip_error; // Erroneous headers sip_request_t *sip_request; // Request line sip_status_t *sip_status; // Status line sip_via_t *sip_via; // Via (v) sip_route_t *sip_route; // Route sip_record_route_t *sip_record_route; // Record-Route sip_max_forwards_t *sip_max_forwards; // Max-Forwards ... } sip_t; @endcode As you can see above, the public #sip_t structure contains the common header members that are also found in the beginning of a header structure. The @e sip_size indicates the size of the structure - the application can extend the parser and #sip_t structure beyond the original size. The @e sip_flags contains various flags used during the parsing and printing process. They are documented in the . These boilerplate members are followed by the pointers to various message elements and headers. @section msg_parsing_example Result of Parsing Process Let us now show how a simple message is parsed and presented to the applications. As an exampe, we choose a SIP request message with method BYE, including only the mandatory fields: @code BYE sip:joe@example.com SIP/2.0 Via: SIP/2.0/UDP sip.example.edu;branch=d7f2e89c.74a72681 Via: SIP/2.0/UDP pc104.example.edu:1030;maddr=110.213.33.19 From: Bobby Brown ;tag=77241a86 To: Joe User ;tag=7c6276c1 Call-ID: 4c4e911b@pc104.example.edu CSeq: 2 @endcode The figure below shows the layout of the BYE message above after parsing: @image html sip-parser2.gif BYE message and its representation in C @image latex sip-parser2.eps BYE message and its representation in C The leftmost box represents the message of type #msg_t. Next box from the left reprents the #sip_t structure, which contains pointers to a header objects. The next column contains the header objects. There is one header object for each message fragment. The rightmost box represents the I/O buffer used when the message was received. Note that the I/O buffer may be non-continous and composed of many separate memory areas. The message object has link to the public message structure (@a m_object), to the dual-linked fragment chain (@a m_frags) and to the I/O buffer (@a m_buffer). The public message structure contains pointers to the headers according to their type. If there are multiple headers of the same type (like there are two Via headers in the above message), the headers are put into a single-linked list. Each fragment has pointers to successing and preceding fragment. It also contains pointer to the corresponding data within the I/O buffer and its length. The main purpose of the fragment chain is to preserve the original order of the headers. If there were an third Via header after CSeq in the message, the fragment representing it would be after the CSeq header in the fragment chain but after second Via in the header list. @section msg_parsing_memory Example: Parsing a Complete Message The following code fragment is an example of parsing a complete message. The parsing process is more hairy when there is stream to be parsed. @code msg_t *parse_memory(msg_mclass_t const *mclass, char const data[], int len) { msg_t *msg; int m; msg_iovec_t iovec[2] = {{ 0 }}; msg = msg_create(mclass, 0); if (!msg) return NULL; m = msg_recv_iovec(msg, iovec, 2, n, 1); if (m < 0) { msg_destroy(msg); return NULL; } assert(m <= 2); assert(iovec[0].mv_len + iovec[1].mv_len == n); memcpy(iovec[0].mv_base, data, n = iovec[0].mv_len); if (m == 2) memcpy(iovec[1].mv_base + n, data + n, iovec[1].mv_len); msg_recv_commit(msg, iovec[0].mv_len + iovec[1].mv_len, 1); m = msg_extract(msg); assert(m != 0); if (m < 0) { msg_destroy(msg); return NULL; } return msg; } @endcode Let's go through this simple function, step by step. First, we get the @a data pointer and its size in bytes, @a len. We first initialize an I/O vector used to represent message with the parser. @code msg_t *parse_memory(msg_mclass_t const *mclass, char const data[], int len) { msg_t *msg; int m; msg_iovec_t iovec[2] = {{ 0 }}; @endcode The message class @a mclass (a parser driver object, #msg_mclass_t) is used to represent a particular protocol-specific parser instance. When a message object is created, it is given as an argument to msg_create() function: @code msg = msg_create(mclass, 0); if (!msg) return NULL; @endcode Next we obtain a memory buffer for data with msg_recv_iovec(). The memory buffer is usually a single continous memory area, but in some cases it may consist of two distinct areas. Therefore the @a iovec is used here to pass the buffers around. The @a iovec is also very handly as it can be directly passed to various system I/O calls. @code m = msg_recv_iovec(msg, iovec, 2, n, 1); if (m < 0) { msg_destroy(msg); return NULL; } @endcode These assumptions hold always true when you call msg_recv_iovec() first time with a complete message: @code assert(m >= 1 && m <= 2); assert(iovec[0].mv_len + iovec[1].mv_len == n); @endcode Next, we copy the data to the I/O vector and commit the copied data to the message. Earlier with msg_recv_iovec() we allocated buffer space for data, now calling msg_recv_commit() indicates that valid data has been copied to the buffer. The last parameter to msg_recv_commit() indicates that the end of stream is encountered and no more data is to be expected. @code memcpy(iovec[0].mv_base, data, n = iovec[0].mv_len); if (m == 2) memcpy(iovec[1].mv_base + n, data + n, iovec[1].mv_len); msg_recv_commit(msg, iovec[0].mv_len + iovec[1].mv_len, 1); @endcode We call msg_extract() next; it takes care of parsing the message. A fatal parsing error is indicated by returning -1. If the message is incomplete, msg_extract() returns 0. When a complete message has been parsed, a positive value is returned. We know that a message cannot be incomplete, as a call to msg_recv_commit() indicated to the parser that the end-of-stream has been encountered. @code m = msg_extract(msg); assert(m != 0); if (m < 0) { msg_destroy(msg); return NULL; } return msg; } @endcode */ /**@class msg_s msg.h * * @brief Message object. * * The message object is used by Sofia parsers for SIP and HTTP * protocols. The message object has an abstract, protocol-independent * inteface type #msg_t, and a separate public protocol-specific interface * #msg_pub_t (which is typedef'ed to #sip_t or #http_t depending * on the protocol). * * The main interface to abstract messages is defined in . The * network I/O interface used by transport protocols is defined in * . The protocol-specific parser table, also known as message * class, is defined in . (The message class is used as a * factory object when a message object is created with msg_create()). */ /**@typedef typedef struct msg_s msg_t; * * Message object. * * The @a msg_t is the type of a message object used by Sofia signaling * protocols and parsers. Its contents are not directly accessible. */ /**@typedef typedef struct msg_common_s msg_common_t; * * Common part of header. * * The @a msg_common_t is the base type of a message headers used by * protocol parsers. Instead of #msg_common_t, most interfaces use * #msg_header_t, which is supposed to be a union of all possible headers. */ /** * @defgroup msg_parser Parser Building Blocks * * This submodule contains the functions and types for building a * protocol-specific parser. */ /** * @defgroup msg_headers Headers * * This submodule contains the functions and types for handling message * headers and other elements. */ /** * @defgroup msg_mime MIME Headers * * This submodule contains the header classes, functions and types for * handling MIME headers (@RFC2045) and MIME multipart (@RFC2046) processing. * * The MIME headers implemented are as follows: * - @ref msg_accept "@b Accept header" * - @ref msg_accept_charset "@b Accept-Charser header" * - @ref msg_accept_encoding "@b Accept-Encoding header" * - @ref msg_accept_language "@b Accept-Language header" * - @ref msg_content_disposition "@b Content-Disposition header" * - @ref msg_content_encoding "@b Content-Encoding header" * - @ref msg_content_id "@b Content-ID header" * - @ref msg_content_location "@b Content-Location header" * - @ref msg_content_language "@b Content-Language header" * - @ref msg_content_md5 "@b Content-MD5 header" * - @ref msg_content_transfer_encoding "@b Content-Transfer-Encoding header" * - @ref msg_mime_version "@b MIME-Version header" */ /** * @defgroup test_msg Testing Parser * * This submodule contains the functions and types for building a * parser objects for testing purposes. */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/msg_auth.c000066400000000000000000000075351223300710500223250ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@ingroup msg_parser * @CFILE msg_auth.c * * Functions for handling authentication-related headers * * @author Pekka Pessi * * @date Created: Tue Jun 13 02:57:51 2000 ppessi * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #if 0 /** * Scan and compact an authentication parameter. * * Scan an authentication parameter, which has syntax as follows: * @code * auth-item = auth-param | base64-string * auth-param = token [ "=" (token | quoted-string)] * @endcode * * Parameters: * @param s pointer to string to scan * * @return Number of characters scanned, or zero upon an error. */ static size_t msg_auth_item_scan(char *start) { char *p, *s; p = s = start; /* XXX */ return start - s; } #endif /* ====================================================================== */ /* * auth = ("Authorization" | "Encryption" | * "Proxy-Authenticate" | "Proxy-Authorization" | * "Response-Key" | "WWW-Authenticate") ":" * scheme 1*SP #auth-param * scheme = token * auth-param = token | token "=" token | token "=" quoted-string */ /** Parse security headers. */ issize_t msg_auth_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { msg_auth_t *au = (msg_auth_t *)h; au->au_scheme = s; skip_token(&s); if (!IS_LWS(*s)) return -1; *s++ = '\0'; /* NUL-terminate scheme */ return msg_commalist_d(home, &s, (msg_param_t **)&au->au_params, NULL /* msg_auth_item_scan */); } issize_t msg_auth_e(char b[], isize_t bsiz, msg_header_t const *h, int f) { msg_auth_t const *au = (msg_auth_t *)h; int compact = MSG_IS_COMPACT(f); char *b0 = b, *end = b + bsiz; MSG_STRING_E(b, end, au->au_scheme); if (au->au_params) { MSG_CHAR_E(b, end, ' '); MSG_COMMALIST_E(b, end, au->au_params, compact); } MSG_TERM_E(b, end); return b - b0; } /**@internal * Extra size of a msg_auth_t object. * * This function calculates extra size required by a msg_auth_t object. * * @param a pointer to a msg_auth_t object * * @return * Size of strings related to msg_auth_t object. */ isize_t msg_auth_dup_xtra(msg_header_t const *h, isize_t offset) { msg_auth_t const *au = (msg_auth_t *)h; MSG_PARAMS_SIZE(offset, au->au_params); offset += MSG_STRING_SIZE(au->au_scheme); return offset; } /**Duplicate one msg_auth_t object. */ char *msg_auth_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra) { msg_auth_t *au = (msg_auth_t *)dst; msg_auth_t const *o = (msg_auth_t const *)src; char *end = b + xtra; b = msg_params_dup(&au->au_params, o->au_params, b, xtra); MSG_STRING_DUP(b, au->au_scheme, o->au_scheme); assert(b <= end); (void)end; return b; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/msg_basic.c000066400000000000000000000234551223300710500224440ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@ingroup msg_headers * @CFILE msg_basic.c * @brief Basic header handling. * * This file contains implementation of basic headers, that is, generic * headers like Subject or Organization containing non-structured text only, * numeric headers like Content-Length or Max-Forwards containing only an * 32-bit unsigned integer, or token list headers like Supported or Allow. * * @author Pekka Pessi * * @date Created: Fri Feb 23 19:51:55 2001 ppessi */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #define msg_generic_update NULL /* ====================================================================== */ /**@ingroup msg_headers * @defgroup msg_error Erroneous Headers * * The erroneous headers are stored in #msg_error_t structure. * * @note Parser may put other headers (like duplicate Content-Length * headers) into the list of erroneous headers. If the list of erroneous * headers is processed, the header type must be validated first by calling * msg_is_error() (or by other relevant tests). */ /**@ingroup msg_error * @typedef typedef struct msg_error_s msg_error_t; * Type for erroneous headers. */ isize_t msg_error_dup_xtra(msg_header_t const *h, isize_t offset); char *msg_error_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra); msg_hclass_t msg_error_class[] = MSG_HEADER_CLASS(msg_, error, "", "", er_common, append, msg_error, msg_generic); issize_t msg_error_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { return 0; } issize_t msg_error_e(char b[], isize_t bsiz, msg_header_t const *h, int flags) { /* There is no way to encode an erroneous header */ return 0; } isize_t msg_error_dup_xtra(msg_header_t const *h, isize_t offset) { return msg_default_dup_xtra(h, offset); } char *msg_error_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra) { return msg_default_dup_one(dst, src, b, xtra); } /* ====================================================================== */ /**@ingroup msg_headers * @defgroup msg_unknown Unknown Headers * * The unknown headers are handled with #msg_unknown_t structure. The whole * unknown header including its name is included in the header value string * @a g_value. * * @note It is possible to speed up parsing process by creating a parser * which does understand only a minimum number of headers. If such a parser * is used, some well-known headers are not regocnized or parser, but they * are treated as unknown and put unparsed into the list of unknown headers. */ /**@ingroup msg_unknown * @typedef typedef struct msg_unknown_s msg_unknown_t; * * Type for unknown headers. */ msg_hclass_t msg_unknown_class[] = MSG_HEADER_CLASS(msg_, unknown, "", "", un_common, append, msg_unknown, msg_generic); issize_t msg_unknown_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { msg_unknown_t *un = (msg_unknown_t *)h; if (msg_token_d(&s, &un->un_name) < 0 || *s != ':') return -1; *s++ = '\0'; skip_lws(&s); un->un_value = s; return 0; } issize_t msg_unknown_e(char b[], isize_t bsiz, msg_header_t const *h, int flags) { char *b0 = b, *end = b + bsiz; msg_unknown_t *un = (msg_unknown_t *)h; int const compact = MSG_IS_COMPACT(flags); MSG_STRING_E(b, end, un->un_name); MSG_CHAR_E(b, end, ':'); if (!compact) MSG_CHAR_E(b, end, ' '); MSG_STRING_E(b, end, un->un_value); return b - b0; } isize_t msg_unknown_dup_xtra(msg_header_t const *h, isize_t offset) { msg_unknown_t const *un = (msg_unknown_t *)h; return offset + MSG_STRING_SIZE(un->un_name) + MSG_STRING_SIZE(un->un_value); } char *msg_unknown_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra) { msg_unknown_t *un = (msg_unknown_t *)dst; msg_unknown_t const *o = (msg_unknown_t *)src; char *end = b + xtra; MSG_STRING_DUP(b, un->un_name, o->un_name); MSG_STRING_DUP(b, un->un_value, o->un_value); assert(b <= end); (void)end; return b; } /* ====================================================================== */ /**@ingroup msg_headers * @defgroup msg_payload Message Body * * The payload object contains the message body. The message body has no * structure, but it is stored in the @a pl_data buffer as a byte array. * Multiple payload objects may be linked to a list. */ /**@ingroup msg_payload * @typedef typedef struct msg_payload_s msg_payload_t; * * The structure msg_payload_t contains representation of MIME message payload. * * The msg_payload_t is defined as follows: * @code * typedef struct msg_payload_s { * msg_common_t pl_common[1]; // Common fragment info * msg_header_t *pl_next; // Next payload object * char *pl_data; // Data - may contain zero bytes * usize_t pl_len; // Length of message payload * } msg_payload_t; * @endcode */ msg_hclass_t msg_payload_class[1] = MSG_HEADER_CLASS(msg_, payload, NULL, "", pl_common, append, msg_payload, msg_generic); /** Create a MIME payload */ msg_payload_t *msg_payload_create(su_home_t *home, void const *data, usize_t len) { msg_header_t *h = msg_header_alloc(home, msg_payload_class, len + 1); if (h) { msg_payload_t *pl = (msg_payload_t *)h; char *b = msg_header_data(h->sh_common); if (data) memcpy(b, data, len); else memset(b, 0, len); b[len] = 0; h->sh_data = pl->pl_data = b; h->sh_len = pl->pl_len = len; return pl; } return NULL; } /** Parse payload. */ issize_t msg_payload_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { msg_payload_t *pl = (msg_payload_t *)h; pl->pl_len = slen; pl->pl_data = s; h->sh_len = slen; h->sh_data = s; return 0; } issize_t msg_payload_e(char b[], isize_t bsiz, msg_header_t const *h, int flags) { msg_payload_t *pl = (msg_payload_t *)h; size_t len = pl->pl_len; if (bsiz > 0) { if (len < bsiz) memcpy(b, pl->pl_data, len), b[len] = '\0'; else memcpy(b, pl->pl_data, bsiz - 1), b[bsiz - 1] = '\0'; } return len; } isize_t msg_payload_dup_xtra(msg_header_t const *h, isize_t offset) { msg_payload_t *pl = (msg_payload_t *)h; return offset + pl->pl_len + 1; } char *msg_payload_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra) { msg_payload_t *pl = (msg_payload_t *)dst; msg_payload_t const *o = (msg_payload_t const *)src; memcpy(pl->pl_data = b, o->pl_data, pl->pl_len = o->pl_len); dst->sh_data = pl->pl_data; dst->sh_len = pl->pl_len; pl->pl_data[pl->pl_len] = 0; /* NUL terminate just in case */ return b + pl->pl_len + 1; } usize_t msg_payload_length(msg_payload_t const *pl) { /* XXX */ return 0; } /* ====================================================================== */ /**@ingroup msg_headers * @defgroup msg_separator Message Separator * * An empty line separates headers from the message body. In order to avoid * modifying messages with integrity protection, the separator line has its * own header structure which is included in the msg_t structure. */ /**@ingroup msg_separator * @typedef typedef struct msg_separator_s msg_separator_t; * * The structure msg_separator_t contains representation of separator line * between message headers and body. * * The msg_separator_t is defined as follows: * @code * typedef struct msg_separator_s { * msg_common_t sep_common[1]; // Common fragment info * msg_header_t *sep_next; // Pointer to next header * char sep_data[4]; // NUL-terminated separator * } msg_separator_t; * @endcode */ msg_hclass_t msg_separator_class[] = MSG_HEADER_CLASS(msg_, separator, NULL, "", sep_common, single, msg_default, msg_generic); /** Calculate length of line ending (0, 1 or 2). @internal */ #define CRLF_TEST(s) ((s[0]) == '\r' ? ((s[1]) == '\n') + 1 : (s[0])=='\n') /** Parse a separator line. */ issize_t msg_separator_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { int len = CRLF_TEST(s); msg_separator_t *sep = (msg_separator_t *)h; if (len == 0 && slen > 0) return -1; memcpy(sep->sep_data, s, len); sep->sep_data[len] = '\0'; return 0; } /** Encode a separator line. */ issize_t msg_separator_e(char b[], isize_t bsiz, msg_header_t const *h, int flags) { msg_separator_t const *sep = (msg_separator_t const *)h; size_t n = strlen(sep->sep_data); if (bsiz > n) strcpy(b, sep->sep_data); return (issize_t)n; } msg_separator_t *msg_separator_create(su_home_t *home) { msg_separator_t *sep; sep = (msg_separator_t *)msg_header_alloc(home, msg_separator_class, 0); if (sep) strcpy(sep->sep_data, CRLF); return sep; } /* ====================================================================== */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/msg_date.c000066400000000000000000000255101223300710500222720ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@ingroup msg_parser * @CFILE msg_date.c * @brief Parser for HTTP-Date and HTTP-Delta. * * Parsing functions for @RFC1123 (GMT) date. * * @author Pekka Pessi * * @date Created: Wed Apr 11 18:57:06 2001 ppessi * */ #include "config.h" #include #include #include #include #include #include #include #include #include /** Return current time as seconds since Mon, 01 Jan 1900 00:00:00 GMT. */ msg_time_t msg_now(void) { return su_now().tv_sec; } #define is_digit(c) ((c) >= '0' && (c) <= '9') /**Epoch year. @internal * * First day of the epoch year should be Monday. */ #define EPOCH 1900 /** Is this year a leap year? @internal */ #define LEAP_YEAR(y) ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0)) /** Day number of New Year Day of given year. @internal */ #define YEAR_DAYS(y) \ (((y)-1) * 365 + ((y)-1) / 4 - ((y)-1) / 100 + ((y)-1) / 400) /* ====================================================================== */ static unsigned char const days_per_months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; /** Offset of first day of the month with formula day = 30 * month + offset. */ static signed char const first_day_offset[12] = { 0, 1, -1, 0, 0, 1, 1, 2, 3, 3, 4, 4 }; static char const wkdays[7 * 4] = "Mon\0" "Tue\0" "Wed\0" "Thu\0" "Fri\0" "Sat\0" "Sun"; static char const months[12 * 4] = "Jan\0" "Feb\0" "Mar\0" "Apr\0" "May\0" "Jun\0" "Jul\0" "Aug\0" "Sep\0" "Oct\0" "Nov\0" "Dec"; /** Parse a month name. * * @return The function month_d() returns 0..11 if given first three letters * of month name, or -1 if no month name matches. */ su_inline int month_d(char const *s) { unsigned const uc = ('a' - 'A') << 16 | ('a' - 'A') << 8 | ('a' - 'A'); unsigned m; if (!s[0] || !s[1] || !s[2]) return -1; #define MONTH_V(s) (uc | (((s[0]) << 16) + ((s[1]) << 8) + ((s[2])))) m = MONTH_V(s); #define MONTH_D(n) \ if (m == (uc | (months[4*(n)]<<16)|(months[4*(n)+1]<<8)|(months[4*(n)+2])))\ return (n) MONTH_D(0); MONTH_D(1); MONTH_D(2); MONTH_D(3); MONTH_D(4); MONTH_D(5); MONTH_D(6); MONTH_D(7); MONTH_D(8); MONTH_D(9); MONTH_D(10); MONTH_D(11); return -1; } /* Parse SP 2DIGIT ":" 2DIGIT ":" 2DIGIT SP */ su_inline int time_d(char const **ss, unsigned long *hour, unsigned long *min, unsigned long *sec) { char const *s = *ss; if (!IS_LWS(*s)) return -1; skip_lws(&s); if (!is_digit(*s)) return -1; *hour = *s++ - '0'; if (is_digit(*s)) *hour = 10 * (*hour) + *s++ - '0'; if (*s++ != ':' || !is_digit(s[0]) || !is_digit(s[1])) return -1; *min = 10 * s[0] + s[1] - 11 * '0'; s += 2; if (*s++ != ':' || !is_digit(s[0]) || !is_digit(s[1])) return -1; *sec = 10 * s[0] + s[1] - 11 * '0'; s += 2; if (*s) { if (!IS_LWS(*s)) return -1; skip_lws(&s); } *ss = s; return 0; } /**Decode RFC1123-date, RFC822-date or asctime-date. * * The function msg_date_d() decodes , which may have * different formats. * * @code * HTTP-date = rfc1123-date / rfc850-date / asctime-date * * rfc1123-date = wkday "," SP date1 SP time SP "GMT" * date1 = 2DIGIT SP month SP 4DIGIT * ; day month year (e.g., 02 Jun 1982) * * rfc850-date = weekday "," SP date2 SP time SP "GMT" * date2 = 2DIGIT "-" month "-" 2DIGIT * ; day-month-year (e.g., 02-Jun-82) * * asctime-date = wkday SP date3 SP time SP 4DIGIT * date3 = month SP ( 2DIGIT / ( SP 1DIGIT )) * ; month day (e.g., Jun 2) * * time = 2DIGIT ":" 2DIGIT ":" 2DIGIT * ; 00:00:00 - 23:59:59 * * wkday = "Mon" / "Tue" / "Wed" / "Thu" / "Fri" / "Sat" / "Sun" * weekday = "Monday" / "Tuesday" / "Wednesday" * / "Thursday" / "Friday" / "Saturday" / "Sunday" * month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" * / "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec" * @endcode */ issize_t msg_date_d(char const **ss, msg_time_t *date) { char const *s = *ss; char const *wkday; char const *tz; unsigned long day, year, hour, min, sec; int mon; if (!IS_TOKEN(*s) || !date) return -1; wkday = s; skip_token(&s); if (*s == ',') s++; while (IS_LWS(*s)) s++; if (is_digit(*s)) { day = *s++ - '0'; if (is_digit(*s)) day = 10 * day + *s++ - '0'; if (*s == ' ') { /* rfc1123-date = wkday "," SP 2DIGIT SP month SP 4DIGIT SP time SP "GMT" */ mon = month_d(++s); skip_token(&s); if (mon < 0 || !IS_LWS(*s)) return -1; s++; if (!is_digit(s[0]) || !is_digit(s[1]) || !is_digit(s[2]) || !is_digit(s[3])) return -1; year = 1000 * s[0] + 100 * s[1] + 10 * s[2] + s[3] - 1111 * '0'; s += 4; } else if (*s == '-') { /* rfc822-date = weekday "," SP 2DIGIT "-" month "-" 2DIGIT SP time SP "GMT" */ mon = month_d(++s); if (mon < 0 || s[3] != '-' || !is_digit(s[4]) || !is_digit(s[5])) return -1; year = 10 * s[4] + s[5] - 11 * '0'; if (is_digit(s[6]) && is_digit(s[7])) { /* rfc2822-date = weekday "," SP 2DIGIT "-" month "-" 4DIGIT SP time SP "GMT" */ year = year * 100 + 10 * s[6] + s[7] - 11 * '0'; s += 8; } else { if (year >= 70) year = 1900 + year; else year = 2000 + year; s += 6; } } else return -1; if (time_d(&s, &hour, &min, &sec) < 0) return -1; if (*s) { tz = s; skip_token(&s); skip_lws(&s); if (!su_casenmatch(tz, "GMT", 3) && !su_casenmatch(tz, "UCT", 3)) return -1; } } else { /* actime-date = wkday SP month SP ( 2DIGIT | ( SP 1DIGIT )) SP time SP 4DIGIT */ mon = month_d(s); skip_token(&s); if (mon < 0 || !IS_LWS(*s)) return -1; s++; while (IS_LWS(*s)) s++; if (!is_digit(*s)) return -1; day = *s++ - '0'; if (is_digit(*s)) day = 10 * day + *s++ - '0'; if (time_d(&s, &hour, &min, &sec) < 0) return -1; /* Accept also unix date (if it is GMT) */ if ((s[0] == 'G' && s[1] == 'M' && s[2] == 'T' && s[3] == ' ') || (s[0] == 'U' && s[1] == 'T' && s[2] == 'C' && s[3] == ' ')) s += 4; else if (s[0] == 'U' && s[1] == 'T' && s[2] == ' ') s += 3; if (!is_digit(s[0]) || !is_digit(s[1]) || !is_digit(s[2]) || !is_digit(s[3])) return -1; year = 1000 * s[0] + 100 * s[1] + 10 * s[2] + s[3] - 1111 * '0'; s += 4; } if (hour > 24 || min >= 60 || sec >= 60 || (hour == 24 && min > 0 && sec > 0)) return -1; if (day == 0 || day > days_per_months[mon]) { if (day != 29 || mon != 1 || !LEAP_YEAR(year)) return -1; } if (year < EPOCH) { *date = 0; } else if (year > EPOCH + 135) { *date = 0xfdeefb80; /* XXX: EPOCH + 135 years */ } else { int leap_year = LEAP_YEAR(year); msg_time_t ydays = YEAR_DAYS(year) - YEAR_DAYS(EPOCH); #if 0 printf("Year %d%s starts %ld = %d - %d days since epoch (%d)\n", year, leap_year ? " (leap year)" : "", ydays, YEAR_DAYS(year), YEAR_DAYS(EPOCH), EPOCH); #endif *date = sec + 60 * (min + 60 * (hour + 24 * (day - 1 + mon * 30 + first_day_offset[mon] + (leap_year && mon > 2) + ydays))); } *ss = s; return 0; } /**Encode RFC1123-date. * * The function msg_date_e() prints @e http-date in the * format. The format is as follows: * * @code * rfc1123-date = wkday "," SP date SP time SP "GMT" * wkday = "Mon" | "Tue" | "Wed" * | "Thu" | "Fri" | "Sat" | "Sun" * date = 2DIGIT SP month SP 4DIGIT * ; day month year (e.g., 02 Jun 1982) * month = "Jan" | "Feb" | "Mar" | "Apr" * | "May" | "Jun" | "Jul" | "Aug" * | "Sep" | "Oct" | "Nov" | "Dec" * time = 2DIGIT ":" 2DIGIT ":" 2DIGIT * ; 00:00:00 - 23:59:59 * @endcode * * @param b buffer to print the date * @param bsiz size of the buffer * @param http_date seconds since 01 Jan 1900. * * @return The function msg_date_e() returns the size of the formatted date. */ issize_t msg_date_e(char b[], isize_t bsiz, msg_time_t http_date) { msg_time_t sec, min, hour, wkday, day, month, year; msg_time_t days_per_month, leap_year; sec = http_date % 60; http_date /= 60; min = http_date % 60; http_date /= 60; hour = http_date % 24; http_date /= 24; wkday = http_date % 7; day = http_date + YEAR_DAYS(EPOCH); year = EPOCH + http_date / 365; for (;;) { if (day >= YEAR_DAYS(year + 1)) year++; else if (day < YEAR_DAYS(year)) year--; else break; } day -= YEAR_DAYS(year); leap_year = LEAP_YEAR(year); month = 0, days_per_month = 31; while (day >= days_per_month) { day -= days_per_month; month++; days_per_month = days_per_months[month] + (leap_year && month == 2); } return snprintf(b, bsiz, "%s, %02ld %s %04ld %02ld:%02ld:%02ld GMT", wkdays + wkday * 4, day + 1, months + month * 4, year, hour, min, sec); } /**Decode a delta-seconds. * * The function msg_delta_d() decodes a field. * * The is defined as follows: * @code * delta-seconds = 1*DIGIT * @endcode * * Note, however, that may not be larger than #MSG_TIME_MAX. */ issize_t msg_delta_d(char const **ss, msg_time_t *delta) { char const *s = *ss; if (!is_digit(*s)) return -1; *delta = strtoul(*ss, (char **)ss, 10); skip_lws(ss); return *ss - s; } /**Encode @ref msg_delta_d() "" field. */ issize_t msg_delta_e(char b[], isize_t bsiz, msg_time_t delta) { return snprintf(b, bsiz, "%lu", (unsigned long)delta); } /** Decode a HTTP date or delta * * Decode a @ref msg_date_d() "" or * @ref msg_delta_d() "" field. */ issize_t msg_date_delta_d(char const **ss, msg_time_t *date, msg_time_t *delta) { if (delta && is_digit(**ss)) { return msg_delta_d(ss, delta); } else if (date && IS_TOKEN(**ss)) { return msg_date_d(ss, date); } return -1; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/msg_generic.c000066400000000000000000000132411223300710500227670ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@internal * @ingroup msg_parser * @file msg_generic.c * @brief Functions for generic headers * * @author Pekka Pessi * * @date Created: Thu Jan 23 20:08:00 2003 ppessi * */ #include "config.h" #include #include "sofia-sip/msg.h" #include "sofia-sip/bnf.h" #include "sofia-sip/msg_parser.h" #include "sofia-sip/msg_header.h" #include #include #include #include #include #include #include /** * Parse a generic header. * * The function msg_generic_d() parses a generic header structure. * * @param[in] home memory home * @param[in,out] h header structure * @param[in] s string to be parsed * @param[in] slen length of the string * * @retval 0 when successful, * @retval -1 upon an error. */ issize_t msg_generic_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { msg_generic_t *g = (msg_generic_t *)h; g->g_string = s; return 0; } /** * Encode a generic header. * * The function @c msg_generic_e encodes a generic header. * */ issize_t msg_generic_e(char b[], isize_t bsiz, msg_header_t const *h, int flags) { msg_generic_t const *g = (msg_generic_t const *)h; size_t n = strlen(g->g_string); if (bsiz > n) strcpy(b, g->g_string); return (issize_t)n; } /** Calculate the size of strings associated with a @c msg_generic_t object. */ isize_t msg_generic_dup_xtra(msg_header_t const *h, isize_t offset) { msg_generic_t const *g = (msg_generic_t const *)h; return offset + MSG_STRING_SIZE(g->g_string); } /** Duplicate one @c msg_generic_t object. */ char *msg_generic_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra) { msg_generic_t *g = (msg_generic_t *)dst; msg_generic_t const *o = (msg_generic_t const *)src; char *end = b + xtra; MSG_STRING_DUP(b, g->g_string, o->g_string); assert(b <= end); (void)end; return b; } issize_t msg_numeric_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { msg_numeric_t *x = (msg_numeric_t *)h; uint32_t value = 0; issize_t retval = msg_uint32_d(&s, &value); assert(h->sh_class->hc_size >= sizeof *x); x->x_value = value; if (*s) return -1; return retval; } issize_t msg_numeric_e(char b[], isize_t bsiz, msg_header_t const *h, int flags) { msg_numeric_t *x = (msg_numeric_t *)h; assert(x->x_common->h_class->hc_size >= sizeof *x); if (x->x_value > 0xffffffffU) return -1; return snprintf(b, bsiz, "%lu", x->x_value); } /* ====================================================================== */ /* Comma-separated list */ /** @typedef struct msg_list_s msg_list_t; * * Type for token list headers. * */ issize_t msg_list_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { msg_list_t *k = (msg_list_t *)h; return msg_commalist_d(home, &s, &k->k_items, NULL); } issize_t msg_list_e(char b[], isize_t bsiz, msg_header_t const *h, int flags) { msg_list_t *k = (msg_list_t *)h; int compact = MSG_IS_COMPACT(flags); char *b0 = b, *end = b + bsiz; MSG_COMMALIST_E(b, end, k->k_items, compact); MSG_TERM_E(b, end); return b - b0; } /**@internal * Extra size of a msg_auth_t object. * * This function calculates extra size required by a msg_auth_t object. * * @param a pointer to a msg_auth_t object * * @return * Size of strings related to msg_auth_t object. */ isize_t msg_list_dup_xtra(msg_header_t const *h, isize_t offset) { msg_list_t const *k = (msg_list_t const *)h; MSG_PARAMS_SIZE(offset, k->k_items); return offset; } char *msg_list_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra) { msg_list_t *k = (msg_list_t *)dst; msg_list_t const *o = (msg_list_t const *)src; char *end = b + xtra; msg_param_t const ** items = (msg_param_t const **)&k->k_items; b = msg_params_dup(items, o->k_items, b, xtra); assert(b <= end); (void)end; return b; } /** Append a list of constant items to a list. * * @retval 0 when successful * @retval -1 upon an error */ int msg_list_append_items(su_home_t *home, msg_list_t *k, msg_param_t const items[]) { size_t i; if (k == NULL) return -1; if (items == NULL) return 0; for (i = 0; items[i]; i++) { if (msg_header_add_param(home, (msg_common_t *)k, items[i]) < 0) return -1; } return 0; } /** Replace a list of constant items. * * @retval 0 when successful * @retval -1 upon an error */ int msg_list_replace_items(su_home_t *home, msg_list_t *k, msg_param_t const items[]) { size_t i; if (k == NULL) return -1; if (items == NULL) return 0; for (i = 0; items[i]; i++) { if (msg_header_replace_item(home, (msg_common_t *)k, items[i]) < 0) return -1; } return 0; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/msg_header_copy.c000066400000000000000000000310641223300710500236400ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@ingroup msg_headers * @CFILE msg_header_copy.c * * Copying and duplicating headers structures. * * @author Pekka Pessi * * @date Created: Tue Jun 13 02:57:51 2000 ppessi * */ #include "config.h" #include #include #include #include #include #include #include #include "msg_internal.h" #include "sofia-sip/msg.h" #include "sofia-sip/msg_parser.h" #include "sofia-sip/msg_header.h" /** Calculate size of a parameter vector */ su_inline size_t msg_params_copy_xtra(msg_param_t const pp[], size_t offset) { size_t n = msg_params_count(pp); if (n) { MSG_STRUCT_SIZE_ALIGN(offset); offset += MSG_PARAMS_NUM(n + 1) * sizeof(pp[0]); } return offset; } /** Copy a vector of parameters */ su_inline char *msg_params_copy(char *b, size_t size, msg_param_t **dst, msg_param_t const src[]) { size_t n = msg_params_count(src); if (n) { MSG_STRUCT_ALIGN(b); *dst = memcpy(b, src, (n + 1) * sizeof(src[0])); b += MSG_PARAMS_NUM(n + 1) * sizeof(src[0]); } else { *dst = NULL; } return b; } /**Copy a header object. * * The function @c msg_header_copy_as() shallowly copies a header object. * * @param home pointer to the memory home * @param hc header class for the copied header * @param src pointer to a header object * * @return * The function @c msg_header_copy_as() returns a pointer to the the shallow copy * of the header object, or @c NULL upon an error. */ static msg_header_t *msg_header_copy_one_as(su_home_t *home, msg_hclass_t *hc, msg_header_t const *src) { msg_header_t *h; size_t size = hc->hc_size, xtra; msg_param_t const *params; char *end; if (hc->hc_params) { params = *(msg_param_t const **)((char const *)src + hc->hc_params); xtra = msg_params_copy_xtra(params, size) - size; } else { params = NULL; xtra = 0; } if (!(h = msg_header_alloc(home, hc, (isize_t)xtra))) return NULL; /* error */ memcpy(&h->sh_data, &src->sh_data, size - offsetof(msg_common_t, h_data)); h->sh_next = NULL; if (params) { msg_param_t **pparams = (msg_param_t **)((char *)h + hc->hc_params); end = msg_params_copy((char *)h + size, xtra, pparams, params); if (!end) { su_free(home, h); return NULL; } } else end = (char *)h + size; assert(end == (char *)h + xtra + size); return h; } /**Copy a list of header objects. * * The function @c msg_header_copy_as() shallowly copies a list of header * objects, and casts them to the given header class. * * @param home pointer to the memory home * @param hc header class * @param src pointer to a list of header objects to be copied * * @return The function @c msg_header_copy_as() returns a pointer to the * first of the copied msg header object(s), or @c NULL upon an error. */ msg_header_t *msg_header_copy_as(su_home_t *home, msg_hclass_t *hc, msg_header_t const *src) { msg_header_t *h, *rv = NULL, *prev = NULL; if (src == NULL || src == MSG_HEADER_NONE) return NULL; if (hc == NULL) hc = src->sh_class; for (; src; src = src->sh_next, prev = h) { if (!(h = msg_header_copy_one_as(home, hc, src))) break; if (!rv) rv = h; else prev->sh_next = h; } if (src) { /* Copy was not successful, free all copied headers in list */ for (;rv; rv = h) { h = rv->sh_next; su_free(home, rv); } } return rv; } /** Copy a single header. */ msg_header_t *msg_header_copy_one(su_home_t *home, msg_header_t const *src) { assert(MSG_HEADER_TEST(src)); if (!src || !src->sh_class) return NULL; return msg_header_copy_one_as(home, src->sh_class, src); } /** Copy a header list. */ msg_header_t *msg_header_copy(su_home_t *home, msg_header_t const *src) { assert(MSG_HEADER_TEST(src)); if (!src || !src->sh_class) return NULL; return msg_header_copy_as(home, src->sh_class, src); } /** Duplicate a sigle header. * * Deeply copy a single header. * * @param home pointer to the memory home * @param src pointer to asingle header object to be copied * * @return Return a pointer to the * the duplicated msg header object(s), or @c NULL upon an error. */ msg_header_t *msg_header_dup_one(su_home_t *home, msg_header_t const *src) { msg_hclass_t *hc; size_t size, xtra; msg_header_t *h; char *end; if (src == NULL || src == MSG_HEADER_NONE) return NULL; hc = src->sh_class; assert(hc); size = hc->hc_size; xtra = hc->hc_dxtra(src, size) - size; if (!(h = msg_header_alloc(home, hc, xtra))) return NULL; if (!(end = hc->hc_dup_one(h, src, (char *)h + size, xtra))) { su_free(home, h); return NULL; } if (hc->hc_update) msg_header_update_params(h->sh_common, 1); assert(end == (char *)h + size + xtra); return h; } /** Duplicate a header as class @a hc. * * The function @c msg_header_dup_as() casts a list of header headers to * given type, and then deeply copies the list. * * @param home pointer to the memory home * @param hc header class * @param src pointer to a list of header objects to be copied * * @return The function @c msg_header_copy_as() returns a pointer to the * first of the copied msg header object(s), or @c NULL upon an error. */ msg_header_t *msg_header_dup_as(su_home_t *home, msg_hclass_t *hc, msg_header_t const *src) { msg_header_t *h, *rv = NULL, **prev; if (src == NULL || src == MSG_HEADER_NONE) return NULL; if (hc == NULL) hc = src->sh_class; assert(hc); for (prev = &rv; src; src = src->sh_next, prev = &h->sh_next) { size_t size = hc->hc_size; size_t xtra = hc->hc_dxtra(src, size) - size; char *end; if (!(h = msg_header_alloc(home, hc, (isize_t)xtra))) break; /* error */ if (!rv) rv = h; if (!(end = hc->hc_dup_one(h, src, (char *)h + size, xtra))) break; /* error */ if (hc->hc_update) msg_header_update_params(h->sh_common, 1); assert(end == (char *)h + size + xtra); *prev = h; } if (src) { /* Copy was not successful, free all duplicated headers in list */ for (;rv; rv = h) { h = rv->sh_next; su_free(home, rv); } } return rv; } /** Duplicate a header list. * * The function @c msg_header_dup() deeply copies a list of message headers * objects. * * @param home pointer to the memory home * @param h pointer to a list of header objects to be copied * * @return The function @c msg_header_dup() returns a pointer to the first * of the copied message header object(s), or @c NULL upon an error. */ msg_header_t *msg_header_dup(su_home_t *home, msg_header_t const *h) { if (h == NULL || h == MSG_HEADER_NONE) return NULL; assert(MSG_HEADER_TEST(h)); return msg_header_dup_as(home, h->sh_class, h); } /** Calculate extra size of a plain header. */ isize_t msg_default_dup_xtra(msg_header_t const *header, isize_t offset) { return offset; } /**Duplicate a header object without external references. * * The function @c msg_default_dup_one() copies the contents of header * object @a src to @a h. The header object should not contain external * references (pointers). * * @param h pointer to newly allocated header object * @param src pointer to a header object to be duplicated * @param b memory buffer used to copy (not used) * @param xtra number bytes in buffer @a b (not used) * * @return The function @c msg_default_dup_one() returns a pointer to the * memory buffer @a b. */ char *msg_default_dup_one(msg_header_t *h, msg_header_t const *src, char *b, isize_t xtra) { size_t skip = offsetof(msg_numeric_t, x_value); /* Skip common part */ memcpy((char *)h + skip, (char const *)src + skip, h->sh_class->hc_size - skip); return b; } /* ====================================================================== */ /* Copying or duplicating all headers in a message */ static int msg_copy_chain(msg_t *msg, msg_t const *copied); static int msg_dup_or_copy_all(msg_t *msg, msg_t const *original, msg_header_t *(*copy_one)(su_home_t *h, msg_header_t const *)); /**Copy a message shallowly. * * @relatesalso msg_s * * Copy a message and the header structures. The copied message will share * all the strings with the original message. It will keep a reference to * the original message, and the original message is not destroyed until all * the copies have been destroyed. * * @param original message to be copied * * @retval pointer to newly copied message object when successful * @retval NULL upon an error */ msg_t *msg_copy(msg_t *original) { if (original) { msg_t *copy = msg_create(original->m_class, original->m_object->msg_flags); if (copy) { if (original->m_chain ? msg_copy_chain(copy, original) < 0 : msg_dup_or_copy_all(copy, original, msg_header_copy_one) < 0) { msg_destroy(copy), copy = NULL; } else msg_set_parent(copy, original); return copy; } } return NULL; } /** Copy header chain. * * @retval 0 when successful * @retval -1 upon an error */ static int msg_copy_chain(msg_t *msg, msg_t const *original) { su_home_t *home = msg_home(msg); msg_pub_t *dst = msg->m_object; msg_header_t **tail; msg_header_t *dh; msg_header_t const *sh; msg_header_t **hh; tail = msg->m_tail; for (sh = original->m_chain; sh; sh = (msg_header_t const *)sh->sh_succ) { hh = msg_hclass_offset(msg->m_class, dst, sh->sh_class); if (!hh) break; while (*hh) hh = &(*hh)->sh_next; dh = msg_header_copy_one(home, sh); if (!dh) break; dh->sh_prev = tail, *tail = dh, tail = &dh->sh_succ; *hh = dh; } msg->m_tail = tail; if (sh) return -1; return 0; } /**Deep copy a message. * * @relatesalso msg_s * * Copy a message, the header structures and all the related strings. The * duplicated message does not share any (non-const) data with original. * Note that the cached representation (in h_data) is not copied. * * @param original message to be duplicated * * @retval pointer to newly duplicated message object when successful * @retval NULL upon an error */ msg_t *msg_dup(msg_t const *original) { if (original) { msg_t *dup = msg_create(original->m_class, original->m_object->msg_flags); if (dup && msg_dup_or_copy_all(dup, original, msg_header_dup_one) < 0) { msg_destroy(dup), dup = NULL; } return dup; } return NULL; } /** Copy a complete message, not keeping the header chain structure. * * @retval 0 when successful * @retval -1 upon an error */ static int msg_dup_or_copy_all(msg_t *msg, msg_t const *original, msg_header_t *(*copy_one)(su_home_t *h, msg_header_t const *)) { su_home_t *home = msg_home(msg); msg_pub_t *dst = msg->m_object; msg_pub_t const *src = original->m_object; msg_header_t * const *ssh; msg_header_t * const *end; msg_header_t const *sh; msg_header_t **hh; msg_header_t *h; assert(copy_one); end = (msg_header_t**)((char *)src + src->msg_size); for (ssh = &src->msg_request; ssh < end; ssh++) { sh = *ssh; if (!sh) continue; hh = msg_hclass_offset(msg->m_class, dst, sh->sh_class); if (hh == NULL) return -1; for (; sh; sh = sh->sh_next) { h = copy_one(home, sh); if (h == NULL) return -1; if (*hh) { /* If there is multiple instances of single headers, put the extra headers into the list of erroneous headers */ if (msg_is_single(h)) { msg_error_t **e; for (e = &dst->msg_error; *e; e = &(*e)->er_next) ; *e = (msg_error_t *)h; continue; } while (*hh) hh = &(*hh)->sh_next; } *hh = h; if (msg_is_list(sh)) /* Copy only first list entry */ break; } } return 0; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/msg_header_make.c000066400000000000000000000077751223300710500236170ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@ingroup msg_headers * @CFILE msg_header_make.c * * Creating message headers from strings. * * @author Pekka Pessi * * @date Created: Fri Feb 23 14:06:34 2001 ppessi * */ #include "config.h" #include #include "sofia-sip/msg.h" #include "sofia-sip/bnf.h" #include "sofia-sip/msg_parser.h" #include "sofia-sip/msg_header.h" #include #include #include #include #include #include #include #if defined(va_copy) /* Xyzzy */ #elif defined(__va_copy) #define va_copy(dst, src) __va_copy((dst), (src)) #else #define va_copy(dst, src) (memcpy(&(dst), &(src), sizeof (va_list))) #endif #include /** Make a header from a value string. */ msg_header_t *msg_header_make(su_home_t *home, msg_hclass_t *hc, char const *s) { size_t xtra; msg_header_t *h; int normal = hc->hc_name || (hc->hc_hash != msg_payload_hash && hc->hc_hash != msg_separator_hash && hc->hc_hash != msg_error_hash); if (s == NULL) return NULL; /* For normal headers, strip LWS from both ends */ if (normal) skip_lws(&s); xtra = strlen(s); if (normal) while (xtra > 0 && IS_LWS(s[xtra - 1])) xtra--; h = msg_header_alloc(home, hc, xtra + 1); if (h) { char *b = MSG_HEADER_DATA(h); strncpy(b, s, xtra)[xtra] = 0; if (hc->hc_parse(home, h, b, xtra) == -1) { /* Note: parsing function is responsible to free everything it has allocated (like parameter lists) */ /* XXX - except header structures */ su_free(home, h), h = NULL; } } return h; } /** Make a MSG header with formatting provided. */ msg_header_t *msg_header_vformat(su_home_t *home, msg_hclass_t *hc, char const *fmt, va_list ap) { msg_header_t *h; int n; size_t xtra = 64; /* reasonable default */ /* Quick path */ if (!fmt || !strchr(fmt, '%')) return msg_header_make(home, hc, fmt); /* Another quickie */ if (strcmp(fmt, "%s") == 0) { fmt = va_arg(ap, char const *); return msg_header_make(home, hc, fmt); } if (!(h = msg_header_alloc(home, hc, xtra))) return NULL; for (;;) { va_list aq; va_copy(aq, ap); n = vsnprintf(MSG_HEADER_DATA(h), xtra, fmt, aq); va_end(aq); if (n >= 0 && (size_t)n < xtra) break; /* Try again with more space */ su_free(home, h); if (xtra >= INT_MAX) return NULL; if (n >= 0) xtra = n + 1; /* precisely what is needed */ else xtra *= 2; /* glibc 2.0 - twice the old size */ if (xtra > INT_MAX) xtra = INT_MAX; if (!(h = msg_header_alloc(home, hc, xtra))) return NULL; } if (hc->hc_parse(home, h, MSG_HEADER_DATA(h), (size_t)n) == -1) { /* Note: parsing function is responsible to free everything it has allocated (like parameter lists) */ su_free(home, h), h = NULL; } return h; } msg_header_t *msg_header_format(su_home_t *home, msg_hclass_t *hc, char const *fmt, ...) { msg_header_t *h; va_list ap; va_start(ap, fmt); h = msg_header_vformat(home, hc, fmt, ap); va_end(ap); return h; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/msg_inlined.c000066400000000000000000000023221223300710500227730ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2007 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE msg_inlined.c * * Expand inlined msg functions non-inline. * */ #include "config.h" #include #if SU_HAVE_INLINE extern int xyzzy; #else #undef SU_HAVE_INLINE #undef su_inline #define SU_HAVE_INLINE 1 #define su_inline #include "sofia-sip/msg_header.h" #include "sofia-sip/msg_mime_protos.h" #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/msg_internal.h000066400000000000000000000107321223300710500231760ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef MSG_INTERNAL_H /** Defined when has been included. */ #define MSG_INTERNAL_H /**@IFILE msg_internal.h * @brief Abstract messages - internal interface * * @author Pekka Pessi * * @date Created: Thu Jun 29 15:58:06 2000 ppessi * */ #ifdef MSG_H #error "msg_internal.h" should be included before "msg.h" #endif #include "sofia-sip/msg.h" #include "sofia-sip/msg_addr.h" #include "sofia-sip/msg_buffer.h" #ifndef SU_ALLOC_H #include #endif SOFIA_BEGIN_DECLS /* ---------------------------------------------------------------------- */ /* Types used when handling streaming */ typedef struct msg_buffer_s msg_buffer_t; /* ---------------------------------------------------------------------- */ struct msg_s { su_home_t m_home[1]; /**< Memory home */ msg_mclass_t const *m_class; /**< Message class */ int m_oflags; /**< Original flags */ msg_pub_t *m_object; /**< Public view to parsed message */ size_t m_maxsize;/**< Maximum size */ size_t m_size; /**< Total size of fragments */ msg_header_t *m_chain; /**< Fragment chain */ msg_header_t **m_tail; /**< Tail of fragment chain */ msg_payload_t *m_chunk; /**< Incomplete payload fragment */ /* Parsing/printing buffer */ struct msg_mbuffer_s { char *mb_data; /**< Pointer to data */ usize_t mb_size; /**< Size of buffer */ usize_t mb_used; /**< Used data */ usize_t mb_commit; /**< Data committed to msg */ unsigned mb_eos:1; /**< End-of-stream flag */ unsigned :0; } m_buffer[1]; msg_buffer_t *m_stream; /**< User-provided buffers */ size_t m_ssize; /**< Stream size */ unsigned short m_extract_err; /**< Bitmask of erroneous headers */ /* Internal flags */ unsigned m_set_buffer:1;/**< Buffer has been set */ unsigned m_streaming:1; /**< Use streaming with message */ unsigned m_prepared:1; /**< Prepared/not */ unsigned :0; msg_t *m_next; /**< Next message */ msg_t *m_parent; /**< Reference to a parent message */ int m_refs; /**< Number of references to this message */ su_addrinfo_t m_addrinfo; /**< Message addressing info (protocol) */ su_sockaddr_t m_addr[1]; /**< Message address */ int m_errno; /**< Errno */ }; /** Buffer for message body. */ struct msg_buffer_s { char *b_data; /**< Data - may contain NUL */ size_t b_size; /**< Length of message payload */ size_t b_used; /**< Used data */ size_t b_avail; /**< Available data */ int b_complete; /**< This buffer completes the message */ msg_buffer_t *b_next; /**< Next buffer */ msg_payload_t *b_chunks; /**< List of body chunks */ }; /** Maximum size when streaming. */ #define MSG_SSIZE_MAX (USIZE_MAX) /* ---------------------------------------------------------------------- */ /* Header-kind predicate functions. */ su_inline int msg_is_single(msg_header_t const *h) { return h->sh_class->hc_kind == msg_kind_single; } su_inline int msg_is_prepend(msg_header_t const *h) { return h->sh_class->hc_kind == msg_kind_prepend; } su_inline int msg_is_append(msg_header_t const *h) { return h->sh_class->hc_kind == msg_kind_append || h->sh_class->hc_kind == msg_kind_apndlist; } su_inline int msg_is_list(msg_header_t const *h) { return h->sh_class->hc_kind == msg_kind_list; } su_inline int msg_is_special(msg_header_t const *h) { return h->sh_class->hc_hash < 0; } SOFIA_END_DECLS #endif /* MSG_INTERNAL_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/msg_mclass.c000066400000000000000000000236751223300710500226510ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@ingroup msg_parser * @CFILE msg_mclass.c * * Message factory object. * * @author Pekka Pessi * * @date Created: Wed Jun 5 14:34:24 2002 ppessi */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "msg_internal.h" #include "sofia-sip/msg_parser.h" #include "sofia-sip/msg_mclass.h" #include "sofia-sip/msg_mclass_hash.h" /** Clone a message class. * * @relatesalso msg_mclass_s * * The function msg_mclass_clone() makes a copy of message class object @a * old. It is possible to resize the hash table by giving a non-zero @a * newsize. If @a newsize is 0, the size of hash table is not changed. If @a * empty is true, the copied message class object will not recognize any * headers. This is useful if more fine-grained control of parsing process * is required, for instance. * * @param[in] old pointer to the message class object to be copied * @param[in] newsize size of hash table in the copied object * @param[in] empty if true, resulting copy does not contain any headers * * @return * The function msg_mclass_clone() returns a pointer to a newly * copied message class object, or NULL upon an error. * The returned message class object can be freed with free(). * * @ERRORS * @ERROR ENOMEM * A memory allocation failed. * @ERROR EINVAL * The function was given invalid arguments. * * @note The empty parser can handle request/status line. All headers are * put into list of unknown headers (unless they are malformed, and they are * put into list of erronous headers). However, SIP, RTSP, and HTTP * protocols all require that the parser recognizes @b Content-Length header * before they can extract the message body from the data received from * network. * */ msg_mclass_t *msg_mclass_clone(msg_mclass_t const *old, int newsize, int empty) { size_t size, shortsize; msg_mclass_t *mc; int identical; unsigned short i; if (newsize == 0) newsize = old->mc_hash_size; if (newsize < old->mc_hash_used || (unsigned)newsize > USHRT_MAX / sizeof(msg_header_t *)) { errno = EINVAL; return NULL; } size = offsetof(msg_mclass_t, mc_hash[newsize]); if (old->mc_short) shortsize = MC_SHORT_SIZE * (sizeof old->mc_short[0]); else shortsize = 0; mc = malloc(size + shortsize); identical = newsize == old->mc_hash_size && !empty; if (mc) { if (!identical) { memcpy(mc, old, offsetof(msg_mclass_t, mc_hash)); memset(mc->mc_hash, 0, size - offsetof(msg_mclass_t, mc_hash)); mc->mc_short = NULL; mc->mc_hash_size = newsize; mc->mc_hash_used = 0; for (i = 0; !empty && i < old->mc_hash_size; i++) { msg_mclass_insert(mc, &old->mc_hash[i]); } } else { memcpy(mc, old, size); mc->mc_short = NULL; } if (shortsize) { if (empty) mc->mc_short = memset((char *)mc + size, 0, shortsize); else mc->mc_short = memcpy((char *)mc + size, old->mc_short, shortsize); } } return mc; } /**Add a new header to the message class. * * @relatesalso msg_mclass_s * * Insert a header class @a hc to the message class object @a mc. If the * given @a offset of the header in @ref msg_pub_t "public message * structure" is zero, the function extends the public message structure in * order to store newly inserted header there. * * @param[in,out] mc pointer to a message class object * @param[in] hc pointer to a header class object * @param[in] offset offset of the header in * @ref msg_pub_t "public message structure" * * If the @a offset is 0, the msg_mclass_insert_header() increases size of * the public message structure and places the header at the end of message. * * @return Number of collisions in hash table, or -1 upon an error. * * @deprecated Use msg_mclass_insert_with_mask() instead. */ int msg_mclass_insert_header(msg_mclass_t *mc, msg_hclass_t *hc, unsigned short offset) { return msg_mclass_insert_with_mask(mc, hc, offset, 0); } /**Add a new header to the message class. * * @relatesalso msg_mclass_s * * Insert a header class @a hc to the message class @a mc. If the given @a * offset of the header in @ref msg_pub_t "public message structure" is * zero, extend the size of the public message structure in order to store * headers at the end of structure. * * @param[in,out] mc pointer to a message class * @param[in] hc pointer to a header class * @param[in] offset offset of the header in * @ref msg_pub_t "public message structure" * @param[in] flags classification flags for the header * * @return Number of collisions in hash table, or -1 upon an error. */ int msg_mclass_insert_with_mask(msg_mclass_t *mc, msg_hclass_t *hc, unsigned short offset, unsigned short flags) { msg_href_t hr[1]; if (mc == NULL || hc == NULL) { errno = EINVAL; return -1; } if (msg_hclass_offset(mc, NULL, hc)) return (void)(errno = EEXIST), -1; if (offset == 0) offset = mc->mc_msize, mc->mc_msize += sizeof(msg_header_t *); assert(offset < mc->mc_msize); hr->hr_class = hc; hr->hr_offset = offset; hr->hr_flags = flags; return msg_mclass_insert(mc, hr); } /** Add a header reference to the message class. * * @relatesalso msg_mclass_s * * @param[in,out] mc pointer to a message class object * @param[in] hr header reference object * * @return Number of collisions in hash table, or -1 upon an error. */ int msg_mclass_insert(msg_mclass_t *mc, msg_href_t const *hr) { int j, j0; int N; int collisions = 0; msg_hclass_t *hc; if (mc == NULL) { errno = EINVAL; return -1; } if (hr == NULL || (hc = hr->hr_class) == NULL) return 0; /* Add short form */ if (mc->mc_short && hc->hc_short[0]) { char compact = hc->hc_short[0]; msg_href_t *shorts = (msg_href_t *)mc->mc_short; if (compact < 'a' || compact > 'z') return -1; if (shorts[compact - 'a'].hr_class && shorts[compact - 'a'].hr_class != hc) return -1; shorts[compact - 'a'] = *hr; } N = mc->mc_hash_size; j0 = msg_header_name_hash(hc->hc_name, NULL) % N; for (j = j0; mc->mc_hash[j].hr_class; ) { collisions++; if (mc->mc_hash[j].hr_class == hc) return -1; j = (j + 1) % N; if (j == j0) return -1; } mc->mc_hash[j] = hr[0]; mc->mc_hash_used++; return collisions; } /** Calculate length of line ending (0, 1 or 2). @internal */ #define CRLF_TEST(cr, lf) ((cr) == '\r' ? ((lf) == '\n') + 1 : (cr)=='\n') /**Search for a header class. * * @relatesalso msg_mclass_s * * The function msg_find_hclass() searches for a header class from a message * class based on the contents of the header to be parsed. The buffer @a s * should point to the first character in the header name. * * @param[in] mc message class object * @param[in] s header contents * @param[out] return_start_of_content start of header content (may be NULL) * * @return The function msg_find_hclass() returns a pointer to a header * reference structure. A pointer to a header reference for unknown headers * is returned, if the header is not included in the message class. * * @par * The return-value parameter @a return_start_of_content will contain the * start of the header contents within @a s, or 0 upon an error parsing the * header name and following colon. * * @par * Upon a fatal error, a NULL pointer is returned. */ msg_href_t const *msg_find_hclass(msg_mclass_t const *mc, char const *s, isize_t *return_start_of_content) { msg_href_t const *hr; short i, N, m; isize_t len; assert(mc); N = mc->mc_hash_size; i = msg_header_name_hash(s, &len) % N; if (len == 0 || len > HC_LEN_MAX) { if (return_start_of_content) *return_start_of_content = 0; return mc->mc_error; } m = (short)len; if (m == 1 && mc->mc_short) { short c = s[0]; if (c >= 'a' && c <= 'z') hr = &mc->mc_short[c - 'a']; else if (c >= 'A' && c <= 'Z') hr = &mc->mc_short[c - 'A']; else hr = mc->mc_unknown; if (hr->hr_class == NULL) hr = mc->mc_unknown; } else { msg_hclass_t *hc; /* long form */ for (hr = NULL; (hc = mc->mc_hash[i].hr_class); i = (i + 1) % N) { if (m == hc->hc_len && su_casenmatch(s, hc->hc_name, m)) { hr = &mc->mc_hash[i]; break; } } if (hr == NULL) hr = mc->mc_unknown; } if (!return_start_of_content) /* Just header name */ return hr; if (s[len] == ':') { /* Fast path */ *return_start_of_content = ++len; return hr; } if (IS_LWS(s[len])) { int crlf = 0; do { len += span_ws(s + len + crlf) + crlf; /* Skip lws before colon */ crlf = CRLF_TEST(s[len], s[len + 1]); } while (IS_WS(s[len + crlf])); } if (s[len++] != ':') /* Colon is required in header */ len = 0; *return_start_of_content = len; return hr; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/msg_mime.c000066400000000000000000001716431223300710500223150ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@ingroup msg_mime * @CFILE msg_mime.c * * MIME-related headers and MIME multipart bodies for SIP/HTTP/RTSP. * * @author Pekka Pessi * * @date Created: Tue Jun 13 02:57:51 2000 ppessi * * */ #include "config.h" #define _GNU_SOURCE 1 #include #include #include #include "msg_internal.h" #include "sofia-sip/msg.h" #include "sofia-sip/msg_mime.h" #include #include #include #include #include #include #include #include /** Protocol version of MIME */ char const msg_mime_version_1_0[] = "MIME/1.0"; #include #include /** Define a header class for headers without any extra data to copy */ #define MSG_HEADER_CLASS_G(c, l, s, kind) \ MSG_HEADER_CLASS(msg_, c, l, s, g_common, kind, msg_generic, msg_generic) #define msg_generic_update NULL /** Define a header class for a msg_list_t kind of header */ #define MSG_HEADER_CLASS_LIST(c, l, s, kind) \ MSG_HEADER_CLASS(msg_, c, l, s, k_items, kind, msg_list, msg_list) #define msg_list_update NULL /* ====================================================================== */ /** Calculate length of line ending (0, 1 or 2). @internal */ #define CRLF_TEST(b) ((b)[0] == '\r' ? ((b)[1] == '\n') + 1 : (b)[0] =='\n') /**@ingroup msg_mime * @defgroup msg_multipart MIME Multipart Body * * Representing MIME multipart bodies and their manipulation. * * The #msg_multipart_t is an object for storing MIME multipart message * bodies. It includes message components used for framing and identifying * message parts. Its syntax is defined in @RFC2046 as follows: * * @code * * multipart-body := [preamble CRLF] * dash-boundary transport-padding CRLF * body-part *encapsulation * close-delimiter transport-padding * [CRLF epilogue] * * preamble := discard-text * * discard-text := *(*text CRLF) * ; May be ignored or discarded. * * dash-boundary := "--" boundary * ; boundary taken from the value of boundary parameter * ; of the Content-Type field. * * boundary := 0*69 bcharsnospace * * bchars := bcharsnospace / " " * * bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" / * "+" / "_" / "," / "-" / "." / * "/" / ":" / "=" / "?" * * transport-padding := *LWSP-char * ; Composers MUST NOT generate non-zero length * ; transport padding, but receivers MUST be able to * ; handle padding added by message transports. * * body-part := <"message" as defined in @RFC822, with all header fields * optional, not starting with the specified dash-boundary, * and with the delimiter not occurring anywhere in the body * part. Note that the semantics of a part differ from the * semantics of a message, as described in the text.> * * encapsulation := delimiter transport-padding CRLF * body-part * * close-delimiter := delimiter "--" * * delimiter := CRLF dash-boundary * * epilogue := discard-text * * @endcode * * @par Parsing a Multipart Message * * When a message body contains a multipart entity (in other words, it has a * MIME media type of "multipart"), the application can split the multipart * entity into body parts * * The parsing is relatively simple, the application just gives a memory * home object, a Content-Type header object and message body object as an * argument to msg_multipart_parse() function: * @code * if (sip->sip_content_type && * su_casenmatch(sip->sip_content_type, "multipart/", 10)) { * msg_multipart_t *mp; * * if (sip->sip_multipart) * mp = sip->sip_multipart; * else * mp = msg_multipart_parse(msg_home(msg), * sip->sip_content_type, * (sip_payload_t *)sip->sip_payload); * * if (mp) * ... processing multipart ... * else * ... error handling ... * } * @endcode * * The resulting list of msg_multipart_t structures contain the parts of the * multipart entity, each part represented by a separate #msg_multipart_t * structure. Please note that in order to make error recovery possible, the * parsing is not recursive - if multipart contains another multipart, the * application is responsible for scanning for it and parsing it. * * @par Constructing a Multipart Message * * Constructing a multipart body is a bit more hairy. The application needs * a message object (#msg_t), which is used to buffer the encoding of * multipart components. * * As an example, let us create a "multipart/mixed" multipart entity with a * HTML and GIF contents, and convert it into a #sip_payload_t structure: * @code * msg_t *msg = msg_create(sip_default_mclass, 0); * su_home_t *home = msg_home(msg); * sip_t *sip = sip_object(msg); * sip_content_type_t *c; * msg_multipart_t *mp = NULL; * msg_header_t *h = NULL; * char *b; * size_t len, offset; * * mp = msg_multipart_create(home, "text/html;level=3", html, strlen(html)); * mp->mp_next = msg_multipart_create(home, "image/gif", gif, giflen); * * c = sip_content_type_make(home, "multipart/mixed"); * * // Add delimiters to multipart, and boundary parameter to content-type * if (msg_multipart_complete(home, c, mp) < 0) * return -1; // Error * * // Combine multipart components into the chain * h = NULL; * if (msg_multipart_serialize(&h, mp) < 0) * return -1; // Error * * // Encode all multipart components * len = msg_multipart_prepare(msg, mp, 0); * if (len < 0) * return -1; // Error * * pl = sip_payload_create(home, NULL, len); * * // Copy each element from multipart to pl_data * b = pl->pl_data; * for (offset = 0, h = mp; offset < len; h = h->sh_succ) { * memcpy(b + offset, h->sh_data, h->sh_len); * offset += h->sh_len; * } * @endcode * */ /**Create a part for MIME multipart entity. * * The function msg_multipart_create() allocates a new #msg_multipart_t * object from memory home @a home. If @a content_type is non-NULL, it makes * a #msg_content_type_t header object and adds the header to the * #msg_multipart_t object. If @a dlen is nonzero, it allocates a * msg_payload_t structure of @a dlen bytes for the payload of the newly * created #msg_multipart_t object. If @a data is non-NULL, it copies the @a * dlen bytes of of data to the payload of the newly created * #msg_multipart_t object. * * @return A pointer to the newly created #msg_multipart_t object, or NULL * upon an error. */ msg_multipart_t *msg_multipart_create(su_home_t *home, char const *content_type, void const *data, isize_t dlen) { msg_multipart_t *mp; mp = (msg_multipart_t *)msg_header_alloc(home, msg_multipart_class, 0); if (mp) { if (content_type) mp->mp_content_type = msg_content_type_make(home, content_type); if (dlen) mp->mp_payload = msg_payload_create(home, data, dlen); if ((!mp->mp_content_type && content_type) || (!mp->mp_payload && dlen)) { su_free(home, mp->mp_content_type); su_free(home, mp->mp_payload); su_free(home, mp); mp = NULL; } } return mp; } /** Convert boundary parameter to a search string. */ static char * msg_multipart_boundary(su_home_t *home, char const *b) { char *boundary; if (!b || !(boundary = su_alloc(home, 2 + 2 + strlen(b) + 2 + 1))) return NULL; strcpy(boundary, CR LF "--"); if (b[0] == '"') /* " See http://bugzilla.gnome.org/show_bug.cgi?id=134216 */ msg_unquote(boundary + 4, b); else strcpy(boundary + 4, b); strcat(boundary + 4, CR LF); return boundary; } /** Boundary chars. */ static char const bchars[] = "'()+_,-./:=?" "0123456789" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" " "; #define bchars_len (sizeof(bchars) - 1) /** Search for a suitable boundary from MIME. */ static char * msg_multipart_search_boundary(su_home_t *home, char const *p, size_t len) { size_t m; unsigned crlf; char const *end = p + len; char *boundary; if (len < 2) return NULL; /* Boundary looks like LF -- string SP* [CR] LF */ if (memcmp("--", p, 2) == 0) { /* We can be at boundary beginning, there is no CR LF */ m = 2 + su_memspn(p + 2, len - 2, bchars, bchars_len); if (m + 2 >= len) return NULL; crlf = p[m] == '\r' ? 1 + (p[m + 1] == '\n') : (p[m] == '\n'); while (p[m - 1] == ' ' || p[m - 1] == '\t') m--; if (m > 2 && crlf) { boundary = su_alloc(home, 2 + m + 2 + 1); if (boundary) { memcpy(boundary, CR LF, 2); memcpy(boundary + 2, p, m); strcpy(boundary + m + 2, CR LF); } return boundary; } } /* Look for LF -- */ for (;(p = bm_memmem(p, end - p, LF "--", 3, NULL)); p += 3) { len = end - p; m = 3 + su_memspn(p + 3, len - 3, bchars, bchars_len); if (m + 2 >= len) return NULL; crlf = p[m] == '\r' ? 1 + (p[m + 1] == '\n') : (p[m] == '\n'); while (p[m - 1] == ' ' || p[m - 1] == '\t') m--; m--; if (m > 2 && crlf) { boundary = su_alloc(home, 2 + m + 2 + 1); if (boundary) { memcpy(boundary, CR LF, 2); memcpy(boundary + 2, p + 1, m); strcpy(boundary + 2 + m, CR LF); } return boundary; } } return NULL; } /** Parse a MIME multipart. * * The function msg_multipart_parse() parses a MIME multipart message. The * common syntax of multiparts is described in @RFC2046 (section 7). * * @param[in,out] home home for allocating structures * @param[in] c content-type header for multipart * @param[in] pl payload structure for multipart * * After parsing, the @a pl will contain the plain-text preamble (if any). * * @note If no @b Content-Type header is given, the msg_multipart_parse() * tries to look for a suitable boundary. Currently, it takes first * boundary-looking string and uses that, so it can be fooled with, for * instance, signature @c "--Pekka". */ msg_multipart_t *msg_multipart_parse(su_home_t *home, msg_content_type_t const *c, msg_payload_t *pl) { msg_multipart_t *mp = NULL, *all = NULL, **mmp = &all; /* Dummy msg object */ msg_t msg[1] = {{{ SU_HOME_INIT(msg) }}}; size_t len, m, blen, prelen; char *boundary, *p, *next, save; char const *b, *end; msg_param_t param; bm_fwd_table_t *fwd = NULL; p = pl->pl_data; len = pl->pl_len; end = p + len; su_home_init(msg_home(msg)); msg->m_class = msg_multipart_mclass; msg->m_tail = &msg->m_chain; /* Get boundary from Content-Type */ if (c && (param = msg_header_find_param(c->c_common, "boundary="))) boundary = msg_multipart_boundary(msg_home(msg), param); else boundary = msg_multipart_search_boundary(msg_home(msg), p, len); if (!boundary) return NULL; m = strlen(boundary) - 2, blen = m - 1; if (blen > 8 * sizeof (long)) fwd = bm_memmem_study(boundary + 1, blen); /* Find first delimiter */ if (memcmp(boundary + 2, p, m - 2) == 0) b = p, p = p + m - 2, len -= m - 2; else if ((p = bm_memmem(p, len, boundary + 1, blen, fwd))) { if (p != pl->pl_data && p[-1] == '\r') b = --p, p = p + m, len -= m; else b = p, p = p + m - 1, len -= m - 1; } else { free(fwd); su_home_deinit(msg_home(msg)); return NULL; } prelen = b - pl->pl_data; /* Split multipart into parts */ for (;;) { while (p[0] == ' ') p++; p += p[0] == '\r' ? 1 + (p[1] == '\n') : (p[0] == '\n'); len = end - p; if (len < blen) break; next = bm_memmem(p, len, boundary + 1, m = blen, fwd); if (!next) break; /* error */ if (next != p && next[-1] == '\r') next--, m++; mp = (msg_multipart_t *) msg_header_alloc(msg_home(msg), msg_multipart_class, 0); if (mp == NULL) break; /* error */ *mmp = mp; mmp = &mp->mp_next; /* Put delimiter transport-padding CRLF here */ mp->mp_common->h_data = b; mp->mp_common->h_len = p - b; /* .. and body-part here */ mp->mp_data = p; mp->mp_len = next - p; if (next[m] == '-' && next[m + 1] == '-') { /* We found close-delimiter */ mp->mp_close_delim = (msg_payload_t *) msg_header_alloc(msg_home(msg), msg_payload_class, 0); if (!mp->mp_close_delim) break; /* error */ /* Include also transport-padding and epilogue in the close-delimiter */ mp->mp_close_delim->pl_data = next; mp->mp_close_delim->pl_len = p + len - next; break; } b = next; p = next + m; } free(fwd), fwd = NULL; if (!mp || !mp->mp_close_delim) { su_home_deinit(msg_home(msg)); /* Delimiter error */ return NULL; } /* Parse each part */ for (mp = all; mp; mp = mp->mp_next) { msg->m_object = (msg_pub_t *)mp; p = mp->mp_data; next = p + mp->mp_len; if (msg->m_tail) mp->mp_common->h_prev = msg->m_tail, *msg->m_tail = (msg_header_t *)mp; msg->m_chain = (msg_header_t *)mp; msg->m_tail = &mp->mp_common->h_succ; save = *next; *next = '\0'; /* NUL-terminate this part */ for (len = next - p; len > 0; len -= m, p += m) { if (IS_CRLF(p[0])) { m = msg_extract_separator(msg, (msg_pub_t*)mp, p, len, 1); assert(m > 0); p += m; len -= m; if (len > 0) { m = msg_extract_payload(msg, (msg_pub_t*)mp, NULL, len, p, len, 1); assert(m > 0); assert(len == m); } break; } m = msg_extract_header(msg, (msg_pub_t*)mp, p, len, 1); if (m <= 0) { assert(m > 0); /* Xyzzy */ } } *next = save; /* XXX - Should we leave the payload NUL-terminated? */ } /* Postprocess */ blen = strlen(boundary); for (mp = all; mp; mp = mp->mp_next) { mp->mp_data = boundary; mp->mp_len = (unsigned)blen; /* XXX */ if (!(mp->mp_payload || mp->mp_separator)) continue; if (mp->mp_close_delim) { msg_header_t **tail; if (mp->mp_payload) tail = &mp->mp_payload->pl_common->h_succ; else tail = &mp->mp_separator->sep_common->h_succ; assert(msg->m_chain == (msg_header_t *)mp); assert(*tail == NULL); mp->mp_close_delim->pl_common->h_prev = tail; *tail = (msg_header_t *)mp->mp_close_delim; } } msg_fragment_clear(pl->pl_common); pl->pl_len = prelen; su_home_move(home, msg_home(msg)); su_home_deinit(msg_home(msg)); return all; } /**Add all missing parts to the multipart. * * Add missing components such as boundaries between body parts, separators * between body-part headers and data, and close-delimiter after last * body-part to the multipart message. * * @param[in,out] home home for allocating structures * @param[in,out] c content-type header for multipart * @param[in,out] mp pointer to first multipart structure * * @retval 0 when successful * @retval -1 upon an error * * @ERRORS * @ERROR EBADMSG * The @b Content-Type header @a c is malformed, or multipart message * contains a malformed @b Content-Type header. * @ERROR ENOMEM * A memory allocation failed. * @ERROR EINVAL * The function msg_multipart_complete() was given invalid arguments. */ int msg_multipart_complete(su_home_t *home, msg_content_type_t *c, msg_multipart_t *mp) { char *boundary; char const *b; size_t blen, m; if (c == NULL || mp == NULL) return (errno = EINVAL), -1; if (!(b = msg_header_find_param(c->c_common, "boundary="))) { /* Generate boundary */ enum { tlen = 16 * 4 / 3 }; char token[sizeof("boundary=") + tlen + 1]; if (mp->mp_data) { b = mp->mp_data; m = mp->mp_len; if (strncmp(b, CR LF "--", 4) == 0) b += 4, m -= 4; else if (strncmp(b, "--", 2) == 0) b += 2, m -= 2; else return (errno = EBADMSG), -1; /* XXX - quoting? */ b = su_sprintf(home, "boundary=\"%.*s\"", (int)m, b); } else { strcpy(token, "boundary="); msg_random_token(token + strlen("boundary="), (size_t)tlen, NULL, 0); b = su_strdup(home, token); } if (!b) return -1; msg_params_replace(home, (msg_param_t **)&c->c_params, b); b += strlen("boundary="); } if (!(boundary = msg_multipart_boundary(home, b))) return -1; blen = strlen(boundary); m = blen - 2; for (; mp; mp = mp->mp_next) { if (mp->mp_data == NULL) { mp->mp_data = boundary; mp->mp_len = (unsigned)blen; /* XXX */ } else { if (mp->mp_len < 3) return -1; if (mp->mp_data[0] == '\r' && mp->mp_data[1] == '\n') { if (mp->mp_len < m || memcmp(mp->mp_data + 2, boundary + 2, m - 2)) return -1; } else if (mp->mp_data[0] == '\n') { if (mp->mp_len < m - 1 || memcmp(mp->mp_data + 1, boundary + 2, m - 2)) return -1; } else { if (mp->mp_len < m - 2 || memcmp(mp->mp_data, boundary + 2, m - 2)) return -1; } } if (mp->mp_next == NULL) { if (!mp->mp_close_delim) mp->mp_close_delim = msg_payload_format(home, "%.*s--" CR LF, (int)m, boundary); if (!mp->mp_close_delim) return -1; } else if (mp->mp_close_delim) { msg_payload_t *e = mp->mp_close_delim; mp->mp_close_delim = NULL; if (e->pl_common->h_prev) *e->pl_common->h_prev = e->pl_common->h_succ; if (e->pl_common->h_succ) e->pl_common->h_succ->sh_prev = e->pl_common->h_prev; } mp->mp_common->h_data = mp->mp_data; mp->mp_common->h_len = mp->mp_len; if (!mp->mp_separator) if (!(mp->mp_separator = msg_separator_make(home, CR LF))) return -1; if (mp->mp_multipart) { c = mp->mp_content_type; if (c == NULL) return (errno = EBADMSG), -1; if (msg_multipart_complete(home, c, mp->mp_multipart) < 0) return -1; } if (!mp->mp_payload) if (!(mp->mp_payload = msg_payload_create(home, NULL, 0))) return -1; } return 0; } /** Serialize a multipart message. * */ msg_header_t *msg_multipart_serialize(msg_header_t **head0, msg_multipart_t *mp) { msg_header_t *h_succ_all = NULL; msg_header_t *h, **head, **hh, *h0, *h_succ; void *hend; #define is_in_chain(h) ((h) && ((msg_frg_t*)(h))->h_prev != NULL) #define insert(head, h) \ ((h)->sh_succ = *(head), *(head) = (h), \ (h)->sh_prev = (head), (head) = &(h)->sh_succ) if (mp == NULL || head0 == NULL) return NULL; h_succ_all = *head0; head = head0; for (; mp; mp = mp->mp_next) { h0 = (msg_header_t *)mp; assert(mp->mp_separator); assert(mp->mp_payload); assert(mp->mp_next || mp->mp_close_delim); if (!mp->mp_separator || !mp->mp_payload || (!mp->mp_next && !mp->mp_close_delim)) return NULL; if ((void *)mp == h_succ_all) h_succ_all = NULL; *head0 = h0; h0->sh_prev = head; if (is_in_chain(mp->mp_separator)) hend = mp->mp_separator; else if (is_in_chain(mp->mp_payload)) hend = mp->mp_payload; else if (is_in_chain(mp->mp_multipart)) hend = mp->mp_multipart; else if (is_in_chain(mp->mp_close_delim)) hend = mp->mp_close_delim; else if (is_in_chain(mp->mp_next)) hend = mp->mp_next; else hend = NULL; /* Search latest header in chain */ for (head = &mp->mp_common->h_succ; *head && *head != hend; head = &(*head)->sh_succ) ; h_succ = *head; /* Serialize headers */ for (hh = &((msg_pub_t*)mp)->msg_request; (char *)hh < (char *)&mp->mp_separator; hh++) { h = *hh; if (!h) continue; for (h = *hh; h; h = h->sh_next) { if (h == h_succ || !is_in_chain(h)) { *head = h; h->sh_prev = head; head = &h->sh_succ; while (*head && *head != hend) head = &(*head)->sh_succ; if (h == h_succ) h_succ = *head; } else { /* XXX Check that h is between head and hend */ } } } if (!is_in_chain(mp->mp_separator)) { insert(head, (msg_header_t *)mp->mp_separator); } else { assert(h_succ == (msg_header_t *)mp->mp_separator); mp->mp_separator->sep_common->h_prev = head; *head = (msg_header_t *)mp->mp_separator; head = &mp->mp_separator->sep_common->h_succ; h_succ = *head; } if (!is_in_chain(mp->mp_payload)) { insert(head, (msg_header_t *)mp->mp_payload); } else { assert(h_succ == (msg_header_t *)mp->mp_payload); mp->mp_payload->pl_common->h_prev = head; *head = (msg_header_t *)mp->mp_payload; head = &mp->mp_payload->pl_common->h_succ; h_succ = *head; } if (mp->mp_multipart) { if ((*head = h_succ)) h_succ->sh_prev = head; if (!(h = msg_multipart_serialize(head, mp->mp_multipart))) return NULL; head = &h->sh_succ; h_succ = *head; } if (mp->mp_close_delim) { if (!is_in_chain(mp->mp_close_delim)) { insert(head, (msg_header_t*)mp->mp_close_delim); } else { assert(h_succ == (msg_header_t *)mp->mp_close_delim); mp->mp_close_delim->pl_common->h_prev = head; *head = (msg_header_t *)mp->mp_close_delim; head = &mp->mp_close_delim->pl_common->h_succ; } if (h_succ_all) *head = h_succ_all, h_succ_all->sh_prev = head; return (msg_header_t *)mp->mp_close_delim; } *head = h_succ; head0 = head; } assert(!mp); return NULL; } /** Encode a multipart. * * @return The size of multipart in bytes, or -1 upon an error. */ issize_t msg_multipart_prepare(msg_t *msg, msg_multipart_t *mp, int flags) { if (!mp || !mp->mp_data) return -1; if (!mp->mp_common->h_data || mp->mp_common->h_len != mp->mp_len - 2 || memcmp(mp->mp_common->h_data, mp->mp_data + 2, mp->mp_len - 2)) { mp->mp_common->h_data = mp->mp_data + 2; mp->mp_common->h_len = mp->mp_len - 2; } return msg_headers_prepare(msg, (msg_header_t *)mp, flags); } /** Decode a multipart. */ issize_t msg_multipart_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { su_home_t tmphome[1] = { SU_HOME_INIT(tmphome) }; msg_payload_t pl[1]; msg_multipart_t *mp, *result; assert(h && msg_is_multipart(h)); msg_payload_init(pl); result = (msg_multipart_t *)h; pl->pl_data = s; pl->pl_len = slen; mp = msg_multipart_parse(tmphome, NULL, pl); if (mp) { *result = *mp; if (result->mp_common->h_succ->sh_prev) result->mp_common->h_succ->sh_prev = &result->mp_common->h_succ; su_free(tmphome, mp); su_home_move(home, tmphome); } su_home_deinit(tmphome); return mp ? 0 : -1; } /** Encode a multipart. * * Please note that here we just encode a element, the msg_multipart_t * itself. */ issize_t msg_multipart_e(char b[], isize_t bsiz, msg_header_t const *h, int flags) { return msg_payload_e(b, bsiz, h, flags); } /** Calculate extra size of a multipart */ isize_t msg_multipart_dup_xtra(msg_header_t const *h, isize_t offset) { msg_multipart_t const *mp = (msg_multipart_t *)h; msg_header_t const * const *hh; offset = msg_payload_dup_xtra(h, offset); for (hh = (msg_header_t const **)&((msg_pub_t *)mp)->msg_request; (char *)hh <= (char *)&mp->mp_close_delim; hh++) { for (h = *hh; h; h = h->sh_next) { MSG_STRUCT_SIZE_ALIGN(offset); offset = h->sh_class->hc_dxtra(h, offset + h->sh_class->hc_size); } } return offset; } /** Duplicate one msg_multipart_t object */ char *msg_multipart_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra) { msg_multipart_t const *mp = (msg_multipart_t *)src; msg_header_t *h, **hh; char *end = b + xtra; b = msg_payload_dup_one(dst, src, b, xtra); for (hh = &((msg_pub_t*)mp)->msg_request; (char *)hh <= (char *)&mp->mp_close_delim; hh++) { for (h = *hh; h; h = h->sh_next) { MSG_STRUCT_ALIGN(b); dst = (msg_header_t *)b; memset(dst, 0, sizeof dst->sh_common); dst->sh_class = h->sh_class; b = h->sh_class->hc_dup_one(dst, h, b + h->sh_class->hc_size, end - b); if (h->sh_class->hc_update) msg_header_update_params(h->sh_common, 0); assert(b <= end); } } return b; } #if 0 msg_hclass_t msg_multipart_class[] = MSG_HEADER_CLASS(msg_, multipart, NULL, "", mp_common, append, msg_multipart); #endif /**Calculate Q value. * * The function msg_q_value() converts q-value string @a q to numeric value * in range (0..1000). Q values are used, for instance, to describe * relative priorities of acceptable Content-Types. * * @param q q-value string ("1" | "." 1,3DIGIT) * * @return * The function msg_q_value() returns an integer in range 0 .. 1000. * * @NEW_UNRELEASED */ unsigned msg_q_value(char const *q) { unsigned value = 0; if (!q) return 1000; if (q[0] != '0' && q[0] != '.' && q[0] != '1') return 500; /* Garbage... */ while (q[0] == '0') q++; if (q[0] >= '1' && q[0] <= '9') return 1000; if (q[0] == '\0') return 0; if (q[0] != '.') return 500; /* Garbage... */ if (q[1] >= '0' && q[1] <= '9') { value = (q[1] - '0') * 100; if (q[2] >= '0' && q[2] <= '9') { value += (q[2] - '0') * 10; if (q[3] >= '0' && q[3] <= '9') { value += (q[3] - '0'); if (q[4] > '5' && q[4] <= '9') /* Round upwards */ value += 1; else if (q[4] == '5') value += value & 1; /* Round to even */ } } } return value; } /** Parse media type (type/subtype). * * The function msg_mediatype_d() parses a mediatype string. * * @param[in,out] ss string to be parsed * @param[out] type value result for media type * * @retval 0 when successful, * @retval -1 upon an error. */ issize_t msg_mediatype_d(char **ss, char const **type) { char *s = *ss; char const *result = s; size_t l1 = 0, l2 = 0, n; /* Media type consists of two tokens, separated by / */ l1 = span_token(s); for (n = l1; IS_LWS(s[n]); n++) {} if (s[n] == '/') { for (n++; IS_LWS(s[n]); n++) {} l2 = span_token(s + n); n += l2; } if (l1 == 0 || l2 == 0) return -1; /* If there is extra ws between tokens, compact version */ if (n > l1 + 1 + l2) { s[l1] = '/'; memmove(s + l1 + 1, s + n - l2, l2); s[l1 + 1 + l2] = 0; } s += n; while (IS_WS(*s)) *s++ = '\0'; *ss = s; if (type) *type = result; return 0; } /* ====================================================================== */ /**@ingroup msg_mime * @defgroup msg_accept Accept Header * * The @b Accept request-header field can be used to specify certain media * types which are acceptable for the response. Its syntax is defined in * [H14.1, S20.1] as follows: * * @code * Accept = "Accept" ":" #( media-range [ accept-params ] ) * * media-range = ( "*" "/" "*" * | ( type "/" "*" ) * | ( type "/" subtype ) ) *( ";" parameter ) * * accept-params = ";" "q" "=" qvalue *( accept-extension ) * * accept-extension = ";" token [ "=" ( token | quoted-string ) ] * @endcode * */ /**@ingroup msg_accept * @typedef typedef struct msg_accept_s msg_accept_t; * * The structure msg_accept_t contains representation of an @b Accept * header. * * The msg_accept_t is defined as follows: * @code * typedef struct msg_accept_s { * msg_common_t ac_common[1]; // Common fragment info * msg_accept_t *ac_next; // Pointer to next Accept header * char const *ac_type; // Pointer to type/subtype * char const *ac_subtype; // Points after first slash in type * msg_param_t const *ac_params; // List of parameters * msg_param_t ac_q; // Value of q parameter * } msg_accept_t; * @endcode */ msg_hclass_t msg_accept_class[] = MSG_HEADER_CLASS(msg_, accept, "Accept", "", ac_params, apndlist, msg_accept, msg_accept); issize_t msg_accept_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { msg_accept_t *ac = (msg_accept_t *)h; while (*s == ',') /* Ignore empty entries (comma-whitespace) */ *s = '\0', s += span_lws(s + 1) + 1; if (*s == '\0') { /* Empty Accept list is not an error */ ac->ac_type = ac->ac_subtype = ""; return 0; } /* "Accept:" #(type/subtyp ; *(parameters))) */ if (msg_mediatype_d(&s, &ac->ac_type) == -1) return -1; if (!(ac->ac_subtype = strchr(ac->ac_type, '/'))) return -1; ac->ac_subtype++; if (*s == ';' && msg_params_d(home, &s, &ac->ac_params) == -1) return -1; return msg_parse_next_field(home, h, s, slen); } issize_t msg_accept_e(char b[], isize_t bsiz, msg_header_t const *h, int flags) { char *b0 = b, *end = b + bsiz; msg_accept_t const *ac = (msg_accept_t *)h; assert(msg_is_accept(h)); if (ac->ac_type) { MSG_STRING_E(b, end, ac->ac_type); MSG_PARAMS_E(b, end, ac->ac_params, flags); } MSG_TERM_E(b, end); return b - b0; } isize_t msg_accept_dup_xtra(msg_header_t const *h, isize_t offset) { msg_accept_t const *ac = (msg_accept_t *)h; if (ac->ac_type) { MSG_PARAMS_SIZE(offset, ac->ac_params); offset += MSG_STRING_SIZE(ac->ac_type); } return offset; } /** Duplicate one msg_accept_t object */ char *msg_accept_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra) { msg_accept_t *ac = (msg_accept_t *)dst; msg_accept_t const *o = (msg_accept_t *)src; char *end = b + xtra; if (o->ac_type) { b = msg_params_dup(&ac->ac_params, o->ac_params, b, xtra); MSG_STRING_DUP(b, ac->ac_type, o->ac_type); if ((ac->ac_subtype = strchr(ac->ac_type, '/'))) ac->ac_subtype++; } assert(b <= end); (void)end; return b; } /** Update parameter(s) for Accept header. */ int msg_accept_update(msg_common_t *h, char const *name, isize_t namelen, char const *value) { msg_accept_t *ac = (msg_accept_t *)h; if (name == NULL) { ac->ac_q = NULL; } else if (namelen == 1 && su_casenmatch(name, "q", 1)) { /* XXX - check for invalid value? */ ac->ac_q = value; } return 0; } /** Check if the Content-Type is Acceptable. * * @return Best Accept header field from @a, or NULL if no match. * * @TODO Content-Type parameters (e.g., charset) are not checked. * * @NEW_UNRELEASED */ msg_accept_t *msg_accept_match(msg_accept_t const *a, msg_content_type_t const *c) { char const *c_type = NULL, *c_subtype = NULL; msg_accept_t const *found = NULL; if (c != NULL) c_type = c->c_type, c_subtype = c->c_subtype; if (c_type == NULL) c_type = "*/*"; if (c_subtype == NULL) c_type = "*"; for (; a; a = a->ac_next) { if (msg_q_value(a->ac_q) == 0 || a->ac_type == NULL) continue; if (found == NULL && su_strmatch(a->ac_type, "*/*")) { found = a; continue; } if (!su_casenmatch(a->ac_type, c_type, a->ac_subtype - a->ac_type)) continue; if (su_casematch(c_subtype, a->ac_subtype)) { found = a; break; } if (su_strmatch(a->ac_subtype, "*")) { if (found == NULL || su_strmatch(found->ac_type, "*/*")) found = a; } } return (msg_accept_t *)found; } /* ====================================================================== */ /** Decode an Accept-* header. */ issize_t msg_accept_any_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { /** @relatesalso msg_accept_any_s */ msg_accept_any_t *aa = (msg_accept_any_t *)h; while (*s == ',') /* Ignore empty entries (comma-whitespace) */ *s = '\0', s += span_lws(s + 1) + 1; if (*s == '\0') return -2; /* Empty list */ /* "Accept-*:" 1#(token *(SEMI accept-param)) */ if (msg_token_d(&s, &aa->aa_value) == -1) return -1; if (*s == ';' && msg_params_d(home, &s, &aa->aa_params) == -1) return -1; return msg_parse_next_field(home, h, s, slen); } /** Encode an Accept-* header field. */ issize_t msg_accept_any_e(char b[], isize_t bsiz, msg_header_t const *h, int f) { /** @relatesalso msg_accept_any_s */ char *b0 = b, *end = b + bsiz; msg_accept_any_t const *aa = (msg_accept_any_t *)h; MSG_STRING_E(b, end, aa->aa_value); MSG_PARAMS_E(b, end, aa->aa_params, flags); MSG_TERM_E(b, end); return b - b0; } /** Calculate extra memory used by accept-* headers. */ isize_t msg_accept_any_dup_xtra(msg_header_t const *h, isize_t offset) { /** @relatesalso msg_accept_any_s */ msg_accept_any_t const *aa = (msg_accept_any_t *)h; MSG_PARAMS_SIZE(offset, aa->aa_params); offset += MSG_STRING_SIZE(aa->aa_value); return offset; } /** Duplicate one msg_accept_any_t object. */ char *msg_accept_any_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra) { /** @relatesalso msg_accept_any_s */ msg_accept_any_t *aa = (msg_accept_any_t *)dst; msg_accept_any_t const *o = (msg_accept_any_t *)src; char *end = b + xtra; b = msg_params_dup(&aa->aa_params, o->aa_params, b, xtra); MSG_STRING_DUP(b, aa->aa_value, o->aa_value); assert(b <= end); (void)end; return b; } /** Update parameter(s) for Accept-* header. */ int msg_accept_any_update(msg_common_t *h, char const *name, isize_t namelen, char const *value) { msg_accept_any_t *aa = (msg_accept_any_t *)h; if (name == NULL) { aa->aa_q = NULL; } else if (namelen == 1 && su_casenmatch(name, "q", 1)) { aa->aa_q = value; } return 0; } /* ====================================================================== */ /**@ingroup msg_mime * @defgroup msg_accept_charset Accept-Charset Header * * The Accept-Charset header is similar to Accept, but restricts the * character set that are acceptable in the response. Its syntax is * defined in [H14.2] as follows: * * @code * Accept-Charset = "Accept-Charset" ":" * 1#( ( charset | "*" )[ ";" "q" "=" qvalue ] ) * @endcode * */ /**@ingroup msg_accept_charset * @typedef typedef struct msg_accept_charset_s msg_accept_charset_t; * * The structure msg_accept_encoding_t contains representation of @b * Accept-Charset header. * * The msg_accept_charset_t is defined as follows: * @code * typedef struct { * msg_common_t aa_common[1]; // Common fragment info * msg_accept_any_t *aa_next; // Pointer to next Accept-Charset * char const *aa_value; // Charset * msg_param_t const *aa_params; // Parameter list * char const *aa_q; // Q-value * } msg_accept_charset_t; * @endcode */ msg_hclass_t msg_accept_charset_class[1] = MSG_HEADER_CLASS(msg_, accept_charset, "Accept-Charset", "", aa_params, apndlist, msg_accept_any, msg_accept_any); issize_t msg_accept_charset_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { return msg_accept_any_d(home, h, s, slen); } issize_t msg_accept_charset_e(char b[], isize_t bsiz, msg_header_t const *h, int f) { assert(msg_is_accept_charset(h)); return msg_accept_any_e(b, bsiz, h, f); } /* ====================================================================== */ /**@ingroup msg_mime * @defgroup msg_accept_encoding Accept-Encoding Header * * The Accept-Encoding header is similar to Accept, but restricts the * content-codings that are acceptable in the response. Its syntax is * defined in [H14.3, S20.2] as follows: * * @code * Accept-Encoding = "Accept-Encoding" ":" * 1#( codings [ ";" "q" "=" qvalue ] ) * codings = ( content-coding | "*" ) * content-coding = token * @endcode * */ /**@ingroup msg_accept_encoding * @typedef typedef struct msg_accept_encoding_s msg_accept_encoding_t; * * The structure msg_accept_encoding_t contains representation of @b * Accept-Encoding header. * * The msg_accept_encoding_t is defined as follows: * @code * typedef struct { * msg_common_t aa_common[1]; // Common fragment info * msg_accept_any_t *aa_next; // Pointer to next Accept-Encoding * char const *aa_value; // Content-coding * msg_param_t const *aa_params; // Parameter list * char const *aa_q; // Q-value * } msg_accept_encoding_t; * @endcode */ msg_hclass_t msg_accept_encoding_class[1] = MSG_HEADER_CLASS(msg_, accept_encoding, "Accept-Encoding", "", aa_params, apndlist, msg_accept_any, msg_accept_any); issize_t msg_accept_encoding_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { return msg_accept_any_d(home, h, s, slen); } issize_t msg_accept_encoding_e(char b[], isize_t bsiz, msg_header_t const *h, int f) { return msg_accept_any_e(b, bsiz, h, f); } /* ====================================================================== */ /**@ingroup msg_mime * @defgroup msg_accept_language Accept-Language Header * * The Accept-Language header allows the client to indicate to the server in * which language it would prefer to receive reason phrases, session * descriptions or status responses carried as message bodies. Its syntax is * defined in [H14.4, S20.3] as follows: * * @code * Accept-Language = "Accept-Language" ":" * 1#( language-range [ ";" "q" "=" qvalue ] ) * * language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" ) * @endcode * */ /**@ingroup msg_accept_language * @typedef typedef struct msg_accept_language_s msg_accept_language_t; * * The structure msg_accept_language_t contains representation of @b * Accept-Language header. * * The msg_accept_language_t is defined as follows: * @code * typedef struct { * msg_common_t aa_common[1]; // Common fragment info * msg_accept_any_t *aa_next; // Pointer to next Accept-Encoding * char const *aa_value; // Language-range * msg_param_t const *aa_params; // Parameter list * char const *aa_q; // Q-value * } msg_accept_language_t; * @endcode */ msg_hclass_t msg_accept_language_class[1] = MSG_HEADER_CLASS(msg_, accept_language, "Accept-Language", "", aa_params, apndlist, msg_accept_any, msg_accept_any); issize_t msg_accept_language_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { return msg_accept_any_d(home, h, s, slen); } issize_t msg_accept_language_e(char b[], isize_t bsiz, msg_header_t const *h, int f) { assert(msg_is_accept_language(h)); return msg_accept_any_e(b, bsiz, h, f); } /* ====================================================================== */ /**@ingroup msg_mime * @defgroup msg_content_disposition Content-Disposition Header * * The Content-Disposition header field describes how the message body or, * in the case of multipart messages, a message body part is to be * interpreted by the UAC or UAS. Its syntax is defined in [S20.11] * as follows: * * @code * Content-Disposition = "Content-Disposition" ":" * disposition-type *( ";" disposition-param ) * disposition-type = "render" | "session" | "icon" | "alert" * | disp-extension-token * disposition-param = "handling" "=" * ( "optional" | "required" | other-handling ) * | generic-param * other-handling = token * disp-extension-token = token * @endcode * * The Content-Disposition header was extended by * draft-lennox-sip-reg-payload-01.txt section 3.1 as follows: * * @code * Content-Disposition = "Content-Disposition" ":" * disposition-type *( ";" disposition-param ) * disposition-type /= "script" | "sip-cgi" | token * disposition-param /= action-param * / modification-date-param * action-param = "action" "=" action-value * action-value = "store" | "remove" | token * modification-date-param = "modification-date" "=" quoted-date-time * quoted-date-time = <"> SIP-date <"> * @endcode */ /**@ingroup msg_content_disposition * @typedef struct msg_content_disposition_s msg_content_disposition_t; * * The structure msg_content_disposition_t contains representation of an @b * Content-Disposition header. * * The msg_content_disposition_t is defined as follows: * @code * typedef struct msg_content_disposition_s * { * msg_common_t cd_common[1]; // Common fragment info * msg_error_t *cd_next; // Link to next (dummy) * char const *cd_type; // Disposition type * msg_param_t const *cd_params; // List of parameters * msg_param_t cd_handling; // Value of @b handling parameter * unsigned cd_required:1; // True if handling=required * unsigned cd_optional:1; // True if handling=optional * } msg_content_disposition_t; * @endcode */ msg_hclass_t msg_content_disposition_class[] = MSG_HEADER_CLASS(msg_, content_disposition, "Content-Disposition", "", cd_params, single, msg_content_disposition, msg_content_disposition); issize_t msg_content_disposition_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { msg_content_disposition_t *cd = (msg_content_disposition_t *)h; if (msg_token_d(&s, &cd->cd_type) < 0 || (*s == ';' && msg_params_d(home, &s, &cd->cd_params) < 0)) return -1; if (cd->cd_params) msg_header_update_params(cd->cd_common, 0); return 0; } issize_t msg_content_disposition_e(char b[], isize_t bsiz, msg_header_t const *h, int f) { char *b0 = b, *end = b + bsiz; msg_content_disposition_t const *cd = (msg_content_disposition_t *)h; assert(msg_is_content_disposition(h)); MSG_STRING_E(b, end, cd->cd_type); MSG_PARAMS_E(b, end, cd->cd_params, f); MSG_TERM_E(b, end); return b - b0; } isize_t msg_content_disposition_dup_xtra(msg_header_t const *h, isize_t offset) { msg_content_disposition_t const *cd = (msg_content_disposition_t *)h; MSG_PARAMS_SIZE(offset, cd->cd_params); offset += MSG_STRING_SIZE(cd->cd_type); return offset; } /** Duplicate one msg_content_disposition_t object */ char *msg_content_disposition_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra) { msg_content_disposition_t *cd = (msg_content_disposition_t *)dst; msg_content_disposition_t const *o = (msg_content_disposition_t *)src; char *end = b + xtra; b = msg_params_dup(&cd->cd_params, o->cd_params, b, xtra); MSG_STRING_DUP(b, cd->cd_type, o->cd_type); assert(b <= end); (void)end; return b; } /** Update Content-Disposition parameters */ int msg_content_disposition_update(msg_common_t *h, char const *name, isize_t namelen, char const *value) { msg_content_disposition_t *cd = (msg_content_disposition_t *)h; if (name == NULL) { cd->cd_handling = NULL, cd->cd_required = 0, cd->cd_optional = 0; } else if (namelen == strlen("handling") && su_casenmatch(name, "handling", namelen)) { cd->cd_handling = value; cd->cd_required = su_casematch(value, "required"); cd->cd_optional = su_casematch(value, "optional"); } return 0; } /* ====================================================================== */ /**@ingroup msg_mime * @defgroup msg_content_encoding Content-Encoding Header * * The Content-Encoding header indicates what additional content codings * have been applied to the entity-body. Its syntax is defined in [H14.11] * and [S20.12] as follows: * * @code * Content-Encoding = ( "Content-Encoding" / "e" ) ":" 1#content-coding * content-coding = token * @endcode */ /**@ingroup msg_content_encoding * @typedef struct msg_list_s msg_content_encoding_t; * * The structure msg_content_encoding_t contains representation of an @b * Content-Encoding header. * * The msg_content_encoding_t is defined as follows: * @code * typedef struct msg_list_s * { * msg_common_t k_common[1]; // Common fragment info * msg_list_t *k_next; // Link to next header * msg_param_t *k_items; // List of items * } msg_content_encoding_t; * @endcode */ msg_hclass_t msg_content_encoding_class[] = MSG_HEADER_CLASS_LIST(content_encoding, "Content-Encoding", "e", list); issize_t msg_content_encoding_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { msg_content_encoding_t *e = (msg_content_encoding_t *)h; return msg_commalist_d(home, &s, &e->k_items, msg_token_scan); } issize_t msg_content_encoding_e(char b[], isize_t bsiz, msg_header_t const *h, int f) { assert(msg_is_content_encoding(h)); return msg_list_e(b, bsiz, h, f); } /* ====================================================================== */ /**@ingroup msg_mime * @defgroup msg_content_language Content-Language Header * * The Content-Language header describes the natural language(s) of the * intended audience for the enclosed message body. Note that this might not * be equivalent to all the languages used within the message-body. Its * syntax is defined in [H14.12, S20.13] as follows: * * @code * Content-Language = "Content-Language" ":" 1#language-tag * @endcode * or * @code * Content-Language = "Content-Language" HCOLON * language-tag *(COMMA language-tag) * language-tag = primary-tag *( "-" subtag ) * primary-tag = 1*8ALPHA * subtag = 1*8ALPHA * @endcode * */ /**@ingroup msg_content_language * @typedef typedef struct msg_content_language_s msg_content_language_t; * * The structure msg_content_language_t contains representation of @b * Content-Language header. * * The msg_content_language_t is defined as follows: * @code * typedef struct { * msg_common_t k_common[1]; // Common fragment info * msg_content_language_t *k_next; // (Content-Encoding header) * msg_param_t *k_items; // List of languages * } msg_content_language_t; * @endcode */ msg_hclass_t msg_content_language_class[] = MSG_HEADER_CLASS_LIST(content_language, "Content-Language", "", list); issize_t msg_content_language_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { msg_content_language_t *k = (msg_content_language_t *)h; return msg_commalist_d(home, &s, &k->k_items, msg_token_scan); } issize_t msg_content_language_e(char b[], isize_t bsiz, msg_header_t const *h, int f) { assert(msg_is_content_language(h)); return msg_list_e(b, bsiz, h, f); } /* ====================================================================== */ /**@ingroup msg_mime * @defgroup msg_content_length Content-Length Header * * The Content-Length header indicates the size of the message-body in * decimal number of octets. Its syntax is defined in [S10.18] as * follows: * * @code * Content-Length = ( "Content-Length" / "l" ) HCOLON 1*DIGIT * @endcode * */ /**@ingroup msg_content_length * @typedef typedef struct msg_content_length_s msg_content_length_t; * * The structure msg_content_length_t contains representation of a * Content-Length header. * * The msg_content_length_t is defined as follows: * @code * typedef struct msg_content_length_s { * msg_common_t l_common[1]; // Common fragment info * msg_error_t *l_next; // Link to next (dummy) * unsigned long l_length; // Numeric value * } msg_content_length_t; * @endcode */ #define msg_content_length_d msg_numeric_d #define msg_content_length_e msg_numeric_e msg_hclass_t msg_content_length_class[] = MSG_HEADER_CLASS(msg_, content_length, "Content-Length", "l", l_common, single_critical, msg_default, msg_generic); /**@ingroup msg_content_length *Create a @b Content-Length header object. * * The function msg_content_length_create() creates a Content-Length * header object with the value @a n. The memory for the header is * allocated from the memory home @a home. * * @param home memory home * @param n payload size in bytes * * @return * The function msg_content_length_create() returns a pointer to newly * created @b Content-Length header object when successful or NULL upon * an error. */ msg_content_length_t *msg_content_length_create(su_home_t *home, uint32_t n) { msg_content_length_t *l = (msg_content_length_t *) msg_header_alloc(home, msg_content_length_class, 0); if (l) l->l_length = n; return l; } /* ====================================================================== */ /**@ingroup msg_mime * @defgroup msg_content_md5 Content-MD5 Header * * The Content-MD5 header is an MD5 digest of the entity-body for the * purpose of providing an end-to-end message integrity check (MIC) of the * message-body. Its syntax is defined in [@RFC1864, H14.15] as follows: * * @code * Content-MD5 = "Content-MD5" ":" md5-digest * md5-digest = * @endcode */ /**@ingroup msg_content_md5 * @typedef struct msg_generic_s msg_content_md5_t; * * The structure msg_content_md5_t contains representation of an @b * Content-MD5 header. * * The msg_content_md5_t is defined as follows: * @code * typedef struct msg_generic_s * { * msg_common_t g_common[1]; // Common fragment info * msg_generic_t *g_next; // Link to next header * char const *g_string; // Header value * } msg_content_md5_t; * @endcode */ #define msg_content_md5_d msg_generic_d #define msg_content_md5_e msg_generic_e msg_hclass_t msg_content_md5_class[] = MSG_HEADER_CLASS_G(content_md5, "Content-MD5", "", single); /* ====================================================================== */ /**@ingroup msg_mime * @defgroup msg_content_id Content-ID Header * * The Content-ID header is an unique identifier of an entity-body. The * Content-ID value may be used for uniquely identifying MIME entities in * several contexts, particularly for caching data referenced by the * message/external-body mechanism. Its syntax is defined in [RFC2045] as * follows: * * @code * Content-ID = "Content-ID" ":" msg-id * msg-id = [CFWS] "<" id-left "@" id-right ">" [CFWS] * id-left = dot-atom-text / no-fold-quote / obs-id-left * id-right = dot-atom-text / no-fold-literal / obs-id-right * @endcode */ /**@ingroup msg_content_id * @typedef msg_generic_t msg_content_id_t; * Content-ID Header Structure. * @code * typedef struct * { * msg_common_t g_common[1]; // Common fragment info * msg_content_id_t *g_next; // Link to next header * char const *g_string; // Header value * } * @endcode */ #define msg_content_id_d msg_generic_d #define msg_content_id_e msg_generic_e msg_hclass_t msg_content_id_class[] = MSG_HEADER_CLASS_G(content_id, "Content-ID", "", single); /* ====================================================================== */ /**@ingroup msg_mime * @defgroup msg_content_type Content-Type Header * * The @b Content-Type header indicates the media type of the message-body * sent to the recipient. Its syntax is defined in [H3.7, S20.15] * as follows: * * @code * Content-Type = ( "Content-Type" | "c" ) ":" media-type * media-type = type "/" subtype *( ";" parameter ) * type = token * subtype = token * @endcode */ /**@ingroup msg_content_type * @typedef typedef struct msg_content_type_s msg_content_type_t; * * The structure msg_content_type_t contains representation of @b * Content-Type header. * * The msg_content_type_t is defined as follows: * @code * typedef struct msg_content_type_s { * msg_common_t c_common[1]; // Common fragment info * msg_unknown_t *c_next; // Dummy link to next * char const *c_type; // Pointer to type/subtype * char const *c_subtype; // Points after first slash in type * msg_param_t const *c_params; // List of parameters * } msg_content_type_t; * @endcode * * The @a c_type is always void of whitespace, that is, there is no * whitespace around the slash. */ #define msg_content_type_update NULL msg_hclass_t msg_content_type_class[] = MSG_HEADER_CLASS(msg_, content_type, "Content-Type", "c", c_params, single, msg_content_type, msg_content_type); issize_t msg_content_type_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { msg_content_type_t *c; assert(h); c = (msg_content_type_t *)h; /* "Content-type:" type/subtyp *(; parameter))) */ if (msg_mediatype_d(&s, &c->c_type) == -1 || /* compacts token / token */ (c->c_subtype = strchr(c->c_type, '/')) == NULL || (*s == ';' && msg_params_d(home, &s, &c->c_params) == -1) || (*s != '\0')) return -1; c->c_subtype++; return 0; } issize_t msg_content_type_e(char b[], isize_t bsiz, msg_header_t const *h, int flags) { char *b0 = b, *end = b + bsiz; msg_content_type_t const *c = (msg_content_type_t *)h; assert(msg_is_content_type(h)); MSG_STRING_E(b, end, c->c_type); MSG_PARAMS_E(b, end, c->c_params, flags); MSG_TERM_E(b, end); return b - b0; } isize_t msg_content_type_dup_xtra(msg_header_t const *h, isize_t offset) { msg_content_type_t const *c = (msg_content_type_t *)h; MSG_PARAMS_SIZE(offset, c->c_params); offset += MSG_STRING_SIZE(c->c_type); return offset; } /** Duplicate one msg_content_type_t object */ char *msg_content_type_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra) { msg_content_type_t *c = (msg_content_type_t *)dst; msg_content_type_t const *o = (msg_content_type_t *)src; char *end = b + xtra; b = msg_params_dup(&c->c_params, o->c_params, b, xtra); MSG_STRING_DUP(b, c->c_type, o->c_type); c->c_subtype = c->c_type ? strchr(c->c_type, '/') : NULL; if (c->c_subtype) c->c_subtype++; assert(b <= end); (void)end; return b; } /* ====================================================================== */ /**@ingroup msg_mime * @defgroup msg_mime_version MIME-Version Header * * MIME-Version header indicates what version of the protocol was used * to construct the message. Its syntax is defined in [H19.4.1, S20.24] * as follows: * * @code * MIME-Version = "MIME-Version" ":" 1*DIGIT "." 1*DIGIT * @endcode */ /**@ingroup msg_mime_version * @typedef struct msg_generic_s msg_mime_version_t; * * The structure msg_mime_version_t contains representation of an @b * MIME-Version header. * * The msg_mime_version_t is defined as follows: * @code * typedef struct msg_generic_s * { * msg_common_t g_common[1]; // Common fragment info * msg_generic_t *g_next; // Link to next header * char const *g_string; // Header value * } msg_mime_version_t; * @endcode */ msg_hclass_t msg_mime_version_class[] = MSG_HEADER_CLASS_G(mime_version, "MIME-Version", "", single); issize_t msg_mime_version_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { return msg_generic_d(home, h, s, slen); } issize_t msg_mime_version_e(char b[], isize_t bsiz, msg_header_t const *h, int f) { assert(msg_is_mime_version(h)); return msg_generic_e(b, bsiz, h, f); } /* ====================================================================== */ /**@ingroup msg_mime * @defgroup msg_content_location Content-Location Header * * */ /**@ingroup msg_content_location * @typedef struct msg_generic_s msg_content_location_t; * * The structure msg_content_location_t contains representation of an @b * Content-Location header. * * The msg_content_location_t is defined as follows: * @code * typedef struct msg_generic_s * { * msg_common_t g_common[1]; // Common fragment info * msg_generic_t *g_next; // Link to next header * char const *g_string; // Header value * } msg_content_location_t; * @endcode */ #define msg_content_location_d msg_generic_d #define msg_content_location_e msg_generic_e msg_hclass_t msg_content_location_class[] = MSG_HEADER_CLASS_G(content_location, "Content-Location", "", single); /* ====================================================================== */ #if 0 /**@ingroup msg_mime * @defgroup msg_content_base Content-Base Header * * @RFC2617: * Content-Base was deleted from the specification: it was not * implemented widely, and there is no simple, safe way to introduce it * without a robust extension mechanism. In addition, it is used in a * similar, but not identical fashion in MHTML [45]. * */ /**@ingroup msg_content_base * @typedef msg_generic_t msg_content_base_t; * Content-Base Header Structure. * @code * typedef struct * { * msg_common_t g_common[1]; // Common fragment info * msg_content_base_t *g_next; // Link to next header * char const *g_string; // Header value * } * @endcode */ #define msg_content_base_d msg_generic_d #define msg_content_base_e msg_generic_e msg_hclass_t msg_content_base_class[] = MSG_HEADER_CLASS_G(content_base, "Content-Base", "", single); #endif /* ====================================================================== */ /**@ingroup msg_mime * @defgroup msg_content_transfer_encoding Content-Transfer-Encoding Header * * */ /**@ingroup msg_content_transfer_encoding * @typedef struct msg_generic_s msg_content_transfer_encoding_t; * * The structure msg_content_transfer_encoding_t contains representation of * an @b Content-Transfer-Encoding header. * * The msg_content_transfer_encoding_t is defined as follows: * @code * typedef struct msg_generic_s * { * msg_common_t g_common[1]; // Common fragment info * msg_generic_t *g_next; // Link to next header * char const *g_string; // Header value * } msg_content_transfer_encoding_t; * @endcode */ #define msg_content_transfer_encoding_d msg_generic_d #define msg_content_transfer_encoding_e msg_generic_e msg_hclass_t msg_content_transfer_encoding_class[] = MSG_HEADER_CLASS_G(content_transfer_encoding, "Content-Transfer-Encoding", "", single); /* ====================================================================== */ /**@ingroup msg_mime * @defgroup msg_warning Warning Header * * The Warning response-header field is used to carry additional information * about the status of a response. Its syntax is defined in [S20.43] * as follows: * * @code * Warning = "Warning" HCOLON warning-value *(COMMA warning-value) * warning-value = warn-code SP warn-agent SP warn-text * warn-code = 3DIGIT * warn-agent = hostport / pseudonym * ; the name or pseudonym of the server adding * ; the Warning header, for use in debugging * warn-text = quoted-string * pseudonym = token * @endcode */ /**@ingroup msg_warning * @typedef struct msg_warning_s msg_warning_t; * * The structure msg_warning_t contains representation of an @b * Warning header. * * The msg_warning_t is defined as follows: * @code * typedef struct msg_warning_s * { * msg_common_t w_common[1]; // Common fragment info * msg_warning_t *w_next; // Link to next Warning header * unsigned w_code; // Warning code * char const *w_host; // Hostname or pseudonym * char const *w_port; // Port number * char const *w_text; // Warning text * } msg_warning_t; * @endcode */ issize_t msg_warning_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { msg_warning_t *w = (msg_warning_t *)h; char *text; while (*s == ',') /* Ignore empty entries (comma-whitespace) */ *s = '\0', s += span_lws(s + 1) + 1; /* Parse protocol */ if (!IS_DIGIT(*s)) return -1; w->w_code = strtoul(s, &s, 10); skip_lws(&s); /* Host (and port) */ if (msg_hostport_d(&s, &w->w_host, &w->w_port) == -1) return -1; if (msg_quoted_d(&s, &text) == -1) return -1; if (msg_unquote(text, text) == NULL) return -1; w->w_text = text; return msg_parse_next_field(home, h, s, slen); } issize_t msg_warning_e(char b[], isize_t bsiz, msg_header_t const *h, int f) { msg_warning_t const *w = (msg_warning_t *)h; char const *port = w->w_port; int n; size_t m; n = snprintf(b, bsiz, "%03u %s%s%s ", w->w_code, w->w_host, port ? ":" : "", port ? port : ""); if (n < 0) return n; m = msg_unquoted_e((size_t)n < bsiz ? b + n : NULL, bsiz - n, w->w_text); if (b && n + m < bsiz) b[n + m] = '\0'; return n + m; } isize_t msg_warning_dup_xtra(msg_header_t const *h, isize_t offset) { msg_warning_t const *w = (msg_warning_t *)h; offset += MSG_STRING_SIZE(w->w_host); offset += MSG_STRING_SIZE(w->w_port); offset += MSG_STRING_SIZE(w->w_text); return offset; } char *msg_warning_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra) { msg_warning_t *w = (msg_warning_t *)dst; msg_warning_t const *o = (msg_warning_t *)src; char *end = b + xtra; w->w_code = o->w_code; MSG_STRING_DUP(b, w->w_host, o->w_host); MSG_STRING_DUP(b, w->w_port, o->w_port); MSG_STRING_DUP(b, w->w_text, o->w_text); assert(b <= end); (void)end; return b; } #define msg_warning_update NULL msg_hclass_t msg_warning_class[] = MSG_HEADER_CLASS(msg_, warning, "Warning", "", w_common, append, msg_warning, msg_warning); sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/msg_mime_table.c.in000066400000000000000000000034201223300710500240540ustar00rootroot00000000000000/**@ingroup msg_mime * @IFILE msg_mime_table.c.in * * Template for . * * @date Created: Wed Feb 21 11:01:45 2001 ppessi */ /* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@ingroup msg_mime * * @CFILE msg_mime_table.c * @brief Parser table used for testing. * * #AUTO# * * This file is generated from template . * * @author Pekka Pessi */ #include "config.h" #include #include #include #include #include #define msg_multipart_extract_body NULL #define msg_request_class NULL #define mp_request mp_common #define msg_status_class NULL #define mp_status mp_common #define msg_multipart_update NULL #define MSG_MULTIPART_HCLASS \ MSG_HEADER_CLASS(msg_, multipart, NULL, "", mp_common, append, \ msg_multipart, msg_multipart) sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/msg_name_hash.c000066400000000000000000000027731223300710500233060ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@ingroup test_msg * @CFILE msg_name_hash.c * * Calculate hash for given header name. * * @author Pekka Pessi * * @date Tue Aug 20 16:27:01 EEST 2002 ppessi * */ #include "config.h" #include #include #include #include #include #include #include #include #include int main(int argc, char *argv[]) { if (!argv[1] || argv[2]) { fprintf(stderr, "usage: msg_name_hash Header-Name\n"); exit(1); } printf("%d\n", msg_header_name_hash(argv[1], NULL)); exit(0); } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/msg_parser.awk000077500000000000000000000375341223300710500232250ustar00rootroot00000000000000#! /usr/bin/env awk # # This script recreates C files containing header-specific boilerplate stuff # using the given list of headers (usually obtained from the master structure). # # It can also create a parser table. # # -------------------------------------------------------------------- # # This file is part of the Sofia-SIP package # # Copyright (C) 2005 Nokia Corporation. # # Contact: Pekka Pessi # # 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 # # -------------------------------------------------------------------- # # Contributor(s): Pekka.Pessi@nokia.com. # # Created: Fri Apr 6 12:59:59 2001 ppessi # BEGIN { "date '+%a %b %e %H:%M:%S %Y'" | getline date; ascii = \ " " \ " !\"#$%&'()*+,-./0123456789:;<=>?" \ "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" \ "`abcdefghijklmnopqrstuvwxyz{|}~"; lower_case = "abcdefghijklmnopqrstuvwxyz"; N=0; # Initialize these as arrays split("", symbols); split("", names); split("", comments); split("", hashes); split("", NAMES); split("", Comments); split("", COMMENTS); # indexed by the C name of the header split("", Since); # Non-NUL if extra split("", Extra); # Offset in extra headers total = 0; ordinary = 0; basic = 0; extra = 0; without_experimental = 0; template=""; template1=""; template2=""; template3=""; prefix=""; tprefix=""; failed=0; success=0; ERRNO="error"; } function name_hash (name) { hash = 0; len = length(name); for (i = 1; i <= len; i++) { c = tolower(substr(name, i, 1)); hash = (38501 * (hash + index(ascii, c))) % 65536; } if (hash == 0) { print "*** msg_parser.awk: calculating hash failed\n"; exit(5); } if (0) { # Test that hash algorithm above agrees with the C version pipe = ("../msg/msg_name_hash " name); pipe | getline; close(pipe); if (hash != $0) { print name ": " hash " != " $0 > "/dev/stderr"; } } return hash ""; } # # Replace magic patterns in template p with header-specific values # function protos (name, comment, hash, since) { NAME=toupper(name); sub(/.*[\/][*][*][<][ ]*/, "", comment); sub(/[ ]*[*][\/].*/, "", comment); sub(/[ ]+/, " ", comment); short = match(comment, /[(][a-z][)]/); if (short) { short = substr(comment, short + 1, 1); sub(/ *[(][a-z][)]/, "", comment); shorts[index(lower_case, short)] = name; } do_hash = hash == 0; if (do_hash) { split(comment, parts, " "); name2 = tolower(parts[1]); gsub(/-/, "_", name2); if (name2 != name && name2 != tprefix "_" name) { print name " mismatch with " comment " (" real ")" > "/dev/stderr"; } hash = name_hash(parts[1]); hashed[name] = hash; if (comment !~ /header/) { comment = comment " header"; } } Comment = comment; if (!do_hash) { comment = tolower(comment); } COMMENT = toupper(comment); # Store the various forms into an array for the footer processing N++; hashes[N] = hash; names[N] = name; NAMES[N] = NAME; comments[N] = comment; Comments[N] = comment; COMMENTS[N] = COMMENT; symbols[name] = comment; if (since) { Since[name] = since; } expr = (without_experimental > 0 && do_hash); if (expr) { printf "%s is experimental\n", Comment; } experimental[N] = expr; if (PR) { if (expr) { print "#if SU_HAVE_EXPERIMENTAL" > PR; } replace(template, hash, name, NAME, comment, Comment, COMMENT, since); replace(template1, hash, name, NAME, comment, Comment, COMMENT, since); replace(template2, hash, name, NAME, comment, Comment, COMMENT, since); replace(template3, hash, name, NAME, comment, Comment, COMMENT, since); if (expr) { print "#endif /* SU_HAVE_EXPERIMENTAL */" > PR; } } } function replace (p, hash, name, NAME, comment, Comment, COMMENT, since) { # # Replace various forms of header name in template, print it out # if (p) { gsub(/#hash#/, hash, p); gsub(/#xxxxxx#/, name, p); gsub(/#XXXXXX#/, NAME, p); gsub(/#xxxxxxx_xxxxxxx#/, comment, p); gsub(/#Xxxxxxx_Xxxxxxx#/, Comment, p); gsub(/#XXXXXXX_XXXXXXX#/, COMMENT, p); if (since) { gsub(/#version#/, since, p); } else { # Remove line with #version# gsub(/\n[^#\n]*#version#[^\n]*/, "", p); } print p > PR; } } # # Repeat each line in the footer containing the magic replacement # pattern with an instance of all headers # function process_footer (text) { if (!match(tolower(text), /#(xxxxxx(x_xxxxxxx)?|hash)#/)) { n = length(text); while (substr(text, n) == "\n") { n = n - 1; text = substr(text, 1, n); } if (n > 0) print text > PR; return; } n = split(text, lines, RS); for (i = 1; i <= n; i++) { l = lines[i]; if (match(tolower(l), /#(xxxxxx(x_xxxxxxx)?|hash)#/)) { expr = 0; for (j = 1; j <= N; j++) { l = lines[i]; if (expr != experimental[j]) { expr = experimental[j]; if (expr) { print "#if SU_HAVE_EXPERIMENTAL" > PR; } else { print "#endif /* SU_HAVE_EXPERIMENTAL */" > PR; } } gsub(/#hash#/, hashes[j], l); gsub(/#xxxxxxx_xxxxxxx#/, comments[j], l); gsub(/#Xxxxxxx_Xxxxxxx#/, Comments[j], l); gsub(/#XXXXXXX_XXXXXXX#/, COMMENTS[j], l); gsub(/#xxxxxx#/, names[j], l); gsub(/#XXXXXX#/, NAMES[j], l); print l > PR; } if (expr) { print "#endif /* SU_HAVE_EXPERIMENTAL */" > PR; } } else { print l > PR; } } } # # Read flags used with headers # function read_header_flags (flagfile, line, tokens, name, value) { while ((getline line < flagfile) > 0) { sub(/^[ \t]+/, "", line); sub(/[ \t]+$/, "", line); if (line ~ /^#/ || line ~ /^$/) continue; split(line, tokens, /[ \t]*=[ \t]*/); name = tolower(tokens[1]); gsub(/-/, "_", name); gsub(/,/, " ", name); # print "FLAG: " name " = " tokens[2] if (header_flags[name]) { print flagfile ": already defined " tokens[1]; } else if (!symbols[name]) { print flagfile ": unknown header \"" tokens[1] "\""; } else { header_flags[name] = tokens[2]; } } close(flagfile); } # # Read in templates # function templates () { if (!auto) { auto = FILENAME; if (!prefix) { prefix = module; } if (!tprefix) { tprefix = prefix; } sub(/.*\//, "", auto); auto = "This file is automatically generated from <" auto "> by msg_parser.awk."; if (PR) { if (TEMPLATE == "") { TEMPLATE = PR ".in"; } RS0=RS; RS="\f\n"; if ((getline theader < TEMPLATE) < 0) { print ( TEMPLATE ": " ERRNO ); failed=1; exit(1); } getline header < TEMPLATE; getline template < TEMPLATE; getline footer < TEMPLATE; if (TEMPLATE1) { if ((getline dummy < TEMPLATE1) < 0) { print(TEMPLATE1 ": " ERRNO); failed=1; exit(1); } getline dummy < TEMPLATE1; getline template1 < TEMPLATE1; getline dummy < TEMPLATE1; } if (TEMPLATE2) { if ((getline dummy < TEMPLATE2) < 0) { print( TEMPLATE2 ": " ERRNO ); failed=1; exit(1); } getline dummy < TEMPLATE2; getline template2 < TEMPLATE2; getline dummy < TEMPLATE2; } if (TEMPLATE3) { if ((getline dummy < TEMPLATE3) < 0) { print( TEMPLATE3 ": " ERRNO ); failed=1; exit(1); } getline dummy < TEMPLATE3; getline template3 < TEMPLATE3; getline dummy < TEMPLATE3; } sub(/.*[\/]/, "", TEMPLATE); gsub(/#AUTO#/, auto, header); gsub(/#DATE#/, "@date Generated: " date, header); if (PACKAGE_NAME) gsub(/#PACKAGE_NAME#/, PACKAGE_NAME, header); if (PACKAGE_VERSION) gsub(/#PACKAGE_VERSION#/, PACKAGE_VERSION, header); print header > PR; RS=RS0; } if (!NO_FIRST) { protos("request", "/**< Request line */", -1); protos("status", "/**< Status line */", -2); } } } /^#### EXTRA HEADER LIST STARTS HERE ####$/ { HLIST=1; templates(); } HLIST && /^#### DEFAULT HEADER LIST ENDS HERE ####$/ { basic=total; } HLIST && /^#### EXPERIMENTAL HEADER LIST STARTS HERE ####$/ { without_experimental = total; } HLIST && /^[a-z]/ { protos($1, $0, 0, $2); headers[total++] = $1; Extra[$1] = extra++; } /^#### EXTRA HEADER LIST ENDS HERE ####$/ { HLIST=0; } /^ *\/\* === Headers start here \*\// { in_header_list=1; templates(); } /^ *\/\* === Headers end here \*\// { in_header_list=0; } PT && /^ *\/\* === Hash headers end here \*\// { in_header_list=0;} in_header_list && /^ (sip|rtsp|http|msg|mp)_[a-z_0-9]+_t/ { n=$0 sub(/;.*$/, "", n); sub(/^ *(sip|rtsp|http|msg|mp)_[a-z0-9_]*_t[ ]*/, "", n); sub(/^[*](sip|rtsp|http|msg|mp)_/, "", n); if ($0 !~ /[\/][*][*][<]/) { getline; } if ($0 !~ /[\/][*][*][<]/) { printf "msg_protos.awk: header %s is malformed\n", n; failed=1; exit 1; } if (!NO_MIDDLE) protos(n, $0, 0); headers[total] = n; total++; ordinary++; } function print_parser_table(struct, scope, name, N, N_EXPERIMENTAL) { if (PT) { if (N > ordinary) { printf("/* Ordinary %u, extra %u, experimental %u */\n", ordinary, N - ordinary, N_EXPERIMENTAL - N) > PT; printf("struct %s {\n", struct) > PT; printf(" %s_t base;\n", module) > PT; printf(" msg_header_t *extra[%u];\n", N - ordinary) > PT; if (N != N_EXPERIMENTAL) { print "#if SU_HAVE_EXPERIMENTAL" > PT; printf(" msg_header_t *extra[%u];\n", N_EXPERIMENTAL - N) > PT; print "#endif" > PT; } printf("};\n\n") > PT; } printf("%s\n", scope) > PT; printf("msg_mclass_t const %s[1] = \n{{\n", name) > PT; printf("# if defined (%s_HCLASS)\n", toupper(module)) > PT; printf(" %s_HCLASS,\n", toupper(module)) > PT; printf("#else\n") > PT; printf(" {{ 0 }},\n") > PT; printf("#endif\n") > PT; printf(" %s_VERSION_CURRENT,\n", toupper(module)) > PT; printf(" %s_PROTOCOL_TAG,\n", toupper(module)) > PT; printf("#if defined (%s_PARSER_FLAGS)\n", toupper(module)) > PT; printf(" %s_PARSER_FLAGS,\n", toupper(module)) > PT; printf("#else\n") > PT; printf(" 0,\n") > PT; printf("#endif\n") > PT; if (N > ordinary) { printf(" sizeof (struct %s),\n", struct) > PT; } else { printf(" sizeof (%s_t),\n", module) > PT; } printf(" %s_extract_body,\n", module) > PT; len = split("request status separator payload unknown error", unnamed, " "); for (i = 1; i <= len; i++) { printf(" {{ %s_%s_class, msg_offsetof(%s_t, %s_%s) }},\n", tprefix, unnamed[i], module, prefix, unnamed[i]) > PT; } if (multipart) { printf(" {{ %s_class, msg_offsetof(%s_t, %s_multipart) }},\n", multipart, module, prefix) > PT; } else { printf(" {{ NULL, 0 }},\n") > PT; } if (MC_SHORT_SIZE) { printf(" %s_short_forms, \n", module) > PT; } else { printf(" NULL, \n") > PT; } printf(" %d, \n", MC_HASH_SIZE) > PT; if (N != N_EXPERIMENTAL) { print "#if SU_HAVE_EXPERIMENTAL" > PT; printf(" %d,\n", N_EXPERIMENTAL) > PT; print "#else" > PT; } printf(" %d,\n", N) > PT; if (N != N_EXPERIMENTAL) { print "#endif" > PT; } printf(" {\n") > PT; for (j = 0; j < MC_HASH_SIZE; j++) { c = (j + 1 == MC_HASH_SIZE) ? "" : ","; if (j in header_hash) { n = header_hash[j]; i = index_hash[j]; flags = header_flags[n]; if (flags) flags = ",\n " flags; if (i >= N) { print "#if SU_HAVE_EXPERIMENTAL" > PT; } if (i >= ordinary) { printf(" { %s_%s_class,\n" \ " msg_offsetof(struct %s, extra[%u])%s }%s\n", tprefix, n, struct, Extra[n], flags, c) > PT; } else { printf(" { %s_%s_class, msg_offsetof(%s_t, %s_%s)%s }%s\n", tprefix, n, module, prefix, n, flags, c) > PT; } if (i >= N) { printf("#else\n { NULL, 0 }%s\n#endif\n", c) > PT; } } else { printf(" { NULL, 0 }%s\n", c) > PT; } } printf(" }\n}};\n\n") > PT; } } END { if (failed) { exit }; if (!NO_LAST) { protos("unknown", "/**< Unknown headers */", -3); protos("error", "/**< Erroneous headers */", -4); protos("separator", "/**< Separator line between headers and body */", -5); protos("payload", "/**< Message payload */", -6); if (multipart) protos("multipart", "/**< Multipart payload */", -7); } if (PR) { process_footer(footer); } else if (PT) { if (FLAGFILE) read_header_flags(FLAGFILE); if (TEMPLATE == "") { TEMPLATE = PT ".in"; } RS0=RS; RS=" \n"; getline theader < TEMPLATE; getline header < TEMPLATE; getline template < TEMPLATE; getline footer < TEMPLATE; RS=RS0; sub(/.*[\/]/, "", TEMPLATE); gsub(/#AUTO#/, auto, header); gsub(/#DATE#/, "@date Generated: " date, header); print header > PT; print "" > PT; print "#define msg_offsetof(s, f) ((unsigned short)offsetof(s ,f))" > PT; print "" > PT; if (MC_SHORT_SIZE) { printf("static msg_href_t const " \ "%s_short_forms[MC_SHORT_SIZE] = \n{\n", module) > PT; for (i = 1; i <= MC_SHORT_SIZE; i = i + 1) { c = (i == MC_SHORT_SIZE) ? "" : ","; if (i in shorts) { n = shorts[i]; flags = header_flags[n]; if (flags) flags = ",\n " flags; printf(" { /* %s */ %s_%s_class, msg_offsetof(%s_t, %s_%s)%s }%s\n", substr(lower_case, i, 1), tprefix, n, module, prefix, n, flags, c) \ > PT; } else { printf(" { NULL }%s\n", c) \ > PT; } } printf("};\n\n") > PT; } # printf("extern msg_hclass_t msg_multipart_class[];\n\n") > PT; if (basic == 0) basic = total; if (without_experimental == 0) without_experimental = total; split("", header_hash); split("", index_hash); for (i = 0; i < basic; i++) { n = headers[i]; h = hashed[n]; if (h < 0) continue; j = h % MC_HASH_SIZE; if (j == -0) j = 0; for (; j in header_hash;) { if (++j == MC_HASH_SIZE) { j = 0; } } header_hash[j] = n; index_hash[j] = i; } m = module "_mclass"; s = "_d_" module "_t"; # Add basic headers if (ordinary == basic) { print_parser_table(s, "", m, basic, basic); } else if (basic < without_experimental) { print_parser_table(s, "", m, basic, basic); } else { print_parser_table(s, "", m, without_experimental, basic); } if (0) { # Hash extra headers for (i = basic; i < total; i++) { n = headers[i]; h = hashed[n]; if (h < 0) continue; j = h % MC_HASH_SIZE; if (j == -0) j = 0; for (; j in header_hash;) { if (++j == MC_HASH_SIZE) { j = 0; } } header_hash[j] = n; index_hash[j] = i; } if (basic < total) { m = module "_ext_mclass"; s = "_e_" module "_s"; print_parser_table(s, "static", m, without_experimental, total); } printf("msg_mclass_t const * %s_extended_mclass = %s;\n\n", module, m) > PT; } if (basic < total) { printf("msg_hclass_t * const %s_extensions[] = {\n", module) > PT; for (i = basic; i < total; i++) { if (i == without_experimental) { print "#if SU_HAVE_EXPERIMENTAL" > PT; } printf(" %s_%s_class,\n", module, headers[i]) > PT; } if (total != without_experimental) print "#endif" > PT; print " NULL\n};\n\n" > PT; } } exit success; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/msg_parser.c000066400000000000000000002211611223300710500226510ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@ingroup msg_parser * @CFILE msg_parser.c * * HTTP-like message parser engine. * * @author Pekka Pessi * * @date Created: Thu Oct 5 14:01:24 2000 ppessi * */ /*#define NDEBUG*/ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include "msg_internal.h" #include "sofia-sip/msg_header.h" #include "sofia-sip/bnf.h" #include "sofia-sip/msg_parser.h" #include "sofia-sip/msg_mclass.h" #include "sofia-sip/msg_mclass_hash.h" #include "sofia-sip/msg_mime.h" #if HAVE_FUNC #elif HAVE_FUNCTION #define __func__ __FUNCTION__ #else static char const __func__[] = "msg_parser"; #endif static int _msg_header_add_dup_as(msg_t *msg, msg_pub_t *pub, msg_hclass_t *hc, msg_header_t const *src); static void msg_insert_chain(msg_t *msg, msg_pub_t *pub, int prepend, msg_header_t **head, msg_header_t *h); static void msg_insert_here_in_chain(msg_t *msg, msg_header_t **prev, msg_header_t *h); su_inline msg_header_t *msg_chain_remove(msg_t *msg, msg_header_t *h); #ifndef NDEBUG static int msg_chain_loop(msg_header_t const *h); static int msg_chain_errors(msg_header_t const *h); #endif /* ====================================================================== */ /* Message properties */ /** Get message flags. */ unsigned msg_get_flags(msg_t const *msg, unsigned mask) { return msg ? msg->m_object->msg_flags & mask : 0; } /** Set message flags. */ unsigned msg_set_flags(msg_t *msg, unsigned mask) { return msg ? msg->m_object->msg_flags |= mask : 0; } /** Clear message flags. */ unsigned msg_zap_flags(msg_t *msg, unsigned mask) { return msg ? msg->m_object->msg_flags &= ~mask : 0; } /** Test if streaming is in progress. */ int msg_is_streaming(msg_t const *msg) { return msg && msg->m_streaming != 0; } /** Enable/disable streaming */ void msg_set_streaming(msg_t *msg, enum msg_streaming_status what) { if (msg) msg->m_streaming = what != 0; } /* ---------------------------------------------------------------------- */ /** Test if header is not in the chain */ #define msg_header_is_removed(h) ((h)->sh_prev == NULL) su_inline int msg_is_request(msg_header_t const *h) { return h->sh_class->hc_hash == msg_request_hash; } su_inline int msg_is_status(msg_header_t const *h) { return h->sh_class->hc_hash == msg_status_hash; } /* ====================================================================== */ /* Message buffer management */ /** Allocate a buffer of @a size octets, with slack of #msg_min_size. */ void *msg_buf_alloc(msg_t *msg, usize_t size) { struct msg_mbuffer_s *mb = msg->m_buffer; size_t room = mb->mb_size - mb->mb_commit - mb->mb_used; size_t target_size; if (mb->mb_data && room >= (unsigned)size) return mb->mb_data + mb->mb_used + mb->mb_commit; target_size = msg_min_size * ((size + mb->mb_commit) / msg_min_size + 1) - mb->mb_commit; return msg_buf_exact(msg, target_size); } /** Allocate a buffer exactly of @a size octets, without any slack. */ void *msg_buf_exact(msg_t *msg, usize_t size) { struct msg_mbuffer_s *mb = msg->m_buffer; size_t room = mb->mb_size - mb->mb_commit - mb->mb_used; char *buffer; int realloc; if (mb->mb_data && room >= (unsigned)size) return mb->mb_data + mb->mb_used + mb->mb_commit; size += mb->mb_commit; if (msg->m_maxsize && msg->m_size + size > msg->m_maxsize + 1) { msg->m_object->msg_flags |= MSG_FLG_TOOLARGE; errno = msg->m_errno = ENOBUFS; return NULL; } realloc = !mb->mb_used && !msg->m_set_buffer; if (realloc) buffer = su_realloc(msg->m_home, mb->mb_data, size); else buffer = su_alloc(msg->m_home, size); if (!buffer) return NULL; if (!realloc && mb->mb_commit && mb->mb_data) memcpy(buffer, mb->mb_data + mb->mb_used, mb->mb_commit); msg->m_set_buffer = 0; mb->mb_data = buffer; mb->mb_size = size; mb->mb_used = 0; return buffer + mb->mb_commit; } /** Commit data into buffer. */ usize_t msg_buf_commit(msg_t *msg, usize_t size, int eos) { if (msg) { struct msg_mbuffer_s *mb = msg->m_buffer; assert(mb->mb_used + mb->mb_commit + size <= mb->mb_size); mb->mb_commit += size; mb->mb_eos = eos; if (mb->mb_used == 0 && !msg->m_chunk && !msg->m_set_buffer) { size_t slack = mb->mb_size - mb->mb_commit; if (eos || slack >= msg_min_size) { /* realloc and cut down buffer */ size_t new_size; void *new_data; if (eos) new_size = mb->mb_commit + 1; else new_size = mb->mb_commit + msg_min_size; new_data = su_realloc(msg->m_home, mb->mb_data, new_size); if (new_data) { mb->mb_data = new_data, mb->mb_size = new_size; } } } } return 0; } /** Get length of committed data */ usize_t msg_buf_committed(msg_t const *msg) { if (msg) return msg->m_buffer->mb_commit; else return 0; } /** Get committed data */ void *msg_buf_committed_data(msg_t const *msg) { return msg && msg->m_buffer->mb_data ? msg->m_buffer->mb_data + msg->m_buffer->mb_used : NULL; } usize_t msg_buf_size(msg_t const *msg) { assert(msg); if (msg) { struct msg_mbuffer_s const *mb = msg->m_buffer; return mb->mb_size - mb->mb_commit - mb->mb_used; } else return 0; } su_inline void msg_buf_used(msg_t *msg, usize_t used) { msg->m_size += used; msg->m_buffer->mb_used += used; if (msg->m_buffer->mb_commit > used) msg->m_buffer->mb_commit -= used; else msg->m_buffer->mb_commit = 0; } /** Set buffer. */ void msg_buf_set(msg_t *msg, void *b, usize_t size) { if (msg) { struct msg_mbuffer_s *mb = msg->m_buffer; assert(!msg->m_set_buffer); /* This can be set only once */ mb->mb_data = b; mb->mb_size = size; mb->mb_used = 0; mb->mb_commit = 0; mb->mb_eos = 0; msg->m_set_buffer = 1; } } /** Move unparsed data from src to dst */ void *msg_buf_move(msg_t *dst, msg_t const *src) { void *retval; struct msg_mbuffer_s *db = dst->m_buffer; struct msg_mbuffer_s const *sb = src->m_buffer; if (!dst || !src) return NULL; if (sb->mb_eos) retval = msg_buf_exact(dst, sb->mb_commit + 1); else retval = msg_buf_alloc(dst, sb->mb_commit + 1); if (retval == NULL) return NULL; memcpy(retval, sb->mb_data + sb->mb_used, sb->mb_commit); db->mb_commit += sb->mb_commit; db->mb_eos = sb->mb_eos; return retval; } /**Obtain I/O vector for receiving the data. * * @relatesalso msg_s * * Allocate buffers for receiving @a n bytes * of data available from network. Function returns the buffers in the I/O vector * @a vec. The @a vec is allocated by the caller, the available length is * given as @a veclen. If the protocol is message-oriented like UDP or SCTP * and the available data ends at message boundary, the caller should set * the @a exact as 1. Otherwise some extra buffer (known as @em slack) is * allocated). * * Currently, the msg_recv_iovec() allocates receive buffers in at most two * blocks, so the caller should allocate at least two elements for the I/O * vector @a vec. * * @param[in] msg message object * @param[out] vec I/O vector * @param[in] veclen available length of @a vec * @param[in] n number of possibly available bytes * @param[in] exact true if data ends at message boundary * * @return * The length of I/O vector to * receive data, 0 if there are not enough buffers, or -1 upon an error. * * @sa msg_iovec(), su_vrecv() */ issize_t msg_recv_iovec(msg_t *msg, msg_iovec_t vec[], isize_t veclen, usize_t n, int exact) { size_t i = 0; size_t len = 0; msg_payload_t *chunk; char *buf; if (n == 0) return 0; if (veclen == 0) vec = NULL; for (chunk = msg->m_chunk; chunk; chunk = MSG_CHUNK_NEXT(chunk)) { buf = MSG_CHUNK_BUFFER(chunk); len = MSG_CHUNK_AVAIL(chunk); if (len == 0) continue; if (!buf) break; #if SU_HAVE_WINSOCK /* WSABUF has u_long */ if (len > SU_IOVECLEN_MAX) len = SU_IOVECLEN_MAX; #endif if (len > n) len = n; if (vec) vec[i].mv_base = buf, vec[i].mv_len = (su_ioveclen_t)len; i++; if (len == n) return i; if (i == veclen) vec = NULL; n -= len; } if (!chunk && msg->m_chunk && msg_get_flags(msg, MSG_FLG_FRAGS)) { /* * If the m_chunk is the last fragment for this message, * receive rest of the data to the next message */ if (msg->m_next == NULL) msg->m_next = msg_create(msg->m_class, msg->m_oflags); if (msg->m_next) { msg->m_next->m_maxsize = msg->m_maxsize; msg_addr_copy(msg->m_next, msg); } msg = msg->m_next; if (msg == NULL) return 0; } if (exact) buf = msg_buf_exact(msg, n + 1), len = n; else if (chunk && len > n && !msg_get_flags(msg, MSG_FLG_CHUNKING)) buf = msg_buf_exact(msg, len + 1); else buf = msg_buf_alloc(msg, n + 1), len = msg_buf_size(msg); if (buf == NULL) return -1; if (vec) vec[i].mv_base = buf, vec[i].mv_len = (su_ioveclen_t)n; if (chunk) { assert(chunk->pl_data == NULL); assert(chunk->pl_common->h_len == 0); chunk->pl_common->h_data = chunk->pl_data = buf; if (len < MSG_CHUNK_AVAIL(chunk)) { msg_header_t *h = (void*)chunk; h->sh_succ = msg_header_alloc(msg_home(msg), h->sh_class, 0); if (!h->sh_succ) return -1; h->sh_succ->sh_prev = &h->sh_succ; chunk->pl_next = (msg_payload_t *)h->sh_succ; chunk->pl_next->pl_len = chunk->pl_len - len; chunk->pl_len = len; } else if (len > MSG_CHUNK_AVAIL(chunk)) { len = MSG_CHUNK_AVAIL(chunk); } msg_buf_used(msg, len); } return i + 1; #if 0 if ((msg->m_ssize || msg->m_stream) /* && msg_get_flags(msg, MSG_FLG_BODY) */) { /* Streaming */ msg_buffer_t *b, *b0; /* Calculate available size of current buffers */ for (b = msg->m_stream, len = 0; b && n > len; b = b->b_next) len += b->b_avail - b->b_size; /* Allocate new buffers */ if (n > len && msg_buf_external(msg, n, 0) < 0) return -1; for (b0 = msg->m_stream; b0; b0 = b0->b_next) if (b0->b_avail != b0->b_size) break; for (b = b0; b && n > 0; i++, b = b->b_next) { len = b->b_size - b->b_avail; len = n < len ? n : len; if (vec && i < veclen) vec[i].mv_base = b->b_data + b->b_avail, vec[i].mv_len = len; else vec = NULL; n -= len; } return i + 1; } #endif } /** Obtain a buffer for receiving data. * * @relatesalso msg_s */ issize_t msg_recv_buffer(msg_t *msg, void **return_buffer) { void *buffer; if (!msg) return -1; if (return_buffer == NULL) return_buffer = &buffer; if (msg->m_chunk) { msg_payload_t *pl; for (pl = msg->m_chunk; pl; pl = pl->pl_next) { size_t n = MSG_CHUNK_AVAIL(pl); if (n) { *return_buffer = MSG_CHUNK_BUFFER(pl); return n; } } return 0; } if (msg_get_flags(msg, MSG_FLG_FRAGS)) { /* Message is complete */ return 0; } else if ((*return_buffer = msg_buf_alloc(msg, 2))) { return msg_buf_size(msg) - 1; } else { return -1; } } /**Commit @a n bytes of buffers. * * @relatesalso msg_s * * The function msg_recv_commit() is called after @a n bytes of data has * been received to the message buffers and the parser can extract the * received data. * * @param msg pointer to message object * @param n number of bytes received * @param eos true if stream is complete * * @note The @a eos should be always true for message-based transports. It * should also be true when a stram oin stream-based transport ends, for * instance, when TCP FIN is received. * * @retval 0 when successful * @retval -1 upon an error. */ isize_t msg_recv_commit(msg_t *msg, usize_t n, int eos) { msg_payload_t *pl; if (eos) msg->m_buffer->mb_eos = 1; for (pl = msg->m_chunk; pl; pl = pl->pl_next) { size_t len = MSG_CHUNK_AVAIL(pl); if (n <= len) len = n; pl->pl_common->h_len += len; n -= len; if (n == 0) return 0; } if (msg->m_chunk && msg->m_next) msg = msg->m_next; return msg_buf_commit(msg, n, eos); } /**Get a next message of the stream. * * @relatesalso msg_s * * When parsing a transport stream, only the first message in the stream is * created with msg_create(). The rest of the messages should be created * with msg_next() after previous message has been completely received and * parsed. * */ msg_t *msg_next(msg_t *msg) { msg_t *next; usize_t n; if (msg && msg->m_next) { next = msg->m_next; msg->m_next = NULL; return next; } if ((n = msg_buf_committed(msg))) { if (msg_buf_move(next = msg_create(msg->m_class, msg->m_oflags), msg)) { msg_addr_copy(next, msg); return next; } /* How to indicate error? */ msg_destroy(next); } return NULL; } /** Set next message of the stream. * * @relatesalso msg_s */ int msg_set_next(msg_t *msg, msg_t *next) { if (!msg || (next && next->m_next)) return -1; if (msg->m_next && next) next->m_next = msg->m_next; msg->m_next = next; return 0; } /** Clear committed data. * * @relatesalso msg_s */ void msg_clear_committed(msg_t *msg) { if (msg) { usize_t n = msg_buf_committed(msg); if (n) msg_buf_used(msg, n); } } #if 0 struct sigcomp_udvm; struct sigcomp_udvm *msg_get_udvm(msg_t *msg); struct sigcomp_udvm *msg_set_udvm(msg_t *msg, struct sigcomp_udvm *); /** Save UDVM. */ struct sigcomp_udvm *msg_set_udvm(msg_t *msg, struct sigcomp_udvm *udvm) { struct sigcomp_udvm *prev = NULL; if (msg) { prev = msg->m_udvm; msg->m_udvm = udvm; } return prev; } /** Get saved UDVM */ struct sigcomp_udvm *msg_get_udvm(msg_t *msg) { return msg ? msg->m_udvm : NULL; } #endif /** Mark message as complete. * * @relatesalso msg_s */ unsigned msg_mark_as_complete(msg_t *msg, unsigned mask) { if (msg) { msg->m_streaming = 0; return msg->m_object->msg_flags |= mask | MSG_FLG_COMPLETE; } else { return 0; } } /** Return true if message is complete. * * @relatesalso msg_s */ int msg_is_complete(msg_t const *msg) { return msg && MSG_IS_COMPLETE(msg->m_object); } /** Return true if message has parsing errors. * * @relatesalso msg_s */ int msg_has_error(msg_t const *msg) { return msg->m_object->msg_flags & MSG_FLG_ERROR; } /**Total size of message. * * @relatesalso msg_s */ usize_t msg_size(msg_t const *msg) { return msg ? msg->m_size : 0; } /** Set the maximum size of a message. * * @relatesalso msg_s * * The function msg_maxsize() sets the maximum buffer size of a message. It * returns the previous maximum size. If the @a maxsize is 0, maximum size * is not set, but the current maximum size is returned. * * If the message size exceeds maxsize, msg_errno() returns ENOBUFS, * MSG_FLG_TOOLARGE and MSG_FLG_ERROR flags are set. */ usize_t msg_maxsize(msg_t *msg, usize_t maxsize) { usize_t retval = 0; if (msg) { retval = msg->m_maxsize; if (maxsize) msg->m_maxsize = maxsize; } return retval; } /**Set the size of next fragment. * * @relatesalso msg_s * * The function msg_streaming_size() sets the size of the message body for * streaming. */ int msg_streaming_size(msg_t *msg, usize_t ssize) { if (!msg) return -1; msg->m_ssize = ssize; return 0; } /**Allocate a list of external buffers. * * @relatesalso msg_s * * The function msg_buf_external() allocates at most msg_n_fragments * external buffers for the message body. * * @return The function msg_buf_external() returns number of allocated * buffers, or -1 upon an error. */ issize_t msg_buf_external(msg_t *msg, usize_t N, usize_t blocksize) { msg_buffer_t *ext, *b, **bb; size_t i, I; assert(N <= 128 * 1024); if (msg == NULL) return -1; if (blocksize == 0) blocksize = msg_min_block; if (N == 0) N = blocksize; if (N > blocksize * msg_n_fragments) N = blocksize * msg_n_fragments; if (N > msg->m_ssize) N = msg->m_ssize; I = (N + blocksize - 1) / blocksize; assert(I <= msg_n_fragments); for (i = 0, bb = &ext; i < I; i++) { *bb = su_zalloc(msg_home(msg), sizeof **bb); if (!*bb) break; bb = &(*bb)->b_next; } if (i == I) for (b = ext, i = 0; b; b = b->b_next, i++) { b->b_data = su_alloc(msg_home(msg), b->b_size = blocksize); if (!b->b_data) break; } if (i == I) { /* Successful return */ for (bb = &msg->m_stream; *bb; bb = &(*bb)->b_next) ; *bb = ext; if (msg->m_ssize != MSG_SSIZE_MAX) for (b = ext; b; b = b->b_next) { if (msg->m_ssize < b->b_size) { b->b_size = msg->m_ssize; } msg->m_ssize -= b->b_size; } return i; } for (b = ext; b; b = ext) { ext = b->b_next; su_free(msg_home(msg), b->b_data); su_free(msg_home(msg), b); } return -1; } int msg_unref_external(msg_t *msg, msg_buffer_t *b) { if (msg && b) { su_free(msg_home(msg), b->b_data); su_free(msg_home(msg), b); return 0; } errno = EINVAL; return -1; } /* ====================================================================== */ /* Parsing messages */ su_inline int extract_incomplete_chunks(msg_t *, int eos); static issize_t extract_first(msg_t *, msg_pub_t *, char b[], isize_t bsiz, int eos); su_inline issize_t extract_next(msg_t *, msg_pub_t *, char *, isize_t bsiz, int eos, int copy); static issize_t extract_header(msg_t *, msg_pub_t*, char b[], isize_t bsiz, int eos, int copy); static msg_header_t *header_parse(msg_t *, msg_pub_t *, msg_href_t const *, char s[], isize_t slen, int copy_buffer); static msg_header_t *error_header_parse(msg_t *msg, msg_pub_t *mo, msg_href_t const *hr); su_inline issize_t extract_trailers(msg_t *msg, msg_pub_t *mo, char *b, isize_t bsiz, int eos, int copy); /** Calculate length of line ending (0, 1 or 2). @internal */ #define CRLF_TEST(b) ((b)[0] == '\r' ? ((b)[1] == '\n') + 1 : (b)[0] =='\n') su_inline void append_parsed(msg_t *msg, msg_pub_t *mo, msg_href_t const *hr, msg_header_t *h, int always_into_chain); /**Extract and parse a message from internal buffer. * * @relatesalso msg_s * * This function parses the internal buffer and adds the parsed fragments to * the message object. It marks the successfully parsed data as extracted. * * @param msg message to be parsed * * @retval positive if a complete message was parsed * @retval 0 if message was incomplete * @retval negative if an error occurred */ int msg_extract(msg_t *msg) { msg_pub_t *mo = msg_object(msg); msg_mclass_t const *mc; char *b; ssize_t m; size_t bsiz; int eos; if (!msg || !msg->m_buffer->mb_data) return -1; assert(mo); mc = msg->m_class; mo = msg->m_object; eos = msg->m_buffer->mb_eos; if (msg->m_chunk) { int incomplete = extract_incomplete_chunks(msg, eos); if (incomplete < 1 || MSG_IS_COMPLETE(mo)) return incomplete; } if (mo->msg_flags & MSG_FLG_TRAILERS) msg_set_streaming(msg, (enum msg_streaming_status)0); if (msg->m_buffer->mb_used + msg->m_buffer->mb_commit == msg->m_buffer->mb_size) /* Why? When? */ return 0; assert(msg->m_buffer->mb_used + msg->m_buffer->mb_commit < msg->m_buffer->mb_size); m = 0; b = msg->m_buffer->mb_data + msg->m_buffer->mb_used; bsiz = msg->m_buffer->mb_commit; b[bsiz] = '\0'; while (msg->m_buffer->mb_commit > 0) { int flags = mo->msg_flags; int copy = MSG_IS_EXTRACT_COPY(flags); if (flags & MSG_FLG_COMPLETE) break; if (flags & MSG_FLG_TRAILERS) m = extract_trailers(msg, mo, b, bsiz, eos, copy); else if (flags & MSG_FLG_BODY) m = mc->mc_extract_body(msg, mo, b, bsiz, eos); else if (flags & MSG_FLG_HEADERS) m = extract_next(msg, mo, b, bsiz, eos, copy); else m = extract_first(msg, mo, b, bsiz, eos); if (m <= 0 || msg->m_chunk) break; b += m; bsiz -= m; msg_buf_used(msg, (size_t)m); } if (eos && bsiz == 0) msg_mark_as_complete(msg, 0); if (m < 0 || (mo->msg_flags & MSG_FLG_ERROR)) { msg_mark_as_complete(msg, MSG_FLG_ERROR); return -1; } else if (!MSG_IS_COMPLETE(mo)) return 0; else if (!(mo->msg_flags & MSG_FLG_HEADERS)) { msg_mark_as_complete(msg, MSG_FLG_ERROR); return -1; } else return 1; } static issize_t extract_first(msg_t *msg, msg_pub_t *mo, char b[], isize_t bsiz, int eos) { /* First line */ size_t k, l, m, n, xtra; int crlf; msg_header_t *h; msg_href_t const *hr; msg_mclass_t const *mc = msg->m_class; for (k = 0; IS_LWS(b[k]); k++) /* Skip whitespace */ ; if (!b[k]) return k; /* If first token contains no /, this is request, otherwise status line */ l = span_token(b + k) + k; if (b[l] != '/') hr = mc->mc_request; else hr = mc->mc_status; n = span_non_crlf(b + l) + l; if (!b[n]) return eos ? -1 : 0; crlf = CRLF_TEST(b + n); for (m = n + crlf; IS_WS(b[m]); m++) ; /* In order to skip possible whitespace after first line, we don't parse first line until first non-ws char from next one has been received */ if (!b[m] && !eos) return 0; xtra = MSG_IS_EXTRACT_COPY(mo->msg_flags) ? n + 1 - k : 0; if (!(h = msg_header_alloc(msg_home(msg), hr->hr_class, xtra))) return -1; if (xtra) { char *bb = memcpy(MSG_HEADER_DATA(h), b, xtra - 1); h->sh_data = b, h->sh_len = n + crlf; b = bb; n = xtra - 1; } else { b = b + k; n = n - k; } b[n] = 0; if (hr->hr_class->hc_parse(msg_home(msg), h, b, n) < 0) return -1; assert(hr->hr_offset); append_parsed(msg, mo, hr, h, 1); mo->msg_flags |= MSG_FLG_HEADERS; return m; } /* Extract header or message body */ su_inline issize_t extract_next(msg_t *msg, msg_pub_t *mo, char *b, isize_t bsiz, int eos, int copy) { if (IS_CRLF(b[0])) return msg->m_class->mc_extract_body(msg, mo, b, bsiz, eos); else return extract_header(msg, mo, b, bsiz, eos, copy); } /** Extract a header. */ issize_t msg_extract_header(msg_t *msg, msg_pub_t *mo, char b[], isize_t bsiz, int eos) { return extract_header(msg, mo, b, bsiz, eos, 0); } /** Extract a header from buffer @a b. */ static issize_t extract_header(msg_t *msg, msg_pub_t *mo, char *b, isize_t bsiz, int eos, int copy_buffer) { size_t len, m; size_t name_len = 0, xtra; isize_t n = 0; int crlf = 0, name_len_set = 0; int error = 0; msg_header_t *h; msg_href_t const *hr; msg_mclass_t const *mc = msg->m_class; hr = msg_find_hclass(mc, b, &n); /* Get header name */ error = n == 0; if (hr == NULL) /* Panic */ return -1; xtra = span_ws(b + n); /* Find next crlf which is not followed by whitespace */ do { n += xtra + crlf; if (!eos && bsiz == n) return 0; m = span_non_crlf(b + n); if (!name_len_set && m) name_len = n, name_len_set = 1; /* First non-ws after COLON */ n += m; crlf = CRLF_TEST(b + n); xtra = span_ws(b + n + crlf); } while (xtra); if (!eos && bsiz == n + crlf) return 0; if (hr->hr_class->hc_hash == msg_unknown_hash) name_len = 0, name_len_set = 1; if (error) { msg->m_extract_err |= hr->hr_flags; if (hr->hr_class->hc_critical) mo->msg_flags |= MSG_FLG_ERROR; hr = mc->mc_error; copy_buffer = 1; h = error_header_parse(msg, mo, hr); } else { if (!name_len_set) /* Empty header - nothing but name, COLON and LWS */ name_len = n; else /* Strip extra whitespace at the end of header */ while (n > name_len && IS_LWS(b[n - 1])) n--, crlf++; h = header_parse(msg, mo, hr, b + name_len, n - name_len, copy_buffer); } if (h == NULL) return -1; len = n + crlf; /* * If the header contains multiple header fields, set the pointer to the * encodeded data correctly */ while (h) { if (copy_buffer) h->sh_data = b, h->sh_len = len; b += len, len = 0; if (h->sh_succ) assert(&h->sh_succ == h->sh_succ->sh_prev); h = h->sh_next; } return n + crlf; } static msg_header_t *header_parse(msg_t *msg, msg_pub_t *mo, msg_href_t const *hr, char s[], isize_t slen, int copy_buffer) { su_home_t *home = msg_home(msg); msg_header_t *h, **hh; msg_hclass_t *hc = hr->hr_class; int n; int add_to_list, clear = 0; hh = (msg_header_t **)((char *)mo + hr->hr_offset); add_to_list = (hc->hc_kind == msg_kind_list && !copy_buffer && *hh); if (add_to_list) h = *hh; else h = msg_header_alloc(home, hc, copy_buffer ? slen + 1 : 0); if (!h) return NULL; if (copy_buffer) s = memcpy(MSG_HEADER_DATA(h), s, slen); s[slen] = '\0'; if (hc->hc_kind == msg_kind_list && *hh) { n = hc->hc_parse(home, *hh, s, slen); /* Clear if adding new header disturbs existing headers */ clear = *hh != h && !copy_buffer; if (clear) msg_fragment_clear((*hh)->sh_common); } else n = hc->hc_parse(home, h, s, slen); if (n < 0) { msg->m_extract_err |= hr->hr_flags; if (hc->hc_critical) mo->msg_flags |= MSG_FLG_ERROR; clear = 0; if (!add_to_list) { /* XXX - This should be done by msg_header_free_all() */ msg_header_t *h_next; msg_param_t *h_params; msg_error_t *er; while (h) { h_next = h->sh_next; if (hc->hc_params) { h_params = *(msg_param_t **)((char *)h + hc->hc_params); if (h_params) su_free(home, h_params); } su_free(home, h); h = h_next; } /* XXX - This should be done by msg_header_free_all() */ hr = msg->m_class->mc_error; h = msg_header_alloc(home, hr->hr_class, 0); er = (msg_error_t *)h; if (!er) return NULL; er->er_name = hc->hc_name; hh = (msg_header_t **)((char *)mo + hr->hr_offset); } } if (clear) for (hh = &(*hh)->sh_next; *hh; *hh = (*hh)->sh_next) msg_chain_remove(msg, *hh); else if (h != *hh) append_parsed(msg, mo, hr, h, 0); return h; } static msg_header_t *error_header_parse(msg_t *msg, msg_pub_t *mo, msg_href_t const *hr) { msg_header_t *h; h = msg_header_alloc(msg_home(msg), hr->hr_class, 0); if (h) append_parsed(msg, mo, hr, h, 0); return h; } /** Complete this header field and parse next header field. * * This function completes parsing a multi-field header like @Accept, * @Contact, @Via or @Warning. It scans for the next header field and * if one is found, it calls the parsing function recursively. * * @param home memory home used ot allocate * new header structures and parameter lists * @param prev pointer to header structure already parsed * @param s header content to parse; should point to the area after * current header field (either end of line or to a comma * separating header fields) * @param slen ignored * * @since New in @VERSION_1_12_4. * * @retval >= 0 when successful * @retval -1 upon an error */ issize_t msg_parse_next_field(su_home_t *home, msg_header_t *prev, char *s, isize_t slen) { msg_hclass_t *hc = prev->sh_class; msg_header_t *h; char *end = s + slen; if (*s && *s != ',') return -1; if (msg_header_update_params(prev->sh_common, 0) < 0) return -1; while (*s == ',') /* Skip comma and following whitespace */ *s = '\0', s += span_lws(s + 1) + 1; if (*s == 0) return 0; h = msg_header_alloc(home, hc, 0); if (!h) return -1; prev->sh_succ = h, h->sh_prev = &prev->sh_succ; prev->sh_next = h; return hc->hc_parse(home, h, s, end - s); } /** Decode a message header. */ msg_header_t *msg_header_d(su_home_t *home, msg_t const *msg, char const *b) { msg_mclass_t const *mc = msg->m_class; msg_href_t const *hr = mc->mc_unknown; isize_t n; /* Length of header contents */ isize_t name_len, xtra; msg_header_t *h; char *bb; n = strlen(b); hr = msg_find_hclass(mc, b, &name_len); if (hr == NULL) return NULL; /* Strip extra whitespace at the end and begin of header */ while (n > name_len && IS_LWS(b[n - 1])) n--; if (name_len < n && IS_LWS(b[name_len])) name_len++; xtra = (n - name_len); if (!(h = msg_header_alloc(home, hr->hr_class, xtra + 1))) return NULL; bb = memcpy(MSG_HEADER_DATA(h), b + name_len, xtra), bb[xtra] = 0; if (hr->hr_class->hc_parse(home, h, bb, xtra) >= 0) return h; hr = mc->mc_unknown; su_free(home, h); if (!(h = msg_header_alloc(home, hr->hr_class, n + 1))) return NULL; bb = memcpy(MSG_HEADER_DATA(h), b, n), bb[n] = 0; if (hr->hr_class->hc_parse(home, h, bb, n) < 0) su_free(home, h), h = NULL; return h; } /** Extract a separator line */ issize_t msg_extract_separator(msg_t *msg, msg_pub_t *mo, char b[], isize_t bsiz, int eos) { msg_mclass_t const *mc = msg->m_class; msg_href_t const *hr = mc->mc_separator; int l = CRLF_TEST(b); /* Separator length */ msg_header_t *h; /* Even if a single CR *may* be a payload separator we cannot be sure */ if (l == 0 || (!eos && bsiz == 1 && b[0] == '\r')) return 0; /* Separator */ if (!(h = msg_header_alloc(msg_home(msg), hr->hr_class, 0))) return -1; if (hr->hr_class->hc_parse(msg_home(msg), h, b, l) < 0) return -1; h->sh_data = b, h->sh_len = l; append_parsed(msg, mo, hr, h, 0); return l; } su_inline msg_header_t **msg_chain_tail(msg_t const *msg); /** Extract a message body of @a body_len bytes. */ issize_t msg_extract_payload(msg_t *msg, msg_pub_t *mo, msg_header_t **return_payload, usize_t body_len, char b[], isize_t bsiz, int eos) { msg_mclass_t const *mc; msg_href_t const *hr; msg_header_t *h, *h0; msg_payload_t *pl; char *x; if (msg == NULL || mo == NULL) return -1; assert(!msg->m_chunk); mc = msg->m_class; hr = mc->mc_payload; if (return_payload == NULL) return_payload = &h0; *return_payload = NULL; assert(body_len > 0); /* Allocate header structure for payload */ if (!(h = msg_header_alloc(msg_home(msg), hr->hr_class, 0))) return -1; append_parsed(msg, mo, hr, h, 0); pl = (msg_payload_t*)h; *return_payload = h; if (bsiz >= body_len) { /* We have a complete body. */ h->sh_data = b, h->sh_len = body_len; pl->pl_data = b, pl->pl_len = body_len; return body_len; } if (msg->m_maxsize != 0 && body_len > msg->m_maxsize) { mo->msg_flags |= MSG_FLG_TOOLARGE; return -1; } assert(msg->m_buffer->mb_commit == bsiz); assert(b == msg->m_buffer->mb_data + msg->m_buffer->mb_used); if (msg->m_buffer->mb_used + body_len <= msg->m_buffer->mb_size) { /* We don't have a complete body, but we have big enough buffer for it. */ msg->m_chunk = pl; h->sh_data = b, h->sh_len = bsiz; pl->pl_data = b, pl->pl_len = body_len; if (msg->m_buffer->mb_used + body_len < msg->m_buffer->mb_size) /* NUL-terminate payload */ b[body_len++] = '\0'; /* Mark the rest of the body as used in the buffer */ /* msg_buf_commit(msg, body_len - bsiz, eos); */ msg_buf_used(msg, body_len); return bsiz; } /* We don't have big enough buffer for body. */ if (msg_get_flags(msg, MSG_FLG_CHUNKING)) { /* Application supports chunking, use multiple chunks for payload */ usize_t current, rest; current = msg->m_buffer->mb_size - msg->m_buffer->mb_used; rest = body_len - current; /* Use all the data from our current buffer */ msg_buf_used(msg, current); msg->m_chunk = pl; h->sh_data = b, h->sh_len = bsiz; pl->pl_data = b, pl->pl_len = current; for (;current < body_len; current += rest) { msg_header_t *h0 = h; /* Allocate header structure for next payload chunk */ if (!(h = msg_header_alloc(msg_home(msg), hr->hr_class, 0))) return -1; if (msg->m_chain) msg_insert_here_in_chain(msg, msg_chain_tail(msg), h); h0->sh_next = h; rest = body_len - current; if (!msg->m_streaming) { x = msg_buf_exact(msg, rest); if (x == NULL) { mo->msg_flags |= MSG_FLG_TOOLARGE; return -1; } } else { x = NULL; } if (x) { /* Mark the just-allocated buffer as used */ rest = msg->m_buffer->mb_size - msg->m_buffer->mb_used; msg_buf_used(msg, rest); } pl = h->sh_payload; h->sh_len = 0, pl->pl_len = rest; h->sh_data = x, pl->pl_data = x; } } else { /* No chunking. * * Allocate a single buffer that contains enough free space for body. * * msg_buf_exact() also copies committed but un-used data * from the old buffer (b[0] .. b[bsiz]) * to the new buffer (x[-bsiz-1]..b[-1]) */ if (!(x = msg_buf_exact(msg, body_len - bsiz + 1))) { if (mo->msg_flags & MSG_FLG_TOOLARGE) { msg_mark_as_complete(msg, MSG_FLG_TRUNC); return bsiz; } return -1; } /* Fake un-received data as already received and then use it */ /* msg_buf_commit(msg, body_len - bsiz + 1, eos); */ msg_buf_used(msg, body_len + 1); msg->m_chunk = h->sh_payload; x -= bsiz; /* Start of un-used data */ x[body_len] = '\0'; h->sh_data = x, h->sh_len = bsiz; pl->pl_data = x, pl->pl_len = body_len; assert(MSG_CHUNK_AVAIL(pl) == body_len - bsiz); } return bsiz; } /** Extract incomplete chunks. */ su_inline int extract_incomplete_chunks(msg_t *msg, int eos) { msg_payload_t *chunk; for (chunk = msg->m_chunk; chunk; chunk = MSG_CHUNK_NEXT(chunk)) { if (MSG_CHUNK_AVAIL(chunk) != 0) break; /* The incomplete payload fragment is now complete */ assert(MSG_CHUNK_BUFFER(chunk) == chunk->pl_data + chunk->pl_len); msg->m_size += chunk->pl_common->h_len; } msg->m_chunk = chunk; if (chunk) { if (eos) { msg_mark_as_complete(msg, MSG_FLG_TRUNC); return 1; } } else { if (msg_get_flags(msg, MSG_FLG_FRAGS)) msg_mark_as_complete(msg, 0); } /**@retval 1 when message is complete * @retval 0 when message is incomplete * @retval -1 upon an error */ return chunk == NULL; } /* Extract trailers */ su_inline issize_t extract_trailers(msg_t *msg, msg_pub_t *mo, char *b, isize_t bsiz, int eos, int copy) { if (IS_CRLF(b[0])) { msg_mark_as_complete(msg, MSG_FLG_COMPLETE); return CRLF_TEST(b); } else return extract_header(msg, mo, b, bsiz, eos, copy); } /* ====================================================================== */ /* Preparing (printing/encoding) a message structure for sending */ /* Internal prototypes */ su_inline size_t msg_header_name_e(char b[], size_t bsiz, msg_header_t const *h, int flags); static size_t msg_header_prepare(msg_mclass_t const *, int flags, msg_header_t *h, msg_header_t **return_next, char *b, size_t bsiz); /**Encode all message fragments. * * @relatesalso msg_s * * The function msg_prepare() prepares a message for sending. It encodes all * serialized fragments in the message. You have to call msg_serialize() * before calling msg_headers_prepare() in order to make sure that all the * heades and other message fragments are included in the chain. * * After encoding, the msg_common_s::h_data field will point to the encoding * result of size msg_common_s::h_len bytes in in each fragment. * * When multiple header fields are represented as a comma-separated list * within a single header line, the first fragment in the header will * contain all the text belonging to the header. The rest of the header * fields will have zero-length encoding with msg_common_s::h_data that * points to the end of the line. * * @return Total size of the encoded message in bytes, or -1 upon an error. * * @sa msg_extract(), msg_serialize() */ int msg_prepare(msg_t *msg) { int total; assert(msg->m_chain); assert(msg_chain_errors(msg->m_chain) == 0); /* Get rid of data that was received but not yet used (parsed) */ msg_clear_committed(msg); total = msg_headers_prepare(msg, msg->m_chain, msg_object(msg)->msg_flags); if (total != -1) { msg->m_size = total; msg->m_prepared = 1; } return total; } /** Clear 'prepared' flag. */ void msg_unprepare(msg_t *msg) { if (msg) msg->m_prepared = 0; } /** Return true if message is prepared. */ int msg_is_prepared(msg_t const *msg) { return msg && msg->m_prepared; } /**Encode headers in chain. * * The function msg_headers_prepare() encodes all the headers in the header * chain. You have to call msg_serialize() before calling * msg_headers_prepare() in order to make sure that all the heades and other * message fragments are included in the chain. * * @return * The size of all the headers in chain, or -1 upon an error. */ issize_t msg_headers_prepare(msg_t *msg, msg_header_t *headers, int flags) { msg_mclass_t const *mc = msg->m_class; msg_header_t *h, *next; ssize_t n = 0; size_t bsiz = 0, used = 0; char *b; size_t total = 0; b = msg_buf_alloc(msg, msg_min_size); bsiz = msg_buf_size(msg); if (!b) return -1; for (h = headers; h;) { if (h->sh_data) { total += h->sh_len; h = h->sh_succ; continue; } for (next = h->sh_succ; next; next = next->sh_succ) if (next->sh_class != h->sh_class || next->sh_data) break; n = msg_header_prepare(mc, flags, h, &next, b, bsiz - used); if (n == (ssize_t)-1) { errno = EINVAL; return -1; } if (used + n >= bsiz) { /* Allocate next buffer */ if ((b = msg_buf_alloc(msg, n + 1)) == NULL) return -1; bsiz = msg_buf_size(msg); used = 0; continue; } h->sh_data = b, h->sh_len = n; for (h = h->sh_succ; h != next; h = h->sh_succ) h->sh_data = b + n, h->sh_len = 0; msg_buf_used(msg, n); total += n; used += n; b += n; } return total; } /** Encode a header or a list of headers */ static size_t msg_header_prepare(msg_mclass_t const *mc, int flags, msg_header_t *h, msg_header_t **return_next, char *b, size_t bsiz) { msg_header_t *h0, *next; msg_hclass_t *hc; char const *s; size_t n; ssize_t m; int compact, one_line_list, comma_list; assert(h); assert(h->sh_class); hc = h->sh_class; compact = MSG_IS_COMPACT(flags); one_line_list = hc->hc_kind == msg_kind_apndlist; comma_list = compact || one_line_list || MSG_IS_COMMA_LISTS(flags); for (h0 = h, n = 0; ; h = next) { next = h->sh_succ; if (h == h0 && hc->hc_name && hc->hc_name[0]) n += msg_header_name_e(b + n, bsiz >= n ? bsiz - n : 0, h, flags); if ((m = hc->hc_print(b + n, bsiz >= n ? bsiz - n : 0, h, flags)) == -1) { if (bsiz >= n + 64) m = 2 * (bsiz - n); else m = 128; } n += m; if (hc->hc_name) { if (!comma_list || !next || next == *return_next) s = CRLF, m = 2; /* Else encode continuation */ else if (compact) s = ",", m = 1; else if (one_line_list) s = ", ", m = 2; else s = "," CRLF "\t", m = 4; if (bsiz > n + m) memcpy(b + n, s, m); n += m; } if (!comma_list || !next || next == *return_next) break; } *return_next = next; return n; } /** Encode a header. * * The function msg_header_e() encodes a header field in the buffer @a * b[]. The encoding includes its name and trailing CRLF. The function * returns the length of the encoding in bytes, excluding the final @c NUL. * The buffer @a b must be large enough for whole encoding, including the * final @c NUL. * * The @a flags parameter define how the encoding is done. If the flags * specify @c MSG_DO_COMPACT, the encoding is compact (short form with * minimal whitespace). */ issize_t msg_header_e(char b[], isize_t bsiz, msg_header_t const *h, int flags) { size_t n, m; assert(h); assert(h->sh_class); if (h == NULL || h->sh_class == NULL) return -1; n = msg_header_name_e(b, bsiz, h, flags); m = h->sh_class->hc_print(b + n, bsiz > n ? bsiz - n : 0, h, flags); if (h->sh_class->hc_name) { /* Ordinary header */ if (bsiz > n + m + strlen(CRLF)) strcpy(b + n + m, CRLF); return n + m + strlen(CRLF); } else return m; } /** Encode header name */ su_inline size_t msg_header_name_e(char b[], size_t bsiz, msg_header_t const *h, int flags) { int compact = MSG_IS_COMPACT(flags); char const *name; size_t n, n2; if (compact && h->sh_class->hc_short[0]) name = h->sh_class->hc_short, n = 1; else name = h->sh_class->hc_name, n = h->sh_class->hc_len; if (!name || !name[0]) return 0; n2 = compact ? n + 1 : n + 2; if (n2 < bsiz) { memcpy(b, name, n); b[n++] = ':'; if (!compact) b[n++] = ' '; b[n++] = '\0'; } return n2; } /** Convert a message to a string. * * A message is encoded and the encoding result is returned as a string. * Because the message may contain binary payload (or NUL in headers), the * message length is returned separately in @a *return_len, too. * * Note that the message is serialized as a side effect. * * @param home memory home used to allocate the string * @param msg message to encode * @param pub message object to encode (may be NULL) * @param flags flags used when encoding * @param return_len return-value parameter for encoded message length * * @return Encoding result as a C string. * * @since New in @VERSION_1_12_4 * * @sa msg_make(), msg_prepare(), msg_serialize(). */ char *msg_as_string(su_home_t *home, msg_t *msg, msg_pub_t *pub, int flags, size_t *return_len) { msg_mclass_t const *mc = msg->m_class; msg_header_t *h, *next; ssize_t n = 0; size_t bsiz = 0, used = 0; char *b, *b2; if (pub == NULL) pub = msg->m_object; if (msg_serialize(msg, pub) < 0) return NULL; if (return_len == NULL) return_len = &used; b = su_alloc(home, bsiz = msg_min_size); if (!b) return NULL; if (pub == msg->m_object) h = msg->m_chain; else h = pub->msg_common->h_succ; while (h) { for (next = h->sh_succ; next; next = next->sh_succ) if (next->sh_class != h->sh_class) break; n = msg_header_prepare(mc, flags, h, &next, b + used, bsiz - used); if (n == -1) { errno = EINVAL; su_free(home, b); return NULL; } if (bsiz > used + n) { used += n; h = next; } else { /* Realloc */ if (h->sh_succ) bsiz = (used + n + msg_min_size) / msg_min_size * msg_min_size; else bsiz = used + n + 1; if (bsiz < msg_min_size) { errno = ENOMEM; su_free(home, b); return NULL; } b2 = su_realloc(home, b, bsiz); if (b2 == NULL) { errno = ENOMEM; su_free(home, b); return NULL; } b = b2; continue; } } *return_len = used; b[used] = '\0'; /* NUL terminate */ return su_realloc(home, b, used + 1); } /* ====================================================================== */ /* Handling header chain */ su_inline void serialize_first(msg_t *msg, msg_header_t *h); static msg_header_t **serialize_one(msg_t *msg, msg_header_t *h, msg_header_t **prev); /** Return head of the fragment chain */ msg_header_t **msg_chain_head(msg_t const *msg) { return msg ? (msg_header_t **)&msg->m_chain : NULL; } su_inline msg_header_t **_msg_chain_head(msg_t const *msg) { return msg ? (msg_header_t **)&msg->m_chain : NULL; } /** Return tail of the fragment chain */ su_inline msg_header_t **msg_chain_tail(msg_t const *msg) { return msg ? msg->m_tail : NULL; } /** Serialize headers into the fragment chain. * * The msg_serialize() collects the headers and other message components in * the fragment chain. It should be called before msg_prepare(). * * @relatesalso msg_s * * @param msg pointer to message object * @param pub public message structure * * @retval 0 when successful * @retval -1 upon an error */ int msg_serialize(msg_t *msg, msg_pub_t *pub) { msg_header_t *h, **hh, **end; msg_header_t **separator; msg_header_t **payload; msg_header_t **multipart; msg_mclass_t const *mc; msg_header_t **tail, ***ptail; if (!msg) return errno = EINVAL, -1; if (pub == NULL) pub = msg->m_object; /* There must be a first line */ if (pub->msg_request) h = pub->msg_request; else if (pub->msg_status) h = pub->msg_status; else return errno = EINVAL, -1; serialize_first(msg, h); mc = msg->m_class; separator = (msg_header_t **)((char *)pub + mc->mc_separator->hr_offset); payload = (msg_header_t **)((char *)pub + mc->mc_payload->hr_offset); if (mc->mc_multipart->hr_class) multipart = (msg_header_t **)((char *)pub + mc->mc_multipart->hr_offset); else multipart = NULL; /* Find place to insert headers: before separator, payload and multipart */ if (*separator && !msg_header_is_removed(*separator)) ptail = &(*separator)->sh_prev; else if (*payload && !msg_header_is_removed(*payload)) ptail = &(*payload)->sh_prev; else if (multipart && *multipart && !msg_header_is_removed(*multipart)) ptail = &(*multipart)->sh_prev; else ptail = &msg->m_tail; tail = *ptail; end = (msg_header_t **)((char *)pub + pub->msg_size); for (hh = pub->msg_headers; hh < end; hh++) { if (!*hh) continue; if (hh == separator || hh == payload || hh == multipart) continue; tail = serialize_one(msg, *hh, tail); } /* Serialize separator, payload and multipart last */ if (*separator) tail = serialize_one(msg, *separator, tail); *ptail = tail; /* Payload comes after separator but before multipart */ if (ptail != &(*separator)->sh_prev) ; else if (*payload && !msg_header_is_removed(*payload)) ptail = &(*payload)->sh_prev; else if (multipart && *multipart && !msg_header_is_removed(*multipart)) ptail = &(*multipart)->sh_prev; else ptail = &msg->m_tail; tail = *ptail; if (*payload) { tail = serialize_one(msg, *payload, tail); *ptail = tail; } if (multipart && *multipart) { msg_header_t *last; last = msg_multipart_serialize(tail, (msg_multipart_t *)*multipart); msg->m_tail = &last->sh_succ; } assert(msg->m_chain && msg_chain_errors(msg->m_chain) == 0); return 0; } su_inline void serialize_first(msg_t *msg, msg_header_t *h) { if (msg_header_is_removed(h)) { if ((h->sh_succ = msg->m_chain)) h->sh_succ->sh_prev = &h->sh_succ; else msg->m_tail = &h->sh_succ; *(h->sh_prev = &msg->m_chain) = h; } } static msg_header_t **serialize_one(msg_t *msg, msg_header_t *h, msg_header_t **prev) { msg_header_t *last; msg_header_t *succ = *prev; if (msg_header_is_removed(h)) { /* Add the first header in the list to the chain */ *prev = h; h->sh_prev = prev; for (last = h; last->sh_succ; last = last->sh_succ) { /* Ensure that chain is connected */ assert(last->sh_next == last->sh_succ); assert(last->sh_succ->sh_prev = &last->sh_succ); } prev = &last->sh_succ; } if ((h = h->sh_next)) { assert(!msg_is_single(h)); if (msg_is_single(h)) { for (; h; h = h->sh_next) if (!msg_header_is_removed(h)) msg_chain_remove(msg, h); } /* Add the rest of the headers in the list to the chain */ else for (; h; h = h->sh_next) { if (msg_header_is_removed(h)) { *prev = h; h->sh_prev = prev; for (;h->sh_succ; h = h->sh_succ) assert(h->sh_succ == h->sh_next); prev = &h->sh_succ; } } } *prev = succ; return prev; } /**Fill an I/O vector with message contents. * * @relatesalso msg_s * * Calculate number of entries in the I/O vector * required to send a message @a msg. It also fills in the I/O vector array, * if it is provided by the caller and it is large enough. * * @param msg pointer to message object * @param vec I/O vector (may be NULL) * @param veclen length of I/O vector in @a vec * * @return * Number of entries of I/O * vector required by @a msg, or 0 upon an error. * * @note The caller should check that the I/O vector @a vec has enough * entries. If the @a vec is too short, it should allocate big enough * vector and re-invoke msg_iovec(). * * @sa msg_recv_iovec(), su_vsend() */ isize_t msg_iovec(msg_t *msg, msg_iovec_t vec[], isize_t veclen) { size_t len = 0, n = 0; char const *p = NULL; msg_header_t *h; size_t total = 0; if (veclen <= 0) veclen = 0; for (h = msg->m_chain; h; h = h->sh_succ) { if (h->sh_data != p) { p = h->sh_data; len = h->sh_len; if (p == NULL) return 0; if (vec && n != veclen) /* new iovec entry */ vec[n].mv_base = (void *)p, vec[n].mv_len = (su_ioveclen_t)len; else vec = NULL; p += len; n++; } else { /* extend old entry */ len = h->sh_len; if (vec) vec[n-1].mv_len += (su_ioveclen_t)len; p += len; } total += len; } msg->m_size = total; return n; } /** Insert a header to existing header chain. * * Headers are either inserted just before the payload, or after the first * line, depending on their type. * * @param[in] msg message object * @param[in,out] pub public message structure * @param prepend if true, add before same type of headers (instead after them) * @param head head of chain * @param h header to insert * */ static void msg_insert_chain(msg_t *msg, msg_pub_t *pub, int prepend, msg_header_t **head, msg_header_t *h) { msg_mclass_t const *mc; msg_header_t **hh; msg_header_t **separator; msg_header_t **payload; assert(msg && pub && head && h); mc = msg->m_class; separator = (msg_header_t **)((char *)pub + mc->mc_separator->hr_offset); payload = (msg_header_t **)((char *)pub + mc->mc_payload->hr_offset); if (msg_is_request(h)) { if (pub->msg_status) pub->msg_status = NULL; hh = head; } else if (msg_is_status(h)) { if (pub->msg_request) pub->msg_request = NULL; hh = head; } else if (msg_is_payload(h)) { /* Append */ hh = msg_chain_tail(msg); } else if (prepend) { if (!msg_is_request(*head) && !msg_is_status(*head)) hh = head; else hh = &((*head)->sh_succ); } /* Append headers before separator or payload */ else if (*separator && (*separator)->sh_prev) hh = (*separator)->sh_prev; else if (*payload && (*payload)->sh_prev) hh = (*payload)->sh_prev; else hh = msg_chain_tail(msg); msg_insert_here_in_chain(msg, hh, h); } /** Insert one or more message header to the chain. * * The function msg_insert_here_in_chain() appends message header to the * chain of headers after the given header. * * @param msg message * @param prev pointer to h_succ of previous fragment in the list * @param h header to be inserted. * * @return The pointer to the last header inserted. */ static void msg_insert_here_in_chain(msg_t *msg, msg_header_t **prev, msg_header_t *h) { if (h) { msg_header_t *last, *next; assert(h->sh_prev == NULL); assert(prev); assert(!msg_chain_errors(h)); for (last = h; last->sh_succ; last = last->sh_succ) ; last->sh_succ = next = *prev; *prev = h; h->sh_prev = prev; if (next) next->sh_prev = &last->sh_succ; else msg->m_tail = &last->sh_succ; assert(msg->m_chain && msg_chain_errors(msg->m_chain) == 0); } } /** * Remove a message from header chain. * * The function @c msg_chain_remove() removes a message header from the header * chain. * * @param msg pointer to the message * @param h pointer to the header in the list to be removed * * @return The pointer to the header just removed. */ su_inline msg_header_t *msg_chain_remove(msg_t *msg, msg_header_t *h) { if (h) { if (h->sh_prev) { assert(*h->sh_prev == h); assert(h->sh_succ == NULL || h->sh_succ->sh_prev == &h->sh_succ); *h->sh_prev = h->sh_succ; } if (h->sh_succ) h->sh_succ->sh_prev = h->sh_prev; else if (msg && h->sh_prev) msg->m_tail = h->sh_prev; h->sh_succ = NULL; h->sh_prev = NULL; if (msg) assert(msg_chain_errors(msg->m_chain) == 0); } return h; } #ifndef NDEBUG /**Check if header chain contains any loops. * * @return * Return 0 if no loop, -1 otherwise. */ static int msg_chain_loop(msg_header_t const *h) { msg_header_t const *h2; if (!h) return 0; for (h2 = h->sh_succ; h && h2 && h2->sh_succ; h = h->sh_succ) { if (h == h2 || h == h2->sh_succ) return 1; h2 = h2->sh_succ->sh_succ; if (h == h2) return 1; } return 0; } /** Check header chain consistency. * * @return * Return 0 if consistent, number of errors otherwise. */ static int msg_chain_errors(msg_header_t const *h) { if (msg_chain_loop(h)) return -1; for (; h; h = h->sh_succ) { if (h->sh_succ && h->sh_succ->sh_prev != &h->sh_succ) return -1; if (h->sh_prev && h != (*h->sh_prev)) return -1; } return 0; } #endif /* ====================================================================== */ /* Handling message structure - allocating, adding and removing headers */ /** Allocate a header structure * * The msg_header_alloc() function allocates a generic MO header structure * and returns a pointer to it. * * @param home memory home * @param hc header class * @param extra amount of extra memory to be allocated after header structure * * @return * A pointer to the newly created header object, or @c NULL upon an error. */ msg_header_t *msg_header_alloc(su_home_t *home, msg_hclass_t *hc, isize_t extra) { isize_t size = hc->hc_size; msg_header_t *h = su_alloc(home, size + extra); if (h) { memset(h, 0, size); h->sh_class = hc; } return h; } /**Add a (list of) header(s) to the header structure and fragment chain. * * The function @c msg_header_add() adds a header or list of headers into * the given place within the message structure. It also inserts the headers * into the the message fragment chain, if it exists. * * If the header is a prepend header, the new header is inserted before * existing headers of the same class. If the header is an append header, * the new header is inserted after existing headers of the same class. If * the header is a singleton, existing headers of the same class are * removed. If the header is a list header, the values in the new header are * added to the existing list. * * @param msg message owning the fragment chain * @param pub public message structure * @param hh place in message structure to which header is added * @param h list of header(s) to be added */ int msg_header_add(msg_t *msg, msg_pub_t *pub, msg_header_t **hh, msg_header_t *h) { msg_header_t **head, *old = NULL, *end; if (msg == NULL || h == NULL || h == MSG_HEADER_NONE || hh == NULL) return -1; if (pub == NULL) pub = msg->m_object; head = _msg_chain_head(msg); if (*head) { msg_header_t *sh, **prev; for (sh = h, prev = NULL; sh; sh = sh->sh_next) { sh->sh_succ = sh->sh_next; sh->sh_prev = prev; prev = &sh->sh_succ; } } switch (h->sh_class->hc_kind) { case msg_kind_single: case msg_kind_list: old = (*hh); break; case msg_kind_append: case msg_kind_apndlist: while (*hh) hh = &(*hh)->sh_next; break; case msg_kind_prepend: for (end = h; end->sh_next; end = end->sh_next) ; end->sh_next = *hh; } if (*head) { /* Insert into existing fragment chain */ msg_insert_chain(msg, pub, msg_is_prepend(h), head, h); /* Remove replaced fragment */ if (old) msg_chain_remove(msg, old); } /* Insert into header list */ *hh = h; return 0; } /**Prepend a (list of) header(s) to the header structure and fragment chain. * * The function @c msg_header_prepend() adds a header or list of headers into * the given place within the message structure. It also inserts the headers * into the the message fragment chain, if it exists. * * Unlike msg_header_add(), msg_header_prepend() always inserts header @a h * before other headers of the same class. If the header is a singleton, * existing headers of the same class are removed. If the header is a list * header, the values in the new header are prepended to the existing list. * * @param msg message owning the fragment chain * @param pub public message structure * @param hh place in message structure to which header is added * @param h list of header(s) to be added */ int msg_header_prepend(msg_t *msg, msg_pub_t *pub, msg_header_t **hh, msg_header_t *h) { msg_header_t **head, *old = NULL, *end; assert(msg && pub); if (msg == NULL || h == NULL || h == MSG_HEADER_NONE || hh == NULL) return -1; if (pub == NULL) pub = msg->m_object; head = _msg_chain_head(msg); if (*head) { msg_header_t *sh, **prev; for (sh = h, prev = NULL; sh; sh = sh->sh_next) { sh->sh_succ = sh->sh_next; sh->sh_prev = prev; prev = &sh->sh_succ; } } switch (h->sh_class->hc_kind) { case msg_kind_single: case msg_kind_list: old = (*hh); break; case msg_kind_append: case msg_kind_apndlist: case msg_kind_prepend: for (end = h; end->sh_next; end = end->sh_next) ; end->sh_next = *hh; break; } if (*head) { /* Insert into existing fragment chain */ msg_insert_chain(msg, pub, 1, head, h); /* Remove replaced fragment */ if (old) msg_chain_remove(msg, old); } /* Insert into header list */ *hh = h; return 0; } /** Find place to insert header of the class @a hc. */ msg_header_t ** msg_hclass_offset(msg_mclass_t const *mc, msg_pub_t const *mo, msg_hclass_t *hc) { int i; assert(mc && hc); if (mc == NULL || hc == NULL) return NULL; if (hc->hc_hash > 0) { unsigned j, N = mc->mc_hash_size; for (j = hc->hc_hash % N; mc->mc_hash[j].hr_class; j = (j + 1) % N) if (mc->mc_hash[j].hr_class == hc) { return (msg_header_t **)((char *)mo + mc->mc_hash[j].hr_offset); } } else /* Header has no name. */ for (i = 0; i <= 6; i++) if (hc->hc_hash == mc->mc_request[i].hr_class->hc_hash) return (msg_header_t **)((char *)mo + mc->mc_request[i].hr_offset); return NULL; } /** Append a parsed header object into the message structure */ su_inline void append_parsed(msg_t *msg, msg_pub_t *mo, msg_href_t const *hr, msg_header_t *h, int always_into_chain) { msg_header_t **hh; assert(msg); assert(hr->hr_offset); hh = (msg_header_t **)((char *)mo + hr->hr_offset); if (msg->m_chain || always_into_chain) msg_insert_here_in_chain(msg, msg_chain_tail(msg), h); if (*hh && msg_is_single(h)) { /* If there is multiple instances of single headers, put the extra headers into the list of erroneous headers */ msg_error_t **e; for (e = &mo->msg_error; *e; e = &(*e)->er_next) ; *e = (msg_error_t *)h; msg->m_extract_err |= hr->hr_flags; if (hr->hr_class->hc_critical) mo->msg_flags |= MSG_FLG_ERROR; return; } while (*hh) hh = &(*hh)->sh_next; *hh = h; } static int _msg_header_add_list_items(msg_t *msg, msg_header_t **hh, msg_header_t const *src); /**Duplicate and add a (list of) header(s) to the message. * * The function @c msg_header_add_dup() duplicates and adds a (list of) * header(s) into a message structure. * * When inserting headers into the fragment chain, a request (or status) is * inserted first and replaces the existing request (or status). Other * headers are inserted after the request or status. * * If the header is a singleton, existing headers with the same class are * removed. * * @param msg message owning the fragment chain * @param pub public message structure to which header is added * @param src list of header(s) to be added */ int msg_header_add_dup(msg_t *msg, msg_pub_t *pub, msg_header_t const *src) { msg_header_t *h, **hh = NULL; msg_hclass_t *hc = NULL; if (msg == NULL) return -1; if (src == NULL || src == MSG_HEADER_NONE) return 0; if (pub == NULL) pub = msg->m_object; for ( ;src; src = src->sh_next) { assert(src->sh_class); if (!src->sh_class) return -1; if (hc != src->sh_class) hh = msg_hclass_offset(msg->m_class, pub, hc = src->sh_class); if (hh == NULL) return -1; if (!*hh || hc->hc_kind != msg_kind_list) { int size = hc->hc_size; isize_t xtra = hc->hc_dxtra(src, size) - size; char *end; if (!(h = msg_header_alloc(msg_home(msg), hc, xtra))) return -1; /* error */ if (!(end = hc->hc_dup_one(h, src, (char *)h + size, xtra))) return -1; /* error */ if (hc->hc_update) msg_header_update_params(h->sh_common, 0); assert(end == (char *)h + size + xtra); if (msg_header_add(msg, pub, hh, h) < 0) return -1; hh = &h->sh_next; } else { if (_msg_header_add_list_items(msg, hh, src) < 0) break; } } if (src) return -1; return 0; } /**Duplicate a header as a given type and add the duplicate into message. * * The function @c msg_header_add_dup_as() duplicates a header as a instance * of the given header class. It adds the new copy into the message. * * When inserting headers into the fragment chain, a request (or status) is * inserted first and replaces the existing request (or status). Other * headers are inserted after the request or status. * * If the header is a singleton, existing headers with the same class are * removed. * * @param msg message owning the fragment chain * @param pub public message structure to which header is added * @param hc header class for header target type * @param src list of header(s) to be duplicated and added */ int msg_header_add_dup_as(msg_t *msg, msg_pub_t *pub, msg_hclass_t *hc, msg_header_t const *src) { if (msg == NULL || hc == NULL) return -1; if (src == NULL || src == MSG_HEADER_NONE) return 0; if (pub == NULL) pub = msg->m_object; return _msg_header_add_dup_as(msg, pub, hc, src); } /** Duplicate and add a (list of) header to a message */ static int _msg_header_add_dup_as(msg_t *msg, msg_pub_t *pub, msg_hclass_t *hc, msg_header_t const *src) { msg_header_t *h, **hh; hh = msg_hclass_offset(msg->m_class, pub, hc); if (hh == NULL) return -1; if (*hh && hc->hc_kind == msg_kind_list) return _msg_header_add_list_items(msg, hh, src); if (!(h = msg_header_dup_as(msg_home(msg), hc, src))) return -1; return msg_header_add(msg, pub, hh, h); } /* Add list items */ static int _msg_header_add_list_items(msg_t *msg, msg_header_t **hh, msg_header_t const *src) { msg_header_t *h = *hh; msg_param_t **s = msg_header_params(src->sh_common); if (!s || !*s) return 0; msg_fragment_clear(h->sh_common); /* Remove empty headers */ for (hh = &h->sh_next; *hh; *hh = (*hh)->sh_next) msg_chain_remove(msg, *hh); if (msg_header_join_items(msg_home(msg), h->sh_common, src->sh_common, 1) < 0) return -1; return 0; } /** Parse a string as a given header field and add result to the message. */ int msg_header_add_make(msg_t *msg, msg_pub_t *pub, msg_hclass_t *hc, char const *s) { msg_header_t *h, **hh; if (msg == NULL) return -1; if (pub == NULL) pub = msg->m_object; hh = msg_hclass_offset(msg->m_class, pub, hc); if (hh == NULL) return -1; if (!s) return 0; if (*hh && hc->hc_kind == msg_kind_list) { /* Add list items */ msg_header_t *h = *hh; msg_param_t **d; char *s0; skip_lws(&s); d = msg_header_params(h->sh_common); assert(d); msg_fragment_clear(h->sh_common); /* Remove empty headers */ for (hh = &h->sh_next; *hh; *hh = (*hh)->sh_next) msg_chain_remove(msg, *hh); s0 = su_strdup(msg_home(msg), s); if (!s0 || msg_commalist_d(msg_home(msg), &s0, d, msg_token_scan) < 0) return -1; return 0; } if (!(h = msg_header_make(msg_home(msg), hc, s))) return -1; return msg_header_add(msg, pub, hh, h); } /** Add formatting result to message. * * Parse result from printf-formatted params as a given header field and add * result to the message. * * @NEW_1_12_10 */ int msg_header_add_format(msg_t *msg, msg_pub_t *pub, msg_hclass_t *hc, char const *fmt, ...) { msg_header_t *h, **hh; va_list va; if (msg == NULL) return -1; if (pub == NULL) pub = msg->m_object; hh = msg_hclass_offset(msg->m_class, pub, hc); if (hh == NULL) return -1; if (!fmt) return 0; va_start(va, fmt); h = msg_header_vformat(msg_home(msg), hc, fmt, va); va_end(va); if (!h) return -1; return msg_header_add(msg, pub, hh, h); } /**Add string contents to message. * * Duplicate a string containing headers (or a message body, if the string * starts with linefeed), parse it and add resulting header objects to the * message object. * * @param msg message object * @param pub message header structure where heades are added (may be NULL) * @param str string to be copied and parsed (not modified, may be NULL) * * @retval 0 when succesful * @retval -1 upon an error */ int msg_header_add_str(msg_t *msg, msg_pub_t *pub, char const *str) { char *s; if (!msg) return -1; if (!str) return 0; s = su_strdup(msg_home(msg), str); if (s == NULL) return -1; return msg_header_parse_str(msg, pub, s); } /**Add string to message. * * Parse a string containing headers (or a message body, if the string * starts with linefeed) and add resulting header objects to the message * object. * * @param msg message object * @param pub message header structure where heades are added (may be NULL) * @param s string to be parsed (and modified) * * @retval 0 when succesful * @retval -1 upon an error * * @sa msg_header_add_str(), url_headers_as_string() * * @since New in @VERSION_1_12_4. */ int msg_header_parse_str(msg_t *msg, msg_pub_t *pub, char *s) { if (!msg) return -1; if (pub == NULL) pub = msg->m_object; if (s) { size_t ssiz = strlen(s), used = 0; ssize_t n = 1; while (ssiz > used) { if (IS_CRLF(s[used])) break; n = msg_extract_header(msg, pub, s + used, ssiz - used, 1); if (n <= 0) break; used += n; } if (n > 0 && ssiz > used) { used += CRLF_TEST(s + used); if (ssiz > used) msg_extract_payload(msg, pub, NULL, ssiz - used, s + used, ssiz - used, 1); } if (n <= 0) return -1; } return 0; } /** Insert a (list of) header(s) to the fragment chain. * * The function @c msg_header_insert() inserts header or list of headers * into a message structure. It also inserts them into the the message * fragment chain, if it exists. * * When inserting headers into the fragment chain, a request (or status) is * inserted first and replaces the existing request (or status). Other * headers are inserted after the request or status. * * If there can be only one header field of this type (hc_kind is * msg_kind_single), existing header objects with the same class are * removed. * * @param msg message object owning the fragment chain * @param pub public message structure to which header is added * @param h list of header(s) to be added */ int msg_header_insert(msg_t *msg, msg_pub_t *pub, msg_header_t *h) { msg_header_t **hh; assert(msg); if (msg == NULL || h == NULL || h == MSG_HEADER_NONE || h->sh_class == NULL) return -1; if (pub == NULL) pub = msg->m_object; hh = msg_hclass_offset(msg->m_class, pub, h->sh_class); return msg_header_add(msg, pub, hh, h); } /**Remove a header from the header structure and fragment chain. * * The function @c msg_header_remove() removes a header from a message * structure. It also removes the message from the message fragment chain * and clears the encoding of other headers objects that share same * encoding. * * @param msg message owning the fragment chain * @param pub public message structure to which header is added * @param h header to be removed */ int msg_header_remove(msg_t *msg, msg_pub_t *pub, msg_header_t *h) { msg_header_t **hh, **hh0; if (msg == NULL || h == NULL || h == MSG_HEADER_NONE || h->sh_class == NULL) return -1; if (pub == NULL) pub = msg->m_object; /* First, remove from public structure (msg_pub_t) */ hh0 = msg_hclass_offset(msg->m_class, pub, h->sh_class); if (!hh0) return -1; for (hh = hh0; *hh; hh = &(*hh)->sh_next) { if (*hh == h) { *hh = h->sh_next; break; } } if (h->sh_data) { void const *data = (char *)h->sh_data + h->sh_len; for (hh = hh0; *hh; hh = &(*hh)->sh_next) { if (data == (char *)(*hh)->sh_data + (*hh)->sh_len) { (*hh)->sh_data = NULL, (*hh)->sh_len = 0; } } } msg_chain_remove(msg, h); return 0; } /**Remove a header list from the header structure and fragment chain. * * The function @c msg_header_remove_all() removes a list of headers from a * message structure. It also removes the message from the message fragment * chain and clears the encoding of other headers objects that share same * encoding. * * @param msg message owning the fragment chain * @param pub public message structure to which header is added * @param h header list to be removed */ int msg_header_remove_all(msg_t *msg, msg_pub_t *pub, msg_header_t *h) { msg_header_t **hh, **hh0; void const *data; if (msg == NULL || h == NULL || h == MSG_HEADER_NONE || h->sh_class == NULL) return -1; if (pub == NULL) pub = msg->m_object; hh0 = msg_hclass_offset(msg->m_class, pub, h->sh_class); if (!hh0) return -1; data = (char *)h->sh_data + h->sh_len; /* First, remove from public structure (msg_pub_t) */ for (hh = hh0; *hh; hh = &(*hh)->sh_next) { if (*hh == h) { break; } if (data && data == (char *)(*hh)->sh_data + (*hh)->sh_len) { h->sh_data = NULL, h->sh_len = 0; (*hh)->sh_data = NULL, (*hh)->sh_len = 0; } } /* Remove from header chain */ while (h) { h->sh_data = NULL, h->sh_len = 0; msg_chain_remove(msg, h); h = h->sh_next; } *hh = NULL; return 0; } /** Replace a header item with a (list of) header(s). * * The function @c msg_header_replace() removes a header structure from * message and replaces it with a new one or a list of headers. It inserts * the new headers into the the message fragment chain, if it exists. * * @param msg message object owning the fragment chain * @param pub public message structure to which header is added * @param replaced old header to be removed (may be NULL) * @param h list of header(s) to be added (may be NULL) */ int msg_header_replace(msg_t *msg, msg_pub_t *pub, msg_header_t *replaced, msg_header_t *h) { msg_header_t *h0, *last, **hh, **hh0; if (msg == NULL) return -1; if (h == NULL || h == MSG_HEADER_NONE || h->sh_class == NULL) return msg_header_remove(msg, pub, replaced); if (pub == NULL) pub = msg->m_object; hh = hh0 = msg_hclass_offset(msg->m_class, pub, h->sh_class); if (hh == NULL) return -1; if (replaced == NULL) return msg_header_add(msg, pub, hh, h); assert(h->sh_prev == NULL); /* Must not be in existing chain! */ for (last = h; last->sh_next; last = last->sh_next) { if ((last->sh_succ = last->sh_next)) last->sh_next->sh_prev = &last->sh_succ; } for (h0 = *hh; h0; hh = &h0->sh_next, h0 = *hh) { if (replaced == h0) break; } if (h0 == NULL) return -1; *hh = h; /* Replace in list */ last->sh_next = replaced->sh_next; if (replaced->sh_prev) { *replaced->sh_prev = h; h->sh_prev = replaced->sh_prev; if ((last->sh_succ = replaced->sh_succ)) last->sh_succ->sh_prev = &last->sh_succ; if (msg->m_tail == &replaced->sh_succ) msg->m_tail = &last->sh_succ; } assert(msg->m_tail != &replaced->sh_succ); replaced->sh_next = NULL; replaced->sh_prev = NULL; replaced->sh_succ = NULL; if (replaced->sh_data) { /* Remove cached encoding if it is shared with more than one header fragments */ int cleared = 0; void const *data = (char *)replaced->sh_data + replaced->sh_len; for (hh = hh0; *hh; hh = &(*hh)->sh_next) { if (data == (char *)(*hh)->sh_data + (*hh)->sh_len) { (*hh)->sh_data = NULL, (*hh)->sh_len = 0, cleared = 1; } } if (cleared) replaced->sh_data = NULL, replaced->sh_len = 0; } return 0; } /** Free a header structure */ void msg_header_free(su_home_t *home, msg_header_t *h) { su_free(home, h); } /** Free a (list of) header structures */ void msg_header_free_all(su_home_t *home, msg_header_t *h) { msg_header_t *h_next; while (h) { h_next = h->sh_next; su_free(home, h); h = h_next; } } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/msg_parser_util.c000066400000000000000000001355401223300710500237130ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@ingroup msg_parser * @CFILE msg_parser_util.c * * Text-message parser helper functions. * * @author Pekka Pessi * * @date Created: Tue Aug 28 16:26:34 2001 ppessi * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include "msg_internal.h" #include "sofia-sip/msg_parser.h" #include "sofia-sip/bnf.h" #include "sofia-sip/url.h" static issize_t msg_comma_scanner(char *start); /** * Parse first line. * * Splits the first line from a message into three whitespace-separated * parts. */ int msg_firstline_d(char *s, char **return_part2, char **return_part3) { char *s1 = s, *s2, *s3; size_t n; /* Split line into three segments separated by whitespace */ if (s1[n = span_non_ws(s1)]) { s1[n] = '\0'; s2 = s1 + n + 1; while (IS_WS(*s2)) s2++; } else { /* Hopeless - no WS in first line */ return -1; } n = span_non_ws(s2); if (s2[n]) { s2[n++] = '\0'; while (IS_WS(s2[n])) n++; } s3 = s2 + n; *return_part2 = s2; *return_part3 = s3; return 0; } /**Parse a token. * * Parses a token from string pointed by @a *ss. It stores the token value * in @a return_token, and updates the @a ss to the end of token and * possible whitespace. */ issize_t msg_token_d(char **ss, char const **return_token) { char *s = *ss; size_t n = span_token(s); if (n) { for (; IS_LWS(s[n]); n++) s[n] = '\0'; *return_token = s; *ss = s + n; return n; } else return -1; } /** Parse a 32-bit unsigned int. * * The function msg_uint32_d() parses a 32-bit unsigned integer in string * pointed by @a *ss. It stores the value in @a return_token and updates the * @a ss to the end of integer and possible whitespace. * * @retval length of parsed integer, or -1 upon an error. */ issize_t msg_uint32_d(char **ss, uint32_t *return_value) { char const *s = *ss, *s0 = s; uint32_t value; unsigned digit; if (!IS_DIGIT(*s)) return -1; for (value = 0; IS_DIGIT(*s); s++) { digit = *s - '0'; if (value > 429496729U) return -1; else if (value == 429496729U && digit > 5) return -1; value = 10 * value + digit; } if (*s) { if (!IS_LWS(*s)) return (issize_t)-1; skip_lws(&s); } *ss = (char *)s; *return_value = value; return s - s0; } /** Parse any list. * * Parses a list of items, separated by @a sep. The parsed string is passed * in @a *ss, which is updated to point to the first non-linear-whitespace * character after the list. The function modifies the string as it parses * it. * * The parsed items are appended to the list @a *append_list. If there the * list in @a *append_list is NULL, allocate a new list and return it in @a * *append_list. Empty list items are ignored, and are not appended to the * list. * * The function @b must be passed a scanning function @a scanner. The * scanning function scans for a legitimate list item, for example, a token. * It should also compact the list item, for instance, if the item consists * of @c name=value parameter definitions it should remove whitespace around * "=" sign. The scanning function returns the length of the scanned item, * including any linear whitespace after it. * * @param[in] home memory home for allocating list pointers * @param[in,out] ss pointer to pointer to string to be parsed * @param[in,out] append_list pointer to list * where parsed list items are appended * @param[in] sep separator character * @param[in] scanner pointer to function for scanning a single item * * @retval 0 if successful. * @retval -1 upon an error. */ issize_t msg_any_list_d(su_home_t *home, char **ss, msg_param_t **append_list, issize_t (*scanner)(char *s), int sep) { char const *stack[MSG_N_PARAMS]; char const **list = stack, **re_list; size_t N = MSG_N_PARAMS, n = 0; issize_t tlen; char *s = *ss; char const **start; if (!scanner) return -1; if (*append_list) { list = *append_list; while (list[n]) n++; N = MSG_PARAMS_NUM(n + 1); } start = &list[n]; skip_lws(&s); while (*s) { tlen = scanner(s); if (tlen < 0 || (s[tlen] && s[tlen] != sep && s[tlen] != ',')) goto error; if (tlen > 0) { if (n + 1 == N) { /* Reallocate list? */ N = MSG_PARAMS_NUM(N + 1); if (list == stack || list == *append_list) { re_list = su_alloc(home, N * sizeof(*list)); if (re_list) memcpy(re_list, list, n * sizeof(*list)); } else re_list = su_realloc(home, list, N * sizeof(*list)); if (!re_list) goto error; list = re_list; } list[n++] = s; s += tlen; } if (*s == sep) { *s++ = '\0'; skip_lws(&s); } else if (*s) break; } *ss = s; if (n == 0) { *append_list = NULL; return 0; } if (list == stack) { size_t size = sizeof(*list) * MSG_PARAMS_NUM(n + 1); list = su_alloc(home, size); if (!list) return -1; memcpy((void *)list, stack, n * sizeof(*list)); } list[n] = NULL; *append_list = list; return 0; error: *start = NULL; if (list != stack && list != *append_list) su_free(home, list); return -1; } /** Scan an attribute (name [= value]) pair. * * The attribute consists of name (a token) and optional value, separated by * equal sign. The value can be a token or quoted string. * * This function compacts the scanned value. It removes the * whitespace around equal sign "=" by moving the equal sign character and * value towards name. * * If there is whitespace within the scanned value or after it, * NUL-terminates the scanned attribute. * * @retval > 0 number of characters scanned, * including the whitespace within the value * @retval -1 upon an error */ issize_t msg_attribute_value_scanner(char *s) { char *p = s; size_t tlen; skip_token(&s); if (s == p) /* invalid parameter name */ return -1; tlen = s - p; if (IS_LWS(*s)) { *s++ = '\0'; skip_lws(&s); } if (*s == '=') { char *v; s++; skip_lws(&s); /* get value */ if (*s == '"') { size_t qlen = span_quoted(s); if (!qlen) return -1; v = s; s += qlen; } else { v = s; skip_param(&s); if (s == v) return -1; } if (p + tlen + 1 != v) { memmove(p + tlen + 1, v, s - v); p[tlen] = '='; p[tlen + 1 + (s - v)] = '\0'; } } if (IS_LWS(*s)) { *s++ = '\0'; skip_lws(&s); } return s - p; } /**Parse an attribute-value list. * * Parses an attribute-value list, which has syntax as follows: * @code * av-list = (av-pair *(";" av-pair) * av-pair = token ["=" ( value / quoted-string) ] ; optional value * @endcode * * @param[in] home pointer to a memory home * @param[in,out] ss pointer to string at the start of parameter list * @param[in,out] append_list pointer to list * where parsed list items are appended * * @retval >= 0 if successful * @retval -1 upon an error */ issize_t msg_avlist_d(su_home_t *home, char **ss, msg_param_t const **append_list) { char const *stack[MSG_N_PARAMS]; char const **params; size_t n = 0, N; char *s = *ss; if (!*s) return -1; if (*append_list) { params = (char const **)*append_list; for (n = 0; params[n]; n++) ; N = MSG_PARAMS_NUM(n + 1); } else { params = stack; N = MSG_PARAMS_NUM(1); } for (;;) { char *p; size_t tlen; /* XXX - we should handle also quoted parameters */ skip_lws(&s); p = s; skip_token(&s); tlen = s - p; if (!tlen) /* invalid parameter name */ goto error; if (IS_LWS(*s)) { *s++ = '\0'; skip_lws(&s); } if (*s == '=') { char *v; s++; skip_lws(&s); /* get value */ if (*s == '"') { size_t qlen = span_quoted(s); if (!qlen) goto error; v = s; s += qlen; } else { v = s; skip_param(&s); if (s == v) goto error; } if (p + tlen + 1 != v) { p = memmove(v - tlen - 1, p, tlen); p[tlen] = '='; } } if (IS_LWS(*s)) { *s++ = '\0'; skip_lws(&s); } if (n == N) { /* Reallocate params */ char const **nparams = su_realloc(home, (void*)(params != stack ? params : NULL), (N = MSG_PARAMS_NUM(N + 1)) * sizeof(*params)); if (!nparams) { goto error; } if (params == stack) memcpy(nparams, stack, n * sizeof(*params)); params = nparams; } params[n++] = p; if (*s != ';') break; *s++ = '\0'; } *ss = s; if (params == stack) { size_t size = sizeof(*params) * MSG_PARAMS_NUM(n + 1); params = su_alloc(home, size); if (!params) return -1; memcpy((void *)params, stack, n * sizeof(*params)); } else if (n == N) { /* Reallocate params */ char const **nparams = su_realloc(home, (void*)(params != stack ? params : NULL), (N = MSG_PARAMS_NUM(N + 1)) * sizeof(*params)); if (!nparams) { goto error; } if (params == stack) memcpy(nparams, stack, n * sizeof(*params)); params = nparams; } params[n] = NULL; *append_list = params; return 0; error: if (params != stack) su_free(home, params); return -1; } /**Parse a semicolon-separated parameter list starting with semicolon. * * Parse a parameter list, which has syntax as follows: * @code * *(";" token [ "=" (token | quoted-string)]). * @endcode * * @param[in] home pointer to a memory home * @param[in,out] ss pointer to string at the start of parameter list * @param[in,out] append_list pointer to list * where parsed list items are appended * * @retval >= 0 if successful * @retval -1 upon an error * * @sa msg_avlist_d() */ issize_t msg_params_d(su_home_t *home, char **ss, msg_param_t const **append_list) { if (**ss == ';') { *(*ss)++ = '\0'; *append_list = NULL; return msg_avlist_d(home, ss, append_list); } if (IS_LWS(**ss)) { *(*ss)++ = '\0'; skip_lws(ss); } return 0; } /** Encode a list of parameters */ isize_t msg_params_e(char b[], isize_t bsiz, msg_param_t const pparams[]) { int i; char *end = b + bsiz, *b0 = b; msg_param_t p; if (pparams) for (i = 0; (p = pparams[i]); i++) { if (p[0]) { MSG_CHAR_E(b, end, ';'); MSG_STRING_E(b, end, p); } } return b - b0; } /** Duplicate a parameter list */ char *msg_params_dup(msg_param_t const **d, msg_param_t const s[], char *b, isize_t xtra) { char *end = b + xtra; char **pp; int i; isize_t n; n = msg_params_count(s); if (n == 0) { *d = NULL; return b; } MSG_STRUCT_ALIGN(b); pp = (char **)b; b += sizeof(*pp) * MSG_PARAMS_NUM(n + 1); for (i = 0; s[i]; i++) { MSG_STRING_DUP(b, pp[i], s[i]); } pp[i] = NULL; assert(b <= end); (void)end; *d = (msg_param_t const *)pp; return b; } /** Parse a comma-separated list. * * Parses a comma-separated list. The parsed string is passed in @a *ss, * which is updated to point to the first non-linear-whitespace character * after the list. The function modifies the string as it parses it. * * A pointer to the resulting list is returned in @a *retval. If there * already is a list in @a *retval, new items are appended. Empty list items * are ignored, and are not included in the list. * * The function can be passed an optional scanning function. The scanning * function scans for a legitimate list item, for example, a token. It also * compacts the list item, for instance, if the item consists of @c * name=value parameter definitions. The scanning function returns the * length of the scanned item, including any linear whitespace after it. * * By default, the scanning function accepts tokens, quoted strings or * separators (except comma, of course). * * @param[in] home memory home for allocating list pointers * @param[in,out] ss pointer to pointer to string to be parsed * @param[in,out] append_list pointer to list * where parsed list items are appended * @param[in] scanner pointer to function scanning a single item * (optional) * * @retval 0 if successful. * @retval -1 upon an error. */ issize_t msg_commalist_d(su_home_t *home, char **ss, msg_param_t **append_list, issize_t (*scanner)(char *s)) { scanner = scanner ? scanner : msg_comma_scanner; return msg_any_list_d(home, ss, append_list, scanner, ','); } /** Token scanner for msg_commalist_d() accepting also empty entries. */ issize_t msg_token_scan(char *start) { char *s = start; skip_token(&s); if (IS_LWS(*s)) *s++ = '\0'; skip_lws(&s); return s - start; } /** Scan and compact a comma-separated item */ static issize_t msg_comma_scanner(char *start) { size_t tlen; char *s, *p; s = p = start; if (s[0] == ',') return 0; for (;;) { /* Grab next section - token, quoted string, or separator character */ char c = *s; if (IS_TOKEN(c)) tlen = span_token(s); else if (c == '"') tlen = span_quoted(s); else /* if (IS_SEPARATOR(c)) */ tlen = 1; if (tlen == 0) return -1; if (p != s) memmove(p, s, tlen); /* Move section to end of paramexter */ p += tlen; s += tlen; skip_lws(&s); /* Skip possible LWS */ if (*s == '\0' || *s == ',') { /* Test for possible end */ if (p != s) *p = '\0'; return s - start; } if (IS_TOKEN(c) && IS_TOKEN(*s)) *p++ = ' '; /* Two tokens must be separated by LWS */ } } /** Parse a comment. * * Parses a multilevel comment. The comment assigned to return-value * parameter @a return_comment is NUL-terminated. The string at return-value * parameter @a ss is updated to point to first non-linear-whitespace * character after the comment. */ issize_t msg_comment_d(char **ss, char const **return_comment) { /* skip comment */ int level = 1; char *s = *ss; assert(s[0] == '('); if (*s != '(') return -1; *s++ = '\0'; if (return_comment) *return_comment = s; while (level) switch (*s++) { case '(': level++; break; case ')': level--; break; case '\0': /* ERROR */ return -1; } assert(s[-1] == ')'); s[-1] = '\0'; skip_lws(&s); *ss = s; return 0; } /** Parse a quoted string */ issize_t msg_quoted_d(char **ss, char **return_quoted) { char *s= *ss, *s0 = s; ssize_t n = span_quoted(s); if (n <= 0) return -1; *return_quoted = s; s += n; if (IS_LWS(*s)) { *s++ = '\0'; skip_lws(&s); /* skip linear whitespace */ } *ss = s; return s - s0; } #if 0 /** Calculate length of string when quoted. */ int msg_quoted_len(char const *u) { int rv; if (!u) return 0; rv = span_token_lws(u); if (u[rv]) { /* We need to quote string */ int n; int extra = 2; /* quote chars */ /* Find all characters to quote */ for (n = strcspn(u + rv, "\\\""); u[rv + n]; rv += n) extra++; rv += extra; } return rv; } #endif /**Parse @e host[":"port] pair. * * Parses a @e host[":"port] pair. The caller passes function a pointer to a * string via @a ss, and pointers to which parsed host and port are assigned * via @a hhost and @a pport, respectively. The value-result parameter @a * *pport must be initialized to default value (e.g., NULL). * * @param ss pointer to pointer to string to be parsed * @param return_host value-result parameter for @e host * @param return_port value-result parameter for @e port * @return * Returns zero when successful, and a negative value upon an error. The * parsed values for host and port are assigned via @a return_host and @a * return_port, respectively. The function also updates the pointer @a *ss, * so if call is successful, the @a *ss points to first * non-linear-whitespace character after @e host[":"port] pair. * * @note * If there is no whitespace after @e port, the value in @a *pport may not be * NUL-terminated. The calling function @b must NUL terminate the value by * setting the @a **ss to NUL after first examining its value. */ int msg_hostport_d(char **ss, char const **return_host, char const **return_port) { char *host, *s = *ss; char *port = NULL; /* Host name */ host = s; if (s[0] != '[') { skip_token(&s); if (host == s) return -1; } else { /* IPv6 */ size_t n = strspn(++s, HEX ":."); if (s[n] != ']') return -1; s += n + 1; } if (IS_LWS(*s)) { *s++ = '\0'; skip_lws(&s); } if (s[0] == ':') { unsigned long nport; *s++ = '\0'; skip_lws(&s); if (!IS_DIGIT(*s)) return -1; port = s; nport = strtoul(s, &s, 10); if (nport > 65535) return -1; if (IS_LWS(*s)) { *s++ = '\0'; skip_lws(&s); } } *return_host = host; *return_port = port; *ss = s; return 0; } /** Clear encoded data from header fields. * * Clear encoded or cached unencoded headers from header fields. * * @param h pointer to header structure */ void msg_fragment_clear_chain(msg_header_t *h) { char const *data; msg_header_t *prev, *succ; if (h == NULL || h->sh_data == NULL) return; data = (char *)h->sh_data + h->sh_len; /* Find first field of header */ for (prev = (msg_header_t *)h->sh_prev; prev && (void *)prev->sh_next == (void *)h;) { if (!prev->sh_data) break; if ((char *)prev->sh_data + prev->sh_len != data) break; h = prev, prev = (msg_header_t *)h->sh_prev; } for (h = h; h; h = succ) { succ = h->sh_succ; h->sh_data = NULL, h->sh_len = 0; if (!data || !succ || h->sh_next != succ || succ->sh_data != (void *)data || succ->sh_len) return; } } /** Find a header parameter. * * Searches for given parameter @a name from the header. If parameter is * found, it returns a non-NULL pointer to the parameter value. If there is * no value for the name (in form "name" or "name=value"), the returned pointer * points to a NUL character. * * @param h pointer to header structure * @param name parameter name (with or without "=" sign) * * @return * A pointer to parameter value, or NULL if parameter was not found. */ char const *msg_header_find_param(msg_common_t const *h, char const *name) { if (h && h->h_class->hc_params) { msg_param_t const **params = (msg_param_t const **) ((char *)h + h->h_class->hc_params); return msg_params_find(*params, name); } return NULL; } /**Modify a parameter value or list item in a header. * * A header parameter @a param can be just a C-string (@a is_item > 0), or * it can have internal format name [ "=" value]. In the latter case, * the value part following = is ignored when replacing or removing the * parameter. * * @param home memory home used to re-allocate parameter list in header * @param h pointer to a header * @param param parameter to be replaced or added * @param is_item how to interpret @a param: * - 1 case-sensitive, no structure * - 0 case-insensitive, name [ "=" value ] * @param remove_replace_add what operation to do: * - -1 remove * - 0 replace * - 1 add * * @retval 1 if parameter was replaced or removed successfully * @retval 0 if parameter was added successfully, * or there was nothing to remove * @retval -1 upon an error */ static int msg_header_param_modify(su_home_t *home, msg_common_t *h, char const *param, int is_item, int remove_replace_add) { msg_param_t *params, **pointer_to_params; size_t plen, n; if (!h || !h->h_class->hc_params || !param) return -1; pointer_to_params = (msg_param_t **)((char *)h + h->h_class->hc_params); params = *pointer_to_params; plen = is_item > 0 ? strlen(param) : strcspn(param, "="); n = 0; if (params) { /* Existing list, try to replace or remove */ for (; params[n]; n++) { char const *maybe = params[n]; if (remove_replace_add > 0) continue; if (is_item > 0) { if (strcmp(maybe, param) == 0) { if (remove_replace_add == 0) return 1; } } else { if (su_casenmatch(maybe, param, plen) && (maybe[plen] == '=' || maybe[plen] == 0)) break; } } } /* Not found? */ if (!params || !params[n]) { if (remove_replace_add < 0) return 0; /* Nothing to remove */ else remove_replace_add = 1; /* Add instead of replace */ } if (remove_replace_add < 0) { /* Remove */ for (; params[n]; n++) params[n] = params[n + 1]; } else { if (remove_replace_add > 0) { /* Add */ size_t m_before = MSG_PARAMS_NUM(n + 1); size_t m_after = MSG_PARAMS_NUM(n + 2); assert(!params || !params[n]); if (m_before != m_after || !params) { msg_param_t *p; /* XXX - we should know when to do realloc */ p = su_alloc(home, m_after * sizeof(*p)); if (!p) return -1; if (n > 0) memcpy(p, params, n * sizeof(p[0])); *pointer_to_params = params = p; } params[n + 1] = NULL; } params[n] = param; /* Add .. or replace */ } if (h->h_data) msg_fragment_clear_chain((msg_header_t *)h); if (h->h_class->hc_update) { /* Update shortcuts */ size_t namelen; char const *name, *value; name = param; namelen = strcspn(name, "="); if (remove_replace_add < 0) value = NULL; else value = param + namelen + (name[namelen] == '='); h->h_class->hc_update(h, name, namelen, value); } return remove_replace_add <= 0; /* 0 when added, 1 otherwise */ } /** Add a parameter to a header. * * You should use this function only when the header accepts multiple * parameters (or list items) with the same name. If that is not the case, * you should use msg_header_replace_param(). * * @note This function @b does @b not duplicate @p param. The caller should * have allocated the @a param from the memory home associated with header * @a h. * * The possible shortcuts to parameter values are updated. For example, the * "received" parameter in @Via header has shortcut in structure #sip_via_t, * the @ref sip_via_s::v_received "v_received" field. The shortcut is usully * a pointer to the parameter value. If the parameter was * "received=127.0.0.1" the @ref sip_via_s::v_received "v_received" field * would be a pointer to "127.0.0.1". If the parameter was "received=" or * "received", the shortcut would be a pointer to an empty string, "". * * @param home memory home used to re-allocate parameter list in header * @param h pointer to a header * @param param parameter to be replaced or added * * @retval 0 if parameter was added * @retval -1 upon an error * * @sa msg_header_replace_param(), msg_header_remove_param(), * msg_header_update_params(), * #msg_common_t, #msg_header_t, * #msg_hclass_t, msg_hclass_t::hc_params, msg_hclass_t::hc_update */ int msg_header_add_param(su_home_t *home, msg_common_t *h, char const *param) { return msg_header_param_modify(home, h, param, 0 /* case-insensitive name=value */, 1 /* add */); } /** Replace or add a parameter to a header. * * A header parameter @a param is a string of format name "=" value * or just name. The value part following "=" is ignored when selecting a * parameter to replace. * * @note This function @b does @b not duplicate @p param. The caller should * have allocated the @a param from the memory home associated with header * @a h. * * The possible shortcuts to parameter values are updated. For example, the * "received" parameter in @Via header has shortcut in structure #sip_via_t, * the @ref sip_via_s::v_received "v_received" field. * * @param home memory home used to re-allocate parameter list in header * @param h pointer to a header * @param param parameter to be replaced or added * * @retval 0 if parameter was added * @retval 1 if parameter was replaced * @retval -1 upon an error * * @sa msg_header_add_param(), msg_header_remove_param(), * msg_header_update_params(), * #msg_common_t, #msg_header_t, * #msg_hclass_t, msg_hclass_t::hc_params, msg_hclass_t::hc_update */ int msg_header_replace_param(su_home_t *home, msg_common_t *h, char const *param) { return msg_header_param_modify(home, h, param, 0 /* case-insensitive name=value */, 0 /* replace */); } /** Remove a parameter from header. * * The parameter name is given as token optionally followed by "=" sign and * value. The "=" and value after it are ignored when selecting a parameter * to remove. * * The possible shortcuts to parameter values are updated. For example, the * "received" parameter in @Via header has shortcut in structure #sip_via_t, * the @ref sip_via_s::v_received "v_received" field. The shortcut to * removed parameter would be set to NULL. * * @param h pointer to a header * @param name name of parameter to be removed * * @retval 1 if a parameter was removed * @retval 0 if no parameter was not removed * @retval -1 upon an error * * @sa msg_header_add_param(), msg_header_replace_param(), * msg_header_update_params(), * #msg_common_t, #msg_header_t, * #msg_hclass_t, msg_hclass_t::hc_params, msg_hclass_t::hc_update */ int msg_header_remove_param(msg_common_t *h, char const *name) { return msg_header_param_modify(NULL, h, name, 0 /* case-insensitive name=value */, -1 /* remove */); } /** Update shortcuts to parameter values. * * Update the shortcuts to parameter values in parameter list. For example, * the "received" parameter in @Via header has shortcut in structure * #sip_via_t, the @ref sip_via_s::v_received "v_received" field. The * shortcut is usully a pointer to the parameter value. If the parameter was * "received=127.0.0.1" the @ref sip_via_s::v_received "v_received" field * would be a pointer to "127.0.0.1". If the parameter was "received=" or * "received", the shortcut would be a pointer to an empty string, "". * * @retval 0 when successful * @retval -1 upon an error * * @sa msg_header_add_param(), msg_header_replace_param(), * msg_header_update_params(), * #msg_common_t, #msg_header_t, * #msg_hclass_t, msg_hclass_t::hc_params, msg_hclass_t::hc_update */ int msg_header_update_params(msg_common_t *h, int clear) { msg_hclass_t *hc; unsigned char offset; msg_update_f *update; int retval; msg_param_t const *params; size_t n; char const *p, *v; if (h == NULL) return errno = EFAULT, -1; hc = h->h_class; offset = hc->hc_params; update = hc->hc_update; if (offset == 0 || update == NULL) return 0; if (clear) update(h, NULL, 0, NULL); params = *(msg_param_t **)((char *)h + offset); if (params == NULL) return 0; retval = 0; for (p = *params; p; p = *++params) { n = strcspn(p, "="); v = p + n + (p[n] == '='); if (update(h, p, n, v) < 0) retval = -1; } return retval; } /** Find a header item. * * Searches for given item @a name from the header. If item is found, the * function returns a non-NULL pointer to the item. * * @param h pointer to header structure * @param item item * * @return * A pointer to item, or NULL if it was not found. * * @since New in @VERSION_1_12_4 * * @sa msg_header_replace_item(), msg_header_remove_item(), * @Allow, @AllowEvents */ char const *msg_header_find_item(msg_common_t const *h, char const *item) { if (h && h->h_class->hc_params) { char const * const * items = *(char const * const * const *) ((char *)h + h->h_class->hc_params); if (items) for (; *items; items++) { if (strcmp(item, *items) == 0) { return *items; } } } return NULL; } /**Add an item to a header. * * This function treats a #msg_header_t as set of C strings. The @a item is * a C string. If no identical string is found from the list, it is added to * the list. * * The shortcuts, if any, to item values are updated accordingly. * * @param home memory home used to re-allocate list in header * @param h pointer to a header * @param item item to be removed * * @retval 0 if item was added * @retval 1 if item was replaced * @retval -1 upon an error * * @since New in @VERSION_1_12_4. * * @sa msg_header_remove_item(), @Allow, @AllowEvents, * msg_header_replace_param(), msg_header_remove_param(), * #msg_common_t, #msg_header_t, #msg_list_t * #msg_hclass_t, msg_hclass_t::hc_params */ int msg_header_replace_item(su_home_t *home, msg_common_t *h, char const *item) { return msg_header_param_modify(home, h, item, 1 /* string item */, 0 /* replace */); } /**Remove an item from a header. * * This function treats a #msg_header_t as set of C strings. The @a item is a * C string. If identical string is found from the list, it is removed. * * The shortcuts, if any, to item values are updated accordingly. * * @param h pointer to a header * @param name item to be removed * * @retval 0 if item was added * @retval 1 if item was replaced * @retval -1 upon an error * * @since New in @VERSION_1_12_4. * * @sa msg_header_replace_item(), @Allow, @AllowEvents, * msg_header_replace_param(), msg_header_remove_param(), * #msg_common_t, #msg_header_t, #msg_list_t * #msg_hclass_t, msg_hclass_t::hc_params */ int msg_header_remove_item(msg_common_t *h, char const *name) { return msg_header_param_modify(NULL, h, name, 1 /* item */, -1 /* remove */); } /** Find a parameter from a parameter list. * * Searches for given parameter @a token from the parameter list. If * parameter is found, it returns a non-NULL pointer to the parameter value. * If there is no value for the parameter (the parameter is of form "name" * or "name="), the returned pointer points to a NUL character. * * @param params list (or vector) of parameters * @param token parameter name (with or without "=" sign) * * @return * A pointer to parameter value, or NULL if parameter was not found. */ msg_param_t msg_params_find(msg_param_t const params[], msg_param_t token) { if (params && token) { size_t i, n = strcspn(token, "="); assert(n > 0); for (i = 0; params[i]; i++) { msg_param_t param = params[i]; if (su_casenmatch(param, token, n)) { if (param[n] == '=') return param + n + 1; else if (param[n] == 0) return param + n; } } } return NULL; } /** Find a slot for parameter from a parameter list. * * Searches for given parameter @a token from the parameter list. If * parameter is found, it returns a non-NULL pointer to the item containing * the parameter. * * @param params list (or vector) of parameters * @param token parameter name (with or without "=" sign) * * @return * A pointer to parameter slot, or NULL if parameter was not found. */ msg_param_t *msg_params_find_slot(msg_param_t params[], msg_param_t token) { if (params && token) { int i; size_t n = strlen(token); assert(n > 0); for (i = 0; params[i]; i++) { msg_param_t param = params[i]; if (su_casenmatch(param, token, n)) { if (param[n] == '=') return params + i; else if (param[n] == 0 || token[n - 1] == '=') return params + i; } } } return NULL; } /** Replace or add a parameter from a list. * * A non-NULL parameter list must have been created by msg_params_d() * or by msg_params_dup(). * * @note This function does not duplicate @p param. * * @param home memory home * @param inout_params pointer to pointer to parameter list * @param param parameter to be replaced or added * * @retval 0 if parameter was added * @retval 1 if parameter was replaced * @retval -1 upon an error */ int msg_params_replace(su_home_t *home, msg_param_t **inout_params, msg_param_t param) { msg_param_t *params; size_t i, n; assert(inout_params); if (param == NULL || param[0] == '=' || param[0] == '\0') return -1; params = *inout_params; n = strcspn(param, "="); if (params) { /* Existing list, try to replace or remove */ for (i = 0; params[i]; i++) { msg_param_t maybe = params[i]; if (su_casenmatch(maybe, param, n)) { if (maybe[n] == '=' || maybe[n] == 0) { params[i] = param; return 1; } } } } /* Not found on list */ return msg_params_add(home, inout_params, param); } /** Remove a parameter from a list. * * @retval 1 if parameter was removed * @retval 0 if parameter was not found * @retval -1 upon an error */ int msg_params_remove(msg_param_t *params, msg_param_t param) { size_t i, n; if (!params || !param || !param[0]) return -1; n = strcspn(param, "="); assert(n > 0); for (i = 0; params[i]; i++) { msg_param_t maybe = params[i]; if (su_casenmatch(maybe, param, n)) { if (maybe[n] == '=' || maybe[n] == 0) { /* Remove */ do { params[i] = params[i + 1]; } while (params[i++]); return 1; } } } return 0; } /** Calculate number of parameters in a parameter list */ size_t msg_params_length(char const * const * params) { size_t len; if (!params) return 0; for (len = 0; params[len]; len++) ; return len; } /** * Add a parameter to a list. * * Add a parameter to the list; the list must have been created by @c * msg_params_d() or by @c msg_params_dup() (or it may contain only @c * NULL). * * @note This function does not duplicate @p param. * * @param home memory home * @param inout_params pointer to pointer to parameter list * @param param parameter to be added * * @retval 0 if parameter was added * @retval -1 upon an error */ int msg_params_add(su_home_t *home, msg_param_t **inout_params, msg_param_t param) { size_t n, m_before, m_after; msg_param_t *p = *inout_params; if (param == NULL) return -1; /* Count number of parameters */ for (n = 0; p && p[n]; n++) ; m_before = MSG_PARAMS_NUM(n + 1); m_after = MSG_PARAMS_NUM(n + 2); if (m_before != m_after || !p) { p = su_alloc(home, m_after * sizeof(*p)); assert(p); if (!p) return -1; if (n) memcpy(p, *inout_params, n * sizeof(*p)); *inout_params = p; } p[n] = param; p[n + 1] = NULL; return 0; } static int msg_param_prune(msg_param_t const d[], msg_param_t p, unsigned prune) { size_t i, nlen; if (prune == 1) nlen = strcspn(p, "="); else nlen = 0; for (i = 0; d[i]; i++) { if ((prune == 1 && su_casenmatch(p, d[i], nlen) && (d[i][nlen] == '=' || d[i][nlen] == '\0')) || (prune == 2 && su_casematch(p, d[i])) || (prune == 3 && strcmp(p, d[i]) == 0)) return 1; } return 0; } /**Join two parameter lists. * * The function @c msg_params_join() joins two parameter lists; the * first list must have been created by @c msg_params_d() or by @c * msg_params_dup() (or it may contain only @c NULL). * * @param home memory home * @param dst pointer to pointer to destination parameter list * @param src source list * @param prune prune duplicates * @param dup duplicate parameters in src list * * @par Pruning * * * * * *
0do not prune
1prune parameters with identical names
2case-insensitive values
3case-sensitive values
* * @return * @retval >= 0 when successful * @retval -1 upon an error */ issize_t msg_params_join(su_home_t *home, msg_param_t **dst, msg_param_t const *src, unsigned prune, int dup) { size_t n, m, n_before, n_after, pruned, total = 0; msg_param_t *d = *dst; if (prune > 3) return -1; if (src == NULL || *src == NULL) return 0; /* Count number of parameters */ for (n = 0; d && d[n]; n++) ; n_before = MSG_PARAMS_NUM(n + 1); for (m = 0, pruned = 0; src[m]; m++) { if (n > 0 && prune > 0 && msg_param_prune(d, src[m], prune)) { pruned++; if (prune > 1) continue; } if (dup) total += strlen(src[m]) + 1; } n_after = MSG_PARAMS_NUM(n + m - pruned + 1); if (n_before != n_after || !d) { d = su_alloc(home, n_after * sizeof(*d)); assert(d); if (!d) return -1; if (n) memcpy(d, *dst, n * sizeof(*d)); *dst = d; } for (m = 0; src[m]; m++) { if (pruned && msg_param_prune(d, src[m], prune)) { pruned--; if (prune > 1) continue; } if (dup) d[n++] = su_strdup(home, src[m]); /* XXX */ else d[n++] = src[m]; } d[n] = NULL; return 0; } /**Join header item lists. * * Join items from a source header to the destination header. The item are * compared with the existing ones. If a match is found, it is not added to * the list. If @a duplicate is true, the entries are duplicated while they * are added to the list. * * @param home memory home * @param dst destination header * @param src source header * @param duplicate if true, allocate and copy items that are added * * @return * @retval >= 0 when successful * @retval -1 upon an error * * @NEW_1_12_5. */ int msg_header_join_items(su_home_t *home, msg_common_t *dst, msg_common_t const *src, int duplicate) { size_t N, m, M, i, n_before, n_after, total; char *dup = NULL; msg_param_t *d, **dd, *s; msg_param_t t, *temp, temp0[16]; size_t *len, len0[(sizeof temp0)/(sizeof temp0[0])]; msg_update_f *update = NULL; if (dst == NULL || dst->h_class->hc_params == 0 || src == NULL || src->h_class->hc_params == 0) return -1; s = *(msg_param_t **)((char *)src + src->h_class->hc_params); if (s == NULL) return 0; for (M = 0; s[M]; M++) {} if (M == 0) return 0; if (M <= (sizeof temp0) / (sizeof temp0[0])) { temp = temp0, len = len0; } else { temp = malloc(M * (sizeof *temp) + M * (sizeof *len)); if (!temp) return -1; len = (void *)(temp + M); } dd = (msg_param_t **)((char *)dst + dst->h_class->hc_params); d = *dd; for (N = 0; d && d[N]; N++) {} for (m = 0, M = 0, total = 0; s[m]; m++) { t = s[m]; for (i = 0; i < N; i++) if (strcmp(t, d[i]) == 0) break; if (i < N) continue; for (i = 0; i < M; i++) if (strcmp(t, temp[i]) == 0) break; if (i < M) continue; temp[M] = t; len[M] = strlen(t); total += len[M++] + 1; } if (M == 0) goto success; dup = su_alloc(home, total); if (!dup) goto error; n_before = MSG_PARAMS_NUM(N + 1); n_after = MSG_PARAMS_NUM(N + M + 1); if (d == NULL || n_before != n_after) { d = su_alloc(home, n_after * sizeof(*d)); if (!d) goto error; if (N) memcpy(d, *dd, N * sizeof(*d)); *dd = d; } update = dst->h_class->hc_update; for (m = 0; m < M; m++) { d[N++] = memcpy(dup, temp[m], len[m] + 1); if (update) update(dst, dup, len[m], dup + len[m]); dup += len[m] + 1; } d[N] = NULL; success: if (temp != temp0) free(temp); return 0; error: if (temp != temp0) free(temp); su_free(home, dup); return -1; } /**Compare parameter lists. * * Compares parameter lists. * * @param a pointer to a parameter list * @param b pointer to a parameter list * * @retval an integer less than zero if @a is less than @a b * @retval an integer zero if @a match with @a b * @retval an integer greater than zero if @a is greater than @a b */ int msg_params_cmp(char const * const a[], char const * const b[]) { int c; size_t nlen; if (a == NULL || b == NULL) return (a != NULL) - (b != NULL); for (;;) { if (*a == NULL || *b == NULL) return (*a != NULL) - (*b != NULL); nlen = strcspn(*a, "="); if ((c = su_strncasecmp(*a, *b, nlen))) return c; if ((c = strcmp(*a + nlen, *b + nlen))) return c; a++, b++; } } /** Unquote string * * Duplicates the string @a q in unquoted form. */ char *msg_unquote_dup(su_home_t *home, char const *q) { char *d; size_t total, n, m; /* First, easy case */ if (q[0] == '"') q++; n = strcspn(q, "\"\\"); if (q[n] == '\0' || q[n] == '"') return su_strndup(home, q, n); /* Hairy case - backslash-escaped chars */ total = n; for (;;) { if (q[n] == '\0' || q[n] == '"' || q[n + 1] == '\0') break; m = strcspn(q + n + 2, "\"\\"); total += m + 1; n += m + 2; } if (!(d = su_alloc(home, total + 1))) return NULL; for (n = 0;;) { m = strcspn(q, "\"\\"); memcpy(d + n, q, m); n += m, q += m; if (q[0] == '\0' || q[0] == '"' || q[1] == '\0') break; d[n++] = q[1]; q += 2; } assert(total == n); d[n] = '\0'; return d; } /** Unquote string */ char *msg_unquote(char *dst, char const *s) { int copy = dst != NULL; char *d = dst; if (*s++ != '"') return NULL; for (;;) { size_t n = strcspn(s, "\"\\"); if (copy) memmove(d, s, n); s += n; d += n; if (*s == '\0') return NULL; else if (*s == '"') { if (copy) *d = '\0'; return dst; } else { /* Copy quoted char */ if ((copy ? (*d++ = *++s) : *++s) == '\0') return NULL; s++; } } } /** Quote string */ issize_t msg_unquoted_e(char *b, isize_t bsiz, char const *s) { isize_t e = 0; if (b == NULL) bsiz = 0; if (0 < bsiz) *b = '"'; e++; for (;*s;) { size_t n = strcspn(s, "\"\\"); if (n == 0) { if (e + 2 <= bsiz) b[e] = '\\', b[e + 1] = s[0]; e += 2; s++; } else { if (e + n <= bsiz) memcpy(b + e, s, n); e += n; s += n; } } if (e < bsiz) b[e] = '"'; e++; return e; } /** Calculate a simple hash over a string. */ unsigned long msg_hash_string(char const *id) { unsigned long hash = 0; if (id) for (; *id; id++) { hash += (unsigned)*id; hash *= 38501U; } else hash *= 38501U; if (hash == 0) hash = (unsigned long)-1; return hash; } /** Calculate the size of a duplicate of a header structure. */ isize_t msg_header_size(msg_header_t const *h) { if (h == NULL || h == MSG_HEADER_NONE) return 0; else return h->sh_class->hc_dxtra(h, h->sh_class->hc_size); } /** Encode a message to the buffer. * * The function msg_encode_e encodes a message to a given buffer. * It returns the length of the message to be encoded, even if the * buffer is too small (just like snprintf() is supposed to do). * * @param b buffer (may be NULL) * @param size size of buffer * @param mo public message structure (#sip_t, #http_t) * @param flags see # */ issize_t msg_object_e(char b[], isize_t size, msg_pub_t const *mo, int flags) { size_t rv = 0; ssize_t n; msg_header_t const *h; if (mo->msg_request) h = mo->msg_request; else h = mo->msg_status; for (; h; h = h->sh_succ) { n = msg_header_e(b, size, h, flags); if (n < 0) return -1; if ((size_t)n < size) b += n, size -= n; else b = NULL, size = 0; rv += n; } return rv; } /** Encode header contents. */ issize_t msg_header_field_e(char b[], isize_t bsiz, msg_header_t const *h, int flags) { assert(h); assert(h->sh_class); return h->sh_class->hc_print(b, bsiz, h, flags); } /** Get offset of header @a h from structure @a mo. */ msg_header_t ** msg_header_offset(msg_t const *msg, msg_pub_t const *mo, msg_header_t const *h) { if (h == NULL || h->sh_class == NULL) return NULL; return msg_hclass_offset(msg->m_class, mo, h->sh_class); } /**Get a header from the public message structure. * * Gets a pointer to header from a message structure. * * @param pub public message structure from which header is obtained * @param hc header class */ msg_header_t * msg_header_access(msg_pub_t const *pub, msg_hclass_t *hc) { msg_header_t * const * hh; if (pub == NULL || hc == NULL) return NULL; hh = msg_hclass_offset((void *)pub->msg_ident, (msg_pub_t *)pub, hc); if (hh) return *hh; else return NULL; } #include /** Generates a random token. * */ issize_t msg_random_token(char token[], isize_t tlen, void const *rmemp, isize_t rsize) { uint32_t random = 0, rword; uint8_t rbyte; uint8_t const *rmem = rmemp; size_t i; ssize_t n; static char const token_chars[33] = /* Create aesthetically pleasing raNDom capS LooK */ "aBcDeFgHjKmNpQrStUvXyZ0123456789"; if (rmem == NULL && rsize == 0) rsize = UINT_MAX; if (rsize == 0) { if (token && tlen > 0) strcpy(token, "+"); return 1; } if (token == NULL) { if (rsize >= tlen * 5 / 8) return tlen; else return rsize / 5 * 8; } for (i = 0, n = 0; i < tlen;) { if (n < 5) { if (rsize == 0) ; else if (rmem) { rbyte = *rmem++, rsize--; random = random | (rbyte << n); n += 8; } else { rword = su_random(); random = (rword >> 13) & 31; n = 6; } } token[i] = token_chars[random & 31]; random >>= 5; i++, n -= 5; if (n < 0 || (n == 0 && rsize == 0)) break; } token[i] = 0; return i; } /** Parse a message. * * Parse a text message with parser @a mc. The @a data is copied and it is * not modified or referenced by the parsed message. * * @par Example * Parse a SIP message fragment (e.g., payload of NOTIFY sent in response to * REFER): * @code * msg_t *m = msg_make(sip_default_mclass(), 0, pl->pl_data, pl->pl_len); * sip_t *frag = sip_object(m); * @endcode * * @param mc message class (parser table) * @param flags message flags (see #msg_flg_user) * @param data message text * @param len size of message text (if -1, use strlen(data)) * * @retval A pointer to a freshly allocated and parsed message. * * Upon parsing error, the header structure may be left incomplete. The * #MSG_FLG_ERROR is set in @a msg_object(msg)->msg_flags. * * @since New in @VERSION_1_12_4 * * @sa msg_as_string(), msg_extract() */ msg_t *msg_make(msg_mclass_t const *mc, int flags, void const *data, ssize_t len) { msg_t *msg; msg_iovec_t iovec[2]; if (len == -1) len = strlen(data); if (len == 0) return NULL; msg = msg_create(mc, flags); if (msg == NULL) return NULL; su_home_preload(msg_home(msg), 1, len + 1024); if (msg_recv_iovec(msg, iovec, 2, len, 1) < 0) { perror("msg_recv_iovec"); } assert((ssize_t)iovec->mv_len == len); memcpy(iovec->mv_base, data, len); msg_recv_commit(msg, len, 1); if (msg_extract(msg) < 0) msg->m_object->msg_flags |= MSG_FLG_ERROR; return msg; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/msg_tag.c000066400000000000000000000165721223300710500221400ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE msg_tag.c Message tag classes * * @author Pekka Pessi * * @date Created: Fri Feb 23 12:46:42 2001 ppessi * */ #include "config.h" #include #include #include #include #include #define TAG_NAMESPACE "msg" #include "msg_internal.h" #include "sofia-sip/msg_header.h" #include "sofia-sip/msg_parser.h" #include #include #include #include "sofia-sip/msg_tag_class.h" #define NONE ((void*)(intptr_t)-1) int msghdrtag_snprintf(tagi_t const *t, char b[], size_t size) { msg_header_t const *h; assert(t); if (!t) { if (size) b[0] = 0; return 0; } h = (msg_header_t const *)t->t_value; if (h != MSG_HEADER_NONE && h != NULL) { return msg_header_field_e(b, size, h, 0); } else { return snprintf(b, size, ""); } } size_t msghdrtag_xtra(tagi_t const *t, size_t offset) { msg_header_t const *h; size_t rv; msg_hclass_t *hc = (msg_hclass_t *)t->t_tag->tt_magic; assert(t); for (h = (msg_header_t const *)t->t_value, rv = offset; h != NULL; h = h->sh_next) { if (h == MSG_HEADER_NONE) break; MSG_STRUCT_SIZE_ALIGN(rv); if (hc) rv = hc->hc_dxtra(h, rv + h->sh_class->hc_size); else rv = h->sh_class->hc_dxtra(h, rv + h->sh_class->hc_size); } return rv - offset; } tagi_t *msghdrtag_dup(tagi_t *dst, tagi_t const *src, void **bb) { msg_header_t const *o; msg_header_t *h, *h0 = NULL, **hh; msg_hclass_t *hc, *hc0 = (msg_hclass_t *)src->t_tag->tt_magic; char *b; size_t size; assert(src); assert(*bb); dst->t_tag = src->t_tag; dst->t_value = 0L; b = *bb; hh = &h0; for (o = (msg_header_t const *)src->t_value; o != NULL; o = o->sh_next) { if (o == MSG_HEADER_NONE) { *hh = (msg_header_t *)o; break; } /* XXX assert(msg_hdr_p(o)); */ MSG_STRUCT_ALIGN(b); h = (msg_header_t *)b; hc = hc0 ? hc0 : o->sh_class; b += hc->hc_size; memset(h, 0, hc->hc_size); h->sh_class = hc; size = SIZE_MAX - (uintptr_t)b; if (size > ISSIZE_MAX) size = ISSIZE_MAX; b = hc->hc_dup_one(h, o, b, size); if (hc->hc_update) msg_header_update_params(h->sh_common, 0); *hh = h; hh = &h->sh_next; assert(b != NULL); } *bb = b; dst->t_value = (tag_value_t)h0; return dst + 1; } /** Convert a string to a header structure based on to the tag. */ int msghdrtag_scan(tag_type_t tt, su_home_t *home, char const *s, tag_value_t *return_value) { msg_hclass_t *hc = (msg_hclass_t *)tt->tt_magic; msg_header_t *h; int retval; h = msg_header_make(home, hc, s); if (h) *return_value = (tag_value_t)h, retval = 1; else *return_value = (tag_value_t)NULL, retval = -1; return retval; } tagi_t *msgstrtag_filter(tagi_t *dst, tagi_t const f[], tagi_t const *src, void **bb); int msgobjtag_snprintf(tagi_t const *t, char b[], size_t size) { msg_pub_t const *mo; assert(t); if (!t || !t->t_value) { if (size) b[0] = 0; return 0; } mo = (msg_pub_t *)t->t_value; return (int)msg_object_e(b, size, mo, MSG_DO_CANONIC); } size_t msgobjtag_xtra(tagi_t const *t, size_t offset) { msg_header_t const *h; msg_pub_t const *mo; size_t rv; assert(t); mo = (msg_pub_t const *)t->t_value; if (mo == NULL || mo == NONE) return 0; rv = offset; MSG_STRUCT_SIZE_ALIGN(rv); rv += mo->msg_size; if (mo->msg_request) h = (msg_header_t const *)mo->msg_request; else h = (msg_header_t const *)mo->msg_status; for (; h; h = h->sh_succ) { MSG_STRUCT_SIZE_ALIGN(rv); rv += msg_header_size(h); } return rv - offset; } tagi_t *msgobjtag_dup(tagi_t *dst, tagi_t const *src, void **bb) { msg_pub_t const *omo; msg_pub_t *mo; msg_header_t *h; msg_header_t const *o; char *b; assert(src); assert(*bb); omo = (msg_pub_t const *)src->t_value; dst->t_tag = src->t_tag; dst->t_value = 0; if (omo == NULL || omo == NONE) { dst->t_value = src->t_value; return dst + 1; } b = *bb; MSG_STRUCT_ALIGN(b); mo = (msg_pub_t *)b; b += omo->msg_size; memset(mo, 0, omo->msg_size); mo->msg_size = omo->msg_size; mo->msg_flags = omo->msg_flags; if (mo->msg_request) o = mo->msg_request; else o = mo->msg_status; for (; o; o = o->sh_succ) { size_t size; MSG_STRUCT_ALIGN(b); h = (msg_header_t *)b; b += o->sh_class->hc_size; memset(h, 0, o->sh_class->hc_size); h->sh_class = o->sh_class; size = SIZE_MAX - (uintptr_t)b; if (size > ISSIZE_MAX) size = ISSIZE_MAX; b = o->sh_class->hc_dup_one(h, o, b, size); if (o->sh_class->hc_update) msg_header_update_params(h->sh_common, 0); assert(b != NULL); } dst->t_value = (tag_value_t)mo; *bb = b; return dst + 1; } #if 0 int msgtag_multipart_xtra(tagi_t const *t, int offset) { msg_header_t const *h; msg_multipart_t const *mp; int rv; assert(t); mp = (msg_multipart_t const *)t->t_value; if (mp == NULL || mp == NONE) return 0; rv = offset; MSG_STRUCT_SIZE_ALIGN(rv); rv += mo->msg_size; if (mo->msg_request) h = (msg_header_t const *)mo->msg_request; else h = (msg_header_t const *)mo->msg_status; for (; h; h = h->sh_succ) { MSG_STRUCT_SIZE_ALIGN(rv); rv += msg_header_size(h); } return rv - offset; } tagi_t *msgtag_multipart_dup(tagi_t *dst, tagi_t const *src, void **bb) { msg_pub_t const *omo; msg_pub_t *mo; msg_header_t *h; msg_header_t const *o; char *b; assert(src); assert(*bb); omo = (msg_pub_t const *)src->t_value; dst->t_tag = src->t_tag; dst->t_value = 0; if (omo == NULL || omo == NONE) { dst->t_value = src->t_value; return dst + 1; } b = *bb; MSG_STRUCT_ALIGN(b); mo = (msg_pub_t *)b; b += omo->msg_size; memset(mo, 0, omo->msg_size); mo->msg_size = omo->msg_size; mo->msg_flags = omo->msg_flags; if (mo->msg_request) o = mo->msg_request; else o = mo->msg_status; for (; o; o = o->sh_succ) { size_t size; MSG_STRUCT_ALIGN(b); h = (msg_header_t *)b; b += o->sh_class->hc_size; memset(h, 0, o->sh_class->hc_size); h->sh_class = o->sh_class; size = SIZE_MAX - (uintptr_t)b; if (size > ISSIZE_MAX) size = ISSIZE_MAX; b = o->sh_class->hc_dup_one(h, o, b, size); if (o->sh_class->hc_update) msg_header_update_params(h->sh_common, 0); assert(b != NULL); } dst->t_value = (long)mo; *bb = b; return dst + 1; } #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/sofia-sip/000077500000000000000000000000001223300710500222325ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/sofia-sip/msg.h000066400000000000000000000131441223300710500231740ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef MSG_H /** Defined when has been included */ #define MSG_H /**@file sofia-sip/msg.h * * Base message interface. * * @author Pekka Pessi * * @date Created: Fri Feb 18 08:54:48 2000 ppessi */ #include #include SOFIA_BEGIN_DECLS SOFIAPUBFUN msg_t *msg_create(msg_mclass_t const *mc, int flags); SOFIAPUBFUN msg_t *msg_ref(msg_t *); SOFIAPUBFUN void msg_unref(msg_t *); SOFIAPUBFUN void msg_destroy(msg_t *); SOFIAPUBFUN msg_t *msg_copy(msg_t *); SOFIAPUBFUN msg_t *msg_dup(msg_t const *); SOFIAPUBFUN msg_t *msg_make(msg_mclass_t const *mc, int flags, void const *data, ssize_t len); SOFIAPUBFUN char *msg_as_string(su_home_t *home, msg_t *msg, msg_pub_t *pub, int flags, size_t *return_len); SOFIAPUBFUN void msg_set_parent(msg_t *kid, msg_t *dad); SOFIAPUBFUN msg_t *msg_ref_create(msg_t *); SOFIAPUBFUN void msg_ref_destroy(msg_t *); SOFIAPUBFUN msg_pub_t *msg_public(msg_t const *msg, void *tag); SOFIAPUBFUN msg_pub_t *msg_object(msg_t const *msg); SOFIAPUBFUN msg_mclass_t const *msg_mclass(msg_t const *msg); SOFIAPUBFUN int msg_extract(msg_t *msg); SOFIAPUBFUN unsigned msg_extract_errors(msg_t const *msg); SOFIAPUBFUN int msg_is_complete(msg_t const *msg); SOFIAPUBFUN int msg_has_error(msg_t const *msg); SOFIAPUBFUN msg_header_t **msg_chain_head(msg_t const *msg); SOFIAPUBFUN int msg_serialize(msg_t *msg, msg_pub_t *mo); SOFIAPUBFUN int msg_prepare(msg_t *msg); SOFIAPUBFUN void msg_unprepare(msg_t *msg); SOFIAPUBFUN int msg_is_prepared(msg_t const *msg); SOFIAPUBFUN usize_t msg_size(msg_t const *msg); SOFIAPUBFUN usize_t msg_maxsize(msg_t *msg, usize_t maxsize); /** Cast a #msg_t pointer to a #su_home_t pointer. */ #define msg_home(h) ((su_home_t*)(h)) /** Streaming state of a #msg_t object. */ enum msg_streaming_status { /** Disable streaming */ msg_stop_streaming = 0, /** Enable streaming */ msg_start_streaming = 1 }; SOFIAPUBFUN int msg_is_streaming(msg_t const *msg); SOFIAPUBFUN void msg_set_streaming(msg_t *msg, enum msg_streaming_status what); SOFIAPUBFUN unsigned msg_mark_as_complete(msg_t *msg, unsigned mask); SOFIAPUBFUN unsigned msg_get_flags(msg_t const *msg, unsigned mask); SOFIAPUBFUN unsigned msg_set_flags(msg_t *msg, unsigned mask); SOFIAPUBFUN unsigned msg_zap_flags(msg_t *msg, unsigned mask); /** Flags controlling parser/printer. */ enum msg_flg_user { /** Use compact form when printing. */ MSG_FLG_COMPACT = (1<<0), /** Use canonic representation when printing. */ MSG_FLG_CANONIC = (1<<1), /** Cache a copy of headers when parsing. */ MSG_FLG_EXTRACT_COPY = (1<<2), /** Print comma-separated lists instead of separate headers */ MSG_FLG_COMMA_LISTS = (1<<3), /**Use mailbox format when parsing - in mailbox format * message has no body unless Content-Length header is present. */ MSG_FLG_MAILBOX = (1<<4), /** Use multiple parts for message body */ MSG_FLG_CHUNKING = (1<<5), /** Enable streaming - parser gives completed message fragments when they * are ready to upper layers */ MSG_FLG_STREAMING = (1<<6), /** Make messages threadsafe. */ MSG_FLG_THRDSAFE = (1<<15), MSG_FLG_USERMASK = (1<<16) - 1 }; /** Flags used by parser. */ enum msg_flg_parser { /** Extract headers for this message */ MSG_FLG_HEADERS = (1<<16), /** Extract body for this message */ MSG_FLG_BODY = (1<<17), /** Extract chunks for this message */ MSG_FLG_CHUNKS = (1<<18), /** Extract trailers for this message */ MSG_FLG_TRAILERS = (1<<19), /** Extract last component of this message */ MSG_FLG_FRAGS = (1<<20), /** This message has been completely extracted */ MSG_FLG_COMPLETE = (1<<24), /** This message has parsing errors */ MSG_FLG_ERROR = (1<<25), /** This message is too large */ MSG_FLG_TOOLARGE = (1<<26), /** This message is truncated */ MSG_FLG_TRUNC = (1<<27), /** This message has timeout */ MSG_FLG_TIMEOUT = (1<<28), MSG_FLG_PARSERMASK = ((-1) ^ ((1<<16) - 1)) }; #define MSG_DO_COMPACT MSG_FLG_COMPACT #define MSG_DO_CANONIC MSG_FLG_CANONIC #define MSG_DO_EXTRACT_COPY MSG_FLG_EXTRACT_COPY /** Test if all the flags in @a v are set in @a f. */ #define MSG_FLAGS(f, v) (((f) & (v)) == v) #define MSG_IS_COMPACT(f) MSG_FLAGS((f), MSG_FLG_COMPACT) #define MSG_IS_CANONIC(f) MSG_FLAGS((f), MSG_FLG_CANONIC) #define MSG_IS_EXTRACT_COPY(f) MSG_FLAGS((f), MSG_FLG_EXTRACT_COPY) #define MSG_IS_COMMA_LISTS(f) MSG_FLAGS((f), MSG_FLG_COMMA_LISTS) #define MSG_IS_MAILBOX(f) MSG_FLAGS((f), MSG_FLG_MAILBOX) #define MSG_HAS_COMPLETE(f) MSG_FLAGS((f), MSG_FLG_COMPLETE) #define MSG_HAS_ERROR(f) MSG_FLAGS((f), MSG_FLG_ERROR) #define MSG_IS_COMPLETE(mo) (((mo)->msg_flags & MSG_FLG_COMPLETE) != 0) SOFIA_END_DECLS #endif /* MSG_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/sofia-sip/msg_addr.h000066400000000000000000000053551223300710500241730ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef MSG_ADDR_H /** Defined when has been included. */ #define MSG_ADDR_H /**@file sofia-sip/msg_addr.h * @brief Addressing and I/O interface for messages. * * @author Pekka Pessi * * @date Created: Thu Jun 8 19:28:55 2000 ppessi */ #ifndef MSG_H #include #endif #ifndef SU_H #include #endif SOFIA_BEGIN_DECLS SOFIAPUBFUN void msg_addr_zero(msg_t *msg); SOFIAPUBFUN su_addrinfo_t *msg_addrinfo(msg_t *msg); SOFIAPUBFUN su_sockaddr_t *msg_addr(msg_t *msg); SOFIAPUBFUN int msg_get_address(msg_t *msg, su_sockaddr_t *, socklen_t *); SOFIAPUBFUN int msg_set_address(msg_t *msg, su_sockaddr_t const *, socklen_t); SOFIAPUBFUN void msg_addr_copy(msg_t *dst, msg_t const *src); SOFIAPUBFUN int msg_errno(msg_t const *msg); SOFIAPUBFUN void msg_set_errno(msg_t *msg, int err); enum { /** Minimum size of a message buffer */ msg_min_size = 512, /** Minimum size of external buffer */ msg_min_block = 8192, /** Number of external buffers */ msg_n_fragments = 8 }; /** I/O vector type. * @sa msg_recv_iovec(), msg_iovec(), #su_iovec_s, su_vsend(), su_vrecv(). */ typedef struct su_iovec_s msg_iovec_t; #define mv_base siv_base #define mv_len siv_len SOFIAPUBFUN isize_t msg_iovec(msg_t *msg, msg_iovec_t vec[], isize_t veclen); SOFIAPUBFUN issize_t msg_recv_iovec(msg_t *msg, msg_iovec_t vec[], isize_t veclen, usize_t n, int exact); SOFIAPUBFUN isize_t msg_recv_commit(msg_t *msg, usize_t n, int eos); SOFIAPUBFUN issize_t msg_recv_buffer(msg_t *msg, void **return_buffer); SOFIAPUBFUN msg_t *msg_next(msg_t *msg); SOFIAPUBFUN int msg_set_next(msg_t *msg, msg_t *next); SOFIAPUBFUN void msg_clear_committed(msg_t *msg); SOFIAPUBFUN issize_t msg_buf_external(msg_t *msg, usize_t N, usize_t blocksize); SOFIA_END_DECLS #endif /* !defined(MSG_ADDR_H) */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/sofia-sip/msg_buffer.h000066400000000000000000000034221223300710500245230ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef MSG_BUFFER_H /** Defined when has been included. */ #define MSG_BUFFER_H /**@file sofia-sip/msg_buffer.h * @brief Internal buffer management functions. * * @author Pekka Pessi * * @date Created: Fri Nov 8 12:23:00 2002 ppessi * */ #ifndef MSG_TYPES_H #include #endif SOFIA_BEGIN_DECLS SOFIAPUBFUN void *msg_buf_alloc(msg_t *msg, usize_t size); SOFIAPUBFUN void *msg_buf_exact(msg_t *msg, usize_t size); SOFIAPUBFUN usize_t msg_buf_commit(msg_t *msg, usize_t size, int eos); SOFIAPUBFUN usize_t msg_buf_committed(msg_t const *msg); SOFIAPUBFUN void *msg_buf_committed_data(msg_t const *msg); SOFIAPUBFUN usize_t msg_buf_size(msg_t const *msg); SOFIAPUBFUN void *msg_buf_move(msg_t *dst, msg_t const *src); SOFIAPUBFUN void msg_buf_set(msg_t *msg, void *b, usize_t size); SOFIA_END_DECLS #endif /* !defined MSG_BUFFER_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/sofia-sip/msg_date.h000066400000000000000000000043201223300710500241650ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef MSG_DATE_H /** Defined when has been included. */ #define MSG_DATE_H /**@ingroup msg_parser * @file sofia-sip/msg_date.h * @brief Types and functions for handling dates and times. * * @author Pekka Pessi * * @date Created: Thu Jun 8 19:28:55 2000 ppessi * */ #ifndef SU_TYPES_H #include #endif SOFIA_BEGIN_DECLS #ifndef MSG_TIME_T_DEFINED #define MSG_TIME_T_DEFINED /** Time in seconds since epoch (1900-Jan-01 00:00:00). */ typedef unsigned long msg_time_t; #endif #ifndef MSG_TIME_MAX /** Latest time that can be expressed with msg_time_t. @HIDE */ #define MSG_TIME_MAX ((msg_time_t)ULONG_MAX) #endif /* Current time. */ SOFIAPUBFUN msg_time_t msg_now(void); SOFIAPUBFUN issize_t msg_date_delta_d(char const **inout_string, msg_time_t *return_date, msg_time_t *return_delta); SOFIAPUBFUN issize_t msg_delta_d(char const **ss, msg_time_t *return_delta); SOFIAPUBFUN issize_t msg_delta_e(char b[], isize_t bsiz, msg_time_t delta); /** Decode RFC1123-date, RFC822-date or asctime-date. */ SOFIAPUBFUN issize_t msg_date_d(char const **ss, msg_time_t *date); /** Encode RFC1123-date. */ SOFIAPUBFUN issize_t msg_date_e(char b[], isize_t bsiz, msg_time_t date); enum { msg_date_string_size = 29 }; SOFIA_END_DECLS #endif /* !defined(MSG_DATE_H) */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/sofia-sip/msg_header.h000066400000000000000000000225061223300710500245060ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef MSG_HEADER_H /** Defined when has been included. */ #define MSG_HEADER_H /**@ingroup msg_headers * @file sofia-sip/msg_header.h * * @brief Message headers. * * @author Pekka Pessi * * @date Created: Mon Aug 27 15:44:27 2001 ppessi * */ #include #include #ifndef SU_TYPES_H #include #endif #ifndef SU_ALLOC_H #include #endif #ifndef MSG_H #include #endif #ifndef URL_H #include #endif SOFIA_BEGIN_DECLS SOFIAPUBFUN msg_header_t *msg_header_alloc(su_home_t *, msg_hclass_t *hc, isize_t extra) __attribute__((__malloc__)); SOFIAPUBFUN isize_t msg_header_size(msg_header_t const *h); SOFIAPUBFUN msg_header_t **msg_header_offset(msg_t const *, msg_pub_t const *, msg_header_t const *); SOFIAPUBFUN msg_header_t **msg_hclass_offset(msg_mclass_t const *, msg_pub_t const *, msg_hclass_t *); SOFIAPUBFUN msg_header_t *msg_header_access(msg_pub_t const *pub, msg_hclass_t *hc); SOFIAPUBFUN msg_header_t *msg_header_copy_as(su_home_t *home, msg_hclass_t *hc, msg_header_t const *o) __attribute__((__malloc__)); SOFIAPUBFUN msg_header_t *msg_header_copy(su_home_t *home, msg_header_t const *o) __attribute__((__malloc__)); SOFIAPUBFUN msg_header_t *msg_header_copy_one(su_home_t *home, msg_header_t const *o) __attribute__((__malloc__)); SOFIAPUBFUN msg_header_t *msg_header_dup_as(su_home_t *home, msg_hclass_t *hc, msg_header_t const *o) __attribute__((__malloc__)); SOFIAPUBFUN msg_header_t *msg_header_dup(su_home_t *home, msg_header_t const *h) __attribute__((__malloc__)); SOFIAPUBFUN msg_header_t *msg_header_dup_one(su_home_t *home, msg_header_t const *h) __attribute__((__malloc__)); SOFIAPUBFUN msg_header_t *msg_header_d(su_home_t *home, msg_t const *msg, char const *b); SOFIAPUBFUN issize_t msg_header_e(char b[], isize_t bsiz, msg_header_t const *h, int flags); SOFIAPUBFUN issize_t msg_object_e(char b[], isize_t size, msg_pub_t const *mo, int flags); SOFIAPUBFUN issize_t msg_header_field_e(char b[], isize_t bsiz, msg_header_t const *h, int flags); SOFIAPUBFUN int msg_header_remove(msg_t *msg, msg_pub_t *mo, msg_header_t *h); SOFIAPUBFUN int msg_header_remove_all(msg_t *msg, msg_pub_t *mo, msg_header_t *h); SOFIAPUBFUN int msg_header_insert(msg_t *msg, msg_pub_t *mo, msg_header_t *h); SOFIAPUBFUN int msg_header_replace(msg_t *msg, msg_pub_t *mo, msg_header_t *old_header, msg_header_t *new_header); SOFIAPUBFUN int msg_header_add_dup(msg_t *msg, msg_pub_t *pub, msg_header_t const *o); SOFIAPUBFUN int msg_header_add_str(msg_t *msg, msg_pub_t *pub, char const *str); SOFIAPUBFUN int msg_header_parse_str(msg_t *msg, msg_pub_t *pub, char *s); SOFIAPUBFUN int msg_header_add_dup_as(msg_t *msg, msg_pub_t *pub, msg_hclass_t *hc, msg_header_t const *o); SOFIAPUBFUN int msg_header_add_make(msg_t *msg, msg_pub_t *pub, msg_hclass_t *hc, char const *s); SOFIAPUBFUN int msg_header_add_format(msg_t *msg, msg_pub_t *pub, msg_hclass_t *hc, char const *fmt, ...); SOFIAPUBFUN int msg_header_prepend(msg_t *msg, msg_pub_t *pub, msg_header_t **hh, msg_header_t *h); SOFIAPUBFUN msg_header_t *msg_header_make(su_home_t *home, msg_hclass_t *hc, char const *s) __attribute__((__malloc__)); SOFIAPUBFUN msg_header_t *msg_header_format(su_home_t *home, msg_hclass_t *hc, char const *fmt, ...) __attribute__ ((__malloc__, __format__ (printf, 3, 4))); SOFIAPUBFUN msg_header_t *msg_header_vformat(su_home_t *home, msg_hclass_t *hc, char const *fmt, va_list ap) __attribute__((__malloc__)); SOFIAPUBFUN void msg_header_free(su_home_t *home, msg_header_t *h); SOFIAPUBFUN void msg_header_free_all(su_home_t *home, msg_header_t *h); SOFIAPUBFUN msg_payload_t *msg_payload_create(su_home_t *home, void const *data, usize_t len) __attribute__((__malloc__)); SOFIAPUBFUN msg_separator_t *msg_separator_create(su_home_t *home) __attribute__((__malloc__)); /* Chunk handling macros */ /** Get pointer to beginning of available buffer space */ #define MSG_CHUNK_BUFFER(pl) \ ((char *)pl->pl_common->h_data + (pl)->pl_common->h_len) /** Get size of available buffer space */ #define MSG_CHUNK_AVAIL(pl) \ ((pl)->pl_len + ((pl)->pl_data - (char *)pl->pl_common->h_data) - \ (pl)->pl_common->h_len) /** Get next chunk in list */ #define MSG_CHUNK_NEXT(pl) \ ((pl)->pl_next) SOFIAPUBFUN issize_t msg_headers_prepare(msg_t *, msg_header_t *headers, int flags); #ifdef SU_HAVE_INLINE /** Clear encoded data from header structure. */ su_inline void msg_fragment_clear(msg_common_t *h) { h->h_data = NULL, h->h_len = 0; } /** Pointer to header parameters. */ su_inline msg_param_t **msg_header_params(msg_common_t const *h) { if (h && h->h_class->hc_params) { return (msg_param_t **)((char *)h + h->h_class->hc_params); } return NULL; } #else #define msg_fragment_clear(h) ((h)->h_data = NULL, (h)->h_len = 0) #define msg_header_params(h) \ (((h) && ((msg_common_t *)h)->h_class->hc_params) ? \ (msg_param_t **)((char *)(h) + ((msg_common_t *)h)->h_class->hc_params) : NULL) #endif SOFIAPUBFUN void msg_fragment_clear_chain(msg_header_t *h); SOFIAPUBFUN char const *msg_header_find_param(msg_common_t const *, char const *name); SOFIAPUBFUN int msg_header_add_param(su_home_t *, msg_common_t *h, char const *param); SOFIAPUBFUN int msg_header_replace_param(su_home_t *, msg_common_t *h, char const *param); SOFIAPUBFUN int msg_header_remove_param(msg_common_t *h, char const *name); SOFIAPUBFUN char const *msg_header_find_item(msg_common_t const *h, char const *item); SOFIAPUBFUN int msg_header_replace_item(su_home_t *, msg_common_t *h, char const *item); SOFIAPUBFUN int msg_header_remove_item(msg_common_t *h, char const *name); /** Append a list of constant items to a list. */ SOFIAPUBFUN int msg_list_append_items(su_home_t *home, msg_list_t *k, msg_param_t const items[]); /** Replace a list of constant items on a list */ SOFIAPUBFUN int msg_list_replace_items(su_home_t *home, msg_list_t *k, msg_param_t const items[]); SOFIAPUBFUN int msg_header_join_items(su_home_t *home, msg_common_t *dst, msg_common_t const *src, int duplicate); SOFIAPUBFUN issize_t msg_random_token(char token[], isize_t tlen, void const *d, isize_t dlen); SOFIAPUBFUN msg_param_t msg_params_find(msg_param_t const pp[], char const *name); SOFIAPUBFUN msg_param_t *msg_params_find_slot(msg_param_t [], char const *name); SOFIAPUBFUN int msg_params_add(su_home_t *sh, msg_param_t **pp, char const *param); SOFIAPUBFUN int msg_params_cmp(char const * const a[], char const * const b[]); SOFIAPUBFUN int msg_params_replace(su_home_t *, char const * **inout_paramlist, char const *); SOFIAPUBFUN int msg_params_remove(char const **paramlist, char const *name); SOFIAPUBFUN size_t msg_params_length(char const * const * params); /** Unquote a string, return a duplicate. */ SOFIAPUBFUN char *msg_unquote_dup(su_home_t *home, char const *q) __attribute__((__malloc__)); SOFIAPUBFUN char *msg_unquote(char *dst, char const *s); /** Calculate a hash over a string. */ SOFIAPUBFUN unsigned long msg_hash_string(char const *id); /* Align pointer p for multiple of t (which must be a power of 2) */ #define MSG_ALIGN(p, t) (((uintptr_t)(p) + (t) - 1) & (0 - (uintptr_t)(t))) #define MSG_STRUCT_SIZE_ALIGN(rv) ((rv) = MSG_ALIGN(rv, sizeof(void *))) #define MSG_STRUCT_ALIGN(p) ((p) = (void*)MSG_ALIGN(p, sizeof(void *))) enum { msg_n_params = 8 /* allocation size of parameter string list */ #define MSG_N_PARAMS msg_n_params }; /** Initialize a header structure. @HIDE */ #define MSG_HEADER_INIT(h, msg_class, size) \ ((void)memset((h), 0, (size)), \ (void)(((msg_common_t *)(h))->h_class = (msg_class)), \ (h)) /** No header. */ #define MSG_HEADER_NONE ((msg_header_t *)(intptr_t)-1) SOFIA_END_DECLS #ifndef MSG_PROTOS_H #include #endif #endif /** !defined(MSG_HEADER_H) */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/sofia-sip/msg_mclass.h000066400000000000000000000124671223300710500245450ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef MSG_MCLASS_H /** Defined when has been included. */ #define MSG_MCLASS_H /**@ingroup msg_parser * @file sofia-sip/msg_mclass.h * * @brief Parser table and message factory object. * * @author Pekka Pessi * * @date Created: Mon Aug 27 15:44:27 2001 ppessi */ #ifndef MSG_HEADER_H #include #endif SOFIA_BEGIN_DECLS enum { /** Default size of hash table */ MC_HASH_SIZE = 127, /** Size of short form table */ MC_SHORT_SIZE = 'Z' - 'A' + 1 }; /**Header reference. * * A header reference object contains a pointer to a * @ref msg_hclass_s "header class" * and a offset to the header objects within the @ref msg_pub_t "public * message structure". * * The @a hr_flags field is used to provide classification of headers. For * instance, the msg_extract_errors() returns bitwise or of all hr_flags * belonging to headers with parsing errors. */ struct msg_href_s { msg_hclass_t *hr_class; /**< Header class */ unsigned short hr_offset; /**< Offset within public message struct. */ unsigned short hr_flags; /**< Header flags */ }; /**Factory object for protocol messages. * * The message class is a kind of a factory object used to create new * message objects for the protocol it represents (see msg_create()). * * The message class object contains all the information needed to parse a * message. It used when headers are added or removed from the message. When * a message is sent, the message class is used to order message components * and print (encode) the message in text format. * * The message class contains reference objects to headers and other components * within the message. Each reference contains a pointer to a @ref * msg_hclass_s "header class" and a offset to the header objects within * public message structure. The parser engine uses these references when it * adds a newly parsed header object to the message structure. The function * msg_find_hclass() searches for the reference of the named header. * The application can make a copy of existing message class object using * the function msg_mclass_clone(). New headers can be added to the message * class with the msg_mclass_insert_header() and msg_mclass_insert() * functions. The message class of an existing message object can be found * out with the function msg_mclass(). * * @sa sip_default_mclass(), http_default_mclass(), msg_create(), * msg_mclass(), msg_mclass_clone(), msg_mclass_insert_header(), * msg_mclass_insert_with_mask(), msg_mclass_insert(). */ struct msg_mclass_s { struct msg_hclass_s mc_hclass[1]; /**< Recursive header class */ char const *mc_name; /**< Protocol name, e.g., "SIP/2.0" */ void *mc_tag; /**< Protocol-specific tag */ unsigned mc_flags; /**< Default flags */ unsigned mc_msize; /**< Size of public message structure */ /** Function extracting the message contents. */ issize_t (*mc_extract_body)(msg_t *msg, msg_pub_t *pub, char b[], isize_t bsiz, int eos); msg_href_t mc_request[1]; /**< Request line reference */ msg_href_t mc_status[1]; /**< Status line reference */ msg_href_t mc_separator[1];/**< Separator line reference */ msg_href_t mc_payload[1]; /**< Message body reference */ msg_href_t mc_unknown[1]; /**< Reference for unknown headers */ msg_href_t mc_error[1]; /**< Reference for erroneous header */ msg_href_t mc_multipart[1];/**< Multipart body reference */ msg_href_t const * mc_short; /**< Short forms (or NULL) */ short mc_hash_size; /**< Size of parsing table */ short mc_hash_used; /**< Number of headers in parsing table */ /** Hash table for parsing containing reference for each header. */ msg_href_t mc_hash[MC_HASH_SIZE]; }; enum { msg_mclass_copy = 0, msg_mclass_empty = 1 }; SOFIAPUBFUN msg_mclass_t *msg_mclass_clone(msg_mclass_t const *old, int newsize, int empty); SOFIAPUBFUN int msg_mclass_insert(msg_mclass_t *mc, msg_href_t const *hr); SOFIAPUBFUN int msg_mclass_insert_header(msg_mclass_t *mc, msg_hclass_t *hc, unsigned short offset); SOFIAPUBFUN int msg_mclass_insert_with_mask(msg_mclass_t *mc, msg_hclass_t *hc, unsigned short offset, unsigned short mask); SOFIAPUBFUN msg_href_t const *msg_find_hclass(msg_mclass_t const *, char const *, isize_t *); SOFIAPUBFUN msg_mclass_t const *msg_mclass(msg_t const *); SOFIA_END_DECLS #endif /* !defined(MSG_MCLASS_H) */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/sofia-sip/msg_mclass_hash.h000066400000000000000000000035331223300710500255420ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef MSG_MCLASS_HASH_H /** Defined when has been included. */ #define MSG_MCLASS_HASH_H /**@ingroup msg_parser * @file sofia-sip/msg_mclass_hash.h * * Hash function for header names. * * @author Pekka Pessi * * @date Created: Tue Aug 21 16:03:45 2001 ppessi * */ #include #ifndef BNF_H #include #endif SOFIA_BEGIN_DECLS /** Hash the header name */ #define MC_HASH(s, n) (msg_header_name_hash(s, NULL) % (unsigned)(n)) /** Hash header name */ su_inline unsigned short msg_header_name_hash(char const *s, isize_t *llen) { unsigned short hash = 0; size_t i; for (i = 0; s[i]; i++) { unsigned char c = s[i]; if (!(_bnf_table[c] & bnf_token)) break; if (c >= 'A' && c <= 'Z') hash += (c + 'a' - 'A'); else hash += c; hash *= 38501U; } if (llen) *llen = i; return hash; } SOFIA_END_DECLS #endif /** MSG_MCLASS_HASH_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/sofia-sip/msg_mime.h000066400000000000000000000213171223300710500242040ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005-2011 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef MSG_MIME_H /** Defined when has been included. */ #define MSG_MIME_H /**@ingroup msg_mime * @file sofia-sip/msg_mime.h * * MIME headers and multipart messages (@RFC2045). * * @author Pekka Pessi * * @date Created: Fri Aug 16 19:18:26 EEST 2002 ppessi * */ #ifndef URL_H #include #endif #ifndef MSG_TYPES_H #include #endif #ifndef SU_TYPES_H #include #endif SOFIA_BEGIN_DECLS typedef struct msg_accept_any_s msg_accept_any_t; typedef struct msg_accept_s msg_accept_t; typedef msg_accept_any_t msg_accept_charset_t; typedef msg_accept_any_t msg_accept_encoding_t; typedef msg_accept_any_t msg_accept_language_t; typedef struct msg_content_disposition_s msg_content_disposition_t; typedef msg_list_t msg_content_encoding_t; typedef msg_generic_t msg_content_id_t; typedef struct msg_content_length_s msg_content_length_t; typedef msg_generic_t msg_content_location_t; typedef msg_list_t msg_content_language_t; typedef msg_generic_t msg_content_md5_t; typedef msg_generic_t msg_content_transfer_encoding_t; typedef struct msg_content_type_s msg_content_type_t; typedef msg_generic_t msg_mime_version_t; typedef struct msg_warning_s msg_warning_t; /** Multipart body object. */ typedef struct msg_multipart_s msg_multipart_t; /**@ingroup msg_accept * @brief Structure for @b Accept header. */ struct msg_accept_s { msg_common_t ac_common[1]; /**< Common fragment info */ msg_accept_t *ac_next; /**< Pointer to next Accept header */ char const *ac_type; /**< Pointer to type/subtype */ char const *ac_subtype; /**< Points after first slash in type */ msg_param_t const *ac_params; /**< List of parameters */ char const *ac_q; /**< Value of q parameter */ }; /**@ingroup msg_accept_encoding * @brief Structure for @b Accept-Charset, @b Accept-Encoding and * @b Accept-Language headers. */ struct msg_accept_any_s { msg_common_t aa_common[1]; /**< Common fragment info */ msg_accept_any_t *aa_next; /**< Pointer to next Accept-* header */ char const *aa_value; /**< Token */ msg_param_t const *aa_params; /**< List of parameters */ char const *aa_q; /**< Value of q parameter */ }; /**@ingroup msg_content_disposition * @brief Structure for @b Content-Disposition header. */ struct msg_content_disposition_s { msg_common_t cd_common[1]; /**< Common fragment info */ msg_error_t *cd_next; /**< Link to next (dummy) */ char const *cd_type; /**< Disposition type */ msg_param_t const *cd_params; /**< List of parameters */ char const *cd_handling; /**< Value of @b handling parameter */ unsigned cd_required:1; /**< True if handling=required */ unsigned cd_optional:1; /**< True if handling=optional */ unsigned :0; /* pad */ }; /**@ingroup msg_content_length * @brief Structure for Content-Length header. */ struct msg_content_length_s { msg_common_t l_common[1]; /**< Common fragment info */ msg_error_t *l_next; /**< Link to next (dummy) */ unsigned long l_length; /**< Digits */ }; /**@ingroup msg_content_type * @brief Structure for Content-Type header. */ struct msg_content_type_s { msg_common_t c_common[1]; /**< Common fragment info */ msg_error_t *c_next; /**< Dummy link to next */ char const *c_type; /**< Pointer to type/subtype */ char const *c_subtype; /**< Points after first slash in type */ msg_param_t const *c_params; /**< List of parameters */ }; /**@ingroup sip_warning * @brief Structure for @b Warning header. */ struct msg_warning_s { msg_common_t w_common[1]; /**< Common fragment info */ msg_warning_t *w_next; /**< Link to next Warning header */ unsigned w_code; /**< Warning code */ char const *w_host; /**< Hostname or pseudonym */ char const *w_port; /**< Port number */ char const *w_text; /**< Warning text */ }; /**@ingroup msg_multipart * * @brief Structure for a part in MIME multipart message. */ struct msg_multipart_s { msg_common_t mp_common[1]; /**< Common fragment information */ msg_multipart_t *mp_next; /**< Next part in multipart body */ /* Preamble for this part */ char *mp_data; /**< Boundary string. */ unsigned mp_len; /**< Length of boundary (mp_data).*/ unsigned mp_flags; msg_error_t *mp_error; /* === Headers start here */ msg_content_type_t *mp_content_type; /**< Content-Type (c) */ msg_content_disposition_t *mp_content_disposition; /**< Content-Disposition */ msg_content_location_t *mp_content_location; /**< Content-Location */ msg_content_id_t *mp_content_id; /**< Content-ID */ msg_content_language_t *mp_content_language; /**< Content-Language */ msg_content_encoding_t *mp_content_encoding; /**< Content-Encoding (e) */ msg_content_transfer_encoding_t *mp_content_transfer_encoding; /**< Content-Transfer-Encoding */ #if 0 /* === Hash headers end here */ /* These MIME headers are here for msg_parser.awk */ msg_accept_t *mp_accept; /**< Accept */ msg_accept_charset_t *mp_accept_charset; /**< Accept-Charset */ msg_accept_encoding_t *mp_accept_encoding; /**< Accept-Encoding */ msg_accept_language_t *mp_accept_language; /**< Accept-Language */ msg_mime_version_t *mp_mime_version; /**< MIME-Version */ msg_content_md5_t *mp_content_md5; /**< Content-MD5 */ msg_content_length_t *mp_content_length; /**< Content-Length */ msg_multipart_t *mp_multipart; /**< Recursive multipart */ msg_warning_t *mp_warning; /**< Warning */ #endif /* === Headers end here */ /** Unknown and extra headers. */ msg_unknown_t *mp_unknown; /**< Unknown headers */ msg_separator_t *mp_separator; /**< Separator */ msg_payload_t *mp_payload; /**< Body part */ msg_multipart_t *mp_multipart; /**< Recursive multipart */ msg_payload_t *mp_close_delim; /**< Closing delimiter */ }; SOFIAPUBFUN msg_multipart_t *msg_multipart_create(su_home_t *home, char const *content_type, void const *data, isize_t dlen); SOFIAPUBFUN msg_multipart_t *msg_multipart_parse(su_home_t *home, msg_content_type_t const *c, msg_payload_t *pl); SOFIAPUBFUN int msg_multipart_complete(su_home_t *home, msg_content_type_t *c, msg_multipart_t *mp); SOFIAPUBFUN msg_header_t *msg_multipart_serialize(msg_header_t **head0, msg_multipart_t *mp); SOFIAPUBFUN issize_t msg_multipart_prepare(msg_t *msg, msg_multipart_t *mp, int flags); SOFIAPUBFUN isize_t msg_accept_any_dup_xtra(msg_header_t const *h, isize_t offset); SOFIAPUBFUN char *msg_accept_any_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra); SOFIAPUBFUN msg_content_length_t *msg_content_length_create(su_home_t *, uint32_t n); SOFIAPUBFUN unsigned msg_q_value(char const *q); SOFIAPUBFUN msg_accept_t *msg_accept_match(msg_accept_t const *, msg_content_type_t const *); /** MIME multipart protocol name. @HIDE */ #define MSG_MULTIPART_VERSION_CURRENT msg_mime_version_1_0 SOFIAPUBVAR char const msg_mime_version_1_0[]; /** MIME multipart parser table identifier. @HIDE */ #define MSG_MULTIPART_PROTOCOL_TAG ((void *)(uintptr_t)0x4d494d45) /* 'MIME' */ SOFIA_END_DECLS #endif /** MSG_MIME_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/sofia-sip/msg_mime_protos.h.in000066400000000000000000000214401223300710500262140ustar00rootroot00000000000000/**@ingroup msg -*- c -*- * @file sofia-sip/msg_mime_protos.h.in * * Template for . */ /* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef MSG_MIME_PROTOS_H /** Defined when has been included. */ #define MSG_MIME_PROTOS_H /**@ingroup msg_mime * @file sofia-sip/msg_mime_protos.h * * Prototypes for MIME headers (@RFC2045). * * #AUTO# * * @author Pekka Pessi */ #ifndef MSG_PARSER_H #include #endif #ifndef MSG_MIME_H #include #endif #ifndef MSG_MCLASS_H #include #endif #ifndef MSG_MCLASS_H #include #endif SOFIA_BEGIN_DECLS MSG_DLL extern msg_mclass_t const msg_multipart_mclass[1]; #define msg_multipart_class ((msg_hclass_t *)msg_multipart_mclass) /* Declare internal prototypes for #xxxxxxx_xxxxxxx# */ /**@addtogroup msg_#xxxxxx# * @{ */ enum { /** Hash of #xxxxxxx_xxxxxxx#. @internal */ msg_#xxxxxx#_hash = #hash# }; /** Parse a #xxxxxxx_xxxxxxx#. @internal */ MSG_DLL msg_parse_f msg_#xxxxxx#_d; /** Print a #xxxxxxx_xxxxxxx#. @internal */ MSG_DLL msg_print_f msg_#xxxxxx#_e; MSG_DLL msg_xtra_f msg_#xxxxxx#_dup_xtra; MSG_DLL msg_dup_f msg_#xxxxxx#_dup_one; /**Header class for #xxxxxxx_xxxxxxx#. * * The header class msg_#xxxxxx#_class defines how a * #xxxxxxx_xxxxxxx# header is parsed and printed. It also * contains methods used by message parser and other functions * to manipulate the #msg_#xxxxxx#_t header structure. * */ #ifndef msg_#xxxxxx#_class MSG_DLL extern msg_hclass_t msg_#xxxxxx#_class[]; #endif /**Initializer for an #msg_#xxxxxx#_t structure. * * A static msg_#xxxxxx#_t structure must be initialized * with the MSG_#XXXXXX#_INIT() macro. For instance, * @code * * msg_#xxxxxx#_t msg_#xxxxxx# = MSG_#XXXXXX#_INIT; * * @endcode * @HI */ #define MSG_#XXXXXX#_INIT() MSG_HDR_INIT(#xxxxxx#) /**Initialize an #msg_#xxxxxx#_t structure. * * An #msg_#xxxxxx#_t structure can be initialized with the * msg_#xxxxxx#_init() function/macro. For instance, * @code * * msg_#xxxxxx#_t msg_#xxxxxx#; * * msg_#xxxxxx#_init(&msg_#xxxxxx#); * * @endcode * * @param x pointer to #msg_#xxxxxx#_t structure */ #if SU_HAVE_INLINE su_inline msg_#xxxxxx#_t *msg_#xxxxxx#_init(msg_#xxxxxx#_t x[1]) { return MSG_HEADER_INIT(x, msg_#xxxxxx#_class, sizeof(msg_#xxxxxx#_t)); } #else #define msg_#xxxxxx#_init(x) \ MSG_HEADER_INIT(x, msg_#xxxxxx#_class, sizeof(msg_#xxxxxx#_t)) #endif /**Test if header object is an instance of #msg_#xxxxxx#_t. * * The function msg_is_#xxxxxx#() returns true (nonzero) if * the header class is an instance of #xxxxxxx_xxxxxxx# * object and false (zero) otherwise. * * @param header pointer to the header structure to be tested * * @return The function msg_is_#xxxxxx#() returns true (nonzero) if the * header object is an instance of header #xxxxxxx_xxxxxxx# and false (zero) * otherwise. */ #if SU_HAVE_INLINE su_inline int msg_is_#xxxxxx#(msg_header_t const *header) { return header && header->sh_class->hc_hash == msg_#xxxxxx#_hash; } #else int msg_is_#xxxxxx#(msg_header_t const *header); #endif #define msg_#xxxxxx#_p(h) msg_is_#xxxxxx#((h)) /**Duplicate (deep copy) #msg_#xxxxxx#_t. * * The function msg_#xxxxxx#_dup() duplicates a header structure @a * header. If the header structure @a header contains a reference * (@c header->x_next) to a list of headers, all the headers in the * list are duplicated, too. * * @param home memory home used to allocate new structure * @param header header structure to be duplicated * * When duplicating, all parameter lists and non-constant strings * attached to the header are copied, too. The function uses given * memory @a home to allocate all the memory areas used to copy the * header. * * @par Example * @code * * #xxxxxx# = msg_#xxxxxx#_dup(home, msg->msg_#xxxxxx#); * * @endcode * * @return * The function msg_#xxxxxx#_dup() returns a pointer to the * newly duplicated #msg_#xxxxxx#_t header structure, or NULL * upon an error. */ #if SU_HAVE_INLINE su_inline #endif msg_#xxxxxx#_t *msg_#xxxxxx#_dup(su_home_t *home, msg_#xxxxxx#_t const *header); #if SU_HAVE_INLINE su_inline msg_#xxxxxx#_t *msg_#xxxxxx#_dup(su_home_t *home, msg_#xxxxxx#_t const *header) { return (msg_#xxxxxx#_t *) msg_header_dup_as(home, msg_#xxxxxx#_class, (msg_header_t const *)header); } #endif /**Copy an #msg_#xxxxxx#_t header structure. * * The function msg_#xxxxxx#_copy() copies a header structure @a * header. If the header structure @a header contains a reference * (@c header->h_next) to a list of headers, all the headers in that * list are copied, too. The function uses given memory @a home to * allocate all the memory areas used to copy the header structure * @a header. * * @param home memory home used to allocate new structure * @param header pointer to the header structure to be duplicated * * When copying, only the header structure and parameter lists * attached to it are duplicated. The new header structure retains * all the references to the strings within the old @a header, * including the encoding of the old header, if present. * * @par Example * @code * * #xxxxxx# = msg_#xxxxxx#_copy(home, msg->msg_#xxxxxx#); * * @endcode * * @return * The function msg_#xxxxxx#_copy() returns a pointer to * newly copied header structure, or NULL upon an error. */ #if SU_HAVE_INLINE su_inline #endif msg_#xxxxxx#_t *msg_#xxxxxx#_copy(su_home_t *home, msg_#xxxxxx#_t const *header); #if SU_HAVE_INLINE su_inline msg_#xxxxxx#_t *msg_#xxxxxx#_copy(su_home_t *home, msg_#xxxxxx#_t const *header) { return (msg_#xxxxxx#_t *) msg_header_copy_as(home, msg_#xxxxxx#_class, (msg_header_t const *)header); } #endif /**Make a header structure #msg_#xxxxxx#_t. * * The function msg_#xxxxxx#_make() makes a new #msg_#xxxxxx#_t header * structure. It allocates a new header structure, and decodes the string @a * s as the value of the structure. * * @param home memory home used to allocate new header structure. * @param s string to be decoded as value of the new header structure * * @note This function may be implemented as a macro calling * msg_header_make(). * * @return * The function msg_#xxxxxx#_make() returns a pointer to newly maked * #msg_#xxxxxx#_t header structure, or NULL upon an error. */ #if SU_HAVE_INLINE su_inline msg_#xxxxxx#_t *msg_#xxxxxx#_make(su_home_t *home, char const *s) { return (msg_#xxxxxx#_t*)msg_header_make(home, msg_#xxxxxx#_class, s); } #else msg_#xxxxxx#_t *msg_#xxxxxx#_make(su_home_t *home, char const *s); #endif /**Make a #xxxxxxx_xxxxxxx# from formatting result. * * The function msg_#xxxxxx#_format() makes a new #xxxxxxx_xxxxxxx# object * using snprintf-formatted result as its value. The function first * prints the arguments according to the format @a fmt specified. Then it * allocates a new header structure, and uses the formatting result as the * header value. * * @param home memory home used to allocate new header structure. * @param fmt string used as a printf()-style format * @param ... argument list for format * * @note This function may be implemented as a macro calling * msg_header_format(). * * @return * The function msg_#xxxxxx#_format() returns a pointer to newly * makes header structure, or NULL upon an error. * * @HIDE */ #if SU_HAVE_INLINE su_inline #endif msg_#xxxxxx#_t *msg_#xxxxxx#_format(su_home_t *home, char const *fmt, ...) __attribute__((__format__ (printf, 2, 3))); #if SU_HAVE_INLINE su_inline msg_#xxxxxx#_t *msg_#xxxxxx#_format(su_home_t *home, char const *fmt, ...) { msg_header_t *h; va_list ap; va_start(ap, fmt); h = msg_header_vformat(home, msg_#xxxxxx#_class, fmt, ap); va_end(ap); return (msg_#xxxxxx#_t*)h; } #endif /** @} */ /* Internal prototypes */ MSG_DLL msg_update_f msg_accept_update; MSG_DLL msg_update_f msg_accept_any_update; MSG_DLL msg_update_f msg_content_disposition_update; SOFIA_END_DECLS #endif /** !defined(MSG_MIME_PROTOS_H) */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/sofia-sip/msg_parser.h000066400000000000000000000250111223300710500245440ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef MSG_PARSER_H /** Defined when has been included. */ #define MSG_PARSER_H /**@ingroup msg_parser * @file sofia-sip/msg_parser.h * * Message parser interface. * * @author Pekka Pessi * * @date Created: Tue Aug 21 16:03:45 2001 ppessi * */ #ifndef SU_ALLOC_H #include #endif #ifndef MSG_HEADER_H #include #endif #ifndef BNF_H #include #endif #ifndef URL_H #include #endif SOFIA_BEGIN_DECLS /* --------------------------------------------------------------------------- * 1) Header class definitions. */ /* Do not use keywords until you fix msg_kind_foo_critical thing! */ \ #if HAVE_STRUCT_KEYWORDS && 0 /** Define a header class */ #define MSG_HEADER_CLASS(pr, c, l, s, params, kind, dup, upd) \ {{ \ hc_hash: pr##c##_hash, \ hc_parse: pr##c##_d, \ hc_print: pr##c##_e, \ hc_dxtra: dup##_dup_xtra, \ hc_dup_one: dup##_dup_one, \ hc_update: upd##_update, \ hc_name: l, \ hc_len: sizeof(l) - 1, \ hc_short: s, \ hc_size: MSG_ALIGN(sizeof(pr##c##_t), sizeof(void*)), \ hc_params: offsetof(pr##c##_t, params), \ hc_kind: msg_kind_##kind, \ }} #else /** Define a header class */ #define MSG_HEADER_CLASS(pr, c, l, s, params, kind, dup, upd) \ {{ \ pr##c##_hash, \ pr##c##_d, \ pr##c##_e, \ dup##_dup_xtra, \ dup##_dup_one, \ upd##_update, \ l, \ sizeof(l) - 1, \ s, \ MSG_ALIGN(sizeof(pr##c##_t), sizeof(void*)), \ offsetof(pr##c##_t, params), \ msg_kind_##kind, \ }} #endif /* Mark headers critical for understanding the message */ #define msg_kind_single_critical msg_kind_single, 1 #define msg_kind_list_critical msg_kind_list, 1 SOFIAPUBFUN issize_t msg_extract_header(msg_t *msg, msg_pub_t *mo, char b[], isize_t bsiz, int eos); SOFIAPUBFUN issize_t msg_extract_separator(msg_t *msg, msg_pub_t *mo, char b[], isize_t bsiz, int eos); SOFIAPUBFUN issize_t msg_extract_payload(msg_t *msg, msg_pub_t *mo, msg_header_t **return_payload, usize_t body_len, char b[], isize_t bsiz, int eos); /* --------------------------------------------------------------------------- * 2) Header processing methods for common headers. */ SOFIAPUBFUN int msg_firstline_d(char *s, char **ss2, char **ss3); SOFIAPUBFUN isize_t msg_default_dup_xtra(msg_header_t const *header, isize_t offset); SOFIAPUBFUN char *msg_default_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra); SOFIAPUBFUN issize_t msg_numeric_d(su_home_t *, msg_header_t *h, char *s, isize_t slen); SOFIAPUBFUN issize_t msg_numeric_e(char [], isize_t, msg_header_t const *, int); SOFIAPUBFUN issize_t msg_list_d(su_home_t *, msg_header_t *h, char *s, isize_t slen); SOFIAPUBFUN issize_t msg_list_e(char [], isize_t, msg_header_t const *, int); SOFIAPUBFUN isize_t msg_list_dup_xtra(msg_header_t const *h, isize_t offset); SOFIAPUBFUN char *msg_list_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra); SOFIAPUBFUN issize_t msg_generic_d(su_home_t *, msg_header_t *, char *, isize_t); SOFIAPUBFUN issize_t msg_generic_e(char [], isize_t, msg_header_t const *, int); SOFIAPUBFUN isize_t msg_generic_dup_xtra(msg_header_t const *h, isize_t offset); SOFIAPUBFUN char *msg_generic_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra); SOFIAPUBFUN isize_t msg_unknown_dup_xtra(msg_header_t const *h, isize_t offset); SOFIAPUBFUN char *msg_unknown_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra); SOFIAPUBFUN isize_t msg_error_dup_xtra(msg_header_t const *h, isize_t offset); SOFIAPUBFUN char *msg_error_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra); SOFIAPUBFUN issize_t msg_payload_d(su_home_t *, msg_header_t *h, char *s, isize_t slen); SOFIAPUBFUN issize_t msg_payload_e(char b[], isize_t bsiz, msg_header_t const *, int f); SOFIAPUBFUN isize_t msg_payload_dup_xtra(msg_header_t const *h, isize_t offset); SOFIAPUBFUN char *msg_payload_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra); SOFIAPUBFUN issize_t msg_separator_d(su_home_t *, msg_header_t *, char *, isize_t); SOFIAPUBFUN issize_t msg_separator_e(char [], isize_t, msg_header_t const *, int); SOFIAPUBFUN issize_t msg_auth_d(su_home_t *, msg_header_t *h, char *s, isize_t slen); SOFIAPUBFUN issize_t msg_auth_e(char b[], isize_t bsiz, msg_header_t const *h, int f); SOFIAPUBFUN isize_t msg_auth_dup_xtra(msg_header_t const *h, isize_t offset); SOFIAPUBFUN char *msg_auth_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra); /* --------------------------------------------------------------------------- * 2) Macros and prototypes for building header decoding/encoding functions. */ #define MSG_HEADER_DATA(h) ((char *)(h) + (h)->sh_class->hc_size) #define MSG_HEADER_TEST(h) ((h) && (h)->sh_class) su_inline void *msg_header_data(msg_frg_t *h); SOFIAPUBFUN int msg_hostport_d(char **ss, char const **return_host, char const **return_port); SOFIAPUBFUN issize_t msg_token_d(char **ss, char const **return_token); SOFIAPUBFUN issize_t msg_uint32_d(char **ss, uint32_t *return_value); SOFIAPUBFUN issize_t msg_comment_d(char **ss, char const **return_comment); SOFIAPUBFUN issize_t msg_quoted_d(char **ss, char **return_unquoted); SOFIAPUBFUN issize_t msg_unquoted_e(char *b, isize_t bsiz, char const *s); SOFIAPUBFUN issize_t msg_parse_next_field(su_home_t *home, msg_header_t *prev, char *s, isize_t slen); /** Terminate encoding. @HI */ #define MSG_TERM_E(p, e) ((p) < (e) ? (p)[0] = '\0' : '\0') /** Encode a character. @HI */ #define MSG_CHAR_E(p, e, c) (++(p) < (e) ? ((p)[-1]=(c)) : (c)) /** Calculate separator and string length. @HI */ #define MSG_STRING_LEN(s, sep_size) ((s) ? (strlen(s) + sep_size) : 0) /** Encode a string. @HI */ #define MSG_STRING_E(p, e, s) do { \ size_t _n = strlen(s); if (p + _n+1 < e) memcpy(p, s, _n+1); p+= _n; } while(0) /** Duplicate string. @HI */ #define MSG_STRING_DUP(p, d, s) \ (void)((s)?((p)=(char*)memccpy((void *)((d)=(char*)p),(s),0,INT_MAX))\ :((d)=NULL)) /* Solaris has broken memccpy - it considers last argument as signed */ /** Calculate string size. @HI */ #define MSG_STRING_SIZE(s) ((s) ? (strlen(s) + 1) : 0) SOFIAPUBFUN issize_t msg_commalist_d(su_home_t *, char **ss, msg_param_t **append_list, issize_t (*scanner)(char *s)); SOFIAPUBFUN issize_t msg_token_scan(char *start); SOFIAPUBFUN issize_t msg_attribute_value_scanner(char *s); SOFIAPUBFUN issize_t msg_any_list_d(su_home_t *, char **ss, msg_param_t **append_list, issize_t (*scanner)(char *s), int sep); /** Encode a comma-separated parameter list */ #define MSG_COMMALIST_E(b, end, params, compact) do { \ char const * const *p_; char const * c_ = ""; \ for (p_ = (params); p_ && *p_; p_++, c_ = (compact ? "," : ", ")) \ { MSG_STRING_E(b, (end), c_); MSG_STRING_E(b, (end), *p_); } \ } while(0) /* Parameter lists */ SOFIAPUBFUN int msg_header_update_params(msg_common_t *h, int clear); /** Match a parameter with any value. @HI */ #define MSG_PARAM_MATCH(v, s, name) \ (strncasecmp(s, name "=", sizeof(name)) == 0 ? (v = s + sizeof(name)) : NULL) /** Match a parameter with known value. @HI */ #define MSG_PARAM_MATCH_P(v, s, name) \ ((strncasecmp((s), name "", sizeof(name) - 1) == 0 && \ ((s)[sizeof(name) - 1] == '=' || (s)[sizeof(name) - 1] == '\0')) ? \ ((v) = 1) : 0) /** Calculate allocated number of items in parameter list. @HI */ #define MSG_PARAMS_NUM(n) (((n) + MSG_N_PARAMS - 1) & (size_t)(0 - MSG_N_PARAMS)) /** Parse a semicolong-separated attribute-value list. @HI */ SOFIAPUBFUN issize_t msg_avlist_d(su_home_t *, char **ss, msg_param_t const **return_params); /** Parse a semicolon-separated parameter list starting with semicolon. @HI */ SOFIAPUBFUN issize_t msg_params_d(su_home_t *, char **ss, msg_param_t const **return_params); /** Encode a list of parameters. */ SOFIAPUBFUN isize_t msg_params_e(char b[], isize_t bsiz, msg_param_t const pparams[]); /** Join list of parameters */ SOFIAPUBFUN issize_t msg_params_join(su_home_t *, msg_param_t **dst, msg_param_t const *src, unsigned prune, int dup); /** Encode a list of parameters. @HI */ #define MSG_PARAMS_E(b, end, params, flags) \ (b) += msg_params_e((b), (size_t)((b) < (end) ? (end) - (b) : 0), (params)) /** Calculate extra size of parametes. @HI */ #define MSG_PARAMS_SIZE(rv, params) (rv = msg_params_dup_xtra(params, rv)) /** Duplicate a parameter list */ SOFIAPUBFUN char *msg_params_dup(msg_param_t const **d, msg_param_t const *s, char *b, isize_t xtra); /** Count number of parameters in the list */ su_inline isize_t msg_params_count(msg_param_t const params[]) { if (params) { size_t n; for (n = 0; params[n]; n++) ; return n; } else { return 0; } } /** Calculate memory size required by parameter list */ su_inline isize_t msg_params_dup_xtra(msg_param_t const params[], isize_t offset) { isize_t n = msg_params_count(params); if (n) { MSG_STRUCT_SIZE_ALIGN(offset); offset += MSG_PARAMS_NUM(n + 1) * sizeof(msg_param_t); for (n = 0; params[n]; n++) offset += strlen(params[n]) + 1; } return offset; } /** Return pointer to extra data after header structure */ su_inline void *msg_header_data(msg_frg_t *h) { if (h) return (char *)h + h->h_class->hc_size; else return NULL; } SOFIA_END_DECLS #endif /** MSG_PARSER_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/sofia-sip/msg_protos.h.in000066400000000000000000000206111223300710500252040ustar00rootroot00000000000000/**@ingroup msg_headers -*- C -*- * @file sofia-sip/msg_protos.h.in * * Template for . */ /* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef MSG_PROTOS_H /** Defined when has been included. */ #define MSG_PROTOS_H /**@ingroup msg_headers * @file sofia-sip/msg_protos.h * * Prototypes for common headers * * #AUTO# * * @author Pekka Pessi * * @date Created: Fri Aug 16 19:18:26 EEST 2002 ppessi */ #ifndef MSG_HEADER_H #include #endif SOFIA_BEGIN_DECLS enum { msg_request_hash = -1, msg_status_hash = -2 }; /* Declare internal prototypes for #xxxxxxx_xxxxxxx# */ /**@addtogroup msg_#xxxxxx# * @{ */ enum { /** Hash of #xxxxxxx_xxxxxxx#. @internal */ msg_#xxxxxx#_hash = #hash# }; /** Parse a #xxxxxxx_xxxxxxx#. @internal */ MSG_DLL msg_parse_f msg_#xxxxxx#_d; /** Print a #xxxxxxx_xxxxxxx#. @internal */ MSG_DLL msg_print_f msg_#xxxxxx#_e; /**Header class for #xxxxxxx_xxxxxxx#. * * The header class msg_#xxxxxx#_class defines how a * #xxxxxxx_xxxxxxx# header is parsed and printed. It also * contains methods used by message parser and other functions * to manipulate the msg_#xxxxxx#_t header structure. * */ MSG_DLL extern msg_hclass_t msg_#xxxxxx#_class[]; /**Initializer for structure msg_#xxxxxx#_t. * * A static msg_#xxxxxx#_t structure must be initialized * with the MSG_#XXXXXX#_INIT() macro. For instance, * @code * * msg_#xxxxxx#_t msg_#xxxxxx# = MSG_#XXXXXX#_INIT; * * @endcode * @HI */ #define MSG_#XXXXXX#_INIT() MSG_HDR_INIT(#xxxxxx#) /**Initialize a structure msg_#xxxxxx#_t. * * An msg_#xxxxxx#_t structure can be initialized with the * msg_#xxxxxx#_init() function/macro. For instance, * @code * * msg_#xxxxxx#_t msg_#xxxxxx#; * * msg_#xxxxxx#_init(&msg_#xxxxxx#); * * @endcode * * @param x pointer to msg_#xxxxxx#_t structure */ #if SU_HAVE_INLINE su_inline msg_#xxxxxx#_t *msg_#xxxxxx#_init(msg_#xxxxxx#_t x[1]) { return MSG_HEADER_INIT(x, msg_#xxxxxx#_class, sizeof(msg_#xxxxxx#_t)); } #else #define msg_#xxxxxx#_init(x) \ MSG_HEADER_INIT(x, msg_#xxxxxx#_class, sizeof(msg_#xxxxxx#_t)) #endif /**Test if header object is instance of msg_#xxxxxx#_t. * * The function msg_is_#xxxxxx#() returns true (nonzero) if * the header class is an instance of #xxxxxxx_xxxxxxx# * object and false (zero) otherwise. * * @param header pointer to the header structure to be tested * * @return * The function msg_is_#xxxxxx#() returns true (nonzero) if * the header object is an instance of header #xxxxxx# and * false (zero) otherwise. */ #if SU_HAVE_INLINE su_inline int msg_is_#xxxxxx#(msg_header_t const *header) { msg_generic_t const *h = (msg_generic_t *)header; return h && h->g_common->h_class->hc_hash == msg_#xxxxxx#_hash; } #else int msg_is_#xxxxxx#(msg_header_t const *header); #endif /**Duplicate (deep copy) @c msg_#xxxxxx#_t. * * The function msg_#xxxxxx#_dup() duplicates a header structure @a * header. If the header structure @a header contains a reference * (@c header->x_next) to a list of headers, all the headers in the * list are duplicated, too. * * @param home memory home used to allocate new structure * @param header header structure to be duplicated * * When duplicating, all parameter lists and non-constant strings * attached to the header are copied, too. The function uses given * memory @a home to allocate all the memory areas used to copy the * header. * * @par Example * @code * * #xxxxxx# = msg_#xxxxxx#_dup(home, msg->msg_#xxxxxx#); * * @endcode * * @return * The function msg_#xxxxxx#_dup() returns a pointer to the * newly duplicated msg_#xxxxxx#_t header structure, or NULL * upon an error. */ #if SU_HAVE_INLINE su_inline #endif msg_#xxxxxx#_t *msg_#xxxxxx#_dup(su_home_t *home, msg_#xxxxxx#_t const *header) __attribute__((__malloc__)); #if SU_HAVE_INLINE su_inline msg_#xxxxxx#_t *msg_#xxxxxx#_dup(su_home_t *home, msg_#xxxxxx#_t const *header) { return (msg_#xxxxxx#_t *) msg_header_dup_as(home, msg_#xxxxxx#_class, (msg_header_t const *)header); } #endif /**Copy a msg_#xxxxxx#_t header structure. * * The function msg_#xxxxxx#_copy() copies a header structure @a * header. If the header structure @a header contains a reference * (@c header->h_next) to a list of headers, all the headers in that * list are copied, too. The function uses given memory @a home to * allocate all the memory areas used to copy the header structure * @a header. * * @param home memory home used to allocate new structure * @param header pointer to the header structure to be duplicated * * When copying, only the header structure and parameter lists * attached to it are duplicated. The new header structure retains * all the references to the strings within the old @a header, * including the encoding of the old header, if present. * * @par Example * @code * * #xxxxxx# = msg_#xxxxxx#_copy(home, msg->msg_#xxxxxx#); * * @endcode * * @return * The function msg_#xxxxxx#_copy() returns a pointer to * newly copied header structure, or NULL upon an error. */ #if SU_HAVE_INLINE su_inline #endif msg_#xxxxxx#_t *msg_#xxxxxx#_copy(su_home_t *home, msg_#xxxxxx#_t const *header) __attribute__((__malloc__)); #if SU_HAVE_INLINE su_inline msg_#xxxxxx#_t *msg_#xxxxxx#_copy(su_home_t *home, msg_#xxxxxx#_t const *header) { return (msg_#xxxxxx#_t *) msg_header_copy_as(home, msg_#xxxxxx#_class, (msg_header_t const *)header); } #endif /**Make a header structure msg_#xxxxxx#_t. * * The function msg_#xxxxxx#_make() makes a new * msg_#xxxxxx#_t header structure. It allocates a new * header structure, and decodes the string @a s as the * value of the structure. * * @param home memory home used to allocate new header structure. * @param s string to be decoded as value of the new header structure * * @note This function is usually implemented as a macro calling * msg_header_make(). * * @return * The function msg_#xxxxxx#_make() returns a pointer to * newly maked msg_#xxxxxx#_t header structure, or NULL upon * an error. */ #if SU_HAVE_INLINE su_inline msg_#xxxxxx#_t *msg_#xxxxxx#_make(su_home_t *home, char const *s) { return (msg_#xxxxxx#_t*)msg_header_make(home, msg_#xxxxxx#_class, s); } #else msg_#xxxxxx#_t *msg_#xxxxxx#_make(su_home_t *home, char const *s) __attribute__((__malloc__)); #endif /**Make a #xxxxxxx_xxxxxxx# from formatting result. * * The function msg_#xxxxxx#_format() makes a new * #xxxxxxx_xxxxxxx# object using formatting result as its * value. The function first prints the arguments according to * the format @a fmt specified. Then it allocates a new header * structure, and uses the formatting result as the header * value. * * @param home memory home used to allocate new header structure. * @param fmt string used as a printf()-style format * @param ... argument list for format * * @note This function is usually implemented as a macro calling * msg_header_format(). * * @return * The function msg_#xxxxxx#_format() returns a pointer to newly * makes header structure, or NULL upon an error. * * @HIDE */ #if SU_HAVE_INLINE su_inline #endif msg_#xxxxxx#_t *msg_#xxxxxx#_format(su_home_t *home, char const *fmt, ...) __attribute__((__malloc__, __format__ (printf, 2, 3))); #if SU_HAVE_INLINE su_inline msg_#xxxxxx#_t *msg_#xxxxxx#_format(su_home_t *home, char const *fmt, ...) { msg_header_t *h; va_list ap; va_start(ap, fmt); h = msg_header_vformat(home, msg_#xxxxxx#_class, fmt, ap); va_end(ap); return (msg_#xxxxxx#_t*)h; } #endif /** @} */ SOFIA_END_DECLS #endif /** !defined(MSG_PROTOS_H) */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/sofia-sip/msg_tag_class.h000066400000000000000000000042311223300710500252110ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef MSG_TAG_CLASS_H /** Defined when has been included */ #define MSG_TAG_CLASS_H /**@file sofia-sip/msg_tag_class.h * @brief Functions for constructing per-protocol tag classes. * * @author Pekka Pessi * * @date Created: Wed Feb 21 11:01:45 2001 ppessi */ #ifndef SU_TAG_H #include #endif SOFIA_BEGIN_DECLS SOFIAPUBFUN int msghdrtag_snprintf(tagi_t const *t, char b[], size_t size); SOFIAPUBFUN size_t msghdrtag_xtra(tagi_t const *t, size_t offset); SOFIAPUBFUN tagi_t *msghdrtag_dup(tagi_t *dst, tagi_t const *src, void **inout_buffer); SOFIAPUBFUN int msghdrtag_scan(tag_type_t tt, su_home_t *home, char const *s, tag_value_t *return_value); SOFIAPUBFUN tagi_t *msghdrtag_filter(tagi_t *dst, tagi_t const f[], tagi_t const *src, void **inout_buffer); SOFIAPUBFUN tagi_t *msgstrtag_filter(tagi_t *dst, tagi_t const f[], tagi_t const *src, void **inout_buffer); SOFIAPUBFUN int msgobjtag_snprintf(tagi_t const *t, char b[], size_t size); SOFIAPUBFUN size_t msgobjtag_xtra(tagi_t const *t, size_t offset); SOFIAPUBFUN tagi_t *msgobjtag_dup(tagi_t *dst, tagi_t const *src, void **inout_buffer); SOFIA_END_DECLS #endif /** !defined(MSG_TAG_CLASS_H) */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/sofia-sip/msg_types.h000066400000000000000000000230251223300710500244170ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef MSG_TYPES_H /** Defined when has been included. */ #define MSG_TYPES_H /**@file sofia-sip/msg_types.h * @brief Types for messages and common headers * * @author Pekka Pessi * * @date Created: Thu Jan 23 15:43:17 2003 ppessi * */ #ifndef SU_TYPES_H #include #endif SOFIA_BEGIN_DECLS /** Message class. */ typedef struct msg_mclass_s msg_mclass_t; /** Header class. */ typedef struct msg_hclass_s const msg_hclass_t; /** Header reference. */ typedef struct msg_href_s msg_href_t; /** Message object. */ typedef struct msg_s msg_t; #ifndef MSG_TIME_T_DEFINED #define MSG_TIME_T_DEFINED /** Time in seconds since epoch (1900-Jan-01 00:00:00). */ typedef unsigned long msg_time_t; #endif #ifndef MSG_TIME_MAX /** Latest time that can be expressed with msg_time_t. @HIDE */ #define MSG_TIME_MAX ((msg_time_t)ULONG_MAX) #endif #ifndef MSG_PUB_T #ifdef MSG_OBJ_T #define MSG_PUB_T MSG_OBJ_T #else #define MSG_PUB_T struct msg_pub_s #endif #endif /**Public protocol-specific message structure for accessing the message. * * This type can be either #sip_t, #http_t, or #msg_multipart_t, depending * on the message. The base structure used by msg module is defined in * struct #msg_pub_s. */ typedef MSG_PUB_T msg_pub_t; #ifndef MSG_HDR_T #define MSG_HDR_T union msg_header_u #endif /** Any protocol-specific header object */ typedef MSG_HDR_T msg_header_t; typedef struct msg_common_s msg_common_t; typedef struct msg_separator_s msg_separator_t; typedef struct msg_payload_s msg_payload_t; typedef struct msg_unknown_s msg_unknown_t; typedef struct msg_error_s msg_error_t; typedef msg_common_t msg_frg_t; typedef char const *msg_param_t; typedef struct msg_numeric_s msg_numeric_t; typedef struct msg_generic_s msg_generic_t; typedef struct msg_list_s msg_list_t; typedef struct msg_auth_s msg_auth_t; typedef struct msg_auth_info_s msg_auth_info_t; #define MSG_HEADER_N 16377 /** Common part of the header objects (or message fragments). * * This structure is also known as #msg_common_t or #sip_common_t. */ struct msg_common_s { msg_header_t *h_succ; /**< Pointer to succeeding fragment. */ msg_header_t **h_prev; /**< Pointer to preceeding fragment. */ msg_hclass_t *h_class; /**< Header class. */ void const *h_data; /**< Fragment data */ usize_t h_len; /**< Fragment length (including CRLF) */ }; /** Message object, common view */ struct msg_pub_s { msg_common_t msg_common[1]; /**< Recursive */ msg_pub_t *msg_next; void *msg_user; unsigned msg_size; unsigned msg_flags; msg_error_t *msg_error; msg_header_t *msg_request; msg_header_t *msg_status; msg_header_t *msg_headers[MSG_HEADER_N]; }; #define msg_ident msg_common->h_class /** Numeric header. * * A numeric header has value range of a 32-bit, 0..4294967295. The @a * x_value field is unsigned long, however. */ struct msg_numeric_s { msg_common_t x_common[1]; /**< Common fragment info */ msg_numeric_t *x_next; /**< Link to next header */ unsigned long x_value; /**< Numeric header value */ }; /** Generic header. * * A generic header does not have any internal structure. Its value is * represented as a string. */ struct msg_generic_s { msg_common_t g_common[1]; /**< Common fragment info */ msg_generic_t *g_next; /**< Link to next header */ char const *g_string; /**< Header value */ }; /** List header. * * A list header consists of comma-separated list of tokens. */ struct msg_list_s { msg_common_t k_common[1]; /**< Common fragment info */ msg_list_t *k_next; /**< Link to next header */ msg_param_t *k_items; /**< List of items */ }; /** Authentication header. * * An authentication header has authentication scheme name and * comma-separated list of parameters as its value. */ struct msg_auth_s { msg_common_t au_common[1]; /**< Common fragment info */ msg_auth_t *au_next; /**< Link to next header */ char const *au_scheme; /**< Auth-scheme like Basic or Digest */ msg_param_t const *au_params; /**< Comma-separated parameters */ }; /**Authentication-Info header * * An Authentication-Info header has comma-separated list of parameters as its value. */ struct msg_auth_info_s { msg_common_t ai_common[1]; /**< Common fragment info */ msg_error_t *ai_next; /**< Dummy link to next */ msg_param_t const *ai_params; /**< List of ainfo */ }; /** Unknown header. */ struct msg_unknown_s { msg_common_t un_common[1]; /**< Common fragment info */ msg_unknown_t *un_next; /**< Link to next unknown header */ char const *un_name; /**< Header name */ char const *un_value; /**< Header field value */ }; /** Erroneus header. */ struct msg_error_s { msg_common_t er_common[1]; /**< Common fragment info */ msg_error_t *er_next; /**< Link to next header */ char const *er_name; /**< Name of bad header (if any). */ }; /** Separator. */ struct msg_separator_s { msg_common_t sep_common[1]; /**< Common fragment info */ msg_error_t *sep_next; /**< Dummy link to next header */ char sep_data[4]; /**< NUL-terminated separator */ }; /** Message payload. */ struct msg_payload_s { msg_common_t pl_common[1]; /**< Common fragment info */ msg_payload_t *pl_next; /**< Next payload chunk */ char *pl_data; /**< Data - may contain NUL */ usize_t pl_len; /**< Length of message payload */ }; /** Any header. */ union msg_header_u { msg_common_t sh_common[1]; /**< Common fragment info */ struct { msg_common_t shn_common; msg_header_t *shn_next; } sh_header_next[1]; #define sh_next sh_header_next->shn_next #define sh_class sh_common->h_class #define sh_succ sh_common->h_succ #define sh_prev sh_common->h_prev #define sh_data sh_common->h_data #define sh_len sh_common->h_len msg_generic_t sh_generic[1]; msg_numeric_t sh_numeric[1]; msg_list_t sh_list[1]; msg_auth_t sh_auth[1]; msg_separator_t sh_separator[1]; msg_payload_t sh_payload[1]; msg_unknown_t sh_unknown[1]; msg_error_t sh_error[1]; }; /* ====================================================================== */ /**Define how to handle existing headers * when a new header is added to a message. */ typedef enum { msg_kind_single, /**< Only one header is allowed */ msg_kind_append, /**< New header is appended */ msg_kind_list, /**< A token list header, * new header is combined with old one. */ msg_kind_apndlist, /**< A complex list header. */ msg_kind_prepend /**< New header is prepended */ } msg_header_kind_t; struct su_home_s; typedef issize_t msg_parse_f(struct su_home_s *, msg_header_t *, char *, isize_t); typedef issize_t msg_print_f(char buf[], isize_t bufsiz, msg_header_t const *, int flags); typedef char *msg_dup_f(msg_header_t *dst, msg_header_t const *src, char *buf, isize_t bufsiz); typedef isize_t msg_xtra_f(msg_header_t const *h, isize_t offset); typedef int msg_update_f(msg_common_t *, char const *name, isize_t namelen, char const *value); /** Factory object for a header. * * The #msg_hclass_t object, "header class", defines how a header is * handled. It has parsing and printing functions, functions used to copy * header objects, header name and other information used when parsing, * printing, removing, adding and replacing headers within a message. */ struct msg_hclass_s { /* XXX size of header class missing. Someone has saved bits in wrong place. */ int hc_hash; /**< Header name hash or ID */ msg_parse_f *hc_parse; /**< Parse header. */ msg_print_f *hc_print; /**< Print header. */ msg_xtra_f *hc_dxtra; /**< Calculate extra size for dup */ msg_dup_f *hc_dup_one; /**< Duplicate one header. */ msg_update_f *hc_update; /**< Update parameter(s) */ char const *hc_name; /**< Full name. */ short hc_len; /**< Length of hc_name. */ char hc_short[2];/**< Short name, if any. */ unsigned char hc_size; /**< Size of header structure. */ unsigned char hc_params; /**< Offset of parameter list */ unsigned hc_kind:3; /**< Kind of header (#msg_header_kind_t): * single, append, list, apndlist, prepend. */ unsigned hc_critical:1; /**< True if header is critical */ unsigned /*pad*/:0; }; #define HC_LEN_MAX SHRT_MAX SOFIA_END_DECLS #endif /* !defined MSG_TYPES_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/test_class.c000066400000000000000000000252361223300710500226600ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@ingroup test_msg * @file test_class.c * * Message class for testing parser and transports. * * @author Pekka Pessi * * @date Created: Tue Mar 5 11:57:20 2002 ppessi */ #include "config.h" #include #include #include #include #include #define TAG_NAMESPACE "tst" #include "test_class.h" #include #include #include "test_protos.h" #include extern msg_mclass_t const msg_test_mclass[1]; extern msg_mclass_t const *msg_test_default(void) { return msg_test_mclass; } #define msg_generic_update NULL /**@ingroup test_msg * @defgroup msg_test_request Request Line for Testing */ static msg_xtra_f msg_request_dup_xtra; static msg_dup_f msg_request_dup_one; msg_hclass_t msg_request_class[] = MSG_HEADER_CLASS(msg_, request, NULL, "", rq_common, single_critical, msg_request, msg_generic); /** Decode a request line */ issize_t msg_request_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { msg_request_t *rq = (msg_request_t *)h; char *uri, *version; if (msg_firstline_d(s, &uri, &version) < 0 || !uri || url_d(rq->rq_url, uri) < 0) return -1; rq->rq_method_name = s; rq->rq_version = version; return 0; } /**Encode a request line. */ issize_t msg_request_e(char b[], isize_t bsiz, msg_header_t const *h, int flags) { msg_request_t const *rq = (msg_request_t const *)h; return snprintf(b, bsiz, "%s " URL_FORMAT_STRING " %s" CRLF, rq->rq_method_name, URL_PRINT_ARGS(rq->rq_url), rq->rq_version); } isize_t msg_request_dup_xtra(msg_header_t const *h, isize_t offset) { isize_t rv = offset; msg_request_t const *rq = (msg_request_t const *)h; rv += url_xtra(rq->rq_url); rv += MSG_STRING_SIZE(rq->rq_method_name); rv += MSG_STRING_SIZE(rq->rq_version); return rv; } /** Duplicate one request header. */ char *msg_request_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra) { msg_request_t *rq = (msg_request_t *)dst; msg_request_t const *o = (msg_request_t const *)src; char *end = b + xtra; URL_DUP(b, end, rq->rq_url, o->rq_url); MSG_STRING_DUP(b, rq->rq_method_name, o->rq_method_name); MSG_STRING_DUP(b, rq->rq_version, o->rq_version); assert(b <= end); return b; } /**@ingroup test_msg * @defgroup msg_test_status Status Line for Testing */ static msg_xtra_f msg_status_dup_xtra; static msg_dup_f msg_status_dup_one; msg_hclass_t msg_status_class[1] = MSG_HEADER_CLASS(msg_, status, NULL, "", st_common, single_critical, msg_status, msg_generic); /** Parse status line */ issize_t msg_status_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { msg_status_t *st = (msg_status_t *)h; char *status, *phrase; unsigned long code; if (msg_firstline_d(s, &status, &phrase) < 0 || (code = strtoul(status, &status, 10)) >= 1000 || *status) return -1; st->st_status = code; st->st_phrase = phrase; st->st_version = s; return 0; } issize_t msg_status_e(char b[], isize_t bsiz, msg_header_t const *h, int flags) { msg_status_t const *st = (msg_status_t const *)h; int status = st->st_status; if (status > 999 || status < 100) status = 0; return snprintf(b, bsiz, "%s %03u %s" CRLF, st->st_version, status, st->st_phrase); } /** Extra size of a msg_status_t object. */ isize_t msg_status_dup_xtra(msg_header_t const *h, isize_t offset) { isize_t rv = offset; msg_status_t const *st = (msg_status_t const *)h; rv += MSG_STRING_SIZE(st->st_version); rv += MSG_STRING_SIZE(st->st_phrase); return rv; } /** Duplicate one status header. */ char *msg_status_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, isize_t xtra) { msg_status_t *st = (msg_status_t *)dst; msg_status_t const *o = (msg_status_t const *)src; char *end = b + xtra; MSG_STRING_DUP(b, st->st_version, o->st_version); st->st_status = o->st_status; MSG_STRING_DUP(b, st->st_phrase, o->st_phrase); assert(b <= end); (void)end; return b; } msg_hclass_t test_numeric_class[] = MSG_HEADER_CLASS(msg_, numeric, "Numeric", "", x_common, single, msg_generic, msg_generic); msg_hclass_t test_auth_class[] = MSG_HEADER_CLASS(msg_, auth, "Auth", "", au_params, append, msg_auth, msg_generic); /** Extract the message body, including separator line. * * @param[in,out] msg message object * @param[in,out] pub public message structure * @param[in] b buffer containing unparsed data * @param[in] bsiz buffer size * @param[in] eos true if buffer contains whole message * * @retval -1 error * @retval 0 message is incomplete * @retval other number of bytes extracted */ issize_t msg_test_extract_body(msg_t *msg, msg_pub_t *pub, char b[], isize_t bsiz, int eos) { msg_test_t *tst = (msg_test_t *)pub; ssize_t m = 0; size_t body_len; if (!(tst->msg_flags & MSG_FLG_BODY)) { /* We are looking at a potential empty line */ m = msg_extract_separator(msg, (msg_pub_t *)tst, b, bsiz, eos); if (m == 0 || m == -1) return m; tst->msg_flags |= MSG_FLG_BODY; b += m; bsiz -= m; } if (tst->msg_content_length) body_len = tst->msg_content_length->l_length; else if (MSG_IS_MAILBOX(tst->msg_flags)) /* message fragments */ body_len = 0; else if (eos) body_len = bsiz; else return -1; if (body_len == 0) { tst->msg_flags |= MSG_FLG_COMPLETE; return m; } if (m) return m; if ((m = msg_extract_payload(msg, (msg_pub_t *)tst, NULL, body_len, b, bsiz, eos) ) == -1) return -1; tst->msg_flags |= MSG_FLG_FRAGS; if (bsiz >= body_len) tst->msg_flags |= MSG_FLG_COMPLETE; return m; } msg_href_t const msg_content_length_href[1] = {{ msg_content_length_class, offsetof(msg_test_t, msg_content_length) }}; #include #include #include #include tagi_t *tsttag_filter(tagi_t *dst, tagi_t const f[], tagi_t const *src, void **bb); /** Tag class for test header tags. @HIDE */ tag_class_t tsthdrtag_class[1] = {{ sizeof(tsthdrtag_class), /* tc_next */ NULL, /* tc_len */ NULL, /* tc_move */ NULL, /* tc_xtra */ msghdrtag_xtra, /* tc_dup */ msghdrtag_dup, /* tc_free */ NULL, /* tc_find */ NULL, /* tc_snprintf */ msghdrtag_snprintf, /* tc_filter */ tsttag_filter, /* tc_ref_set */ t_ptr_ref_set, /* tc_scan */ msghdrtag_scan, }}; /** Tag class for TST header string tags. @HIDE */ tag_class_t tststrtag_class[1] = {{ sizeof(tststrtag_class), /* tc_next */ NULL, /* tc_len */ NULL, /* tc_move */ NULL, /* tc_xtra */ t_str_xtra, /* tc_dup */ t_str_dup, /* tc_free */ NULL, /* tc_find */ NULL, /* tc_snprintf */ t_str_snprintf, /* tc_filter */ NULL /* msgtag_str_filter */, /* tc_ref_set */ t_ptr_ref_set, /* tc_scan */ t_str_scan }}; /** Tag class for TST message tags. @HIDE */ tag_class_t tstmsgtag_class[1] = {{ sizeof(tstmsgtag_class), /* tc_next */ NULL, /* tc_len */ NULL, /* tc_move */ NULL, /* tc_xtra */ msgobjtag_xtra, /* tc_dup */ msgobjtag_dup, /* tc_free */ NULL, /* tc_find */ NULL, /* tc_snprintf */ msgobjtag_snprintf, /* tc_filter */ NULL /* tsttag_tst_filter */, /* tc_ref_set */ t_ptr_ref_set, }}; tag_typedef_t tsttag_header = {{ TAG_NAMESPACE, "header", tsthdrtag_class, 0 }}; tag_typedef_t tsttag_header_str = STRTAG_TYPEDEF(header_str); /** Filter a TST header structure. */ tagi_t *tsttag_filter(tagi_t *dst, tagi_t const f[], tagi_t const *src, void **bb) { tagi_t stub[2] = {{ NULL }}; tag_type_t sctt, tt = f->t_tag; msg_hclass_t *hc = (msg_hclass_t *)tt->tt_magic; assert(src); sctt = src->t_tag; if (sctt && sctt->tt_class == tstmsgtag_class) { msg_test_t const *tst = (msg_test_t const *)src->t_value; msg_mclass_t *mc = (msg_mclass_t *)tst->msg_ident; msg_header_t const **hh = (msg_header_t const **) msg_hclass_offset(mc, (msg_pub_t *)tst, hc); msg_header_t const *h; if (tst == NULL || (char *)hh >= ((char *)tst + tst->msg_size) || (char *)hh < (char const *)&tst->msg_request) return dst; h = *hh; if (h == NULL) return dst; stub[0].t_tag = tt; stub[0].t_value = (tag_value_t)h; src = stub; sctt = tt; } if (tt != sctt) return dst; if (!src->t_value) return dst; else if (dst) { return t_dup(dst, src, bb); } else { *bb = (char *)*bb + t_xtra(src, (size_t)*bb); return dst + 1; } } /** Add duplicates of headers from taglist to the TST message. */ int tst_add_tl(msg_t *msg, msg_test_t *tst, tag_type_t tag, tag_value_t value, ...) { tagi_t const *t; ta_list ta; ta_start(ta, tag, value); for (t = ta_args(ta); t; t = tl_next(t)) { if (!(tag = t->t_tag) || !(value = t->t_value)) continue; if (TSTTAG_P(tag)) { msg_hclass_t *hc = (msg_hclass_t *)tag->tt_magic; msg_header_t *h = (msg_header_t *)value, **hh; if (h == NULL) ; else if (h == MSG_HEADER_NONE) { /* Remove header */ hh = msg_hclass_offset(msg_mclass(msg), (msg_pub_t *)tst, hc); while (hh && *hh) msg_header_remove(msg, (msg_pub_t *)tst, *hh); } else if (msg_header_add_dup_as(msg, (msg_pub_t *)tst, hc, h) < 0) break; } else if (TSTTAG_STR_P(tag)) { msg_hclass_t *hc = (msg_hclass_t *)tag->tt_magic; char const *s = (char const *)value; if (s && msg_header_add_make(msg, (msg_pub_t *)tst, hc, s) < 0) break; } else if (tag == tsttag_header_str) { if (msg_header_add_str(msg, (msg_pub_t *)tst, (char const *)value) < 0) break; } } ta_end(ta); return t ? -1 : 0; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/test_class.h000066400000000000000000000130351223300710500226570ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef TEST_CLASS_H /** Defined when has been included. */ #define TEST_CLASS_H /**@ingroup test_msg * @file test_class.h * @brief Message and header classes for testing. * * @author Pekka Pessi * * @date Created: Thu Jun 29 15:58:06 2000 ppessi */ #ifndef URL_H #include #endif #ifndef MSG_H #include #endif #ifndef MSG_HEADER_H #include #endif #ifndef MSG_MIME_H #include #endif #ifndef MSG_MCLASS_H #include #endif SOFIA_BEGIN_DECLS #define MSG_TEST_PROTOCOL_TAG ((void *)(size_t)0xdeadbeef) #define MSG_TEST_VERSION_CURRENT "msg/1.0" extern msg_mclass_t const msg_test_mclass[1]; extern msg_href_t const msg_content_length_href[1]; typedef struct msg_request_s msg_request_t; typedef struct msg_status_s msg_status_t; /** Request line. */ struct msg_request_s { msg_common_t rq_common[1]; /**< Common fragment info */ msg_header_t *rq_next; /**< Link to next header */ char const *rq_method_name; /**< Method name */ url_t rq_url[1]; /**< RequestURI */ char const *rq_version; /**< Protocol version */ }; /** Status line. */ struct msg_status_s { msg_common_t st_common[1]; /**< Common fragment info */ msg_header_t *st_next; /**< Link to next (dummy) */ char const *st_version; /**< Protocol version */ int st_status; /**< Status code */ char const *st_phrase; /**< Status phrase */ }; /** Message object for tests. */ typedef struct msg_test_s { msg_common_t msg_common[1]; /**< For recursive inclusion */ msg_pub_t *msg_next; void *msg_user; /**< User data */ unsigned msg_size; unsigned msg_flags; msg_error_t *msg_error; msg_request_t *msg_request; msg_status_t *msg_status; /* === Headers start here */ msg_content_type_t *msg_content_type; /**< Content-Type */ msg_content_disposition_t *msg_content_disposition; /**< Content-Disposition */ msg_content_location_t *msg_content_location; /**< Content-Location */ msg_content_language_t *msg_content_language; /**< Content-Language */ msg_accept_t *msg_accept; /**< Accept */ msg_accept_charset_t *msg_accept_charset; /**< Accept-Charset */ msg_accept_encoding_t *msg_accept_encoding; /**< Accept-Encoding */ msg_accept_language_t *msg_accept_language; /**< Accept-Language */ msg_mime_version_t *msg_mime_version; /**< MIME-Version */ msg_content_md5_t *msg_content_md5; /**< Content-MD5 */ msg_content_encoding_t *msg_content_encoding; /**< Content-Encoding */ msg_content_length_t *msg_content_length; /**< Content-Length */ msg_auth_t *msg_auth; /**< Auth (testing) */ msg_numeric_t *msg_numeric; /**< Numeric (testing) */ /* === Headers end here */ msg_unknown_t *msg_unknown; msg_separator_t *msg_separator; msg_payload_t *msg_payload; msg_multipart_t *msg_multipart; } msg_test_t; union msg_test_u { msg_common_t sh_common[1]; struct { msg_common_t shn_common; msg_header_t *shn_next; } sh_header_next[1]; msg_request_t sh_request[1]; msg_status_t sh_status[1]; msg_accept_t sh_accept[1]; msg_accept_charset_t sh_accept_charset[1]; msg_accept_encoding_t sh_accept_encoding[1]; msg_accept_language_t sh_accept_language[1]; msg_content_disposition_t sh_content_disposition[1]; msg_content_encoding_t sh_content_encoding[1]; msg_content_id_t sh_content_id[1]; msg_content_md5_t sh_content_md5[1]; msg_content_language_t sh_content_language[1]; msg_content_length_t sh_content_length[1]; msg_content_location_t sh_content_location[1]; msg_content_type_t sh_content_type[1]; msg_mime_version_t sh_mime_version[1]; msg_generic_t sh_generic[1]; msg_numeric_t sh_numeric[1]; msg_list_t sh_list[1]; msg_auth_t sh_auth[1]; msg_separator_t sh_separator[1]; msg_payload_t sh_payload[1]; msg_unknown_t sh_unknown[1]; }; issize_t msg_test_extract_body(msg_t *, msg_pub_t *, char b[], isize_t bsiz, int eos); su_inline msg_test_t *msg_test_public(msg_t *msg) { return (msg_test_t *)msg_public(msg, MSG_TEST_PROTOCOL_TAG); } #define msg_auth_class test_auth_class #define msg_numeric_class test_numeric_class enum { msg_auth_hash = 22894, msg_numeric_hash = 24435 }; extern msg_hclass_t test_auth_class[1], test_numeric_class[1]; SOFIA_END_DECLS #endif /* !defined(TEST_CLASS_H) */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/test_inlined.c000066400000000000000000000022441223300710500231670ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2007 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE test_inlined.c * * Expand inlined test functions non-inline. * */ #include "config.h" #include #if SU_HAVE_INLINE extern int xyzzy; #else #undef SU_HAVE_INLINE #undef su_inline #define SU_HAVE_INLINE 1 #define su_inline #include "test_protos.h" #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/test_msg.c000066400000000000000000001462041223300710500223400ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005,2011 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@ingroup test_msg * * @CFILE test_msg.c * * Torture tests for message parser. * * @author Pekka Pessi * * @date Created: Tue Aug 21 15:18:26 2001 ppessi */ #include "config.h" #include "test_class.h" #include "test_protos.h" #include "sofia-sip/msg.h" #include "sofia-sip/msg_addr.h" #include "sofia-sip/msg_date.h" #include "sofia-sip/msg_parser.h" #include "sofia-sip/bnf.h" #include "sofia-sip/msg_mclass.h" #include "sofia-sip/msg_mclass_hash.h" #include #include #include #include #include #include static int test_flags = 0; #define TSTFLAGS test_flags #include char const name[] = "test_msg"; static int msg_time_test(void) { char buf[32]; char const *s; char date1900[] = "Mon, 1 Jan 1900 00:00:00 GMT"; char date1900_1[] = "Mon, 01 Jan 1900 00:00:01 GMT"; char date822[] = "Thursday, 01-Jan-70 00:00:01 GMT"; char date822b[] = "Wednesday, 09-Nov-99 23:12:40 GMT"; char date822c[] = "Wednesday, 01-Sep-04 23:12:40 GMT"; char date2822[] = "Monday, 01-Jan-1900 00:00:01 GMT"; char dateasc[] = "Mon Jan 1 00:00:01 1900"; msg_time_t now = msg_now(), date = now; BEGIN(); s = date1900; TEST_1(msg_date_d(&s, &date) == 0); TEST(date, 0); TEST_SIZE(msg_date_e(buf, sizeof(buf), date), strlen(date1900)); TEST_SIZE(msg_date_e(buf, sizeof(buf), 1), strlen(date1900_1)); TEST_S(buf, date1900_1); s = date822; TEST_1(msg_date_d(&s, &date) == 0); TEST(date, 2208988801U); s = date822b; TEST_1(msg_date_d(&s, &date) == 0); TEST(date, 3151177960U); s = date822c; TEST_1(msg_date_d(&s, &date) == 0); TEST(date, 3303069160U); s = date2822; TEST_1(msg_date_d(&s, &date) == 0); TEST(date, 1); s = dateasc; TEST_1(msg_date_d(&s, &date) == 0); TEST(date, 1); { char error1[] = "Mo"; char error2[] = "Mon, 1 Jan 19100 00:00:00 GMT"; char error3[] = "Mon, 1 Jan 1900 00:00:"; char error4[] = "Mon, 1 Jan 1900 25:00:00 GMT"; char noerror5[] = "Mon, 1 Jan 1899 24:00:00 GMT"; char error6[] = "Mon, 30 Feb 1896 23:59:59 GMT"; char noerror7[] = "Mon, 29 Feb 1896 23:59:59 GMT"; char error8[] = "Mon, 32 Jan 1900 24:00:00 GMT"; char error9[] = "Mon, 27 Fev 1900 24:00:00 GMT"; s = error1; TEST_1(msg_date_d(&s, &date) < 0); s = error2; TEST_1(msg_date_d(&s, &date) < 0); s = error3; TEST_1(msg_date_d(&s, &date) < 0); s = error4; TEST_1(msg_date_d(&s, &date) < 0); s = noerror5; TEST_1(msg_date_d(&s, &date) == 0); TEST(date, 0); s = error6; TEST_1(msg_date_d(&s, &date) < 0); s = noerror7; TEST_1(msg_date_d(&s, &date) == 0); TEST(date, 0); s = error8; TEST_1(msg_date_d(&s, &date) < 0); s = error9; TEST_1(msg_date_d(&s, &date) < 0); } { char error1[] = "4294967297"; char *s; msg_numeric_t x[1]; memset(x, 0, sizeof (x)); x->x_common->h_class = test_numeric_class; TEST_1(msg_numeric_d(NULL, (msg_header_t *)x, s = error1, strlen(error1)) < 0); } END(); } static int addr_test(void) { BEGIN(); /* It *will* fail. */ /* TEST(sizeof(socklen_t), sizeof(msg_addrlen(NULL))); */ END(); } int test_header_parsing(void) { BEGIN(); { /* Test quoting/unquoting */ su_home_t home[1] = { SU_HOME_INIT(home) }; char *quoted = "\"foo \\b\\a\\r\\\"\\\\\"extra"; char *unquoted; TEST_1(unquoted = msg_unquote_dup(home, quoted)); TEST_S(unquoted, "foo bar\"\\"); su_home_deinit(home); } { /* Test parameter list */ su_home_t home[1] = { SU_HOME_INIT(home) }; msg_param_t const *params = NULL; char str[] = ";uffe;duffe = \"entten\" ; doo = [::1] ", *s = str; char const canonic[] = ";uffe;duffe=\"entten\";doo=[::1]"; char *end = str + strlen(str); char b[sizeof(canonic) + 8]; TEST_1(msg_params_d(home, &s, ¶ms) >= 0); TEST_1(params != 0); TEST_P(s, end); TEST_S(params[0], "uffe"); TEST_S(params[1], "duffe=\042entten\042"); TEST_S(params[2], "doo=[::1]"); TEST_1(params[3] == NULL); TEST_SIZE(msg_params_e(NULL, 0, params), strlen(canonic)); TEST_SIZE(msg_params_e(b, sizeof(b), params), strlen(canonic)); TEST_S(b, canonic); TEST_S(msg_params_find(params, "uffe"), ""); TEST_S(msg_params_find(params, "uffe="), ""); TEST_S(msg_params_find(params, "duffe"), "\"entten\""); TEST_S(msg_params_find(params, "duffe="), "\"entten\""); TEST_S(msg_params_find(params, "doo"), "[::1]"); TEST_S(msg_params_find(params, "doo="), "[::1]"); TEST(msg_params_remove((msg_param_t *)params, "uffe"), 1); TEST_S(params[0], "duffe=\042entten\042"); TEST_S(params[1], "doo=[::1]"); TEST_1(params[2] == NULL); TEST(msg_params_remove((msg_param_t *)params, "doo"), 1); TEST_S(params[0], "duffe=\042entten\042"); TEST_1(params[1] == NULL); su_home_deinit(home); } { /* Test that parameter list of length MSG_PARAMS_N is handled correctly */ su_home_t home[1] = { SU_HOME_INIT(home) }; msg_param_t const *params = NULL; char list1[] = ";one;two;three;four;five;six;seven;eight", *s = list1; char list2[] = ";one;two;three;four;five;six;seven"; char list3[] = ";one;two;three;four;five;six;seven, humppaa"; char *end3 = strchr(list3, ','); char list4[] = ";one;two;three;four;five;six;seven;eight;nine;ten" ";eleven;twelve;thirteen;fourteen;fiveteen;sixteen"; char list5[] = ";one;two;three;four;five;six;seven;eight;nine;ten" ";eleven;twelve;thirteen;fourteen;fiveteen"; char list6[] = ";one;two;three;four;five;six;seven;eight;nine;ten" ";eleven;twelve;thirteen;fourteen;fiveteen;sixteen;seventeen"; int i; TEST_1(msg_params_d(home, &s, ¶ms) >= 0); TEST_1(params); for (i = 0; i < 8; i++) TEST_1(params[i]); TEST_1(params[8] == NULL); s = list2, params = NULL; TEST_1(msg_params_d(home, &s, ¶ms) >= 0); TEST_1(params); for (i = 0; i < 7; i++) TEST_1(params[i]); TEST_1(params[7] == NULL); s = list3; params = NULL; TEST_1(msg_params_d(home, &s, ¶ms) >= 0); TEST_S(s, end3); TEST_1(params); for (i = 0; i < 7; i++) TEST_1(params[i]); TEST_1(params[7] == NULL); s = list4; params = NULL; TEST_1(msg_params_d(home, &s, ¶ms) >= 0); TEST_1(params); for (i = 0; i < 16; i++) TEST_1(params[i]); TEST_1(params[16] == NULL); s = list5; params = NULL; TEST_1(msg_params_d(home, &s, ¶ms) >= 0); TEST_1(params); for (i = 0; i < 15; i++) TEST_1(params[i]); TEST_1(params[15] == NULL); s = list6 ; params = NULL; TEST_1(msg_params_d(home, &s, ¶ms) >= 0); TEST_1(params); for (i = 0; i < 17; i++) TEST_1(params[i]); TEST_1(params[17] == NULL); su_home_deinit(home); } { /* Test parameter lists */ su_home_t home[1] = { SU_HOME_INIT(home) }; unsigned i, j; msg_param_t const *p = NULL; char *master = ";0", *list, *end; for (i = 1; i < 256; i++) { master = su_sprintf(home, "%s; %u", master, i); TEST_1(master); list = end = su_strdup(home, master); TEST_1(msg_params_d(home, &end, &p) >= 0); TEST_S(end, ""); TEST_1(p); for (j = 0; j <= i; j++) { char number[10]; snprintf(number, sizeof number, "%u", j); TEST_S(p[j], number); } TEST_1(p[i + 1] == NULL); su_free(home, list); su_free(home, (void *)p), p = NULL; } master = ";0"; for (i = 1; i < 256; i++) { master = su_sprintf(home, "%s; %u", master, i); TEST_1(master); list = end = su_strdup(home, master); TEST_1(msg_params_d(NULL, &end, &p) >= 0); TEST_S(end, ""); TEST_1(p); for (j = 0; j <= i; j++) { char number[10]; snprintf(number, sizeof number, "%u", j); TEST_S(p[j], number); } TEST_1(p[i + 1] == NULL); su_free(home, list); su_free(NULL, (void *)p), p = NULL; } su_home_deinit(home); } { /* Test comma-separated list */ su_home_t home[1] = { SU_HOME_INIT(home) }; msg_list_t k1[1] = {{{{ 0 }}}}; char list1[] = "foo, bar, baz zi \"baz\""; TEST_1(msg_list_d(home, (msg_header_t *)k1, list1, strlen(list1)) >= 0); TEST_1(k1->k_items); TEST_S(k1->k_items[0], "foo"); TEST_S(k1->k_items[1], "bar"); TEST_S(k1->k_items[2], "baz zi\042baz\042"); TEST_1(!k1->k_items[3]); su_home_deinit(home); } { /* Test that list of length MSG_PARAMS_N is handled correctly */ su_home_t home[1] = { SU_HOME_INIT(home) }; msg_list_t k2[1] = {{{{ 0 }}}}; char list2[] = "one, two, three, four, five, six, seven, eight"; TEST_1( msg_list_d(home, (msg_header_t *)k2, list2, strlen(list2)) >= 0); TEST_1(k2->k_items); TEST_1(k2->k_items[7]); TEST_1(k2->k_items[8] == NULL); su_home_deinit(home); } { /* Test that list longer than MSG_PARAMS_N is handled correctly */ su_home_t home[1] = { SU_HOME_INIT(home) }; msg_list_t k3[1] = {{{{ 0 }}}}; char list3[] = "one, two, three, four, five, six, seven, eight, nine"; TEST_1( msg_list_d(home, (msg_header_t *)k3, list3, strlen(list3)) >= 0); TEST_1(k3->k_items); TEST_1(k3->k_items[7]); TEST_1(k3->k_items[8]); TEST_1(k3->k_items[9] == NULL); su_home_deinit(home); } { /* Test that long lists are handled correctly */ su_home_t home[1] = { SU_HOME_INIT(home) }; msg_param_t *k = NULL; char *s; char list1[] = "one, two, three, four, five, six, seven, eight"; char list2[] = "one, two, three, four, five, six, seven, eight"; char list3[] = "one, two, three, four, five, six, seven, eight"; char list4[] = "one, two, three, four, five, six, seven, eight, nine"; s = list1; TEST_1(msg_commalist_d(home, &s, &k, msg_token_scan) >= 0); TEST_1(k); TEST_1(k[7]); TEST_1(k[8] == NULL); s = list2; TEST_1(msg_commalist_d(home, &s, &k, msg_token_scan) >= 0); s = list3; TEST_1(msg_commalist_d(home, &s, &k, msg_token_scan) >= 0); s = list4; TEST_1(msg_commalist_d(home, &s, &k, msg_token_scan) >= 0); su_home_deinit(home); } { /* Test parameter lists */ su_home_t home[1] = { SU_HOME_INIT(home) }; unsigned i, j; msg_param_t *p = NULL; char *master = "0", *list, *end; for (i = 1; i < 256; i++) { master = su_sprintf(home, "%s, %u", master, i); TEST_1(master); list = end = su_strdup(home, master); TEST_1(msg_commalist_d(home, &end, &p, msg_token_scan) >= 0); TEST_S(end, ""); TEST_1(p); for (j = 0; j <= i; j++) { char number[10]; snprintf(number, sizeof number, "%u", j); TEST_S(p[j], number); } TEST_1(p[i + 1] == NULL); su_free(home, list); su_free(home, (void *)p), p = NULL; } su_home_deinit(home); } { /* Test that errors in lists are handled correctly */ su_home_t home[1] = { SU_HOME_INIT(home) }; msg_param_t *k = NULL; char *s; char list1[] = "one, two, three, four, five, six, seven, foo=\"eight"; char list2[] = "one, two, three,,@,$ four, five, six, seven, eight"; s = list1; TEST_1(msg_commalist_d(home, &s, &k, NULL) < 0); TEST_1(k == NULL); s = list2; TEST_1(msg_commalist_d(home, &s, &k, msg_token_scan) < 0); su_home_deinit(home); } { /* Test empty parameter list */ su_home_t home[1] = { SU_HOME_INIT(home) }; msg_list_t k4[1] = {{{{ 0 }}}}; char list4[] = ", ,\t,\r\n\t, , "; TEST_1( msg_list_d(home, (msg_header_t *)k4, list4, strlen(list4)) >= 0); TEST_1(k4->k_items == NULL); su_home_deinit(home); } { /* Test authentication headers */ su_home_t home[1] = { SU_HOME_INIT(home) }; msg_auth_t au[1] = {{{{ 0 }}}}; char s[] = "Basic foo = \"bar==\" ,, bar=baari," "baz=\"bof,\\\\ \\\" baff\", base\t64/ - is== ,,"; TEST_1(msg_auth_d(home, (msg_header_t *)au, s, strlen(s)) >= 0); TEST_S(au->au_scheme, "Basic"); TEST_1(au->au_params); TEST_S(au->au_params[0], "foo=\042bar==\042"); TEST_S(au->au_params[1], "bar=baari"); TEST_S(au->au_params[2], "baz=\042bof,\\\\ \\\042 baff\042"); TEST_S(au->au_params[3], "base 64/- is=="); TEST_1(!au->au_params[4]); su_home_deinit(home); } /* Test that msg_*_format() works */ { su_home_t home[1] = { SU_HOME_INIT(home) }; msg_content_type_t *c; c = msg_content_type_format(home, "%s/%s;%s;%s;%s;%s;%s;%s", "text", "plain", "charset=iso-8859-15", "format=flowed", "q=0.999", "msg-size=782572564", "name-space-url=\"http://www.nokia.com/foo\"", "foo=bar"); su_home_deinit(home); } { /* Test parameter handling */ su_home_t home[1] = { SU_HOME_INIT(home) }; msg_content_encoding_t *ce; ce = msg_content_encoding_make(home, "zip, zap, zup, lz, zl, zz, ll"); TEST_1(ce); TEST_S(msg_header_find_param(ce->k_common, "zz"), ""); TEST_S(msg_header_find_item(ce->k_common, "zz"), "zz"); TEST_P(msg_header_find_param(ce->k_common, "k"), NULL); TEST(msg_header_add_param(home, ce->k_common, "zip"), 0); TEST(msg_header_remove_param(ce->k_common, "zip"), 1); TEST_S(msg_header_find_param(ce->k_common, "zip"), ""); TEST(msg_header_remove_param(ce->k_common, "zip"), 1); TEST_P(msg_header_find_param(ce->k_common, "zip"), NULL); TEST(msg_header_remove_param(ce->k_common, "zip"), 0); TEST(msg_header_replace_param(home, ce->k_common, "zip=zap"), 0); TEST_S(msg_header_find_param(ce->k_common, "zip=1"), "zap"); TEST(msg_header_replace_param(home, ce->k_common, "zip=zup"), 1); TEST_S(msg_header_find_param(ce->k_common, "zip"), "zup"); su_home_deinit(home); } { char b[8]; TEST(msg_unquoted_e(NULL, 0, "\"\""), 6); TEST(msg_unquoted_e(b, 0, "\"\""), 6); TEST(msg_unquoted_e(b, 4, "\"\""), 6); TEST(msg_unquoted_e(b, 6, "\"\""), 6); TEST(memcmp(b, "\"\\\"\\\"\"", 6), 0); TEST(msg_unquoted_e(b, 4, "\""), 4); memset(b, 0, sizeof b); TEST(msg_unquoted_e(b, 1, "\"kuik"), 8); TEST(memcmp(b, "\"\0", 2), 0); TEST(msg_unquoted_e(b, 3, "\"kuik"), 8); TEST(memcmp(b, "\"\\\"\0", 4), 0); TEST(msg_unquoted_e(b, 7, "\"kuik"), 8); TEST(memcmp(b, "\"\\\"kuik\0", 8), 0); } END(); } int hash_test(void) { int i, j, hash = 0; msg_mclass_t const *mc = msg_test_mclass; msg_hclass_t *hc; BEGIN(); for (i = 0; i < mc->mc_hash_size; i++) { hc = mc->mc_hash[i].hr_class; if (hc == NULL) continue; hash = msg_header_name_hash(hc->hc_name, NULL); TEST(hash, hc->hc_hash); /* Cross-check hashes */ for (j = i + 1; j < mc->mc_hash_size; j++) { if (mc->mc_hash[j].hr_class == NULL) continue; if (hc->hc_hash == mc->mc_hash[j].hr_class->hc_hash) fprintf(stderr, "\t%s and %s have same hash\n", hc->hc_name, mc->mc_hash[j].hr_class->hc_name); TEST_1(hc->hc_hash != mc->mc_hash[j].hr_class->hc_hash); } } END(); } msg_t *read_msg(char const buffer[]) { return msg_make(msg_test_mclass, MSG_DO_EXTRACT_COPY, buffer, -1); } /**Check if header chain contains any loops. * * @return * Return 0 if no loop, -1 otherwise. */ static int msg_chain_loop(msg_header_t const *h) { msg_header_t const *h2; if (!h) return 0; for (h2 = h->sh_succ; h && h2 && h2->sh_succ; h = h->sh_succ) { if (h == h2 || h == h2->sh_succ) return 1; h2 = h2->sh_succ->sh_succ; if (h == h2) return 1; } return 0; } /** Check header chain consistency. * * @return * Return 0 if consistent, number of errors otherwise. */ static int msg_chain_errors(msg_header_t const *h) { if (msg_chain_loop(h)) return -1; for (; h; h = h->sh_succ) { if (h->sh_succ && h->sh_succ->sh_prev != &h->sh_succ) return -1; if (h->sh_prev && h != (*h->sh_prev)) return -1; } return 0; } int test_msg_parsing(void) { msg_t *msg, *orig; su_home_t *home; msg_test_t *tst, *otst; msg_request_t *request; msg_status_t *status; msg_content_location_t *location; msg_content_language_t *language; msg_accept_language_t *en, *se; msg_separator_t *separator; msg_payload_t *payload; BEGIN(); msg = read_msg("GET a-life HTTP/1.1" CRLF "Content-Length: 6" CRLF "Accept-Encoding: bzip2" CRLF "Accept-Language: en;q=0.8, fi, se ; q = 0.6" CRLF "Accept-Encoding: gzip" CRLF "Foo: bar" CRLF CRLF "test" CRLF); home = msg_home(msg); tst = msg_test_public(msg); TEST_1(msg); TEST_1(home); TEST_1(tst); TEST_P(tst->msg_error, NULL); TEST_1(tst->msg_accept_language); TEST_1(status = msg_status_make(home, "HTTP/1.1 200 Ok")); TEST(msg_header_insert(msg, (msg_pub_t *)tst, (msg_header_t *)status), 0); TEST_P(tst->msg_status, status); TEST_P(tst->msg_request, NULL); TEST_1(request = msg_request_make(home, "GET a-wife HTTP/1.0")); TEST(msg_header_insert(msg, (msg_pub_t *)tst, (msg_header_t *)request), 0); TEST_P(tst->msg_request, request); TEST_P(tst->msg_status, NULL); TEST_1(separator = msg_separator_make(home, "\r\n")); TEST(msg_header_insert(msg, (msg_pub_t *)tst, (msg_header_t *)separator), 0); TEST_P(tst->msg_separator, separator); TEST_P(separator->sep_common->h_succ, tst->msg_payload); /* Try to add a new payload */ TEST_1(payload = msg_payload_make(home, "foofaa\r\n")); TEST(msg_header_insert(msg, (msg_pub_t *)tst, (msg_header_t *)payload), 0); /* It is appended */ TEST_P(tst->msg_payload->pl_next, payload); TEST_P(tst->msg_payload->pl_common->h_succ, payload); { msg_param_t vs; int vi = 0; msg_param_t foo = "foo=bar"; vs = NULL; MSG_PARAM_MATCH(vs, foo, "foo"); TEST_S(vs, "bar"); vs = NULL; MSG_PARAM_MATCH(vs, foo, "fo"); TEST_P(vs, NULL); vi = 0; MSG_PARAM_MATCH_P(vi, foo, "foo"); TEST(vi, 1); MSG_PARAM_MATCH_P(vi, foo, "fo"); TEST(vi, 1); vi = 0; MSG_PARAM_MATCH_P(vi, foo, "fo"); TEST(vi, 0); } /* Test msg_fragment_clear_chain() */ en = tst->msg_accept_language; TEST_1(en->aa_common->h_data != NULL); msg_fragment_clear_chain((msg_header_t *)en->aa_next->aa_next); TEST_1(en->aa_common->h_data == NULL); TEST_1(en->aa_next->aa_common->h_data == NULL); TEST_1(en->aa_next->aa_next->aa_common->h_data == NULL); msg_destroy(msg); /* Bug #2624: */ msg = read_msg("GET /replaces HTTP/1.1" CRLF "Accept-Encoding: gzip" CRLF "Accept-Encoding: bzip2" CRLF "Accept-Encoding: deflate" CRLF "Accept-Language: en;q=0.8, fi, se ; q = 0.6" CRLF ); TEST_1(msg); tst = msg_test_public(msg); TEST_1(tst); { msg_accept_encoding_t *gzip, *bzip2, *deflate; msg_accept_encoding_t *lzss; msg_accept_language_t *en, *fi, *se; msg_accept_language_t *de, *sv, *sv_fi; TEST_1(gzip = tst->msg_accept_encoding); TEST_1(bzip2 = gzip->aa_next); TEST_1(deflate = bzip2->aa_next); TEST_1(gzip->aa_common->h_data); TEST_1(lzss = msg_accept_encoding_make(msg_home(msg), "lzss")); TEST(msg_header_replace(msg, (msg_pub_t *)tst, (void *)bzip2, (void *)lzss), 0); TEST_1(gzip->aa_common->h_data); TEST_1(en = tst->msg_accept_language); TEST_1(fi = en->aa_next); TEST_1(se = fi->aa_next); TEST_S(en->aa_value, "en"); TEST_M(en->aa_common->h_data, "Accept-Language: en;q=0.8, fi, se ; q = 0.6" CRLF, en->aa_common->h_len); TEST_P((char *)en->aa_common->h_data + en->aa_common->h_len, fi->aa_common->h_data); TEST(fi->aa_common->h_len, 0); TEST_P((char *)en->aa_common->h_data + en->aa_common->h_len, se->aa_common->h_data); TEST(se->aa_common->h_len, 0); TEST_1(de = msg_accept_language_make(msg_home(msg), "de;q=0.3")); TEST(msg_header_replace(msg, (msg_pub_t *)tst, (void *)se, (void *)de), 0); TEST_P(en->aa_common->h_data, NULL); TEST_P(en->aa_next, fi); TEST_P(fi->aa_next, de); TEST_P(de->aa_next, NULL); TEST_P(en->aa_common->h_succ, fi); TEST_P(en->aa_common->h_prev, &deflate->aa_common->h_succ); TEST_P(fi->aa_common->h_succ, de); TEST_P(fi->aa_common->h_prev, &en->aa_common->h_succ); TEST_P(de->aa_common->h_succ, NULL); TEST_P(de->aa_common->h_prev, &fi->aa_common->h_succ); TEST_P(se->aa_next, NULL); TEST_P(se->aa_common->h_succ, NULL); TEST_P(se->aa_common->h_prev, NULL); TEST_1(sv = msg_accept_language_make(msg_home(msg), "sv;q=0.6,sv_FI;q=0.7")); TEST_1(sv_fi = sv->aa_next); TEST(msg_header_replace(msg, (msg_pub_t *)tst, (void *)fi, (void *)sv), 0); TEST_P(en->aa_next, sv); TEST_P(sv->aa_next->aa_next, de); TEST_P(de->aa_next, NULL); TEST_P(en->aa_common->h_succ, sv); TEST_P(en->aa_common->h_prev, &deflate->aa_common->h_succ); TEST_P(sv->aa_common->h_succ, sv_fi); TEST_P(sv->aa_common->h_prev, &en->aa_common->h_succ); TEST_P(sv_fi->aa_common->h_succ, de); TEST_P(sv_fi->aa_common->h_prev, &sv->aa_common->h_succ); TEST_P(de->aa_common->h_succ, NULL); TEST_P(de->aa_common->h_prev, &sv_fi->aa_common->h_succ); TEST(msg_serialize(msg, (msg_pub_t *)tst), 0); } msg_destroy(msg); /* Bug #2429 */ orig = read_msg("GET a-life HTTP/1.1" CRLF "Foo: bar" CRLF "Content-Length: 6" CRLF CRLF "test" CRLF "extra stuff" CRLF); TEST_1(orig); otst = msg_test_public(orig); TEST_1(otst); msg = msg_copy(orig); msg_destroy(orig); tst = msg_test_public(msg); TEST_1(tst); home = msg_home(msg); TEST_1(request = msg_request_make(home, "GET a-wife HTTP/1.1")); TEST(msg_header_insert(msg, (msg_pub_t *)tst, (void *)request), 0); TEST_1(location = msg_content_location_make(home, "http://localhost:8080/wife")); TEST(msg_header_insert(msg, (msg_pub_t *)tst, (void *)location), 0); TEST(msg_serialize(msg, (msg_pub_t *)tst), 0); TEST_1(msg_prepare(msg) > 0); TEST_1(language = msg_content_language_make(home, "se-FI, fi-FI, sv-FI")); TEST(msg_header_insert(msg, (msg_pub_t *)tst, (void *)language), 0); TEST_1(se = msg_accept_language_make(home, "se, fi, sv")); TEST_1(se->aa_next); TEST_1(se->aa_next->aa_next); TEST(msg_header_insert(msg, (msg_pub_t *)tst, (void *)se), 0); TEST(msg_serialize(msg, (msg_pub_t *)tst), 0); TEST_1(msg_prepare(msg) > 0); { char const encoded[] = "GET a-wife HTTP/1.1\r\n"; TEST_SIZE(request->rq_common->h_len, strlen(encoded)); TEST_M(request->rq_common->h_data, encoded, request->rq_common->h_len); } { char const encoded[] = "Content-Location: http://localhost:8080/wife\r\n"; TEST_SIZE(location->g_common->h_len, strlen(encoded)); TEST_M(location->g_common->h_data, encoded, location->g_common->h_len); } { char const encoded[] = "Content-Language: se-FI, fi-FI, sv-FI\r\n"; TEST_SIZE(language->k_common->h_len, strlen(encoded)); TEST_M(language->k_common->h_data, encoded, language->k_common->h_len); } { char const encoded[] = "Accept-Language: se, fi, sv\r\n"; TEST_SIZE(se->aa_common->h_len, strlen(encoded)); TEST_M(se->aa_common->h_data, encoded, se->aa_common->h_len); TEST_P((char *)se->aa_common->h_data + se->aa_common->h_len, se->aa_next->aa_common->h_data); TEST_P((char *)se->aa_common->h_data + se->aa_common->h_len, se->aa_next->aa_next->aa_common->h_data); } { size_t size = SIZE_MAX; char *s; char body[66 * 15 + 1]; int i; msg_payload_t *pl; /* Bug #1726034 */ for (i = 0; i < 15; i++) strcpy(body + i * 66, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\r\n"); pl = msg_payload_make(msg_home(msg), body); TEST(msg_header_insert(msg, (msg_pub_t *)tst, (void *)pl), 0); s = msg_as_string(msg_home(msg), msg, NULL, 0, &size); TEST_S(s, "GET a-wife HTTP/1.1" CRLF "Foo: bar" CRLF "Content-Length: 6" CRLF "Content-Location: http://localhost:8080/wife\r\n" "Content-Language: se-FI, fi-FI, sv-FI\r\n" "Accept-Language: se, fi, sv\r\n" CRLF "test" CRLF "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" CRLF "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" CRLF "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" CRLF "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" CRLF "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" CRLF "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" CRLF "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" CRLF "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" CRLF "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" CRLF "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" CRLF "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" CRLF "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" CRLF "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" CRLF "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" CRLF "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" CRLF ); } msg_destroy(msg); END(); } static int test_warning(void) { msg_warning_t *w; su_home_t *home; char buf[64]; BEGIN(); TEST_1(home = su_home_new(sizeof *home)); TEST_1((w = msg_warning_make(home, "399 host:5060 \"Ok\", " "399 [::1]:39999 \"foo\\\" bar\""))); TEST(w->w_code, 399); TEST_S(w->w_host, "host"); TEST_S(w->w_port, "5060"); TEST_S(w->w_text, "Ok"); TEST_1(w = w->w_next); TEST(w->w_code, 399); TEST_S(w->w_host, "[::1]"); TEST_S(w->w_port, "39999"); TEST_S(w->w_text, "foo\" bar"); TEST_1(w->w_next == NULL); TEST_1(msg_warning_e(buf, sizeof buf, (msg_header_t *)w, 0) > 0); TEST_S(buf, "399 [::1]:39999 \"foo\\\" bar\""); su_home_unref(home); END(); } /* Test error handling */ int test_msg_error(void) { msg_t *msg; su_home_t *home; msg_test_t *tst; BEGIN(); msg = read_msg("GET a-life HTTP/1.1" CRLF "Content-Length: 6" CRLF "Content-Language: fi" CRLF "Content-Language: " CRLF "Accept-Language: en;q=0.8, fi, \"\", se ; q = 0.6" CRLF "Foo bar baf: bar" CRLF CRLF "test" CRLF); home = msg_home(msg); tst = msg_test_public(msg); TEST_1(msg); TEST_1(home); TEST_1(tst); TEST_1(tst->msg_error); msg_destroy(msg); END(); } int test_mclass(void) { msg_t *msg; su_home_t *home; msg_test_t *tst; msg_request_t *request; msg_status_t *status; msg_separator_t *separator; msg_payload_t *payload; msg_content_length_t *l; msg_content_language_t *la; msg_content_encoding_t *k0, *k; msg_unknown_t *foo; BEGIN(); /* Test that critical errors are signaled */ msg = read_msg("GET a-life HTTP/1.1" CRLF "Content-Length: 6bytes" CRLF "Content-Type: *" CRLF "Foo: bar" CRLF "Content-Encoding: identity" CRLF "Content-Language: en" CRLF "Content-Language: en-us" CRLF CRLF "test" CRLF); tst = msg_test_public(msg); TEST_1(msg); TEST_1(tst); TEST_1(MSG_HAS_ERROR(tst->msg_flags)); /* Content-Length is critical */ msg_destroy(msg); msg = read_msg("GET a-life HTTP/1.1" CRLF "Content-Length: 6" CRLF "Content-Type: *" CRLF "Foo: bar" CRLF "Content-Encoding: " CRLF /* XXX */ "Content-Language: en" CRLF "Content-Language: en-us" CRLF CRLF "test" CRLF); home = msg_home(msg); tst = msg_test_public(msg); TEST_1(msg); TEST_1(home); TEST_1(tst); TEST_SIZE(msg_iovec(msg, NULL, 0), 1); TEST_1(tst->msg_unknown); /* Foo */ TEST_1(tst->msg_content_type == NULL); TEST_1(tst->msg_error); /* Content-Type */ TEST_1(tst->msg_error->er_next == NULL); TEST_1(!MSG_HAS_ERROR(tst->msg_flags)); /* Content-type is not critical */ TEST_1(la = tst->msg_content_language); TEST_1(la->k_common->h_data); TEST_1(la->k_items); TEST_S(la->k_items[0], "en"); TEST_S(la->k_items[1], "en-us"); TEST_P(la->k_items[2], NULL); TEST_1(la->k_next); TEST_1(la->k_next->k_common->h_data); TEST_1(la->k_next->k_items == NULL); TEST(msg_header_add_make(msg, (msg_pub_t *)tst, msg_content_language_class, "en-gb"), 0); TEST_P(la, tst->msg_content_language); TEST_P(la->k_common->h_data, NULL); TEST_S(la->k_items[2], "en-gb"); TEST_P(la->k_next, NULL); TEST_1(status = msg_status_make(home, "HTTP/1.1 200 Ok")); TEST(msg_header_insert(msg, (msg_pub_t *)tst, (msg_header_t *)status), 0); TEST_P(tst->msg_status, status); TEST_P(tst->msg_request, NULL); TEST_1(request = msg_request_make(home, "GET a-wife HTTP/1.0")); TEST(msg_header_insert(msg, (msg_pub_t *)tst, (msg_header_t *)request), 0); TEST_P(tst->msg_request, request); TEST_P(tst->msg_status, NULL); TEST_1(separator = msg_separator_make(home, "\r\n")); TEST(msg_header_insert(msg, (msg_pub_t *)tst, (msg_header_t *)separator), 0); TEST_P(tst->msg_separator, separator); TEST_P(separator->sep_common->h_succ, tst->msg_payload); /* Try to add a new payload */ TEST_1(payload = msg_payload_make(home, "foofaa\r\n")); TEST(msg_header_insert(msg, (msg_pub_t *)tst, (msg_header_t *)payload), 0); /* The new payload should be appended */ TEST_P(tst->msg_payload->pl_next, payload); TEST_P(tst->msg_payload->pl_common->h_succ, payload); /* Try to add a new header */ TEST_1(l = msg_content_length_create(home, tst->msg_payload->pl_len + payload->pl_len)); TEST(msg_header_insert(msg, (msg_pub_t *)tst, (msg_header_t *)l), 0); /* The new header should be last before separator */ TEST_P(l->l_common->h_succ, separator); TEST_1(foo = tst->msg_unknown); TEST_S(foo->un_name, "Foo"); TEST_S(foo->un_value, "bar"); foo->un_value = "baz"; TEST_1(foo = msg_unknown_dup(home, foo)); TEST(msg_header_insert(msg, (msg_pub_t *)tst, (msg_header_t *)foo), 0); TEST_P(tst->msg_unknown->un_next, foo); TEST_1(k = msg_content_encoding_make(home, "gzip, compress")); k0 = tst->msg_content_encoding; TEST(msg_header_add_dup(msg, (msg_pub_t *)tst, (msg_header_t *)k), 0); TEST_P(k0, tst->msg_content_encoding); TEST_1(k0->k_items); TEST_S(k0->k_items[0], "gzip"); TEST_S(k0->k_items[1], "compress"); TEST_P(k0->k_items[2], NULL); TEST_1(k = msg_content_encoding_make(home, "gzip, deflate, compress")); TEST(msg_header_add_dup(msg, (msg_pub_t *)tst, (msg_header_t *)k), 0); TEST_P(k0, tst->msg_content_encoding); TEST_1(k0->k_items); TEST_S(k0->k_items[0], "gzip"); TEST_S(k0->k_items[1], "compress"); TEST_S(k0->k_items[2], "deflate"); TEST_P(k0->k_items[3], NULL); msg_destroy(msg); END(); } int test_copy(void) { msg_t *msg0, *msg, *msg1, *msg2; su_home_t *home; msg_test_t *tst0, *tst, *copy, *dup; msg_request_t *request; msg_common_t *h, *h_succ; msg_iovec_t iovec[8]; char const s[] = "GET /a-life HTTP/1.1" CRLF "Content-Length: 6" CRLF "Content-Type: *" CRLF "Foo: bar" CRLF "Content-Language: " CRLF CRLF "test" CRLF; BEGIN(); msg0 = read_msg(s); TEST_1(msg0); TEST_1(tst0 = msg_test_public(msg0)); TEST_SIZE(msg_iovec(msg0, iovec, 8), 1); TEST_1(msg = msg_copy(msg0)); TEST_1(copy = msg_test_public(msg)); TEST_1(copy->msg_request); TEST_1(tst0->msg_request); TEST_S(copy->msg_request->rq_url->url_path, tst0->msg_request->rq_url->url_path); TEST_S(copy->msg_request->rq_url->url_path, "a-life"); TEST_P(copy->msg_request->rq_url->url_path, tst0->msg_request->rq_url->url_path); msg_destroy(msg); TEST_1(msg = msg_dup(msg0)); TEST_1(dup = msg_test_public(msg)); TEST_1(dup->msg_request); TEST_1(tst0->msg_request); TEST_S(dup->msg_request->rq_url->url_path, tst0->msg_request->rq_url->url_path); TEST_S(dup->msg_request->rq_url->url_path, "a-life"); TEST_1(dup->msg_request->rq_url->url_path != tst0->msg_request->rq_url->url_path); msg_destroy(msg); TEST_1(msg = msg_copy(msg0)); msg_destroy(msg0); TEST_1(home = msg_home(msg)); TEST_1(tst = msg_test_public(msg)); TEST_1(tst->msg_unknown); /* Foo */ TEST_1(tst->msg_content_type == NULL); TEST_1(tst->msg_error); /* Content-Type */ TEST_1(!MSG_HAS_ERROR(tst->msg_flags)); /* Flags are not copied */ TEST_1(tst0->msg_request); TEST_1(request = tst->msg_request); TEST_P(tst0->msg_request->rq_url->url_path, request->rq_url->url_path); TEST_SIZE(msg_iovec(msg, iovec, 8), 1); TEST_S(iovec->siv_base, s); TEST_1(msg1 = msg_dup(msg)); TEST_1(tst = msg_test_public(msg1)); TEST_1(tst->msg_request); for (h = tst->msg_request->rq_common; h; h = h_succ) { if (h->h_prev) *h->h_prev = NULL; h_succ = (msg_common_t*)h->h_succ; h->h_succ = NULL; } TEST_1(msg2 = msg_copy(msg1)); msg_destroy(msg2); TEST_1(msg2 = msg_dup(msg1)); msg_destroy(msg2); msg_destroy(msg1); msg_destroy(msg); END(); } int test_mime(void) { msg_t *msg; su_home_t *home; int n; msg_test_t *tst; msg_header_t *h, *h_succ, *head; void *removed; msg_accept_t *ac, *ac0; msg_accept_charset_t *aa; msg_multipart_t *mp, *mp0, *mpX, *mpnew; msg_payload_t *pl; msg_content_type_t *c; msg_content_id_t *cid; msg_content_transfer_encoding_t *cte; char const s[] = "GET /a-life HTTP/1.1" CRLF "Accept: text/html;level=4;q=1" CRLF "Accept: text / plain;q=0.9" CRLF "Accept: text / calendar;q=0.0" CRLF "Accept: text/*, */*" CRLF "Accept-Charset: *;q=0.1, iso-latin-1, utf-8;q=0.9" CRLF "Accept-Encoding: gzip;q=0.9, deflate" CRLF "Accept-Encoding: , identity ," CRLF "Accept: */*;q=0.2" CRLF "Accept-Language: en;q=0.5, es;q=0.2, fr;q=0.9, fi, x-pig-latin" CRLF "Content-Language: fi, se" CRLF "Content-Language: en, de" CRLF "Content-Disposition: render; required" CRLF "Content-Encoding: gzip, deflate" CRLF "Content-Base: http://localhost/foo" CRLF "MIME-Version: 1.0" CRLF "Content-Type: multipart/alternative ; boundary=\"LaGqGt4BI6Ho\"" CRLF /* "Content-Length: 305" CRLF */ "Content-MD5: LLO7gLaGqGt4BI6HouiWng==" CRLF CRLF "test" CRLF CRLF /* 1 */ "--LaGqGt4BI6Ho" " " CRLF CRLF /* 2 */ "part 1" CRLF /* 3 */ CRLF /* 4 */ "--LaGqGt4BI6Ho" CRLF "Content-Type: text/plain ; charset = iso-8859-1" CRLF /* 5 */ "Content-ID: " CRLF /* 6 */ "Content-Transfer-Encoding: quoted-unreadable" CRLF /* 7 */ CRLF /* 8 */ "part 2" /* 9 */ CRLF "--LaGqGt4BI6Ho" /* 10 */ "Content-Type: text/html" CRLF /* 11 */ "Content-ID: <4SP77aQZ9z6Top2dvLqKPQ@localhost>" CRLF /* 12 */ CRLF /* 13 */ #define BODY3 "part 3" CRLF BODY3 /* 14 */ CRLF "--LaGqGt4BI6Ho" /* 15 */ "c: text/html" CRLF /* 16 */ "l: 9" CRLF /* 17 */ "e: identity" CRLF /* 18 */ CRLF /* 19 */ #define BODY4 "" CRLF BODY4 /* 20 */ CRLF "--LaGqGt4BI6Ho--" /* 21 */ CRLF; BEGIN(); msg = read_msg(s); home = msg_home(msg); tst = msg_test_public(msg); TEST_1(msg); TEST_1(home); TEST_1(tst); TEST_1(tst->msg_error == NULL); TEST_1((tst->msg_flags & MSG_FLG_ERROR) == 0); TEST_1(ac = tst->msg_accept); TEST_1(ac = ac->ac_next); TEST_S(ac->ac_type, "text/plain"); TEST_S(ac->ac_q, "0.9"); TEST_1(ac = msg_accept_dup(home, ac)); TEST_S(ac->ac_type, "text/plain"); TEST_S(ac->ac_q, "0.9"); TEST_S(tst->msg_accept->ac_next->ac_q, "0.9"); TEST_1(ac->ac_q != tst->msg_accept->ac_next->ac_q); TEST_1(ac = msg_accept_make(home, "text / plain")); ac->ac_q = "1.0"; TEST_1(ac = msg_accept_dup(home, ac0 = ac)); TEST_1(ac->ac_q != ac0->ac_q); for (h = (msg_header_t *)tst->msg_request; h; h = h->sh_succ) { TEST_1(h->sh_data); if (h->sh_succ) TEST_P((char*)h->sh_data + h->sh_len, h->sh_succ->sh_data); } TEST_1(aa = tst->msg_accept_charset); TEST_S(aa->aa_value, "*"); TEST_S(aa->aa_q, "0.1"); { msg_content_type_t *c = msg_content_type_make(home, "text/plain"); msg_accept_t *ac; TEST_1(c != NULL); ac = msg_accept_match(tst->msg_accept, c); TEST_1(ac != NULL); TEST_S(ac->ac_type, "text/plain"); ac = msg_accept_match(ac->ac_next, c); TEST_1(ac != NULL); TEST_S(ac->ac_type, "text/*"); ac = msg_accept_match(ac->ac_next, c); TEST_1(ac != NULL); TEST_S(ac->ac_type, "*/*"); su_free(home, c); c = msg_content_type_make(home, "text/calendar"); ac = msg_accept_match(tst->msg_accept, c); TEST_1(ac != NULL); TEST_S(ac->ac_type, "text/*"); } mp = msg_multipart_parse(home, tst->msg_content_type, tst->msg_payload); TEST_1(mp0 = mp); TEST_1(mp->mp_data); TEST(memcmp(mp->mp_data, CRLF "--" "LaGqGt4BI6Ho" CRLF, mp->mp_len), 0); TEST_1(mp->mp_common->h_data); TEST_M(mp->mp_common->h_data, CRLF "--" "LaGqGt4BI6Ho" " " CRLF, mp->mp_common->h_len); TEST_1(pl = mp->mp_payload); TEST_1(pl->pl_data); TEST_SIZE(strlen("part 1" CRLF), pl->pl_len); TEST(memcmp(pl->pl_data, "part 1" CRLF, pl->pl_len), 0); TEST_1(mp = mp->mp_next); TEST_1(mp->mp_data); TEST(memcmp(mp->mp_data, CRLF "--" "LaGqGt4BI6Ho" CR LF, mp->mp_len), 0); TEST_1(c = mp->mp_content_type); TEST_S(c->c_type, "text/plain"); TEST_S(c->c_subtype, "plain"); TEST_1(c->c_params); TEST_1(c->c_params[0]); TEST_S(c->c_params[0], "charset=iso-8859-1"); TEST_1(cid = mp->mp_content_id); TEST_1(cte = mp->mp_content_transfer_encoding); TEST_S(cte->g_string, "quoted-unreadable"); TEST_1(pl = mp->mp_payload); TEST_1(pl->pl_data); TEST_SIZE(strlen("part 2"), pl->pl_len); TEST(memcmp(pl->pl_data, "part 2", pl->pl_len), 0); TEST_1(mp = mp->mp_next); TEST_1(mp->mp_data); TEST_M(mp->mp_data, CRLF "--" "LaGqGt4BI6Ho" CRLF, mp->mp_len); TEST_1(pl = mp->mp_payload); TEST_1(pl->pl_data); TEST_SIZE(strlen(BODY3), pl->pl_len); TEST(memcmp(pl->pl_data, BODY3, pl->pl_len), 0); TEST_1(mp = mp->mp_next); TEST_1(mp->mp_data); TEST_M(mp->mp_data, CRLF "--" "LaGqGt4BI6Ho" CRLF, mp->mp_len); TEST_1(mp->mp_content_encoding); TEST_1(mp->mp_content_type); TEST_1(pl = mp->mp_payload); TEST_1(pl->pl_data); TEST_SIZE(strlen(BODY4), pl->pl_len); TEST(memcmp(pl->pl_data, BODY4, pl->pl_len), 0); mpX = mp; TEST_1(!(mp = mp->mp_next)); /* Test serialization */ head = NULL; TEST_1(h = msg_multipart_serialize(&head, mp0)); TEST_P((void *)h, mpX->mp_close_delim); TEST_1(!msg_chain_errors((msg_header_t *)mp0)); /* Remove chain */ for (h = (msg_header_t *)mp0, n = 0; h; h = h_succ, n++) { h_succ = h->sh_succ; if (h->sh_prev) *h->sh_prev = NULL; h->sh_prev = NULL; h->sh_succ = NULL; } TEST(n, 21); head = NULL; TEST_1(h = msg_multipart_serialize(&head, mp0)); TEST_P(h, mpX->mp_close_delim); TEST_1(!msg_chain_errors((msg_header_t *)mp0)); for (h = (msg_header_t *)mp0, n = 0; h; h = h_succ, n++) { h_succ = h->sh_succ; } TEST(n, 21); /* Add a new part to multipart */ mpnew = su_zalloc(home, sizeof(*mpnew)); TEST_1(mpnew); removed = mpX->mp_close_delim; mpX->mp_next = mpnew; mpX = mpnew; mpnew->mp_content_type = msg_content_type_make(home, "multipart/mixed"); TEST_1(mpnew->mp_content_type); TEST(msg_multipart_complete(msg_home(msg), tst->msg_content_type, mp0), 0); head = NULL; TEST_1(h = msg_multipart_serialize(&head, mp0)); TEST_P((void *)h, mpX->mp_close_delim); TEST_1(!msg_chain_errors((msg_header_t *)mp0)); for (h = (msg_header_t *)mp0, n = 0; h; h = h_succ, n++) { h_succ = h->sh_succ; TEST_1(h != removed); } TEST(n, 21 + 4); #define remove(h) \ (((*((msg_header_t*)(h))->sh_prev = ((msg_header_t*)(h))->sh_succ) ? \ (((msg_header_t*)(h))->sh_succ->sh_prev = ((msg_header_t*)(h))->sh_prev) \ : NULL), \ ((msg_header_t*)(h))->sh_succ = NULL, \ ((msg_header_t*)(h))->sh_prev = NULL) remove(mp0->mp_separator); remove(mp0->mp_next->mp_payload); remove(mp0->mp_next->mp_next->mp_content_type); remove(mp0->mp_next->mp_next->mp_next->mp_next->mp_close_delim); TEST_1(!msg_chain_errors((msg_header_t *)mp0)); head = NULL; TEST_1(h = msg_multipart_serialize(&head, mp0)); TEST_P(h, mpX->mp_close_delim); TEST_1(!msg_chain_errors((msg_header_t *)mp0)); for (h = (msg_header_t *)mp0, n = 0; h; h = h_succ, n++) { h_succ = h->sh_succ; if (h_succ == NULL) TEST_P(h, mpX->mp_close_delim); TEST_1(h != removed); } TEST(n, 21 + 4); /* Add an recursive multipart */ mpnew = su_zalloc(home, sizeof(*mpnew)); TEST_1(mpnew); mpX->mp_multipart = mpnew; mpnew->mp_content_type = msg_content_type_make(home, "text/plain"); TEST_1(mpnew->mp_content_type); TEST(msg_multipart_complete(msg_home(msg), tst->msg_content_type, mp0), 0); TEST_1(mpnew->mp_close_delim); head = NULL; TEST_1(h = msg_multipart_serialize(&head, mp0)); TEST_P(h, mpX->mp_close_delim); TEST_1(!msg_chain_errors((msg_header_t *)mp0)); for (h = (msg_header_t *)mp0, n = 0; h; h = h_succ, n++) h_succ = h->sh_succ; TEST(n, 21 + 9); su_home_check(home); su_home_zap(home); END(); } /** Test MIME encoding */ int test_mime2(void) { msg_t *msg; su_home_t *home; int n, m, len; msg_test_t *tst; msg_header_t *h; msg_accept_charset_t *aa; msg_multipart_t *mp; msg_content_type_t *c; msg_payload_t *pl; char const *end; char const s[] = "GET /a-life HTTP/1.1" CRLF "Accept: text/html;level=4;q=1" CRLF "Accept: text / plain;q=0.9" CRLF "Accept-Charset: *;q=0.1, iso-latin-1, utf-8;q=0.9" CRLF "Accept-Encoding: gzip;q=0.9, deflate" CRLF "Accept-Encoding: , identity ," CRLF "Accept: */*;q=0.2" CRLF "Accept-Language: en;q=0.5, es;q=0.2, fr;q=0.9, fi, x-pig-latin" CRLF "Content-Language: fi, se" CRLF "Content-Language: en, de" CRLF "Content-Disposition: render; required" CRLF "Content-Encoding: gzip, deflate" CRLF "Content-Base: http://localhost/foo" CRLF "MIME-Version: 1.0" CRLF "Content-Type: multipart/alternative ; boundary=\"LaGqGt4BI6Ho\"" CRLF "Content-MD5: LLO7gLaGqGt4BI6HouiWng==" CRLF CRLF "test" CRLF CRLF /* 1 */ "--LaGqGt4BI6Ho" " " CRLF CRLF /* 2 */ "part 1" CRLF /* 3 */ CRLF /* 4 */ "--LaGqGt4BI6Ho" CRLF "Content-Type: text/plain;charset=iso-8859-1" CRLF /* 5 */ "Content-ID: " CRLF /* 6 */ "Content-Transfer-Encoding: quoted-unreadable" CRLF /* 7 */ CRLF /* 8 */ "part 2" /* 9 */ CRLF "--LaGqGt4BI6Ho" /* 10 */ "Content-Type: text/html" CRLF /* 11 */ "Content-ID: <4SP77aQZ9z6Top2dvLqKPQ@localhost>" CRLF /* 12 */ CRLF /* 13 */ #define BODY3 "part 3" CRLF BODY3 /* 14 */ CRLF /* 15 */ "--LaGqGt4BI6Ho--" CRLF; char const part1[] = "This is text\n"; char const part2[] = "This is html"; char const part3[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; BEGIN(); msg = read_msg(s); home = msg_home(msg); tst = msg_test_public(msg); TEST_1(msg); TEST_1(home); TEST_1(tst); TEST_1(tst->msg_error == NULL); TEST_1((tst->msg_flags & MSG_FLG_ERROR) == 0); for (h = (msg_header_t *)tst->msg_request; h; h = h->sh_succ) { TEST_1(h->sh_data); if (h->sh_succ) TEST_P((char*)h->sh_data + h->sh_len, h->sh_succ->sh_data); } TEST_1(aa = tst->msg_accept_charset); TEST_S(aa->aa_value, "*"); TEST_S(aa->aa_q, "0.1"); TEST_1(c = tst->msg_content_type); TEST_1(tst->msg_payload); { su_home_t h0[1] = { SU_HOME_INIT(h0) }; pl = msg_payload_dup(h0, tst->msg_payload); TEST_1(pl); mp = msg_multipart_parse(home, c, pl); TEST_1(mp); for (n = 0, h = (msg_header_t *)mp; h; h = h->sh_succ, n++) h->sh_data = NULL, h->sh_len = 0; TEST(n, 15); n = msg_multipart_prepare(msg, mp, 0); TEST_1(end = strstr(s, "--LaGqGt4BI6Ho ")); len = strlen(end); TEST(len, n); TEST_1(mp = msg_multipart_dup(h0, mp)); su_home_check(h0); su_home_deinit(h0); } /* Test parsing without explicit boundary */ { su_home_t h0[1] = { SU_HOME_INIT(h0) }; pl = msg_payload_dup(h0, tst->msg_payload); TEST_1(pl); mp = msg_multipart_parse(h0, NULL, pl); TEST_1(mp); for (n = 0, h = (msg_header_t *)mp; h; h = h->sh_succ, n++) h->sh_data = NULL, h->sh_len = 0; TEST(n, 15); n = msg_multipart_prepare(msg, mp, 0); TEST_1(end = strstr(s, "--LaGqGt4BI6Ho ")); len = strlen(end); TEST(len, n); TEST_1(mp = msg_multipart_dup(h0, mp)); su_home_check(h0); su_home_deinit(h0); } /* Test parsing without preamble and explicit boundary */ { su_home_t h0[1] = { SU_HOME_INIT(h0) }; pl = msg_payload_dup(h0, tst->msg_payload); TEST_1(pl); n = strstr(pl->pl_data, "--LaGqGt4BI6Ho") - (char *)pl->pl_data; pl->pl_data = n + (char *)pl->pl_data; pl->pl_len -= n; len = pl->pl_len; mp = msg_multipart_parse(h0, NULL, pl); TEST_1(mp); for (n = 0, h = (msg_header_t *)mp; h; h = h->sh_succ, n++) h->sh_data = NULL, h->sh_len = 0; TEST(n, 15); n = msg_multipart_prepare(msg, mp, 0); TEST(len, n); TEST_1(mp = msg_multipart_dup(h0, mp)); su_home_check(h0); su_home_deinit(h0); } /* Test parsing without CR's */ { su_home_t h0[1] = { SU_HOME_INIT(h0) }; char *b; pl = msg_payload_dup(h0, tst->msg_payload); TEST_1(pl); /* Remove CRs */ b = pl->pl_data, len = pl->pl_len; for (n = m = 0; n < len; n++) { if ((b[m] = b[n]) != '\r') m++; } pl->pl_len = m; mp = msg_multipart_parse(h0, NULL, pl); TEST_1(mp); for (n = 0, h = (msg_header_t *)mp; h; h = h->sh_succ, n++) h->sh_data = NULL, h->sh_len = 0; TEST(n, 15); n = msg_multipart_prepare(msg, mp, 0); TEST_1(n > 0); TEST_1(mp = msg_multipart_dup(h0, mp)); su_home_check(h0); su_home_deinit(h0); } /* Create a new multipart from three parts */ TEST_1(c = msg_content_type_make(home, "multipart/related")); TEST_1(mp = msg_multipart_create(home, "text/plain", part1, strlen(part1))); TEST_1(mp->mp_next = msg_multipart_create(home, "text/html", part2, strlen(part2))); TEST_1(mp->mp_next->mp_next = msg_multipart_create(home, "application/octet-stream", part3, sizeof part3)); TEST(msg_multipart_complete(home, c, mp), 0); h = NULL; TEST_P(msg_multipart_serialize(&h, mp), mp->mp_next->mp_next->mp_close_delim); TEST_1(msg_multipart_prepare(msg, mp, 0)); TEST_1(mp = msg_multipart_dup(home, mp)); su_home_check(home); su_home_zap(home); END(); } /* Test serialization */ int test_serialize(void) { msg_t *msg; su_home_t *home; msg_test_t *tst; msg_mime_version_t *mime; msg_separator_t *sep; msg_payload_t *pl; msg_accept_encoding_t *aen; msg_accept_language_t *ala; char const s[] = "GET /a-life HTTP/1.1" CRLF "Accept-Language: fi" CRLF "Accept-Encoding: z0" CRLF "Accept-Language: se, de" CRLF "Accept-Encoding: z1, z2" CRLF "Accept-Language: en, sv" CRLF "Accept-Encoding: z3, z4" CRLF "Content-Length: 6" CRLF CRLF "test" CRLF; BEGIN(); msg = read_msg(s); TEST_1(msg); home = msg_home(msg); TEST_1(tst = msg_test_public(msg)); TEST(msg_chain_errors((msg_header_t *)tst->msg_request), 0); TEST_1(ala = tst->msg_accept_language->aa_next->aa_next); TEST(msg_header_remove(msg, (msg_pub_t *)tst, (msg_header_t *)ala), 0); TEST_S(ala->aa_value, "de"); TEST_1(ala = tst->msg_accept_language); TEST_1(ala = ala->aa_next); TEST_S(ala->aa_value, "se"); /* Make sure that cached encoding of se is reset */ TEST_1(ala->aa_common->h_data == NULL); TEST_1(ala->aa_common->h_len == 0); TEST_1(ala = ala->aa_next); TEST_S(ala->aa_value, "en"); /* Make sure that cached encoding of en is kept intact */ TEST_1(ala->aa_common->h_data != NULL); TEST_1(ala->aa_common->h_len != 0); TEST_1(aen = tst->msg_accept_encoding->aa_next->aa_next); TEST(msg_header_remove_all(msg, (msg_pub_t *)tst, (msg_header_t *)aen), 0); TEST_1(aen = tst->msg_accept_encoding); TEST_1(aen = aen->aa_next); TEST_S(aen->aa_value, "z1"); /* Make sure that cached encoding of z1 is reset */ TEST_1(aen->aa_common->h_data == NULL); TEST_1(aen->aa_common->h_len == 0); TEST_1(aen->aa_next == NULL); TEST_1(aen->aa_common->h_succ == (void *)ala); TEST_1(ala->aa_next->aa_common); TEST_1(ala->aa_next->aa_common->h_succ == (void *)tst->msg_content_length); TEST_1(mime = msg_mime_version_make(home, "1.0")); tst->msg_mime_version = mime; TEST(msg_serialize(msg, (msg_pub_t *)tst), 0); TEST(msg_chain_errors((msg_header_t *)tst->msg_request), 0); TEST_P(tst->msg_content_length->l_common->h_succ, mime); TEST_P(mime->g_common->h_succ, tst->msg_separator); msg_header_remove(msg, (msg_pub_t *)tst, (msg_header_t *)tst->msg_separator); TEST_1(sep = msg_separator_make(home, CRLF)); tst->msg_separator = sep; TEST(msg_serialize(msg, (msg_pub_t *)tst), 0); TEST(msg_chain_errors((msg_header_t *)tst->msg_request), 0); TEST_P(mime->g_common->h_succ, sep); TEST_P(sep->sep_common->h_succ, tst->msg_payload); msg_header_remove(msg, (msg_pub_t *)tst, (msg_header_t *)tst->msg_payload); TEST_1(pl = msg_payload_make(home, "foobar" CRLF)); pl->pl_next = tst->msg_payload; tst->msg_payload = pl; TEST(msg_serialize(msg, (msg_pub_t *)tst), 0); TEST(msg_chain_errors((msg_header_t *)tst->msg_request), 0); TEST_P(mime->g_common->h_succ, sep); TEST_P(sep->sep_common->h_succ, pl); TEST_P(pl->pl_common->h_succ, pl->pl_next); msg_destroy(msg); END(); } static int random_test(void) { struct { uint64_t low, mid, hi; } seed = { 0, 0, 0 }; uint8_t zeros[24] = { 0 }; uint8_t ones[24]; char token[33]; BEGIN(); memset(ones, 255, sizeof ones); TEST_SIZE(msg_random_token(token, 32, (void *)&seed, sizeof(seed)), 32); TEST_S(token, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); TEST_SIZE(msg_random_token(token, 32, zeros, 4), 7); TEST_S(token, "aaaaaaa"); TEST_SIZE(msg_random_token(token, 32, ones, 4), 7); /* Last char may vary.. */ token[6] = 0; TEST_S(token, "999999"); TEST_SIZE(msg_random_token(token, 32, zeros, 8), 13); TEST_S(token, "aaaaaaaaaaaaa"); TEST_SIZE(msg_random_token(token, 32, zeros, 12), 20); TEST_S(token, "aaaaaaaaaaaaaaaaaaaa"); END(); } void usage(int exitcode) { fprintf(stderr, "usage: %s [-v] [-a]\n", name); exit(exitcode); } int main(int argc, char *argv[]) { int retval = 0; int i; for (i = 1; argv[i]; i++) { if (strcmp(argv[i], "-v") == 0) test_flags |= tst_verbatim; else if (strcmp(argv[i], "-a") == 0) test_flags |= tst_abort; else usage(1); } #if HAVE_OPEN_C test_flags |= tst_verbatim; #endif retval |= msg_time_test(); fflush(stdout); retval |= addr_test(); fflush(stdout); retval |= hash_test(); fflush(stdout); retval |= random_test(); fflush(stdout); retval |= test_header_parsing(); fflush(stdout); retval |= test_msg_parsing(); fflush(stdout); retval |= test_warning(); fflush(stdout); retval |= test_msg_error(); fflush(stdout); retval |= test_mclass(); fflush(stdout); retval |= test_copy(); fflush(stdout); retval |= test_mime(); fflush(stdout); retval |= test_mime2(); fflush(stdout); retval |= test_serialize(); fflush(stdout); return retval; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/test_protos.h.in000066400000000000000000000241211223300710500235030ustar00rootroot00000000000000/**-*- c -*- * @ingroup msg * @internal @file test_protos.h.in * * Template for "test_protos.h". */ /* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef TEST_PROTOS_H /** Defined when has been included. */ #define TEST_PROTOS_H /**@ingroup test_msg * @file test_protos.h * * Prototypes and macros for dummy testing protocol headers. * * #AUTO# * * @author Pekka Pessi */ #include #include #include #ifndef MSG_HEADER_H #include #endif #ifndef MSG_MIME_PROTOS_H #include #endif #ifndef TEST_CLASS_H #include #endif SOFIA_BEGIN_DECLS /** Test if tag type marks a msg_test_t structure. @HIDE */ #define TSTTAG_P(tt) ((tt)->tt_class == tsthdrtag_class) /** Test if tag type marks a TST header string. @HIDE */ #define TSTTAG_STR_P(tt) ((tt)->tt_class == tststrtag_class) /** Test if tag type marks a TST header structure. @HIDE */ #define TSTTAG_TST_P(tt) ((tt)->tt_class == tstmsgtag_class) /** Test if tag item contains msg_test_t structure. @HIDE */ #define TSTTAGI_P(t) (TSTTAG_P((t)->t_tag)) /** Test if tag item contains a TST header string. @HIDE */ #define TSTTAGI_STR_P(t) (TSTTAG_STR_P((t)->t_tag)) /** Test if tag item contains a TST header structure. @HIDE */ #define TSTTAGI_TST_P(t) (TSTTAG_TST_P((t)->t_tag)) /** Tag class for TST headers */ extern tag_class_t tsthdrtag_class[1]; /** Tag class for string values of TST headers */ extern tag_class_t tststrtag_class[1]; /** Tag class for TST message */ extern tag_class_t tstmsgtag_class[1]; /**Tag list item for header string. * * The TSTTAG_HEADER_STR() macro is used to include a tag item containing a * header string in the tag list, e.g., * @code * TSTTAG_HEADER_STR("Priority: urgent"). * @endcode * * @param x pointer to a string, or NULL. * * @HIDE */ #define TSTTAG_HEADER(x) tsttag_header, tsttag_header_v((x)) /** Tag for header string */ extern tag_typedef_t tsttag_header; #define TSTTAG_HEADER_REF(x) tsttag_header_ref, tsttag_header_vr(&(x)) extern tag_typedef_t tsttag_header_ref; #if HAVE_INLINE su_inline tag_value_t tsttag_header_v(msg_header_t const *v) { return (tag_value_t)v; } su_inline tag_value_t tsttag_header_vr(msg_header_t const **vp) { return (tag_value_t)vp; } #else #define tsttag_header_v(v) (tag_value_t)(v) #define tsttag_header_vr(vp) (tag_value_t)(vp) #endif /**Tag list item for header string. * * The TSTTAG_HEADER_STR() macro is used to include a tag item containing a * header string in the tag list. * * @param x pointer to a string, or NULL. * * @HIDE */ #define TSTTAG_HEADER_STR(x) tsttag_header_str, tag_str_v((x)) /** Tag for header string */ extern tag_typedef_t tsttag_header_str; #define TSTTAG_HEADER_STR_REF(x) tsttag_header_str_ref, tag_str_vr(&(x)) extern tag_typedef_t tsttag_header_str_ref; #if HAVE_INLINE su_inline tag_value_t tsttag_tst_v(msg_test_t const *v) { return (tag_value_t)v; } su_inline tag_value_t tsttag_tst_vr(msg_test_t const **vp) { return (tag_value_t)vp; } #else #define tsttag_tst_v(v) (tag_value_t)(v) #define tsttag_tst_vr(vp) (tag_value_t)(vp) #endif /**@addtogroup test_msg_#xxxxxx#*//**@{*/ /** Parse a #xxxxxxx_xxxxxxx#. @internal */ msg_parse_f msg_#xxxxxx#_d; /** Print a #xxxxxxx_xxxxxxx#. @internal */ msg_print_f msg_#xxxxxx#_e; /**Header class for #xxxxxxx_xxxxxxx#. * * The header class msg_#xxxxxx#_class defines how a * #xxxxxxx_xxxxxxx# is parsed and printed. It also * contains methods used by message parser and other functions * to manipulate the msg_#xxxxxx#_t header structure. */ extern msg_hclass_t msg_#xxxxxx#_class[]; /**Initializer for structure msg_#xxxxxx#_t. * * A static msg_#xxxxxx#_t structure must be initialized * with the MSG_#XXXXXX#_INIT() macro. For instance, * @code * * msg_#xxxxxx#_t msg_#xxxxxx# = MSG_#XXXXXX#_INIT; * * @endcode * @HI */ #define MSG_#XXXXXX#_INIT() MSG_HDR_INIT(#xxxxxx#) /**Initialize a structure msg_#xxxxxx#_t. * * An msg_#xxxxxx#_t structure can be initialized with the * msg_#xxxxxx#_init() function/macro. For instance, * @code * * msg_#xxxxxx#_t msg_#xxxxxx#; * * msg_#xxxxxx#_init(&msg_#xxxxxx#); * * @endcode * @HI */ #if SU_HAVE_INLINE su_inline msg_#xxxxxx#_t *msg_#xxxxxx#_init(msg_#xxxxxx#_t x[1]) { return MSG_HEADER_INIT(x, msg_#xxxxxx#_class, sizeof(msg_#xxxxxx#_t)); } #else #define msg_#xxxxxx#_init(x) \ MSG_HEADER_INIT(x, msg_#xxxxxx#_class, sizeof(msg_#xxxxxx#_t)) #endif /**Test if header object is instance of msg_#xxxxxx#_t. * * The function msg_is_#xxxxxx#() returns true (nonzero) if * the header class is an instance of #xxxxxxx_xxxxxxx# * object and false (zero) otherwise. * * @param header pointer to the header structure to be tested * * @return * The function msg_is_x#xxxxxx#() returns true (nonzero) if * the header object is an instance of header #xxxxxx# and * false (zero) otherwise. */ #if SU_HAVE_INLINE su_inline int msg_is_#xxxxxx#(msg_header_t const *header) { return header && header->sh_class->hc_hash == msg_#xxxxxx#_hash; } #else int msg_is_#xxxxxx#(msg_header_t const *header); #endif #define msg_#xxxxxx#_p(h) msg_is_#xxxxxx#((h)) /**Duplicate (deep copy) @c msg_#xxxxxx#_t. * * The function msg_#xxxxxx#_dup() duplicates a header * structure @a hdr. If the header structure @a hdr * contains a reference (@c hdr->x_next) to a list of * headers, all the headers in the list are duplicated, too. * * @param home memory home used to allocate new structure * @param hdr header structure to be duplicated * * When duplicating, all parameter lists and non-constant * strings attached to the header are copied, too. The * function uses given memory @a home to allocate all the * memory areas used to copy the header. * * @par Example * @code * * #xxxxxx# = msg_#xxxxxx#_dup(home, tst->msg_#xxxxxx#); * * @endcode * * @return * The function msg_#xxxxxx#_dup() returns a pointer to the * newly duplicated msg_#xxxxxx#_t header structure, or NULL * upon an error. */ msg_#xxxxxx#_t *msg_#xxxxxx#_dup(su_home_t *home, msg_#xxxxxx#_t const *hdr); /**Copy a msg_#xxxxxx#_t header structure. * * The function msg_#xxxxxx#_copy() copies a header structure @a * hdr. If the header structure @a hdr contains a reference (@c * hdr->h_next) to a list of headers, all the headers in that * list are copied, too. The function uses given memory @a home * to allocate all the memory areas used to copy the header * structure @a hdr. * * @param home memory home used to allocate new structure * @param hdr pointer to the header structure to be duplicated * * When copying, only the header structure and parameter lists * attached to it are duplicated. The new header structure * retains all the references to the strings within the old @a * header, including the encoding of the old header, if present. * * @par Example * @code * * #xxxxxx# = msg_#xxxxxx#_copy(home, tst->msg_#xxxxxx#); * * @endcode * * @return * The function msg_#xxxxxx#_copy() returns a pointer to * newly copied header structure, or NULL upon an error. */ msg_#xxxxxx#_t *msg_#xxxxxx#_copy(su_home_t *home, msg_#xxxxxx#_t const *hdr); /**Make a header structure msg_#xxxxxx#_t. * * The function msg_#xxxxxx#_make() makes a new * msg_#xxxxxx#_t header structure. It allocates a new * header structure, and decodes the string @a s as the * value of the structure. * * @param home memory home used to allocate new header structure. * @param s string to be decoded as value of the new header structure * * @note This function is usually implemented as a macro calling * msg_header_make(). * * @return * The function msg_#xxxxxx#_make() returns a pointer to * newly maked msg_#xxxxxx#_t header structure, or NULL upon * an error. */ #if SU_HAVE_INLINE su_inline msg_#xxxxxx#_t *msg_#xxxxxx#_make(su_home_t *home, char const *s) { return (msg_#xxxxxx#_t *)msg_header_make(home, msg_#xxxxxx#_class, s); } #else msg_#xxxxxx#_t *msg_#xxxxxx#_make(su_home_t *home, char const *s); #endif /**Make a #xxxxxxx_xxxxxxx# from formatting result. * * The function msg_#xxxxxx#_format() makes a new * #xxxxxxx_xxxxxxx# object using formatting result as its * value. The function first prints the arguments according to * the format @a fmt specified. Then it allocates a new header * structure, and uses the formatting result as the header * value. * * @param home memory home used to allocate new header structure. * @param fmt string used as a printf()-style format * @param ... argument list for format * * @note This function is usually implemented as a macro calling * msg_header_format(). * * @return * The function msg_#xxxxxx#_format() returns a pointer to newly * makes header structure, or NULL upon an error. * * @HIDE */ #if SU_HAVE_INLINE su_inline #endif msg_#xxxxxx#_t *msg_#xxxxxx#_format(su_home_t *home, char const *fmt, ...) __attribute__((__format__ (printf, 2, 3))); #if SU_HAVE_INLINE su_inline msg_#xxxxxx#_t *msg_#xxxxxx#_format(su_home_t *home, char const *fmt, ...) { msg_header_t *h; va_list ap; va_start(ap, fmt); h = msg_header_vformat(home, msg_#xxxxxx#_class, fmt, ap); va_end(ap); return (msg_#xxxxxx#_t *)h; } #endif /** @} */ SOFIA_END_DECLS #endif /* !defined(TEST_PROTOS_H) */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/msg/test_table.c.in000066400000000000000000000026341223300710500232440ustar00rootroot00000000000000/**@ingroup test_msg * @IFILE test_table.c.in * * Template for . * * @date Created: Wed Feb 21 11:01:45 2001 ppessi */ /* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@ingroup test_msg * * @CFILE test_table.c * @brief Parser table used for testing. * * #AUTO# * * @author Pekka Pessi * * @date Created: Wed Jan 22 19:03:21 EET 2003 ppessi */ #include "config.h" #include #include #include "test_class.h" #include "test_protos.h" #include #include sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nea/000077500000000000000000000000001223300710500203155ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nea/ChangeLog000066400000000000000000000001471223300710500220710ustar00rootroot000000000000002005-07-18 Kai Vehmanen * Initial import of the module to Sofia-SIP tree. sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nea/Doxyfile.in000066400000000000000000000010551223300710500224310ustar00rootroot00000000000000PROJECT_NAME = "nea" OUTPUT_DIRECTORY = ../docs/html/nea INPUT = @srcdir@/nea.docs @srcdir@/sofia-sip @srcdir@ . @INCLUDE_PATH = . @srcdir@ @INCLUDE = ../docs/Doxyfile.conf EXCLUDE_PATTERNS = test*.c torture*.c TAGFILES += \ "../docs/su.doxytags=../su" \ "../docs/ipt.doxytags=../ipt" \ "../docs/bnf.doxytags=../bnf" \ "../docs/url.doxytags=../url" \ "../docs/msg.doxytags=../msg" \ "../docs/sip.doxytags=../sip" \ "../docs/nta.doxytags=../nta" GENERATE_TAGFILE = ../docs/nea.doxytags ALIASES += sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nea/Makefile.am000066400000000000000000000031111223300710500223450ustar00rootroot00000000000000# # Makefile.am for nea module # # Copyright (C) 2005,2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # ---------------------------------------------------------------------- # Header paths INCLUDES = -I$(srcdir)/../ipt -I../ipt \ -I$(srcdir)/../msg -I../msg \ -I$(srcdir)/../nta -I../nta \ -I$(srcdir)/../sip -I../sip \ -I$(srcdir)/../sresolv -I../sresolv \ -I$(srcdir)/../tport -I../tport \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su # ---------------------------------------------------------------------- # Build targets noinst_LTLIBRARIES = libnea.la TESTS = # ---------------------------------------------------------------------- # Rules for building the targets BUILT_SOURCES = nea_tag_ref.c nobase_include_sofia_HEADERS =\ sofia-sip/nea.h sofia-sip/nea_tag.h libnea_la_SOURCES = nea.c nea_event.c \ nea_server.c nea_debug.h nea_debug.c \ nea_tag.c nea_tag_ref.c COVERAGE_INPUT = $(libnea_la_SOURCES) $(include_sofia_HEADERS) LDADD = libnea.la \ ../nta/libnta.la \ ../ipt/libipt.la \ ../sip/libsip.la \ ../sresolv/libsresolv.la \ ../tport/libtport.la \ ../stun/libstun.la \ ../http/libhttp.la \ ../msg/libmsg.la \ ../url/liburl.la \ ../bnf/libbnf.la \ ../su/libsu.la # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST = nea.docs $(BUILT_SOURCES) # ---------------------------------------------------------------------- # Sofia specific rules include $(top_srcdir)/rules/sofia.am sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nea/Makefile.in000066400000000000000000001306611223300710500223710ustar00rootroot00000000000000# Makefile.in generated by automake 1.14 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 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 nea module # # Copyright (C) 2005,2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # ---------------------------------------------------------------------- # Header paths # common Makefile targets for libsofia-sip-ua(-glib) modules # ---------------------------------------------------------- # # run tests with valgrind # # Copyright (C) 2007 Nokia Corporation. # 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 file contains free software from Makefile.in by the Free Software # Foundation: # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 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. # # Generate lcov output # # # Copyright (C) 2007 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # # Silent compilation w/ Automake 1.9 or 1.10 # ---------------------------------------------------------- # Automake 1.9.6 is not clever enough to override suffix rules within if # if SOFIA_COMPILE_SILENT VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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@ TESTS = DIST_COMMON = $(top_srcdir)/rules/sofia.am \ $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am \ $(top_srcdir)/rules/silent.am $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(srcdir)/Doxyfile.in \ $(top_srcdir)/depcomp $(nobase_include_sofia_HEADERS) \ $(top_srcdir)/test-driver ChangeLog # Use with --enable-ndebug @NDEBUG_TRUE@am__append_1 = -DNDEBUG @HAVE_GENPNG_TRUE@@HAVE_LCOV_TRUE@am__append_2 = --frames @HAVE_LCOV_TRUE@am__append_3 = lcov lcov-report lcov-rerun clean-lcov covcheck uncovered subdir = libsofia-sip-ua/nea ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(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)/m4/sac-coverage.m4 \ $(top_srcdir)/m4/sac-general.m4 \ $(top_srcdir)/m4/sac-openssl.m4 \ $(top_srcdir)/m4/sac-pkg-config.m4 $(top_srcdir)/m4/sac-su2.m4 \ $(top_srcdir)/m4/sac-tport.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libsofia-sip-ua/su/sofia-sip/su_configure.h CONFIG_CLEAN_FILES = Doxyfile CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libnea_la_LIBADD = am_libnea_la_OBJECTS = nea.lo nea_event.lo nea_server.lo nea_debug.lo \ nea_tag.lo nea_tag_ref.lo libnea_la_OBJECTS = $(am_libnea_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) -I$(top_builddir)/libsofia-sip-ua/su/sofia-sip depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f 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) 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 = $(libnea_la_SOURCES) DIST_SOURCES = $(libnea_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)$(include_sofiadir)" HEADERS = $(nobase_include_sofia_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)` 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=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ 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 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 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CHECK_CFLAGS = @CHECK_CFLAGS@ CHECK_LIBS = @CHECK_LIBS@ COVERAGE_FLAGS = @COVERAGE_FLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CWFLAG = @CWFLAG@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV = @GCOV@ GENHTML = @GENHTML@ GENPNG = @GENPNG@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GLIB_VERSION = @GLIB_VERSION@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVER_SOFIA_SIP_UA_AGE = @LIBVER_SOFIA_SIP_UA_AGE@ LIBVER_SOFIA_SIP_UA_CUR = @LIBVER_SOFIA_SIP_UA_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_AGE = @LIBVER_SOFIA_SIP_UA_GLIB_AGE@ LIBVER_SOFIA_SIP_UA_GLIB_CUR = @LIBVER_SOFIA_SIP_UA_GLIB_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_REV = @LIBVER_SOFIA_SIP_UA_GLIB_REV@ LIBVER_SOFIA_SIP_UA_GLIB_SOVER = @LIBVER_SOFIA_SIP_UA_GLIB_SOVER@ LIBVER_SOFIA_SIP_UA_REV = @LIBVER_SOFIA_SIP_UA_REV@ LIBVER_SOFIA_SIP_UA_SOVER = @LIBVER_SOFIA_SIP_UA_SOVER@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MINGW_ENVIRONMENT = @MINGW_ENVIRONMENT@ MKDIR_P = @MKDIR_P@ MOSTLYCLEANFILES = @MOSTLYCLEANFILES@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ RANLIB = @RANLIB@ REPLACE_LIBADD = @REPLACE_LIBADD@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ SOFIA_GLIB_CFLAGS = @SOFIA_GLIB_CFLAGS@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ SOFIA_PLAT_CFLAGS = @SOFIA_PLAT_CFLAGS@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ VERSION = @VERSION@ VER_LIBSOFIA_SIP_UA_MAJOR_MINOR = @VER_LIBSOFIA_SIP_UA_MAJOR_MINOR@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ include_sofiadir = @include_sofiadir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ openssl_CFLAGS = @openssl_CFLAGS@ openssl_LIBS = @openssl_LIBS@ 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@ INCLUDES = -I$(srcdir)/../ipt -I../ipt \ -I$(srcdir)/../msg -I../msg \ -I$(srcdir)/../nta -I../nta \ -I$(srcdir)/../sip -I../sip \ -I$(srcdir)/../sresolv -I../sresolv \ -I$(srcdir)/../tport -I../tport \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su # ---------------------------------------------------------------------- # Build targets noinst_LTLIBRARIES = libnea.la # ---------------------------------------------------------------------- # Rules for building the targets BUILT_SOURCES = nea_tag_ref.c nobase_include_sofia_HEADERS = \ sofia-sip/nea.h sofia-sip/nea_tag.h libnea_la_SOURCES = nea.c nea_event.c \ nea_server.c nea_debug.h nea_debug.c \ nea_tag.c nea_tag_ref.c COVERAGE_INPUT = $(libnea_la_SOURCES) $(include_sofia_HEADERS) LDADD = libnea.la ../nta/libnta.la ../ipt/libipt.la ../sip/libsip.la \ ../sresolv/libsresolv.la ../tport/libtport.la \ ../stun/libstun.la ../http/libhttp.la ../msg/libmsg.la \ ../url/liburl.la ../bnf/libbnf.la ../su/libsu.la \ $(openssl_LIBS) # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST = nea.docs $(BUILT_SOURCES) sofiasrcdir = ${top_srcdir}/libsofia-sip-ua sofiabuilddir = ${top_builddir}/libsofia-sip-ua AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(SOFIA_CFLAGS) \ $(openssl_CFLAGS) $(SOFIA_PLAT_CFLAGS) $(am__append_1) SOFIA_COVERAGE = $(COVERAGE_FLAGS) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files TAG_AWK = ${sofiasrcdir}/su/tag_dll.awk SUFFIXES = _tag_ref.c _tag.c INTERNAL_INCLUDES = \ -I${sofiasrcdir}/features -I${sofiabuilddir}/features \ -I${sofiasrcdir}/ipt -I${sofiabuilddir}/ipt \ -I${sofiasrcdir}/iptsec -I${sofiabuilddir}/iptsec \ -I${sofiasrcdir}/bnf -I${sofiabuilddir}/bnf \ -I${sofiasrcdir}/http -I${sofiabuilddir}/http \ -I${sofiasrcdir}/msg -I${sofiabuilddir}/msg \ -I${sofiasrcdir}/nth -I${sofiabuilddir}/nth \ -I${sofiasrcdir}/nta -I${sofiabuilddir}/nta \ -I${sofiasrcdir}/nea -I${sofiabuilddir}/nea \ -I${sofiasrcdir}/nua -I${sofiabuilddir}/nua \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sdp -I${sofiabuilddir}/sdp \ -I${sofiasrcdir}/sip -I${sofiabuilddir}/sip \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sresolv -I${sofiabuilddir}/sresolv \ -I${sofiasrcdir}/tport -I${sofiabuilddir}/tport \ -I${sofiasrcdir}/stun -I${sofiabuilddir}/stun \ -I${sofiasrcdir}/url -I${sofiabuilddir}/url \ -I${sofiasrcdir}/su -I${sofiabuilddir}/su PHONY = built-sources clean-built-sources $(am__append_3) VALGRIND = valgrind VALGRINDFLAGS = --tool=memcheck # Scripts @HAVE_LCOV_TRUE@LCOV_UNCOVERED = ${top_srcdir}/scripts/uncovered @HAVE_LCOV_TRUE@LCOV_REPORT = ${top_srcdir}/scripts/lcov-report # Report directory @HAVE_LCOV_TRUE@lcovdir = ${top_builddir}/lcov # Options @HAVE_LCOV_TRUE@GENHTML_OPTIONS = --show-details --legend \ @HAVE_LCOV_TRUE@ $(am__append_2) # Fancy shell command that expands to directory relative to top_builddir @HAVE_LCOV_TRUE@expand_subdir = `pwd|sed "s'\`cd ${top_builddir};pwd\`''"` SOFIA_SILENT = @ LIBTOOL_FLAGS = --silent # From Automake 1.9.6 - LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(LIBTOOL_FLAGS) \ $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) LINK = ${SOFIA_SILENT}test "${SOFIA_SILENT}" != @ || echo ' LINK $@'; \ $(LIBTOOL) --tag=CC --mode=link $(LIBTOOL_FLAGS) \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: _tag_ref.c _tag.c .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.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 libsofia-sip-ua/nea/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu libsofia-sip-ua/nea/Makefile .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.am: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): Doxyfile: $(top_builddir)/config.status $(srcdir)/Doxyfile.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ 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}; \ } libnea.la: $(libnea_la_OBJECTS) $(libnea_la_DEPENDENCIES) $(EXTRA_libnea_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libnea_la_OBJECTS) $(libnea_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nea.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nea_debug.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nea_event.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nea_server.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nea_tag.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nea_tag_ref.Plo@am__quote@ .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.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) '$<'` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-nobase_include_sofiaHEADERS: $(nobase_include_sofia_HEADERS) @$(NORMAL_INSTALL) @list='$(nobase_include_sofia_HEADERS)'; test -n "$(include_sofiadir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(include_sofiadir)'"; \ $(MKDIR_P) "$(DESTDIR)$(include_sofiadir)" || exit 1; \ fi; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo " $(MKDIR_P) '$(DESTDIR)$(include_sofiadir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(include_sofiadir)/$$dir"; }; \ echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(include_sofiadir)/$$dir'"; \ $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(include_sofiadir)/$$dir" || exit $$?; }; \ done uninstall-nobase_include_sofiaHEADERS: @$(NORMAL_UNINSTALL) @list='$(nobase_include_sofia_HEADERS)'; test -n "$(include_sofiadir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ dir='$(DESTDIR)$(include_sofiadir)'; $(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; \ else \ 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: $(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-TESTS check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(include_sofiadir)"; 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: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) -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: 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) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) 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) @HAVE_LCOV_FALSE@clean-local: clean: clean-am clean-am: clean-generic clean-libtool clean-local \ clean-noinstLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -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-nobase_include_sofiaHEADERS 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 -rf ./$(DEPDIR) -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-nobase_include_sofiaHEADERS .MAKE: all check check-am install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-generic clean-libtool clean-local \ 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-nobase_include_sofiaHEADERS 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 \ uninstall-nobase_include_sofiaHEADERS built-sources: $(BUILT_SOURCES) clean-built-sources: -rm -rf $(BUILT_SOURCES) $(BUILT_SOURCES:%=$(srcdir)/%) *_tag_ref.c: $(TAG_AWK) _tag.c_tag_ref.c: $(AWK) -f $(TAG_AWK) NODLL=1 $(TAG_DLL_FLAGS) REF=$@ $< ../bnf/libbnf.la ../http/libhttp.la ../ipt/libipt.la ../iptsec/libiptsec.la \ ../msg/libmsg.la ../nea/libnea.la ../nta/libnta.la ../nth/libnth.la \ ../nua/libnua.la ../sdp/libsdp.la ../sip/libsip.la ../soa/libsoa.la \ ../sresolv/libsresolv.la ../stun/libstun.la ../su/libsu.la \ ../tport/libtport.la ../url/liburl.la: cd $(@D) && $(MAKE) $(@F) checklib: $(noinst_LTLIBRARIES) $(check_LTLIBRARIES) valcheck: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) valcheck-am valcheck-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS # Run tests with valgrind in valcheck-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ list='$(TESTS)'; \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ if case $$tst in \ run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ $${dir}$$tst ;; \ esac ; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ echo "XPASS: $$tst"; \ ;; \ *) \ echo "PASS: $$tst"; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xfail=`expr $$xfail + 1`; \ echo "XFAIL: $$tst"; \ ;; \ *) \ failed=`expr $$failed + 1`; \ echo "FAIL: $$tst"; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ echo "SKIP: $$tst"; \ fi; \ done; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="All $$all tests passed"; \ else \ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all tests failed"; \ else \ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ skipped="($$skip tests were not run)"; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ report=""; \ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ report="Please report to $(PACKAGE_BUGREPORT)"; \ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ echo "$$dashes"; \ echo "$$banner"; \ test -z "$$skipped" || echo "$$skipped"; \ test -z "$$report" || echo "$$report"; \ echo "$$dashes"; \ test "$$failed" -eq 0; \ else :; fi # # Generate pretty coverage report (unless it has been already done) # @HAVE_LCOV_TRUE@lcov: @HAVE_LCOV_TRUE@ @-test -r ${lcovdir}${expand_subdir}/lcov.info \ @HAVE_LCOV_TRUE@ || make lcov-report # Generate pretty coverage report based on current coverage data @HAVE_LCOV_TRUE@lcov-report: @HAVE_LCOV_TRUE@ sub=${expand_subdir} odir=${lcovdir}$$sub ; \ @HAVE_LCOV_TRUE@ rm -rf $$odir ; mkdir -p $$odir && \ @HAVE_LCOV_TRUE@ ${LCOV_REPORT} ${GENHTML_OPTIONS} \ @HAVE_LCOV_TRUE@ --title "${PACKAGE_NAME}-${PACKAGE_VERSION}$$sub" \ @HAVE_LCOV_TRUE@ --srcdir=${srcdir} -o $$odir # Rerun checks before generating report @HAVE_LCOV_TRUE@lcov-rerun: clean-lcov @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) lcov-report # Show all uncovered lines as errors @HAVE_LCOV_TRUE@uncovered: @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} # Run check in current dir and show all uncovered lines as errors @HAVE_LCOV_TRUE@covcheck: @HAVE_LCOV_TRUE@ -find . -name "*.gcda" | xargs rm -rf @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} @HAVE_LCOV_TRUE@clean-local:: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true @HAVE_LCOV_TRUE@clean-lcov: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true # Rules from depend2.am (GENERIC = TRUE, SUBDIROBJ = FALSE, %FASTDEP% = am_fastdepCC) silenced. .c.o: @test "${SOFIA_SILENT}" != @ || echo ' COMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(COMPILE) -c -o $@ $< .c.lo: @test "${SOFIA_SILENT}" != @ || echo ' LTCOMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(LTCOMPILE) -c -o $@ $< # endif # ---------------------------------------------------------------------- # Sofia specific rules # 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: sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nea/nea.c000066400000000000000000000354461223300710500212400ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE nea.c Nokia Event Client API agent implementation. * * @author Pekka Pessi * * @date Created: Wed Feb 14 18:32:58 2001 ppessi */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #define SU_TIMER_ARG_T struct nea_s #define NTA_LEG_MAGIC_T struct nea_s #define NTA_OUTGOING_MAGIC_T struct nea_s #define NEA_TIMER_DELTA 2 /* time to resubscribe without expiration */ #define EXPIRES_DEFAULT 3600 #include #include "sofia-sip/nea.h" struct nea_s { su_home_t nea_home[1]; su_timer_t *nea_timer; nta_agent_t *nea_agent; nta_leg_t *nea_leg; nta_outgoing_t *nea_oreq; /**< Outstanding request */ sip_to_t *nea_to; /**< The other end of subscription :) */ nea_notify_f nea_callback; /**< Notify callback */ nea_magic_t *nea_context; /**< Application context */ sip_contact_t *nea_contact; /**< */ sip_expires_t *nea_expires; /**< Proposed expiration time */ nea_state_t nea_state; /**< State of our subscription */ sip_time_t nea_deadline; /**< When our subscription expires */ tagi_t *nea_args; unsigned nea_dialog : 1; /**< Dialog has been established */ unsigned nea_notify_received : 1; unsigned nea_terminating : 1; unsigned nea_strict_3265 : 1; /**< Strict mode */ }; int details = 0; static int process_nea_request(nea_t *nea, nta_leg_t *leg, nta_incoming_t *ireq, sip_t const *sip); static int handle_notify(nta_leg_magic_t *lmagic, nta_leg_t *leg, nta_incoming_t *ireq, sip_t const *sip); static int response_to_subscribe(nea_t *nea, nta_outgoing_t *req, sip_t const *sip); static int response_to_unsubscribe(nea_t *nea, nta_outgoing_t *req, sip_t const *sip); static void nea_expires_renew(su_root_magic_t *magic, su_timer_t *timer, nea_t *nea); /* ---------------------------------------------------------- */ /** Create a event watcher object. * */ nea_t *nea_create(nta_agent_t *agent, su_root_t *root, nea_notify_f no_callback, nea_magic_t *context, tag_type_t tag, tag_value_t value, ...) { nea_t *nea = NULL; ta_list ta; int have_from, have_to, have_contact; sip_expires_t const *expires = NULL; char const *expires_str = NULL; sip_method_t method = sip_method_subscribe; char const *SUBSCRIBE = "SUBSCRIBE"; char const *method_name = SUBSCRIBE; ta_start(ta, tag, value); have_to = tl_find(ta_args(ta), siptag_to) || tl_find(ta_args(ta), siptag_to_str); have_from = tl_find(ta_args(ta), siptag_from) || tl_find(ta_args(ta), siptag_from_str); have_contact = tl_find(ta_args(ta), siptag_contact) || tl_find(ta_args(ta), siptag_contact_str); if (have_to && (nea = su_home_new(sizeof(nea_t)))) { su_home_t *home = nea->nea_home; sip_contact_t *m = nta_agent_contact(agent); sip_from_t *from; sip_to_t const *to; int strict = 0; nea->nea_agent = agent; nea->nea_callback = no_callback; nea->nea_context = context; if (!have_from) from = sip_from_create(home, (url_string_t*)m->m_url); else from = NULL; nea->nea_args = tl_tlist(home, TAG_IF(!have_contact, SIPTAG_CONTACT(m)), ta_tags(ta)); /* Get and remove Expires header from tag list */ tl_gets(nea->nea_args, SIPTAG_EXPIRES_REF(expires), SIPTAG_EXPIRES_STR_REF(expires_str), SIPTAG_TO_REF(to), NEATAG_STRICT_3265_REF(strict), NTATAG_METHOD_REF(method_name), TAG_END()); nea->nea_strict_3265 = strict; if (to) nea->nea_to = sip_to_dup(home, to); if (expires) nea->nea_expires = sip_expires_dup(home, expires); else if (expires_str) nea->nea_expires = sip_expires_make(home, expires_str); else nea->nea_expires = sip_expires_create(home, EXPIRES_DEFAULT); tl_tremove(nea->nea_args, SIPTAG_EXPIRES(0), SIPTAG_EXPIRES_STR(0), TAG_END()); if (method_name != SUBSCRIBE) method = sip_method_code(method_name); if (method != sip_method_invalid) /* Create the timer object */ nea->nea_timer = su_timer_create(su_root_task(root), 0L); if (nea->nea_timer) { /* Create leg for NOTIFY requests */ nea->nea_leg = nta_leg_tcreate(nea->nea_agent, process_nea_request, nea, TAG_IF(!have_from, SIPTAG_FROM(from)), TAG_NEXT(nea->nea_args)); if (nea->nea_leg) { nta_leg_tag(nea->nea_leg, NULL); nea->nea_oreq = nta_outgoing_tcreate(nea->nea_leg, response_to_subscribe, nea, NULL, method, method_name, NULL, SIPTAG_EXPIRES(nea->nea_expires), TAG_NEXT(nea->nea_args)); } } if (!nea->nea_leg || !nea->nea_oreq || !nea->nea_timer) nea_destroy(nea), nea = NULL; } ta_end(ta); return nea; } int nea_update(nea_t *nea, tag_type_t tag, tag_value_t value, ...) { ta_list ta; sip_expires_t const *expires = NULL; sip_payload_t const *pl = NULL; sip_content_type_t const *ct = NULL; char const *cts = NULL; /* char const *expires_str = NULL; */ su_home_t *home = nea->nea_home; /* XXX - hack, previous request still waiting for response */ if (!nea->nea_leg || nea->nea_oreq) return -1; ta_start(ta, tag, value); tl_gets(ta_args(ta), SIPTAG_CONTENT_TYPE_REF(ct), SIPTAG_CONTENT_TYPE_STR_REF(cts), SIPTAG_PAYLOAD_REF(pl), SIPTAG_EXPIRES_REF(expires), TAG_NULL()); if (!pl || (!ct && !cts)) { ta_end(ta); return -1; } tl_tremove(nea->nea_args, SIPTAG_CONTENT_TYPE(0), SIPTAG_CONTENT_TYPE_STR(0), SIPTAG_PAYLOAD(0), SIPTAG_PAYLOAD_STR(0), TAG_END()); su_free(home, nea->nea_expires); if (expires) nea->nea_expires = sip_expires_dup(home, expires); else nea->nea_expires = sip_expires_create(home, EXPIRES_DEFAULT); /* nta_leg_tag(nea->nea_leg, NULL); */ nea->nea_oreq = nta_outgoing_tcreate(nea->nea_leg, response_to_subscribe, nea, NULL, SIP_METHOD_SUBSCRIBE, NULL, SIPTAG_TO(nea->nea_to), SIPTAG_PAYLOAD(pl), TAG_IF(ct, SIPTAG_CONTENT_TYPE(ct)), TAG_IF(cts, SIPTAG_CONTENT_TYPE_STR(cts)), SIPTAG_EXPIRES(nea->nea_expires), TAG_NEXT(nea->nea_args)); ta_end(ta); if (!nea->nea_oreq) return -1; return 0; } /** Unsubscribe the agent. */ void nea_end(nea_t *nea) { if (nea == NULL) return; nea->nea_terminating = 1; su_timer_destroy(nea->nea_timer), nea->nea_timer = NULL; if (nea->nea_leg && nea->nea_deadline) { nea->nea_oreq = nta_outgoing_tcreate(nea->nea_leg, response_to_unsubscribe, nea, NULL, SIP_METHOD_SUBSCRIBE, NULL, SIPTAG_EXPIRES_STR("0"), TAG_NEXT(nea->nea_args)); } } void nea_destroy(nea_t *nea) { if (nea == NULL) return; if (nea->nea_oreq) nta_outgoing_destroy(nea->nea_oreq), nea->nea_oreq = NULL; if (nea->nea_leg) nta_leg_destroy(nea->nea_leg), nea->nea_leg = NULL; if (nea->nea_timer) { su_timer_reset(nea->nea_timer); su_timer_destroy(nea->nea_timer), nea->nea_timer = NULL; } su_free(NULL, nea); } /* Function called by NTA to handle incoming requests belonging to the leg */ int process_nea_request(nea_t *nea, nta_leg_t *leg, nta_incoming_t *ireq, sip_t const *sip) { switch (sip->sip_request->rq_method) { case sip_method_notify: return handle_notify(nea, leg, ireq, sip); case sip_method_ack: return 400; default: nta_incoming_treply(ireq, SIP_405_METHOD_NOT_ALLOWED, SIPTAG_ALLOW_STR("NOTIFY"), TAG_END()); return 405; } } /* Callback function to handle subscription requests */ int response_to_subscribe(nea_t *nea, nta_outgoing_t *oreq, sip_t const *sip) { int status = sip->sip_status->st_status; int error = status >= 300; if (status >= 200 && oreq == nea->nea_oreq) nea->nea_oreq = NULL; nea->nea_callback(nea, nea->nea_context, sip); if (status < 200) return 0; nea->nea_oreq = NULL; if (status < 300) { sip_time_t now = sip_now(); if (!nea->nea_notify_received) { nea->nea_deadline = now + sip_contact_expires(NULL, sip->sip_expires, sip->sip_date, EXPIRES_DEFAULT, now); if (sip->sip_to->a_tag && !nea->nea_dialog) { nea->nea_dialog = 1; nta_leg_rtag(nea->nea_leg, sip->sip_to->a_tag); nta_leg_client_route(nea->nea_leg, sip->sip_record_route, sip->sip_contact); } } } else { nea->nea_deadline = 0; nea->nea_state = nea_terminated; if (status == 301 || status == 302 || status == 305) { sip_contact_t *m; for (m = sip->sip_contact; m; m = m->m_next) { if (m->m_url->url_type == url_sip || m->m_url->url_type == url_sips) break; } if (m) { url_string_t const *proxy, *url; if (status == 305) url = NULL, proxy = (url_string_t *)m->m_url; else url = (url_string_t *)m->m_url, proxy = NULL; nea->nea_oreq = nta_outgoing_tcreate(nea->nea_leg, response_to_subscribe, nea, proxy, SIP_METHOD_SUBSCRIBE, url, SIPTAG_EXPIRES(nea->nea_expires), TAG_NEXT(nea->nea_args)); } } else if (status == 423 && sip->sip_min_expires) { unsigned value = sip->sip_min_expires->me_delta; su_free(nea->nea_home, nea->nea_expires); nea->nea_expires = sip_expires_format(nea->nea_home, "%u", value); nea->nea_oreq = nta_outgoing_tcreate(nea->nea_leg, response_to_subscribe, nea, NULL, SIP_METHOD_SUBSCRIBE, NULL, SIPTAG_EXPIRES(nea->nea_expires), TAG_NEXT(nea->nea_args)); } } if (status >= 200) nta_outgoing_destroy(oreq); if (nea->nea_oreq || !error) { su_time_t now = su_now(); now.tv_sec = nea->nea_deadline; su_timer_set_at(nea->nea_timer, nea_expires_renew, nea, now); } else nea->nea_callback(nea, nea->nea_context, NULL); return 0; } int response_to_unsubscribe(nea_t *nea, nta_outgoing_t *orq, sip_t const *sip) { int status = sip->sip_status->st_status; nea->nea_callback(nea, nea->nea_context, sip); if (status >= 200) nta_outgoing_destroy(orq), nea->nea_oreq = NULL; if (status >= 300) nea->nea_callback(nea, nea->nea_context, NULL); return 0; } /** handle notifications */ int handle_notify(nea_t *nea, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip) { sip_subscription_state_t *ss = sip->sip_subscription_state; sip_subscription_state_t ss0[1]; char expires[32]; if (nea->nea_strict_3265) { char const *phrase = NULL; if (ss == NULL) phrase = "NOTIFY Has No Subscription-State Header"; else if (sip->sip_event == NULL) phrase = "Event Header Missing"; if (phrase) { nta_incoming_treply(irq, 400, phrase, TAG_END()); nta_incoming_destroy(irq); nta_leg_destroy(nea->nea_leg), nea->nea_leg = NULL; nea->nea_state = nea_terminated; nea->nea_callback(nea, nea->nea_context, NULL); return 0; } } if (ss == NULL) { /* Do some compatibility stuff here */ unsigned long delta = 3600; sip_subscription_state_init(ss = ss0); if (sip->sip_expires) delta = sip->sip_expires->ex_delta; if (delta == 0) ss->ss_substate = "terminated"; else ss->ss_substate = "active"; if (delta > 0) { snprintf(expires, sizeof expires, "%lu", delta); ss->ss_expires = expires; } } if (!nea->nea_dialog) { nea->nea_dialog = 1; nta_leg_rtag(nea->nea_leg, sip->sip_from->a_tag); nta_leg_server_route(nea->nea_leg, sip->sip_record_route, sip->sip_contact); } nea->nea_notify_received = 1; nea->nea_callback(nea, nea->nea_context, sip); if (su_casematch(ss->ss_substate, "terminated")) { nta_leg_destroy(nea->nea_leg), nea->nea_leg = NULL; nea->nea_state = nea_terminated; if (su_casematch(ss->ss_reason, "deactivated")) { nea->nea_state = nea_embryonic; nea->nea_deadline = sip_now(); } else if (su_casematch(ss->ss_reason, "probation")) { sip_time_t retry = sip_now() + NEA_TIMER_DELTA; if (ss->ss_retry_after) retry += strtoul(ss->ss_retry_after, NULL, 10); else retry += NEA_TIMER_DELTA; nea->nea_state = nea_embryonic; nea->nea_deadline = retry; } else { nea->nea_deadline = 0; nea->nea_callback(nea, nea->nea_context, NULL); return 200; } } else if (su_casematch(ss->ss_substate, "pending")) nea->nea_state = nea_pending; else if (su_casematch(ss->ss_substate, "active")) nea->nea_state = nea_active; else nea->nea_state = nea_extended; if (nea->nea_state != nea_embryonic && ss->ss_expires) { unsigned retry = strtoul(ss->ss_expires, NULL, 10); if (retry > 60) retry -= 30; else retry /= 2; nea->nea_deadline = sip_now() + retry; } { su_time_t now = su_now(); now.tv_sec = nea->nea_deadline; su_timer_set_at(nea->nea_timer, nea_expires_renew, nea, now); } return 200; } void nea_expires_renew(su_root_magic_t *magic, su_timer_t *timer, nea_t *nea) { sip_time_t now = sip_now(); /* re-subscribe if expires soon */ if (nea->nea_state == nea_terminated || nea->nea_deadline == 0 || nea->nea_deadline > now + NEA_TIMER_DELTA) return; if (!nea->nea_notify_received) /* Hmph. */ return; nea->nea_notify_received = 0; nea->nea_oreq = nta_outgoing_tcreate(nea->nea_leg, response_to_subscribe, nea, NULL, SIP_METHOD_SUBSCRIBE, NULL, SIPTAG_EXPIRES(nea->nea_expires), TAG_NEXT(nea->nea_args)); return; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nea/nea.docs000066400000000000000000000077251223300710500217450ustar00rootroot00000000000000/* -*- c -*- */ /**@MODULEPAGE "nea" - SIP Events Module * * @section nea_meta Module Meta Information * * Sofia Event API provides an interface to different events used in SIP * presence and conferencing. Interface used both in client and server sides * is presented in . * * @CONTACT Pekka Pessi * * @STATUS @SofiaSIP Core library * * @LICENSE LGPL * * @section Creating NEA server and events * * @section nea_server_create Creating NEA server * * NEA server generates, receives and sends events to subscribed * parties. The server is presentity specific, ie. a different server * is created for every presentity. * * First, a server object is created. The object uses the NTA @e agent * (#nta_agent_t) that handles incoming and outgoing SIP messages. * * The example below provides a way to create the NEA server. The * function nea_server_create() creates the server. Parameters @e * agent, @e root define the transaction engine. Third parameter is * the address of the presentity. event_callback is a callback * function pointer and is called every time a new user subscribes to * an event that does not exist or requests for payload type that * doesn't match. * * @code * presence_t *presence_create(su_root_t *root, * nta_agent_t *agent, * sip_contact_t const *m) * { * presentity_t *pr = su_home_clone(p->p_home, sizeof (*pr)); * ... * pr->pr_nes = * nea_server_create(agent, root, * m->m_url, * MAX_SUBSCRIBERS, * event_callback, pr, * SIPTAG_CONTACT(m), * SIPTAG_SERVER_STR("Sofia-SIP NEA"), * TAG_NULL()); * ... * } * @endcode * * @section nea_event_create Creating Events * * Next, events are created. The function nea_event_create () defines * an event, its package and content types (a comma separated * list). The parameter presence_callback defines the callback * function that is called when a someone subscribes to a defined * event. * * @code * #define PRESENCE_PACKAGE "presence" * #define XPIDF_MIME_TYPE "application/xpidf+xml" * #define PIDF_MIME_TYPE "application/cpim-pidf+xml" * ne = nea_event_create(pr->pr_nes, presence_callback, ep, * PRESENCE_PACKAGE, NULL, * PIDF_MIME_TYPE, * PIDF_MIME_TYPE "," XPIDF_MIME_TYPE); * @endcode * * @section nea_server_update Operating with event payloads * * A new payload can be inserted to a event with the function * nea_server_update(). The 4th parameter describes if the updated * content is a fake (for unauthorized subscribers). A real payload is * inserted (updated) with the 4th parameter being 0. If the event is * not updated with the content type @a ct before, a new content type * format for the event is created. Otherwise the old payload is * replaced with the new one. * * After the update, subscribers of the event are notified (with SIP * NOTIFY) of the changed payload with nea_server_update (). * * @code * nea_server_update(pr->pr_nes, home, event, 1, * SIPTAG_CONTENT_TYPE(ct), * SIPTAG_PAYLOAD(pl), * TAG_END()); * nea_server_notify(pr->pr_nes, event); * @endcode * * Obtaining the event's payload and removing it is presented in the * example below. The event is defined as a part of the @a package_t * structure. Function nea_payloads_get() is used to return a payload * (in this case content type being predefined * "application/cpim-pidf+xml"). The real and fake payloads are stored * in the structure #nea_payloads_t. Finally, the payload is removed * with nea_payload_remove(). * * @code * int remove_old_payload(package_t *ep) * { * nea_payloads_t *np; * sip_content_type_t *ct; * sip_payload_t *real; * sip_payload_t *fake; * event = ep->ep_event; * np = nea_payloads_get(event, PIDF_MIME_TYPE); * ct = nea_content_type_get(np); * real = nea_payload_get(np); * fake = nea_fake_get(np); * nea_payload_remove(ep->ep_home, np); * return 0; * } * @endcode */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nea/nea_debug.c000066400000000000000000000047731223300710500224050ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /* */ /* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE nea_debug.c Debug Log for Nokia Event Client API * * @author Pekka Pessi * */ #include #include "nea_debug.h" /**@var NEA_DEBUG * * Environment variable determining the debug log level for @b nea * module. * * The NEA_DEBUG environment variable is used to determine the debug * logging level for @b nea module. The default level is 3. * * @sa , nea_log, SOFIA_DEBUG */ extern char const NEA_DEBUG[]; #ifndef SU_DEBUG #define SU_DEBUG 3 #endif /**Debug log for @b nea module. * * The nea_log is the log object used by @b nea module. The level of * #nea_log is set using #NEA_DEBUG environment variable. */ su_log_t nea_log[] = { SU_LOG_INIT("nea", "NEA_DEBUG", SU_DEBUG) }; sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nea/nea_debug.h000066400000000000000000000023341223300710500224010ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef NEA_DEBUG_H /** Defined when has been included. */ #define NEA_DEBUG_H /**@file nea_debug.h * @brief Debug log for @b nea module. * * @author Pekka Pessi * @date Created: Thu Sep 6 19:06:40 2001 ppessi */ #define SU_LOG (nea_log) #include #endif /* !defined(NEA_DEBUG_H) */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nea/nea_event.c000066400000000000000000000037731223300710500224370ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@internal * @file nea_event.c * @brief Default MIME type for certain events. * * @author Pekka Pessi * * @date Created: Thu Dec 11 20:28:46 2003 ppessi */ #include "config.h" #include #include char const *nea_default_content_type(char const *event) { char const *template = strrchr(event, '.'); if (strcmp(event, "presence") == 0) return "application/pidf+xml"; else if (strcmp(event, "cpl") == 0) return "application/cpl+xml"; else if (strcmp(event, "reg") == 0) return "application/reginfo+xml"; else if (strcmp(event, "presencelist") == 0) return "application/cpim-plidf+xml"; else if (strcmp(event, "message-summary") == 0) return "application/simple-message-summary"; else if (template && strcmp(template, ".acl") == 0) return "application/vnd.nokia-acl+xml"; else if (template && strcmp(template, ".winfo") == 0) return "application/watcherinfo+xml"; else if (template && strcmp(template, ".list") == 0) return "application/rlmi+xml"; else if (strcmp(event, "rlmi") == 0) return "application/rlmi+xml"; else return NULL; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nea/nea_server.c000066400000000000000000001770121223300710500226220ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@internal @file nea_server.c * @brief Nokia Event API - event notifier implementation. * * @author Pekka Pessi * @author Martti Mela * * @date Created: Wed Feb 14 18:37:04 EET 2001 ppessi */ #include "config.h" #include #include #include #include #include #include "nea_debug.h" #define NONE ((void *)(intptr_t)-1) #define SU_ROOT_MAGIC_T struct nea_server_s #define SU_MSG_ARG_T tagi_t #define NTA_AGENT_MAGIC_T struct nea_server_s #define NTA_LEG_MAGIC_T struct nea_sub_s #define NTA_INCOMING_MAGIC_T struct nea_sub_s #define NTA_OUTGOING_MAGIC_T struct nea_sub_s #include #include #include #include #include #include #include #include #include /** Number of primary views (with different MIME type or content) */ #define NEA_VIEW_MAX (8) /** @internal Server object, created for every notifier. */ struct nea_server_s { su_home_t nes_home[1]; su_root_t *nes_root; su_timer_t *nes_timer; nta_agent_t *nes_agent; nta_leg_t *nes_leg; nea_sub_t *nes_subscribers; sip_require_t *nes_require; sip_time_t nes_min_expires; sip_time_t nes_expires; sip_time_t nes_max_expires; int nes_max_subs; unsigned nes_throttle; /**< Default throttle */ unsigned nes_min_throttle; /**< Minimum throttle */ unsigned nes_eventlist:1; /**< Eventlist only */ unsigned nes_in_callback : 1; unsigned nes_pending_destroy : 1; unsigned nes_pending_flush : 1; unsigned nes_202_before_notify:1; unsigned nes_in_list; unsigned nes_throttled; /**< Throttled notifications? */ char const *nes_server; sip_contact_t *nes_eventity_uri; sip_allow_events_t *nes_allow_events; sip_allow_t *nes_allow_methods; nea_new_event_f *nes_callback; nea_smagic_t *nes_context; /** Events. * Each subscriber will be added to one of these. */ nea_event_t *nes_events; }; /** @internal Supported events and their subscribers */ struct nea_event_s { nea_event_t *ev_next; nea_event_t **ev_prev; nea_watcher_f *ev_callback; nea_emagic_t *ev_magic; unsigned ev_throttle; /**< Default throttle */ unsigned ev_min_throttle; /**< Minimum throttle */ unsigned ev_eventlist:1; /**< Eventlist is supported */ unsigned ev_reliable:1; /**< Keep all notifications */ unsigned :0; /** Sequence number of first unsent update */ unsigned ev_throttling; unsigned ev_updated; /**< Sequence number for updates */ sip_require_t *ev_require; /**< Required features */ sip_supported_t *ev_supported; /**< Supported features */ sip_event_t *ev_event; sip_accept_t const *ev_default;/**< Default content type */ sip_accept_t const *ev_accept; /**< Supported content types */ nea_event_view_t *ev_views[NEA_VIEW_MAX + 1]; }; typedef struct nea_event_queue_s nea_event_queue_t; /** @internal Object representing particular view of event */ struct nea_event_view_s { nea_event_view_t *evv_next; nea_event_view_t *evv_primary; /**< Backpointer to the primary view */ nea_evmagic_t *evv_magic; unsigned evv_throttle; /**< Default throttle */ unsigned evv_min_throttle; /**< Minimum throttle */ unsigned evv_fake:1; /**< This is "fake" (ie. default) view */ unsigned evv_private:1; /**< This is private view */ unsigned evv_reliable:1; /**< Keep all notifications */ unsigned:0; /** @internal Queued notification */ struct nea_event_queue_s { nea_event_queue_t *evq_next; unsigned evq_updated; unsigned evq_version; sip_content_type_t *evq_content_type; sip_payload_t *evq_payload; } evv_head[1]; }; #define evv_version evv_head->evq_version #define evv_updated evv_head->evq_updated #define evv_content_type evv_head->evq_content_type #define evv_payload evv_head->evq_payload /** @internal Subscription object. */ struct nea_sub_s { nea_sub_t *s_next; nea_sub_t **s_prev; nta_leg_t *s_leg; nta_incoming_t *s_irq; nta_outgoing_t *s_oreq; nea_server_t *s_nes; sip_contact_t *s_local; /**< Local contact */ sip_from_t *s_from; sip_contact_t *s_remote; /**< Remote contact */ /* sip_accept_t *s_accept; */ sip_event_t *s_id; nea_event_t *s_event; nea_event_view_t *s_view; nea_state_t s_state; char const *s_extended; sip_content_type_t *s_content_type; /** Content-Type of SUBSCRIBE body. */ sip_payload_t *s_payload; /**< Body of SUBSCRIBE. */ unsigned s_reported :1 ; /**< Made watcher report upon un-SUBSCRIBE */ unsigned s_processing : 1; unsigned s_rejected : 1; unsigned s_pending_flush : 1; unsigned s_garbage : 1; unsigned s_fake : 1; /**< Do not send real information to user */ unsigned s_eventlist : 1; /**< Subscriber supported eventlist */ sip_time_t s_subscribed; /**< When first SUBSCRIBE was recv */ sip_time_t s_notified; /**< When last notification was sent */ sip_time_t s_expires; /**< Expiration time. */ unsigned s_version; /**< Version number set by application */ unsigned s_latest; /**< External version of latest payload */ unsigned s_updated; /**< Internal version of latest payload */ unsigned s_throttle; /**< Minimum time between notifications */ }; /* Prototypes */ static void nea_server_pending_flush(nea_server_t *nes); static int nea_view_update(nea_server_t *nes, nea_event_t *ev, nea_event_view_t **evvp, int private, int fake, tag_type_t tag, tag_value_t value, ...); static nea_sub_t *nea_sub_create(nea_server_t *nes); static int nea_sub_is_removed(nea_sub_t const *s); static void nea_sub_remove(nea_sub_t *s); static void nea_sub_destroy(nea_sub_t *s); static int nea_server_callback(nea_sub_t *nes_as_sub, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip); static int nea_sub_process_incoming(nea_sub_t *s, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip); static int nea_sub_process_subscribe(nea_sub_t *s, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip); static int nea_sub_notify(nea_server_t *nes, nea_sub_t *s, sip_time_t now, tag_type_t tag, tag_value_t value, ...); static int response_to_notify(nea_sub_t *s, nta_outgoing_t *oreq, sip_t const *sip); static void nes_event_timer(nea_server_t *nes, su_timer_t *timer, su_timer_arg_t *arg); static int nea_view_queue(nea_server_t *nes, nea_event_view_t *evv, nea_event_queue_t *evq); /** Assign an event view to subscriber. */ su_inline void nea_sub_assign_view(nea_sub_t *s, nea_event_view_t *evv) { if (s->s_view != evv) /* Make sure we send a notification */ s->s_updated = evv->evv_updated - 1; s->s_view = evv; s->s_throttle = evv->evv_throttle; } su_inline void nea_subnode_init(nea_subnode_t *sn, nea_sub_t *s, sip_time_t now) { sn->sn_state = s->s_state; sn->sn_fake = s->s_fake; sn->sn_subscriber = s; sn->sn_event = s->s_event; sn->sn_remote = s->s_from; sn->sn_contact = s->s_remote; sn->sn_content_type = s->s_content_type; sn->sn_payload = s->s_payload; if (s->s_expires != 0 && (int)(s->s_expires - now) > 0) sn->sn_expires = s->s_expires - now; else sn->sn_expires = 0; sn->sn_latest = s->s_latest; sn->sn_throttle = s->s_throttle; sn->sn_eventlist = s->s_eventlist; sn->sn_version = s->s_version; sn->sn_subscribed = now - s->s_subscribed; sn->sn_notified = s->s_notified; sn->sn_view = s->s_view; } /** Create an event server. * * The function nea_server_create() initializes an event server object and * registers it with @b nta. An event server object takes care of all events * for a particular URI (@em eventity). * * @param agent pointer to an @b nta agent object * @param root pointer to an @b root object *@param url url of the server to be created * @param max_subs maximum number of subscriptions * @param callback authorization function, * or @c NULL if no authorization is required * @param context server context (pointer to application data) * @param tag, value, ... optional list of tag parameters * * @TAGS * The function nea_server_create() takes the following tag values as its * arguments: *
* *
SIPTAG_CONTACT() or SIPTAG_CONTACT_STR() *
The target address of the event server. * *
SIPTAG_ALLOW_EVENTS() *
The initial list of events supported by eventity. This list is * extended whenever a new event is created with nea_event_tcreate(). * *
SIPTAG_SERVER_STR() *
The @b Server header for the event server. * *
NEATAG_MINSUB() *
Minimum duration of a subscription. * *
NEATAG_THROTTLE() *
Default value for event throttle (by default, 5 seconds). * Throttle determines the minimum interval betweeen notifications. Note * that the notification indicating that the subscription has terminated * will be sent regardless of throttle. * * The default throttle value is used if the subscriber does not include * a throttle parameter in @ref sip_event "Event" header of SUBSCRIBE request. * *
NEATAG_MINTHROTTLE() *
Minimum allowed throttle value (by default, 5 seconds). * *
NEATAG_EVENTLIST() *
If true, the subscribers must support eventlists. If SIPTAG_REQUIRE() * is given, it must contain the "eventlist" feature. * *
NEATAG_DIALOG() *
Give an optional NTA destination leg to event server. * *
SIPTAG_REQUIRE()/SIPTAG_REQUIRE_STR() *
The @b Require header for the event server. The subscribers must * indicate support the specified features. * *
* * @return * The function nea_server_create() returns a pointer to an event server * object, or @c NULL upon an error. */ nea_server_t *nea_server_create(nta_agent_t *agent, su_root_t *root, url_t const *url, int max_subs, nea_new_event_f *callback, nea_smagic_t *context, tag_type_t tag, tag_value_t value, ...) { nea_server_t *nes = NULL; sip_contact_t const *contact = NULL; sip_allow_events_t const *allow_events = NULL; sip_require_t const *rq = NULL; char const *contact_str = NULL; char const *server_str = NULL; char const *rq_str = NULL; unsigned min_expires = 15 * 60, expires = NEA_DEFAULT_EXPIRES, max_expires = 24 * 60 * 60; nta_leg_t *leg = NONE; unsigned throttle = 5, min_throttle = throttle; int eventlist = 0; { ta_list ta; ta_start(ta, tag, value); tl_gets(ta_args(ta), SIPTAG_CONTACT_REF(contact), SIPTAG_CONTACT_STR_REF(contact_str), SIPTAG_ALLOW_EVENTS_REF(allow_events), SIPTAG_SERVER_STR_REF(server_str), SIPTAG_REQUIRE_REF(rq), SIPTAG_REQUIRE_STR_REF(rq_str), NEATAG_MIN_EXPIRES_REF(min_expires), NEATAG_EXPIRES_REF(expires), NEATAG_MAX_EXPIRES_REF(max_expires), NEATAG_DIALOG_REF(leg), NEATAG_THROTTLE_REF(throttle), NEATAG_MINTHROTTLE_REF(min_throttle), NEATAG_EVENTLIST_REF(eventlist), TAG_NULL()); ta_end(ta); } if (throttle < min_throttle) throttle = min_throttle; if (!url) { SU_DEBUG_5(("nea_server_create(): invalid url\n")); return NULL; } if (min_expires > expires || expires > max_expires) { SU_DEBUG_5(("nea_server_create(): invalid expiration range\n")); return NULL; } nes = su_home_new(sizeof(nea_server_t)); if (nes) { su_home_t *home = nes->nes_home; nes->nes_root = root; nes->nes_agent = agent; nes->nes_max_subs = max_subs; nes->nes_min_expires = min_expires; nes->nes_expires = expires; nes->nes_max_expires = max_expires; nes->nes_throttle = throttle; nes->nes_min_throttle = min_throttle; if (allow_events) nes->nes_allow_events = sip_allow_events_dup(home, allow_events); else nes->nes_allow_events = sip_allow_events_make(home, ""); nes->nes_allow_methods = sip_allow_make(home, "SUBSCRIBE"); nes->nes_server = su_sprintf(home, "%s%snea/" NEA_VERSION_STR " %s", server_str ? server_str : "", server_str ? " " : "", nta_agent_version(agent)); if (contact) nes->nes_eventity_uri = sip_contact_dup(home, contact); else if (contact_str) nes->nes_eventity_uri = sip_contact_make(home, contact_str); else nes->nes_eventity_uri = sip_contact_create(home, (url_string_t *)url, NULL); if (leg != NONE) { nes->nes_leg = leg; if (leg != NULL) nta_leg_bind(leg, nea_server_callback, (nea_sub_t*)nes); } else { nes->nes_leg = nta_leg_tcreate(agent, nea_server_callback, (nea_sub_t*)nes, NTATAG_NO_DIALOG(1), NTATAG_METHOD("SUBSCRIBE"), URLTAG_URL(url), TAG_END()); } nes->nes_eventlist = eventlist; /* Every event is a list */ if (eventlist && rq == NULL && rq_str == NULL) rq_str = "eventlist"; if (rq) nes->nes_require = sip_require_dup(nes->nes_home, rq); else if (rq_str) nes->nes_require = sip_require_make(nes->nes_home, rq_str); nes->nes_timer = su_timer_create(su_root_task(nes->nes_root), nes->nes_min_throttle ? 500L * nes->nes_min_throttle : 500L); if (nes->nes_allow_events && nes->nes_eventity_uri && (nes->nes_leg || leg == NULL) && nes->nes_timer) { SU_DEBUG_5(("nea_server_create(%p): success\n", (void *)nes)); su_timer_set(nes->nes_timer, nes_event_timer, nes); nes->nes_callback = callback; nes->nes_context = context; } else { SU_DEBUG_5(("nea_server_create(%p): failed\n", (void *)nes)); nea_server_destroy(nes), nes = NULL; } } return nes; } /** Invoke the new event callback. * * The function nes_event_callback() calls the callback provided by the * application using the notifier object. * * @param nes pointer to notifier object * @param ev pointer to event view * @param s pointer to subscription object * @param sip pointer to subscribe request * * @return * The function nes_event_callback() returns -1 if the notifier object * has been destroyed by the callback function, 0 otherwise. */ static int nes_new_event_callback(nea_server_t *nes, nea_event_t **ev_p, nea_event_view_t **view_p, nta_incoming_t *irq, sip_t const *sip) { if (nes->nes_callback) return nes->nes_callback(nes->nes_context, nes, ev_p, view_p, irq, sip); else return -1; } /** Shutdown event server. */ int nea_server_shutdown(nea_server_t *nes, int retry_after) { nea_sub_t *s; int status = 200; int in_callback; if (nes == NULL) return 500; if (nes->nes_in_callback) { SU_DEBUG_5(("nea_server_shutdown(%p) while in callback\n", (void *)nes)); return 100; } SU_DEBUG_5(("nea_server_shutdown(%p)\n", (void *)nes)); in_callback = nes->nes_in_callback; nes->nes_in_callback = 1; for (s = nes->nes_subscribers; s; s = s->s_next) { if (s->s_state == nea_terminated) continue; if (s->s_pending_flush) continue; if (s->s_oreq == NULL) nea_sub_auth(s, nea_terminated, TAG_IF(retry_after, NEATAG_REASON("probation")), TAG_IF(!retry_after, NEATAG_REASON("deactivated")), TAG_IF(retry_after, NEATAG_RETRY_AFTER(retry_after)), TAG_END()); else status = 180; } nes->nes_in_callback = in_callback; return 200; } void nea_server_destroy(nea_server_t *nes) { if (nes == NULL) return; if (nes->nes_in_callback) { SU_DEBUG_5(("nea_server_destroy(%p) while in callback\n", (void *)nes)); nes->nes_pending_destroy = 1; return; } SU_DEBUG_5(("nea_server_destroy(%p)\n", (void *)nes)); nta_leg_destroy(nes->nes_leg), nes->nes_leg = NULL; while (nes->nes_subscribers) nea_sub_destroy(nes->nes_subscribers); su_timer_destroy(nes->nes_timer), nes->nes_timer = NULL; su_home_unref(nes->nes_home); } /* ----------------------------------------------------------------- */ /**Update server payload. * * A nea event server has typed content that is delivered to the * subscribers. Different content types are each assigned a separate primary * view. There can be also primary views with "fake" content, content * delivered to politely blocked subscribers. * * In addition to primary views, there can be secondary views, views * assigned to a single subscriber only. * * @TAGS * The following tagged arguments are accepted: *
* *
SIPTAG_PAYLOAD() or SIPTAG_PAYLOAD_STR() *
Updated event content. * *
SIPTAG_CONTENT_TYPE() or SIPTAG_CONTENT_TYPE_STR(). *
MIME type of the content. * *
NEATAG_FAKE(fak) *
If @a fake is true, 'fake' view is updated. * *
NEATAG_VIEW(view) *
If included in tagged arguments, @a view is * updated. Used when * updating secondary view. * *
NEATAG_VERSION(version) *
The application-provided @a version for * event content. After updated content has been sent to subscriber, @a * version is copied to subscriber information structure. * *
NEATAG_EVMAGIC(context) *
Application-provided @a context pointer. * The @a context pointer is returned by nea_view_magic() function. * *
NEATAG_RELIABLE(reliable) *
The @a reliable flag determines how overlapping updates are handled. * If @a reliable is true, all updates are delivered to the subscribers. * *
NEATAG_THROTTLE(throttl) *
Default value for event throttle for updated event view. Throttle * determines the minimum interval in seconds betweeen notifications. Note * that the notification indicating that the subscription has terminated * will be sent regardless of throttle. * * The default throttle value is used if the subscriber does not include * a throttle parameter in @ref sip_event "Event" header of SUBSCRIBE request. * *
NEATAG_MINTHROTTLE() *
Minimum allowed throttle value for updated event view. * *
* * @retval -1 upon an error. * @retval 0 if event document was not updated. * @retval 1 if event document was updated. */ int nea_server_update(nea_server_t *nes, nea_event_t *ev, tag_type_t tag, tag_value_t value, ...) { nea_event_view_t *evv = NULL; int fake = 0, updated; ta_list ta; if (ev == NULL) ev = nes->nes_events; ta_start(ta, tag, value); tl_gets(ta_args(ta), NEATAG_FAKE_REF(fake), NEATAG_VIEW_REF(evv), TAG_NULL()); updated = nea_view_update(nes, ev, &evv, 0, fake, ta_tags(ta)); ta_end(ta); return updated; } static int nea_view_update(nea_server_t *nes, nea_event_t *ev, nea_event_view_t **evvp, int private, int fake, tag_type_t tag, tag_value_t value, ...) { ta_list ta; su_home_t *home = nes->nes_home; sip_content_type_t const *ct = NULL; char const *cts = NULL, *pls = NULL; sip_payload_t const *pl = NULL; sip_payload_t *new_pl; nea_event_view_t *evv, **eevv = &evv; nea_event_view_t *primary = NULL, **primary_p = &primary; unsigned version = UINT_MAX; nea_evmagic_t *evmagic = NULL; int reliable = ev->ev_reliable; unsigned throttle = ev->ev_throttle; unsigned min_throttle = ev->ev_min_throttle; nea_event_queue_t evq[1] = {{ NULL }}; ta_start(ta, tag, value); tl_gets(ta_args(ta), SIPTAG_CONTENT_TYPE_REF(ct), SIPTAG_CONTENT_TYPE_STR_REF(cts), SIPTAG_PAYLOAD_REF(pl), SIPTAG_PAYLOAD_STR_REF(pls), NEATAG_VERSION_REF(version), NEATAG_EVMAGIC_REF(evmagic), NEATAG_RELIABLE_REF(reliable), NEATAG_THROTTLE_REF(throttle), NEATAG_MINTHROTTLE_REF(min_throttle), TAG_NULL()); ta_end(ta); if (min_throttle < throttle) min_throttle = throttle; if (ct == NULL && cts == NULL) return -1; if (ct) cts = ct->c_type; evv = *evvp; if (!evv) { int i; /* Check if the payload type already exists */ for (i = 0; (evv = ev->ev_views[i]); i++) if (su_casematch(cts, evv->evv_content_type->c_type)) break; if (private && evv == NULL) /* No private view without primary view. */ return -1; if (i == NEA_VIEW_MAX) /* Too many primary views. */ return -1; primary_p = eevv = ev->ev_views + i; /* Search for fakeness/eventlist/private view */ if (evv && (private || evv->evv_private || evv->evv_fake != (unsigned)fake)) { for (eevv = &evv->evv_next; (evv = *eevv); eevv = &evv->evv_next) { if (private || evv->evv_private) continue; if (evv->evv_fake == (unsigned)fake) break; } } } /* New event view, allocate and link to chain */ if (!evv) { sip_content_type_t *new_ct; evv = su_zalloc(home, sizeof (*evv)); if (!evv) return -1; new_pl = pl ? sip_payload_dup(home, pl) : sip_payload_make(home, pls); new_ct = ct ? sip_content_type_dup(home, ct) : sip_content_type_make(home, cts); if ((!new_pl && pl) || !new_ct) { su_free(home, evv); su_free(home, new_pl); return -1; } *evvp = *eevv = evv; evv->evv_primary = *primary_p; evv->evv_private = private != 0; evv->evv_fake = fake != 0; evv->evv_reliable = reliable != 0; evv->evv_magic = evmagic; evv->evv_content_type = new_ct; evv->evv_payload = new_pl; evv->evv_throttle = throttle; evv->evv_min_throttle = min_throttle; assert(evv->evv_content_type); } else { if (pl && evv->evv_payload && evv->evv_payload->pl_len == pl->pl_len && memcmp(evv->evv_payload->pl_data, pl->pl_data, pl->pl_len) == 0) return 0; if (!pl && pls && evv->evv_payload && evv->evv_payload->pl_len == strlen(pls) && memcmp(evv->evv_payload->pl_data, pls, evv->evv_payload->pl_len) == 0) return 0; if (!pl && !pls && !evv->evv_payload) return 0; *evq = *evv->evv_head; new_pl = pl ? sip_payload_dup(home, pl) : sip_payload_make(home, pls); if (!new_pl && (pl || pls)) return -1; evv->evv_payload = new_pl; } if (version != UINT_MAX) evv->evv_version = version; if (!fake) evv->evv_updated = ++ev->ev_updated; if (evq->evq_content_type) nea_view_queue(nes, evv, evq); SU_DEBUG_7(("nea_server_update(%p): %s (%s)\n", (void *)nes, ev->ev_event->o_type, evv->evv_content_type->c_type)); return 1; } nea_event_view_t *nea_view_create(nea_server_t *nes, nea_event_t *ev, nea_evmagic_t *magic, tag_type_t tag, tag_value_t value, ...) { nea_event_view_t *evv = NULL; ta_list ta; if (ev == NULL) return NULL; ta_start(ta, tag, value); nea_view_update(nes, ev, &evv, 1, 0, ta_tags(ta)); ta_end(ta); return evv; } void nea_view_destroy(nea_server_t *nes, nea_event_view_t *evv) { nea_event_view_t **evvp; nea_sub_t *s; if (nes == NULL || evv == NULL || !evv->evv_private) return; assert(evv->evv_primary && evv != evv->evv_primary); for (evvp = &evv->evv_primary->evv_next; *evvp; evvp = &(*evvp)->evv_next) if (*evvp == evv) { *evvp = evv->evv_next; break; } for (s = nes->nes_subscribers; s; s = s->s_next) if (s->s_view == evv) nea_sub_assign_view(s, evv->evv_primary); su_free(nes->nes_home, evv->evv_content_type); su_free(nes->nes_home, evv->evv_payload); su_free(nes->nes_home, evv); } nea_evmagic_t *nea_view_magic(nea_event_view_t const *evv) { return evv ? evv->evv_magic : NULL; } void nea_view_set_magic(nea_event_view_t *evv, nea_evmagic_t *magic) { if (evv) evv->evv_magic = magic; } unsigned nea_view_version(nea_event_view_t const *evv) { return evv ? evv->evv_version : 0; } /** Get primary, non-fake event view for given content type */ nea_event_view_t *nea_event_view(nea_event_t *ev, char const *content_type) { int i; nea_event_view_t *evv; /* Check if the payload type already exists */ for (i = 0; ev->ev_views[i]; i++) if (su_casematch(content_type, ev->ev_views[i]->evv_content_type->c_type)) break; for (evv = ev->ev_views[i]; evv; evv = evv->evv_next) if (!evv->evv_fake) return evv; return ev->ev_views[i]; } /** Get the content type for event view */ sip_content_type_t const *nea_view_content_type(nea_event_view_t const *evv) { return evv ? evv->evv_content_type : NULL; } /** Queue an old notification if needed. */ static int nea_view_queue(nea_server_t *nes, nea_event_view_t *evv, nea_event_queue_t *evq) { nea_sub_t *s = NULL; assert(nes && evv && evq); if (evv->evv_reliable) for (s = nes->nes_subscribers; s; s = s->s_next) { if (s->s_view != evv) continue; if (s->s_updated > evq->evq_updated) continue; if (s->s_updated == evq->evq_updated && s->s_oreq == NULL) continue; break; /* This */ } if (s) { nea_event_queue_t *evq0 = su_alloc(nes->nes_home, sizeof *evq); if (evq0 == NULL) return -1; *evq0 = *evq, evq = evq0; /* evq should be copy of old head but with changed payload */ assert(evq->evq_next == evv->evv_head->evq_next); evv->evv_head->evq_next = evq; /* insert to the queue */ return 0; } su_free(nes->nes_home, (void *)evq->evq_payload); return 0; } /** Remove old unneeded notifications. */ static int nea_view_dequeue(nea_server_t *nes, nea_event_t *ev) { int i; nea_event_view_t *evv; nea_event_queue_t **prev, *evq;; assert(nes && ev); for (i = 0; ev->ev_views[i]; i++) { for (evv = ev->ev_views[i]; evv; evv = evv->evv_next) { if (!evv->evv_reliable) continue; for (prev = &evv->evv_head->evq_next; *prev; prev = &(*prev)->evq_next) if (ev->ev_throttling >= (*prev)->evq_updated) break; /* Free from evq onwards */ for (evq = *prev; evq; evq = *prev) { *prev = evq->evq_next; su_free(nes->nes_home, evq->evq_payload); su_free(nes->nes_home, evq); } } } return 0; } /* ----------------------------------------------------------------- */ /** Notify watchers. * * @return * The function nea_server_notify() returns number of subscribers that the * notification could be sent, or -1 upon an error. */ int nea_server_notify(nea_server_t *nes, nea_event_t *ev) { sip_time_t now = sip_now(); nea_sub_t *s; int notified = 0, throttled = nes->nes_throttled; SU_DEBUG_7(("nea_server_notify(%p): %s\n", (void *)nes, ev ? ev->ev_event->o_type: "")); ++nes->nes_in_list; nes->nes_throttled = 0; if (ev == NULL) for (ev = nes->nes_events; ev; ev = ev->ev_next) ev->ev_throttling = UINT_MAX; else ev->ev_throttling = UINT_MAX; for (s = nes->nes_subscribers; s; s = s->s_next) { if ((ev == NULL || ev == s->s_event) && s->s_state != nea_terminated) { notified += nea_sub_notify(nes, s, now, TAG_END()); } } if (throttled) { /* Dequeue throttled updates */ if (ev == NULL) for (ev = nes->nes_events; ev; ev = ev->ev_next) { nea_view_dequeue(nes, ev); SU_DEBUG_3(("nea_server(): notified %u, throttling at %u\n", notified, ev->ev_throttling)); } else { SU_DEBUG_3(("nea_server(): notified %u, throttling at %u\n", notified, ev->ev_throttling)); nea_view_dequeue(nes, ev); } } if (--nes->nes_in_list == 0 && nes->nes_pending_flush) nea_server_pending_flush(nes); return notified; } /* ----------------------------------------------------------------- */ void nea_server_flush(nea_server_t *nes, nea_event_t *event) { nea_sub_t *s, **ss; sip_time_t now; if (nes == NULL) return; now = sip_now(); for (ss = &nes->nes_subscribers; (s = *ss);) { if ((event == NULL || s->s_event == event) && (s->s_state == nea_terminated || s->s_expires < now)) { /** On first flush, mark as garbage, remove on second flush */ if (!s->s_garbage) s->s_garbage = 1; else if (nes->nes_in_callback || nes->nes_in_list) { nes->nes_pending_flush = 1; (*ss)->s_pending_flush = 1; } else { nea_sub_destroy(*ss); continue; } } ss = &((*ss)->s_next); } } /* ----------------------------------------------------------------- */ static void nea_server_pending_flush(nea_server_t *nes) { nea_sub_t **ss; for (ss = &nes->nes_subscribers; *ss;) { if ((*ss)->s_pending_flush && !(*ss)->s_processing) { nea_sub_destroy(*ss); } else { ss = &((*ss)->s_next); } } nes->nes_pending_flush = 0; } /* ----------------------------------------------------------------- */ nea_sub_t *nea_sub_create(nea_server_t *nes) { nea_sub_t *s; assert(nes); s = su_zalloc(nes->nes_home, sizeof (*s)); if (s) { s->s_nes = nes; if ((s->s_next = nes->nes_subscribers)) s->s_next->s_prev = &s->s_next; s->s_prev = &nes->nes_subscribers; nes->nes_subscribers = s; /* Copy default values */ s->s_throttle = nes->nes_throttle; } return s; } /* ----------------------------------------------------------------- */ nta_incoming_t *nea_subnode_get_incoming(nea_subnode_t *sn) { assert(sn); if (sn->sn_subscriber) { return sn->sn_subscriber->s_irq; } return NULL; } /* ----------------------------------------------------------------- */ void nea_sub_remove(nea_sub_t *s) { if (s) { assert(s->s_prev); if ((*s->s_prev = s->s_next)) s->s_next->s_prev = s->s_prev; s->s_prev = NULL; s->s_next = NULL; } } /* ----------------------------------------------------------------- */ /**Check if subscriber has been removed from list */ static int nea_sub_is_removed(nea_sub_t const *s) { return s->s_prev == NULL; } /* ----------------------------------------------------------------- */ void nea_sub_destroy(nea_sub_t *s) { if (s) { nea_sub_t *del = s; su_home_t *home = del->s_nes->nes_home; if (!nea_sub_is_removed(del)) nea_sub_remove(del); del->s_event = NULL; su_free(home, del->s_local), del->s_local = NULL; su_free(home, del->s_remote), del->s_remote = NULL; if (del->s_oreq) nta_outgoing_destroy(del->s_oreq), del->s_oreq = NULL; if (del->s_leg) nta_leg_destroy(del->s_leg), del->s_leg = NULL; if (del->s_from) su_free(home, del->s_from), del->s_from = NULL; su_free(home, del); } } /** Create a new event. * * The function nea_event_create() creates a new event for the event server. */ nea_event_t *nea_event_create(nea_server_t *nes, nea_watcher_f *callback, nea_emagic_t *context, char const *name, char const *subname, char const *default_content_type, char const *accept) { return nea_event_tcreate(nes, callback, context, name, subname, SIPTAG_CONTENT_TYPE_STR(default_content_type), SIPTAG_ACCEPT_STR(accept), TAG_END()); } /** Create a new event (or subevent) with tags */ nea_event_t *nea_event_tcreate(nea_server_t *nes, nea_watcher_f *callback, nea_emagic_t *context, char const *name, char const *subname, tag_type_t tag, tag_value_t value, ...) { nea_event_t *ev, **pev; ta_list ta; if (nes == NULL || callback == NULL || name == NULL) return NULL; /* Find a matching event */ if (subname == NULL) { for (pev = &nes->nes_events; (ev = *pev); pev = &(*pev)->ev_next) { if (strcmp(ev->ev_event->o_type, name) != 0) continue; SU_DEBUG_5(("nea_event_create(): already event %s\n", name)); return NULL; } } else { size_t len = strlen(name); if (len == 0) return NULL; for (pev = &nes->nes_events; (ev = *pev); pev = &(*pev)->ev_next) { if (strncmp(ev->ev_event->o_type, name, len) != 0 || ev->ev_event->o_type[len] != '.' || strcmp(subname, ev->ev_event->o_type + len + 1) != 0) continue; SU_DEBUG_5(("nea_event_create(): already event %s.%s\n", name, subname)); return NULL; } } ta_start(ta, tag, value); ev = su_zalloc(nes->nes_home, sizeof (*ev)); if (ev) { int reliable = 0; sip_content_type_t const *ct = NULL; sip_accept_t const *ac = NULL; sip_supported_t const *k = NULL; sip_require_t const *rq = NULL; char const *ct_str = NULL, *ac_str = NULL, *k_str = NULL, *rq_str = NULL; unsigned throttle = nes->nes_throttle, min_throttle = nes->nes_min_throttle; int eventlist = nes->nes_eventlist; tl_gets(ta_args(ta), NEATAG_RELIABLE_REF(reliable), NEATAG_THROTTLE_REF(throttle), NEATAG_MINTHROTTLE_REF(min_throttle), NEATAG_EVENTLIST_REF(eventlist), SIPTAG_CONTENT_TYPE_REF(ct), SIPTAG_CONTENT_TYPE_STR_REF(ct_str), SIPTAG_ACCEPT_REF(ac), SIPTAG_ACCEPT_STR_REF(ac_str), SIPTAG_SUPPORTED_REF(k), SIPTAG_SUPPORTED_STR_REF(k_str), SIPTAG_REQUIRE_REF(rq), SIPTAG_REQUIRE_STR_REF(rq_str), TAG_END()); ev->ev_callback = callback; ev->ev_magic = context; ev->ev_event = sip_event_format(nes->nes_home, "%s%s%s", name, subname ? "." : "", subname ? subname : ""); ev->ev_reliable = reliable != 0; ev->ev_throttle = throttle; ev->ev_min_throttle = min_throttle; ev->ev_eventlist = eventlist; if (eventlist && rq == NULL && rq_str == NULL) rq_str = "eventlist"; if (rq) ev->ev_require = sip_require_dup(nes->nes_home, rq); else if (rq_str) ev->ev_require = sip_require_make(nes->nes_home, rq_str); if (ev->ev_event) { #define sip_allow_events_find(k, i) sip_params_find(k->k_items, i) if (!sip_allow_events_find(nes->nes_allow_events, ev->ev_event->o_type)) sip_allow_events_add(nes->nes_home, nes->nes_allow_events, ev->ev_event->o_type); } if (ct) ev->ev_default = sip_accept_make(nes->nes_home, ct->c_type); else ev->ev_default = sip_accept_make(nes->nes_home, ct_str); if (ac == NULL && ac_str == NULL) ac_str = ct ? ct->c_type : ct_str; if (ac) ev->ev_accept = sip_accept_dup(nes->nes_home, ac); else ev->ev_accept = sip_accept_make(nes->nes_home, ac_str ? ac_str : ""); if (k) ev->ev_supported = sip_supported_dup(nes->nes_home, k); else if (k_str) ev->ev_supported = sip_supported_make(nes->nes_home, k_str); ev->ev_prev = pev; *pev = ev; } ta_end(ta); return ev; } /* ----------------------------------------------------------------- */ /** Return magic context bound to nea_event. * * The function returns the magic context bound to the event. * * @param ev pointer to event object * * @return * The function nea_emagic_get() returns the magic context * bound to the event. */ nea_emagic_t *nea_emagic_get(nea_event_t *ev) { assert(ev); return ev->ev_magic; } /* ----------------------------------------------------------------- */ /** Get named event */ nea_event_t *nea_event_get(nea_server_t const *nes, char const *e) { nea_event_t *ev = NULL; for (ev = nes->nes_events; ev; ev = ev->ev_next) if (e == NULL || strcmp(ev->ev_event->o_type, e) == 0) break; return ev; } /* ----------------------------------------------------------------- */ nta_incoming_t *nea_sub_get_request(nea_sub_t *sub) { assert(sub); return sub->s_irq; } /** Invoke the event callback. * * The function nes_watcher_callback() calls the callback provided by the * application using the notifier object. * * @param nes pointer to notifier object * @param ev pointer to event view * @param s pointer to subscription object * @param sip pointer to subscribe request * * @return * The function nes_watcher_callback() returns -1 if the notifier object * has been destroyed by the callback function, 0 otherwise. */ static int nes_watcher_callback(nea_server_t *nes, nea_event_t *ev, nea_sub_t *s, sip_t const *sip, sip_time_t now) { if (!nes->nes_in_callback) { nes->nes_in_callback = 1; if (ev->ev_callback && !s->s_reported) { nea_subnode_t sn[1]; nea_subnode_init(sn, s, now); if (sn->sn_expires == 0 || sn->sn_state == nea_terminated) s->s_reported = 1; ev->ev_callback(nes, ev->ev_magic, ev, sn, sip); } nes->nes_in_callback = 0; if (nes->nes_in_list) return 0; if (nes->nes_pending_destroy) { nea_server_destroy(nes); return -2; } if (sip == NULL && nes->nes_pending_flush) { int flushed = s->s_pending_flush; nea_server_pending_flush(nes); if (flushed) return -1; } } return 0; } /* ----------------------------------------------------------------- */ #if 0 /** Process incoming SUBSCRIBE message. * * The function nea_server_add() is called when the notifier receives a * SUBSCRIBE request without existing event dialog. * * @param nes pointer to notifier * @param local_target optional contact header * @param msg pointer to request message * @param sip pointer to SIP view to request message * * @return * The function nea_server_add() returns 0 if successful, -1 upon an * error. * */ int nea_server_add(nea_server_t *nes, sip_contact_t const *local_target, msg_t *msg, sip_t *sip) { su_home_t *home = nes->nes_home; nea_sub_t *s = NULL; url_t target[1]; s = nea_sub_create(nes); s->s_from = sip_from_dup(home, sip->sip_from); if (local_target == NULL) local_target = nes->nes_eventity_uri; s->s_local = sip_contact_dup(nes->nes_home, local_target); *target = *local_target->m_url; s->s_leg = nta_leg_tcreate(nes->nes_agent, nea_sub_process_incoming, s, SIPTAG_CALL_ID(sip->sip_call_id), SIPTAG_FROM(sip->sip_to), /* local address */ SIPTAG_TO(sip->sip_from), /* remote address */ URLTAG_URL(target), TAG_END()); if (s->s_local && s->s_leg) { nta_leg_tag(s->s_leg, NULL); return 0; } else { nea_sub_destroy(s); return -1; } } #endif static int nea_server_callback(nea_sub_t *nes_as_sub, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip) { return nea_server_add_irq((nea_server_t *)nes_as_sub, leg, NULL, irq, sip); } /** Process incoming request */ int nea_server_add_irq(nea_server_t *nes, nta_leg_t *leg, sip_contact_t const *local_target, nta_incoming_t *irq, sip_t const *sip) { nea_sub_t *s = nea_sub_create(nes); if (s == NULL) return 500; s->s_from = sip_from_dup(nes->nes_home, sip->sip_from); if (local_target == NULL) local_target = nes->nes_eventity_uri; s->s_local = sip_contact_dup(nes->nes_home, local_target); if (leg == NULL || leg == nes->nes_leg) { url_t target[1]; *target = *local_target->m_url; s->s_leg = nta_leg_tcreate(nes->nes_agent, nea_sub_process_incoming, s, SIPTAG_FROM(sip->sip_to), SIPTAG_TO(sip->sip_from), SIPTAG_CALL_ID(sip->sip_call_id), URLTAG_URL((url_string_t *)target), TAG_NULL()); } else { nta_leg_bind(s->s_leg = leg, nea_sub_process_incoming, s); } if (s->s_leg) { if (sip->sip_to->a_tag == NULL) { nta_leg_tag(s->s_leg, NULL); nta_incoming_tag(irq, nta_leg_get_tag(s->s_leg)); } nta_leg_server_route(s->s_leg, sip->sip_record_route, sip->sip_contact); return nea_sub_process_incoming(s, s->s_leg, irq, sip); } else { nea_sub_destroy(s); return 500; } } /* ----------------------------------------------------------------- */ /**Process incoming transactions for event dialog. * * The nea_sub_process_incoming() processes the transactions for event * dialog. Currently, no other methods allowed beside SUBSCRIBE. The * SUBSCRIBE is processed by nea_sub_process_subscribe(). * * @param s pointer to subscriber object * @param leg pointer to NTA dialog object * @param irq pointer to NTA server transaction * @param sip pointer to structure containing SIP headers of the request * * The nea_sub_process_incoming() returns 0 if successful, SIP error code * otherwise. */ int nea_sub_process_incoming(nea_sub_t *s, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip) { int retval; s->s_processing = 1; s->s_irq = irq; switch(sip->sip_request->rq_method) { case sip_method_subscribe: retval = nea_sub_process_subscribe(s, leg, irq, sip); break; default: nta_incoming_treply(irq, retval = SIP_405_METHOD_NOT_ALLOWED, SIPTAG_ALLOW_STR("SUBSCRIBE"), TAG_END()); retval = 405; } s->s_processing = 0; if (s->s_irq) nta_incoming_destroy(irq), s->s_irq = NULL; if (s->s_pending_flush || s->s_state == nea_embryonic) nea_sub_destroy(s); return retval; } /* ----------------------------------------------------------------- */ /**Process incoming SUBSCRIBE transactions for event dialog. * * The function nea_sub_process_subscribe() processes the SUBSCRIBE * transactions for (possible) event dialog. * * @param s pointer to subscriber object * @param leg pointer to NTA dialog object * @param irq pointer to NTA server transaction * @param sip pointer to structure containing SIP headers of the request * * @return * The function nea_sub_process_subscribe() returns 0 if successful, and a * SIP error code otherwise. */ int nea_sub_process_subscribe(nea_sub_t *s, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip) { nea_server_t *nes = s->s_nes; su_home_t *home = nes->nes_home; nea_event_t *ev = NULL, *ev_maybe = NULL; nea_event_view_t *evv = NULL, *evv_maybe = NULL; sip_time_t delta = 0, now = sip_now(); sip_expires_t expires[1] = { SIP_EXPIRES_INIT() }; sip_unsupported_t *unsupported; sip_event_t const *o; sip_accept_t const *ac = NULL, *accept = NULL; sip_accept_t *a0 = NULL, *a, *a_next, **aa; sip_accept_t accept_default[1]; unsigned proposed_throttle; char const *type, *throttle; int once, what, supported_eventlist, require_eventlist; if (sip->sip_payload && !sip->sip_content_type) { nta_incoming_treply(irq, 400, "Missing Content-Type", SIPTAG_SERVER_STR(nes->nes_server), SIPTAG_ALLOW_EVENTS(nes->nes_allow_events), SIPTAG_ALLOW(nes->nes_allow_methods), TAG_NULL()); return 0; } if (sip->sip_expires && sip->sip_expires->ex_delta > 0 && sip->sip_expires->ex_delta < nes->nes_min_expires) { sip_min_expires_t me[1]; sip_min_expires_init(me); me->me_delta = nes->nes_min_expires; nta_incoming_treply(irq, 423, "Subscription Interval Too Small", SIPTAG_ACCEPT(accept), SIPTAG_MIN_EXPIRES(me), SIPTAG_SERVER_STR(nes->nes_server), SIPTAG_ALLOW_EVENTS(nes->nes_allow_events), SIPTAG_ALLOW(nes->nes_allow_methods), TAG_NULL()); return 0; } /* Check features */ if (nes->nes_require) { unsupported = sip_has_unsupported2(nes->nes_home, sip->sip_supported, sip->sip_require, nes->nes_require); if (unsupported) { nta_incoming_treply(irq, SIP_421_EXTENSION_REQUIRED, SIPTAG_REQUIRE(nes->nes_require), SIPTAG_UNSUPPORTED(unsupported), SIPTAG_SERVER_STR(nes->nes_server), SIPTAG_ALLOW_EVENTS(nes->nes_allow_events), SIPTAG_ALLOW(nes->nes_allow_methods), TAG_NULL()); su_free(nes->nes_home, unsupported); return 0; } } supported_eventlist = sip_has_feature(sip->sip_supported, "eventlist"); require_eventlist = sip_has_feature(sip->sip_require, "eventlist"); supported_eventlist = supported_eventlist || require_eventlist; if (s->s_id && (!sip->sip_event || str0cmp(s->s_id->o_type, sip->sip_event->o_type) != 0 || str0cmp(s->s_id->o_id, sip->sip_event->o_id))) { /* Multiple subscriptions per dialog are not supported. */ return nta_incoming_treply(irq, 501, "Multiple subscriptions not implemented", SIPTAG_SERVER_STR(nes->nes_server), TAG_NULL()); } /* Check that subscriber asks for a supported event */ for (once = 0; ev == NULL ;once++) { o = sip->sip_event; /* Check that we have a matching event */ if (o && o->o_type) { for (ev = nes->nes_events; ev; ev = ev->ev_next) { if (strcmp(o->o_type, ev->ev_event->o_type) == 0) { ev_maybe = ev; if (ev->ev_eventlist) { if (supported_eventlist) break; } else { if (!supported_eventlist) break; } } } } if (!ev && !require_eventlist) ev = ev_maybe; if (ev || once) break; /* Ask the application either to 1) add a new event or assing us an event/payload (0), 2) take care of transaction (positive), or 3) drop request (negative). */ if ((what = nes_new_event_callback(nes, &ev, &evv, irq, sip)) < 0) break; if (what > 0) { s->s_irq = NULL; return 0; } } if (ev_maybe == NULL && ev == NULL) { nta_incoming_treply(irq, SIP_489_BAD_EVENT, SIPTAG_SERVER_STR(nes->nes_server), SIPTAG_ALLOW_EVENTS(nes->nes_allow_events), SIPTAG_ALLOW(nes->nes_allow_methods), NULL); return 0; } else if (ev == NULL) { ev = ev_maybe; unsupported = sip_has_unsupported(nes->nes_home, ev->ev_supported, sip->sip_require); nta_incoming_treply(irq, SIP_420_BAD_EXTENSION, SIPTAG_UNSUPPORTED(unsupported), SIPTAG_REQUIRE(ev->ev_require), SIPTAG_SUPPORTED(ev->ev_supported), SIPTAG_SERVER_STR(nes->nes_server), SIPTAG_ALLOW_EVENTS(nes->nes_allow_events), SIPTAG_ALLOW(nes->nes_allow_methods), TAG_NULL()); su_free(nes->nes_home, unsupported); return 0; } if (sip->sip_accept) accept = sip->sip_accept; else if (evv && evv->evv_content_type) { /* Generate accept header from event view specified by application */ sip_accept_init(accept_default); accept_default->ac_type = evv->evv_content_type->c_type; accept_default->ac_subtype = evv->evv_content_type->c_subtype; accept = a0; } else accept = ev->ev_default; for (once = 0; evv == NULL ;once++) { /* If there are multiple accept values with different Q values, insertion sort by Q value */ for (ac = accept->ac_next; ac; ac = ac->ac_next) { if (ac->ac_q != accept->ac_q) { if ((a0 = sip_accept_dup(home, accept))) { /* Sort the accept list by Q values */ for (a = a0, accept = NULL; a; a = a_next) { a_next = a->ac_next; for (aa = (sip_accept_t **)&accept; *aa && msg_q_value((*aa)->ac_q) >= msg_q_value(a->ac_q); aa = &(*aa)->ac_next) ; a->ac_next = *aa; *aa = a; /* Insert */ } } break; } } /* Check that subscriber asks for a supported content type */ for (ac = accept; ac; ac = ac->ac_next) { int i; if (ac->ac_type == NULL || ac->ac_subtype == NULL) continue; /* Check all supported content types v. accept */ for (i = 0; (evv = ev->ev_views[i]); i++) { assert(evv->evv_content_type && evv->evv_content_type->c_type); if (strcmp(ac->ac_type, "*/*") == 0) break; type = evv->evv_content_type->c_type; if ((su_casematch(ac->ac_type, type)) || (su_casematch(ac->ac_subtype, "*") && su_casenmatch(ac->ac_type, type, ac->ac_subtype - ac->ac_type))) { if (evv_maybe == NULL) evv_maybe = evv; } } if (evv) /* Found */ break; } /* Free the sorted Accept list */ for (a = a0; a; a = a_next) a_next = a->ac_next, su_free(home, a); if (!evv) evv = evv_maybe; if (evv || once) break; /* Ask the application either to 1) add a new event view or assign us an event view (0), 2) take care of transaction (positive), or 3) drop request (negative). */ if ((what = nes_new_event_callback(nes, &ev, &evv, irq, sip)) < 0) break; if (what > 0) { s->s_irq = NULL; return 0; } } if (evv == NULL) { SU_DEBUG_3(("nea_server: event %s rejected %u %s\n", ev->ev_event->o_type, SIP_406_NOT_ACCEPTABLE)); /* There is no media acceptable to watcher */ return nta_incoming_treply(irq, SIP_406_NOT_ACCEPTABLE, SIPTAG_ACCEPT(ev->ev_accept), SIPTAG_SERVER_STR(nes->nes_server), SIPTAG_ALLOW_EVENTS(nes->nes_allow_events), SIPTAG_ALLOW(nes->nes_allow_methods), TAG_NULL()); } /* Do not change private view */ if (s->s_view && s->s_view->evv_primary == evv) evv = s->s_view; /* Set throttle */ if (sip->sip_event && (throttle = sip_params_find(sip->sip_event->o_params, "throttle="))) { proposed_throttle = strtoul(throttle, NULL, 10); if (proposed_throttle < evv->evv_min_throttle) proposed_throttle = evv->evv_min_throttle; } else proposed_throttle = evv->evv_throttle; s->s_throttle = proposed_throttle; /* Update route, store remote contact */ nta_leg_server_route(leg, sip->sip_record_route, sip->sip_contact); su_free(home, s->s_remote); s->s_remote = sip_contact_dup(home, sip->sip_contact); /* Store content-type and body */ if (sip->sip_content_type) { su_free(home, s->s_content_type); s->s_content_type = sip_content_type_dup(home, sip->sip_content_type); su_free(home, s->s_payload); s->s_payload = sip_payload_dup(home, sip->sip_payload); } /* Calculate expiration time for subscription */ delta = sip_contact_expires(NULL, sip->sip_expires, sip->sip_date, nes->nes_expires, now); if (delta > nes->nes_max_expires) delta = nes->nes_max_expires; expires->ex_delta = delta; if (s->s_subscribed == 0) s->s_subscribed = now; s->s_expires = now + delta; /* s->s_accept = sip_accept_dup(home, accept); */ if (s->s_id == NULL) s->s_id = sip_event_dup(home, sip->sip_event); s->s_event = ev; s->s_eventlist = supported_eventlist; nea_sub_assign_view(s, evv); s->s_updated = evv->evv_updated - 1; /* Force notify */ if (nes->nes_202_before_notify) { nta_incoming_treply(irq, SIP_202_ACCEPTED, SIPTAG_SERVER_STR(nes->nes_server), SIPTAG_ALLOW_EVENTS(nes->nes_allow_events), SIPTAG_ALLOW(nes->nes_allow_methods), SIPTAG_REQUIRE(ev->ev_require), SIPTAG_SUPPORTED(ev->ev_supported), SIPTAG_EXPIRES(expires), SIPTAG_CONTACT(s->s_local), TAG_END()); nta_incoming_destroy(irq), s->s_irq = irq = NULL; } /* Callback for checking subscriber authorization */ if (nes_watcher_callback(nes, ev, s, sip, now) < 0) { if (irq) { nta_incoming_treply(irq, SIP_503_SERVICE_UNAVAILABLE, TAG_END()); nta_incoming_destroy(irq); } return -1; } evv = s->s_view; /* Callback can change event view */ if (s->s_state == nea_embryonic) nea_sub_auth(s, nea_pending, NEATAG_FAKE(1), TAG_END()); if (s->s_updated != evv->evv_updated && !(irq && s->s_rejected)) nea_sub_notify(nes, s, now, TAG_END()); if (irq) { if (s->s_rejected) nta_incoming_treply(irq, SIP_403_FORBIDDEN, SIPTAG_SERVER_STR(nes->nes_server), TAG_END()); else if (s->s_state == nea_active) nta_incoming_treply(irq, SIP_200_OK, SIPTAG_REQUIRE(ev->ev_require), SIPTAG_SUPPORTED(ev->ev_supported), SIPTAG_EXPIRES(expires), SIPTAG_SERVER_STR(nes->nes_server), SIPTAG_CONTACT(s->s_local), SIPTAG_ALLOW_EVENTS(nes->nes_allow_events), SIPTAG_ALLOW(nes->nes_allow_methods), TAG_END()); else nta_incoming_treply(irq, SIP_202_ACCEPTED, SIPTAG_REQUIRE(ev->ev_require), SIPTAG_SUPPORTED(ev->ev_supported), SIPTAG_EXPIRES(expires), SIPTAG_SERVER_STR(nes->nes_server), SIPTAG_ALLOW_EVENTS(nes->nes_allow_events), SIPTAG_ALLOW(nes->nes_allow_methods), SIPTAG_CONTACT(s->s_local), TAG_END()); } return 0; } /* ----------------------------------------------------------------- */ /**Notify subscriber * * The function nea_sub_notify() sends a notification to the subscriber. The * event type is specified by subscriber event, payload type and payload in * the event view. The responses to the NOTIFY transaction are * processed by response_to_notify(). * * @param nes pointer to the notifier object * @param s pointer to the subscription object * @param now current SIP time (if 0, no body is sent, * but updated Subscription-State header only * @param tag,value,... tag list * */ int nea_sub_notify(nea_server_t *nes, nea_sub_t *s, sip_time_t now, tag_type_t tag, tag_value_t value, ...) { int notified = 0; ta_list ta; int suppress = now != 0; nea_event_t *ev = s->s_event; nea_state_t substate = s->s_state; if (s->s_pending_flush || (s->s_oreq && substate != nea_terminated)) { if (ev && ev->ev_throttling > s->s_updated) ev->ev_throttling = s->s_updated; return 0; } if (s->s_oreq) nta_outgoing_destroy(s->s_oreq), s->s_oreq = NULL; assert(s->s_view); assert(ev); if (suppress && s->s_view->evv_updated == s->s_updated) return 0; if (now == 0) now = sip_now(); if (s->s_notified + s->s_throttle > now && /* Do not throttle state termination notification */ substate != nea_terminated && (long)(s->s_expires - now) > 0) { if (ev->ev_throttling > s->s_updated && !s->s_fake) ev->ev_throttling = s->s_updated; nes->nes_throttled++; return 0; } ta_start(ta, tag, value); { sip_subscription_state_t ss[1]; char expires[32]; sip_param_t params[] = { NULL, NULL, NULL }; char const *reason = NULL; int fake = 0; char reason_buf[64]; unsigned retry_after = (unsigned)-1; char retry_after_buf[64]; int i = 0; nta_response_f *callback; nea_event_view_t *evv = s->s_view; nea_event_queue_t *evq, *n_evq; assert(ev); sip_subscription_state_init(ss); tl_gets(ta_args(ta), NEATAG_REASON_REF(reason), NEATAG_FAKE_REF(fake), /* XXX - semantics??? */ NEATAG_RETRY_AFTER_REF(retry_after), TAG_END()); if (substate == nea_terminated) { if (reason) snprintf(reason_buf, sizeof(reason_buf), "reason=%s", reason), params[i++] = reason_buf; if (retry_after != (unsigned)-1) snprintf(retry_after_buf, sizeof(retry_after_buf), "retry-after=%u", retry_after), params[i++] = retry_after_buf; } else if ((long)(s->s_expires - now) <= 0) { substate = nea_terminated; params[i++] = "reason=timeout"; } else { snprintf(expires, sizeof(expires), "expires=%lu", (unsigned long)(s->s_expires - now)); params[i++] = expires; } ss->ss_params = params; switch (substate) { case nea_extended: ss->ss_substate = s->s_extended; break; case nea_pending: ss->ss_substate = "pending"; break; case nea_active: ss->ss_substate = "active"; break; case nea_terminated: ss->ss_substate = "terminated"; break; /* Do not send notifys for embryonic subscriptions */ case nea_embryonic: ta_end(ta); return 0; } callback = substate != nea_terminated ? response_to_notify : NULL; for (evq = evv->evv_head; evq->evq_next; evq = evq->evq_next) { if (evq->evq_next->evq_updated <= s->s_updated) break; } suppress = (s->s_view->evv_updated == s->s_updated); n_evq = evq->evq_payload ? evq : evv->evv_primary->evv_head; s->s_oreq = nta_outgoing_tcreate(s->s_leg, callback, s, NULL, SIP_METHOD_NOTIFY, NULL, SIPTAG_SUBSCRIPTION_STATE(ss), SIPTAG_REQUIRE(ev->ev_require), SIPTAG_SUPPORTED(ev->ev_supported), SIPTAG_USER_AGENT_STR(nes->nes_server), SIPTAG_CONTACT(s->s_local), SIPTAG_EVENT(s->s_id), TAG_IF(!suppress, SIPTAG_CONTENT_TYPE(n_evq->evq_content_type)), TAG_IF(!suppress, SIPTAG_PAYLOAD(n_evq->evq_payload)), ta_tags(ta)); notified = s->s_oreq != 0; if (notified) { s->s_notified = now; s->s_state = substate; /* XXX - we need state for "waiting" */ s->s_latest = evq->evq_version; /* Application version */ s->s_updated = evq->evq_updated; /* Internal version */ if (ev->ev_throttling > s->s_updated) ev->ev_throttling = s->s_updated; } if (callback == NULL) { nta_outgoing_destroy(s->s_oreq), s->s_oreq = NULL; /* Inform the application of a subscriber leaving the subscription. */ nes_watcher_callback(nes, ev, s, NULL, now); } } ta_end(ta); return notified; } /* ----------------------------------------------------------------- */ /**Process responses to the NOTIFY. * * The response_to_notify() processes the responses to the NOTIFY request. * If there was an error with delivering the NOTIFY, the subscription is * considered terminated. * * @param s pointer to subscription object */ int response_to_notify(nea_sub_t *s, nta_outgoing_t *oreq, sip_t const *sip) { nea_server_t *nes = s->s_nes; int status = sip->sip_status->st_status; sip_time_t now = sip_now(); if (status < 200) return 0; nta_outgoing_destroy(s->s_oreq), s->s_oreq = NULL; if (status < 300) { if (s->s_view->evv_updated != s->s_updated) { if (s->s_notified + s->s_throttle <= now) nea_sub_notify(nes, s, now, TAG_END()); else nes->nes_throttled++; } } if (s->s_state == nea_terminated || status >= 300) { SU_DEBUG_5(("nea_server: removing subscriber " URL_PRINT_FORMAT "\n", URL_PRINT_ARGS(s->s_from->a_url))); /* Inform the application of a subscriber leaving the subscription. */ nes_watcher_callback(nes, s->s_event, s, NULL, now); } return 0; } /* ----------------------------------------------------------------- */ /** Get number of active subscribers. * * The function nea_server_active() counts the number of active subscribers * watching the specified view. If the view is not specified (@a ev is @c * NULL), it counts the number of all subscribers. * * @param nes notifier * @param ev event * * The function nea_server_active() returns number of active subscribers. */ int nea_server_active(nea_server_t *nes, nea_event_t const *ev) { int n = 0; nea_sub_t *s = NULL; /* Count the number of subscribers watching this event */ for (s = nes->nes_subscribers; s ; s = s->s_next) if (!s->s_pending_flush && s->s_state == nea_active && (ev == NULL || ev == s->s_event)) n++; return n; } /** Get number of non-embryonic subscribers. * * The function nea_server_non_embryonic() counts the number of pending, * active or terminated subscribers watching the specified view. If the view * is not specified (@a ev is @c NULL), it counts the number of all * subscribers. * * @param nes notifier * @param ev event view * * The function nea_server_active() returns number of active subscribers. */ int nea_server_non_embryonic(nea_server_t *nes, nea_event_t const *ev) { int n = 0; nea_sub_t *s = NULL; /* Count the number of subscribers watching this event */ for (s = nes->nes_subscribers; s ; s = s->s_next) if (!s->s_pending_flush && s->s_state != nea_embryonic && (ev == NULL || ev == s->s_event)) n++; return n; } /** Set application version number */ int nea_sub_version(nea_sub_t *s, unsigned version) { if (s) return s->s_version = version; return 0; } /** Authorize a subscription. * * Application can modify the subscription state and authorize the user. * The subscription state has following simple state diagram: * * @code * +---------------+ +------------------+ * | | | | * +-----------+ | +---------+ V | +------------+ V +------------+ * | embryonic |-+->| pending |--+-+->| authorized |--+->| terminated | * +-----------+ +---------+ +------------+ +------------+ * * @endcode * * @TAGS * IF NEATAG_VIEW(view) is included in tagged arguments, @a view is assigned * to the subscriber and the content from the view is delivered to the * subscriber. * * If NEATAG_FAKE(1) is included in tags, content marked as 'fake' is * delivered to the subscriber. * * @retval 0 if successful * @retval -1 upon an error */ int nea_sub_auth(nea_sub_t *s, nea_state_t state, tag_type_t tag, tag_value_t value, ...) { ta_list ta; int retval, embryonic, rejected = 0; int fake = 0; char const *reason = NULL; nea_event_view_t *evv = NULL; if (s == NULL) return -1; if (state == nea_embryonic) return -1; if (state < s->s_state) return -1; ta_start(ta, tag, value); embryonic = s->s_state == nea_embryonic; s->s_state = state; if (tl_gets(ta_args(ta), NEATAG_VIEW_REF(evv), TAG_END()) && evv) { nea_sub_assign_view(s, evv); } else { if (tl_gets(ta_args(ta), NEATAG_FAKE_REF(fake), TAG_END())) s->s_fake = fake; if (s->s_view && s->s_view->evv_fake != s->s_fake) { for (evv = s->s_view->evv_primary; evv; evv = evv->evv_next) if (!evv->evv_private && evv->evv_fake == s->s_fake) { nea_sub_assign_view(s, evv); break; } } } tl_gets(ta_args(ta), NEATAG_REASON_REF(reason), TAG_END()); rejected = su_casematch(reason, "rejected"); if (state == nea_terminated && embryonic && rejected && s->s_irq) retval = 0, s->s_rejected = 1; else retval = nea_sub_notify(s->s_nes, s, 0, ta_tags(ta)); ta_end(ta); return retval; } /** Obtain a list of subscribers */ nea_subnode_t const **nea_server_get_subscribers(nea_server_t *nes, nea_event_t const *ev) { nea_sub_t *s; nea_subnode_t **sn_list, *sn; int i, n; sip_time_t now = sip_now(); n = nea_server_non_embryonic(nes, ev); if (n == 0) return NULL; sn_list = su_zalloc(nes->nes_home, (n + 1) * sizeof(sn) + n * sizeof(*sn)); if (sn_list) { sn = (nea_subnode_t *)(sn_list + n + 1); for (i = 0, s = nes->nes_subscribers; s; s = s->s_next) { if (!s->s_pending_flush && s->s_state != nea_embryonic && (ev == NULL || ev == s->s_event)) { assert(i < n); nea_subnode_init(sn, s, now); sn_list[i++] = sn++; } } nes->nes_in_list++; sn_list[i] = NULL; } return (nea_subnode_t const **)sn_list; } /** Free a list of subscriptions. */ void nea_server_free_subscribers(nea_server_t *nes, nea_subnode_t const **sn_list) { if (sn_list) { su_free(nes->nes_home, (void *)sn_list); if (--nes->nes_in_list == 0 && nes->nes_pending_flush) nea_server_pending_flush(nes); } } /* ----------------------------------------------------------------- */ void nes_event_timer(nea_server_t *srvr, su_timer_t *timer, su_timer_arg_t *arg) { nea_server_t *nes = (nea_server_t *) arg; sip_time_t now = sip_now(); nea_sub_t *s = NULL, *s_next = NULL; su_root_t *root = su_timer_root(timer); su_timer_set(timer, nes_event_timer, nes); nes->nes_in_list++; /* Notify and terminate expired subscriptions */ for (s = nes->nes_subscribers; s; s = s_next) { s_next = s->s_next; if (s->s_state == nea_terminated) continue; if ((int)(now - s->s_expires) >= 0) { nea_sub_notify(nes, s, now, TAG_END()); /* Yield so we can handle received packets */ su_root_yield(root); } } if (--nes->nes_in_list == 0 && nes->nes_pending_flush) nea_server_pending_flush(nes); if (nes->nes_throttled) nea_server_notify(nes, NULL); return; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nea/nea_tag.c000066400000000000000000000045051223300710500220630ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE nea_tag.c * @brief Tags for Nokia SIP Transaction API * * @author Pekka Pessi * @author Martti Mela * * @date Created: Tue Jul 24 22:28:34 2001 ppessi */ #include "config.h" #include #include #define TAG_NAMESPACE "nea" #include "sofia-sip/nea.h" #include #include #include tag_typedef_t neatag_any = NSTAG_TYPEDEF(*); tag_typedef_t neatag_min_expires = UINTTAG_TYPEDEF(min_expires); tag_typedef_t neatag_expires = UINTTAG_TYPEDEF(expires); tag_typedef_t neatag_max_expires = UINTTAG_TYPEDEF(max_expires); tag_typedef_t neatag_throttle = UINTTAG_TYPEDEF(throttle); tag_typedef_t neatag_minthrottle = UINTTAG_TYPEDEF(minthrottle); tag_typedef_t neatag_dialog = PTRTAG_TYPEDEF(dialog); tag_typedef_t neatag_eventlist = BOOLTAG_TYPEDEF(eventlist); tag_typedef_t neatag_fake = BOOLTAG_TYPEDEF(fake); tag_typedef_t neatag_reason = STRTAG_TYPEDEF(reason); tag_typedef_t neatag_retry_after = UINTTAG_TYPEDEF(retry_after); tag_typedef_t neatag_exstate = STRTAG_TYPEDEF(exstate); tag_typedef_t neatag_version = INTTAG_TYPEDEF(version); tag_typedef_t neatag_view = PTRTAG_TYPEDEF(view); tag_typedef_t neatag_evmagic = PTRTAG_TYPEDEF(evmagic); tag_typedef_t neatag_reliable = BOOLTAG_TYPEDEF(reliable); tag_typedef_t neatag_sub = PTRTAG_TYPEDEF(sub); tag_typedef_t neatag_strict_3265 = BOOLTAG_TYPEDEF(strict_3265); sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nea/sofia-sip/000077500000000000000000000000001223300710500222075ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nea/sofia-sip/nea.h000066400000000000000000000264061223300710500231330ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef NEA_H /** Defined when has been included. */ #define NEA_H /**@file sofia-sip/nea.h * @brief Event API for SIP * * @author Pekka Pessi * @author Martti Mela * * @date Created: Fri Feb 7 13:23:44 EET 2003 ppessi */ #ifndef SU_ALLOC_H #include #endif #include #ifndef NTA_H #include #endif #ifndef NEA_TAG_H #include #endif SOFIA_BEGIN_DECLS #define NEA_VERSION 3.0 #define NEA_VERSION_STR "3.0" #define NEA_DEFAULT_EXPIRES 3600 /** Event notifier object. */ typedef struct nea_server_s nea_server_t; /** Subscription object. */ typedef struct nea_sub_s nea_sub_t; /** Event. */ typedef struct nea_event_s nea_event_t; /** Event view. */ typedef struct nea_event_view_s nea_event_view_t; #ifndef NEA_SMAGIC_T #define NEA_SMAGIC_T struct nea_smagic_t #endif /** NEA server context */ typedef NEA_SMAGIC_T nea_smagic_t; #ifndef NEA_EMAGIC_T #define NEA_EMAGIC_T struct nea_emagic_t #endif /** NEA server event context */ typedef NEA_EMAGIC_T nea_emagic_t; #ifndef NEA_EVMAGIC_T #define NEA_EVMAGIC_T struct nea_evmagic_t #endif /** Event view context */ typedef NEA_EVMAGIC_T nea_evmagic_t; /** Description of subscription */ typedef struct nea_subnode_t { nea_state_t sn_state; /**< Subscription state */ unsigned sn_fake; /**< True if subscriber is given * fake contents. */ unsigned sn_eventlist; /**< Subscriber supports eventlist */ nea_sub_t *sn_subscriber; /**< Pointer to subscriber object */ nea_event_t *sn_event; /**< Event */ sip_from_t const *sn_remote; /**< Identity of subscriber */ sip_contact_t const *sn_contact; /**< Contact of subscriber */ /** Content-Type of SUBSCRIBE body (filter). */ sip_content_type_t const *sn_content_type; sip_payload_t const *sn_payload; /**< Body of subscribe*/ unsigned sn_expires; /**< When subscription expires */ unsigned sn_latest; /**< Latest notification version */ unsigned sn_throttle; /**< Throttle value */ unsigned sn_version; /**< Latest notified version # by application */ sip_time_t sn_notified; /**< When latest notify was sent */ sip_time_t sn_subscribed; /**< When first SUBSCRIBE was recv */ nea_event_view_t *sn_view; /**< Event view for this subscriber */ } nea_subnode_t; /** Multiple content types per event. */ typedef struct nea_payloads_s nea_payloads_t; /**Unknown event callback. * * The event server invokes this callback function when it has received a * request for an unknown event or event with unknown content type. * * The callback may be called twice for one watcher, once for an unknown * event, another time for an unknown content type. * * @retval 1 application takes care of responding to request * @retval 0 application has added new event or payload format * @retval -1 nea server rejects request */ typedef int (nea_new_event_f)(nea_smagic_t *context, nea_server_t *nes, nea_event_t **event_p, nea_event_view_t **view_p, nta_incoming_t *irq, sip_t const *sip); /** Create a notifier server */ SOFIAPUBFUN nea_server_t *nea_server_create(nta_agent_t *agent, su_root_t *root, url_t const *url, int max_subs, nea_new_event_f *callback, nea_smagic_t *context, tag_type_t tag, tag_value_t value, ...); /** Shutdown an event server */ SOFIAPUBFUN int nea_server_shutdown(nea_server_t *nes, int retry_after); /** Destroy a server */ SOFIAPUBFUN void nea_server_destroy(nea_server_t *nes); /** Zap terminated subscribtions. */ SOFIAPUBFUN void nea_server_flush(nea_server_t *nes, nea_event_t *event); /** Update event information */ SOFIAPUBFUN int nea_server_update(nea_server_t *nes, nea_event_t *ev, tag_type_t tag, tag_value_t value, ...); /** Add a new subscriber from subscribe transaction to an existing notifier. */ SOFIAPUBFUN int nea_server_add_irq(nea_server_t *nes, nta_leg_t *leg, sip_contact_t const *local_target, nta_incoming_t *irq, sip_t const *sip); /** QAUTH callback function type. * * The event server invokes this callback function upon each incoming * SUBSCRIBE transaction when the subscription has expired. The @a sip is * NULL if the subscription has expired. * * The application determines if the subscription is authorized and relays * the decision to event server via nea_server_auth() function. */ typedef void (nea_watcher_f)(nea_server_t *nes, nea_emagic_t *context, nea_event_t *event, nea_subnode_t *subnode, sip_t const *sip); /** Create a new event (or subevent) */ SOFIAPUBFUN nea_event_t *nea_event_create(nea_server_t *nes, nea_watcher_f *callback, nea_emagic_t *context, char const *name, char const *subname, char const *default_content_type, char const *accept); /** Create a new event (or subevent) with tags */ SOFIAPUBFUN nea_event_t *nea_event_tcreate(nea_server_t *nes, nea_watcher_f *callback, nea_emagic_t *context, char const *name, char const *subname, tag_type_t, tag_value_t, ...); /** Return magic context bind to nea_event */ SOFIAPUBFUN nea_emagic_t *nea_emagic_get(nea_event_t *event); /** Find a nea event object with given event name */ SOFIAPUBFUN nea_event_t *nea_event_get(nea_server_t const *, char const *name); /** Get number of active subscribers */ SOFIAPUBFUN int nea_server_active(nea_server_t *nes, nea_event_t const *ev); /** Get number of (non-embryonic) subscribers. */ int nea_server_non_embryonic(nea_server_t *nes, nea_event_t const *ev); /** Obtain a list of subscriptions. */ SOFIAPUBFUN nea_subnode_t const **nea_server_get_subscribers(nea_server_t *nes, nea_event_t const *ev); /** Free a list of subscriptions. */ SOFIAPUBFUN void nea_server_free_subscribers(nea_server_t *nes, nea_subnode_t const **); /** Notify subscribers */ SOFIAPUBFUN int nea_server_notify(nea_server_t *nes, nea_event_t *ev); /** Notify a subscriber */ SOFIAPUBFUN int nea_server_notify_one(nea_server_t *nes, nea_event_t *ev, nea_sub_t *ns); #define nea_server_auth nea_sub_auth /** Get nta_incoming_t from nea_sub_t */ SOFIAPUBFUN nta_incoming_t *nea_sub_get_request(nea_sub_t *sub); /** Authorize a subscription */ SOFIAPUBFUN int nea_sub_auth(nea_sub_t *, nea_state_t state, tag_type_t, tag_value_t, ...); /** Get nta_incoming_t from sn->sn_subscriber */ SOFIAPUBFUN nta_incoming_t *nea_subnode_get_incoming(nea_subnode_t *sn); /** Set subscriber version sequence */ SOFIAPUBFUN int nea_sub_version(nea_sub_t *, unsigned); /** Return time until next notification can be sent */ SOFIAPUBFUN unsigned nea_sub_pending(nea_sub_t const *); #if 0 /** Do a remote qauth. * * The function nea_server_qauth() is given as q_callback pointer * to nea_server_create() if remote authentication from url is desired. */ void nea_server_qauth(nea_server_t *nes, nea_emagic_t *context, nea_sub_t *subscriber, sip_t const *sip); #endif /** Get primary event view for given content type */ SOFIAPUBFUN nea_event_view_t *nea_event_view(nea_event_t *, char const *content_type); /** Get a content type for event's payload */ SOFIAPUBFUN sip_content_type_t const *nea_view_content_type(nea_event_view_t const *); /** Get actual payload for an event */ SOFIAPUBFUN sip_payload_t const *nea_view_payload(nea_event_view_t *); /** Create a private event view */ SOFIAPUBFUN nea_event_view_t *nea_view_create(nea_server_t *nes, nea_event_t *ev, nea_evmagic_t *magic, tag_type_t tag, tag_value_t value, ...); /** Destroy a private event view */ SOFIAPUBFUN void nea_view_destroy(nea_server_t *nes, nea_event_view_t *ev); SOFIAPUBFUN nea_evmagic_t *nea_view_magic(nea_event_view_t const *); SOFIAPUBFUN void nea_view_set_magic(nea_event_view_t *, nea_evmagic_t *magic); SOFIAPUBFUN unsigned nea_view_version(nea_event_view_t const *); /** Reliable notify */ #define NEATAG_RELIABLE(x) neatag_reliable, tag_bool_v((x)) SOFIAPUBVAR tag_typedef_t neatag_reliable; #define NEATAG_RELIABLE_REF(x) neatag_reliable_ref, tag_bool_vr((&x)) SOFIAPUBVAR tag_typedef_t neatag_reliable_ref; /** Event view handle */ #define NEATAG_VIEW(x) neatag_view, tag_ptr_v((x)) SOFIAPUBVAR tag_typedef_t neatag_view; #define NEATAG_VIEW_REF(x) neatag_view_ref, tag_ptr_vr((&x), (x)) SOFIAPUBVAR tag_typedef_t neatag_view_ref; /** Event view magic. */ #define NEATAG_EVMAGIC(x) neatag_evmagic, tag_ptr_v((x)) SOFIAPUBVAR tag_typedef_t neatag_evmagic; #define NEATAG_EVMAGIC_REF(x) neatag_evmagic_ref, tag_ptr_vr((&x), (x)) SOFIAPUBVAR tag_typedef_t neatag_evmagic_ref; /** tag for nea_sub_t */ #define NEATAG_SUB(x) neatag_sub, tag_ptr_v((x)) SOFIAPUBVAR tag_typedef_t neatag_sub; #define NEATAG_SUB_REF(x) neatag_sub_ref, tag_ptr_vr((&x), (x)) SOFIAPUBVAR tag_typedef_t neatag_sub_ref; /* ====================================================================== */ /* Watcher side */ /** NEA Event Watcher */ typedef struct nea_s nea_t; #ifndef NEA_MAGIC_T #define NEA_MAGIC_T struct nea_magic_t #endif /** NEA Event Agent context */ typedef NEA_MAGIC_T nea_magic_t; /** Event notification callback type. * * This callback is called also when initial or refresh subscribe transaction * completes with the transaction result in @a sip. */ typedef int (*nea_notify_f)(nea_t *nea, nea_magic_t *context, sip_t const *sip); /* ====================================================================== */ /* Client side */ /** Create a subscription agent. */ SOFIAPUBFUN nea_t *nea_create(nta_agent_t *agent, su_root_t *root, nea_notify_f no_callback, nea_magic_t *context, tag_type_t tag, tag_value_t value, ...); /** Update SUBSCRIBE payload (filter rules) */ SOFIAPUBFUN int nea_update(nea_t *nea, tag_type_t tag, tag_value_t value, ...); /** Unsubscribe agent. */ SOFIAPUBFUN void nea_end(nea_t *agent); /** Destroy a subscription agent. */ SOFIAPUBFUN void nea_destroy(nea_t *agent); SOFIAPUBFUN char const *nea_default_content_type(char const *event); SOFIA_END_DECLS #endif /* !defined(NEA_H) */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nea/sofia-sip/nea_tag.h000066400000000000000000000134541223300710500237650ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef NEA_TAG_H /** Defined when has been included. */ #define NEA_TAG_H /**@file sofia-sip/nea_tag.h * @brief Tags for Nokia User Agent Library * * @author Pekka Pessi * @author Martti Mela * * @date Created: Mon Nov 28 18:54:26 EET 2005 mela */ #ifndef SU_TAG_H #include #endif #ifndef URL_TAG_H #include #endif #ifndef SIP_TAG_H #include #endif #ifndef NTA_TAG_H #include #endif SOFIA_BEGIN_DECLS /** Event states */ typedef enum { nea_extended = -1, nea_embryonic = 0, /** Before first notify */ nea_pending, nea_active, nea_terminated } nea_state_t; /** Filter tag matching any nea tag. */ #define NEATAG_ANY() neatag_any, ((tag_value_t)0) SOFIAPUBVAR tag_typedef_t neatag_any; /** Specify the minimum duration of a subscription (by default, 15 minutes) */ #define NEATAG_MIN_EXPIRES(x) neatag_min_expires, tag_uint_v((x)) SOFIAPUBVAR tag_typedef_t neatag_min_expires; #define NEATAG_MIN_EXPIRES_REF(x) neatag_min_expires_ref, tag_uint_vr((&x)) SOFIAPUBVAR tag_typedef_t neatag_min_expires_ref; #define NEATAG_MINSUB(x) neatag_min_expires, tag_uint_v((x)) #define NEATAG_MINSUB_REF(x) neatag_min_expires_ref, tag_uint_vr((&x)) /** Specify the default duration of a subscription (by default, 60 minutes) */ #define NEATAG_EXPIRES(x) neatag_expires, tag_uint_v((x)) SOFIAPUBVAR tag_typedef_t neatag_expires; #define NEATAG_EXPIRES_REF(x) neatag_expires_ref, tag_uint_vr((&x)) SOFIAPUBVAR tag_typedef_t neatag_expires_ref; /** Specify the maximum duration of a subscription (by default, 24 hours) */ #define NEATAG_MAX_EXPIRES(x) neatag_max_expires, tag_uint_v((x)) SOFIAPUBVAR tag_typedef_t neatag_max_expires; #define NEATAG_MAX_EXPIRES_REF(x) neatag_max_expires_ref, tag_uint_vr((&x)) SOFIAPUBVAR tag_typedef_t neatag_max_expires_ref; /** Indicate/require support for "eventlist" feature. */ #define NEATAG_EVENTLIST(x) neatag_eventlist, tag_bool_v((x)) SOFIAPUBVAR tag_typedef_t neatag_eventlist; #define NEATAG_EVENTLIST_REF(x) neatag_eventlist_ref, tag_bool_vr((&x)) SOFIAPUBVAR tag_typedef_t neatag_eventlist_ref; /** Specify the default throttle value for subscription. */ #define NEATAG_THROTTLE(x) neatag_throttle, tag_uint_v((x)) SOFIAPUBVAR tag_typedef_t neatag_throttle; #define NEATAG_THROTTLE_REF(x) neatag_throttle_ref, tag_uint_vr((&x)) SOFIAPUBVAR tag_typedef_t neatag_throttle_ref; /** Specify the minimum throttle value for subscription. */ #define NEATAG_MINTHROTTLE(x) neatag_minthrottle, tag_uint_v((x)) SOFIAPUBVAR tag_typedef_t neatag_minthrottle; #define NEATAG_MINTHROTTLE_REF(x) neatag_minthrottle_ref, tag_uint_vr((&x)) SOFIAPUBVAR tag_typedef_t neatag_minthrottle_ref; /** Specify dialog handle */ #define NEATAG_DIALOG(x) neatag_dialog, tag_ptr_v((x)) SOFIAPUBVAR tag_typedef_t neatag_dialog; #define NEATAG_DIALOG_REF(x) neatag_dialog_ref, tag_ptr_vr((&x), (x)) SOFIAPUBVAR tag_typedef_t neatag_dialog_ref; /* Server-specific tags */ /** Pass pointer to subscription */ #define NEATAG_SUB(x) neatag_sub, tag_ptr_v((x)) SOFIAPUBVAR tag_typedef_t neatag_sub; #define NEATAG_SUB_REF(x) neatag_sub_ref, tag_ptr_vr((&x), (x)) SOFIAPUBVAR tag_typedef_t neatag_sub_ref; /** Use fake content. @sa nea_sub_auth() and nea_server_update(). */ #define NEATAG_FAKE(x) neatag_fake, tag_bool_v((x)) SOFIAPUBVAR tag_typedef_t neatag_fake; #define NEATAG_FAKE_REF(x) neatag_fake_ref, tag_bool_vr((&x)) SOFIAPUBVAR tag_typedef_t neatag_fake_ref; /** Specify reason for termination */ #define NEATAG_REASON(x) neatag_reason, tag_str_v((x)) SOFIAPUBVAR tag_typedef_t neatag_reason; #define NEATAG_REASON_REF(x) neatag_reason_ref, tag_str_vr((&x)) SOFIAPUBVAR tag_typedef_t neatag_reason_ref; /** Specify retry-after for termination */ #define NEATAG_RETRY_AFTER(x) neatag_retry_after, tag_uint_v((x)) SOFIAPUBVAR tag_typedef_t neatag_retry_after; #define NEATAG_RETRY_AFTER_REF(x) neatag_retry_after_ref, tag_uint_vr((&x)) SOFIAPUBVAR tag_typedef_t neatag_retry_after_ref; /** Specify extended state for subscription-state */ #define NEATAG_EXSTATE(x) neatag_exstate, tag_str_v((x)) SOFIAPUBVAR tag_typedef_t neatag_exstate; #define NEATAG_EXSTATE_REF(x) neatag_exstate_ref, tag_str_vr((&x)) SOFIAPUBVAR tag_typedef_t neatag_exstate_ref; /** Do not try to conform pre-3265 notifiers/watchers */ #define NEATAG_STRICT_3265(x) neatag_strict_3265, tag_bool_v((x)) SOFIAPUBVAR tag_typedef_t neatag_strict_3265; #define NEATAG_STRICT_3265_REF(x) neatag_strict_3265_ref, tag_bool_vr((&x)) SOFIAPUBVAR tag_typedef_t neatag_strict_3265_ref; /** Version number of content */ #define NEATAG_VERSION(x) neatag_version, tag_uint_v((x)) SOFIAPUBVAR tag_typedef_t neatag_version; #define NEATAG_VERSION_REF(x) neatag_version_ref, tag_uint_vr((&x)) SOFIAPUBVAR tag_typedef_t neatag_version_ref; /** List of all NEA tags. */ /* extern tag_type_t nea_tag_list[]; */ SOFIA_END_DECLS #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/000077500000000000000000000000001223300710500203345ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/ChangeLog000066400000000000000000000057421223300710500221160ustar00rootroot000000000000002005-11-08 Pekka Pessi * Renamed nta_test.c as test_nta.c. 2005-10-21 Pekka Pessi * Fixed server-rport feature in nta.c. M ./libsofia-sip-ua/nta/nta.c -2 +2 * Fixed agent_init_contact() in nta/nta.c. The logic for selecting transport parameter for primary contact was flawed. Added some tests, too. M ./libsofia-sip-ua/nta/nta.c -9 +20 M ./libsofia-sip-ua/nta/nta_test.c +54 2005-10-15 Pekka Pessi * Fix callerpref bug #1326727. Copying Accept-Contact, Reject-Contact, and Request-Disposition from original request to ACK/CANCEL. M ./libsofia-sip-ua/nta/nta.c -1 +5 * Fixed socket() if AF_INET6 is used. M ./libsofia-sip-ua/nta/nta_test.c -3 +3 * Removed Last modified. M ./libsofia-sip-ua/nta/nta.c -1 M ./libsofia-sip-ua/nta/nta.h -1 M ./libsofia-sip-ua/nta/nta_compat.c -1 M ./libsofia-sip-ua/nta/nta_compat.h -1 M ./libsofia-sip-ua/nta/nta_dll.h -1 M ./libsofia-sip-ua/nta/nta_internal.h -1 M ./libsofia-sip-ua/nta/nta_stateless.h -1 M ./libsofia-sip-ua/nta/nta_tag.c -1 M ./libsofia-sip-ua/nta/nta_tag.h -1 M ./libsofia-sip-ua/nta/nta_test.c -1 M ./libsofia-sip-ua/nta/nta_tport.h -1 M ./libsofia-sip-ua/nta/portbind.c -1 M ./libsofia-sip-ua/nta/sl_read_payload.c -1 M ./libsofia-sip-ua/nta/sl_utils.h -1 M ./libsofia-sip-ua/nta/sl_utils_log.c -1 M ./libsofia-sip-ua/nta/sl_utils_print.c -1 2005-10-12 Pekka Pessi * Contact generated by nta now contains URL transport parameter. The transport=UDP was left out from contact URL always. Now it is left out only if both UDP and TCP are supported. Added utility function sip_contact_create_from_via_with_transport(). M ./libsofia-sip-ua/nta/nta.c -2 +14 M ./libsofia-sip-ua/sip/sip_util.c -10 +28 M ./libsofia-sip-ua/sip/sip_util.h +6 2005-10-10 Pekka Pessi * Fixed memory leak in nta_agent_create()/nta_agent_destroy(). M ./libsofia-sip-ua/nta/nta.c -2 +2 2005-10-04 Pekka Pessi * Added agent.pem and cafile.pem for TLS testing. 2005-08-29 Pekka Pessi * nta.c (nta_agent_set_params()): Returning -1 upon an error. 2005-08-26 Pekka Pessi * nta.c, nta_test.c: Fixed alias usage. 2005-08-10 Pekka Pessi * Now we can start agent without any transport interfaces. Added flag for disabling server-side rport. 2005-08-03 Pekka Pessi * Fixed running tests on IPv6. Added portbind. 2005-07-14 Pekka Pessi * nta_internal.h, nta_tag.h, nta_tag.c, nta.c: Added bitmasks for detecting parsing errors. * nta.c: Accept CANCELs for non-INVITEs, too. 2005-07-20 Pekka Pessi * run_nta_test: Fixed portbind/bind test. 2005-07-18 Kai Vehmanen * Initial import of the module to Sofia-SIP tree. sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/Doxyfile.in000066400000000000000000000015011223300710500224440ustar00rootroot00000000000000PROJECT_NAME = "nta" OUTPUT_DIRECTORY = ../docs/html/nta INPUT = @srcdir@/nta.docs @srcdir@/sofia-sip @srcdir@ . @INCLUDE_PATH = . @srcdir@ @INCLUDE = ../docs/Doxyfile.conf TAGFILES += ../docs/su.doxytags=../su TAGFILES += ../docs/ipt.doxytags=../ipt TAGFILES += ../docs/bnf.doxytags=../bnf TAGFILES += ../docs/url.doxytags=../url TAGFILES += ../docs/msg.doxytags=../msg TAGFILES += ../docs/sip.doxytags=../sip TAGFILES += ../docs/sresolv.doxytags=../sresolv TAGFILES += ../docs/tport.doxytags=../tport TAGFILES += ../docs/nua.doxytags=../nua GENERATE_TAGFILE = ../docs/nta.doxytags EXCLUDE_PATTERNS += sl_*.h sl_*.c nta_compat.* ALIASES += @INCLUDE_PATH = . @srcdir@ @INCLUDE = ../sip/sip.doxyaliasessofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/Makefile.am000066400000000000000000000047131223300710500223750ustar00rootroot00000000000000# # Makefile.am for nta module # # Copyright (C) 2005,2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # ---------------------------------------------------------------------- # Header paths INCLUDES = -I$(srcdir)/../ipt -I../ipt \ -I$(srcdir)/../msg -I../msg \ -I$(srcdir)/../sip -I../sip \ -I$(srcdir)/../bnf -I../bnf \ -I$(srcdir)/../sresolv -I../sresolv \ -I$(srcdir)/../tport -I../tport \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../features -I../features \ -I$(srcdir)/../su -I../su \ -I$(top_srcdir)/s2check \ -I$(srcdir)/../stun -I ../stun # ---------------------------------------------------------------------- # Build targets noinst_LTLIBRARIES = libnta.la check_PROGRAMS = check_nta test_nta_api test_nta portbind dist_noinst_SCRIPTS = run_check_nta run_test_nta_api run_test_nta TESTS = run_check_nta run_test_nta_api run_test_nta TESTS_ENVIRONMENT = $(SHELL) # ---------------------------------------------------------------------- # Rules for building the targets BUILT_SOURCES = nta_tag_ref.c nobase_include_sofia_HEADERS = \ sofia-sip/nta.h sofia-sip/nta_stateless.h \ sofia-sip/nta_tport.h sofia-sip/nta_tag.h \ sofia-sip/sl_utils.h libnta_la_SOURCES = nta.c nta_check.c nta_tag.c nta_tag_ref.c \ nta_internal.h \ sl_utils_print.c sl_utils_log.c \ sl_read_payload.c COVERAGE_INPUT = $(libnta_la_SOURCES) $(include_sofia_HEADERS) LDADD = libnta.la \ ../ipt/libipt.la \ ../sip/libsip.la \ ../features/libfeatures.la \ ../sresolv/libsresolv.la \ ../tport/libtport.la \ ../http/libhttp.la \ ../stun/libstun.la \ ../url/liburl.la \ ../msg/libmsg.la \ ../bnf/libbnf.la \ ../su/libsu.la \ ${top_builddir}/s2check/libs2.a test_nta_LDFLAGS = -static MOSTLYCLEANFILES += .test[0-9]* if HAVE_CHECK check_nta_SOURCES = check_nta.h \ check_nta_api.c \ check_nta_client.c \ check_nta_server.c \ check_nta.c check_nta_LDADD = ${LDADD} @CHECK_LIBS@ else check_nta_SOURCES = $(top_srcdir)/s2check/exit77.c endif # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST = nta.docs sl_utils.docs \ agent.pem cafile.pem \ invite.msc $(BUILT_SOURCES) # ---------------------------------------------------------------------- # Sofia specific rules include $(top_srcdir)/rules/sofia.am # Generate list of nta tags TAG_DLL_FLAGS = LIST=nta_tag_listsofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/Makefile.in000066400000000000000000001507031223300710500224070ustar00rootroot00000000000000# Makefile.in generated by automake 1.14 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 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 nta module # # Copyright (C) 2005,2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # ---------------------------------------------------------------------- # Header paths # common Makefile targets for libsofia-sip-ua(-glib) modules # ---------------------------------------------------------- # # run tests with valgrind # # Copyright (C) 2007 Nokia Corporation. # 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 file contains free software from Makefile.in by the Free Software # Foundation: # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 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. # # Generate lcov output # # # Copyright (C) 2007 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # # Silent compilation w/ Automake 1.9 or 1.10 # ---------------------------------------------------------- # Automake 1.9.6 is not clever enough to override suffix rules within if # if SOFIA_COMPILE_SILENT VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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@ check_PROGRAMS = check_nta$(EXEEXT) test_nta_api$(EXEEXT) \ test_nta$(EXEEXT) portbind$(EXEEXT) DIST_COMMON = $(top_srcdir)/rules/sofia.am \ $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am \ $(top_srcdir)/rules/silent.am $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(srcdir)/Doxyfile.in \ $(dist_noinst_SCRIPTS) $(top_srcdir)/depcomp \ $(nobase_include_sofia_HEADERS) $(top_srcdir)/test-driver \ ChangeLog # Use with --enable-ndebug @NDEBUG_TRUE@am__append_1 = -DNDEBUG @HAVE_GENPNG_TRUE@@HAVE_LCOV_TRUE@am__append_2 = --frames @HAVE_LCOV_TRUE@am__append_3 = lcov lcov-report lcov-rerun clean-lcov covcheck uncovered subdir = libsofia-sip-ua/nta ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(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)/m4/sac-coverage.m4 \ $(top_srcdir)/m4/sac-general.m4 \ $(top_srcdir)/m4/sac-openssl.m4 \ $(top_srcdir)/m4/sac-pkg-config.m4 $(top_srcdir)/m4/sac-su2.m4 \ $(top_srcdir)/m4/sac-tport.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libsofia-sip-ua/su/sofia-sip/su_configure.h CONFIG_CLEAN_FILES = Doxyfile CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libnta_la_LIBADD = am_libnta_la_OBJECTS = nta.lo nta_check.lo nta_tag.lo nta_tag_ref.lo \ sl_utils_print.lo sl_utils_log.lo sl_read_payload.lo libnta_la_OBJECTS = $(am_libnta_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__check_nta_SOURCES_DIST = $(top_srcdir)/s2check/exit77.c \ check_nta.h check_nta_api.c check_nta_client.c \ check_nta_server.c check_nta.c @HAVE_CHECK_FALSE@am_check_nta_OBJECTS = exit77.$(OBJEXT) @HAVE_CHECK_TRUE@am_check_nta_OBJECTS = check_nta_api.$(OBJEXT) \ @HAVE_CHECK_TRUE@ check_nta_client.$(OBJEXT) \ @HAVE_CHECK_TRUE@ check_nta_server.$(OBJEXT) \ @HAVE_CHECK_TRUE@ check_nta.$(OBJEXT) check_nta_OBJECTS = $(am_check_nta_OBJECTS) am__DEPENDENCIES_1 = am__DEPENDENCIES_2 = libnta.la ../ipt/libipt.la ../sip/libsip.la \ ../features/libfeatures.la ../sresolv/libsresolv.la \ ../tport/libtport.la ../http/libhttp.la ../stun/libstun.la \ ../url/liburl.la ../msg/libmsg.la ../bnf/libbnf.la \ ../su/libsu.la ${top_builddir}/s2check/libs2.a \ $(am__DEPENDENCIES_1) @HAVE_CHECK_TRUE@check_nta_DEPENDENCIES = $(am__DEPENDENCIES_2) portbind_SOURCES = portbind.c portbind_OBJECTS = portbind.$(OBJEXT) portbind_LDADD = $(LDADD) portbind_DEPENDENCIES = libnta.la ../ipt/libipt.la ../sip/libsip.la \ ../features/libfeatures.la ../sresolv/libsresolv.la \ ../tport/libtport.la ../http/libhttp.la ../stun/libstun.la \ ../url/liburl.la ../msg/libmsg.la ../bnf/libbnf.la \ ../su/libsu.la ${top_builddir}/s2check/libs2.a \ $(am__DEPENDENCIES_1) test_nta_SOURCES = test_nta.c test_nta_OBJECTS = test_nta.$(OBJEXT) test_nta_LDADD = $(LDADD) test_nta_DEPENDENCIES = libnta.la ../ipt/libipt.la ../sip/libsip.la \ ../features/libfeatures.la ../sresolv/libsresolv.la \ ../tport/libtport.la ../http/libhttp.la ../stun/libstun.la \ ../url/liburl.la ../msg/libmsg.la ../bnf/libbnf.la \ ../su/libsu.la ${top_builddir}/s2check/libs2.a \ $(am__DEPENDENCIES_1) test_nta_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(test_nta_LDFLAGS) $(LDFLAGS) -o $@ test_nta_api_SOURCES = test_nta_api.c test_nta_api_OBJECTS = test_nta_api.$(OBJEXT) test_nta_api_LDADD = $(LDADD) test_nta_api_DEPENDENCIES = libnta.la ../ipt/libipt.la \ ../sip/libsip.la ../features/libfeatures.la \ ../sresolv/libsresolv.la ../tport/libtport.la \ ../http/libhttp.la ../stun/libstun.la ../url/liburl.la \ ../msg/libmsg.la ../bnf/libbnf.la ../su/libsu.la \ ${top_builddir}/s2check/libs2.a $(am__DEPENDENCIES_1) SCRIPTS = $(dist_noinst_SCRIPTS) 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) -I$(top_builddir)/libsofia-sip-ua/su/sofia-sip depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f 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) 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 = $(libnta_la_SOURCES) $(check_nta_SOURCES) portbind.c \ test_nta.c test_nta_api.c DIST_SOURCES = $(libnta_la_SOURCES) $(am__check_nta_SOURCES_DIST) \ portbind.c test_nta.c test_nta_api.c 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)$(include_sofiadir)" HEADERS = $(nobase_include_sofia_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)` 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=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ 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_DRIVER = $(SHELL) $(top_srcdir)/test-driver 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) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CHECK_CFLAGS = @CHECK_CFLAGS@ CHECK_LIBS = @CHECK_LIBS@ COVERAGE_FLAGS = @COVERAGE_FLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CWFLAG = @CWFLAG@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV = @GCOV@ GENHTML = @GENHTML@ GENPNG = @GENPNG@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GLIB_VERSION = @GLIB_VERSION@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVER_SOFIA_SIP_UA_AGE = @LIBVER_SOFIA_SIP_UA_AGE@ LIBVER_SOFIA_SIP_UA_CUR = @LIBVER_SOFIA_SIP_UA_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_AGE = @LIBVER_SOFIA_SIP_UA_GLIB_AGE@ LIBVER_SOFIA_SIP_UA_GLIB_CUR = @LIBVER_SOFIA_SIP_UA_GLIB_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_REV = @LIBVER_SOFIA_SIP_UA_GLIB_REV@ LIBVER_SOFIA_SIP_UA_GLIB_SOVER = @LIBVER_SOFIA_SIP_UA_GLIB_SOVER@ LIBVER_SOFIA_SIP_UA_REV = @LIBVER_SOFIA_SIP_UA_REV@ LIBVER_SOFIA_SIP_UA_SOVER = @LIBVER_SOFIA_SIP_UA_SOVER@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MINGW_ENVIRONMENT = @MINGW_ENVIRONMENT@ MKDIR_P = @MKDIR_P@ MOSTLYCLEANFILES = @MOSTLYCLEANFILES@ .test[0-9]* NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ RANLIB = @RANLIB@ REPLACE_LIBADD = @REPLACE_LIBADD@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ SOFIA_GLIB_CFLAGS = @SOFIA_GLIB_CFLAGS@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ SOFIA_PLAT_CFLAGS = @SOFIA_PLAT_CFLAGS@ STRIP = @STRIP@ TESTS_ENVIRONMENT = $(SHELL) VERSION = @VERSION@ VER_LIBSOFIA_SIP_UA_MAJOR_MINOR = @VER_LIBSOFIA_SIP_UA_MAJOR_MINOR@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ include_sofiadir = @include_sofiadir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ openssl_CFLAGS = @openssl_CFLAGS@ openssl_LIBS = @openssl_LIBS@ 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@ INCLUDES = -I$(srcdir)/../ipt -I../ipt \ -I$(srcdir)/../msg -I../msg \ -I$(srcdir)/../sip -I../sip \ -I$(srcdir)/../bnf -I../bnf \ -I$(srcdir)/../sresolv -I../sresolv \ -I$(srcdir)/../tport -I../tport \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../features -I../features \ -I$(srcdir)/../su -I../su \ -I$(top_srcdir)/s2check \ -I$(srcdir)/../stun -I ../stun # ---------------------------------------------------------------------- # Build targets noinst_LTLIBRARIES = libnta.la dist_noinst_SCRIPTS = run_check_nta run_test_nta_api run_test_nta TESTS = run_check_nta run_test_nta_api run_test_nta # ---------------------------------------------------------------------- # Rules for building the targets BUILT_SOURCES = nta_tag_ref.c nobase_include_sofia_HEADERS = \ sofia-sip/nta.h sofia-sip/nta_stateless.h \ sofia-sip/nta_tport.h sofia-sip/nta_tag.h \ sofia-sip/sl_utils.h libnta_la_SOURCES = nta.c nta_check.c nta_tag.c nta_tag_ref.c \ nta_internal.h \ sl_utils_print.c sl_utils_log.c \ sl_read_payload.c COVERAGE_INPUT = $(libnta_la_SOURCES) $(include_sofia_HEADERS) LDADD = libnta.la ../ipt/libipt.la ../sip/libsip.la \ ../features/libfeatures.la ../sresolv/libsresolv.la \ ../tport/libtport.la ../http/libhttp.la ../stun/libstun.la \ ../url/liburl.la ../msg/libmsg.la ../bnf/libbnf.la \ ../su/libsu.la ${top_builddir}/s2check/libs2.a $(openssl_LIBS) test_nta_LDFLAGS = -static @HAVE_CHECK_FALSE@check_nta_SOURCES = $(top_srcdir)/s2check/exit77.c @HAVE_CHECK_TRUE@check_nta_SOURCES = check_nta.h \ @HAVE_CHECK_TRUE@ check_nta_api.c \ @HAVE_CHECK_TRUE@ check_nta_client.c \ @HAVE_CHECK_TRUE@ check_nta_server.c \ @HAVE_CHECK_TRUE@ check_nta.c @HAVE_CHECK_TRUE@check_nta_LDADD = ${LDADD} @CHECK_LIBS@ # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST = nta.docs sl_utils.docs \ agent.pem cafile.pem \ invite.msc $(BUILT_SOURCES) sofiasrcdir = ${top_srcdir}/libsofia-sip-ua sofiabuilddir = ${top_builddir}/libsofia-sip-ua AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(SOFIA_CFLAGS) \ $(openssl_CFLAGS) $(SOFIA_PLAT_CFLAGS) $(am__append_1) SOFIA_COVERAGE = $(COVERAGE_FLAGS) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files TAG_AWK = ${sofiasrcdir}/su/tag_dll.awk SUFFIXES = _tag_ref.c _tag.c INTERNAL_INCLUDES = \ -I${sofiasrcdir}/features -I${sofiabuilddir}/features \ -I${sofiasrcdir}/ipt -I${sofiabuilddir}/ipt \ -I${sofiasrcdir}/iptsec -I${sofiabuilddir}/iptsec \ -I${sofiasrcdir}/bnf -I${sofiabuilddir}/bnf \ -I${sofiasrcdir}/http -I${sofiabuilddir}/http \ -I${sofiasrcdir}/msg -I${sofiabuilddir}/msg \ -I${sofiasrcdir}/nth -I${sofiabuilddir}/nth \ -I${sofiasrcdir}/nta -I${sofiabuilddir}/nta \ -I${sofiasrcdir}/nea -I${sofiabuilddir}/nea \ -I${sofiasrcdir}/nua -I${sofiabuilddir}/nua \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sdp -I${sofiabuilddir}/sdp \ -I${sofiasrcdir}/sip -I${sofiabuilddir}/sip \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sresolv -I${sofiabuilddir}/sresolv \ -I${sofiasrcdir}/tport -I${sofiabuilddir}/tport \ -I${sofiasrcdir}/stun -I${sofiabuilddir}/stun \ -I${sofiasrcdir}/url -I${sofiabuilddir}/url \ -I${sofiasrcdir}/su -I${sofiabuilddir}/su PHONY = built-sources clean-built-sources $(am__append_3) VALGRIND = valgrind VALGRINDFLAGS = --tool=memcheck # Scripts @HAVE_LCOV_TRUE@LCOV_UNCOVERED = ${top_srcdir}/scripts/uncovered @HAVE_LCOV_TRUE@LCOV_REPORT = ${top_srcdir}/scripts/lcov-report # Report directory @HAVE_LCOV_TRUE@lcovdir = ${top_builddir}/lcov # Options @HAVE_LCOV_TRUE@GENHTML_OPTIONS = --show-details --legend \ @HAVE_LCOV_TRUE@ $(am__append_2) # Fancy shell command that expands to directory relative to top_builddir @HAVE_LCOV_TRUE@expand_subdir = `pwd|sed "s'\`cd ${top_builddir};pwd\`''"` SOFIA_SILENT = @ LIBTOOL_FLAGS = --silent # From Automake 1.9.6 - LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(LIBTOOL_FLAGS) \ $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) LINK = ${SOFIA_SILENT}test "${SOFIA_SILENT}" != @ || echo ' LINK $@'; \ $(LIBTOOL) --tag=CC --mode=link $(LIBTOOL_FLAGS) \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ # ---------------------------------------------------------------------- # Sofia specific rules # Generate list of nta tags TAG_DLL_FLAGS = LIST=nta_tag_list all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: _tag_ref.c _tag.c .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.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 libsofia-sip-ua/nta/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu libsofia-sip-ua/nta/Makefile .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.am: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): Doxyfile: $(top_builddir)/config.status $(srcdir)/Doxyfile.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ 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}; \ } libnta.la: $(libnta_la_OBJECTS) $(libnta_la_DEPENDENCIES) $(EXTRA_libnta_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libnta_la_OBJECTS) $(libnta_la_LIBADD) $(LIBS) 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 check_nta$(EXEEXT): $(check_nta_OBJECTS) $(check_nta_DEPENDENCIES) $(EXTRA_check_nta_DEPENDENCIES) @rm -f check_nta$(EXEEXT) $(AM_V_CCLD)$(LINK) $(check_nta_OBJECTS) $(check_nta_LDADD) $(LIBS) portbind$(EXEEXT): $(portbind_OBJECTS) $(portbind_DEPENDENCIES) $(EXTRA_portbind_DEPENDENCIES) @rm -f portbind$(EXEEXT) $(AM_V_CCLD)$(LINK) $(portbind_OBJECTS) $(portbind_LDADD) $(LIBS) test_nta$(EXEEXT): $(test_nta_OBJECTS) $(test_nta_DEPENDENCIES) $(EXTRA_test_nta_DEPENDENCIES) @rm -f test_nta$(EXEEXT) $(AM_V_CCLD)$(test_nta_LINK) $(test_nta_OBJECTS) $(test_nta_LDADD) $(LIBS) test_nta_api$(EXEEXT): $(test_nta_api_OBJECTS) $(test_nta_api_DEPENDENCIES) $(EXTRA_test_nta_api_DEPENDENCIES) @rm -f test_nta_api$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_nta_api_OBJECTS) $(test_nta_api_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check_nta.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check_nta_api.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check_nta_client.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check_nta_server.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exit77.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nta.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nta_check.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nta_tag.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nta_tag_ref.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/portbind.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sl_read_payload.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sl_utils_log.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sl_utils_print.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_nta.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_nta_api.Po@am__quote@ .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.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) '$<'` exit77.o: $(top_srcdir)/s2check/exit77.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT exit77.o -MD -MP -MF $(DEPDIR)/exit77.Tpo -c -o exit77.o `test -f '$(top_srcdir)/s2check/exit77.c' || echo '$(srcdir)/'`$(top_srcdir)/s2check/exit77.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/exit77.Tpo $(DEPDIR)/exit77.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/s2check/exit77.c' object='exit77.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) $(AM_CFLAGS) $(CFLAGS) -c -o exit77.o `test -f '$(top_srcdir)/s2check/exit77.c' || echo '$(srcdir)/'`$(top_srcdir)/s2check/exit77.c exit77.obj: $(top_srcdir)/s2check/exit77.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT exit77.obj -MD -MP -MF $(DEPDIR)/exit77.Tpo -c -o exit77.obj `if test -f '$(top_srcdir)/s2check/exit77.c'; then $(CYGPATH_W) '$(top_srcdir)/s2check/exit77.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/s2check/exit77.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/exit77.Tpo $(DEPDIR)/exit77.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/s2check/exit77.c' object='exit77.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) $(AM_CFLAGS) $(CFLAGS) -c -o exit77.obj `if test -f '$(top_srcdir)/s2check/exit77.c'; then $(CYGPATH_W) '$(top_srcdir)/s2check/exit77.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/s2check/exit77.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-nobase_include_sofiaHEADERS: $(nobase_include_sofia_HEADERS) @$(NORMAL_INSTALL) @list='$(nobase_include_sofia_HEADERS)'; test -n "$(include_sofiadir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(include_sofiadir)'"; \ $(MKDIR_P) "$(DESTDIR)$(include_sofiadir)" || exit 1; \ fi; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo " $(MKDIR_P) '$(DESTDIR)$(include_sofiadir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(include_sofiadir)/$$dir"; }; \ echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(include_sofiadir)/$$dir'"; \ $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(include_sofiadir)/$$dir" || exit $$?; }; \ done uninstall-nobase_include_sofiaHEADERS: @$(NORMAL_UNINSTALL) @list='$(nobase_include_sofia_HEADERS)'; test -n "$(include_sofiadir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ dir='$(DESTDIR)$(include_sofiadir)'; $(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; \ else \ 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 $(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 $$? run_check_nta.log: run_check_nta @p='run_check_nta'; \ b='run_check_nta'; \ $(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) run_test_nta_api.log: run_test_nta_api @p='run_test_nta_api'; \ b='run_test_nta_api'; \ $(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) run_test_nta.log: run_test_nta @p='run_test_nta'; \ b='run_test_nta'; \ $(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: $(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: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LTLIBRARIES) $(SCRIPTS) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(include_sofiadir)"; 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: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) -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: 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) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) 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) @HAVE_LCOV_FALSE@clean-local: clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libtool clean-local \ clean-noinstLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -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-nobase_include_sofiaHEADERS 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 -rf ./$(DEPDIR) -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-nobase_include_sofiaHEADERS .MAKE: all check check-am install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libtool clean-local \ 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-nobase_include_sofiaHEADERS 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 \ uninstall-nobase_include_sofiaHEADERS built-sources: $(BUILT_SOURCES) clean-built-sources: -rm -rf $(BUILT_SOURCES) $(BUILT_SOURCES:%=$(srcdir)/%) *_tag_ref.c: $(TAG_AWK) _tag.c_tag_ref.c: $(AWK) -f $(TAG_AWK) NODLL=1 $(TAG_DLL_FLAGS) REF=$@ $< ../bnf/libbnf.la ../http/libhttp.la ../ipt/libipt.la ../iptsec/libiptsec.la \ ../msg/libmsg.la ../nea/libnea.la ../nta/libnta.la ../nth/libnth.la \ ../nua/libnua.la ../sdp/libsdp.la ../sip/libsip.la ../soa/libsoa.la \ ../sresolv/libsresolv.la ../stun/libstun.la ../su/libsu.la \ ../tport/libtport.la ../url/liburl.la: cd $(@D) && $(MAKE) $(@F) checklib: $(noinst_LTLIBRARIES) $(check_LTLIBRARIES) valcheck: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) valcheck-am valcheck-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS # Run tests with valgrind in valcheck-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ list='$(TESTS)'; \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ if case $$tst in \ run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ $${dir}$$tst ;; \ esac ; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ echo "XPASS: $$tst"; \ ;; \ *) \ echo "PASS: $$tst"; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xfail=`expr $$xfail + 1`; \ echo "XFAIL: $$tst"; \ ;; \ *) \ failed=`expr $$failed + 1`; \ echo "FAIL: $$tst"; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ echo "SKIP: $$tst"; \ fi; \ done; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="All $$all tests passed"; \ else \ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all tests failed"; \ else \ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ skipped="($$skip tests were not run)"; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ report=""; \ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ report="Please report to $(PACKAGE_BUGREPORT)"; \ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ echo "$$dashes"; \ echo "$$banner"; \ test -z "$$skipped" || echo "$$skipped"; \ test -z "$$report" || echo "$$report"; \ echo "$$dashes"; \ test "$$failed" -eq 0; \ else :; fi # # Generate pretty coverage report (unless it has been already done) # @HAVE_LCOV_TRUE@lcov: @HAVE_LCOV_TRUE@ @-test -r ${lcovdir}${expand_subdir}/lcov.info \ @HAVE_LCOV_TRUE@ || make lcov-report # Generate pretty coverage report based on current coverage data @HAVE_LCOV_TRUE@lcov-report: @HAVE_LCOV_TRUE@ sub=${expand_subdir} odir=${lcovdir}$$sub ; \ @HAVE_LCOV_TRUE@ rm -rf $$odir ; mkdir -p $$odir && \ @HAVE_LCOV_TRUE@ ${LCOV_REPORT} ${GENHTML_OPTIONS} \ @HAVE_LCOV_TRUE@ --title "${PACKAGE_NAME}-${PACKAGE_VERSION}$$sub" \ @HAVE_LCOV_TRUE@ --srcdir=${srcdir} -o $$odir # Rerun checks before generating report @HAVE_LCOV_TRUE@lcov-rerun: clean-lcov @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) lcov-report # Show all uncovered lines as errors @HAVE_LCOV_TRUE@uncovered: @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} # Run check in current dir and show all uncovered lines as errors @HAVE_LCOV_TRUE@covcheck: @HAVE_LCOV_TRUE@ -find . -name "*.gcda" | xargs rm -rf @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} @HAVE_LCOV_TRUE@clean-local:: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true @HAVE_LCOV_TRUE@clean-lcov: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true # Rules from depend2.am (GENERIC = TRUE, SUBDIROBJ = FALSE, %FASTDEP% = am_fastdepCC) silenced. .c.o: @test "${SOFIA_SILENT}" != @ || echo ' COMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(COMPILE) -c -o $@ $< .c.lo: @test "${SOFIA_SILENT}" != @ || echo ' LTCOMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(LTCOMPILE) -c -o $@ $< # endif # 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: sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/agent.pem000066400000000000000000000040271223300710500221400ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIDPjCCAqegAwIBAgIHJQIBAZACBjANBgkqhkiG9w0BAQUFADBwMQswCQYDVQQG EwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTERMA8GA1UEBxMIU2FuIEpvc2UxDjAM BgNVBAoTBXNpcGl0MSkwJwYDVQQLEyBTaXBpdCBUZXN0IENlcnRpZmljYXRlIEF1 dGhvcml0eTAeFw0wMzEyMDMxODMwMjJaFw0wNjEyMDIxODMwMjJaMGUxCzAJBgNV BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMREwDwYDVQQHEwhTYW4gSm9zZTEO MAwGA1UEChMFc2lwaXQxHjAcBgNVBAMTFXBla2thLm5va2lhLnNpcGl0Lm5ldDCB nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsdJn/O6JoIC1I2iXOVJLQypmt9sN HmvB84853Qx9KS+xqP3U2nqNMnDQby6ZmTsRHNGAK5QuGugU11wocmYNP0/TQFaz KNLhNt0pMBOfpAV9vG6pCSkocObsUo2XFULPTEB/SzGcvE1G1em3XmwRfPA178y9 L2+sVNT5Vtt5KfMCAwEAAaOB7DCB6TAgBgNVHREEGTAXghVwZWtrYS5ub2tpYS5z aXBpdC5uZXQwCQYDVR0TBAIwADAdBgNVHQ4EFgQU1OjdL9cdA0NNbxPDQ9xZUZG6 NnIwgZoGA1UdIwSBkjCBj4AUa0YXFOqUdiWAVG4TVNqh41QUobahdKRyMHAxCzAJ BgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMREwDwYDVQQHEwhTYW4gSm9z ZTEOMAwGA1UEChMFc2lwaXQxKTAnBgNVBAsTIFNpcGl0IFRlc3QgQ2VydGlmaWNh dGUgQXV0aG9yaXR5ggEAMA0GCSqGSIb3DQEBBQUAA4GBADCO35LJqgiK5OUR+DuT N4CfUhsn9T5kDSf2rikna4ZFbuS7smc/oVu4g26HHjt6DKs4UEx9OmyXFslSENZ+ tFNeVClpHJrPsNwjk/uyjhfeW1NezhXMIi6q8DYcwE5I7r+Uz2XST+jWCTb4obPY 10ysI7e7/rgCoITe+qO2U35D -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQCx0mf87omggLUjaJc5UktDKma32w0ea8HzjzndDH0pL7Go/dTa eo0ycNBvLpmZOxEc0YArlC4a6BTXXChyZg0/T9NAVrMo0uE23SkwE5+kBX28bqkJ KShw5uxSjZcVQs9MQH9LMZy8TUbV6bdebBF88DXvzL0vb6xU1PlW23kp8wIDAQAB AoGAVtICT64vqBvvVPB2FVimwo5rRI1BJH88XSyq9dBpM7jDp1z3lgyL7/rA6ef4 uqXqPwXS7HQW5rA1rMikPuawxE5UG31OG3U0+H/OGl0xwAq57mEtRDR8464jSUPY l9bzkRpjnEgdUtkLnogm8F4mALexdc3KxIgg3uo/OOg0N5ECQQDZon1JBNEYWxEF GBNbEvQthPy7rRLmxontgcsfhRvm5lSbuC+VP1uRHibwwIrXOUZD8uuEVdVZNzfV bGPdh70HAkEA0Ss6HyAWczRBzrvC8eVvPmkI9XihdLqUFLTDL0R1sMCISwW/FEeH X9yFqOY+y6EJAitzhxtol+0k+UsIJl5ctQJAXU0L6QHnokloQobPxXuasukQcGUC dW0oNGowapLmI1cbbqbHv3QqDUyf5Rambx5ewUKjNViW3miNxzFwnshSgQJAINuQ gskwnaJM4CPgqM0o333yeVUcz9BraKFItAkmD8D+6AIcFRxzaJykpnac0LIYTy3y NPwaPxtynnKp8hUKrQJBAM1i5051UzJVFuRedwtPdGDrfkNwoJm27fwWozSQcBC6 G5VnTrQ6V8VCJglNzVhy9b2WqlqfWV3D5BCgxyuH984= -----END RSA PRIVATE KEY----- sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/cafile.pem000066400000000000000000000021771223300710500222710ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIDJDCCAo2gAwIBAgIBADANBgkqhkiG9w0BAQUFADBwMQswCQYDVQQGEwJVUzET MBEGA1UECBMKQ2FsaWZvcm5pYTERMA8GA1UEBxMIU2FuIEpvc2UxDjAMBgNVBAoT BXNpcGl0MSkwJwYDVQQLEyBTaXBpdCBUZXN0IENlcnRpZmljYXRlIEF1dGhvcml0 eTAeFw0wMzA3MTgxMjIxNTJaFw0xMzA3MTUxMjIxNTJaMHAxCzAJBgNVBAYTAlVT MRMwEQYDVQQIEwpDYWxpZm9ybmlhMREwDwYDVQQHEwhTYW4gSm9zZTEOMAwGA1UE ChMFc2lwaXQxKTAnBgNVBAsTIFNpcGl0IFRlc3QgQ2VydGlmaWNhdGUgQXV0aG9y aXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDIh6DkcUDLDyK9BEUxkud +nJ4xrCVGKfgjHm6XaSuHiEtnfELHM+9WymzkBNzZpJu30yzsxwfKoIKugdNUrD4 N3viCicwcN35LgP/KnbN34cavXHr4ZlqxH+OdKB3hQTpQa38A7YXdaoz6goW2ft5 Mi74z03GNKP/G9BoKOGd5QIDAQABo4HNMIHKMB0GA1UdDgQWBBRrRhcU6pR2JYBU bhNU2qHjVBShtjCBmgYDVR0jBIGSMIGPgBRrRhcU6pR2JYBUbhNU2qHjVBShtqF0 pHIwcDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExETAPBgNVBAcT CFNhbiBKb3NlMQ4wDAYDVQQKEwVzaXBpdDEpMCcGA1UECxMgU2lwaXQgVGVzdCBD ZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0B AQUFAAOBgQCWbRvv1ZGTRXxbH8/EqkdSCzSoUPrs+rQqR0xdQac9wNY/nlZbkR3O qAezG6Sfmklvf+DOg5RxQq/+Y6I03LRepc7KeVDpaplMFGnpfKsibETMipwzayNQ QgUf4cKBiF+65Ue7hZuDJa2EMv8qW4twEhGDYclpFU9YozyS1OhvUg== -----END CERTIFICATE----- sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/check_nta.c000066400000000000000000000244711223300710500224270ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2008 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE check_nta.c * @brief 2nd test Suite for Sofia SIP Transaction Engine * * @author Pekka Pessi * * @date Created: Wed Apr 30 12:48:27 EEST 2008 ppessi */ #include "config.h" #undef NDEBUG #include "check_nta.h" #include "s2dns.h" #include "s2base.h" #include "s2sip.h" #include #include #include #include #include #include #include #include #include #include #include #include #include /* -- Globals -------------------------------------------------------------- */ struct s2nta *s2; /* -- main ----------------------------------------------------------------- */ static void usage(int exitcode) { fprintf(exitcode ? stderr : stdout, "usage: %s [--xml=logfile] case,...\n", s2_tester); exit(exitcode); } int main(int argc, char *argv[]) { int i, failed = 0, selected = 0; char const *xml = NULL; Suite *suite; SRunner *runner; s2_tester = "check_nta"; s2_suite("NTA"); if (getenv("CHECK_NTA_VERBOSE")) s2_start_stop = strtoul(getenv("CHECK_NTA_VERBOSE"), NULL, 10); for (i = 1; argv[i]; i++) { if (su_strnmatch(argv[i], "--xml=", strlen("--xml="))) { xml = argv[i] + strlen("--xml="); } else if (su_strmatch(argv[i], "--xml")) { if (!(xml = argv[++i])) usage(2); } else if (su_strmatch(argv[i], "-v")) { s2_start_stop = 1; } else if (su_strmatch(argv[i], "-?") || su_strmatch(argv[i], "-h") || su_strmatch(argv[i], "--help")) usage(0); else { s2_select_tests(argv[i]); selected = 1; } } if (!selected) s2_select_tests(getenv("CHECK_NTA_CASES")); suite = suite_create("Unit tests for nta (Sofia-SIP Transaction Engine)"); suite_add_tcase(suite, check_nta_api_1_0()); suite_add_tcase(suite, check_nta_client_2_0()); suite_add_tcase(suite, check_nta_client_2_1()); suite_add_tcase(suite, check_nta_client_2_2()); suite_add_tcase(suite, check_nta_server_3_0()); runner = srunner_create(suite); if (xml) srunner_set_xml(runner, argv[1]); srunner_run_all(runner, CK_ENV); failed = srunner_ntests_failed(runner); srunner_free(runner); exit(failed ? EXIT_FAILURE : EXIT_SUCCESS); } /* -- NTA callbacks -------------------------------------------------------- */ struct event * s2_nta_remove_event(struct event *e) { if ((*e->prev = e->next)) e->next->prev = e->prev; e->prev = NULL, e->next = NULL; return e; } void s2_nta_free_event(struct event *e) { if (e) { if (e->prev) { if ((*e->prev = e->next)) e->next->prev = e->prev; } if (e->msg) msg_destroy(e->msg); free(e); } } void s2_nta_flush_events(void) { while (s2->events) { s2_nta_free_event(s2->events); } } struct event * s2_nta_next_event(void) { for (;;) { if (s2->events) return s2_nta_remove_event(s2->events); su_root_step(s2->root, 1); } } struct event * s2_nta_vwait_for(enum wait_for wait_for0, void const *value0, va_list va0) { struct event *e; for (;;) { for (e = s2->events; e; e = e->next) { va_list va; enum wait_for wait_for; void const *value; va_copy(va, va0); for (wait_for = wait_for0, value = value0; wait_for; wait_for = va_arg(va, enum wait_for), value = va_arg(va, void const *)) { switch (wait_for) { case wait_for_amagic: if (value != e->amagic) goto next; break; case wait_for_omagic: if (value != e->omagic) goto next; break; case wait_for_orq: if (value != e->orq) goto next; break; case wait_for_lmagic: if (value != e->lmagic) goto next; break; case wait_for_leg: if (value != e->leg) goto next; break; case wait_for_imagic: if (value != e->imagic) goto next; break; case wait_for_irq: if (value != e->irq) goto next; break; case wait_for_method: if ((sip_method_t)value != e->method) goto next; break; case wait_for_method_name: if (!su_strmatch(value, e->method_name)) goto next; break; case wait_for_status: if ((int)value != e->status) goto next; break; case wait_for_phrase: if (!su_casematch(value, e->phrase)) goto next; break; } } next: va_end(va); if (!wait_for) return s2_nta_remove_event(e); } su_root_step(s2->root, 1); } } struct event * s2_nta_wait_for(enum wait_for wait_for, void const *value, ...) { struct event *e; va_list va; va_start(va, value); e = s2_nta_vwait_for(wait_for, value, va); va_end(va); return e; } int s2_nta_check_request(enum wait_for wait_for, void const *value, ...) { struct event *e; va_list va; va_start(va, value); e = s2_nta_vwait_for(wait_for, value, va); va_end(va); s2_nta_free_event(e); return e != NULL; } int s2_nta_msg_callback(nta_agent_magic_t *magic, nta_agent_t *nta, msg_t *msg, sip_t *sip) { struct event *e, **prev; e = calloc(1, sizeof *e); e->amagic = magic; e->msg = msg; e->sip = sip; if (sip->sip_request) { e->method = sip->sip_request->rq_method; e->method_name = sip->sip_request->rq_method_name; } else { e->status = sip->sip_status->st_status; e->phrase = sip->sip_status->st_phrase; } for (prev = &s2->events; *prev; prev = &(*prev)->next) ; *prev = e, e->prev = prev; return 0; } int s2_nta_orq_callback(nta_outgoing_magic_t *magic, nta_outgoing_t *orq, sip_t const *sip) { struct event *e, **prev; e = calloc(1, sizeof *e); e->omagic = magic; e->orq = orq; e->msg = nta_outgoing_getresponse(orq); e->sip = sip_object(e->msg); e->status = nta_outgoing_status(orq); e->phrase = sip ? sip->sip_status->st_phrase : ""; for (prev = &s2->events; *prev; prev = &(*prev)->next) ; *prev = e, e->prev = prev; return 0; } int s2_nta_leg_callback(nta_leg_magic_t *magic, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip) { struct event *e, **prev; e = calloc(1, sizeof *e); e->lmagic = magic; e->leg = leg; e->irq = irq; e->msg = nta_incoming_getrequest(irq); e->sip = sip_object(e->msg); e->method = e->sip->sip_request->rq_method; e->method_name = e->sip->sip_request->rq_method_name; for (prev = &s2->events; *prev; prev = &(*prev)->next) ; *prev = e, e->prev = prev; return 0; } int s2_nta_irq_callback(nta_incoming_magic_t *magic, nta_incoming_t *irq, sip_t const *sip) { struct event *e, **prev; e = calloc(1, sizeof *e); e->imagic = magic; e->irq = irq; e->msg = nta_incoming_getrequest_ackcancel(irq); e->sip = sip_object(e->msg); e->method = e->sip ? e->sip->sip_request->rq_method : 0; e->method_name = e->sip ? e->sip->sip_request->rq_method_name : NULL; for (prev = &s2->events; *prev; prev = &(*prev)->next) ; *prev = e, e->prev = prev; return 0; } /* ====================================================================== */ SOFIAPUBVAR su_log_t nta_log[]; SOFIAPUBVAR su_log_t sresolv_log[]; SOFIAPUBVAR su_log_t tport_log[]; SOFIAPUBVAR su_log_t su_log_default[]; void s2_nta_setup_logs(int level) { su_log_soft_set_level(su_log_default, level); su_log_soft_set_level(tport_log, level); su_log_soft_set_level(nta_log, level); su_log_soft_set_level(sresolv_log, level); if (getenv("TPORT_LOG") == NULL && getenv("S2_TPORT_LOG") == NULL) { if (s2sip) tport_set_params(s2sip->master, TPTAG_LOG(level > 1), TAG_END()); } } void s2_nta_setup(char const *label, char const * const *transports, tag_type_t tag, tag_value_t value, ...) { ta_list ta; s2_setup(label); s2_nta_setup_logs(0); s2_dns_setup(s2base->root); ta_start(ta, tag, value); s2_sip_setup("example.org", transports, ta_tags(ta)); ta_end(ta); assert(s2sip->contact); s2_dns_domain("example.org", 1, "s2", 1, s2sip->udp.contact ? s2sip->udp.contact->m_url : NULL, "s2", 1, s2sip->tcp.contact ? s2sip->tcp.contact->m_url : NULL, "s2", 1, s2sip->tls.contact ? s2sip->tls.contact->m_url : NULL, NULL); } nta_agent_t * s2_nta_agent_setup(url_string_t const *bind_url, nta_message_f *callback, nta_agent_magic_t *magic, tag_type_t tag, tag_value_t value, ...) { ta_list ta; assert(s2base); s2 = su_home_new(sizeof *s2); assert(s2); s2->root = su_root_clone(s2base->root, s2); assert(s2->root); fail_unless(s2->root != NULL); ta_start(ta, tag, value); s2->nta = nta_agent_create(s2->root, bind_url ? bind_url : URL_STRING_MAKE("sip:*:*"), callback, magic, /* Use internal DNS server */ /* Force sresolv to use localhost and s2dns as DNS server */ #if HAVE_WIN32 SRESTAG_RESOLV_CONF("NUL"), #else SRESTAG_RESOLV_CONF("/dev/null"), #endif ta_tags(ta)); ta_end(ta); assert(s2->nta); if (callback == NULL) s2->default_leg = nta_leg_tcreate(s2->nta, s2_nta_leg_callback, NULL, NTATAG_NO_DIALOG(1), TAG_END()); s2sip->sut.contact = nta_agent_contact(s2->nta); return s2->nta; } void s2_nta_teardown(void) { if (s2) { s2_nta_flush_events(); if (s2->default_leg) nta_leg_destroy(s2->default_leg), s2->default_leg = NULL; nta_agent_destroy(s2->nta), s2->nta = NULL; su_root_destroy(s2->root), s2->root = NULL; su_home_unref(s2->home); s2 = NULL; } s2_dns_teardown(); s2_sip_teardown(); s2_teardown(); } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/check_nta.h000066400000000000000000000061701223300710500224300ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2008 Nokia Corporation. * * Contact: Pekka Pessi * * 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 */ #ifndef CHECK_NTA_H #define CHECK_NTA_H #include #include #include #include #include #include "s2sip.h" extern struct s2nta { su_home_t home[1]; nta_agent_t *nta; su_root_t *root; nta_leg_t *default_leg; struct event { struct event *next, **prev; nta_agent_magic_t *amagic; nta_outgoing_magic_t *omagic; nta_outgoing_t *orq; nta_leg_magic_t *lmagic; nta_leg_t *leg; nta_incoming_magic_t *imagic; nta_incoming_t *irq; sip_method_t method; char const *method_name; int status; char const *phrase; msg_t *msg; sip_t *sip; } *events; } *s2; struct event *s2_nta_remove_event(struct event *e); void s2_nta_free_event(struct event *e); void s2_nta_flush_events(void); struct event *s2_nta_next_event(void); enum wait_for { wait_for_amagic = 1, wait_for_omagic, wait_for_orq, wait_for_lmagic, wait_for_leg, wait_for_imagic, wait_for_irq, wait_for_method, wait_for_method_name, wait_for_status, wait_for_phrase }; struct event *s2_nta_vwait_for(enum wait_for, void const *value, va_list va); struct event *s2_nta_wait_for(enum wait_for, void const *value, ...); int s2_nta_check_for(enum wait_for, void const *value, ...); int s2_nta_msg_callback(nta_agent_magic_t *magic, nta_agent_t *nta, msg_t *msg, sip_t *sip); int s2_nta_orq_callback(nta_outgoing_magic_t *magic, nta_outgoing_t *orq, sip_t const *sip); int s2_nta_leg_callback(nta_leg_magic_t *magic, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip); int s2_nta_irq_callback(nta_incoming_magic_t *magic, nta_incoming_t *irq, sip_t const *sip); void s2_nta_setup_logs(int level); void s2_nta_setup(char const *label, char const * const *transports, tag_type_t tag, tag_value_t value, ...); nta_agent_t *s2_nta_agent_setup(url_string_t const *bind_url, nta_message_f *callback, nta_agent_magic_t *magic, tag_type_t tag, tag_value_t value, ...); void s2_nta_teardown(void); TCase *check_nta_api_1_0(void); TCase *check_nta_client_2_0(void); TCase *check_nta_client_2_1(void); TCase *check_nta_client_2_2(void); TCase *check_nta_server_3_0(void); #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/check_nta_api.c000066400000000000000000000217441223300710500232600ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2008 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE check_nta_api.c * * @brief Check-driven tester for NTA API * * @author Pekka Pessi * * @copyright (C) 2009 Nokia Corporation. */ #include "config.h" #include "check_nta.h" #include "s2base.h" #include "nta_internal.h" #include #include #include #include #include #include #include #include #define NONE ((void *)-1) static void api_setup(void) { s2_nta_setup("NTA", NULL, TAG_END()); } static void api_teardown(void) { mark_point(); s2_nta_teardown(); } START_TEST(api_1_0_0) { su_root_t *root = s2base->root; nta_agent_t *nta; su_home_t home[1]; su_nanotime_t nano; nta_agent_magic_t *amagic = (void *)(home + 1); nta_outgoing_magic_t *omagic = (void *)(home + 2); msg_t *msg; memset(home, 0, sizeof home); home->suh_size = (sizeof home); su_home_init(home); fail_unless(nta_agent_create(NULL, (url_string_t *)"sip:*:*", NULL, NULL, TAG_END()) == NULL); fail_unless(nta_agent_create(root, (url_string_t *)"http://localhost:*/invalid/bind/url", NULL, NULL, TAG_END()) == NULL); fail_unless(nta_agent_create(root, (url_string_t *)"sip:*:*;transport=XXX", NULL, NULL, TAG_END()) == NULL); mark_point(); nta = nta_agent_create(root, (url_string_t *)"sip:*:*", NULL, NULL, TAG_END()); fail_unless(nta != NULL); mark_point(); nta_agent_destroy(NULL); mark_point(); nta_agent_destroy(nta); mark_point(); nta = nta_agent_create(root, (url_string_t *)"sip:*:*", s2_nta_msg_callback, amagic, TAG_END()); fail_unless(nta != NULL); fail_unless(nta_agent_contact(NULL) == NULL); fail_unless(nta_agent_via(NULL) == NULL); fail_if(strcmp(nta_agent_version(nta), nta_agent_version(NULL))); fail_unless(nta_agent_magic(NULL) == NULL); fail_unless(nta_agent_magic(nta) == amagic); fail_unless(nta_agent_add_tport(NULL, NULL, TAG_END()) == -1); fail_unless(nta_agent_newtag(home, "tag=%s", NULL) == NULL); fail_unless(nta_agent_newtag(home, "tag=%s", nta) != NULL); fail_unless(nta_msg_create(NULL, 0) == NULL); fail_unless(nta_msg_complete(NULL) == -1); fail_unless((msg = nta_msg_create(nta, 0)) != NULL); fail_unless(nta_msg_complete(msg) == -1); fail_unless( nta_msg_request_complete(msg, NULL, SIP_METHOD(FOO), NULL) == -1); fail_unless(nta_is_internal_msg(NULL) == 0); fail_unless(nta_is_internal_msg(msg) == 0); fail_unless(msg_set_flags(msg, NTA_INTERNAL_MSG)); fail_unless(nta_is_internal_msg(msg) == 1); mark_point(); msg_destroy(msg); mark_point(); fail_unless(nta_leg_tcreate(NULL, NULL, NULL, TAG_END()) == NULL); mark_point(); nta_leg_destroy(NULL); mark_point(); fail_unless(nta_leg_magic(NULL, NULL) == NULL); mark_point(); nta_leg_bind(NULL, NULL, NULL); mark_point(); fail_unless(nta_leg_tag(NULL, "fidsafsa") == NULL); fail_unless(nta_leg_rtag(NULL, "fidsafsa") == NULL); fail_unless(nta_leg_get_tag(NULL) == NULL); fail_unless(nta_leg_client_route(NULL, NULL, NULL) == -1); fail_unless(nta_leg_client_reroute(NULL, NULL, NULL, 0) == -1); fail_unless(nta_leg_server_route(NULL, NULL, NULL) == -1); fail_unless(nta_leg_by_uri(NULL, NULL) == NULL); fail_unless( nta_leg_by_dialog(NULL, NULL, NULL, NULL, NULL, NULL, NULL) == NULL); fail_unless( nta_leg_by_dialog(nta, NULL, NULL, NULL, NULL, NULL, NULL) == NULL); fail_unless(nta_leg_make_replaces(NULL, NULL, 1) == NULL); fail_unless(nta_leg_by_replaces(NULL, NULL) == NULL); fail_unless(nta_incoming_create(NULL, NULL, NULL, NULL, TAG_END()) == NULL); fail_unless(nta_incoming_create(nta, NULL, NULL, NULL, TAG_END()) == NULL); mark_point(); nta_incoming_bind(NULL, NULL, NULL); mark_point(); fail_unless(nta_incoming_magic(NULL, NULL) == NULL); fail_unless(nta_incoming_find(NULL, NULL, NULL) == NULL); fail_unless(nta_incoming_find(nta, NULL, NULL) == NULL); fail_unless(nta_incoming_tag(NULL, NULL) == NULL); fail_unless(nta_incoming_gettag(NULL) == NULL); fail_unless(nta_incoming_status(NULL) == 400); fail_unless(nta_incoming_method(NULL) == sip_method_invalid); fail_unless(nta_incoming_method_name(NULL) == NULL); fail_unless(nta_incoming_url(NULL) == NULL); fail_unless(nta_incoming_cseq(NULL) == 0); fail_unless(nta_incoming_received(NULL, &nano) == 0); fail_unless(nano == 0); fail_unless(nta_incoming_set_params(NULL, TAG_END()) == -1); fail_unless(nta_incoming_getrequest(NULL) == NULL); fail_unless(nta_incoming_getrequest_ackcancel(NULL) == NULL); fail_unless(nta_incoming_getresponse(NULL) == NULL); fail_unless( nta_incoming_complete_response(NULL, NULL, 800, "foo", TAG_END()) == -1); fail_unless(nta_incoming_treply(NULL, SIP_200_OK, TAG_END()) == -1); fail_unless(nta_incoming_mreply(NULL, NULL) == -1); mark_point(); nta_incoming_destroy(NULL); mark_point(); fail_unless( nta_outgoing_tcreate(NULL, s2_nta_orq_callback, omagic, URL_STRING_MAKE("sip:localhost"), SIP_METHOD_MESSAGE, URL_STRING_MAKE("sip:localhost"), TAG_END()) == NULL); fail_unless( nta_outgoing_mcreate(NULL, s2_nta_orq_callback, omagic, URL_STRING_MAKE("sip:localhost"), NULL, TAG_END()) == NULL); fail_unless(nta_outgoing_default(NULL, NULL, NULL) == NULL); fail_unless(nta_outgoing_bind(NULL, NULL, NULL) == -1); fail_unless(nta_outgoing_magic(NULL, NULL) == NULL); fail_unless(nta_outgoing_status(NULL) == 500); fail_unless(nta_outgoing_method(NULL) == sip_method_invalid); fail_unless(nta_outgoing_method_name(NULL) == NULL); fail_unless(nta_outgoing_cseq(NULL) == 0); fail_unless(nta_outgoing_delay(NULL) == UINT_MAX); fail_unless(nta_outgoing_request_uri(NULL) == NULL); fail_unless(nta_outgoing_route_uri(NULL) == NULL); fail_unless(nta_outgoing_getresponse(NULL) == NULL); fail_unless(nta_outgoing_getrequest(NULL) == NULL); fail_unless(nta_outgoing_tagged(NULL, NULL, NULL, NULL, NULL) == NULL); fail_unless(nta_outgoing_cancel(NULL) == -1); fail_unless(nta_outgoing_tcancel(NULL, NULL, NULL, TAG_END()) == NULL); mark_point(); nta_outgoing_destroy(NULL); mark_point(); fail_unless(nta_outgoing_find(NULL, NULL, NULL, NULL) == NULL); fail_unless(nta_outgoing_find(nta, NULL, NULL, NULL) == NULL); fail_unless(nta_outgoing_status(NONE) == 500); fail_unless(nta_outgoing_method(NONE) == sip_method_invalid); fail_unless(nta_outgoing_method_name(NONE) == NULL); fail_unless(nta_outgoing_cseq(NONE) == 0); fail_unless(nta_outgoing_delay(NONE) == UINT_MAX); fail_unless(nta_outgoing_request_uri(NONE) == NULL); fail_unless(nta_outgoing_route_uri(NONE) == NULL); fail_unless(nta_outgoing_getresponse(NONE) == NULL); fail_unless(nta_outgoing_getrequest(NONE) == NULL); fail_unless(nta_outgoing_tagged(NONE, NULL, NULL, NULL, NULL) == NULL); fail_unless(nta_outgoing_cancel(NONE) == -1); fail_unless(nta_outgoing_tcancel(NONE, NULL, NULL, TAG_END()) == NULL); mark_point(); nta_outgoing_destroy(NONE); mark_point(); fail_unless(nta_reliable_treply(NULL, NULL, NULL, 0, NULL, TAG_END()) == NULL); fail_unless(nta_reliable_mreply(NULL, NULL, NULL, NULL) == NULL); mark_point(); nta_reliable_destroy(NULL); mark_point(); mark_point(); nta_agent_destroy(nta); mark_point(); mark_point(); su_home_deinit(home); mark_point(); fail_unless( nta_check_required(NULL, NULL, NULL, TAG_END()) == 500); fail_unless( nta_check_supported(NULL, NULL, NULL, TAG_END()) == 500); fail_unless( nta_check_method(NULL, NULL, NULL, TAG_END()) == 500); fail_unless( nta_check_session_content(NULL, NULL, NULL, TAG_END()) == 500); fail_unless( nta_check_accept(NULL, NULL, NULL, NULL, TAG_END()) == 500); fail_unless( nta_check_session_expires(NULL, NULL, 0, TAG_END()) == 500); } END_TEST /* ---------------------------------------------------------------------- */ TCase *check_nta_api_1_0(void) { TCase *tc = tcase_create("NTA 1 - API"); tcase_add_checked_fixture(tc, api_setup, api_teardown); tcase_set_timeout(tc, 10); tcase_add_test(tc, api_1_0_0); return tc; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/check_nta_client.c000066400000000000000000000333541223300710500237650ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2008 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE check_nta_client.c * * @brief Check-driven tester for NTA client transactions * * @author Pekka Pessi * * @copyright (C) 2009 Nokia Corporation. */ #include "config.h" #include "check_nta.h" #include "s2base.h" #include "s2dns.h" #include #include #include #include #include #include #include #include #include #include #define NONE ((void *)-1) static void client_setup(void) { s2_nta_setup("NTA", NULL, TAG_END()); s2_nta_agent_setup(URL_STRING_MAKE("sip:0.0.0.0:*"), NULL, NULL, NTATAG_DEFAULT_PROXY("sip:example.org"), TAG_END()); } static void client_setup_udp_only_server(void) { char const * const transports[] = { "udp", NULL }; s2_nta_setup("NTA", transports, TAG_END()); s2_nta_agent_setup(URL_STRING_MAKE("sip:0.0.0.0:*"), NULL, NULL, NTATAG_DEFAULT_PROXY(s2sip->contact->m_url), TAG_END()); } static void client_setup_tcp_only_server(void) { char const * const transports[] = { "tcp", NULL }; s2_nta_setup("NTA", transports, TAG_END()); s2_nta_agent_setup(URL_STRING_MAKE("sip:0.0.0.0:*"), NULL, NULL, NTATAG_DEFAULT_PROXY(s2sip->contact->m_url), TAG_END()); } static void client_teardown(void) { mark_point(); s2_nta_teardown(); } START_TEST(client_2_0_0) { nta_outgoing_t *orq; struct message *request; struct event *response; S2_CASE("client-2.0.0", "Send MESSAGE", "Basic non-INVITE transaction with outbound proxy"); orq = nta_outgoing_tcreate(s2->default_leg, s2_nta_orq_callback, NULL, NULL, SIP_METHOD_MESSAGE, URL_STRING_MAKE("sip:test2.0.example.org"), SIPTAG_FROM_STR(""), TAG_END()); fail_unless(orq != NULL); request = s2_sip_wait_for_request(SIP_METHOD_MESSAGE); fail_unless(request != NULL); s2_sip_respond_to(request, NULL, 200, "2.0.0", TAG_END()); response = s2_nta_wait_for(wait_for_orq, orq, wait_for_status, 200, 0); s2_sip_free_message(request); s2_nta_free_event(response); nta_outgoing_destroy(orq); } END_TEST START_TEST(client_2_0_1) { nta_outgoing_t *orq; struct message *request; struct event *response; S2_CASE("client-2.0.1", "Send MESSAGE", "Basic non-INVITE transaction with " "numeric per-transaction outbound proxy"); orq = nta_outgoing_tcreate(s2->default_leg, s2_nta_orq_callback, NULL, (url_string_t *)s2sip->contact->m_url, SIP_METHOD_MESSAGE, URL_STRING_MAKE("sip:test2.0.example.org"), SIPTAG_FROM_STR(""), TAG_END()); fail_unless(orq != NULL); request = s2_sip_wait_for_request(SIP_METHOD_MESSAGE); fail_unless(request != NULL); s2_sip_respond_to(request, NULL, 200, "OK 2.0.1", TAG_END()); response = s2_nta_wait_for(wait_for_orq, orq, wait_for_status, 200, 0); s2_sip_free_message(request); s2_nta_free_event(response); nta_outgoing_destroy(orq); } END_TEST START_TEST(client_2_0_2) { nta_outgoing_t *orq; struct message *request; struct event *response; char payload[2048]; S2_CASE("client-2.0.2", "Send MESSAGE", "Basic non-INVITE transaction exceeding " "default path MTU (1300 bytes)"); memset(payload, 'x', sizeof payload); payload[(sizeof payload) - 1] = '\0'; orq = nta_outgoing_tcreate(s2->default_leg, s2_nta_orq_callback, NULL, NULL, SIP_METHOD_MESSAGE, URL_STRING_MAKE("sip:test2.0.example.org"), SIPTAG_FROM_STR(""), SIPTAG_PAYLOAD_STR(payload), TAG_END()); fail_unless(orq != NULL); request = s2_sip_wait_for_request(SIP_METHOD_MESSAGE); fail_unless(request != NULL); fail_unless(request->sip->sip_via->v_protocol == sip_transport_tcp); s2_sip_respond_to(request, NULL, 200, "OK 2.0.2", TAG_END()); response = s2_nta_wait_for(wait_for_orq, orq, wait_for_status, 200, 0); s2_nta_free_event(response); nta_outgoing_destroy(orq); } END_TEST /* ---------------------------------------------------------------------- */ TCase *check_nta_client_2_0(void) { TCase *tc = tcase_create("NTA 2.0 - Client"); tcase_add_checked_fixture(tc, client_setup, client_teardown); tcase_set_timeout(tc, 2); tcase_add_test(tc, client_2_0_0); tcase_add_test(tc, client_2_0_1); tcase_add_test(tc, client_2_0_2); return tc; } /* ---------------------------------------------------------------------- */ START_TEST(client_2_1_0) { nta_outgoing_t *orq; struct message *request; struct event *response; char payload[2048]; S2_CASE("client-2.1.0", "Try UDP after trying with TCP", "TCP connect() is refused"); memset(payload, 'x', sizeof payload); payload[(sizeof payload) - 1] = '\0'; client_setup_udp_only_server(); orq = nta_outgoing_tcreate(s2->default_leg, s2_nta_orq_callback, NULL, NULL, SIP_METHOD_MESSAGE, URL_STRING_MAKE("sip:test2.0.example.org"), SIPTAG_FROM_STR(""), SIPTAG_PAYLOAD_STR(payload), TAG_END()); fail_unless(orq != NULL); request = s2_sip_wait_for_request(SIP_METHOD_MESSAGE); fail_unless(request != NULL); fail_unless(request->sip->sip_via->v_protocol == sip_transport_udp); s2_sip_respond_to(request, NULL, 200, "OK", TAG_END()); s2_sip_free_message(request); response = s2_nta_wait_for(wait_for_orq, orq, wait_for_status, 200, 0); s2_nta_free_event(response); nta_outgoing_destroy(orq); } END_TEST #undef SU_LOG #include "tport_internal.h" tport_vtable_t hacked_tcp_vtable; /* Make TCP connection to 192.168.255.2:9999 */ static tport_t * hacked_tcp_connect(tport_primary_t *pri, su_addrinfo_t *ai, tp_name_t const *tpn) { su_addrinfo_t fake_ai[1]; su_sockaddr_t fake_addr[1]; uint32_t fake_ip = htonl(0xc0a8ff02); /* 192.168.255.2 */ *fake_ai = *ai; assert(ai->ai_addrlen <= (sizeof fake_addr)); fake_ai->ai_addr = memcpy(fake_addr, ai->ai_addr, ai->ai_addrlen); fake_ai->ai_family = AF_INET; fake_addr->su_family = AF_INET; memcpy(&fake_addr->su_sin.sin_addr, &fake_ip, sizeof fake_ip); fake_addr->su_sin.sin_port = htons(9999); return tport_base_connect(pri, fake_ai, ai, tpn); } START_TEST(client_2_1_1) { tport_t *tp; nta_outgoing_t *orq; struct message *request; struct event *response; char payload[2048]; S2_CASE("client-2.1.1", "Try UDP after trying with TCP", "TCP connect() times out"); memset(payload, 'x', sizeof payload); payload[(sizeof payload) - 1] = '\0'; client_setup_udp_only_server(); hacked_tcp_vtable = tport_tcp_vtable; hacked_tcp_vtable.vtp_connect = hacked_tcp_connect; fail_unless(tport_tcp_vtable.vtp_connect == NULL); for (tp = tport_primaries(nta_agent_tports(s2->nta)); tp; tp = tport_next(tp)) { if (tport_is_tcp(tp)) { tp->tp_pri->pri_vtable = &hacked_tcp_vtable; break; } } orq = nta_outgoing_tcreate(s2->default_leg, s2_nta_orq_callback, NULL, NULL, SIP_METHOD_MESSAGE, URL_STRING_MAKE("sip:test2.0.example.org"), SIPTAG_FROM_STR(""), SIPTAG_PAYLOAD_STR(payload), TAG_END()); fail_unless(orq != NULL); s2_fast_forward(1, s2->root); s2_fast_forward(1, s2->root); s2_fast_forward(1, s2->root); s2_fast_forward(1, s2->root); s2_fast_forward(1, s2->root); request = s2_sip_wait_for_request(SIP_METHOD_MESSAGE); fail_unless(request != NULL); fail_unless(request->sip->sip_via->v_protocol == sip_transport_udp); s2_sip_respond_to(request, NULL, 200, "OK", TAG_END()); s2_sip_free_message(request); response = s2_nta_wait_for(wait_for_orq, orq, wait_for_status, 200, 0); s2_nta_free_event(response); nta_outgoing_destroy(orq); } END_TEST START_TEST(client_2_1_2) { nta_outgoing_t *orq; struct message *request; struct event *response; url_t udpurl[1]; S2_CASE("client-2.1.2", "Send MESSAGE", "Non-INVITE transaction to TCP-only server"); client_setup_tcp_only_server(); *udpurl = *s2sip->tcp.contact->m_url; udpurl->url_params = "transport=udp"; /* Create DNS records for both UDP and TCP, resolver matches UDP */ s2_dns_domain("udptcp.org", 1, "s2", 1, udpurl, "s2", 2, s2sip->tcp.contact->m_url, NULL); /* Sent to tport selected by resolver */ orq = nta_outgoing_tcreate(s2->default_leg, s2_nta_orq_callback, NULL, URL_STRING_MAKE("sip:udptcp.org"), SIP_METHOD_MESSAGE, URL_STRING_MAKE("sip:test2.0.example.org"), SIPTAG_FROM_STR(""), TAG_END()); fail_unless(orq != NULL); response = s2_nta_wait_for(wait_for_orq, orq, wait_for_status, 503, 0); s2_nta_free_event(response); nta_outgoing_destroy(orq); /* Message size exceeds 1300, tries to use TCP even if NAPTR points to UDP */ orq = nta_outgoing_tcreate(s2->default_leg, s2_nta_orq_callback, NULL, URL_STRING_MAKE("sip:udptcp.org"), SIP_METHOD_MESSAGE, URL_STRING_MAKE("sip:test2.0.example.org"), SIPTAG_FROM_STR(""), #define ROW "012345678901234567890123456789012345678901234\n" SIPTAG_PAYLOAD_STR( /* > 1300 bytes */ "0000 " ROW "0050 " ROW "0100 " ROW "0150 " ROW "0200 " ROW "0250 " ROW "0300 " ROW "0350 " ROW "0400 " ROW "0450 " ROW "0500 " ROW "0550 " ROW "0600 " ROW "0650 " ROW "0700 " ROW "0750 " ROW "0800 " ROW "0850 " ROW "0900 " ROW "0950 " ROW "1000 " ROW "1050 " ROW "1100 " ROW "1150 " ROW "1200 " ROW "1250 " ROW ), #undef ROW TAG_END()); fail_unless(orq != NULL); request = s2_sip_wait_for_request(SIP_METHOD_MESSAGE); fail_unless(request != NULL); fail_unless(request->sip->sip_via->v_protocol == sip_transport_tcp); s2_sip_respond_to(request, NULL, 200, "2.1.2", TAG_END()); s2_sip_free_message(request); response = s2_nta_wait_for(wait_for_orq, orq, wait_for_status, 200, 0); s2_nta_free_event(response); nta_outgoing_destroy(orq); } END_TEST TCase *check_nta_client_2_1(void) { TCase *tc = tcase_create("NTA 2.1 - Client"); tcase_add_checked_fixture(tc, NULL, client_teardown); tcase_set_timeout(tc, 20); tcase_add_test(tc, client_2_1_0); tcase_add_test(tc, client_2_1_1); tcase_add_test(tc, client_2_1_2); return tc; } /* ---------------------------------------------------------------------- */ #include START_TEST(client_2_2_0) { nta_outgoing_t *orq; struct message *request; struct event *response; static tp_name_t const tpn[1] = {{ "*", "*", "*", "5060", NULL, NULL }}; static char const * const default_protocols[] = { "udp", "tcp", NULL }; char proxy[] = "sip:cname.example.org:0000000"; S2_CASE("client-2.2.0", "Send MESSAGE", "Basic non-INVITE transaction with target using CNAME"); /* Test for sf.net bug #2531152 */ s2_nta_setup("NTA", NULL, TAG_END()); fail_unless(s2sip->udp.contact != NULL); if (s2sip->udp.contact->m_url->url_port == NULL || tport_tbind(s2sip->master, tpn, default_protocols, TPTAG_SERVER(1), TAG_END()) == -1) { snprintf(proxy, sizeof proxy, "sip:cname.example.org:%s", s2sip->udp.contact->m_url->url_port); } else { strcpy(proxy, "sip:cname.example.org"); } s2_dns_default("example.org."); s2_dns_record("cname.example.org.", sres_type_a, "", sres_type_cname, "a.example.org.", "a", sres_type_a, s2sip->udp.contact->m_url->url_host, NULL); s2_dns_record("cname.example.org.", sres_type_naptr, "", sres_type_cname, "a.example.org.", NULL); s2_dns_record("cname.example.org.", sres_type_aaaa, "", sres_type_cname, "a.example.org.", NULL); s2_dns_record("a.example.org.", sres_type_a, "", sres_type_a, s2sip->udp.contact->m_url->url_host, NULL); s2_nta_agent_setup(URL_STRING_MAKE("sip:0.0.0.0:*"), NULL, NULL, NTATAG_DEFAULT_PROXY(proxy), TAG_END()); orq = nta_outgoing_tcreate(s2->default_leg, s2_nta_orq_callback, NULL, NULL, SIP_METHOD_MESSAGE, URL_STRING_MAKE("sip:test2.2.example.org"), SIPTAG_FROM_STR(""), TAG_END()); fail_unless(orq != NULL); request = s2_sip_wait_for_request(SIP_METHOD_MESSAGE); fail_unless(request != NULL); s2_sip_respond_to(request, NULL, 200, "2.2.0", TAG_END()); response = s2_nta_wait_for(wait_for_orq, orq, wait_for_status, 200, 0); s2_sip_free_message(request); s2_nta_free_event(response); nta_outgoing_destroy(orq); } END_TEST TCase * check_nta_client_2_2(void) { TCase *tc = tcase_create("NTA 2.2 - Client"); tcase_add_checked_fixture(tc, NULL, client_teardown); tcase_set_timeout(tc, 2); tcase_add_test(tc, client_2_2_0); return tc; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/check_nta_server.c000066400000000000000000000105301223300710500240040ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2008 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE check_nta_server.c * * @brief Check-driven tester for NTA server transactions * * @author Pekka Pessi * * @copyright (C) 2010 Nokia Corporation. */ #include "config.h" #include "check_nta.h" #include "s2base.h" #include "s2dns.h" #include #include #include #include #include #include #include #include #include #include #define NONE ((void *)-1) static struct dialog *dialog = NULL; static void server_setup(void) { s2_nta_setup("NTA", NULL, TAG_END()); s2_nta_agent_setup(URL_STRING_MAKE("sip:0.0.0.0:*"), NULL, NULL, TAG_END()); dialog = su_home_new(sizeof *dialog); fail_if(!dialog); dialog->local = sip_from_make(dialog->home, "Alice "); dialog->remote = sip_to_make(dialog->home, "Bob "); } static void server_teardown(void) { mark_point(); s2_nta_teardown(); } START_TEST(server_3_0_0) { struct event *request; struct message *response; S2_CASE("server-3.0.0", "Receive MESSAGE", "Basic non-INVITE transaction"); fail_if(s2_sip_request_to(dialog, SIP_METHOD_MESSAGE, NULL, TAG_END())); request = s2_nta_wait_for(wait_for_method, (void *)sip_method_message, 0); fail_unless(request != NULL); fail_unless(request->irq != NULL); nta_incoming_treply(request->irq, SIP_200_OK, TAG_END()); nta_incoming_destroy(request->irq); response = s2_sip_wait_for_response(200, SIP_METHOD_MESSAGE); fail_unless(response != NULL); } END_TEST START_TEST(server_3_0_1) { struct event *request; struct message *response; sip_via_t *vorig = s2_sip_tport_via(s2sip->udp.tport); sip_via_t via[2]; char *v0_params[8] = {}, *v1_params[8] = {}; char branch0[32], branch1[32]; S2_CASE("server-3.0.1", "Receive MESSAGE", "Basic non-INVITE transaction with comma-separated Via headers"); s2_sip_msg_flags = MSG_FLG_COMMA_LISTS|MSG_FLG_COMPACT; fail_if(vorig == NULL); fail_if(nta_agent_set_params(s2->nta, NTATAG_SIPFLAGS(MSG_FLG_EXTRACT_COPY), TAG_END()) != 1); via[0] = *vorig; via[0].v_host = "example.net"; via[0].v_params = (void *)v0_params; snprintf(v0_params[0] = branch0, sizeof branch0, "branch=z9hG4bK%lx", ++s2sip->tid); fail_if(vorig == NULL); via[1] = *vorig; via[1].v_params = (void *)v1_params; snprintf(v1_params[0] = branch1, sizeof branch1, "branch=z9hG4bK%lx", ++s2sip->tid); fail_if(s2_sip_request_to(dialog, SIP_METHOD_MESSAGE, NULL, SIPTAG_VIA(via + 1), SIPTAG_VIA(via + 0), TAG_END())); request = s2_nta_wait_for(wait_for_method, (void *)sip_method_message, 0); fail_unless(request != NULL); fail_unless(request->irq != NULL); fail_if(nta_incoming_treply(request->irq, SIP_200_OK, TAG_END()) != 0); nta_incoming_destroy(request->irq); response = s2_sip_wait_for_response(200, SIP_METHOD_MESSAGE); fail_unless(response != NULL); fail_unless(response->sip->sip_via != NULL && response->sip->sip_via->v_next != NULL); } END_TEST /* ---------------------------------------------------------------------- */ TCase *check_nta_server_3_0(void) { TCase *tc = tcase_create("NTA 2.0 - Server"); tcase_add_checked_fixture(tc, server_setup, server_teardown); tcase_set_timeout(tc, 2); tcase_add_test(tc, server_3_0_0); tcase_add_test(tc, server_3_0_1); return tc; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/invite.msc000066400000000000000000000177741223300710500223560ustar00rootroot00000000000000# # MSCs Illustrating NTA Usage # User Agent Client Initiating a Call ----------------------------------- APP NTA User Agent | | nta = nta_agent_create |- - - - - - - - - - - - - - - - -> NTA | (msg_cb, contact) agent | | | | |- - ->Call | | | | | | leg = nta_leg_create | | |- - - - - - -- - - - - - -|- - - -> leg | |(nta, leg_cb, ..., To, From, ... ) | | | | | | | | | | | oreq = nta_outgoing_create| | | |- - - - - - -- - - - - - -|- - - - - | - - -> outgoing | | (leg, response_cb, INVITE, url, headers...) | | | | | | | | | | | INVITE | | | | |----> | | | | | | | | | | 100 Trying | | | | |<---- | | | | | | | | | | 180 Ringing | | | response_cb(180) |<---- | ALERT |<--------------------------|----------|------------| |<-------| | | | 200 OK | | | response_cb(200) |<---- |OFFHOOK |<--------------------------|----------|------------| |<-------| | | | | | nta_outgoing_destroy | | | | |---------------------------|----------|----------->| | | | | X | | nta_leg_destroy | | | |---------------------------|--------->| | | | X | | leg = nta_leg_create | | |- - - - - - -- - - - - - -|- - - -> leg | |(nta, leg_cb, ..., To+tag, From, ...) | | | | | | | oreq = nta_outgoing_create| | | |- - - - - - -- - - - - - -|- - - - - | - - -> outgoing | | (leg, ..., ACK, url, headers) | | | | | | | ACK | | | | |----> | | nta_outgoing_destroy | | | | |---------------------------|----------|----------->| | | | | X User Agent Client Releasing a Call ----------------------------------- APP NTA User Call NTA leg Agent | agent | | | | | |ONHOOK | | | |------->| | | | |oreq = nta_outgoing_create | | | |- - - - - - -- - - - - - -|- - - - - | - - -> outgoing | | (leg, ..., BYE, url, headers) | | | | | | | BYE | | | | |----> | | | | | | | | | | 180 Ringing | | | response_cb(180) |<---- | |<--------------------------|----------|------------| | | | | | 200 OK | | | response_cb(200) |<---- | |<--------------------------|----------|------------| | | | | | | |nta_outgoing_destroy | | | | |---------------------------|----------|----------->| | | | | X | |nta_leg_destroy | | | |---------------------------|--------->| | | | X | X | User Agent Server Accepting a Call ---------------------------------- APP NTA User NTA Agent agent | | INVITE | |<---------------------- | | | msg_cb(leg, msg) | |<-----------------------------------| | | |- - -> Call | | | nta_msg_leg | | |-------------------------->|- - - -> leg | | (msg, request_cb) | | | | | |- - - -> incoming | | nta_leg_tag | | | | |---------------------------|--------->| | | | (tag) | | | | | | request_cb(reply) | | |<--------------------------|----------|------------| | | | | | | | nta_incoming_bind(ireq, ack_cb) | | | |---------------------------|----------|----------->| | | | | | | | nta_incoming_reply(180) | | | | ALERT |---------------------------|----------|----------->| 180 Ringing |<-------| | | |----> | | | | | |OFFHOOK | | | | |------->| nta_incoming_reply | | | | |---------------------------|----------|----------->| 200 Ok | | (200, sdp) | | |----> | | | | | | | | | | ACK | | | |ack_cb(ACK) |<---- | |<--------------------------|----------|------------| | | | | | | | nta_incoming_destroy(ireq)| | | | |---------------------------|----------|----------->| | | | | X User Agent Server Receiving a Call Release ------------------------------------------ APP NTA User Call NTA leg Agent | agent | | | | | BYE | | | |<------------------ | | | | | | | |- - - -> Incoming | | | | | | | | request_cb(reply) | | ONHOOK |<--------------------------|----------|------------| |<-------| | | | | | nta_incoming_reply(200) | | | | |---------------------------|----------|----------->| 200 Ok | | (200, sdp) | | |----> | | | | | | | nta_incoming_destroy(ireq)| | | | |---------------------------|----------|----------->| | | | | X | |nta_leg_destroy | | | |---------------------------|--------->| | X | X sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/nta.c000066400000000000000000012016051223300710500212670ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE nta.c * @brief Sofia SIP Transaction API implementation * * This source file has been divided into sections as follows: * 1) agent * 2) tport handling * 3) dispatching messages received from network * 4) message creation and message utility functions * 5) stateless operation * 6) dialogs (legs) * 7) server transactions (incoming) * 8) client transactions (outgoing) * 9) resolving URLs for client transactions * 10) 100rel reliable responses (reliable) * 11) SigComp handling and public transport interface * * @author Pekka Pessi * * @date Created: Tue Jun 13 02:57:51 2000 ppessi * * @sa * @RFC3261, @RFC4320 */ #include "config.h" #include /** @internal SU message argument structure type */ #define SU_MSG_ARG_T union sm_arg_u /** @internal SU timer argument pointer type */ #define SU_TIMER_ARG_T struct nta_agent_s #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Resolver context type */ #define SRES_CONTEXT_T nta_outgoing_t /* We are customer of tport_t */ #define TP_AGENT_T nta_agent_t #define TP_MAGIC_T sip_via_t #define TP_CLIENT_T nta_outgoing_t #include "nta_internal.h" #include #include #include #include #include #include #include /* From AM_INIT/AC_INIT in our "config.h" */ char const nta_version[] = PACKAGE_VERSION; #if HAVE_FUNC #elif HAVE_FUNCTION #define __func__ __FUNCTION__ #else static char const __func__[] = "nta"; #endif #define NONE ((void *)(intptr_t)-1) /* ------------------------------------------------------------------------- */ /** Resolving order */ enum nta_res_order_e { nta_res_ip6_ip4, nta_res_ip4_ip6, nta_res_ip6_only, nta_res_ip4_only }; HTABLE_DECLARE_WITH(leg_htable, lht, nta_leg_t, size_t, hash_value_t); HTABLE_DECLARE_WITH(outgoing_htable, oht, nta_outgoing_t, size_t, hash_value_t); HTABLE_DECLARE_WITH(incoming_htable, iht, nta_incoming_t, size_t, hash_value_t); typedef struct outgoing_queue_t { nta_outgoing_t **q_tail; nta_outgoing_t *q_head; size_t q_length; unsigned q_timeout; } outgoing_queue_t; typedef struct incoming_queue_t { nta_incoming_t **q_tail; nta_incoming_t *q_head; size_t q_length; unsigned q_timeout; } incoming_queue_t; struct nta_agent_s { su_home_t sa_home[1]; su_root_t *sa_root; su_timer_t *sa_timer; nta_agent_magic_t *sa_magic; nta_message_f *sa_callback; nta_update_magic_t *sa_update_magic; nta_update_tport_f *sa_update_tport; su_time_t sa_now; /**< Timestamp in microsecond resolution. */ uint32_t sa_next; /**< Timestamp for next agent_timer. */ uint32_t sa_millisec; /**< Timestamp in milliseconds. */ uint32_t sa_cseq; msg_mclass_t const *sa_mclass; uint32_t sa_flags; /**< SIP message flags */ unsigned sa_preload; /**< Memory preload for SIP messages. */ tport_t *sa_tports; sip_contact_t *sa_contact; sip_via_t *sa_vias; /**< @Via headers for all transports */ sip_via_t *sa_public_vias; /**< @Vias for public transports */ sip_contact_t *sa_aliases;/**< List of aliases for agent */ uint64_t sa_branch; /**< Generator for branch parameters */ uint64_t sa_tags; /**< Generator for tag parameters */ #if HAVE_SOFIA_SRESOLV sres_resolver_t *sa_resolver; /**< DNS resolver */ enum nta_res_order_e sa_res_order; /** Resolving order (AAAA/A) */ #endif url_t *sa_default_proxy; /**< Default outbound proxy */ unsigned sa_bad_req_mask; /**< Request error mask */ unsigned sa_bad_resp_mask; /**< Response error mask */ usize_t sa_maxsize; /**< Maximum size of incoming messages */ usize_t sa_max_proceeding; /**< Maximum size of proceeding queue */ unsigned sa_udp_mtu; /**< Maximum size of outgoing UDP requests */ unsigned sa_t1; /**< SIP T1 - initial retransmit interval (500 ms) */ unsigned sa_t2; /**< SIP T2 - maximum retransmit interval (4000 ms) */ unsigned sa_t4; /**< SIP T4 - clear message time (5000 ms) */ unsigned sa_t1x64; /**< SIP T1X64 - transaction lifetime (32 s) */ unsigned sa_progress; /**< Progress timer. Interval between retransmitting provisional responses. */ unsigned sa_timer_c; /**< SIP timer C. Maximum interval between receiving provisional responses. */ unsigned sa_graylist; /**< Graylisting period */ unsigned sa_blacklist; /**< Blacklisting period */ unsigned sa_drop_prob : 10; /**< NTA is used to test packet drop */ unsigned sa_is_a_uas : 1; /**< NTA is acting as an User Agent server */ unsigned sa_is_stateless : 1; /**< Process requests statelessly * unless they match existing dialog. */ unsigned sa_user_via:1; /**< Let application provide @Via headers */ unsigned sa_extra_100:1; /**< Allow NTA to return "100 Trying" response * even if application has not responded. */ unsigned sa_pass_100:1; /**< Pass the "100 Trying" * provisional responses to the application */ unsigned sa_timeout_408:1; /**< A "408 Request Timeout" message * is generated when outgoing request expires. */ unsigned sa_pass_408:1; /**< A "408 Request Timeout" responses * are passed to client. */ unsigned sa_merge_482 : 1; /**< A "482 Request Merged" response is returned * to merged requests. */ unsigned sa_cancel_2543 : 1; /**< Send a CANCEL to an INVITE without * waiting for an provisional response. */ unsigned sa_cancel_487 : 1; /**< Return 487 response automatically when * a CANCEL is received. */ unsigned sa_invite_100rel:1; /**< Include 100rel in INVITE requests. */ unsigned sa_timestamp : 1; /**< Insert @Timestamp in requests. */ unsigned sa_tport_ip4 : 1; /**< Transports support IPv4. */ unsigned sa_tport_ip6 : 1; /**< Transports support IPv6. */ unsigned sa_tport_udp : 1; /**< Transports support UDP. */ unsigned sa_tport_tcp : 1; /**< Transports support TCP. */ unsigned sa_tport_sctp : 1; /**< Transports support SCTP. */ unsigned sa_tport_tls : 1; /**< Transports support TLS. */ unsigned sa_use_naptr : 1; /**< Use NAPTR lookup */ unsigned sa_use_srv : 1; /**< Use SRV lookup */ unsigned sa_tport_threadpool:1; /**< Transports use threadpool */ unsigned sa_rport:1; /**< Use rport at client */ unsigned sa_server_rport:2; /**< Use rport at server */ unsigned sa_tcp_rport:1; /**< Use rport with tcp, too */ unsigned sa_tls_rport:1; /**< Use rport with tls, too */ unsigned sa_auto_comp:1; /**< Automatically create compartments */ unsigned sa_in_timer:1; /**< Set when executing timers */ unsigned sa_use_timer_c:1; /**< Application has set value for timer C */ unsigned :0; #if HAVE_SMIME sm_object_t *sa_smime; #else void *sa_smime; #endif /** @MaxForwards */ sip_max_forwards_t sa_max_forwards[1]; /** Name of SigComp algorithm */ char const *sa_algorithm; /** Options for SigComp. */ char const *sa_sigcomp_options; char const* const *sa_sigcomp_option_list; char const *sa_sigcomp_option_free; nta_compressor_t *sa_compressor; /* Statistics */ struct { usize_t as_recv_msg; usize_t as_recv_request; usize_t as_recv_response; usize_t as_bad_message; usize_t as_bad_request; usize_t as_bad_response; usize_t as_drop_request; usize_t as_drop_response; usize_t as_client_tr; usize_t as_server_tr; usize_t as_dialog_tr; usize_t as_acked_tr; usize_t as_canceled_tr; usize_t as_trless_request; usize_t as_trless_to_tr; usize_t as_trless_response; usize_t as_trless_200; usize_t as_merged_request; usize_t as_sent_msg; usize_t as_sent_request; usize_t as_sent_response; usize_t as_retry_request; usize_t as_retry_response; usize_t as_recv_retry; usize_t as_tout_request; usize_t as_tout_response; } sa_stats[1]; /** Hash of dialogs. */ leg_htable_t sa_dialogs[1]; /** Default leg */ nta_leg_t *sa_default_leg; /** Hash of legs without dialogs. */ leg_htable_t sa_defaults[1]; /** Hash table for outgoing transactions */ outgoing_htable_t sa_outgoing[1]; nta_outgoing_t *sa_default_outgoing; /** Hash table for incoming transactions */ incoming_htable_t sa_incoming[1]; nta_incoming_t *sa_default_incoming; /* Queues (states) for outgoing client transactions */ struct { /** Queue for retrying client transactions */ nta_outgoing_t *re_list; nta_outgoing_t **re_t1; /**< Special place for T1 timer */ size_t re_length; /**< Length of sa_out.re_list */ outgoing_queue_t delayed[1]; outgoing_queue_t resolving[1]; outgoing_queue_t trying[1]; /* Timer F / Timer E */ outgoing_queue_t completed[1]; /* Timer K */ outgoing_queue_t terminated[1]; /* Special queues (states) for outgoing INVITE transactions */ outgoing_queue_t inv_calling[1]; /* Timer B/A */ outgoing_queue_t inv_proceeding[1]; /* Timer C */ outgoing_queue_t inv_completed[1]; /* Timer D */ /* Temporary queue for transactions waiting to be freed */ outgoing_queue_t *free; } sa_out; /* Queues (states) for incoming server transactions */ struct { /** Queue for retransmitting response of server transactions */ nta_incoming_t *re_list; nta_incoming_t **re_t1; /**< Special place for T1 timer */ size_t re_length; /**< Length of sa_in.re_list */ incoming_queue_t proceeding[1]; /**< Request received */ incoming_queue_t preliminary[1]; /**< 100rel sent */ incoming_queue_t completed[1]; /**< Final answer sent (non-invite). */ incoming_queue_t inv_completed[1]; /**< Final answer sent (INVITE). */ incoming_queue_t inv_confirmed[1]; /**< Final answer sent, ACK recvd. */ incoming_queue_t terminated[1]; /**< Terminated, ready to free. */ incoming_queue_t final_failed[1]; } sa_in; /* Special task for freeing memory */ su_clone_r sa_terminator; }; struct nta_leg_s { su_home_t leg_home[1]; hash_value_t leg_hash; unsigned leg_dialog : 1; unsigned leg_stateless : 1; /**< Process requests statelessly */ #ifdef NTA_STRICT_ROUTING unsigned leg_contact_set : 1; #else unsigned leg_loose_route : 1; /**< Topmost route in set is LR */ #endif unsigned leg_route_set : 1; /**< Route set has been saved */ unsigned leg_local_is_to : 1; /**< Backwards-compatibility. */ unsigned leg_tagged : 1; /**< Tagged after creation. * * Request missing @To tag matches * a tagged leg even after tagging. */ unsigned:0; nta_request_f *leg_callback; nta_leg_magic_t *leg_magic; nta_agent_t *leg_agent; url_t const *leg_url; /**< Match incoming requests. */ char const *leg_method; /**< Match incoming requests. */ uint32_t leg_seq; /**< Sequence number for next transaction */ uint32_t leg_rseq; /**< Remote sequence number */ sip_call_id_t *leg_id; /**< Call ID */ sip_from_t *leg_remote; /**< Remote address (@To/@From) */ sip_to_t *leg_local; /**< Local address (@From/@To) */ sip_route_t *leg_route; /**< @Route for outgoing requests. */ sip_contact_t *leg_target; /**< Remote destination (from @Contact). */ }; struct nta_incoming_s { su_home_t *irq_home; hash_value_t irq_hash; nta_agent_t *irq_agent; nta_ack_cancel_f *irq_callback; nta_incoming_magic_t *irq_magic; /* Timeout/state queue */ nta_incoming_t **irq_prev; nta_incoming_t *irq_next; incoming_queue_t *irq_queue; /* Retry queue */ nta_incoming_t **irq_rprev; nta_incoming_t *irq_rnext; sip_method_t irq_method; sip_request_t *irq_rq; sip_from_t *irq_from; sip_to_t *irq_to; char const *irq_tag; sip_cseq_t *irq_cseq; sip_call_id_t *irq_call_id; sip_via_t *irq_via; sip_record_route_t *irq_record_route; char const *irq_branch; uint32_t irq_rseq; sip_timestamp_t *irq_timestamp; su_time_t irq_received; uint32_t irq_timeout; /**< Timer H, I, J */ uint32_t irq_retry; /**< Timer G */ unsigned short irq_interval; /**< Next timer */ short irq_status; unsigned irq_retries:8; /**< Number of retries. * Disable SigComp if too many retries. */ unsigned irq_default:1; /**< Default transaction */ unsigned irq_canceled:1; /**< Transaction is canceled */ unsigned irq_completed:1; /**< Transaction is completed */ unsigned irq_confirmed:1; /**< Response has been acked */ unsigned irq_terminated:1; /**< Transaction is terminated */ unsigned irq_final_failed:1; /**< Sending final response failed */ unsigned irq_destroyed :1; /**< Transaction is destroyed */ unsigned irq_in_callback:1; /**< Callback is being invoked */ unsigned irq_reliable_tp:1; /**< Transport is reliable */ unsigned irq_sigcomp_zap:1; /**< Reset SigComp */ unsigned irq_must_100rel:1; /**< 100rel is required */ unsigned irq_extra_100:1; /**< 100 Trying should be sent */ unsigned irq_tag_set:1; /**< Tag is not from request */ unsigned :0; tp_name_t irq_tpn[1]; tport_t *irq_tport; struct sigcomp_compartment *irq_cc; msg_t *irq_request; msg_t *irq_request2; /**< ACK/CANCEL */ msg_t *irq_response; nta_reliable_t *irq_reliable; /**< List of reliable responses */ }; struct nta_reliable_s { nta_reliable_t *rel_next; nta_incoming_t *rel_irq; nta_prack_f *rel_callback; nta_reliable_magic_t *rel_magic; uint32_t rel_rseq; unsigned short rel_status; unsigned rel_pracked:1; unsigned rel_precious:1; msg_t *rel_response; msg_t *rel_unsent; }; typedef struct sipdns_resolver sipdns_resolver_t; struct nta_outgoing_s { hash_value_t orq_hash; /**< Hash value */ nta_agent_t *orq_agent; nta_response_f *orq_callback; nta_outgoing_magic_t *orq_magic; /* Timeout/state queue */ nta_outgoing_t **orq_prev; nta_outgoing_t *orq_next; outgoing_queue_t *orq_queue; /* Retry queue */ nta_outgoing_t **orq_rprev; nta_outgoing_t *orq_rnext; sip_method_t orq_method; char const *orq_method_name; url_t const *orq_url; /**< Original RequestURI */ sip_from_t const *orq_from; sip_to_t const *orq_to; char const *orq_tag; /**< Tag from final response. */ sip_cseq_t const *orq_cseq; sip_call_id_t const *orq_call_id; msg_t *orq_request; msg_t *orq_response; su_time_t orq_sent; /**< When request was sent? */ unsigned orq_delay; /**< RTT estimate */ uint32_t orq_retry; /**< Timer A, E */ uint32_t orq_timeout; /**< Timer B, D, F, K */ unsigned short orq_interval; /**< Next timer A/E */ unsigned short orq_status; unsigned char orq_retries; /**< Number of tries this far */ unsigned orq_default:1; /**< This is default transaction */ unsigned orq_inserted:1; unsigned orq_resolved:1; unsigned orq_via_added:1; unsigned orq_prepared:1; unsigned orq_canceled:1; unsigned orq_terminated:1; unsigned orq_destroyed:1; unsigned orq_completed:1; unsigned orq_delayed:1; unsigned orq_user_tport:1; /**< Application provided tport - don't retry */ unsigned orq_try_tcp_instead:1; unsigned orq_try_udp_instead:1; unsigned orq_reliable:1; /**< Transport is reliable */ unsigned orq_forked:1; /**< Tagged fork */ /* Attributes */ unsigned orq_sips:1; unsigned orq_uas:1; /**< Running this transaction as UAS */ unsigned orq_user_via:1; unsigned orq_stateless:1; unsigned orq_pass_100:1; unsigned orq_sigcomp_new:1; /**< Create compartment if needed */ unsigned orq_sigcomp_zap:1; /**< Reset SigComp after completing */ unsigned orq_must_100rel:1; unsigned orq_timestamp:1; /**< Insert @Timestamp header. */ unsigned orq_100rel:1; /**< Support 100rel */ unsigned:0; /* pad */ #if HAVE_SOFIA_SRESOLV sipdns_resolver_t *orq_resolver; #endif url_t *orq_route; /**< Route URL */ tp_name_t orq_tpn[1]; /**< Where to send request */ tport_t *orq_tport; struct sigcomp_compartment *orq_cc; tagi_t *orq_tags; /**< Tport tag items */ char const *orq_branch; /**< Transaction branch */ char const *orq_via_branch; /**< @Via branch */ int *orq_status2b; /**< Delayed response */ nta_outgoing_t *orq_cancel; /**< Delayed CANCEL transaction */ nta_outgoing_t *orq_forking; /**< Untagged transaction */ nta_outgoing_t *orq_forks; /**< Tagged transactions */ uint32_t orq_rseq; /**< Latest incoming rseq */ int orq_pending; /**< Request is pending in tport */ }; /* ------------------------------------------------------------------------- */ /* Internal tags */ /* Delay sending of request */ #define NTATAG_DELAY_SENDING(x) ntatag_delay_sending, tag_bool_v((x)) #define NTATAG_DELAY_SENDING_REF(x) \ ntatag_delay_sending_ref, tag_bool_vr(&(x)) extern tag_typedef_t ntatag_delay_sending; extern tag_typedef_t ntatag_delay_sending_ref; /* Allow sending incomplete responses */ #define NTATAG_INCOMPLETE(x) ntatag_incomplete, tag_bool_v((x)) #define NTATAG_INCOMPLETE_REF(x) \ ntatag_incomplete_ref, tag_bool_vr(&(x)) extern tag_typedef_t ntatag_incomplete; extern tag_typedef_t ntatag_incomplete_ref; nta_compressor_vtable_t *nta_compressor_vtable = NULL; /* Agent */ static int agent_tag_init(nta_agent_t *self); static int agent_timer_init(nta_agent_t *agent); static void agent_timer(su_root_magic_t *rm, su_timer_t *, nta_agent_t *); static int agent_launch_terminator(nta_agent_t *agent); static void agent_kill_terminator(nta_agent_t *agent); static int agent_set_params(nta_agent_t *agent, tagi_t *tags); static void agent_set_udp_params(nta_agent_t *self, usize_t udp_mtu); static int agent_get_params(nta_agent_t *agent, tagi_t *tags); /* Transport interface */ static sip_via_t const *agent_tport_via(tport_t *tport); static int outgoing_insert_via(nta_outgoing_t *orq, sip_via_t const *); static int nta_tpn_by_via(tp_name_t *tpn, sip_via_t const *v, int *using_rport); static msg_t *nta_msg_create_for_transport(nta_agent_t *agent, int flags, char const data[], usize_t dlen, tport_t const *tport, tp_client_t *via); static int complete_response(msg_t *response, int status, char const *phrase, msg_t *request); static int mreply(nta_agent_t *agent, msg_t *reply, int status, char const *phrase, msg_t *req_msg, tport_t *tport, int incomplete, int sdwn_after, char const *to_tag, tag_type_t tag, tag_value_t value, ...); #define IF_SIGCOMP_TPTAG_COMPARTMENT(cc) TAG_IF(cc && cc != NONE, TPTAG_COMPARTMENT(cc)), #define IF_SIGCOMP_TPTAG_COMPARTMENT_REF(cc) TPTAG_COMPARTMENT_REF(cc), struct sigcomp_compartment; struct sigcomp_compartment * nta_compartment_ref(struct sigcomp_compartment *cc); static struct sigcomp_compartment * agent_compression_compartment(nta_agent_t *sa, tport_t *tp, tp_name_t const *tpn, int new_if_needed); static int agent_accept_compressed(nta_agent_t *sa, msg_t *msg, struct sigcomp_compartment *cc); static int agent_close_compressor(nta_agent_t *sa, struct sigcomp_compartment *cc); static int agent_zap_compressor(nta_agent_t *sa, struct sigcomp_compartment *cc); static char const * stateful_branch(su_home_t *home, nta_agent_t *); static char const * stateless_branch(nta_agent_t *, msg_t *, sip_t const *, tp_name_t const *tp); #define NTA_BRANCH_PRIME SU_U64_C(0xB9591D1C361C6521) #define NTA_TAG_PRIME SU_U64_C(0xB9591D1C361C6521) #ifndef UINT32_MAX #define UINT32_MAX (0xffffffffU) #endif HTABLE_PROTOS_WITH(leg_htable, lht, nta_leg_t, size_t, hash_value_t); static nta_leg_t *leg_find(nta_agent_t const *sa, char const *method_name, url_t const *request_uri, sip_call_id_t const *i, char const *from_tag, char const *to_tag); static nta_leg_t *dst_find(nta_agent_t const *sa, url_t const *u0, char const *method); static void leg_recv(nta_leg_t *, msg_t *, sip_t *, tport_t *); static void leg_free(nta_agent_t *sa, nta_leg_t *leg); #define NTA_HASH(i, cs) ((i)->i_hash + 26839U * (uint32_t)(cs)) HTABLE_PROTOS_WITH(incoming_htable, iht, nta_incoming_t, size_t, hash_value_t); static nta_incoming_t *incoming_create(nta_agent_t *agent, msg_t *request, sip_t *sip, tport_t *tport, char const *tag); static int incoming_callback(nta_leg_t *leg, nta_incoming_t *irq, sip_t *sip); static void incoming_free(nta_incoming_t *irq); su_inline void incoming_cut_off(nta_incoming_t *irq); su_inline void incoming_reclaim(nta_incoming_t *irq); static void incoming_queue_init(incoming_queue_t *, unsigned timeout); static void incoming_queue_adjust(nta_agent_t *sa, incoming_queue_t *queue, unsigned timeout); static nta_incoming_t *incoming_find(nta_agent_t const *agent, sip_t const *sip, sip_via_t const *v, nta_incoming_t **merge, nta_incoming_t **ack, nta_incoming_t **cancel); static int incoming_reply(nta_incoming_t *irq, msg_t *msg, sip_t *sip); su_inline int incoming_recv(nta_incoming_t *irq, msg_t *msg, sip_t *sip, tport_t *tport); su_inline int incoming_ack(nta_incoming_t *irq, msg_t *msg, sip_t *sip, tport_t *tport); su_inline int incoming_cancel(nta_incoming_t *irq, msg_t *msg, sip_t *sip, tport_t *tport); static void request_merge(nta_agent_t *, msg_t *msg, sip_t *sip, tport_t *tport, char const *to_tag); su_inline int incoming_timestamp(nta_incoming_t *, msg_t *, sip_t *); static void _nta_incoming_timer(nta_agent_t *); static nta_reliable_t *reliable_mreply(nta_incoming_t *, nta_prack_f *, nta_reliable_magic_t *, msg_t *, sip_t *); static int reliable_send(nta_incoming_t *, nta_reliable_t *, msg_t *, sip_t *); static int reliable_final(nta_incoming_t *irq, msg_t *msg, sip_t *sip); static msg_t *reliable_response(nta_incoming_t *irq); static nta_reliable_t *reliable_find(nta_agent_t const *, sip_t const *); static int reliable_recv(nta_reliable_t *rel, msg_t *, sip_t *, tport_t *); static void reliable_flush(nta_incoming_t *irq); static void reliable_timeout(nta_incoming_t *irq, int timeout); HTABLE_PROTOS_WITH(outgoing_htable, oht, nta_outgoing_t, size_t, hash_value_t); static nta_outgoing_t *outgoing_create(nta_agent_t *agent, nta_response_f *callback, nta_outgoing_magic_t *magic, url_string_t const *route_url, tp_name_t const *tpn, msg_t *msg, tag_type_t tag, tag_value_t value, ...); static void outgoing_queue_init(outgoing_queue_t *, unsigned timeout); static void outgoing_queue_adjust(nta_agent_t *sa, outgoing_queue_t *queue, unsigned timeout); static void outgoing_free(nta_outgoing_t *orq); su_inline void outgoing_cut_off(nta_outgoing_t *orq); su_inline void outgoing_reclaim(nta_outgoing_t *orq); static nta_outgoing_t *outgoing_find(nta_agent_t const *sa, msg_t const *msg, sip_t const *sip, sip_via_t const *v); static int outgoing_recv(nta_outgoing_t *orq, int status, msg_t *, sip_t *); static void outgoing_default_recv(nta_outgoing_t *, int, msg_t *, sip_t *); static void _nta_outgoing_timer(nta_agent_t *); static int outgoing_recv_reliable(nta_outgoing_t *orq, msg_t *msg, sip_t *sip); /* Internal message passing */ union sm_arg_u { struct outgoing_recv_s { nta_outgoing_t *orq; msg_t *msg; sip_t *sip; int status; } a_outgoing_recv[1]; incoming_queue_t a_incoming_queue[1]; outgoing_queue_t a_outgoing_queue[1]; }; /* Global module data */ /**@var char const NTA_DEBUG[]; * * Environment variable determining the default debug log level. * * The NTA_DEBUG environment variable is used to determine the default * debug logging level. The normal level is 3. * * @sa , #su_log_global, #SOFIA_DEBUG */ #if DOXYGEN_ONLY char const NTA_DEBUG[]; /* dummy declaration for Doxygen */ #endif #ifndef SU_DEBUG #define SU_DEBUG 3 #endif /**Debug log for @b nta module. * * The nta_log is the log object used by @b nta module. The level of * nta_log is set using #NTA_DEBUG environment variable. */ su_log_t nta_log[] = { SU_LOG_INIT("nta", "NTA_DEBUG", SU_DEBUG) }; /* ====================================================================== */ /* 1) Agent */ /** * Create an NTA agent object. * * Create an NTA agent object. The agent * object creates and binds a server socket with address specified in @e url. * If the @e host portion of the @e url is @c "*", the agent listens to all * addresses available on the host. * * When a message is received, the agent object parses it. If the result is * a valid SIP message, the agent object passes the message to the * application by invoking the nta_message_f @e callback function. * * @note * The @e url can be either parsed url (of type url_t ()), or a valid * SIP URL as a string. * * @note * If @e url is @c NULL, the default @e url @c "sip:*" is used. * @par * If @e url is @c NONE (iow, (void*)-1), no server sockets are bound. * @par * If @p transport parameters are specified in @a url, agent uses only * specified transport type. * * @par * If an @p maddr parameter is specified in @e url, agent binds to the * specified address, but uses @e host part of @e url when it generates * @Contact and @Via headers. The @p maddr parameter is also included, * unless it equals to @c INADDR_ANY (@p 0.0.0.0 or @p [::]). * * @param root pointer to a su_root_t used for synchronization * @param contact_url URL that agent uses to bind the server sockets * @param callback pointer to callback function * @param magic pointer to user data * @param tag,value,... tagged arguments * * @TAGS * NTATAG_ALIASES(), * NTATAG_BAD_REQ_MASK(), NTATAG_BAD_RESP_MASK(), NTATAG_BLACKLIST(), * NTATAG_CANCEL_2543(), NTATAG_CANCEL_487(), NTATAG_CLIENT_RPORT(), * NTATAG_DEBUG_DROP_PROB(), NTATAG_DEFAULT_PROXY(), * NTATAG_EXTRA_100(), NTATAG_GRAYLIST(), * NTATAG_MAXSIZE(), NTATAG_MAX_FORWARDS(), NTATAG_MERGE_482(), NTATAG_MCLASS() * NTATAG_PASS_100(), NTATAG_PASS_408(), NTATAG_PRELOAD(), NTATAG_PROGRESS(), * NTATAG_REL100(), * NTATAG_SERVER_RPORT(), * NTATAG_SIPFLAGS(), * NTATAG_SIP_T1X64(), NTATAG_SIP_T1(), NTATAG_SIP_T2(), NTATAG_SIP_T4(), * NTATAG_STATELESS(), * NTATAG_TAG_3261(), NTATAG_TCP_RPORT(), NTATAG_TIMEOUT_408(), * NTATAG_TLS_RPORT(), * NTATAG_TIMER_C(), NTATAG_MAX_PROCEEDING(), * NTATAG_UA(), NTATAG_UDP_MTU(), NTATAG_USER_VIA(), * NTATAG_USE_NAPTR(), NTATAG_USE_SRV() and NTATAG_USE_TIMESTAMP(). * * @note The value from following tags are stored, but they currently do nothing: * NTATAG_SIGCOMP_ALGORITHM(), NTATAG_SIGCOMP_OPTIONS(), NTATAG_SMIME() * * @note It is possible to provide @c (url_string_t*)-1 as @a contact_url. * In that case, no server sockets are bound. * * @retval handle to the agent when successful, * @retval NULL upon an error. * * @sa NUTAG_ */ nta_agent_t *nta_agent_create(su_root_t *root, url_string_t const *contact_url, nta_message_f *callback, nta_agent_magic_t *magic, tag_type_t tag, tag_value_t value, ...) { nta_agent_t *agent; ta_list ta; if (root == NULL) return su_seterrno(EINVAL), NULL; ta_start(ta, tag, value); if ((agent = su_home_new(sizeof(*agent)))) { unsigned timer_c = 0, timer_d = 32000; agent->sa_root = root; agent->sa_callback = callback; agent->sa_magic = magic; agent->sa_flags = MSG_DO_CANONIC; agent->sa_cseq = (su_nanotime(NULL) / 4 / SU_E9) & 0x3fffffff; agent->sa_maxsize = 2 * 1024 * 1024; /* 2 MB */ agent->sa_bad_req_mask = /* * Bit-wise not of these - what is left is suitable for UAs with * 100rel, timer, events, publish */ (unsigned) ~(sip_mask_response | sip_mask_proxy | sip_mask_registrar | sip_mask_pref | sip_mask_privacy); agent->sa_bad_resp_mask = (unsigned) ~(sip_mask_request | sip_mask_proxy | sip_mask_registrar | sip_mask_pref | sip_mask_privacy); agent->sa_t1 = NTA_SIP_T1; agent->sa_t2 = NTA_SIP_T2; agent->sa_t4 = NTA_SIP_T4; agent->sa_t1x64 = 64 * NTA_SIP_T1; agent->sa_timer_c = 185 * 1000; agent->sa_graylist = 600; agent->sa_drop_prob = 0; agent->sa_is_a_uas = 0; agent->sa_progress = 60 * 1000; agent->sa_user_via = 0; agent->sa_extra_100 = 0; agent->sa_pass_100 = 0; agent->sa_timeout_408 = 1; agent->sa_pass_408 = 0; agent->sa_merge_482 = 0; agent->sa_cancel_2543 = 0; agent->sa_cancel_487 = 1; agent->sa_invite_100rel = 0; agent->sa_timestamp = 0; agent->sa_use_naptr = 1; agent->sa_use_srv = 1; agent->sa_auto_comp = 0; agent->sa_server_rport = 1; /* RFC 3261 section 8.1.1.6 */ sip_max_forwards_init(agent->sa_max_forwards); if (getenv("SIPCOMPACT")) agent->sa_flags |= MSG_DO_COMPACT; agent_set_params(agent, ta_args(ta)); if (agent->sa_mclass == NULL) agent->sa_mclass = sip_default_mclass(); agent->sa_in.re_t1 = &agent->sa_in.re_list; incoming_queue_init(agent->sa_in.proceeding, 0); incoming_queue_init(agent->sa_in.preliminary, agent->sa_t1x64); /* P1 */ incoming_queue_init(agent->sa_in.inv_completed, agent->sa_t1x64); /* H */ incoming_queue_init(agent->sa_in.inv_confirmed, agent->sa_t4); /* I */ incoming_queue_init(agent->sa_in.completed, agent->sa_t1x64); /* J */ incoming_queue_init(agent->sa_in.terminated, 0); incoming_queue_init(agent->sa_in.final_failed, 0); agent->sa_out.re_t1 = &agent->sa_out.re_list; if (agent->sa_use_timer_c || !agent->sa_is_a_uas) timer_c = agent->sa_timer_c; if (timer_d < agent->sa_t1x64) timer_d = agent->sa_t1x64; outgoing_queue_init(agent->sa_out.delayed, 0); outgoing_queue_init(agent->sa_out.resolving, 0); outgoing_queue_init(agent->sa_out.trying, agent->sa_t1x64); /* F */ outgoing_queue_init(agent->sa_out.completed, agent->sa_t4); /* K */ outgoing_queue_init(agent->sa_out.terminated, 0); /* Special queues (states) for outgoing INVITE transactions */ outgoing_queue_init(agent->sa_out.inv_calling, agent->sa_t1x64); /* B */ outgoing_queue_init(agent->sa_out.inv_proceeding, timer_c); /* C */ outgoing_queue_init(agent->sa_out.inv_completed, timer_d); /* D */ if (leg_htable_resize(agent->sa_home, agent->sa_dialogs, 0) < 0 || leg_htable_resize(agent->sa_home, agent->sa_defaults, 0) < 0 || outgoing_htable_resize(agent->sa_home, agent->sa_outgoing, 0) < 0 || incoming_htable_resize(agent->sa_home, agent->sa_incoming, 0) < 0) { SU_DEBUG_0(("nta_agent_create: failure with %s\n", "hash tables")); goto deinit; } SU_DEBUG_9(("nta_agent_create: initialized %s\n", "hash tables")); if (contact_url != (url_string_t *)-1 && nta_agent_add_tport(agent, contact_url, ta_tags(ta)) < 0) { SU_DEBUG_7(("nta_agent_create: failure with %s\n", "transport")); goto deinit; } SU_DEBUG_9(("nta_agent_create: initialized %s\n", "transports")); if (agent_tag_init(agent) < 0) { SU_DEBUG_3(("nta_agent_create: failure with %s\n", "random identifiers")); goto deinit; } SU_DEBUG_9(("nta_agent_create: initialized %s\n", "random identifiers")); if (agent_timer_init(agent) < 0) { SU_DEBUG_0(("nta_agent_create: failure with %s\n", "timer")); goto deinit; } SU_DEBUG_9(("nta_agent_create: initialized %s\n", "timer")); if (agent_launch_terminator(agent) == 0) SU_DEBUG_9(("nta_agent_create: initialized %s\n", "threads")); #if HAVE_SOFIA_SRESOLV agent->sa_resolver = sres_resolver_create(root, NULL, ta_tags(ta)); if (!agent->sa_resolver) { SU_DEBUG_0(("nta_agent_create: failure with %s\n", "resolver")); } SU_DEBUG_9(("nta_agent_create: initialized %s\n", "resolver")); #endif ta_end(ta); return agent; deinit: nta_agent_destroy(agent); } ta_end(ta); return NULL; } /** * Destroy an NTA agent object. * * @param agent the NTA agent object to be destroyed. * */ void nta_agent_destroy(nta_agent_t *agent) { if (agent) { size_t i; outgoing_htable_t *oht = agent->sa_outgoing; incoming_htable_t *iht = agent->sa_incoming; /* Currently, this is pretty pointless, as legs don't keep any resources */ leg_htable_t *lht; nta_leg_t *leg; for (i = 0, lht = agent->sa_dialogs; i < lht->lht_size; i++) { if ((leg = lht->lht_table[i])) { SU_DEBUG_3(("nta_agent_destroy: destroying dialog with <" URL_PRINT_FORMAT ">\n", URL_PRINT_ARGS(leg->leg_remote->a_url))); leg_free(agent, leg); } } for (i = 0, lht = agent->sa_defaults; i < lht->lht_size; i++) { if ((leg = lht->lht_table[i])) { SU_DEBUG_3(("%s: destroying leg for <" URL_PRINT_FORMAT ">\n", __func__, URL_PRINT_ARGS(leg->leg_url))); leg_free(agent, leg); } } if (agent->sa_default_leg) leg_free(agent, agent->sa_default_leg); for (i = iht->iht_size; i-- > 0; ) while (iht->iht_table[i]) { nta_incoming_t *irq = iht->iht_table[i]; if (!irq->irq_destroyed) SU_DEBUG_3(("%s: destroying %s server transaction from <" URL_PRINT_FORMAT ">\n", __func__, irq->irq_rq->rq_method_name, URL_PRINT_ARGS(irq->irq_from->a_url))); incoming_free(irq); } for (i = oht->oht_size; i-- > 0;) while (oht->oht_table[i]) { nta_outgoing_t *orq = oht->oht_table[i]; if (!orq->orq_destroyed) SU_DEBUG_3(("%s: destroying %s%s client transaction to <" URL_PRINT_FORMAT ">\n", __func__, (orq->orq_forking || orq->orq_forks) ? "forked " : "forking", orq->orq_method_name, URL_PRINT_ARGS(orq->orq_to->a_url))); orq->orq_forks = NULL, orq->orq_forking = NULL; outgoing_free(orq); } su_timer_destroy(agent->sa_timer), agent->sa_timer = NULL; # if HAVE_SOFIA_SRESOLV sres_resolver_destroy(agent->sa_resolver), agent->sa_resolver = NULL; # endif tport_destroy(agent->sa_tports), agent->sa_tports = NULL; agent_kill_terminator(agent); su_home_unref(agent->sa_home); } } /** Return agent context. */ nta_agent_magic_t *nta_agent_magic(nta_agent_t const *agent) { return agent ? agent->sa_magic : NULL; } /** Return @Contact header. * * Get a @Contact header, which can be used to reach @a agent. * * @param agent NTA agent object * * User agents can insert the @Contact header in the outgoing REGISTER, * INVITE, and ACK requests and replies to incoming INVITE and OPTIONS * transactions. * * Proxies can use the @Contact header to create appropriate @RecordRoute * headers: * @code * r_r = sip_record_route_create(msg_home(msg), * sip->sip_request->rq_url, * contact->m_url); * @endcode * * @return A sip_contact_t object corresponding to the @a agent. */ sip_contact_t *nta_agent_contact(nta_agent_t const *agent) { return agent ? agent->sa_contact : NULL; } /** Return a list of @Via headers. * * Get @Via headers for all activated transport. * * @param agent NTA agent object * * @return A list of #sip_via_t objects used by the @a agent. */ sip_via_t *nta_agent_via(nta_agent_t const *agent) { return agent ? agent->sa_vias : NULL; } /** Return a list of public (UPnP, STUN) @Via headers. * * Get public @Via headers for all activated transports. * * @param agent NTA agent object * * @return A list of #sip_via_t objects used by the @a agent. */ sip_via_t *nta_agent_public_via(nta_agent_t const *agent) { return agent ? agent->sa_public_vias : NULL; } /** Match a @Via header @a v with @Via headers in @a agent. * */ static sip_via_t *agent_has_via(nta_agent_t const *agent, sip_via_t const *via) { sip_via_t const *v; for (v = agent->sa_public_vias; v; v = v->v_next) { if (!su_casematch(via->v_host, v->v_host)) continue; if (!su_strmatch(via->v_port, v->v_port)) continue; if (!su_casematch(via->v_protocol, v->v_protocol)) continue; return (sip_via_t *)v; } for (v = agent->sa_vias; v; v = v->v_next) { if (!su_casematch(via->v_host, v->v_host)) continue; if (!su_strmatch(via->v_port, v->v_port)) continue; if (!su_casematch(via->v_protocol, v->v_protocol)) continue; return (sip_via_t *)v; } return NULL; } /** Return @UserAgent header. * * Get @UserAgent information with NTA version. * * @param agent NTA agent object (may be NULL) * * @return A string containing the @a agent version. */ char const *nta_agent_version(nta_agent_t const *agent) { return "nta" "/" VERSION; } /** Initialize default tag */ static int agent_tag_init(nta_agent_t *self) { sip_contact_t *m = self->sa_contact; uint32_t hash = su_random(); if (m) { if (m->m_url->url_user) hash = 914715421U * hash + msg_hash_string(m->m_url->url_user); if (m->m_url->url_host) hash = 914715421U * hash + msg_hash_string(m->m_url->url_host); if (m->m_url->url_port) hash = 914715421U * hash + msg_hash_string(m->m_url->url_port); if (m->m_url->url_params) hash = 914715421U * hash + msg_hash_string(m->m_url->url_params); } if (hash == 0) hash = 914715421U; self->sa_branch = NTA_BRANCH_PRIME * (uint64_t)su_nanotime(NULL); self->sa_branch *= hash; self->sa_tags = NTA_TAG_PRIME * self->sa_branch; return 0; } static uint32_t agent_seq(nta_agent_t *agent) { return ++agent->sa_cseq; } /** Initialize agent timer. */ static int agent_timer_init(nta_agent_t *agent) { agent->sa_timer = su_timer_create(su_root_task(agent->sa_root), NTA_SIP_T1 / 8); #if 0 return su_timer_set(agent->sa_timer, agent_timer, agent); #endif return -(agent->sa_timer == NULL); } /** * Agent timer routine. */ static void agent_timer(su_root_magic_t *rm, su_timer_t *timer, nta_agent_t *agent) { su_time_t stamp = su_now(); uint32_t now = su_time_ms(stamp), next, latest; now += now == 0; agent->sa_next = 0; agent->sa_now = stamp; agent->sa_millisec = now; agent->sa_in_timer = 1; _nta_outgoing_timer(agent); _nta_incoming_timer(agent); /* agent->sa_now is used only if sa_millisec != 0 */ agent->sa_millisec = 0; agent->sa_in_timer = 0; /* Calculate next timeout */ next = latest = now + NTA_TIME_MAX + 1; #define NEXT_TIMEOUT(next, p, f, now) \ (void)(p && (int32_t)(p->f - (next)) < 0 && \ ((next) = ((int32_t)(p->f - (now)) > 0 ? p->f : (now)))) NEXT_TIMEOUT(next, agent->sa_out.re_list, orq_retry, now); NEXT_TIMEOUT(next, agent->sa_out.inv_completed->q_head, orq_timeout, now); NEXT_TIMEOUT(next, agent->sa_out.completed->q_head, orq_timeout, now); NEXT_TIMEOUT(next, agent->sa_out.inv_calling->q_head, orq_timeout, now); if (agent->sa_out.inv_proceeding->q_timeout) NEXT_TIMEOUT(next, agent->sa_out.inv_proceeding->q_head, orq_timeout, now); NEXT_TIMEOUT(next, agent->sa_out.trying->q_head, orq_timeout, now); NEXT_TIMEOUT(next, agent->sa_in.preliminary->q_head, irq_timeout, now); NEXT_TIMEOUT(next, agent->sa_in.inv_completed->q_head, irq_timeout, now); NEXT_TIMEOUT(next, agent->sa_in.inv_confirmed->q_head, irq_timeout, now); NEXT_TIMEOUT(next, agent->sa_in.completed->q_head, irq_timeout, now); NEXT_TIMEOUT(next, agent->sa_in.re_list, irq_retry, now); if (agent->sa_next) NEXT_TIMEOUT(next, agent, sa_next, now); #undef NEXT_TIMEOUT if (next == latest) { /* Do not set timer? */ SU_DEBUG_9(("nta: timer not set\n")); assert(!agent->sa_out.completed->q_head); assert(!agent->sa_out.trying->q_head); assert(!agent->sa_out.inv_calling->q_head); assert(!agent->sa_out.re_list); assert(!agent->sa_in.inv_confirmed->q_head); assert(!agent->sa_in.preliminary->q_head); assert(!agent->sa_in.completed->q_head); assert(!agent->sa_in.inv_completed->q_head); assert(!agent->sa_in.re_list); return; } if (next == now) if (++next == 0) ++next; SU_DEBUG_9(("nta: timer %s to %ld ms\n", "set next", (long)(next - now))); agent->sa_next = next; su_timer_set_at(timer, agent_timer, agent, su_time_add(stamp, next - now)); } /** Add uin32_t milliseconds to the time. */ static su_time_t add_milliseconds(su_time_t t0, uint32_t ms) { unsigned long sec = ms / 1000, usec = (ms % 1000) * 1000; t0.tv_usec += usec; t0.tv_sec += sec; if (t0.tv_usec >= 1000000) { t0.tv_sec += 1; t0.tv_usec -= 1000000; } return t0; } /** Calculate nonzero value for timeout. * * Sets or adjusts agent timer when needed. * * @retval 0 if offset is 0 * @retval timeout (millisecond counter) otherwise */ static uint32_t set_timeout(nta_agent_t *agent, uint32_t offset) { su_time_t now; uint32_t next, ms; if (offset == 0) return 0; if (agent->sa_millisec) /* Avoid expensive call to su_now() */ now = agent->sa_now, ms = agent->sa_millisec; else now = su_now(), ms = su_time_ms(now); next = ms + offset; if (next == 0) next = 1; if (agent->sa_in_timer) /* Currently executing timer */ return next; if (agent->sa_next == 0 || (int32_t)(agent->sa_next - next - 5L) > 0) { /* Set timer */ if (agent->sa_next) SU_DEBUG_9(("nta: timer %s to %ld ms\n", "shortened", (long)offset)); else SU_DEBUG_9(("nta: timer %s to %ld ms\n", "set", (long)offset)); su_timer_set_at(agent->sa_timer, agent_timer, agent, add_milliseconds(now, offset)); agent->sa_next = next; } return next; } /** Return current timeval. */ static su_time_t agent_now(nta_agent_t const *agent) { if (agent && agent->sa_millisec != 0) return agent->sa_now; else return su_now(); } /** Launch transaction terminator task */ static int agent_launch_terminator(nta_agent_t *agent) { #ifdef TPTAG_THRPSIZE if (agent->sa_tport_threadpool) { su_home_threadsafe(agent->sa_home); return su_clone_start(agent->sa_root, agent->sa_terminator, NULL, NULL, NULL); } #endif return -1; } /** Kill transaction terminator task */ static void agent_kill_terminator(nta_agent_t *agent) { su_clone_wait(agent->sa_root, agent->sa_terminator); } /**Set NTA Parameters. * * The nta_agent_set_params() function sets the stack parameters. The * parameters determine the way NTA handles the retransmissions, how long * NTA keeps transactions alive, does NTA apply proxy or user-agent logic to * INVITE transactions, or how the @Via headers are generated. * * @note * Setting the parameters NTATAG_MAXSIZE(), NTATAG_UDP_MTU(), NTATAG_MAX_PROCEEDING(), * NTATAG_SIP_T1X64(), NTATAG_SIP_T1(), NTATAG_SIP_T2(), NTATAG_SIP_T4() to * 0 selects the default value. * * @TAGS * NTATAG_ALIASES(), * NTATAG_BAD_REQ_MASK(), NTATAG_BAD_RESP_MASK(), NTATAG_BLACKLIST(), * NTATAG_CANCEL_2543(), NTATAG_CANCEL_487(), NTATAG_CLIENT_RPORT(), * NTATAG_DEBUG_DROP_PROB(), NTATAG_DEFAULT_PROXY(), * NTATAG_EXTRA_100(), NTATAG_GRAYLIST(), * NTATAG_MAXSIZE(), NTATAG_MAX_FORWARDS(), NTATAG_MERGE_482(), NTATAG_MCLASS() * NTATAG_PASS_100(), NTATAG_PASS_408(), NTATAG_PRELOAD(), NTATAG_PROGRESS(), * NTATAG_REL100(), * NTATAG_SERVER_RPORT(), * NTATAG_SIPFLAGS(), * NTATAG_SIP_T1X64(), NTATAG_SIP_T1(), NTATAG_SIP_T2(), NTATAG_SIP_T4(), * NTATAG_STATELESS(), * NTATAG_TAG_3261(), NTATAG_TCP_RPORT(), NTATAG_TIMEOUT_408(), * NTATAG_TLS_RPORT(), * NTATAG_TIMER_C(), NTATAG_MAX_PROCEEDING(), * NTATAG_UA(), NTATAG_UDP_MTU(), NTATAG_USER_VIA(), * NTATAG_USE_NAPTR(), NTATAG_USE_SRV() and NTATAG_USE_TIMESTAMP(). * * @note The value from following tags are stored, but they currently do nothing: * NTATAG_SIGCOMP_ALGORITHM(), NTATAG_SIGCOMP_OPTIONS(), NTATAG_SMIME() */ int nta_agent_set_params(nta_agent_t *agent, tag_type_t tag, tag_value_t value, ...) { int retval; if (agent) { ta_list ta; ta_start(ta, tag, value); retval = agent_set_params(agent, ta_args(ta)); ta_end(ta); } else { su_seterrno(EINVAL); retval = -1; } return retval; } /** Internal function for setting tags */ static int agent_set_params(nta_agent_t *agent, tagi_t *tags) { int n, nC, m; unsigned bad_req_mask = agent->sa_bad_req_mask; unsigned bad_resp_mask = agent->sa_bad_resp_mask; usize_t maxsize = agent->sa_maxsize; usize_t max_proceeding = agent->sa_max_proceeding; unsigned max_forwards = agent->sa_max_forwards->mf_count; unsigned udp_mtu = agent->sa_udp_mtu; unsigned sip_t1 = agent->sa_t1; unsigned sip_t2 = agent->sa_t2; unsigned sip_t4 = agent->sa_t4; unsigned sip_t1x64 = agent->sa_t1x64; unsigned timer_c = agent->sa_timer_c; unsigned timer_d = 32000; unsigned graylist = agent->sa_graylist; unsigned blacklist = agent->sa_blacklist; int ua = agent->sa_is_a_uas; unsigned progress = agent->sa_progress; int stateless = agent->sa_is_stateless; unsigned drop_prob = agent->sa_drop_prob; int user_via = agent->sa_user_via; int extra_100 = agent->sa_extra_100; int pass_100 = agent->sa_pass_100; int timeout_408 = agent->sa_timeout_408; int pass_408 = agent->sa_pass_408; int merge_482 = agent->sa_merge_482; int cancel_2543 = agent->sa_cancel_2543; int cancel_487 = agent->sa_cancel_487; int invite_100rel = agent->sa_invite_100rel; int use_timestamp = agent->sa_timestamp; int use_naptr = agent->sa_use_naptr; int use_srv = agent->sa_use_srv; void *smime = agent->sa_smime; uint32_t flags = agent->sa_flags; int rport = agent->sa_rport; int server_rport = agent->sa_server_rport; int tcp_rport = agent->sa_tcp_rport; int tls_rport = agent->sa_tls_rport; unsigned preload = agent->sa_preload; unsigned threadpool = agent->sa_tport_threadpool; char const *sigcomp = agent->sa_sigcomp_options; char const *algorithm = NONE; msg_mclass_t const *mclass = NONE; sip_contact_t const *aliases = NONE; url_string_t const *proxy = NONE; tport_t *tport; su_home_t *home = agent->sa_home; n = tl_gets(tags, NTATAG_ALIASES_REF(aliases), NTATAG_BAD_REQ_MASK_REF(bad_req_mask), NTATAG_BAD_RESP_MASK_REF(bad_resp_mask), NTATAG_BLACKLIST_REF(blacklist), NTATAG_CANCEL_2543_REF(cancel_2543), NTATAG_CANCEL_487_REF(cancel_487), NTATAG_DEBUG_DROP_PROB_REF(drop_prob), NTATAG_DEFAULT_PROXY_REF(proxy), NTATAG_EXTRA_100_REF(extra_100), NTATAG_GRAYLIST_REF(graylist), NTATAG_MAXSIZE_REF(maxsize), NTATAG_MAX_PROCEEDING_REF(max_proceeding), NTATAG_MAX_FORWARDS_REF(max_forwards), NTATAG_MCLASS_REF(mclass), NTATAG_MERGE_482_REF(merge_482), NTATAG_PASS_100_REF(pass_100), NTATAG_PASS_408_REF(pass_408), NTATAG_PRELOAD_REF(preload), NTATAG_PROGRESS_REF(progress), NTATAG_REL100_REF(invite_100rel), NTATAG_RPORT_REF(rport), NTATAG_SERVER_RPORT_REF(server_rport), NTATAG_SIGCOMP_ALGORITHM_REF(algorithm), NTATAG_SIGCOMP_OPTIONS_REF(sigcomp), NTATAG_SIPFLAGS_REF(flags), NTATAG_SIP_T1X64_REF(sip_t1x64), NTATAG_SIP_T1_REF(sip_t1), NTATAG_SIP_T2_REF(sip_t2), NTATAG_SIP_T4_REF(sip_t4), #if HAVE_SOFIA_SMIME NTATAG_SMIME_REF(smime), #endif NTATAG_STATELESS_REF(stateless), NTATAG_TCP_RPORT_REF(tcp_rport), NTATAG_TLS_RPORT_REF(tls_rport), NTATAG_TIMEOUT_408_REF(timeout_408), NTATAG_UA_REF(ua), NTATAG_UDP_MTU_REF(udp_mtu), NTATAG_USER_VIA_REF(user_via), NTATAG_USE_NAPTR_REF(use_naptr), NTATAG_USE_SRV_REF(use_srv), NTATAG_USE_TIMESTAMP_REF(use_timestamp), #ifdef TPTAG_THRPSIZE /* If threadpool is enabled, start a separate "reaper thread" */ TPTAG_THRPSIZE_REF(threadpool), #endif TAG_END()); nC = tl_gets(tags, NTATAG_TIMER_C_REF(timer_c), TAG_END()); n += nC; if (mclass != NONE) agent->sa_mclass = mclass ? mclass : sip_default_mclass(); m = 0; for (tport = agent->sa_tports; tport; tport = tport_next(tport)) { int m0 = tport_set_params(tport, TAG_NEXT(tags)); if (m0 < 0) return m0; if (m0 > m) m = m0; } n += m; if (aliases != NONE) { sip_contact_t const *m, *m_next; m = agent->sa_aliases; agent->sa_aliases = sip_contact_dup(home, aliases); for (; m; m = m_next) { /* Free old aliases */ m_next = m->m_next; su_free(home, (void *)m); } } if (proxy != NONE) { url_t *dp = url_hdup(home, proxy->us_url); url_sanitize(dp); if (dp == NULL || dp->url_type == url_sip || dp->url_type == url_sips) { if (agent->sa_default_proxy) su_free(home, agent->sa_default_proxy); agent->sa_default_proxy = dp; } else n = -1; } if (algorithm != NONE) agent->sa_algorithm = su_strdup(home, algorithm); if (!su_strmatch(sigcomp, agent->sa_sigcomp_options)) { msg_param_t const *l = NULL; char *s = su_strdup(home, sigcomp); char *s1 = su_strdup(home, s), *s2 = s1; if (s && s2 && msg_avlist_d(home, &s2, &l) == 0 && *s2 == '\0') { su_free(home, (void *)agent->sa_sigcomp_options); su_free(home, (void *)agent->sa_sigcomp_option_list); agent->sa_sigcomp_options = s; agent->sa_sigcomp_option_free = s1; agent->sa_sigcomp_option_list = l; } else { su_free(home, s); su_free(home, s1); su_free(home, (void *)l); n = -1; } } if (maxsize == 0) maxsize = 2 * 1024 * 1024; if (maxsize > UINT32_MAX) maxsize = UINT32_MAX; agent->sa_maxsize = maxsize; if (max_proceeding == 0) max_proceeding = USIZE_MAX; agent->sa_max_proceeding = max_proceeding; if (max_forwards == 0) max_forwards = 70; /* Default value */ agent->sa_max_forwards->mf_count = max_forwards; if (udp_mtu == 0) udp_mtu = 1300; if (udp_mtu > 65535) udp_mtu = 65535; if (agent->sa_udp_mtu != udp_mtu) { agent->sa_udp_mtu = udp_mtu; agent_set_udp_params(agent, udp_mtu); } if (sip_t1 == 0) sip_t1 = NTA_SIP_T1; if (sip_t1 > NTA_TIME_MAX) sip_t1 = NTA_TIME_MAX; agent->sa_t1 = sip_t1; if (sip_t2 == 0) sip_t2 = NTA_SIP_T2; if (sip_t2 > NTA_TIME_MAX) sip_t2 = NTA_TIME_MAX; agent->sa_t2 = sip_t2; if (sip_t4 == 0) sip_t4 = NTA_SIP_T4; if (sip_t4 > NTA_TIME_MAX) sip_t4 = NTA_TIME_MAX; if (agent->sa_t4 != sip_t4) { incoming_queue_adjust(agent, agent->sa_in.inv_confirmed, sip_t4); outgoing_queue_adjust(agent, agent->sa_out.completed, sip_t4); } agent->sa_t4 = sip_t4; if (sip_t1x64 == 0) sip_t1x64 = NTA_SIP_T1 * 64; if (sip_t1x64 > NTA_TIME_MAX) sip_t1x64 = NTA_TIME_MAX; if (agent->sa_t1x64 != sip_t1x64) { incoming_queue_adjust(agent, agent->sa_in.preliminary, sip_t1x64); incoming_queue_adjust(agent, agent->sa_in.completed, sip_t1x64); incoming_queue_adjust(agent, agent->sa_in.inv_completed, sip_t1x64); outgoing_queue_adjust(agent, agent->sa_out.trying, sip_t1x64); outgoing_queue_adjust(agent, agent->sa_out.inv_calling, sip_t1x64); } agent->sa_t1x64 = sip_t1x64; if (nC == 1) { agent->sa_use_timer_c = 1; if (timer_c == 0) timer_c = 185 * 1000; agent->sa_timer_c = timer_c; outgoing_queue_adjust(agent, agent->sa_out.inv_proceeding, timer_c); } if (timer_d < sip_t1x64) timer_d = sip_t1x64; outgoing_queue_adjust(agent, agent->sa_out.inv_completed, timer_d); if (graylist > 24 * 60 * 60) graylist = 24 * 60 * 60; agent->sa_graylist = graylist; if (blacklist > 24 * 60 * 60) blacklist = 24 * 60 * 60; agent->sa_blacklist = blacklist; if (progress == 0) progress = 60 * 1000; agent->sa_progress = progress; if (server_rport > 3) server_rport = 1; else if (server_rport < 0) server_rport = 1; agent->sa_server_rport = server_rport; agent->sa_bad_req_mask = bad_req_mask; agent->sa_bad_resp_mask = bad_resp_mask; agent->sa_is_a_uas = ua != 0; agent->sa_is_stateless = stateless != 0; agent->sa_drop_prob = drop_prob < 1000 ? drop_prob : 1000; agent->sa_user_via = user_via != 0; agent->sa_extra_100 = extra_100 != 0; agent->sa_pass_100 = pass_100 != 0; agent->sa_timeout_408 = timeout_408 != 0; agent->sa_pass_408 = pass_408 != 0; agent->sa_merge_482 = merge_482 != 0; agent->sa_cancel_2543 = cancel_2543 != 0; agent->sa_cancel_487 = cancel_487 != 0; agent->sa_invite_100rel = invite_100rel != 0; agent->sa_timestamp = use_timestamp != 0; agent->sa_use_naptr = use_naptr != 0; agent->sa_use_srv = use_srv != 0; agent->sa_smime = smime; agent->sa_flags = flags & MSG_FLG_USERMASK; agent->sa_rport = rport != 0; agent->sa_tcp_rport = tcp_rport != 0; agent->sa_tls_rport = tls_rport != 0; agent->sa_preload = preload; agent->sa_tport_threadpool = threadpool; return n; } static void agent_set_udp_params(nta_agent_t *self, usize_t udp_mtu) { tport_t *tp; /* Set via fields for the tports */ for (tp = tport_primaries(self->sa_tports); tp; tp = tport_next(tp)) { if (tport_is_udp(tp)) tport_set_params(tp, TPTAG_TIMEOUT(2 * self->sa_t1x64), TPTAG_MTU(udp_mtu), TAG_END()); } } /**Get NTA Parameters. * * The nta_agent_get_params() function retrieves the stack parameters. The * parameters determine the way NTA handles the retransmissions, how long * NTA keeps transactions alive, does NTA apply proxy or user-agent logic to * INVITE transactions, or how the @Via headers are generated. * * @TAGS * NTATAG_ALIASES_REF(), NTATAG_BLACKLIST_REF(), * NTATAG_CANCEL_2543_REF(), NTATAG_CANCEL_487_REF(), * NTATAG_CLIENT_RPORT_REF(), NTATAG_CONTACT_REF(), * NTATAG_DEBUG_DROP_PROB_REF(), NTATAG_DEFAULT_PROXY_REF(), * NTATAG_EXTRA_100_REF(), NTATAG_GRAYLIST_REF(), * NTATAG_MAXSIZE_REF(), NTATAG_MAX_FORWARDS_REF(), NTATAG_MCLASS_REF(), * NTATAG_MERGE_482_REF(), NTATAG_MAX_PROCEEDING_REF(), * NTATAG_PASS_100_REF(), NTATAG_PASS_408_REF(), NTATAG_PRELOAD_REF(), * NTATAG_PROGRESS_REF(), * NTATAG_REL100_REF(), * NTATAG_SERVER_RPORT_REF(), * NTATAG_SIGCOMP_ALGORITHM_REF(), NTATAG_SIGCOMP_OPTIONS_REF(), * NTATAG_SIPFLAGS_REF(), * NTATAG_SIP_T1_REF(), NTATAG_SIP_T1X64_REF(), NTATAG_SIP_T2_REF(), * NTATAG_SIP_T4_REF(), NTATAG_SMIME_REF(), NTATAG_STATELESS_REF(), * NTATAG_TAG_3261_REF(), NTATAG_TIMEOUT_408_REF(), NTATAG_TIMER_C_REF(), * NTATAG_UA_REF(), NTATAG_UDP_MTU_REF(), NTATAG_USER_VIA_REF(), * NTATAG_USE_NAPTR_REF(), NTATAG_USE_SRV_REF(), * and NTATAG_USE_TIMESTAMP_REF(). * */ int nta_agent_get_params(nta_agent_t *agent, tag_type_t tag, tag_value_t value, ...) { int n; ta_list ta; if (agent) { ta_start(ta, tag, value); n = agent_get_params(agent, ta_args(ta)); ta_end(ta); return n; } su_seterrno(EINVAL); return -1; } /** Get NTA parameters */ static int agent_get_params(nta_agent_t *agent, tagi_t *tags) { return tl_tgets(tags, NTATAG_ALIASES(agent->sa_aliases), NTATAG_BLACKLIST(agent->sa_blacklist), NTATAG_CANCEL_2543(agent->sa_cancel_2543), NTATAG_CANCEL_487(agent->sa_cancel_487), NTATAG_CLIENT_RPORT(agent->sa_rport), NTATAG_CONTACT(agent->sa_contact), NTATAG_DEBUG_DROP_PROB(agent->sa_drop_prob), NTATAG_DEFAULT_PROXY(agent->sa_default_proxy), NTATAG_EXTRA_100(agent->sa_extra_100), NTATAG_GRAYLIST(agent->sa_graylist), NTATAG_MAXSIZE(agent->sa_maxsize), NTATAG_MAX_PROCEEDING(agent->sa_max_proceeding), NTATAG_MAX_FORWARDS(agent->sa_max_forwards->mf_count), NTATAG_MCLASS(agent->sa_mclass), NTATAG_MERGE_482(agent->sa_merge_482), NTATAG_PASS_100(agent->sa_pass_100), NTATAG_PASS_408(agent->sa_pass_408), NTATAG_PRELOAD(agent->sa_preload), NTATAG_PROGRESS(agent->sa_progress), NTATAG_REL100(agent->sa_invite_100rel), NTATAG_SERVER_RPORT((int)(agent->sa_server_rport)), NTATAG_SIGCOMP_ALGORITHM(agent->sa_algorithm), NTATAG_SIGCOMP_OPTIONS(agent->sa_sigcomp_options ? agent->sa_sigcomp_options : "sip"), NTATAG_SIPFLAGS(agent->sa_flags), NTATAG_SIP_T1(agent->sa_t1), NTATAG_SIP_T1X64(agent->sa_t1x64), NTATAG_SIP_T2(agent->sa_t2), NTATAG_SIP_T4(agent->sa_t4), #if HAVE_SOFIA_SMIME NTATAG_SMIME(agent->sa_smime), #else NTATAG_SMIME(NULL), #endif NTATAG_STATELESS(agent->sa_is_stateless), NTATAG_TAG_3261(1), NTATAG_TIMEOUT_408(agent->sa_timeout_408), NTATAG_TIMER_C(agent->sa_timer_c), NTATAG_UA(agent->sa_is_a_uas), NTATAG_UDP_MTU(agent->sa_udp_mtu), NTATAG_USER_VIA(agent->sa_user_via), NTATAG_USE_NAPTR(agent->sa_use_naptr), NTATAG_USE_SRV(agent->sa_use_srv), NTATAG_USE_TIMESTAMP(agent->sa_timestamp), TAG_END()); } /**Get NTA statistics. * * The nta_agent_get_stats() function retrieves the stack statistics. * * @TAGS * NTATAG_S_ACKED_TR_REF(), * NTATAG_S_BAD_MESSAGE_REF(), * NTATAG_S_BAD_REQUEST_REF(), * NTATAG_S_BAD_RESPONSE_REF(), * NTATAG_S_CANCELED_TR_REF(), * NTATAG_S_CLIENT_TR_REF(), * NTATAG_S_DIALOG_TR_REF(), * NTATAG_S_DROP_REQUEST_REF(), * NTATAG_S_DROP_RESPONSE_REF(), * NTATAG_S_IRQ_HASH_REF(), * NTATAG_S_IRQ_HASH_USED_REF(), * NTATAG_S_LEG_HASH_REF(), * NTATAG_S_LEG_HASH_USED_REF(), * NTATAG_S_MERGED_REQUEST_REF(), * NTATAG_S_ORQ_HASH_REF(), * NTATAG_S_ORQ_HASH_USED_REF(), * NTATAG_S_RECV_MSG_REF(), * NTATAG_S_RECV_REQUEST_REF(), * NTATAG_S_RECV_RESPONSE_REF(), * NTATAG_S_RECV_RETRY_REF(), * NTATAG_S_RETRY_REQUEST_REF(), * NTATAG_S_RETRY_RESPONSE_REF(), * NTATAG_S_SENT_MSG_REF(), * NTATAG_S_SENT_REQUEST_REF(), * NTATAG_S_SENT_RESPONSE_REF(), * NTATAG_S_SERVER_TR_REF(), * NTATAG_S_TOUT_REQUEST_REF(), * NTATAG_S_TOUT_RESPONSE_REF(), * NTATAG_S_TRLESS_200_REF(), * NTATAG_S_TRLESS_REQUEST_REF(), * NTATAG_S_TRLESS_RESPONSE_REF(), and * NTATAG_S_TRLESS_TO_TR_REF(), */ int nta_agent_get_stats(nta_agent_t *agent, tag_type_t tag, tag_value_t value, ...) { int n; ta_list ta; if (!agent) return su_seterrno(EINVAL); ta_start(ta, tag, value); n = tl_tgets(ta_args(ta), NTATAG_S_IRQ_HASH(agent->sa_incoming->iht_size), NTATAG_S_ORQ_HASH(agent->sa_outgoing->oht_size), NTATAG_S_LEG_HASH(agent->sa_dialogs->lht_size), NTATAG_S_IRQ_HASH_USED(agent->sa_incoming->iht_used), NTATAG_S_ORQ_HASH_USED(agent->sa_outgoing->oht_used), NTATAG_S_LEG_HASH_USED(agent->sa_dialogs->lht_used), NTATAG_S_RECV_MSG(agent->sa_stats->as_recv_msg), NTATAG_S_RECV_REQUEST(agent->sa_stats->as_recv_request), NTATAG_S_RECV_RESPONSE(agent->sa_stats->as_recv_response), NTATAG_S_BAD_MESSAGE(agent->sa_stats->as_bad_message), NTATAG_S_BAD_REQUEST(agent->sa_stats->as_bad_request), NTATAG_S_BAD_RESPONSE(agent->sa_stats->as_bad_response), NTATAG_S_DROP_REQUEST(agent->sa_stats->as_drop_request), NTATAG_S_DROP_RESPONSE(agent->sa_stats->as_drop_response), NTATAG_S_CLIENT_TR(agent->sa_stats->as_client_tr), NTATAG_S_SERVER_TR(agent->sa_stats->as_server_tr), NTATAG_S_DIALOG_TR(agent->sa_stats->as_dialog_tr), NTATAG_S_ACKED_TR(agent->sa_stats->as_acked_tr), NTATAG_S_CANCELED_TR(agent->sa_stats->as_canceled_tr), NTATAG_S_TRLESS_REQUEST(agent->sa_stats->as_trless_request), NTATAG_S_TRLESS_TO_TR(agent->sa_stats->as_trless_to_tr), NTATAG_S_TRLESS_RESPONSE(agent->sa_stats->as_trless_response), NTATAG_S_TRLESS_200(agent->sa_stats->as_trless_200), NTATAG_S_MERGED_REQUEST(agent->sa_stats->as_merged_request), NTATAG_S_SENT_MSG(agent->sa_stats->as_sent_msg), NTATAG_S_SENT_REQUEST(agent->sa_stats->as_sent_request), NTATAG_S_SENT_RESPONSE(agent->sa_stats->as_sent_response), NTATAG_S_RETRY_REQUEST(agent->sa_stats->as_retry_request), NTATAG_S_RETRY_RESPONSE(agent->sa_stats->as_retry_response), NTATAG_S_RECV_RETRY(agent->sa_stats->as_recv_retry), NTATAG_S_TOUT_REQUEST(agent->sa_stats->as_tout_request), NTATAG_S_TOUT_RESPONSE(agent->sa_stats->as_tout_response), TAG_END()); ta_end(ta); return n; } /**Calculate a new unique tag. * * This function generates a series of 2**64 unique tags for @From or @To * headers. The start of the tag series is derived from the NTP time the NTA * agent was initialized. * */ char const *nta_agent_newtag(su_home_t *home, char const *fmt, nta_agent_t *sa) { char tag[(8 * 8 + 4)/ 5 + 1]; if (sa == NULL) return su_seterrno(EINVAL), NULL; /* XXX - use a cryptographically safe func here? */ sa->sa_tags += NTA_TAG_PRIME; msg_random_token(tag, sizeof(tag) - 1, &sa->sa_tags, sizeof(sa->sa_tags)); if (fmt && fmt[0]) return su_sprintf(home, fmt, tag); else return su_strdup(home, tag); } /** * Calculate branch value. */ static char const *stateful_branch(su_home_t *home, nta_agent_t *sa) { char branch[(8 * 8 + 4)/ 5 + 1]; /* XXX - use a cryptographically safe func here? */ sa->sa_branch += NTA_BRANCH_PRIME; msg_random_token(branch, sizeof(branch) - 1, &sa->sa_branch, sizeof(sa->sa_branch)); return su_sprintf(home, "branch=z9hG4bK%s", branch); } #include /** * Calculate branch value for stateless operation. * * XXX - should include HMAC of previous @Via line. */ static char const *stateless_branch(nta_agent_t *sa, msg_t *msg, sip_t const *sip, tp_name_t const *tpn) { su_md5_t md5[1]; uint8_t digest[SU_MD5_DIGEST_SIZE]; char branch[(SU_MD5_DIGEST_SIZE * 8 + 4)/ 5 + 1]; sip_route_t const *r; assert(sip->sip_request); if (!sip->sip_via) return stateful_branch(msg_home(msg), sa); su_md5_init(md5); su_md5_str0update(md5, tpn->tpn_host); su_md5_str0update(md5, tpn->tpn_port); url_update(md5, sip->sip_request->rq_url); if (sip->sip_call_id) { su_md5_str0update(md5, sip->sip_call_id->i_id); } if (sip->sip_from) { url_update(md5, sip->sip_from->a_url); su_md5_stri0update(md5, sip->sip_from->a_tag); } if (sip->sip_to) { url_update(md5, sip->sip_to->a_url); /* XXX - some broken implementations include To tag in CANCEL */ /* su_md5_str0update(md5, sip->sip_to->a_tag); */ } if (sip->sip_cseq) { uint32_t cseq = htonl(sip->sip_cseq->cs_seq); su_md5_update(md5, &cseq, sizeof(cseq)); } for (r = sip->sip_route; r; r = r->r_next) url_update(md5, r->r_url); su_md5_digest(md5, digest); msg_random_token(branch, sizeof(branch) - 1, digest, sizeof(digest)); return su_sprintf(msg_home(msg), "branch=z9hG4bK.%s", branch); } /* ====================================================================== */ /* 2) Transport interface */ /* Local prototypes */ static int agent_create_master_transport(nta_agent_t *self, tagi_t *tags); static int agent_init_via(nta_agent_t *self, tport_t *primaries, int use_maddr); static int agent_init_contact(nta_agent_t *self); static void agent_recv_message(nta_agent_t *agent, tport_t *tport, msg_t *msg, sip_via_t *tport_via, su_time_t now); static void agent_tp_error(nta_agent_t *agent, tport_t *tport, int errcode, char const *remote); static void agent_update_tport(nta_agent_t *agent, tport_t *); /**For each transport, we have name used by tport module, SRV prefixes used * for resolving, and NAPTR service/conversion. */ static struct sipdns_tport { char name[6]; /**< Named used by tport module */ char port[6]; /**< Default port number */ char prefix[14]; /**< Prefix for SRV domains */ char service[10]; /**< NAPTR service */ } #define SIPDNS_TRANSPORTS (4) const sipdns_tports[SIPDNS_TRANSPORTS] = { { "udp", "5060", "_sip._udp.", "SIP+D2U" }, { "tcp", "5060", "_sip._tcp.", "SIP+D2T" }, { "sctp", "5060", "_sip._sctp.", "SIP+D2S" }, { "tls", "5061", "_sips._tcp.", "SIPS+D2T" }, }; static char const * const tports_sip[] = { "udp", "tcp", "sctp", NULL }; static char const * const tports_sips[] = { "tls", NULL }; static tport_stack_class_t nta_agent_class[1] = {{ sizeof(nta_agent_class), agent_recv_message, agent_tp_error, nta_msg_create_for_transport, agent_update_tport, }}; /** Add a transport to the agent. * * Creates a new transport and binds it * to the port specified by the @a uri. The @a uri must have sip: or sips: * scheme or be a wildcard uri ("*"). The @a uri syntax allowed is as * follows: * * @code url :[:] @endcode * where may be * @code * ;transport= * ;maddr= * ;comp=sigcomp * @endcode * * The scheme part determines which transports are used. "sip" implies UDP * and TCP, "sips" TLS over TCP. In the future, more transports can be * supported, for instance, "sip" can use SCTP or DCCP, "sips" DTLS or TLS * over SCTP. * * The "host" part determines what address/domain name is used in @Contact. * An "*" in "host" part is shorthand for any local IP address. 0.0.0.0 * means that the only the IPv4 addresses are used. [::] means that only * the IPv6 addresses are used. If a domain name or a specific IP address * is given as "host" part, an additional "maddr" parameter can be used to * control which addresses are used by the stack when binding listen * sockets for incoming requests. * * The "port" determines what port is used in contact, and to which port the * stack binds in order to listen for incoming requests. Empty or missing * port means that default port should be used (5060 for sip, 5061 for * sips). An "*" in "port" part means any port, i.e., the stack binds to an * ephemeral port. * * The "transport" parameter determines the transport protocol that is used * and how they are preferred. If no protocol is specified, both UDP and TCP * are used for SIP URL and TLS for SIPS URL. The preference can be * indicated with a comma-separated list of transports, for instance, * parameter @code transport=tcp,udp @endcode indicates that TCP is * preferred to UDP. * * The "maddr" parameter determines to which address the stack binds in * order to listen for incoming requests. An "*" in "maddr" parameter is * shorthand for any local IP address. 0.0.0.0 means that only IPv4 sockets * are created. [::] means that only IPv6 sockets are created. * * The "comp" parameter determines the supported compression protocol. * Currently only sigcomp is supported (with suitable library). * * @par Examples: * @code sip:172.21.40.24;maddr=* @endcode \n * @code sip:172.21.40.24:50600;transport=TCP,UDP;comp=sigcomp @endcode \n * @code sips:* @endcode * * @return * On success, zero is returned. On error, -1 is returned, and @a errno is * set appropriately. */ int nta_agent_add_tport(nta_agent_t *self, url_string_t const *uri, tag_type_t tag, tag_value_t value, ...) { url_t *url; char tp[32]; char maddr[256]; char comp[32]; tp_name_t tpn[1] = {{ NULL }}; char const * const * tports = tports_sip; int error; ta_list ta; if (self == NULL) { su_seterrno(EINVAL); return -1; } if (uri == NULL) uri = (url_string_t *)"sip:*"; else if (url_string_p(uri) ? strcmp(uri->us_str, "*") == 0 : uri->us_url->url_type == url_any) { uri = (url_string_t *)"sip:*:*"; } if (!(url = url_hdup(self->sa_home, uri->us_url)) || (url->url_type != url_sip && url->url_type != url_sips)) { if (url_string_p(uri)) SU_DEBUG_1(("nta: %s: invalid bind URL\n", uri->us_str)); else SU_DEBUG_1(("nta: invalid bind URL\n")); su_seterrno(EINVAL); return -1; } tpn->tpn_canon = url->url_host; tpn->tpn_host = url->url_host; tpn->tpn_port = url_port(url); if (url->url_type == url_sip) { tpn->tpn_proto = "*"; tports = tports_sip; if (!tpn->tpn_port || !tpn->tpn_port[0]) tpn->tpn_port = SIP_DEFAULT_SERV; } else { assert(url->url_type == url_sips); tpn->tpn_proto = "*"; tports = tports_sips; if (!tpn->tpn_port || !tpn->tpn_port[0]) tpn->tpn_port = SIPS_DEFAULT_SERV; } if (url->url_params) { if (url_param(url->url_params, "transport", tp, sizeof(tp)) > 0) { if (strchr(tp, ',')) { int i; char *t, *tps[9]; /* Split tp into transports */ for (i = 0, t = tp; t && i < 8; i++) { tps[i] = t; if ((t = strchr(t, ','))) *t++ = '\0'; } tps[i] = NULL; tports = (char const * const *)tps; } else { tpn->tpn_proto = tp; } } if (url_param(url->url_params, "maddr", maddr, sizeof(maddr)) > 0) tpn->tpn_host = maddr; if (url_param(url->url_params, "comp", comp, sizeof(comp)) > 0) tpn->tpn_comp = comp; if (tpn->tpn_comp && (nta_compressor_vtable == NULL || !su_casematch(tpn->tpn_comp, nta_compressor_vtable->ncv_name))) { SU_DEBUG_1(("nta(%p): comp=%s not supported for " URL_PRINT_FORMAT "\n", (void *)self, tpn->tpn_comp, URL_PRINT_ARGS(url))); } } ta_start(ta, tag, value); if (self->sa_tports == NULL) { if (agent_create_master_transport(self, ta_args(ta)) < 0) { error = su_errno(); SU_DEBUG_1(("nta: cannot create master transport: %s\n", su_strerror(error))); goto error; } } if (tport_tbind(self->sa_tports, tpn, tports, ta_tags(ta)) < 0) { error = su_errno(); SU_DEBUG_1(("nta: bind(%s:%s;transport=%s%s%s%s%s): %s\n", tpn->tpn_canon, tpn->tpn_port, tpn->tpn_proto, tpn->tpn_canon != tpn->tpn_host ? ";maddr=" : "", tpn->tpn_canon != tpn->tpn_host ? tpn->tpn_host : "", tpn->tpn_comp ? ";comp=" : "", tpn->tpn_comp ? tpn->tpn_comp : "", su_strerror(error))); goto error; } else SU_DEBUG_5(("nta: bound to (%s:%s;transport=%s%s%s%s%s)\n", tpn->tpn_canon, tpn->tpn_port, tpn->tpn_proto, tpn->tpn_canon != tpn->tpn_host ? ";maddr=" : "", tpn->tpn_canon != tpn->tpn_host ? tpn->tpn_host : "", tpn->tpn_comp ? ";comp=" : "", tpn->tpn_comp ? tpn->tpn_comp : "")); /* XXX - when to use maddr? */ if ((agent_init_via(self, tport_primaries(self->sa_tports), 0)) < 0) { error = su_errno(); SU_DEBUG_1(("nta: cannot create Via headers\n")); goto error; } else SU_DEBUG_9(("nta: Via fields initialized\n")); if ((agent_init_contact(self)) < 0) { error = su_errno(); SU_DEBUG_1(("nta: cannot create Contact header\n")); goto error; } else SU_DEBUG_9(("nta: Contact header created\n")); su_free(self->sa_home, url); ta_end(ta); return 0; error: ta_end(ta); su_seterrno(error); return -1; } static int agent_create_master_transport(nta_agent_t *self, tagi_t *tags) { self->sa_tports = tport_tcreate(self, nta_agent_class, self->sa_root, TPTAG_SDWN_ERROR(0), TPTAG_IDLE(1800000), TAG_NEXT(tags)); if (!self->sa_tports) return -1; SU_DEBUG_9(("nta: master transport created\n")); return 0; } /** Initialize @Via headers. */ static int agent_init_via(nta_agent_t *self, tport_t *primaries, int use_maddr) { sip_via_t *via = NULL, *new_via, *dup_via, *v, **vv = &via; sip_via_t *new_vias, **next_new_via, *new_publics, **next_new_public; tport_t *tp; su_addrinfo_t const *ai; su_home_t autohome[SU_HOME_AUTO_SIZE(2048)]; su_home_auto(autohome, sizeof autohome); self->sa_tport_ip4 = 0; self->sa_tport_ip6 = 0; self->sa_tport_udp = 0; self->sa_tport_tcp = 0; self->sa_tport_sctp = 0; self->sa_tport_tls = 0; /* Set via fields for the tports */ for (tp = primaries; tp; tp = tport_next(tp)) { int maddr, first_via; tp_name_t tpn[1]; char const *comp = NULL; *tpn = *tport_name(tp); assert(tpn->tpn_proto); assert(tpn->tpn_canon); assert(tpn->tpn_host); assert(tpn->tpn_port); #if 0 if (getenv("SIP_UDP_CONNECT") && strcmp(tpn->tpn_proto, "udp") == 0) tport_set_params(tp, TPTAG_CONNECT(1), TAG_END()); #endif if (tport_has_ip4(tp)) self->sa_tport_ip4 = 1; #if SU_HAVE_IN6 if (tport_has_ip6(tp)) self->sa_tport_ip6 = 1; #endif if (su_casematch(tpn->tpn_proto, "udp")) self->sa_tport_udp = 1; else if (su_casematch(tpn->tpn_proto, "tcp")) self->sa_tport_tcp = 1; else if (su_casematch(tpn->tpn_proto, "sctp")) self->sa_tport_sctp = 1; if (tport_has_tls(tp)) self->sa_tport_tls = 1; first_via = 1; ai = tport_get_address(tp); for (; ai; ai = ai->ai_next) { char host[TPORT_HOSTPORTSIZE] = ""; char sport[8]; char const *canon = ai->ai_canonname; su_sockaddr_t *su = (void *)ai->ai_addr; int port; if (su) { su_inet_ntop(su->su_family, SU_ADDR(su), host, sizeof host); maddr = use_maddr && !su_casematch(canon, host); port = ntohs(su->su_port); } else { msg_random_token(host, 16, NULL, 0); canon = strcat(host, ".is.invalid"); maddr = 0; port = 0; } if (su_casenmatch(tpn->tpn_proto, "tls", 3) ? port == SIPS_DEFAULT_PORT : port == SIP_DEFAULT_PORT) port = 0; snprintf(sport, sizeof sport, ":%u", port); comp = tpn->tpn_comp; SU_DEBUG_9(("nta: agent_init_via: " "%s/%s %s%s%s%s%s%s (%s)\n", SIP_VERSION_CURRENT, tpn->tpn_proto, canon, port ? sport : "", maddr ? ";maddr=" : "", maddr ? host : "", comp ? ";comp=" : "", comp ? comp : "", tpn->tpn_ident ? tpn->tpn_ident : "*")); v = sip_via_format(autohome, "%s/%s %s%s%s%s%s%s", SIP_VERSION_CURRENT, tpn->tpn_proto, canon, port ? sport : "", maddr ? ";maddr=" : "", maddr ? host : "", comp ? ";comp=" : "", comp ? comp : ""); if (v == NULL) goto error; v->v_comment = tpn->tpn_ident; v->v_common->h_data = tp; /* Nasty trick */ *vv = v; vv = &(*vv)->v_next; } } /* Duplicate the list bind to the transports */ new_via = sip_via_dup(self->sa_home, via); /* Duplicate the complete list shown to the application */ dup_via = sip_via_dup(self->sa_home, via); if (via && (!new_via || !dup_via)) { msg_header_free(self->sa_home, (void *)new_via); msg_header_free(self->sa_home, (void *)dup_via); goto error; } new_vias = NULL, next_new_via = &new_vias; new_publics = NULL, next_new_public = &new_publics; /* Set via field magic for the tports */ for (tp = primaries; tp; tp = tport_next(tp)) { assert(via->v_common->h_data == tp); v = tport_magic(tp); tport_set_magic(tp, new_via); msg_header_free(self->sa_home, (void *)v); if (tport_is_public(tp)) *next_new_public = dup_via; else *next_new_via = dup_via; while (via->v_next && via->v_next->v_common->h_data == tp) via = via->v_next, new_via = new_via->v_next, dup_via = dup_via->v_next; via = via->v_next; /* Break the link in via list between transports */ vv = &new_via->v_next, new_via = *vv, *vv = NULL; vv = &dup_via->v_next, dup_via = *vv, *vv = NULL; if (tport_is_public(tp)) while (*next_new_public) next_new_public = &(*next_new_public)->v_next; else while (*next_new_via) next_new_via = &(*next_new_via)->v_next; } assert(dup_via == NULL); assert(new_via == NULL); if (self->sa_tport_udp) agent_set_udp_params(self, self->sa_udp_mtu); v = self->sa_vias; self->sa_vias = new_vias; msg_header_free(self->sa_home, (void *)v); v = self->sa_public_vias; self->sa_public_vias = new_publics; msg_header_free(self->sa_home, (void *)v); su_home_deinit(autohome); return 0; error: su_home_deinit(autohome); return -1; } /** Initialize main contact header. */ static int agent_init_contact(nta_agent_t *self) { sip_via_t const *v1, *v2; char const *tp; if (self->sa_contact) return 0; for (v1 = self->sa_vias ? self->sa_vias : self->sa_public_vias; v1; v1 = v1->v_next) { if (host_is_ip_address(v1->v_host)) { if (!host_is_local(v1->v_host)) break; } else if (!host_has_domain_invalid(v1->v_host)) { break; } } if (v1 == NULL) v1 = self->sa_vias ? self->sa_vias : self->sa_public_vias; if (!v1) return -1; tp = strrchr(v1->v_protocol, '/'); if (!tp++) return -1; v2 = v1->v_next; if (v2 && su_casematch(v1->v_host, v2->v_host) && su_casematch(v1->v_port, v2->v_port)) { char const *p1 = v1->v_protocol, *p2 = v2->v_protocol; if (!su_casematch(p1, sip_transport_udp)) p1 = v2->v_protocol, p2 = v1->v_protocol; if (su_casematch(p1, sip_transport_udp) && su_casematch(p2, sip_transport_tcp)) /* Do not include transport if we have both UDP and TCP */ tp = NULL; } self->sa_contact = sip_contact_create_from_via_with_transport(self->sa_home, v1, NULL, tp); if (!self->sa_contact) return -1; agent_tag_init(self); return 0; } /** Return @Via line corresponging to tport. */ static sip_via_t const *agent_tport_via(tport_t *tport) { sip_via_t *v = tport_magic(tport); while (v && v->v_next) v = v->v_next; return v; } /** Insert @Via to a request message */ static int outgoing_insert_via(nta_outgoing_t *orq, sip_via_t const *via) { nta_agent_t *self = orq->orq_agent; msg_t *msg = orq->orq_request; sip_t *sip = sip_object(msg); char const *branch = orq->orq_via_branch; int already = orq->orq_user_via || orq->orq_via_added; int user_via = orq->orq_user_via; sip_via_t *v; int clear = 0; assert(sip); assert(via); if (already && sip->sip_via) { /* Use existing @Via */ v = sip->sip_via; } else if (msg && via && sip->sip_request && (v = sip_via_copy(msg_home(msg), via))) { if (msg_header_insert(msg, (msg_pub_t *)sip, (msg_header_t *)v) < 0) return -1; orq->orq_via_added = 1; } else return -1; if (!v->v_rport && ((self->sa_rport && v->v_protocol == sip_transport_udp) || (self->sa_tcp_rport && v->v_protocol == sip_transport_tcp) || (self->sa_tls_rport && v->v_protocol == sip_transport_tls))) msg_header_add_param(msg_home(msg), v->v_common, "rport"); if (!orq->orq_tpn->tpn_comp) msg_header_remove_param(v->v_common, "comp"); if (branch && branch != v->v_branch) { char const *bvalue = branch + strcspn(branch, "="); if (*bvalue) bvalue++; if (!v->v_branch || !su_casematch(bvalue, v->v_branch)) msg_header_replace_param(msg_home(msg), v->v_common, branch); } if (!su_casematch(via->v_protocol, v->v_protocol)) clear = 1, v->v_protocol = via->v_protocol; /* XXX - should we do this? */ if ((!user_via || !v->v_host) && !su_strmatch(via->v_host, v->v_host)) clear = 1, v->v_host = via->v_host; if ((!user_via || !v->v_port || /* Replace port in user Via only if we use udp and no rport */ (v->v_protocol == sip_transport_udp && !v->v_rport && !orq->orq_stateless)) && !su_strmatch(via->v_port, v->v_port)) clear = 1, v->v_port = via->v_port; if (clear) msg_fragment_clear_chain((msg_header_t *)v); return 0; } /** Get destination name from @Via. * * If @a using_rport is non-null, try rport. * If *using_rport is non-zero, try rport even if is not UDP. * If is UDP, set *using_rport to zero. */ static int nta_tpn_by_via(tp_name_t *tpn, sip_via_t const *v, int *using_rport) { if (!v) return -1; tpn->tpn_proto = sip_via_transport(v); tpn->tpn_canon = v->v_host; if (v->v_maddr) tpn->tpn_host = v->v_maddr; else if (v->v_received) tpn->tpn_host = v->v_received; else tpn->tpn_host = v->v_host; tpn->tpn_port = sip_via_port(v, using_rport); tpn->tpn_comp = v->v_comp; tpn->tpn_ident = NULL; return 0; } /** Get transport name from URL. */ static int nta_tpn_by_url(su_home_t *home, tp_name_t *tpn, char const **scheme, char const **port, url_string_t const *us) { url_t url[1]; isize_t n; char *b; n = url_xtra(us->us_url); b = su_alloc(home, n); if (b == NULL || url_dup(b, n, url, us->us_url) < 0) { su_free(home, b); return -1; } if (url->url_type != url_sip && url->url_type != url_sips && url->url_type != url_im && url->url_type != url_pres) { su_free(home, b); return -1; } SU_DEBUG_7(("nta: selecting scheme %s\n", url->url_scheme)); *scheme = url->url_scheme; tpn->tpn_proto = NULL; tpn->tpn_canon = url->url_host; tpn->tpn_host = url->url_host; if (url->url_params) { for (b = (char *)url->url_params; b[0]; b += n) { n = strcspn(b, ";"); if (n > 10 && su_casenmatch(b, "transport=", 10)) tpn->tpn_proto = b + 10; else if (n > 5 && su_casenmatch(b, "comp=", 5)) tpn->tpn_comp = b + 5; else if (n > 6 && su_casenmatch(b, "maddr=", 6)) tpn->tpn_host = b + 6; if (b[n]) b[n++] = '\0'; } } if ((*port = url->url_port)) tpn->tpn_port = url->url_port; tpn->tpn_ident = NULL; if (tpn->tpn_proto) return 1; if (su_casematch(url->url_scheme, "sips")) tpn->tpn_proto = "tls"; else tpn->tpn_proto = "*"; return 0; } /** Handle transport errors. */ static void agent_tp_error(nta_agent_t *agent, tport_t *tport, int errcode, char const *remote) { su_llog(nta_log, 1, "nta_agent: tport: %s%s%s\n", remote ? remote : "", remote ? ": " : "", su_strerror(errcode)); } /** Handle updated transport addresses */ static void agent_update_tport(nta_agent_t *self, tport_t *tport) { /* Initialize local Vias first */ agent_init_via(self, tport_primaries(self->sa_tports), 0); if (self->sa_update_tport) { self->sa_update_tport(self->sa_update_magic, self); } else { /* XXX - we should do something else? */ SU_DEBUG_3(("%s(%p): %s\n", "nta", (void *)self, "transport address updated")); } } /* ====================================================================== */ /* 3) Message dispatch */ static void agent_recv_request(nta_agent_t *agent, msg_t *msg, sip_t *sip, tport_t *tport); static int agent_check_request_via(nta_agent_t *agent, msg_t *msg, sip_t *sip, sip_via_t *v, tport_t *tport); static int agent_aliases(nta_agent_t const *, url_t [], tport_t *); static void agent_recv_response(nta_agent_t*, msg_t *, sip_t *, sip_via_t *, tport_t*); static void agent_recv_garbage(nta_agent_t*, msg_t*, tport_t*); /** Handle incoming message. */ static void agent_recv_message(nta_agent_t *agent, tport_t *tport, msg_t *msg, sip_via_t *tport_via, su_time_t now) { sip_t *sip = sip_object(msg); agent->sa_millisec = su_time_ms(agent->sa_now = now); if (sip && sip->sip_request) { agent_recv_request(agent, msg, sip, tport); } else if (sip && sip->sip_status) { agent_recv_response(agent, msg, sip, tport_via, tport); } else { agent_recv_garbage(agent, msg, tport); } agent->sa_millisec = 0; } /** @internal Handle incoming requests. */ static void agent_recv_request(nta_agent_t *agent, msg_t *msg, sip_t *sip, tport_t *tport) { nta_leg_t *leg; nta_incoming_t *irq, *merge = NULL, *ack = NULL, *cancel = NULL; sip_method_t method = sip->sip_request->rq_method; char const *method_name = sip->sip_request->rq_method_name; url_t url[1]; unsigned cseq = sip->sip_cseq ? sip->sip_cseq->cs_seq : 0; int insane, errors, stream; agent->sa_stats->as_recv_msg++; agent->sa_stats->as_recv_request++; SU_DEBUG_5(("nta: received %s " URL_PRINT_FORMAT " %s (CSeq %u)\n", method_name, URL_PRINT_ARGS(sip->sip_request->rq_url), sip->sip_request->rq_version, cseq)); if (agent->sa_drop_prob && !tport_is_reliable(tport)) { if ((unsigned)su_randint(0, 1000) < agent->sa_drop_prob) { SU_DEBUG_5(("nta: %s (%u) is %s\n", method_name, cseq, "dropped simulating packet loss")); agent->sa_stats->as_drop_request++; msg_destroy(msg); return; } } stream = tport_is_stream(tport); /* Try to use compression on reverse direction if @Via has comp=sigcomp */ if (stream && sip->sip_via && sip->sip_via->v_comp && tport_can_send_sigcomp(tport) && tport_name(tport)->tpn_comp == NULL && tport_has_compression(tport_parent(tport), sip->sip_via->v_comp)) { tport_set_compression(tport, sip->sip_via->v_comp); } if (sip->sip_flags & MSG_FLG_TOOLARGE) { SU_DEBUG_5(("nta: %s (%u) is %s\n", method_name, cseq, sip_413_Request_too_large)); agent->sa_stats->as_bad_request++; mreply(agent, NULL, SIP_413_REQUEST_TOO_LARGE, msg, tport, 1, stream, NULL, TAG_END()); return; } insane = 0; if (agent->sa_bad_req_mask != ~0U) errors = msg_extract_errors(msg) & agent->sa_bad_req_mask; else errors = sip->sip_error != NULL; if (errors || (sip->sip_flags & MSG_FLG_ERROR) /* Fatal error */ || (insane = (sip_sanity_check(sip) < 0))) { sip_header_t const *h; char const *badname = NULL, *phrase; agent->sa_stats->as_bad_message++; agent->sa_stats->as_bad_request++; if (insane) SU_DEBUG_5(("nta: %s (%u) %s\n", method_name, cseq, "failed sanity check")); for (h = (sip_header_t const *)sip->sip_error; h; h = h->sh_next) { char const *bad; if (h->sh_class == sip_error_class) bad = h->sh_error->er_name; else bad = h->sh_class->hc_name; if (bad) SU_DEBUG_5(("nta: %s has bad %s header\n", method_name, bad)); if (!badname) badname = bad; } if (sip->sip_via && method != sip_method_ack) { msg_t *reply = nta_msg_create(agent, 0); agent_check_request_via(agent, msg, sip, sip->sip_via, tport); if (badname && reply) phrase = su_sprintf(msg_home(reply), "Bad %s Header", badname); else phrase = sip_400_Bad_request; SU_DEBUG_5(("nta: %s (%u) is %s\n", method_name, cseq, phrase)); mreply(agent, reply, 400, phrase, msg, tport, 1, stream, NULL, TAG_END()); } else { msg_destroy(msg); if (stream) /* Send FIN */ tport_shutdown(tport, 1); } return; } if (!su_casematch(sip->sip_request->rq_version, sip_version_2_0)) { agent->sa_stats->as_bad_request++; agent->sa_stats->as_bad_message++; SU_DEBUG_5(("nta: bad version %s for %s (%u)\n", sip->sip_request->rq_version, method_name, cseq)); mreply(agent, NULL, SIP_505_VERSION_NOT_SUPPORTED, msg, tport, 0, stream, NULL, TAG_END()); return; } if (agent_check_request_via(agent, msg, sip, sip->sip_via, tport) < 0) { agent->sa_stats->as_bad_message++; agent->sa_stats->as_bad_request++; SU_DEBUG_5(("nta: %s (%u) %s\n", method_name, cseq, "has invalid Via")); msg_destroy(msg); return; } /* First, try existing incoming requests */ irq = incoming_find(agent, sip, sip->sip_via, agent->sa_merge_482 && !sip->sip_to->a_tag && method != sip_method_ack ? &merge : NULL, method == sip_method_ack ? &ack : NULL, method == sip_method_cancel ? &cancel : NULL); if (irq) { /* Match - this is a retransmission */ SU_DEBUG_5(("nta: %s (%u) going to existing %s transaction\n", method_name, cseq, irq->irq_rq->rq_method_name)); if (incoming_recv(irq, msg, sip, tport) >= 0) return; } else if (ack) { SU_DEBUG_5(("nta: %s (%u) is going to %s (%u)\n", method_name, cseq, ack->irq_cseq->cs_method_name, ack->irq_cseq->cs_seq)); if (incoming_ack(ack, msg, sip, tport) >= 0) return; } else if (cancel) { SU_DEBUG_5(("nta: %s (%u) is going to %s (%u)\n", method_name, cseq, cancel->irq_cseq->cs_method_name, cancel->irq_cseq->cs_seq)); if (incoming_cancel(cancel, msg, sip, tport) >= 0) return; } else if (merge) { SU_DEBUG_5(("nta: %s (%u) %s\n", method_name, cseq, "is a merged request")); request_merge(agent, msg, sip, tport, merge->irq_tag); return; } if (method == sip_method_prack && sip->sip_rack) { nta_reliable_t *rel = reliable_find(agent, sip); if (rel) { SU_DEBUG_5(("nta: %s (%u) is going to %s (%u)\n", method_name, cseq, rel->rel_irq->irq_cseq->cs_method_name, rel->rel_irq->irq_cseq->cs_seq)); reliable_recv(rel, msg, sip, tport); return; } } *url = *sip->sip_request->rq_url; url->url_params = NULL; agent_aliases(agent, url, tport); /* canonize urls */ if ((leg = leg_find(agent, method_name, url, sip->sip_call_id, sip->sip_from->a_tag, sip->sip_to->a_tag))) { /* Try existing dialog */ SU_DEBUG_5(("nta: %s (%u) %s\n", method_name, cseq, "going to existing leg")); leg_recv(leg, msg, sip, tport); return; } else if (!agent->sa_is_stateless && (leg = dst_find(agent, url, method_name))) { /* Dialogless legs - let application process transactions statefully */ SU_DEBUG_5(("nta: %s (%u) %s\n", method_name, cseq, "going to a dialogless leg")); leg_recv(leg, msg, sip, tport); } else if (!agent->sa_is_stateless && (leg = agent->sa_default_leg)) { if (method == sip_method_invite && agent->sa_in.proceeding->q_length >= agent->sa_max_proceeding) { SU_DEBUG_5(("nta: proceeding queue full for %s (%u)\n", method_name, cseq)); mreply(agent, NULL, SIP_503_SERVICE_UNAVAILABLE, msg, tport, 0, 0, NULL, TAG_END()); return; } else { SU_DEBUG_5(("nta: %s (%u) %s\n", method_name, cseq, "going to a default leg")); leg_recv(leg, msg, sip, tport); } } else if (agent->sa_callback) { /* Stateless processing for request */ agent->sa_stats->as_trless_request++; SU_DEBUG_5(("nta: %s (%u) %s\n", method_name, cseq, "to message callback")); (void)agent->sa_callback(agent->sa_magic, agent, msg, sip); } else { agent->sa_stats->as_trless_request++; SU_DEBUG_5(("nta: %s (%u) %s\n", method_name, cseq, "not processed by application: returning 501")); if (method != sip_method_ack) mreply(agent, NULL, SIP_501_NOT_IMPLEMENTED, msg, tport, 0, 0, NULL, TAG_END()); else msg_destroy(msg); } } /** Check @Via header. * */ static int agent_check_request_via(nta_agent_t *agent, msg_t *msg, sip_t *sip, sip_via_t *v, tport_t *tport) { enum { receivedlen = sizeof("received=") - 1 }; char received[receivedlen + TPORT_HOSTPORTSIZE]; char *hostport = received + receivedlen; char const *rport; su_sockaddr_t const *from; sip_via_t const *tpv = agent_tport_via(tport); assert(tport); assert(msg); assert(sip); assert(sip->sip_request); assert(tpv); from = msg_addr(msg); if (v == NULL) { /* Make up a via line */ v = sip_via_format(msg_home(msg), "SIP/2.0/%s %s", tport_name(tport)->tpn_proto, tport_hostport(hostport, TPORT_HOSTPORTSIZE, from, 1)); msg_header_insert(msg, (msg_pub_t *)sip, (msg_header_t *)v); return v ? 0 : -1; } if (!su_strmatch(v->v_protocol, tpv->v_protocol)) { tport_hostport(hostport, TPORT_HOSTPORTSIZE, from, 1); SU_DEBUG_1(("nta: Via check: invalid transport \"%s\" from %s\n", v->v_protocol, hostport)); return -1; } if (v->v_received) { /* Nasty, nasty */ tport_hostport(hostport, TPORT_HOSTPORTSIZE, from, 1); SU_DEBUG_1(("nta: Via check: extra received=%s from %s\n", v->v_received, hostport)); msg_header_remove_param(v->v_common, "received"); } if (!tport_hostport(hostport, TPORT_HOSTPORTSIZE, from, 0)) return -1; if (!su_casematch(hostport, v->v_host)) { size_t rlen; /* Add the "received" field */ memcpy(received, "received=", receivedlen); if (hostport[0] == '[') { rlen = strlen(hostport + 1) - 1; memmove(hostport, hostport + 1, rlen); hostport[rlen] = '\0'; } msg_fragment_clear_chain((msg_header_t *)v); msg_header_replace_param(msg_home(msg), v->v_common, su_strdup(msg_home(msg), received)); SU_DEBUG_5(("nta: Via check: %s\n", received)); } if (!agent->sa_server_rport) { /*Xyzzy*/; } else if (v->v_rport) { rport = su_sprintf(msg_home(msg), "rport=%u", ntohs(from->su_port)); msg_header_replace_param(msg_home(msg), v->v_common, rport); } else if (tport_is_tcp(tport)) { rport = su_sprintf(msg_home(msg), "rport=%u", ntohs(from->su_port)); msg_header_replace_param(msg_home(msg), v->v_common, rport); } else if (agent->sa_server_rport == 2 || (agent->sa_server_rport == 3 && sip && sip->sip_user_agent && su_casenmatch(sip->sip_user_agent->g_string, "Polycom", 7))) { rport = su_sprintf(msg_home(msg), "rport=%u", ntohs(from->su_port)); msg_header_replace_param(msg_home(msg), v->v_common, rport); } return 0; } /** @internal Handle aliases of local node. * * Return true if @a url is modified. */ static int agent_aliases(nta_agent_t const *agent, url_t url[], tport_t *tport) { sip_contact_t *m; sip_via_t const *lv; char const *tport_port = ""; if (!url->url_host) return 0; if (tport) tport_port = tport_name(tport)->tpn_port; assert(tport_port); for (m = agent->sa_aliases ? agent->sa_aliases : agent->sa_contact; m; m = m->m_next) { if (url->url_type != m->m_url->url_type) continue; if (host_cmp(url->url_host, m->m_url->url_host)) continue; if (url->url_port == NULL) break; if (m->m_url->url_port) { if (strcmp(url->url_port, m->m_url->url_port)) continue; } else { if (strcmp(url->url_port, tport_port)) continue; } break; } if (!m) return 0; SU_DEBUG_7(("nta: canonizing " URL_PRINT_FORMAT " with %s\n", URL_PRINT_ARGS(url), agent->sa_aliases ? "aliases" : "contact")); url->url_host = "%"; if (agent->sa_aliases) { url->url_type = agent->sa_aliases->m_url->url_type; url->url_scheme = agent->sa_aliases->m_url->url_scheme; url->url_port = agent->sa_aliases->m_url->url_port; return 1; } else { /* Canonize the request URL port */ if (tport) { lv = agent_tport_via(tport_parent(tport)); assert(lv); if (lv->v_port) /* Add non-default port */ url->url_port = lv->v_port; return 1; } if (su_strmatch(url->url_port, url_port_default((enum url_type_e)url->url_type)) || su_strmatch(url->url_port, "")) /* Remove default or empty port */ url->url_port = NULL; return 0; } } /** @internal Handle incoming responses. */ static void agent_recv_response(nta_agent_t *agent, msg_t *msg, sip_t *sip, sip_via_t *tport_via, tport_t *tport) { int status = sip->sip_status->st_status; int errors; char const *phrase = sip->sip_status->st_phrase; char const *method = sip->sip_cseq ? sip->sip_cseq->cs_method_name : ""; uint32_t cseq = sip->sip_cseq ? sip->sip_cseq->cs_seq : 0; nta_outgoing_t *orq; agent->sa_stats->as_recv_msg++; agent->sa_stats->as_recv_response++; SU_DEBUG_5(("nta: received %03d %s for %s (%u)\n", status, phrase, method, cseq)); if (agent->sa_drop_prob && !tport_is_reliable(tport)) { if ((unsigned)su_randint(0, 1000) < agent->sa_drop_prob) { SU_DEBUG_5(("nta: %03d %s %s\n", status, phrase, "dropped simulating packet loss")); agent->sa_stats->as_drop_response++; msg_destroy(msg); return; } } if (agent->sa_bad_resp_mask) errors = msg_extract_errors(msg) & agent->sa_bad_resp_mask; else errors = sip->sip_error != NULL; if (errors || sip_sanity_check(sip) < 0) { sip_header_t const *h; agent->sa_stats->as_bad_response++; agent->sa_stats->as_bad_message++; SU_DEBUG_5(("nta: %03d %s %s\n", status, phrase, errors ? "has fatal syntax errors" : "failed sanity check")); for (h = (sip_header_t const *)sip->sip_error; h; h = h->sh_next) { if (h->sh_class->hc_name) { SU_DEBUG_5(("nta: %03d has bad %s header\n", status, h->sh_class->hc_name)); } } msg_destroy(msg); return; } if (!su_casematch(sip->sip_status->st_version, sip_version_2_0)) { agent->sa_stats->as_bad_response++; agent->sa_stats->as_bad_message++; SU_DEBUG_5(("nta: bad version %s %03d %s\n", sip->sip_status->st_version, status, phrase)); msg_destroy(msg); return; } if (sip->sip_cseq->cs_method == sip_method_ack) { /* Drop response messages to ACK */ agent->sa_stats->as_bad_response++; agent->sa_stats->as_bad_message++; SU_DEBUG_5(("nta: %03d %s %s\n", status, phrase, "is response to ACK")); msg_destroy(msg); return; } /* XXX - should check if msg should be discarded based on via? */ if ((orq = outgoing_find(agent, msg, sip, sip->sip_via))) { SU_DEBUG_5(("nta: %03d %s %s\n", status, phrase, "is going to a transaction")); if (outgoing_recv(orq, status, msg, sip) == 0) return; } agent->sa_stats->as_trless_response++; if ((orq = agent->sa_default_outgoing)) { SU_DEBUG_5(("nta: %03d %s %s\n", status, phrase, "to the default transaction")); outgoing_default_recv(orq, status, msg, sip); return; } else if (agent->sa_callback) { SU_DEBUG_5(("nta: %03d %s %s\n", status, phrase, "to message callback")); /* * Store message and transport to hook for the duration of the callback * so that the transport can be obtained by nta_transport(). */ (void)agent->sa_callback(agent->sa_magic, agent, msg, sip); return; } if (sip->sip_cseq->cs_method == sip_method_invite && 200 <= sip->sip_status->st_status && sip->sip_status->st_status < 300 /* Exactly one Via header, belonging to us */ && sip->sip_via && !sip->sip_via->v_next && agent_has_via(agent, sip->sip_via)) { agent->sa_stats->as_trless_200++; } SU_DEBUG_5(("nta: %03d %s %s\n", status, phrase, "was discarded")); msg_destroy(msg); } /** @internal Agent receives garbage */ static void agent_recv_garbage(nta_agent_t *agent, msg_t *msg, tport_t *tport) { agent->sa_stats->as_recv_msg++; agent->sa_stats->as_bad_message++; #if SU_DEBUG >= 3 if (nta_log->log_level >= 3) { tp_name_t tpn[1]; tport_delivered_from(tport, msg, tpn); SU_DEBUG_3(("nta_agent: received garbage from " TPN_FORMAT "\n", TPN_ARGS(tpn))); } #endif msg_destroy(msg); } /* ====================================================================== */ /* 4) Message handling - create, complete, destroy */ /** Create a new message belonging to the agent */ msg_t *nta_msg_create(nta_agent_t *agent, int flags) { msg_t *msg; if (agent == NULL) return su_seterrno(EINVAL), NULL; msg = msg_create(agent->sa_mclass, agent->sa_flags | flags); if (agent->sa_preload) su_home_preload(msg_home(msg), 1, agent->sa_preload); return msg; } /** Create a new message for transport */ msg_t *nta_msg_create_for_transport(nta_agent_t *agent, int flags, char const data[], usize_t dlen, tport_t const *tport, tp_client_t *via) { msg_t *msg = msg_create(agent->sa_mclass, agent->sa_flags | flags); msg_maxsize(msg, agent->sa_maxsize); if (agent->sa_preload) su_home_preload(msg_home(msg), 1, dlen + agent->sa_preload); return msg; } /** Complete a message. */ int nta_msg_complete(msg_t *msg) { return sip_complete_message(msg); } /** Discard a message */ void nta_msg_discard(nta_agent_t *agent, msg_t *msg) { msg_destroy(msg); } /** Check if the headers are from response generated locally by NTA. */ int nta_sip_is_internal(sip_t const *sip) { return sip == NULL /* No message generated */ || (sip->sip_flags & NTA_INTERNAL_MSG) == NTA_INTERNAL_MSG; } /** Check if the message is internally generated by NTA. */ int nta_msg_is_internal(msg_t const *msg) { return msg_get_flags(msg, NTA_INTERNAL_MSG) == NTA_INTERNAL_MSG; } /** Check if the message is internally generated by NTA. * * @deprecated Use nta_msg_is_internal() instead */ int nta_is_internal_msg(msg_t const *msg) { return nta_msg_is_internal(msg); } /* ====================================================================== */ /* 5) Stateless operation */ /**Forward a request or response message. * * @note * The ownership of @a msg is taken over by the function even if the * function fails. */ int nta_msg_tsend(nta_agent_t *agent, msg_t *msg, url_string_t const *u, tag_type_t tag, tag_value_t value, ...) { int retval = -1; ta_list ta; sip_t *sip = sip_object(msg); tp_name_t tpn[1] = {{ NULL }}; char const *what; if (!sip) { msg_destroy(msg); return -1; } what = sip->sip_status ? "nta_msg_tsend(response)" : sip->sip_request ? "nta_msg_tsend(request)" : "nta_msg_tsend()"; ta_start(ta, tag, value); if (sip_add_tl(msg, sip, ta_tags(ta)) < 0) SU_DEBUG_3(("%s: cannot add headers\n", what)); else if (sip->sip_status) { tport_t *tport = NULL; int *use_rport = NULL; int retry_without_rport = 0; struct sigcomp_compartment *cc; cc = NONE; if (agent->sa_server_rport) use_rport = &retry_without_rport, retry_without_rport = 1; tl_gets(ta_args(ta), NTATAG_TPORT_REF(tport), IF_SIGCOMP_TPTAG_COMPARTMENT_REF(cc) /* NTATAG_INCOMPLETE_REF(incomplete), */ TAG_END()); if (!sip->sip_separator && !(sip->sip_separator = sip_separator_create(msg_home(msg)))) SU_DEBUG_3(("%s: cannot create sip_separator\n", what)); else if (msg_serialize(msg, (msg_pub_t *)sip) != 0) SU_DEBUG_3(("%s: sip_serialize() failed\n", what)); else if (!sip_via_remove(msg, sip)) SU_DEBUG_3(("%s: cannot remove Via\n", what)); else if (nta_tpn_by_via(tpn, sip->sip_via, use_rport) < 0) SU_DEBUG_3(("%s: bad via\n", what)); else { if (!tport) tport = tport_by_name(agent->sa_tports, tpn); if (!tport) tport = tport_by_protocol(agent->sa_tports, tpn->tpn_proto); if (retry_without_rport) tpn->tpn_port = sip_via_port(sip->sip_via, NULL); if (tport && tpn->tpn_comp && cc == NONE) cc = agent_compression_compartment(agent, tport, tpn, -1); if (tport_tsend(tport, msg, tpn, IF_SIGCOMP_TPTAG_COMPARTMENT(cc) TPTAG_MTU(INT_MAX), ta_tags(ta), TAG_END())) { agent->sa_stats->as_sent_msg++; agent->sa_stats->as_sent_response++; retval = 0; } else { SU_DEBUG_3(("%s: send fails\n", what)); } } } else { /* Send request */ if (outgoing_create(agent, NULL, NULL, u, NULL, msg_ref(msg), NTATAG_STATELESS(1), ta_tags(ta))) retval = 0; } if (retval == 0) SU_DEBUG_5(("%s\n", what)); ta_end(ta); msg_destroy(msg); return retval; } /** Reply to a request message. * * @param agent nta agent object * @param req_msg request message * @param status status code * @param phrase status phrase (may be NULL if status code is well-known) * @param tag, value, ... optional additional headers terminated by TAG_END() * * @retval 0 when succesful * @retval -1 upon an error * * @note * The ownership of @a msg is taken over by the function even if the * function fails. */ int nta_msg_treply(nta_agent_t *agent, msg_t *req_msg, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...) { int retval; ta_list ta; ta_start(ta, tag, value); retval = mreply(agent, NULL, status, phrase, req_msg, NULL, 0, 0, NULL, ta_tags(ta)); ta_end(ta); return retval; } /**Reply to the request message. * * @note * The ownership of @a msg is taken over by the function even if the * function fails. */ int nta_msg_mreply(nta_agent_t *agent, msg_t *reply, sip_t *sip, int status, char const *phrase, msg_t *req_msg, tag_type_t tag, tag_value_t value, ...) { int retval = -1; ta_list ta; ta_start(ta, tag, value); retval = mreply(agent, reply, status, phrase, req_msg, NULL, 0, 0, NULL, ta_tags(ta)); ta_end(ta); return retval; } static int mreply(nta_agent_t *agent, msg_t *reply, int status, char const *phrase, msg_t *req_msg, tport_t *tport, int incomplete, int sdwn_after, char const *to_tag, tag_type_t tag, tag_value_t value, ...) { ta_list ta; sip_t *sip; int *use_rport = NULL; int retry_without_rport = 0; tp_name_t tpn[1]; int retval = -1; if (!agent) return -1; if (agent->sa_server_rport) use_rport = &retry_without_rport, retry_without_rport = 1; ta_start(ta, tag, value); tl_gets(ta_args(ta), NTATAG_TPORT_REF(tport), TAG_END()); if (reply == NULL) { reply = nta_msg_create(agent, 0); } sip = sip_object(reply); if (!sip) { SU_DEBUG_3(("%s: cannot create response msg\n", __func__)); } else if (sip_add_tl(reply, sip, ta_tags(ta)) < 0) { SU_DEBUG_3(("%s: cannot add user headers\n", __func__)); } else if (complete_response(reply, status, phrase, req_msg) < 0 && !incomplete) { SU_DEBUG_3(("%s: cannot complete message\n", __func__)); } else if (sip->sip_status && sip->sip_status->st_status > 100 && sip->sip_to && !sip->sip_to->a_tag && (to_tag == NONE ? 0 : to_tag != NULL ? sip_to_tag(msg_home(reply), sip->sip_to, to_tag) < 0 : sip_to_tag(msg_home(reply), sip->sip_to, nta_agent_newtag(msg_home(reply), "tag=%s", agent)) < 0)) { SU_DEBUG_3(("%s: cannot add To tag\n", __func__)); } else if (nta_tpn_by_via(tpn, sip->sip_via, use_rport) < 0) { SU_DEBUG_3(("%s: no Via\n", __func__)); } else { struct sigcomp_compartment *cc = NONE; if (tport == NULL) tport = tport_delivered_by(agent->sa_tports, req_msg); if (!tport) { tport_t *primary = tport_by_protocol(agent->sa_tports, tpn->tpn_proto); tport = tport_by_name(primary, tpn); if (!tport) tport = primary; } if (retry_without_rport) tpn->tpn_port = sip_via_port(sip->sip_via, NULL); if (tport && tpn->tpn_comp) { tl_gets(ta_args(ta), TPTAG_COMPARTMENT_REF(cc), /* XXX - should also check ntatag_sigcomp_close() */ TAG_END()); if (cc == NONE) cc = agent_compression_compartment(agent, tport, tpn, -1); if (cc != NULL && cc != NONE && tport_delivered_with_comp(tport, req_msg, NULL) != -1) { agent_accept_compressed(agent, req_msg, cc); } } if (tport_tsend(tport, reply, tpn, IF_SIGCOMP_TPTAG_COMPARTMENT(cc) TPTAG_MTU(INT_MAX), TPTAG_SDWN_AFTER(sdwn_after), ta_tags(ta))) { agent->sa_stats->as_sent_msg++; agent->sa_stats->as_sent_response++; retval = 0; /* Success! */ } else { SU_DEBUG_3(("%s: send fails\n", __func__)); } } msg_destroy(reply); msg_destroy(req_msg); ta_end(ta); return retval; } /** Add headers from the request to the response message. */ static int complete_response(msg_t *response, int status, char const *phrase, msg_t *request) { su_home_t *home = msg_home(response); sip_t *response_sip = sip_object(response); sip_t const *request_sip = sip_object(request); int incomplete = 0; if (!response_sip || !request_sip || !request_sip->sip_request) return -1; if (!response_sip->sip_status) response_sip->sip_status = sip_status_create(home, status, phrase, NULL); if (!response_sip->sip_via) response_sip->sip_via = sip_via_dup(home, request_sip->sip_via); if (!response_sip->sip_from) response_sip->sip_from = sip_from_dup(home, request_sip->sip_from); if (!response_sip->sip_to) response_sip->sip_to = sip_to_dup(home, request_sip->sip_to); if (!response_sip->sip_call_id) response_sip->sip_call_id = sip_call_id_dup(home, request_sip->sip_call_id); if (!response_sip->sip_cseq) response_sip->sip_cseq = sip_cseq_dup(home, request_sip->sip_cseq); if (!response_sip->sip_record_route && request_sip->sip_record_route) sip_add_dup(response, response_sip, (void*)request_sip->sip_record_route); incomplete = sip_complete_message(response) < 0; msg_serialize(response, (msg_pub_t *)response_sip); if (incomplete || !response_sip->sip_status || !response_sip->sip_via || !response_sip->sip_from || !response_sip->sip_to || !response_sip->sip_call_id || !response_sip->sip_cseq || !response_sip->sip_content_length || !response_sip->sip_separator || (request_sip->sip_record_route && !response_sip->sip_record_route)) return -1; return 0; } /** ACK and BYE an unknown 200 OK response to INVITE. * * A UAS may still return a 2XX series response to client request after the * client transactions has been terminated. In that case, the UAC can not * really accept the call. This function was used to accept and immediately * terminate such a call. * * @deprecated This was a bad idea: see sf.net bug #1750691. It can be used * to amplify DoS attacks. Let UAS take care of retransmission timeout and * let it terminate the session. As of @VERSION_1_12_7, this function just * returns -1. */ int nta_msg_ackbye(nta_agent_t *agent, msg_t *msg) { sip_t *sip = sip_object(msg); msg_t *amsg = nta_msg_create(agent, 0); sip_t *asip = sip_object(amsg); msg_t *bmsg = NULL; sip_t *bsip; url_string_t const *ruri; nta_outgoing_t *ack = NULL, *bye = NULL; sip_cseq_t *cseq; sip_request_t *rq; sip_route_t *route = NULL, *r, r0[1]; su_home_t *home = msg_home(amsg); if (asip == NULL) return -1; sip_add_tl(amsg, asip, SIPTAG_TO(sip->sip_to), SIPTAG_FROM(sip->sip_from), SIPTAG_CALL_ID(sip->sip_call_id), TAG_END()); if (sip->sip_contact) { ruri = (url_string_t const *)sip->sip_contact->m_url; } else { ruri = (url_string_t const *)sip->sip_to->a_url; } /* Reverse (and fix) record route */ route = sip_route_reverse(home, sip->sip_record_route); if (route && !url_has_param(route->r_url, "lr")) { for (r = route; r->r_next; r = r->r_next) ; /* Append r-uri */ *sip_route_init(r0)->r_url = *ruri->us_url; r->r_next = sip_route_dup(home, r0); /* Use topmost route as request-uri */ ruri = (url_string_t const *)route->r_url; route = route->r_next; } msg_header_insert(amsg, (msg_pub_t *)asip, (msg_header_t *)route); bmsg = msg_copy(amsg); bsip = sip_object(bmsg); if (!(cseq = sip_cseq_create(home, sip->sip_cseq->cs_seq, SIP_METHOD_ACK))) goto err; else msg_header_insert(amsg, (msg_pub_t *)asip, (msg_header_t *)cseq); if (!(rq = sip_request_create(home, SIP_METHOD_ACK, ruri, NULL))) goto err; else msg_header_insert(amsg, (msg_pub_t *)asip, (msg_header_t *)rq); if (!(ack = nta_outgoing_mcreate(agent, NULL, NULL, NULL, amsg, NTATAG_ACK_BRANCH(sip->sip_via->v_branch), NTATAG_STATELESS(1), TAG_END()))) goto err; else nta_outgoing_destroy(ack); /* Fire and forget */ home = msg_home(bmsg); if (!(cseq = sip_cseq_create(home, 0x7fffffff, SIP_METHOD_BYE))) goto err; else msg_header_insert(bmsg, (msg_pub_t *)bsip, (msg_header_t *)cseq); if (!(rq = sip_request_create(home, SIP_METHOD_BYE, ruri, NULL))) goto err; else msg_header_insert(bmsg, (msg_pub_t *)bsip, (msg_header_t *)rq); if (!(bye = nta_outgoing_mcreate(agent, NULL, NULL, NULL, bmsg, NTATAG_STATELESS(1), TAG_END()))) goto err; else nta_outgoing_destroy(bye); /* Fire and forget */ msg_destroy(msg); return 0; err: msg_destroy(amsg); msg_destroy(bmsg); return -1; } /**Complete a request with values from dialog. * * Complete a request message @a msg belonging to a dialog associated with * @a leg. It increments the local @CSeq value, adds @CallID, @To, @From and * @Route headers (if there is such headers present in @a leg), and creates * a new request line object from @a method, @a method_name and @a * request_uri. * * @param msg pointer to a request message object * @param leg pointer to a #nta_leg_t object * @param method request method number or #sip_method_unknown * @param method_name method name (if @a method == #sip_method_unknown) * @param request_uri request URI * * If @a request_uri contains query part, the query part is converted as SIP * headers and added to the request. * * @retval 0 when successful * @retval -1 upon an error * * @sa nta_outgoing_mcreate(), nta_outgoing_tcreate() */ int nta_msg_request_complete(msg_t *msg, nta_leg_t *leg, sip_method_t method, char const *method_name, url_string_t const *request_uri) { su_home_t *home = msg_home(msg); sip_t *sip = sip_object(msg); sip_to_t const *to; uint32_t seq; url_t reg_url[1]; url_string_t const *original = request_uri; if (!leg || !msg || !sip) return -1; if (!sip->sip_route && leg->leg_route) { if (leg->leg_loose_route) { if (leg->leg_target) { request_uri = (url_string_t *)leg->leg_target->m_url; } sip->sip_route = sip_route_dup(home, leg->leg_route); } else { sip_route_t **rr; request_uri = (url_string_t *)leg->leg_route->r_url; sip->sip_route = sip_route_dup(home, leg->leg_route->r_next); for (rr = &sip->sip_route; *rr; rr = &(*rr)->r_next) ; if (leg->leg_target) *rr = sip_route_dup(home, (sip_route_t *)leg->leg_target); } } else if (leg->leg_target) request_uri = (url_string_t *)leg->leg_target->m_url; if (!request_uri && sip->sip_request) request_uri = (url_string_t *)sip->sip_request->rq_url; to = sip->sip_to ? sip->sip_to : leg->leg_remote; if (!request_uri && to) { if (method != sip_method_register) request_uri = (url_string_t *)to->a_url; else { /* Remove user part from REGISTER requests */ *reg_url = *to->a_url; reg_url->url_user = reg_url->url_password = NULL; request_uri = (url_string_t *)reg_url; } } if (!request_uri) return -1; if (method || method_name) { sip_request_t *rq = sip->sip_request; int use_headers = request_uri == original || (url_t *)request_uri == rq->rq_url; if (!rq || request_uri != (url_string_t *)rq->rq_url || method != rq->rq_method || !su_strmatch(method_name, rq->rq_method_name)) rq = NULL; if (rq == NULL) { rq = sip_request_create(home, method, method_name, request_uri, NULL); if (msg_header_insert(msg, (msg_pub_t *)sip, (msg_header_t *)rq) < 0) return -1; } /* @RFC3261 table 1 (page 152): * Req-URI cannot contain method parameter or headers */ if (rq->rq_url->url_params) { rq->rq_url->url_params = url_strip_param_string((char *)rq->rq_url->url_params, "method"); msg_fragment_clear(rq->rq_common); } if (rq->rq_url->url_headers) { if (use_headers) { char *s = url_query_as_header_string(msg_home(msg), rq->rq_url->url_headers); if (!s) return -1; msg_header_parse_str(msg, (msg_pub_t*)sip, s); } rq->rq_url->url_headers = NULL; msg_fragment_clear(rq->rq_common); } } if (!sip->sip_request) return -1; if (!sip->sip_max_forwards) sip_add_dup(msg, sip, (sip_header_t *)leg->leg_agent->sa_max_forwards); if (!sip->sip_from) sip->sip_from = sip_from_dup(home, leg->leg_local); else if (leg->leg_local && leg->leg_local->a_tag && (!sip->sip_from->a_tag || !su_casematch(sip->sip_from->a_tag, leg->leg_local->a_tag))) sip_from_tag(home, sip->sip_from, leg->leg_local->a_tag); if (sip->sip_from && !sip->sip_from->a_tag) { msg_fragment_clear(sip->sip_from->a_common); sip_from_add_param(home, sip->sip_from, nta_agent_newtag(home, "tag=%s", leg->leg_agent)); } if (sip->sip_to) { if (leg->leg_remote && leg->leg_remote->a_tag) sip_to_tag(home, sip->sip_to, leg->leg_remote->a_tag); } else if (leg->leg_remote) { sip->sip_to = sip_to_dup(home, leg->leg_remote); } else { sip_to_t *to = sip_to_create(home, request_uri); if (to) sip_aor_strip(to->a_url); sip->sip_to = to; } if (!sip->sip_from || !sip->sip_from || !sip->sip_to) return -1; method = sip->sip_request->rq_method; method_name = sip->sip_request->rq_method_name; if (!leg->leg_id && sip->sip_cseq) seq = sip->sip_cseq->cs_seq; else if (method == sip_method_ack || method == sip_method_cancel) /* Dangerous - we may do PRACK/UPDATE meanwhile */ seq = sip->sip_cseq ? sip->sip_cseq->cs_seq : leg->leg_seq; else if (leg->leg_seq) seq = ++leg->leg_seq; else if (sip->sip_cseq) /* Obtain initial value from existing CSeq header */ seq = leg->leg_seq = sip->sip_cseq->cs_seq; else seq = leg->leg_seq = agent_seq(leg->leg_agent); if (!sip->sip_call_id) { if (leg->leg_id) sip->sip_call_id = sip_call_id_dup(home, leg->leg_id); else sip->sip_call_id = sip_call_id_create(home, NULL); } if (!sip->sip_cseq || seq != sip->sip_cseq->cs_seq || method != sip->sip_cseq->cs_method || !su_strmatch(method_name, sip->sip_cseq->cs_method_name)) { sip_cseq_t *cseq = sip_cseq_create(home, seq, method, method_name); if (msg_header_insert(msg, (msg_pub_t *)sip, (msg_header_t *)cseq) < 0) return -1; } return 0; } /* ====================================================================== */ /* 6) Dialogs (legs) */ static void leg_insert(nta_agent_t *agent, nta_leg_t *leg); static int leg_route(nta_leg_t *leg, sip_record_route_t const *route, sip_record_route_t const *reverse, sip_contact_t const *contact, int reroute); static int leg_callback_default(nta_leg_magic_t*, nta_leg_t*, nta_incoming_t*, sip_t const *); #define HTABLE_HASH_LEG(leg) ((leg)->leg_hash) HTABLE_BODIES_WITH(leg_htable, lht, nta_leg_t, HTABLE_HASH_LEG, size_t, hash_value_t); su_inline hash_value_t hash_istring(char const *, char const *, hash_value_t); /**@typedef nta_request_f * * Callback for incoming requests * * This is a callback function invoked by NTA for each incoming SIP request. * * @param lmagic call leg context * @param leg call leg handle * @param ireq incoming request * @param sip incoming request contents * * @retval 100..699 * NTA constructs a reply message with given error code and corresponding * standard phrase, then sends the reply. * * @retval 0 * The application takes care of sending (or not sending) the reply. * * @retval other * All other return values will be interpreted as * @e 500 @e Internal @e server @e error. */ /** * Create a new leg object. * * Creates a leg object, which is used to represent dialogs, partial dialogs * (for example, in case of REGISTER), and destinations within a particular * NTA object. * * When a leg is created, a callback pointer and a application context is * provided. All other parameters are optional. * * @param agent agent object * @param callback function which is called for each * incoming request belonging to this leg * @param magic call leg context * @param tag,value,... optional extra headers in taglist * * When a leg representing dialog is created, the tags SIPTAG_CALL_ID(), * SIPTAG_FROM(), SIPTAG_TO(), and SIPTAG_CSEQ() (for local @CSeq number) are used * to establish dialog context. The SIPTAG_FROM() is used to pass local * address (@From header when making a call, @To header when answering * to a call) to the newly created leg. Respectively, the SIPTAG_TO() is * used to pass remote address (@To header when making a call, @From * header when answering to a call). * * If there is a (preloaded) route associated with the leg, SIPTAG_ROUTE() * and NTATAG_TARGET() can be used. A client or server can also set the * route using @RecordRoute and @Contact headers from a response or * request message with the functions nta_leg_client_route() and * nta_leg_server_route(), respectively. * * When a leg representing a local destination is created, the tags * NTATAG_NO_DIALOG(1), NTATAG_METHOD(), and URLTAG_URL() are used. When a * request with matching request-URI (URLTAG_URL()) and method * (NTATAG_METHOD()) is received, it is passed to the callback function * provided with the leg. * * @sa nta_leg_stateful(), nta_leg_bind(), * nta_leg_tag(), nta_leg_rtag(), * nta_leg_client_route(), nta_leg_server_route(), * nta_leg_destroy(), nta_outgoing_tcreate(), and nta_request_f(). * * @TAGS * NTATAG_NO_DIALOG(), NTATAG_STATELESS(), NTATAG_METHOD(), * URLTAG_URL(), SIPTAG_CALL_ID(), SIPTAG_CALL_ID_STR(), SIPTAG_FROM(), * SIPTAG_FROM_STR(), SIPTAG_TO(), SIPTAG_TO_STR(), SIPTAG_ROUTE(), * NTATAG_TARGET() and SIPTAG_CSEQ(). * */ nta_leg_t *nta_leg_tcreate(nta_agent_t *agent, nta_request_f *callback, nta_leg_magic_t *magic, tag_type_t tag, tag_value_t value, ...) { sip_route_t const *route = NULL; sip_contact_t const *contact = NULL; sip_cseq_t const *cs = NULL; sip_call_id_t const *i = NULL; sip_from_t const *from = NULL; sip_to_t const *to = NULL; char const *method = NULL; char const *i_str = NULL, *to_str = NULL, *from_str = NULL, *cs_str = NULL; url_string_t const *url_string = NULL; int no_dialog = 0; unsigned rseq = 0; /* RFC 3261 section 12.2.1.1 */ uint32_t seq = 0; ta_list ta; nta_leg_t *leg; su_home_t *home; url_t *url; char const *what = NULL; if (agent == NULL) return su_seterrno(EINVAL), NULL; ta_start(ta, tag, value); tl_gets(ta_args(ta), NTATAG_NO_DIALOG_REF(no_dialog), NTATAG_METHOD_REF(method), URLTAG_URL_REF(url_string), SIPTAG_CALL_ID_REF(i), SIPTAG_CALL_ID_STR_REF(i_str), SIPTAG_FROM_REF(from), SIPTAG_FROM_STR_REF(from_str), SIPTAG_TO_REF(to), SIPTAG_TO_STR_REF(to_str), SIPTAG_ROUTE_REF(route), NTATAG_TARGET_REF(contact), NTATAG_REMOTE_CSEQ_REF(rseq), SIPTAG_CSEQ_REF(cs), SIPTAG_CSEQ_STR_REF(cs_str), TAG_END()); ta_end(ta); if (cs) seq = cs->cs_seq; else if (cs_str) seq = strtoul(cs_str, (char **)&cs_str, 10); if (i == NONE) /* Magic value, used for compatibility */ no_dialog = 1; if (!(leg = su_home_clone(agent->sa_home, sizeof(*leg)))) return NULL; home = leg->leg_home; leg->leg_agent = agent; nta_leg_bind(leg, callback, magic); if (from) { /* Now this is kludge */ leg->leg_local_is_to = sip_is_to((sip_header_t*)from); leg->leg_local = sip_to_dup(home, from); } else if (from_str) leg->leg_local = sip_to_make(home, from_str); if (to && no_dialog) { /* Remove tag, if any */ sip_to_t to0[1]; *to0 = *to; to0->a_params = NULL; leg->leg_remote = sip_from_dup(home, to0); } else if (to) leg->leg_remote = sip_from_dup(home, to); else if (to_str) leg->leg_remote = sip_from_make(home, to_str); if (route && route != NONE) leg->leg_route = sip_route_dup(home, route), leg->leg_route_set = 1; if (contact && contact != NONE) { sip_contact_t m[1]; sip_contact_init(m); *m->m_url = *contact->m_url; m->m_url->url_headers = NULL; leg->leg_target = sip_contact_dup(home, m); } url = url_hdup(home, url_string->us_url); /* Match to local hosts */ if (url && agent_aliases(agent, url, NULL)) { url_t *changed = url_hdup(home, url); su_free(home, url); url = changed; } leg->leg_rseq = rseq; leg->leg_seq = seq; leg->leg_url = url; if (from && from != NONE && leg->leg_local == NULL) { what = "cannot duplicate local address"; goto err; } else if (to && to != NONE && leg->leg_remote == NULL) { what = "cannot duplicate remote address"; goto err; } else if (route && route != NONE && leg->leg_route == NULL) { what = "cannot duplicate route"; goto err; } else if (contact && contact != NONE && leg->leg_target == NULL) { what = "cannot duplicate target"; goto err; } else if (url_string && leg->leg_url == NULL) { what = "cannot duplicate local destination"; goto err; } if (!no_dialog) { if (!leg->leg_local || !leg->leg_remote) { /* To and/or From header missing */ if (leg->leg_remote) what = "Missing local dialog address"; else if (leg->leg_local) what = "Missing remote dialog address"; else what = "Missing dialog addresses"; goto err; } leg->leg_dialog = 1; if (i != NULL) leg->leg_id = sip_call_id_dup(home, i); else if (i_str != NULL) leg->leg_id = sip_call_id_make(home, i_str); else leg->leg_id = sip_call_id_create(home, NULL); if (!leg->leg_id) { what = "cannot create Call-ID"; goto err; } leg->leg_hash = leg->leg_id->i_hash; } else if (url) { /* This is "default leg" with a destination URL. */ hash_value_t hash = 0; if (method) { leg->leg_method = su_strdup(home, method); } #if 0 else if (url->url_params) { int len = url_param(url->url_params, "method", NULL, 0); if (len) { char *tmp = su_alloc(home, len); leg->leg_method = tmp; url_param(url->url_params, "method", tmp, len); } } #endif if (url->url_user && strcmp(url->url_user, "") == 0) url->url_user = "%"; /* Match to any user */ hash = hash_istring(url->url_scheme, ":", 0); hash = hash_istring(url->url_host, "", hash); hash = hash_istring(url->url_user, "@", hash); leg->leg_hash = hash; } else { /* This is "default leg" without a destination URL. */ if (agent->sa_default_leg) { SU_DEBUG_1(("%s(): %s\n", "nta_leg_tcreate", "tried to create second default leg")); su_seterrno(EEXIST); goto err; } else { agent->sa_default_leg = leg; } return leg; } if (url) { /* Parameters are ignored when comparing incoming URLs */ url->url_params = NULL; } leg_insert(agent, leg); SU_DEBUG_9(("%s(%p)\n", "nta_leg_tcreate", (void *)leg)); return leg; err: if (what) SU_DEBUG_9(("%s(): %s\n", "nta_leg_tcreate", what)); su_home_zap(leg->leg_home); return NULL; } /** Return the default leg, if any */ nta_leg_t *nta_default_leg(nta_agent_t const *agent) { return agent ? agent->sa_default_leg : NULL; } /** * Insert a call leg to agent. */ static void leg_insert(nta_agent_t *sa, nta_leg_t *leg) { leg_htable_t *leg_hash; assert(leg); assert(sa); if (leg->leg_dialog) leg_hash = sa->sa_dialogs; else leg_hash = sa->sa_defaults; if (leg_htable_is_full(leg_hash)) { leg_htable_resize(sa->sa_home, leg_hash, 0); assert(leg_hash->lht_table); SU_DEBUG_7(("nta: resized%s leg hash to "MOD_ZU"\n", leg->leg_dialog ? "" : " default", leg_hash->lht_size)); } /* Insert entry into hash table (before other legs with same hash) */ leg_htable_insert(leg_hash, leg); } /** * Destroy a leg. * * @param leg leg to be destroyed */ void nta_leg_destroy(nta_leg_t *leg) { SU_DEBUG_9(("nta_leg_destroy(%p)\n", (void *)leg)); if (leg) { leg_htable_t *leg_hash; nta_agent_t *sa = leg->leg_agent; assert(sa); if (leg->leg_dialog) { assert(sa->sa_dialogs); leg_hash = sa->sa_dialogs; } else if (leg != sa->sa_default_leg) { assert(sa->sa_defaults); leg_hash = sa->sa_defaults; } else { sa->sa_default_leg = NULL; leg_hash = NULL; } if (leg_hash) leg_htable_remove(leg_hash, leg); leg_free(sa, leg); } } static void leg_free(nta_agent_t *sa, nta_leg_t *leg) { su_free(sa->sa_home, leg); } /** Return application context for the leg */ nta_leg_magic_t *nta_leg_magic(nta_leg_t const *leg, nta_request_f *callback) { if (leg) if (!callback || leg->leg_callback == callback) return leg->leg_magic; return NULL; } /**Bind a callback function and context to a leg object. * * Change the callback function and context pointer attached to a leg * object. * * @param leg leg object to be bound * @param callback new callback function (or NULL if no callback is desired) * @param magic new context pointer */ void nta_leg_bind(nta_leg_t *leg, nta_request_f *callback, nta_leg_magic_t *magic) { if (leg) { if (callback) leg->leg_callback = callback; else leg->leg_callback = leg_callback_default; leg->leg_magic = magic; } } /** Add a local tag to the leg. * * @param leg leg to be tagged * @param tag tag to be added (if NULL, a tag generated by @b NTA is added) * * @return * Pointer to tag if successful, NULL otherwise. */ char const *nta_leg_tag(nta_leg_t *leg, char const *tag) { if (!leg || !leg->leg_local) return su_seterrno(EINVAL), NULL; if (tag && strchr(tag, '=')) tag = strchr(tag, '=') + 1; /* If there already is a tag, return NULL if it does not match with new one */ if (leg->leg_local->a_tag) { if (tag == NULL || su_casematch(tag, leg->leg_local->a_tag)) return leg->leg_local->a_tag; else return NULL; } if (tag) { if (sip_to_tag(leg->leg_home, leg->leg_local, tag) < 0) return NULL; leg->leg_tagged = 1; return leg->leg_local->a_tag; } tag = nta_agent_newtag(leg->leg_home, "tag=%s", leg->leg_agent); if (!tag || sip_to_add_param(leg->leg_home, leg->leg_local, tag) < 0) return NULL; leg->leg_tagged = 1; return leg->leg_local->a_tag; } /** Get local tag. */ char const *nta_leg_get_tag(nta_leg_t const *leg) { if (leg && leg->leg_local) return leg->leg_local->a_tag; else return NULL; } /** Add a remote tag to the leg. * * @note No remote tag is ever generated. * * @param leg leg to be tagged * @param tag tag to be added (@b must be non-NULL) * * @return * Pointer to tag if successful, NULL otherwise. */ char const *nta_leg_rtag(nta_leg_t *leg, char const *tag) { /* Add a tag parameter, unless there already is a tag */ if (leg && leg->leg_remote && tag) { if (sip_from_tag(leg->leg_home, leg->leg_remote, tag) < 0) return NULL; } if (leg && leg->leg_remote) return leg->leg_remote->a_tag; else return NULL; } /** Get remote tag. */ char const *nta_leg_get_rtag(nta_leg_t const *leg) { if (leg && leg->leg_remote) return leg->leg_remote->a_tag; else return NULL; } /** Get local request sequence number. */ uint32_t nta_leg_get_seq(nta_leg_t const *leg) { return leg ? leg->leg_seq : 0; } /** Get remote request sequence number. */ uint32_t nta_leg_get_rseq(nta_leg_t const *leg) { return leg ? leg->leg_rseq : 0; } /** Save target and route set at UAC side. * * @sa nta_leg_client_reroute(), nta_leg_server_route(), @RFC3261 section 12.1.2 * * @bug Allows modifying the route set after initial transaction, if initial * transaction had no @RecordRoute headers. * * @deprecated Use nta_leg_client_reroute() instead. */ int nta_leg_client_route(nta_leg_t *leg, sip_record_route_t const *route, sip_contact_t const *contact) { return leg_route(leg, NULL, route, contact, 0); } /** Save target and route set at UAC side. * * If @a initial is true, the route set is modified even if it has been set * earlier. * * @param leg pointer to dialog leg * @param route @RecordRoute headers from response * @param contact @Contact header from response * @param initial true if response to initial transaction * * @sa nta_leg_client_route(), nta_leg_server_route(), @RFC3261 section 12.1.2 * * @NEW_1_12_11 */ int nta_leg_client_reroute(nta_leg_t *leg, sip_record_route_t const *route, sip_contact_t const *contact, int initial) { return leg_route(leg, NULL, route, contact, initial ? 2 : 1); } /** Save target and route set at UAS side. * * @param leg pointer to dialog leg * @param route @RecordRoute headers from request * @param contact @Contact header from request * * @sa nta_leg_client_reroute(), @RFC3261 section 12.1.1 */ int nta_leg_server_route(nta_leg_t *leg, sip_record_route_t const *route, sip_contact_t const *contact) { return leg_route(leg, route, NULL, contact, 1); } /** Return route components. */ int nta_leg_get_route(nta_leg_t *leg, sip_route_t const **return_route, sip_contact_t const **return_target) { if (!leg) return -1; if (return_route) *return_route = leg->leg_route; if (return_target) *return_target = leg->leg_target; return 0; } /** Generate @Replaces header. * * @since New in @VERSION_1_12_2. */ sip_replaces_t * nta_leg_make_replaces(nta_leg_t *leg, su_home_t *home, int early_only) { char const *from_tag, *to_tag; if (!leg) return NULL; if (!leg->leg_dialog || !leg->leg_local || !leg->leg_remote || !leg->leg_id) return NULL; from_tag = leg->leg_local->a_tag; if (!from_tag) from_tag = "0"; to_tag = leg->leg_remote->a_tag; if (!to_tag) to_tag = "0"; return sip_replaces_format(home, "%s;from-tag=%s;to-tag=%s%s", leg->leg_id->i_id, from_tag, to_tag, early_only ? ";early-only" : ""); } /** Get dialog leg by @Replaces header. * * @since New in @VERSION_1_12_2. */ nta_leg_t * nta_leg_by_replaces(nta_agent_t *sa, sip_replaces_t const *rp) { nta_leg_t *leg = NULL; if (sa && rp && rp->rp_call_id && rp->rp_from_tag && rp->rp_to_tag) { char const *from_tag = rp->rp_from_tag, *to_tag = rp->rp_to_tag; sip_call_id_t id[1]; sip_call_id_init(id); id->i_hash = msg_hash_string(id->i_id = rp->rp_call_id); leg = leg_find(sa, NULL, NULL, id, from_tag, to_tag); if (leg == NULL && strcmp(from_tag, "0") == 0) leg = leg_find(sa, NULL, NULL, id, NULL, to_tag); if (leg == NULL && strcmp(to_tag, "0") == 0) leg = leg_find(sa, NULL, NULL, id, from_tag, NULL); } return leg; } /**@internal * Find a leg corresponding to the request message. * */ static nta_leg_t * leg_find_call_id(nta_agent_t const *sa, sip_call_id_t const *i) { hash_value_t hash = i->i_hash; leg_htable_t const *lht = sa->sa_dialogs; nta_leg_t **ll, *leg = NULL; for (ll = leg_htable_hash(lht, hash); (leg = *ll); ll = leg_htable_next(lht, ll)) { sip_call_id_t const *leg_i = leg->leg_id; if (leg->leg_hash != hash) continue; if (strcmp(leg_i->i_id, i->i_id) != 0) continue; return leg; } return leg; } /** Get dialog leg by @CallID. * * @note Usually there should be only single dialog per @CallID on * User-Agents. However, proxies may fork requests initiating the dialog and * result in multiple calls per @CallID. * * @since New in @VERSION_1_12_9. */ nta_leg_t * nta_leg_by_call_id(nta_agent_t *sa, const char *call_id) { nta_leg_t *leg = NULL; if (call_id) { sip_call_id_t id[1]; sip_call_id_init(id); id->i_hash = msg_hash_string(id->i_id = call_id); leg = leg_find_call_id(sa, id); } return leg; } /** Calculate a simple case-insensitive hash over a string */ su_inline hash_value_t hash_istring(char const *s, char const *term, hash_value_t hash) { if (s) { for (; *s; s++) { unsigned char c = *s; if ('A' <= c && c <= 'Z') c += 'a' - 'A'; hash = 38501U * (hash + c); } for (s = term; *s; s++) { unsigned char c = *s; hash = 38501U * (hash + c); } } return hash; } /** @internal Handle requests intended for this leg. */ static void leg_recv(nta_leg_t *leg, msg_t *msg, sip_t *sip, tport_t *tport) { nta_agent_t *agent = leg->leg_agent; nta_incoming_t *irq; sip_method_t method = sip->sip_request->rq_method; char const *method_name = sip->sip_request->rq_method_name; char const *tag = NULL; int status; if (leg->leg_local) tag = leg->leg_local->a_tag; if (leg->leg_dialog) agent->sa_stats->as_dialog_tr++; /* RFC-3262 section 3 (page 4) */ if (agent->sa_is_a_uas && method == sip_method_prack) { mreply(agent, NULL, 481, "No such response", msg, tport, 0, 0, NULL, TAG_END()); return; } if (!(irq = incoming_create(agent, msg, sip, tport, tag))) { SU_DEBUG_3(("nta: leg_recv(%p): cannot create transaction for %s\n", (void *)leg, method_name)); mreply(agent, NULL, SIP_500_INTERNAL_SERVER_ERROR, msg, tport, 0, 0, NULL, TAG_END()); return; } irq->irq_in_callback = 1; status = incoming_callback(leg, irq, sip); irq->irq_in_callback = 0; if (irq->irq_destroyed) { if (irq->irq_terminated) { incoming_free(irq); return; } if (status < 200) status = 500; } if (status == 0) return; if (status < 100 || status > 699) { SU_DEBUG_3(("nta_leg(%p): invalid status %03d from callback\n", (void *)leg, status)); status = 500; } else if (method == sip_method_invite && status >= 200 && status < 300) { SU_DEBUG_3(("nta_leg(%p): invalid INVITE status %03d from callback\n", (void *)leg, status)); status = 500; } if (status >= 100 && irq->irq_status < 200) nta_incoming_treply(irq, status, NULL, TAG_END()); if (status >= 200) nta_incoming_destroy(irq); } /**Compare two SIP from/to fields. * * @retval nonzero if matching. * @retval zero if not matching. */ su_inline int addr_cmp(url_t const *a, url_t const *b) { if (b == NULL) return 0; else return host_cmp(a->url_host, b->url_host) || su_strcmp(a->url_port, b->url_port) || su_strcmp(a->url_user, b->url_user); } /** Get a leg by dialog. * * Search for a dialog leg from agent's hash table. The matching rules based * on parameters are as follows: * * @param agent pointer to agent object * @param request_uri if non-NULL, and there is destination URI * associated with the dialog, these URIs must match * @param call_id if non-NULL, must match with @CallID header contents * @param remote_tag if there is remote tag * associated with dialog, @a remote_tag must match * @param remote_uri ignored * @param local_tag if non-NULL and there is local tag associated with leg, * it must math * @param local_uri ignored * * @note * If @a remote_tag or @a local_tag is an empty string (""), the tag is * ignored when matching legs. */ nta_leg_t *nta_leg_by_dialog(nta_agent_t const *agent, url_t const *request_uri, sip_call_id_t const *call_id, char const *remote_tag, url_t const *remote_uri, char const *local_tag, url_t const *local_uri) { void *to_be_freed = NULL; url_t *url; url_t url0[1]; nta_leg_t *leg; if (!agent || !call_id) return su_seterrno(EINVAL), NULL; if (request_uri == NULL) { url = NULL; } else if (URL_IS_STRING(request_uri)) { /* accept a string as URL */ to_be_freed = url = url_hdup(NULL, request_uri); } else { *url0 = *request_uri, url = url0; } if (url) { url->url_params = NULL; agent_aliases(agent, url, NULL); /* canonize url */ } if (remote_tag && remote_tag[0] == '\0') remote_tag = NULL; if (local_tag && local_tag[0] == '\0') local_tag = NULL; leg = leg_find(agent, NULL, url, call_id, remote_tag, local_tag); if (to_be_freed) su_free(NULL, to_be_freed); return leg; } /**@internal * Find a leg corresponding to the request message. * * A leg matches to message if leg_match_request() returns true ("Call-ID", * "To"-tag, and "From"-tag match). */ static nta_leg_t *leg_find(nta_agent_t const *sa, char const *method_name, url_t const *request_uri, sip_call_id_t const *i, char const *from_tag, char const *to_tag) { hash_value_t hash = i->i_hash; leg_htable_t const *lht = sa->sa_dialogs; nta_leg_t **ll, *leg, *loose_match = NULL; for (ll = leg_htable_hash(lht, hash); (leg = *ll); ll = leg_htable_next(lht, ll)) { sip_call_id_t const *leg_i = leg->leg_id; char const *remote_tag = leg->leg_remote->a_tag; char const *local_tag = leg->leg_local->a_tag; url_t const *leg_url = leg->leg_url; char const *leg_method = leg->leg_method; if (leg->leg_hash != hash) continue; if (strcmp(leg_i->i_id, i->i_id) != 0) continue; /* Do not match if the incoming To has tag, but the local does not */ if (!local_tag && to_tag) continue; /* * Do not match if incoming To has no tag and we have local tag * and the tag has been there from the beginning. */ if (local_tag && !to_tag && !leg->leg_tagged) continue; /* Do not match if incoming From has no tag but remote has a tag */ if (remote_tag && !from_tag) continue; /* Avoid matching with itself */ if (!remote_tag != !from_tag && !local_tag != !to_tag) continue; if (local_tag && to_tag && !su_casematch(local_tag, to_tag) && to_tag[0]) continue; if (remote_tag && from_tag && !su_casematch(remote_tag, from_tag) && from_tag[0]) continue; if (leg_url && request_uri && url_cmp(leg_url, request_uri)) continue; if (leg_method && method_name && !su_casematch(method_name, leg_method)) continue; /* Perfect match if both local and To have tag * or local does not have tag. */ if ((!local_tag || to_tag)) return leg; if (loose_match == NULL) loose_match = leg; } return loose_match; } /** Get leg by destination */ nta_leg_t *nta_leg_by_uri(nta_agent_t const *agent, url_string_t const *us) { url_t *url; nta_leg_t *leg = NULL; if (!agent) return NULL; if (!us) return agent->sa_default_leg; url = url_hdup(NULL, us->us_url); if (url) { agent_aliases(agent, url, NULL); leg = dst_find(agent, url, NULL); su_free(NULL, url); } return leg; } /** Find a non-dialog leg corresponding to the request uri u0 */ static nta_leg_t *dst_find(nta_agent_t const *sa, url_t const *u0, char const *method_name) { hash_value_t hash, hash2; leg_htable_t const *lht = sa->sa_defaults; nta_leg_t **ll, *leg, *loose_match = NULL; int again; url_t url[1]; *url = *u0; hash = hash_istring(url->url_scheme, ":", 0); hash = hash_istring(url->url_host, "", hash); hash2 = hash_istring("%", "@", hash); hash = hash_istring(url->url_user, "@", hash); /* First round, search with user name */ /* Second round, search without user name */ do { for (ll = leg_htable_hash(lht, hash); (leg = *ll); ll = leg_htable_next(lht, ll)) { if (leg->leg_hash != hash) continue; if (url_cmp(url, leg->leg_url)) continue; if (!method_name) { if (leg->leg_method) continue; return leg; } else if (leg->leg_method) { if (!su_casematch(method_name, leg->leg_method)) continue; return leg; } loose_match = leg; } if (loose_match) return loose_match; again = 0; if (url->url_user && strcmp(url->url_user, "%")) { url->url_user = "%"; hash = hash2; again = 1; } } while (again); return NULL; } /** Set leg route and target URL. * * Sets the leg route and contact using the @RecordRoute and @Contact * headers. * * @param reroute - allow rerouting * - if 1, follow @RFC3261 semantics * - if 2, response to initial transaction) */ static int leg_route(nta_leg_t *leg, sip_record_route_t const *route, sip_record_route_t const *reverse, sip_contact_t const *contact, int reroute) { su_home_t *home = leg->leg_home; sip_route_t *r, r0[1], *old; int route_is_set; if (!leg) return -1; if (route == NULL && reverse == NULL && contact == NULL) return 0; sip_route_init(r0); route_is_set = reroute ? leg->leg_route_set : leg->leg_route != NULL; if (route_is_set && reroute <= 1) { r = leg->leg_route; } else if (route) { r = sip_route_fixdup(home, route); if (!r) return -1; } else if (reverse) { r = sip_route_reverse(home, reverse); if (!r) return -1; } else r = NULL; #ifdef NTA_STRICT_ROUTING /* * Handle Contact according to the RFC2543bis04 sections 16.1, 16.2 and 16.4. */ if (contact) { *r0->r_url = *contact->m_url; if (!(m_r = sip_route_dup(leg->leg_home, r0))) return -1; /* Append, but replace last entry if it was generated from contact */ for (rr = &r; *rr; rr = &(*rr)->r_next) if (leg->leg_contact_set && (*rr)->r_next == NULL) break; } else rr = NULL; if (rr) { if (*rr) su_free(leg->leg_home, *rr); *rr = m_r; } if (m_r != NULL) leg->leg_contact_set = 1; #else if (r && r->r_url->url_params) leg->leg_loose_route = url_has_param(r->r_url, "lr"); if (contact) { sip_contact_t *target, m[1], *m0; sip_contact_init(m); *m->m_url = *contact->m_url; m->m_url->url_headers = NULL; target = sip_contact_dup(leg->leg_home, m); if (target && target->m_url->url_params) { /* Remove ttl, method. @RFC3261 table 1, page 152 */ char *p = (char *)target->m_url->url_params; p = url_strip_param_string(p, "method"); p = url_strip_param_string(p, "ttl"); target->m_url->url_params = p; } m0 = leg->leg_target, leg->leg_target = target; if (m0) su_free(leg->leg_home, m0); } #endif old = leg->leg_route; leg->leg_route = r; if (old && old != r) msg_header_free(leg->leg_home, (msg_header_t *)old); leg->leg_route_set = 1; return 0; } /** @internal Default leg callback. */ static int leg_callback_default(nta_leg_magic_t *magic, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip) { nta_incoming_treply(irq, SIP_501_NOT_IMPLEMENTED, TAG_END()); return 501; } /* ====================================================================== */ /* 7) Server-side (incoming) transactions */ #define HTABLE_HASH_IRQ(irq) ((irq)->irq_hash) HTABLE_BODIES_WITH(incoming_htable, iht, nta_incoming_t, HTABLE_HASH_IRQ, size_t, hash_value_t); static void incoming_insert(nta_agent_t *agent, incoming_queue_t *queue, nta_incoming_t *irq); su_inline int incoming_is_queued(nta_incoming_t const *irq); su_inline void incoming_queue(incoming_queue_t *queue, nta_incoming_t *); su_inline void incoming_remove(nta_incoming_t *irq); su_inline void incoming_set_timer(nta_incoming_t *, uint32_t interval); su_inline void incoming_reset_timer(nta_incoming_t *); su_inline size_t incoming_mass_destroy(nta_agent_t *, incoming_queue_t *); static int incoming_set_params(nta_incoming_t *irq, tagi_t const *tags); su_inline int incoming_set_compartment(nta_incoming_t *irq, tport_t *tport, msg_t *msg, int create_if_needed); su_inline nta_incoming_t *incoming_call_callback(nta_incoming_t *, msg_t *, sip_t *); su_inline int incoming_final_failed(nta_incoming_t *irq, msg_t *); static void incoming_retransmit_reply(nta_incoming_t *irq, tport_t *tport); /** Create a default server transaction. * * The default server transaction is used by a proxy to forward responses * statelessly. * * @param agent pointer to agent object * * @retval pointer to default server transaction object * @retval NULL if failed */ nta_incoming_t *nta_incoming_default(nta_agent_t *agent) { msg_t *msg; su_home_t *home; nta_incoming_t *irq; if (agent == NULL) return su_seterrno(EFAULT), NULL; if (agent->sa_default_incoming) return su_seterrno(EEXIST), NULL; msg = nta_msg_create(agent, 0); if (!msg) return NULL; irq = su_zalloc(home = msg_home(msg), sizeof(*irq)); if (!irq) return (void)msg_destroy(msg), NULL; irq->irq_home = home; irq->irq_request = NULL; irq->irq_agent = agent; irq->irq_received = agent_now(agent); irq->irq_method = sip_method_invalid; irq->irq_default = 1; agent->sa_default_incoming = irq; return irq; } /** Create a server transaction. * * Create a server transaction for a request message. This function is used * when an element processing requests statelessly wants to process a * particular request statefully. * * @param agent pointer to agent object * @param leg pointer to leg object (either @a agent or @a leg may be NULL) * @param msg pointer to message object * @param sip pointer to SIP structure (may be NULL) * @param tag,value,... optional tagged parameters * * @note * The ownership of @a msg is taken over by the function even if the * function fails. * * @TAGS * @TAG NTATAG_TPORT() specifies the transport used to receive the request * and also default transport for sending the response. * * @retval nta_incoming_t pointer to the newly created server transaction * @retval NULL if failed */ nta_incoming_t *nta_incoming_create(nta_agent_t *agent, nta_leg_t *leg, msg_t *msg, sip_t *sip, tag_type_t tag, tag_value_t value, ...) { char const *to_tag = NULL; tport_t *tport = NULL; ta_list ta; nta_incoming_t *irq; if (msg == NULL) return NULL; if (agent == NULL && leg != NULL) agent = leg->leg_agent; if (sip == NULL) sip = sip_object(msg); if (agent == NULL || sip == NULL || !sip->sip_request || !sip->sip_cseq) return msg_destroy(msg), NULL; ta_start(ta, tag, value); tl_gets(ta_args(ta), NTATAG_TPORT_REF(tport), TAG_END()); ta_end(ta); if (leg && leg->leg_local) to_tag = leg->leg_local->a_tag; if (tport == NULL) tport = tport_delivered_by(agent->sa_tports, msg); irq = incoming_create(agent, msg, sip, tport, to_tag); if (!irq) msg_destroy(msg); return irq; } /** @internal Create a new incoming transaction object. */ static nta_incoming_t *incoming_create(nta_agent_t *agent, msg_t *msg, sip_t *sip, tport_t *tport, char const *tag) { nta_incoming_t *irq = su_zalloc(msg_home(msg), sizeof(*irq)); agent->sa_stats->as_server_tr++; if (irq) { su_home_t *home; incoming_queue_t *queue; sip_method_t method = sip->sip_request->rq_method; irq->irq_request = msg; irq->irq_home = home = msg_home(msg_ref(msg)); irq->irq_agent = agent; irq->irq_received = agent_now(agent); /* Timestamp originally from tport */ irq->irq_method = method; irq->irq_rq = sip_request_copy(home, sip->sip_request); irq->irq_from = sip_from_copy(home, sip->sip_from); irq->irq_to = sip_to_copy(home, sip->sip_to); irq->irq_call_id = sip_call_id_copy(home, sip->sip_call_id); irq->irq_cseq = sip_cseq_copy(home, sip->sip_cseq); irq->irq_via = sip_via_copy(home, sip->sip_via); switch (method) { case sip_method_ack: case sip_method_cancel: case sip_method_bye: case sip_method_options: case sip_method_register: /* Handling Path is up to application */ case sip_method_info: case sip_method_prack: case sip_method_publish: break; default: irq->irq_record_route = sip_record_route_copy(home, sip->sip_record_route); } irq->irq_branch = sip->sip_via->v_branch; irq->irq_reliable_tp = tport_is_reliable(tport); irq->irq_extra_100 = 1; /* Sending extra 100 trying true by default */ if (sip->sip_timestamp) irq->irq_timestamp = sip_timestamp_copy(home, sip->sip_timestamp); /* Tag transaction */ if (tag) sip_to_tag(home, irq->irq_to, tag); irq->irq_tag = irq->irq_to->a_tag; if (method != sip_method_ack) { int *use_rport = NULL; int retry_without_rport = 0; if (agent->sa_server_rport) use_rport = &retry_without_rport, retry_without_rport = 1; if (nta_tpn_by_via(irq->irq_tpn, irq->irq_via, use_rport) < 0) SU_DEBUG_1(("%s: bad via\n", __func__)); } incoming_set_compartment(irq, tport, msg, 0); if (method == sip_method_invite) { irq->irq_must_100rel = sip->sip_require && sip_has_feature(sip->sip_require, "100rel"); if (irq->irq_must_100rel || (sip->sip_supported && sip_has_feature(sip->sip_supported, "100rel"))) { irq->irq_rseq = su_randint(1, 0x7fffffff); /* Initialize rseq */ } queue = agent->sa_in.proceeding; if (irq->irq_reliable_tp) incoming_set_timer(irq, agent->sa_t2 / 2); /* N1 = T2 / 2 */ else incoming_set_timer(irq, 200); /* N1 = 200 ms */ irq->irq_tport = tport_ref(tport); } else if (method == sip_method_ack) { irq->irq_status = 700; /* Never send reply to ACK */ irq->irq_completed = 1; if (irq->irq_reliable_tp || !agent->sa_is_a_uas) { queue = agent->sa_in.terminated; irq->irq_terminated = 1; } else { queue = agent->sa_in.completed; /* Timer J */ } } else { queue = agent->sa_in.proceeding; /* RFC 4320 (nit-actions-03): Blacklisting on a late response occurs even over reliable transports. Thus, if an element processing a request received over a reliable transport is delaying its final response at all, sending a 100 Trying well in advance of the timeout will prevent blacklisting. Sending a 100 Trying immediately will not harm the transaction as it would over UDP, but a policy of always sending such a message results in unneccessary traffic. A policy of sending a 100 Trying after the period of time in which Timer E reaches T2 had this been a UDP hop is one reasonable compromise. */ if (agent->sa_extra_100 && irq->irq_reliable_tp) incoming_set_timer(irq, agent->sa_t2 / 2); /* T2 / 2 */ irq->irq_tport = tport_ref(tport); } irq->irq_hash = NTA_HASH(irq->irq_call_id, irq->irq_cseq->cs_seq); incoming_insert(agent, queue, irq); } return irq; } /** @internal * Insert incoming transaction to hash table. */ static void incoming_insert(nta_agent_t *agent, incoming_queue_t *queue, nta_incoming_t *irq) { incoming_queue(queue, irq); if (incoming_htable_is_full(agent->sa_incoming)) incoming_htable_resize(agent->sa_home, agent->sa_incoming, 0); if (irq->irq_method != sip_method_ack) incoming_htable_insert(agent->sa_incoming, irq); else /* ACK is appended - final response with tags match with it, * not with the original INVITE transaction */ /* XXX - what about rfc2543 servers, which do not add tag? */ incoming_htable_append(agent->sa_incoming, irq); } /** Call callback for incoming request */ static int incoming_callback(nta_leg_t *leg, nta_incoming_t *irq, sip_t *sip) { sip_method_t method = sip->sip_request->rq_method; char const *method_name = sip->sip_request->rq_method_name; /* RFC-3261 section 12.2.2 (page 76) */ if (leg->leg_dialog && irq->irq_agent->sa_is_a_uas && method != sip_method_ack) { uint32_t seq = sip->sip_cseq->cs_seq; if (leg->leg_rseq > sip->sip_cseq->cs_seq) { SU_DEBUG_3(("nta_leg(%p): out-of-order %s (%u < %u)\n", (void *)leg, method_name, seq, leg->leg_rseq)); return 500; } leg->leg_rseq = seq; } return leg->leg_callback(leg->leg_magic, leg, irq, sip); } /** * Destroy an incoming transaction. * * This function does not actually free transaction object, but marks it as * disposable. The object is freed after a timeout. * * @param irq incoming request object to be destroyed */ void nta_incoming_destroy(nta_incoming_t *irq) { if (irq) { irq->irq_callback = NULL; irq->irq_magic = NULL; irq->irq_destroyed = 1; if (!irq->irq_in_callback) { if (irq->irq_terminated || irq->irq_default) incoming_free(irq); else if (irq->irq_status < 200) nta_incoming_treply(irq, SIP_500_INTERNAL_SERVER_ERROR, TAG_END()); } } } /** @internal * Initialize a queue for incoming transactions. */ static void incoming_queue_init(incoming_queue_t *queue, unsigned timeout) { memset(queue, 0, sizeof *queue); queue->q_tail = &queue->q_head; queue->q_timeout = timeout; } /** Change the timeout value of a queue */ static void incoming_queue_adjust(nta_agent_t *sa, incoming_queue_t *queue, uint32_t timeout) { nta_incoming_t *irq; uint32_t latest; if (timeout >= queue->q_timeout || !queue->q_head) { queue->q_timeout = timeout; return; } latest = set_timeout(sa, queue->q_timeout = timeout); for (irq = queue->q_head; irq; irq = irq->irq_next) { if ((int32_t)(irq->irq_timeout - latest) > 0) irq->irq_timeout = latest; } } /** @internal * Test if an incoming transaction is in a queue. */ su_inline int incoming_is_queued(nta_incoming_t const *irq) { return irq && irq->irq_queue; } /** @internal * Insert an incoming transaction into a queue. * * Insert a server transaction into a queue, and sets the corresponding * timeout at the same time. */ su_inline void incoming_queue(incoming_queue_t *queue, nta_incoming_t *irq) { if (irq->irq_queue == queue) { assert(queue->q_timeout == 0); return; } if (incoming_is_queued(irq)) incoming_remove(irq); assert(*queue->q_tail == NULL); irq->irq_timeout = set_timeout(irq->irq_agent, queue->q_timeout); irq->irq_queue = queue; irq->irq_prev = queue->q_tail; *queue->q_tail = irq; queue->q_tail = &irq->irq_next; queue->q_length++; } /** @internal * Remove an incoming transaction from a queue. */ su_inline void incoming_remove(nta_incoming_t *irq) { assert(incoming_is_queued(irq)); assert(irq->irq_queue->q_length > 0); if ((*irq->irq_prev = irq->irq_next)) irq->irq_next->irq_prev = irq->irq_prev; else irq->irq_queue->q_tail = irq->irq_prev, assert(!*irq->irq_queue->q_tail); irq->irq_queue->q_length--; irq->irq_next = NULL; irq->irq_prev = NULL; irq->irq_queue = NULL; irq->irq_timeout = 0; } su_inline void incoming_set_timer(nta_incoming_t *irq, uint32_t interval) { nta_incoming_t **rq; assert(irq); if (interval == 0) { incoming_reset_timer(irq); return; } if (irq->irq_rprev) { if ((*irq->irq_rprev = irq->irq_rnext)) irq->irq_rnext->irq_rprev = irq->irq_rprev; if (irq->irq_agent->sa_in.re_t1 == &irq->irq_rnext) irq->irq_agent->sa_in.re_t1 = irq->irq_rprev; } else { irq->irq_agent->sa_in.re_length++; } irq->irq_retry = set_timeout(irq->irq_agent, irq->irq_interval = interval); rq = irq->irq_agent->sa_in.re_t1; if (!(*rq) || (int32_t)((*rq)->irq_retry - irq->irq_retry) > 0) rq = &irq->irq_agent->sa_in.re_list; while (*rq && (int32_t)((*rq)->irq_retry - irq->irq_retry) <= 0) rq = &(*rq)->irq_rnext; if ((irq->irq_rnext = *rq)) irq->irq_rnext->irq_rprev = &irq->irq_rnext; *rq = irq; irq->irq_rprev = rq; /* Optimization: keep special place for transactions with T1 interval */ if (interval == irq->irq_agent->sa_t1) irq->irq_agent->sa_in.re_t1 = rq; } su_inline void incoming_reset_timer(nta_incoming_t *irq) { if (irq->irq_rprev) { if ((*irq->irq_rprev = irq->irq_rnext)) irq->irq_rnext->irq_rprev = irq->irq_rprev; if (irq->irq_agent->sa_in.re_t1 == &irq->irq_rnext) irq->irq_agent->sa_in.re_t1 = irq->irq_rprev; irq->irq_agent->sa_in.re_length--; } irq->irq_interval = 0, irq->irq_retry = 0; irq->irq_rnext = NULL, irq->irq_rprev = NULL; } /** @internal * Free an incoming transaction. */ static void incoming_free(nta_incoming_t *irq) { SU_DEBUG_9(("nta: incoming_free(%p)\n", (void *)irq)); incoming_cut_off(irq); incoming_reclaim(irq); } /** Remove references to the irq */ su_inline void incoming_cut_off(nta_incoming_t *irq) { nta_agent_t *agent = irq->irq_agent; assert(agent); if (irq->irq_default) { if (irq == agent->sa_default_incoming) agent->sa_default_incoming = NULL; irq->irq_default = 0; return; } if (incoming_is_queued(irq)) incoming_remove(irq); incoming_reset_timer(irq); incoming_htable_remove(agent->sa_incoming, irq); if (irq->irq_cc) nta_compartment_decref(&irq->irq_cc); if (irq->irq_tport) tport_decref(&irq->irq_tport); } /** Reclaim the memory used by irq */ su_inline void incoming_reclaim(nta_incoming_t *irq) { su_home_t *home = irq->irq_home; nta_reliable_t *rel, *rel_next; if (irq->irq_request) msg_destroy(irq->irq_request), irq->irq_request = NULL; if (irq->irq_request2) msg_destroy(irq->irq_request2), irq->irq_request2 = NULL; if (irq->irq_response) msg_destroy(irq->irq_response), irq->irq_response = NULL; for (rel = irq->irq_reliable; rel; rel = rel_next) { rel_next = rel->rel_next; if (rel->rel_unsent) msg_destroy(rel->rel_unsent); su_free(irq->irq_agent->sa_home, rel); } irq->irq_home = NULL; su_free(home, irq); msg_destroy((msg_t *)home); } /** Queue request to be freed */ su_inline void incoming_free_queue(incoming_queue_t *q, nta_incoming_t *irq) { incoming_cut_off(irq); incoming_queue(q, irq); } /** Reclaim memory used by queue of requests */ static void incoming_reclaim_queued(su_root_magic_t *rm, su_msg_r msg, union sm_arg_u *u) { incoming_queue_t *q = u->a_incoming_queue; nta_incoming_t *irq, *irq_next; SU_DEBUG_9(("incoming_reclaim_all(%p, %p, %p)\n", (void *)rm, (void *)msg, (void *)u)); for (irq = q->q_head; irq; irq = irq_next) { irq_next = irq->irq_next; incoming_reclaim(irq); } } /**Bind a callback and context to an incoming transaction object * * Set the callback function and context pointer attached to an incoming * request object. The callback function will be invoked if the incoming * request is cancelled, or if the final response to an incoming @b INVITE * request has been acknowledged. * * If the callback is NULL, or no callback has been bound, NTA invokes the * request callback of the call leg. * * @param irq incoming transaction * @param callback callback function * @param magic application context */ void nta_incoming_bind(nta_incoming_t *irq, nta_ack_cancel_f *callback, nta_incoming_magic_t *magic) { if (irq) { irq->irq_callback = callback; irq->irq_magic = magic; } } /** Add a @To tag to incoming request if needed. * * If @a tag is NULL, a new tag is generated. */ char const *nta_incoming_tag(nta_incoming_t *irq, char const *tag) { if (!irq) return su_seterrno(EFAULT), NULL; if (irq->irq_default) return su_seterrno(EINVAL), NULL; if (tag && strchr(tag, '=')) tag = strchr(tag, '=') + 1; if (tag && irq->irq_tag && !su_casematch(tag, irq->irq_tag)) return NULL; if (!irq->irq_tag) { if (tag) tag = su_strdup(irq->irq_home, tag); else tag = nta_agent_newtag(irq->irq_home, NULL, irq->irq_agent); if (!tag) return tag; irq->irq_tag = tag; irq->irq_tag_set = 1; } return irq->irq_tag; } /**Get request message. * * Retrieve the incoming request message of the incoming transaction. Note * that the message is not copied, but a new reference to it is created. * * @param irq incoming transaction handle * * @retval * A pointer to request message is returned. */ msg_t *nta_incoming_getrequest(nta_incoming_t *irq) { msg_t *msg = NULL; if (irq && !irq->irq_default) msg = msg_ref(irq->irq_request); return msg; } /**Get ACK or CANCEL message. * * Retrieve the incoming ACK or CANCEL request message of the incoming * transaction. Note that the ACK or CANCEL message is not copied, but a new * reference to it is created. * * @param irq incoming transaction handle * * @retval A pointer to request message is returned, or NULL if there is no * CANCEL or ACK received. */ msg_t *nta_incoming_getrequest_ackcancel(nta_incoming_t *irq) { msg_t *msg = NULL; if (irq && irq->irq_request2) msg = msg_ref(irq->irq_request2); return msg; } /**Get response message. * * Retrieve the response message latest sent by the server transaction. Note * that the message is not copied, but a new reference to it is created. Use * msg_dup() or msg_copy() to make a copy of it. * * @param irq incoming transaction handle * * @retval * A pointer to a response message is returned. */ msg_t *nta_incoming_getresponse(nta_incoming_t *irq) { msg_t *msg = NULL; if (irq && irq->irq_response) msg = msg_ref(irq->irq_response); return msg; } /** Get method of a server transaction. */ sip_method_t nta_incoming_method(nta_incoming_t const *irq) { return irq ? irq->irq_method : sip_method_invalid; } /** Get method name of a server transaction. */ char const *nta_incoming_method_name(nta_incoming_t const *irq) { if (irq == NULL) return NULL; else if (irq->irq_rq) return irq->irq_rq->rq_method_name; else return "*"; } /** Get Request-URI of a server transaction */ url_t const *nta_incoming_url(nta_incoming_t const *irq) { return irq && irq->irq_rq ? irq->irq_rq->rq_url : NULL; } /** Get sequence number of a server transaction. */ uint32_t nta_incoming_cseq(nta_incoming_t const *irq) { return irq && irq->irq_cseq ? irq->irq_cseq->cs_seq : 0; } /** Get local tag for incoming request */ char const *nta_incoming_gettag(nta_incoming_t const *irq) { return irq ? irq->irq_tag : 0; } /** * Get status code of a server transaction. */ int nta_incoming_status(nta_incoming_t const *irq) { return irq ? irq->irq_status : 400; } /** Get application context for a server transaction. * * @param irq server transaction * @param callback callback pointer * * Return the application context bound to the server transaction. If the @a * callback function pointer is given, return application context only if * the callback matches with the callback bound to the server transaction. * */ nta_incoming_magic_t *nta_incoming_magic(nta_incoming_t *irq, nta_ack_cancel_f *callback) { return irq && (callback == NULL || irq->irq_callback == callback) ? irq->irq_magic : NULL; } /** When received. * * Return timestamp from the reception of the initial request. * * @NEW_1_12_7. */ sip_time_t nta_incoming_received(nta_incoming_t *irq, su_nanotime_t *return_nano) { su_time_t tv = { 0, 0 }; if (irq) tv = irq->irq_received; if (return_nano) *return_nano = (su_nanotime_t)tv.tv_sec * 1000000000 + tv.tv_usec * 1000; return tv.tv_sec; } /** Find incoming transaction. */ nta_incoming_t *nta_incoming_find(nta_agent_t const *agent, sip_t const *sip, sip_via_t const *v) { if (agent && sip && v) return incoming_find(agent, sip, v, NULL, NULL, NULL); else return NULL; } /** Find a matching server transaction object. * * Check also for requests to merge, to ACK, or to CANCEL. */ static nta_incoming_t *incoming_find(nta_agent_t const *agent, sip_t const *sip, sip_via_t const *v, nta_incoming_t **return_merge, nta_incoming_t **return_ack, nta_incoming_t **return_cancel) { sip_cseq_t const *cseq = sip->sip_cseq; sip_call_id_t const *i = sip->sip_call_id; sip_to_t const *to = sip->sip_to; sip_from_t const *from = sip->sip_from; sip_request_t *rq = sip->sip_request; incoming_htable_t const *iht = agent->sa_incoming; hash_value_t hash = NTA_HASH(i, cseq->cs_seq); char const *magic_branch; nta_incoming_t **ii, *irq; int is_uas_ack = return_ack && agent->sa_is_a_uas; if (v->v_branch && su_casenmatch(v->v_branch, "z9hG4bK", 7)) magic_branch = v->v_branch + 7; else magic_branch = NULL; for (ii = incoming_htable_hash(iht, hash); (irq = *ii); ii = incoming_htable_next(iht, ii)) { if (hash != irq->irq_hash || irq->irq_call_id->i_hash != i->i_hash || strcmp(irq->irq_call_id->i_id, i->i_id)) continue; if (irq->irq_cseq->cs_seq != cseq->cs_seq) continue; if (su_strcasecmp(irq->irq_from->a_tag, from->a_tag)) continue; if (is_uas_ack && irq->irq_method == sip_method_invite && 200 <= irq->irq_status && irq->irq_status < 300 && su_casematch(irq->irq_tag, to->a_tag)) { *return_ack = irq; return NULL; } if (magic_branch) { /* RFC3261 17.2.3: * * The request matches a transaction if branch and sent-by in topmost * the method of the request matches the one that created the * transaction, except for ACK, where the method of the request * that created the transaction is INVITE. */ if (irq->irq_via->v_branch && su_casematch(irq->irq_via->v_branch + 7, magic_branch) && su_casematch(irq->irq_via->v_host, v->v_host) && su_strmatch(irq->irq_via->v_port, v->v_port)) { if (irq->irq_method == cseq->cs_method && strcmp(irq->irq_cseq->cs_method_name, cseq->cs_method_name) == 0) return irq; if (return_ack && irq->irq_method == sip_method_invite) return *return_ack = irq, NULL; if (return_cancel && irq->irq_method != sip_method_ack) return *return_cancel = irq, NULL; } } else { /* No magic branch */ /* INVITE request matches a transaction if the Request-URI, To tag, From tag, Call-ID, CSeq, and top Via header match */ /* From tag, Call-ID, and CSeq number has been matched above */ /* Match top Via header field */ if (!su_casematch(irq->irq_via->v_branch, v->v_branch) || !su_casematch(irq->irq_via->v_host, v->v_host) || !su_strmatch(irq->irq_via->v_port, v->v_port)) ; /* Match Request-URI */ else if (url_cmp(irq->irq_rq->rq_url, rq->rq_url)) ; else { /* Match CSeq */ if (irq->irq_method == cseq->cs_method && su_strmatch(irq->irq_cseq->cs_method_name, cseq->cs_method_name)) { /* Match To tag */ if (!su_strcasecmp(irq->irq_to->a_tag, to->a_tag)) return irq; /* found */ } else if ( /* Tag set by UAS */ su_strcasecmp(irq->irq_tag, to->a_tag) && /* Original tag */ su_strcasecmp(irq->irq_to->a_tag, to->a_tag)) ; else if (return_ack && irq->irq_method == sip_method_invite) return *return_ack = irq, NULL; else if (return_cancel && irq->irq_method != sip_method_ack) return *return_cancel = irq, NULL; } } /* RFC3261 - section 8.2.2.2 Merged Requests */ if (return_merge) { if (irq->irq_cseq->cs_method == cseq->cs_method && strcmp(irq->irq_cseq->cs_method_name, cseq->cs_method_name) == 0) *return_merge = irq, return_merge = NULL; } } return NULL; } /** Process retransmitted requests. */ su_inline int incoming_recv(nta_incoming_t *irq, msg_t *msg, sip_t *sip, tport_t *tport) { nta_agent_t *agent = irq->irq_agent; agent->sa_stats->as_recv_retry++; if (irq->irq_status >= 100) { SU_DEBUG_5(("nta: re-received %s request, retransmitting %u reply\n", sip->sip_request->rq_method_name, irq->irq_status)); incoming_retransmit_reply(irq, tport); } else if (irq->irq_agent->sa_extra_100 && irq->irq_extra_100) { /* Agent and Irq configured to answer automatically with 100 Trying */ if (irq->irq_method == sip_method_invite || /* * Send 100 trying to non-invite if at least half of T2 has expired * since the transaction was created. */ su_duration(agent_now(irq->irq_agent), irq->irq_received) * 2U > irq->irq_agent->sa_t2) { SU_DEBUG_5(("nta: re-received %s request, sending 100 Trying\n", sip->sip_request->rq_method_name)); nta_incoming_treply(irq, SIP_100_TRYING, NTATAG_TPORT(tport), TAG_END()); } } msg_destroy(msg); return 0; } su_inline int incoming_ack(nta_incoming_t *irq, msg_t *msg, sip_t *sip, tport_t *tport) { nta_agent_t *agent = irq->irq_agent; /* Process ACK separately? */ if (irq->irq_status >= 200 && irq->irq_status < 300 && !agent->sa_is_a_uas) return -1; if (irq->irq_queue == agent->sa_in.inv_completed) { if (!irq->irq_confirmed) agent->sa_stats->as_acked_tr++; irq->irq_confirmed = 1; incoming_reset_timer(irq); /* Reset timer G */ if (!irq->irq_reliable_tp) { incoming_queue(agent->sa_in.inv_confirmed, irq); /* Timer I */ } else { irq->irq_terminated = 1; incoming_queue(agent->sa_in.terminated, irq); } if (!irq->irq_destroyed) { if (!irq->irq_callback) /* Process ACK normally */ return -1; incoming_call_callback(irq, msg, sip); /* ACK callback */ } } else if (irq->irq_queue == agent->sa_in.proceeding || irq->irq_queue == agent->sa_in.preliminary) return -1; else assert(irq->irq_queue == agent->sa_in.inv_confirmed || irq->irq_queue == agent->sa_in.terminated); msg_destroy(msg); return 0; } /** Respond to the CANCEL. */ su_inline int incoming_cancel(nta_incoming_t *irq, msg_t *msg, sip_t *sip, tport_t *tport) { nta_agent_t *agent = irq->irq_agent; /* According to the RFC 3261, this INVITE has been destroyed */ if (irq->irq_method == sip_method_invite && 200 <= irq->irq_status && irq->irq_status < 300) { mreply(agent, NULL, SIP_481_NO_TRANSACTION, msg, tport, 0, 0, NULL, TAG_END()); return 0; } /* UAS MUST use same tag in final response to CANCEL and INVITE */ if (agent->sa_is_a_uas && irq->irq_tag == NULL) { nta_incoming_tag(irq, NULL); } mreply(agent, NULL, SIP_200_OK, msg_ref(msg), tport, 0, 0, irq->irq_tag, TAG_END()); /* We have already sent final response */ if (irq->irq_completed || irq->irq_method != sip_method_invite) { msg_destroy(msg); return 0; } if (!irq->irq_canceled) { irq->irq_canceled = 1; agent->sa_stats->as_canceled_tr++; irq = incoming_call_callback(irq, msg, sip); } if (irq && !irq->irq_completed && agent->sa_cancel_487) /* Respond to the cancelled request */ nta_incoming_treply(irq, SIP_487_REQUEST_CANCELLED, TAG_END()); msg_destroy(msg); return 0; } /** Merge request */ static void request_merge(nta_agent_t *agent, msg_t *msg, sip_t *sip, tport_t *tport, char const *to_tag) { nta_incoming_t *irq; agent->sa_stats->as_merged_request++; irq = incoming_create(agent, msg, sip, tport, to_tag); if (irq) { nta_incoming_treply(irq, 482, "Request merged", TAG_END()); nta_incoming_destroy(irq); } else { SU_DEBUG_3(("nta: request_merge(): cannot create transaction for %s\n", sip->sip_request->rq_method_name)); mreply(agent, NULL, 482, "Request merged", msg, tport, 0, 0, NULL, TAG_END()); } } /**@typedef nta_ack_cancel_f * * Callback function prototype for CANCELed/ACKed requests * * This is a callback function is invoked by NTA when an incoming request * has been cancelled or an response to an incoming INVITE request has been * acknowledged. * * @param magic incoming request context * @param ireq incoming request * @param sip ACK/CANCEL message * * @retval 0 * This callback function should return always 0. */ /** Call callback of incoming transaction */ su_inline nta_incoming_t * incoming_call_callback(nta_incoming_t *irq, msg_t *msg, sip_t *sip) { if (irq->irq_callback) { irq->irq_in_callback = 1; irq->irq_request2 = msg; irq->irq_callback(irq->irq_magic, irq, sip); irq->irq_request2 = NULL; irq->irq_in_callback = 0; if (irq->irq_terminated && irq->irq_destroyed) incoming_free(irq), irq = NULL; } return irq; } /**Set server transaction parameters. * * Sets the server transaction parameters. Among others, parameters determine the way * the SigComp compression is handled. * * @TAGS * NTATAG_COMP(), NTATAG_SIGCOMP_CLOSE() and NTATAG_EXTRA_100(). * * @retval number of set parameters when succesful * @retval -1 upon an error */ int nta_incoming_set_params(nta_incoming_t *irq, tag_type_t tag, tag_value_t value, ...) { int retval = -1; if (irq) { ta_list ta; ta_start(ta, tag, value); retval = incoming_set_params(irq, ta_args(ta)); ta_end(ta); } else { su_seterrno(EINVAL); } return retval; } static int incoming_set_params(nta_incoming_t *irq, tagi_t const *tags) { int retval = 0; tagi_t const *t; char const *comp = NONE; struct sigcomp_compartment *cc = NONE; if (irq->irq_default) return retval; for (t = tags; t; t = tl_next(t)) { tag_type_t tt = t->t_tag; if (ntatag_comp == tt) comp = (char const *)t->t_value, retval++; else if (ntatag_sigcomp_close == tt) irq->irq_sigcomp_zap = t->t_value != 0, retval++; else if (tptag_compartment == tt) cc = (void *)t->t_value, retval++; else if (ntatag_extra_100 == tt) irq->irq_extra_100 = t->t_value != 0, retval++; } if (cc != NONE) { if (cc) agent_accept_compressed(irq->irq_agent, irq->irq_request, cc); if (irq->irq_cc) nta_compartment_decref(&irq->irq_cc); irq->irq_cc = nta_compartment_ref(cc); } else if (comp != NULL && comp != NONE && irq->irq_cc == NULL) { incoming_set_compartment(irq, irq->irq_tport, irq->irq_request, 1); } else if (comp == NULL) { irq->irq_tpn->tpn_comp = NULL; } return retval; } su_inline int incoming_set_compartment(nta_incoming_t *irq, tport_t *tport, msg_t *msg, int create_if_needed) { if (!nta_compressor_vtable) return 0; if (irq->irq_cc == NULL || irq->irq_tpn->tpn_comp || tport_delivered_with_comp(tport, msg, NULL) != -1) { struct sigcomp_compartment *cc; cc = agent_compression_compartment(irq->irq_agent, tport, irq->irq_tpn, create_if_needed); if (cc) agent_accept_compressed(irq->irq_agent, msg, cc); irq->irq_cc = cc; } return 0; } /** Add essential headers to the response message */ static int nta_incoming_response_headers(nta_incoming_t *irq, msg_t *msg, sip_t *sip) { int clone = 0; su_home_t *home = msg_home(msg); if (!sip->sip_from) clone = 1, sip->sip_from = sip_from_copy(home, irq->irq_from); if (!sip->sip_to) clone = 1, sip->sip_to = sip_to_copy(home, irq->irq_to); if (!sip->sip_call_id) clone = 1, sip->sip_call_id = sip_call_id_copy(home, irq->irq_call_id); if (!sip->sip_cseq) clone = 1, sip->sip_cseq = sip_cseq_copy(home, irq->irq_cseq); if (!sip->sip_via) clone = 1, sip->sip_via = sip_via_copy(home, irq->irq_via); if (clone) msg_set_parent(msg, (msg_t *)irq->irq_home); if (!sip->sip_from || !sip->sip_to || !sip->sip_call_id || !sip->sip_cseq || !sip->sip_via) return -1; return 0; } /** Complete a response message. * * @param irq server transaction object * @param msg response message to be completed * @param status status code (in range 100 - 699) * @param phrase status phrase (may be NULL) * @param tag,value,... taged argument list * * Generate status structure based on @a status and @a phrase. * Add essential headers to the response message: * @From, @To, @CallID, @CSeq, @Via, and optionally * @RecordRoute. */ int nta_incoming_complete_response(nta_incoming_t *irq, msg_t *msg, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...) { su_home_t *home = msg_home(msg); sip_t *sip = sip_object(msg); int retval; ta_list ta; if (irq == NULL || sip == NULL) return su_seterrno(EFAULT); if (status != 0 && (status < 100 || status > 699)) return su_seterrno(EINVAL); if (status != 0 && !sip->sip_status) sip->sip_status = sip_status_create(home, status, phrase, NULL); ta_start(ta, tag, value); retval = sip_add_tl(msg, sip, ta_tags(ta)); ta_end(ta); if (retval < 0) return -1; if (irq->irq_default) return sip_complete_message(msg); if (status > 100 && !irq->irq_tag) { if (sip->sip_to) nta_incoming_tag(irq, sip->sip_to->a_tag); else nta_incoming_tag(irq, NULL); } if (nta_incoming_response_headers(irq, msg, sip) < 0) return -1; if (sip->sip_status && sip->sip_status->st_status > 100 && irq->irq_tag && sip->sip_to && !sip->sip_to->a_tag) if (sip_to_tag(home, sip->sip_to, irq->irq_tag) < 0) return -1; if (status < 300 && !sip->sip_record_route && irq->irq_record_route) if (sip_add_dup(msg, sip, (sip_header_t *)irq->irq_record_route) < 0) return -1; return sip_complete_message(msg); } /** Create a response message for request. * * @NEW_1_12_5. */ msg_t *nta_incoming_create_response(nta_incoming_t *irq, int status, char const *phrase) { msg_t *msg = NULL; sip_t *sip; if (irq) { msg = nta_msg_create(irq->irq_agent, 0); sip = sip_object(msg); if (sip) { if (status != 0) sip->sip_status = sip_status_create(msg_home(msg), status, phrase, NULL); if (nta_incoming_response_headers(irq, msg, sip) < 0) msg_destroy(msg), msg = NULL; } } return msg; } /**Reply to an incoming transaction request. * * This function creates a response message to an incoming request and sends * it to the client. * * @note * It is possible to send several non-final (1xx) responses, but only one * final response. * * @param irq incoming request * @param status status code * @param phrase status phrase (may be NULL if status code is well-known) * @param tag,value,... optional additional headers terminated by TAG_END() * * @retval 0 when succesful * @retval -1 upon an error */ int nta_incoming_treply(nta_incoming_t *irq, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...) { int retval = -1; if (irq && (irq->irq_status < 200 || status < 200 || (irq->irq_method == sip_method_invite && status < 300))) { ta_list ta; msg_t *msg = nta_msg_create(irq->irq_agent, 0); ta_start(ta, tag, value); if (!msg) ; else if (nta_incoming_complete_response(irq, msg, status, phrase, ta_tags(ta)) < 0) msg_destroy(msg); else if (incoming_set_params(irq, ta_args(ta)) < 0) msg_destroy(msg); else retval = nta_incoming_mreply(irq, msg); ta_end(ta); if (retval < 0 && status >= 200) incoming_final_failed(irq, NULL); } return retval; } /** * Return a response message to client. * * @note * The ownership of @a msg is taken over by the function even if the * function fails. * * @retval 0 when succesful * @retval -1 upon an error */ int nta_incoming_mreply(nta_incoming_t *irq, msg_t *msg) { sip_t *sip = sip_object(msg); int status; if (irq == NULL) { msg_destroy(msg); return -1; } if (msg == NULL || sip == NULL) return -1; if (msg == irq->irq_response) return 0; if (!sip->sip_status || !sip->sip_via || !sip->sip_cseq) return incoming_final_failed(irq, msg); assert (sip->sip_cseq->cs_method == irq->irq_method || irq->irq_default); status = sip->sip_status->st_status; if (!irq->irq_tag && status > 100 && !irq->irq_default) nta_incoming_tag(irq, NULL); if (/* (irq->irq_confirmed && status >= 200) || */ (irq->irq_completed && status >= 300)) { SU_DEBUG_3(("%s: already %s transaction\n", __func__, irq->irq_confirmed ? "confirmed" : "completed")); msg_destroy(msg); return -1; } if (irq->irq_must_100rel && !sip->sip_rseq && status > 100 && status < 200) { /* This nta_reliable_t object will be destroyed by PRACK or timeout */ if (nta_reliable_mreply(irq, NULL, NULL, msg)) return 0; return -1; } if (status >= 200 && irq->irq_reliable && irq->irq_reliable->rel_unsent) { if (reliable_final(irq, msg, sip) == 0) return 0; } return incoming_reply(irq, msg, sip); } /** Send the response message. * * @note The ownership of msg is handled to incoming_reply(). */ int incoming_reply(nta_incoming_t *irq, msg_t *msg, sip_t *sip) { nta_agent_t *agent = irq->irq_agent; int status = sip->sip_status->st_status; int sending = 1; int *use_rport = NULL; int retry_without_rport = 0; tp_name_t *tpn, default_tpn[1]; if (status == 408 && irq->irq_method != sip_method_invite && !agent->sa_pass_408 && !irq->irq_default) { /* RFC 4320 nit-actions-03 Action 2: A transaction-stateful SIP element MUST NOT send a response with Status-Code of 408 to a non-INVITE request. As a consequence, an element that can not respond before the transaction expires will not send a final response at all. */ sending = 0; } if (irq->irq_status == 0 && irq->irq_timestamp && !sip->sip_timestamp) incoming_timestamp(irq, msg, sip); if (irq->irq_default) { if (agent->sa_server_rport) use_rport = &retry_without_rport, retry_without_rport = 1; tpn = default_tpn; if (nta_tpn_by_via(tpn, sip->sip_via, use_rport) < 0) tpn = NULL; } else { tpn = irq->irq_tpn; } if (sip_complete_message(msg) < 0) SU_DEBUG_1(("%s: sip_complete_message() failed\n", __func__)); else if (msg_serialize(msg, (msg_pub_t *)sip) < 0) SU_DEBUG_1(("%s: sip_serialize() failed\n", __func__)); else if (!(irq->irq_tport) && !(tport_decref(&irq->irq_tport), irq->irq_tport = tpn ? tport_by_name(agent->sa_tports, tpn) : 0)) SU_DEBUG_1(("%s: no tport\n", __func__)); else { int i, err = 0; tport_t *tp = NULL; incoming_queue_t *queue; char const *method_name; uint32_t cseq; if (irq->irq_default) { assert(sip->sip_cseq); method_name = sip->sip_cseq->cs_method_name, cseq = sip->sip_cseq->cs_seq; } else { method_name = irq->irq_rq->rq_method_name, cseq = irq->irq_cseq->cs_seq; } if (sending) { for (i = 0; i < 3; i++) { tp = tport_tsend(irq->irq_tport, msg, tpn, IF_SIGCOMP_TPTAG_COMPARTMENT(irq->irq_cc) TPTAG_MTU(INT_MAX), TAG_END()); if (tp) break; err = msg_errno(msg); SU_DEBUG_5(("%s: tport_tsend: %s%s\n", __func__, su_strerror(err), err == EPIPE ? "(retrying)" : "")); if (err != EPIPE && err != ECONNREFUSED) break; tport_decref(&irq->irq_tport); irq->irq_tport = tport_ref(tport_by_name(agent->sa_tports, tpn)); } if (!tp) { SU_DEBUG_3(("%s: tport_tsend: " "error (%s) while sending %u %s for %s (%u)\n", __func__, su_strerror(err), status, sip->sip_status->st_phrase, method_name, cseq)); if (status < 200) msg_destroy(msg); else incoming_final_failed(irq, msg); return 0; } agent->sa_stats->as_sent_msg++; agent->sa_stats->as_sent_response++; } SU_DEBUG_5(("nta: %s %u %s for %s (%u)\n", sending ? "sent" : "not sending", status, sip->sip_status->st_phrase, method_name, cseq)); if (irq->irq_default) { msg_destroy(msg); return 0; } incoming_reset_timer(irq); if (status < 200) { queue = agent->sa_in.proceeding; if (irq->irq_method == sip_method_invite && status > 100 && agent->sa_progress != UINT_MAX && agent->sa_is_a_uas) { /* Retransmit preliminary responses in regular intervals */ incoming_set_timer(irq, agent->sa_progress); /* N2 */ } } else { irq->irq_completed = 1; /* XXX - we should do this only after message has actually been sent! */ if (irq->irq_sigcomp_zap && irq->irq_cc) agent_close_compressor(irq->irq_agent, irq->irq_cc); if (irq->irq_method != sip_method_invite) { irq->irq_confirmed = 1; if (irq->irq_reliable_tp) { irq->irq_terminated = 1; queue = agent->sa_in.terminated ; /* J - set for 0 seconds */ } else { queue = agent->sa_in.completed; /* J */ } tport_decref(&irq->irq_tport); } else if (status >= 300 || agent->sa_is_a_uas) { if (status < 300 || !irq->irq_reliable_tp) incoming_set_timer(irq, agent->sa_t1); /* G */ queue = agent->sa_in.inv_completed; /* H */ } else { #if 1 /* Avoid bug in @RFC3261: Keep INVITE transaction around in order to catch retransmitted INVITEs */ irq->irq_confirmed = 1; queue = agent->sa_in.inv_confirmed; /* H */ #else irq->irq_terminated = 1; queue = agent->sa_in.terminated; #endif } } if (irq->irq_queue != queue) incoming_queue(queue, irq); if (status >= 200 || irq->irq_status < 200) { if (irq->irq_response) msg_destroy(irq->irq_response); assert(msg_home(msg) != irq->irq_home); irq->irq_response = msg; } else { msg_destroy(msg); } if (sip->sip_cseq->cs_method == irq->irq_method && irq->irq_status < 200 && status > irq->irq_status) irq->irq_status = status; return 0; } /* * XXX - handling error is very problematic. * Nobody checks return code from nta_incoming_*reply() */ if (status < 200) { msg_destroy(msg); return -1; } /* We could not send final response. */ return incoming_final_failed(irq, msg); } /** @internal Sending final response has failed. * * Put transaction into its own queue, try later to send the response. */ su_inline int incoming_final_failed(nta_incoming_t *irq, msg_t *msg) { msg_destroy(msg); if (!irq->irq_default) { irq->irq_final_failed = 1; incoming_queue(irq->irq_agent->sa_in.final_failed, irq); } return -1; } /** @internal Retransmit the reply */ static void incoming_retransmit_reply(nta_incoming_t *irq, tport_t *tport) { msg_t *msg = NULL; if (irq->irq_final_failed) return; if (tport == NULL) tport = irq->irq_tport; if (tport == NULL) return; /* Answer with existing reply */ if (irq->irq_reliable && !irq->irq_reliable->rel_pracked) msg = reliable_response(irq); else msg = irq->irq_response; if (msg == NULL) return; if (irq->irq_tpn->tpn_comp && ++irq->irq_retries == 2) { irq->irq_tpn->tpn_comp = NULL; if (irq->irq_cc) { agent_close_compressor(irq->irq_agent, irq->irq_cc); nta_compartment_decref(&irq->irq_cc); } } if (tport_tsend(tport, msg, irq->irq_tpn, IF_SIGCOMP_TPTAG_COMPARTMENT(irq->irq_cc) TPTAG_MTU(INT_MAX), TAG_END())) { irq->irq_agent->sa_stats->as_sent_msg++; irq->irq_agent->sa_stats->as_sent_response++; } } /** @internal Create timestamp header for response */ static int incoming_timestamp(nta_incoming_t *irq, msg_t *msg, sip_t *sip) { sip_timestamp_t ts[1]; su_time_t now = su_now(); char delay[32]; double diff = su_time_diff(now, irq->irq_received); snprintf(delay, sizeof delay, "%.06f", diff); *ts = *irq->irq_timestamp; ts->ts_delay = delay; return sip_add_dup(msg, sip, (sip_header_t *)ts); } enum { timer_max_retransmit = 30, timer_max_terminate = 100000, timer_max_timeout = 100 }; /** @internal Timer routine for the incoming request. */ static void _nta_incoming_timer(nta_agent_t *sa) { uint32_t now = sa->sa_millisec; nta_incoming_t *irq, *irq_next; size_t retransmitted = 0, timeout = 0, terminated = 0, destroyed = 0; size_t unconfirmed = sa->sa_in.inv_completed->q_length + sa->sa_in.preliminary->q_length; size_t unterminated = sa->sa_in.inv_confirmed->q_length + sa->sa_in.completed->q_length; size_t total = sa->sa_incoming->iht_used; incoming_queue_t rq[1]; incoming_queue_init(rq, 0); /* Handle retry queue */ while ((irq = sa->sa_in.re_list)) { if ((int32_t)(irq->irq_retry - now) > 0) break; if (retransmitted >= timer_max_retransmit) break; if (irq->irq_method == sip_method_invite && irq->irq_status >= 200) { /* Timer G */ assert(irq->irq_queue == sa->sa_in.inv_completed); retransmitted++; SU_DEBUG_5(("nta: timer %s fired, retransmitting %u reply\n", "G", irq->irq_status)); incoming_retransmit_reply(irq, irq->irq_tport); if (2U * irq->irq_interval < sa->sa_t2) incoming_set_timer(irq, 2U * irq->irq_interval); /* G */ else incoming_set_timer(irq, sa->sa_t2); /* G */ } else if (irq->irq_method == sip_method_invite && irq->irq_status >= 100) { if (irq->irq_queue == sa->sa_in.preliminary) { /* Timer P1 - PRACK timer */ retransmitted++; SU_DEBUG_5(("nta: timer %s fired, retransmitting %u reply\n", "P1", irq->irq_status)); incoming_retransmit_reply(irq, irq->irq_tport); incoming_set_timer(irq, 2 * irq->irq_interval); /* P1 */ } else { /* Retransmitting provisional responses */ SU_DEBUG_5(("nta: timer %s fired, retransmitting %u reply\n", "N2", irq->irq_status)); incoming_set_timer(irq, sa->sa_progress); retransmitted++; incoming_retransmit_reply(irq, irq->irq_tport); } } else { /* Timer N1 */ incoming_reset_timer(irq); if(irq->irq_extra_100) { SU_DEBUG_5(("nta: timer N1 fired, sending %u %s\n", SIP_100_TRYING)); nta_incoming_treply(irq, SIP_100_TRYING, TAG_END()); } else { SU_DEBUG_5(("nta: timer N1 fired, but avoided sending %u %s\n", SIP_100_TRYING)); } } } while ((irq = sa->sa_in.final_failed->q_head)) { incoming_remove(irq); irq->irq_final_failed = 0; /* Report error to application */ SU_DEBUG_5(("nta: sending final response failed, timeout %u response\n", irq->irq_status)); reliable_timeout(irq, 0); nta_incoming_treply(irq, SIP_500_INTERNAL_SERVER_ERROR, TAG_END()); if (!irq->irq_final_failed) /* We have taken care of the error... */ continue; if (irq->irq_destroyed) { incoming_free_queue(rq, irq); continue; } incoming_reset_timer(irq); irq->irq_confirmed = 1; irq->irq_terminated = 1; incoming_queue(sa->sa_in.terminated, irq); } /* Timeouts. * For each state the request is in, there is always a queue of its own */ while ((irq = sa->sa_in.preliminary->q_head)) { assert(irq->irq_status < 200); assert(irq->irq_timeout); if ((int32_t)(irq->irq_timeout - now) > 0) break; if (timeout >= timer_max_timeout) break; timeout++; /* Timer P2 - PRACK timer */ SU_DEBUG_5(("nta: timer %s fired, %s %u response\n", "P2", "timeout", irq->irq_status)); incoming_reset_timer(irq); irq->irq_timeout = 0; reliable_timeout(irq, 1); } while ((irq = sa->sa_in.inv_completed->q_head)) { assert(irq->irq_status >= 200); assert(irq->irq_timeout); assert(irq->irq_method == sip_method_invite); if ((int32_t)(irq->irq_timeout - now) > 0 || timeout >= timer_max_timeout || terminated >= timer_max_terminate) break; /* Timer H */ SU_DEBUG_5(("nta: timer %s fired, %s %u response\n", "H", "timeout and terminate", irq->irq_status)); irq->irq_confirmed = 1; irq->irq_terminated = 1; incoming_reset_timer(irq); if (!irq->irq_destroyed) { timeout++; incoming_queue(sa->sa_in.terminated, irq); /* report timeout error to user */ incoming_call_callback(irq, NULL, NULL); } else { timeout++; terminated++; incoming_free_queue(rq, irq); } } while ((irq = sa->sa_in.inv_confirmed->q_head)) { assert(irq->irq_timeout); assert(irq->irq_status >= 200); assert(irq->irq_method == sip_method_invite); if ((int32_t)(irq->irq_timeout - now) > 0 || terminated >= timer_max_terminate) break; /* Timer I */ SU_DEBUG_5(("nta: timer %s fired, %s %u response\n", "I", "terminate", irq->irq_status)); terminated++; irq->irq_terminated = 1; if (!irq->irq_destroyed) incoming_queue(sa->sa_in.terminated, irq); else incoming_free_queue(rq, irq); } while ((irq = sa->sa_in.completed->q_head)) { assert(irq->irq_status >= 200); assert(irq->irq_timeout); assert(irq->irq_method != sip_method_invite); if ((int32_t)(irq->irq_timeout - now) > 0 || terminated >= timer_max_terminate) break; /* Timer J */ SU_DEBUG_5(("nta: timer %s fired, %s %u response\n", "J", "terminate", irq->irq_status)); terminated++; irq->irq_terminated = 1; if (!irq->irq_destroyed) incoming_queue(sa->sa_in.terminated, irq); else incoming_free_queue(rq, irq); } for (irq = sa->sa_in.terminated->q_head; irq; irq = irq_next) { irq_next = irq->irq_next; if (irq->irq_destroyed) incoming_free_queue(rq, irq); } destroyed = incoming_mass_destroy(sa, rq); if (retransmitted || timeout || terminated || destroyed) SU_DEBUG_5(("nta_incoming_timer: " MOD_ZU"/"MOD_ZU" resent, " MOD_ZU"/"MOD_ZU" tout, " MOD_ZU"/"MOD_ZU" term, " MOD_ZU"/"MOD_ZU" free\n", retransmitted, unconfirmed, timeout, unconfirmed, terminated, unterminated, destroyed, total)); } /** Mass destroy server transactions */ su_inline size_t incoming_mass_destroy(nta_agent_t *sa, incoming_queue_t *q) { size_t destroyed = q->q_length; if (destroyed > 2 && *sa->sa_terminator) { su_msg_r m = SU_MSG_R_INIT; if (su_msg_create(m, su_clone_task(sa->sa_terminator), su_root_task(sa->sa_root), incoming_reclaim_queued, sizeof(incoming_queue_t)) == SU_SUCCESS) { incoming_queue_t *mq = su_msg_data(m)->a_incoming_queue; *mq = *q; if (su_msg_send(m) == SU_SUCCESS) q->q_length = 0; } } if (q->q_length > 0) incoming_reclaim_queued(NULL, NULL, (void *)q); return destroyed; } /* ====================================================================== */ /* 8) Client-side (outgoing) transactions */ #define HTABLE_HASH_ORQ(orq) ((orq)->orq_hash) HTABLE_BODIES_WITH(outgoing_htable, oht, nta_outgoing_t, HTABLE_HASH_ORQ, size_t, hash_value_t); static int outgoing_features(nta_agent_t *agent, nta_outgoing_t *orq, msg_t *msg, sip_t *sip, tagi_t *tags); static void outgoing_prepare_send(nta_outgoing_t *orq); static void outgoing_send_via(nta_outgoing_t *orq, tport_t *tp); static void outgoing_send(nta_outgoing_t *orq, int retransmit); static void outgoing_try_tcp_instead(nta_outgoing_t *orq); static void outgoing_try_udp_instead(nta_outgoing_t *orq, int timeout); static void outgoing_tport_error(nta_agent_t *agent, nta_outgoing_t *orq, tport_t *tp, msg_t *msg, int error); static void outgoing_print_tport_error(nta_outgoing_t *orq, int level, char *todo, tp_name_t const *, msg_t *, int error); static void outgoing_insert(nta_agent_t *sa, nta_outgoing_t *orq); static void outgoing_destroy(nta_outgoing_t *orq); su_inline int outgoing_is_queued(nta_outgoing_t const *orq); su_inline void outgoing_queue(outgoing_queue_t *queue, nta_outgoing_t *orq); su_inline void outgoing_remove(nta_outgoing_t *orq); su_inline void outgoing_set_timer(nta_outgoing_t *orq, uint32_t interval); static void outgoing_reset_timer(nta_outgoing_t *orq); static size_t outgoing_timer_dk(outgoing_queue_t *q, char const *timer, uint32_t now); static size_t outgoing_timer_bf(outgoing_queue_t *q, char const *timer, uint32_t now); static size_t outgoing_timer_c(outgoing_queue_t *q, char const *timer, uint32_t now); static void outgoing_ack(nta_outgoing_t *orq, sip_t *sip); static msg_t *outgoing_ackmsg(nta_outgoing_t *, sip_method_t, char const *, tag_type_t tag, tag_value_t value, ...); static void outgoing_retransmit(nta_outgoing_t *orq); static void outgoing_trying(nta_outgoing_t *orq); static void outgoing_timeout(nta_outgoing_t *orq, uint32_t now); static int outgoing_complete(nta_outgoing_t *orq); static void outgoing_terminate_invite(nta_outgoing_t *); static void outgoing_remove_fork(nta_outgoing_t *orq); static int outgoing_terminate(nta_outgoing_t *orq); static size_t outgoing_mass_destroy(nta_agent_t *sa, outgoing_queue_t *q); static void outgoing_estimate_delay(nta_outgoing_t *orq, sip_t *sip); static int outgoing_duplicate(nta_outgoing_t *orq, msg_t *msg, sip_t *sip); static int outgoing_reply(nta_outgoing_t *orq, int status, char const *phrase, int delayed); static int outgoing_default_cb(nta_outgoing_magic_t *magic, nta_outgoing_t *request, sip_t const *sip); #if HAVE_SOFIA_SRESOLV static void outgoing_resolve(nta_outgoing_t *orq, int explicit_transport, enum nta_res_order_e order); su_inline void outgoing_cancel_resolver(nta_outgoing_t *orq); su_inline void outgoing_destroy_resolver(nta_outgoing_t *orq); static int outgoing_other_destinations(nta_outgoing_t const *orq); static int outgoing_try_another(nta_outgoing_t *orq); #else #define outgoing_other_destinations(orq) (0) #define outgoing_try_another(orq) (0) #define outgoing_cancel_resolver(orq) ((void)0) #endif /** Create a default outgoing transaction. * * The default outgoing transaction is used when agent receives responses * not belonging to any transaction. * * @sa nta_leg_default(), nta_incoming_default(). */ nta_outgoing_t *nta_outgoing_default(nta_agent_t *agent, nta_response_f *callback, nta_outgoing_magic_t *magic) { nta_outgoing_t *orq; if (agent == NULL) return NULL; if (agent->sa_default_outgoing) return NULL; orq = su_zalloc(agent->sa_home, sizeof *orq); if (!orq) return NULL; orq->orq_agent = agent; orq->orq_callback = callback; orq->orq_magic = magic; orq->orq_method = sip_method_invalid; orq->orq_method_name = "*"; orq->orq_default = 1; orq->orq_stateless = 1; orq->orq_delay = UINT_MAX; return agent->sa_default_outgoing = orq; } /**Create an outgoing request and client transaction belonging to the leg. * * Create a request message and pass the request message to an outgoing * client transaction object. The request is sent to the @a route_url (if * non-NULL), default proxy (if defined by NTATAG_DEFAULT_PROXY()), or to * the address specified by @a request_uri. If no @a request_uri is * specified, it is taken from route-set target or from the @To header. * * When NTA receives response to the request, it invokes the @a callback * function. * * @param leg call leg object * @param callback callback function (may be @c NULL) * @param magic application context pointer * @param route_url optional URL used to route transaction requests * @param method method type * @param name method name * @param request_uri Request-URI * @param tag, value, ... list of tagged arguments * * @return * A pointer to a newly created outgoing transaction object if successful, * and NULL otherwise. * * @note If NTATAG_STATELESS(1) tag is given and the @a callback is NULL, * the transaction object is marked as destroyed from the beginning. In that * case, the function may return @code (nta_outgoing_t *)-1 @endcode if the * transaction is freed before returning from the function. * * @sa * nta_outgoing_mcreate(), nta_outgoing_tcancel(), nta_outgoing_destroy(). * * @TAGS * NTATAG_STATELESS(), NTATAG_DELAY_SENDING(), NTATAG_BRANCH_KEY(), * NTATAG_ACK_BRANCH(), NTATAG_DEFAULT_PROXY(), NTATAG_PASS_100(), * NTATAG_USE_TIMESTAMP(), NTATAG_USER_VIA(), TPTAG_IDENT(), NTATAG_TPORT(). All * SIP tags from can be used to manipulate the request message. * SIP tags after SIPTAG_END() are ignored, however. */ nta_outgoing_t *nta_outgoing_tcreate(nta_leg_t *leg, nta_response_f *callback, nta_outgoing_magic_t *magic, url_string_t const *route_url, sip_method_t method, char const *name, url_string_t const *request_uri, tag_type_t tag, tag_value_t value, ...) { nta_agent_t *agent; msg_t *msg; sip_t *sip; nta_outgoing_t *orq = NULL; ta_list ta; tagi_t const *tagi; if (leg == NULL) return NULL; agent = leg->leg_agent; msg = nta_msg_create(agent, 0); sip = sip_object(msg); if (route_url == NULL) route_url = (url_string_t *)agent->sa_default_proxy; ta_start(ta, tag, value); tagi = ta_args(ta); if (sip_add_tagis(msg, sip, &tagi) < 0) { if (tagi && tagi->t_tag) { tag_type_t t = tagi->t_tag; SU_DEBUG_5(("%s(): bad tag %s::%s\n", __func__, t->tt_ns ? t->tt_ns : "", t->tt_name ? t->tt_name : "")); } } else if (route_url == NULL && leg->leg_route && leg->leg_loose_route && !(route_url = (url_string_t *)leg->leg_route->r_url)) ; else if (nta_msg_request_complete(msg, leg, method, name, request_uri) < 0) ; else orq = outgoing_create(agent, callback, magic, route_url, NULL, msg, ta_tags(ta)); ta_end(ta); if (!orq) msg_destroy(msg); return orq; } /**Create an outgoing client transaction. * * Create an outgoing transaction object. The request message is passed to * the transaction object, which sends the request to the network. The * request is sent to the @a route_url (if non-NULL), default proxy (if * defined by NTATAG_DEFAULT_PROXY()), or to the address specified by @a * request_uri. If no @a request_uri is specified, it is taken from * route-set target or from the @To header. * * When NTA receives response to the request, it invokes the @a callback * function. * * @param agent NTA agent object * @param callback callback function (may be @c NULL) * @param magic application context pointer * @param route_url optional URL used to route transaction requests * @param msg request message * @param tag, value, ... tagged parameter list * * @return * Returns a pointer to newly created outgoing transaction object if * successful, and NULL otherwise. * * @note The caller is responsible for destroying the request message @a msg * upon failure. * * @note If NTATAG_STATELESS(1) tag is given and the @a callback is NULL, * the transaction object is marked as destroyed from the beginning. In that * case, the function may return @code (nta_outgoing_t *)-1 @endcode if the * transaction is freed before returning from the function. * * @sa * nta_outgoing_tcreate(), nta_outgoing_tcancel(), nta_outgoing_destroy(). * * @TAGS * NTATAG_STATELESS(), NTATAG_DELAY_SENDING(), NTATAG_BRANCH_KEY(), * NTATAG_ACK_BRANCH(), NTATAG_DEFAULT_PROXY(), NTATAG_PASS_100(), * NTATAG_USE_TIMESTAMP(), NTATAG_USER_VIA(), TPTAG_IDENT(), NTATAG_TPORT(). All * SIP tags from can be used to manipulate the request message. * SIP tags after SIPTAG_END() are ignored, however. */ nta_outgoing_t *nta_outgoing_mcreate(nta_agent_t *agent, nta_response_f *callback, nta_outgoing_magic_t *magic, url_string_t const *route_url, msg_t *msg, tag_type_t tag, tag_value_t value, ...) { nta_outgoing_t *orq = NULL; int cleanup = 0; if (msg == NONE) msg = nta_msg_create(agent, 0), cleanup = 1; if (msg && agent) { ta_list ta; ta_start(ta, tag, value); if (sip_add_tl(msg, sip_object(msg), ta_tags(ta)) >= 0) orq = outgoing_create(agent, callback, magic, route_url, NULL, msg, ta_tags(ta)); ta_end(ta); } if (!orq && cleanup) msg_destroy(msg); return orq; } /** Cancel the request. */ int nta_outgoing_cancel(nta_outgoing_t *orq) { nta_outgoing_t *cancel = nta_outgoing_tcancel(orq, NULL, NULL, TAG_NULL()); return (cancel != NULL) - 1; } /** Cancel the request. * * Initiate a cancel transaction for client transaction @a orq. * * @param orq client transaction to cancel * @param callback callback function (may be @c NULL) * @param magic application context pointer * @param tag, value, ... list of extra arguments * * @note The function may return @code (nta_outgoing_t *)-1 @endcode (NONE) * if callback is NULL. * * @TAGS * NTATAG_CANCEL_2534(), NTATAG_CANCEL_408() and all the tags that are * accepted by nta_outgoing_tcreate(). * * If NTATAG_CANCEL_408(1) or NTATAG_CANCEL_2543(1) is given, the stack * generates a 487 response to the request internally. If * NTATAG_CANCEL_408(1) is given, no CANCEL request is actually sent. * * @note * nta_outgoing_tcancel() refuses to send a CANCEL request for non-INVITE * requests. */ nta_outgoing_t *nta_outgoing_tcancel(nta_outgoing_t *orq, nta_response_f *callback, nta_outgoing_magic_t *magic, tag_type_t tag, tag_value_t value, ...) { msg_t *msg; int cancel_2543, cancel_408; ta_list ta; int delay_sending; if (orq == NULL || orq == NONE) return NULL; if (orq->orq_destroyed) { SU_DEBUG_3(("%s: trying to cancel destroyed request\n", __func__)); return NULL; } if (orq->orq_method != sip_method_invite) { SU_DEBUG_3(("%s: trying to cancel non-INVITE request\n", __func__)); return NULL; } if (orq->orq_forking) orq = orq->orq_forking; if (orq->orq_status >= 200 /* && orq->orq_method != sip_method_invite ... !multicast */) { SU_DEBUG_3(("%s: trying to cancel completed request\n", __func__)); return NULL; } if (orq->orq_canceled) { SU_DEBUG_3(("%s: trying to cancel cancelled request\n", __func__)); return NULL; } orq->orq_canceled = 1; #if HAVE_SOFIA_SRESOLV if (!orq->orq_resolved) { outgoing_destroy_resolver(orq); outgoing_reply(orq, SIP_487_REQUEST_CANCELLED, 1); return NULL; /* XXX - Does anyone care about reply? */ } #endif cancel_408 = 0; /* Don't really CANCEL, this is timeout. */ cancel_2543 = orq->orq_agent->sa_cancel_2543; /* CANCEL may be sent only after a provisional response has been received. */ delay_sending = orq->orq_status < 100; ta_start(ta, tag, value); tl_gets(ta_args(ta), NTATAG_CANCEL_408_REF(cancel_408), NTATAG_CANCEL_2543_REF(cancel_2543), TAG_END()); if (!cancel_408) msg = outgoing_ackmsg(orq, SIP_METHOD_CANCEL, ta_tags(ta)); else msg = NULL; ta_end(ta); if ((cancel_2543 || cancel_408) && !orq->orq_stateless) outgoing_reply(orq, SIP_487_REQUEST_CANCELLED, 1); if (msg) { nta_outgoing_t *cancel; if (cancel_2543) /* Follow RFC 2543 semantics for CANCEL */ delay_sending = 0; cancel = outgoing_create(orq->orq_agent, callback, magic, NULL, orq->orq_tpn, msg, NTATAG_BRANCH_KEY(orq->orq_branch), NTATAG_DELAY_SENDING(delay_sending), NTATAG_USER_VIA(1), TAG_END()); if (delay_sending) orq->orq_cancel = cancel; if (cancel) { if (!delay_sending) outgoing_complete(orq); return cancel; } msg_destroy(msg); } return NULL; } /**Bind callback and application context to a client transaction. * * @param orq outgoing client transaction * @param callback callback function (may be NULL) * @param magic application context pointer * (given as argument to @a callback) * * @NEW_1_12_9 */ int nta_outgoing_bind(nta_outgoing_t *orq, nta_response_f *callback, nta_outgoing_magic_t *magic) { if (orq && !orq->orq_destroyed) { if (callback == NULL) callback = outgoing_default_cb; orq->orq_callback = callback; orq->orq_magic = magic; return 0; } return -1; } /**Get application context bound to a client transaction. * * @param orq outgoing client transaction * @param callback callback function (may be NULL) * * Return the application context bound to a client transaction. If the @a * callback function pointer is given, return application context only if * the callback matches with the callback bound to the client transaction. * * @NEW_1_12_11 */ nta_outgoing_magic_t * nta_outgoing_magic(nta_outgoing_t const *orq, nta_response_f *callback) { if (orq && (callback == NULL || callback == orq->orq_callback)) return orq->orq_magic; else return NULL; } /** * Destroy a request object. * * @note * This function does not actually free the object, but marks it as * disposable. The object is freed after a timeout. */ void nta_outgoing_destroy(nta_outgoing_t *orq) { if (orq == NULL || orq == NONE) return; if (orq->orq_destroyed) { SU_DEBUG_1(("%s(%p): %s\n", "nta_outgoing_destroy", (void *)orq, "already destroyed")); return; } outgoing_destroy(orq); } /** Return the request URI */ url_t const *nta_outgoing_request_uri(nta_outgoing_t const *orq) { return orq != NULL && orq != NONE ? orq->orq_url : NULL; } /** Return the URI used to route the request */ url_t const *nta_outgoing_route_uri(nta_outgoing_t const *orq) { return orq != NULL && orq != NONE ? orq->orq_route : NULL; } /** Return method of the client transaction */ sip_method_t nta_outgoing_method(nta_outgoing_t const *orq) { return orq != NULL && orq != NONE ? orq->orq_method : sip_method_invalid; } /** Return method name of the client transaction */ char const *nta_outgoing_method_name(nta_outgoing_t const *orq) { return orq != NULL && orq != NONE ? orq->orq_method_name : NULL; } /** Get sequence number of a client transaction. */ uint32_t nta_outgoing_cseq(nta_outgoing_t const *orq) { return orq != NULL && orq != NONE && orq->orq_cseq ? orq->orq_cseq->cs_seq : 0; } /** * Get the status code of a client transaction. */ int nta_outgoing_status(nta_outgoing_t const *orq) { /* Return 500 Internal server error for invalid handles. */ return orq != NULL && orq != NONE ? orq->orq_status : 500; } /** Get the RTT delay measured using @Timestamp header. */ unsigned nta_outgoing_delay(nta_outgoing_t const *orq) { return orq != NULL && orq != NONE ? orq->orq_delay : UINT_MAX; } /** Get the branch parameter. @NEW_1_12_7. */ char const *nta_outgoing_branch(nta_outgoing_t const *orq) { return orq != NULL && orq != NONE && orq->orq_branch ? orq->orq_branch + strlen("branch=") : NULL; } /**Get reference to response message. * * Retrieve the latest incoming response message to the outgoing * transaction. Note that the message is not copied, but a new reference to * it is created instead. * * @param orq outgoing transaction handle * * @retval * A pointer to response message is returned, or NULL if no response message * has been received. */ msg_t *nta_outgoing_getresponse(nta_outgoing_t *orq) { if (orq != NULL && orq != NONE) return msg_ref(orq->orq_response); else return NULL; } /**Get request message. * * Retrieves the request message sent to the network. Note that the request * message is @b not copied, but a new reference to it is created. * * @retval * A pointer to the request message is returned, or NULL if an error * occurred. */ msg_t *nta_outgoing_getrequest(nta_outgoing_t *orq) { if (orq != NULL && orq != NONE) return msg_ref(orq->orq_request); else return NULL; } /**Create an outgoing request. * * Create an outgoing transaction object and send the request to the * network. The request is sent to the @a route_url (if non-NULL), default * proxy (if defined by NTATAG_DEFAULT_PROXY()), or to the address specified * by @a sip->sip_request->rq_url. * * When NTA receives response to the request, it invokes the @a callback * function. * * @param agent nta agent object * @param callback callback function (may be @c NULL) * @param magic application context pointer * @param route_url optional URL used to route transaction requests * @param msg request message * @param tpn (optional) transport name * @param msg request message to * @param tag, value, ... tagged arguments * * @return * Returns a pointer to newly created outgoing transaction object if * successful, and NULL otherwise. * * @note If NTATAG_STATELESS(1) tag is given and the @a callback is NULL, * the transaction object is marked as destroyed from the beginning. In that * case, the function may return @code (nta_outgoing_t *)-1 @endcode if the * transaction is freed before returning from the function. * * @TAG NTATAG_TPORT must point to an existing transport object for * 'agent' (the passed tport is otherwise ignored). * * @sa * nta_outgoing_tcreate(), nta_outgoing_tcancel(), nta_outgoing_destroy(). */ nta_outgoing_t *outgoing_create(nta_agent_t *agent, nta_response_f *callback, nta_outgoing_magic_t *magic, url_string_t const *route_url, tp_name_t const *tpn, msg_t *msg, tag_type_t tag, tag_value_t value, ...) { nta_outgoing_t *orq; sip_t *sip; su_home_t *home; char const *comp = NONE; char const *branch = NONE; char const *ack_branch = NONE; char const *tp_ident; int delay_sending = 0, sigcomp_zap = 0; int pass_100 = agent->sa_pass_100, use_timestamp = agent->sa_timestamp; enum nta_res_order_e res_order = agent->sa_res_order; struct sigcomp_compartment *cc = NULL; ta_list ta; char const *scheme = NULL; char const *port = NULL; int invalid, resolved = 0, stateless = 0, user_via = agent->sa_user_via; int invite_100rel = agent->sa_invite_100rel; int explicit_transport = 1; tagi_t const *t; tport_t *override_tport = NULL; if (!agent->sa_tport_ip6) res_order = nta_res_ip4_only; else if (!agent->sa_tport_ip4) res_order = nta_res_ip6_only; if (!callback) callback = outgoing_default_cb; if (!route_url) route_url = (url_string_t *)agent->sa_default_proxy; sip = sip_object(msg); home = msg_home(msg); if (!sip->sip_request || sip_complete_message(msg) < 0) { SU_DEBUG_3(("nta: outgoing_create: incomplete request\n")); return NULL; } if (!route_url && !tpn && sip->sip_route && sip->sip_route->r_url->url_params && url_param(sip->sip_route->r_url->url_params, "lr", NULL, 0)) route_url = (url_string_t *)sip->sip_route->r_url; if (!(orq = su_zalloc(agent->sa_home, sizeof(*orq)))) return NULL; tp_ident = tpn ? tpn->tpn_ident : NULL; ta_start(ta, tag, value); /* tl_gets() is a bit too slow here... */ for (t = ta_args(ta); t; t = tl_next(t)) { tag_type_t tt = t->t_tag; if (ntatag_stateless == tt) stateless = t->t_value != 0; else if (ntatag_delay_sending == tt) delay_sending = t->t_value != 0; else if (ntatag_branch_key == tt) branch = (void *)t->t_value; else if (ntatag_pass_100 == tt) pass_100 = t->t_value != 0; else if (ntatag_use_timestamp == tt) use_timestamp = t->t_value != 0; else if (ntatag_user_via == tt) user_via = t->t_value != 0; else if (ntatag_ack_branch == tt) ack_branch = (void *)t->t_value; else if (ntatag_default_proxy == tt) route_url = (void *)t->t_value; else if (tptag_ident == tt) tp_ident = (void *)t->t_value; else if (ntatag_comp == tt) comp = (char const *)t->t_value; else if (ntatag_sigcomp_close == tt) sigcomp_zap = t->t_value != 0; else if (tptag_compartment == tt) cc = (void *)t->t_value; else if (ntatag_tport == tt) { override_tport = (tport_t *)t->t_value; } else if (ntatag_rel100 == tt) { invite_100rel = t->t_value != 0; } } orq->orq_agent = agent; orq->orq_callback = callback; orq->orq_magic = magic; orq->orq_method = sip->sip_request->rq_method; orq->orq_method_name = sip->sip_request->rq_method_name; orq->orq_cseq = sip->sip_cseq; orq->orq_to = sip->sip_to; orq->orq_from = sip->sip_from; orq->orq_call_id = sip->sip_call_id; orq->orq_tags = tl_afilter(home, tport_tags, ta_args(ta)); orq->orq_delayed = delay_sending != 0; orq->orq_pass_100 = pass_100 != 0; orq->orq_sigcomp_zap = sigcomp_zap; orq->orq_sigcomp_new = comp != NONE && comp != NULL; orq->orq_timestamp = use_timestamp; orq->orq_delay = UINT_MAX; orq->orq_stateless = stateless != 0; orq->orq_user_via = user_via != 0 && sip->sip_via; orq->orq_100rel = invite_100rel; orq->orq_uas = !stateless && agent->sa_is_a_uas; if (cc) orq->orq_cc = nta_compartment_ref(cc); /* Add supported features */ outgoing_features(agent, orq, msg, sip, ta_args(ta)); ta_end(ta); /* select the tport to use for the outgoing message */ if (override_tport) { /* note: no ref taken to the tport as its only used once here */ if (tport_is_secondary(override_tport)) { tpn = tport_name(override_tport); orq->orq_user_tport = 1; } } if (tpn) { /* CANCEL or ACK to [3456]XX */ invalid = tport_name_dup(home, orq->orq_tpn, tpn); #if 0 /* XXX - HAVE_SOFIA_SRESOLV */ /* We send ACK or CANCEL only if original request was really sent */ assert(tport_name_is_resolved(orq->orq_tpn)); #endif resolved = tport_name_is_resolved(orq->orq_tpn); orq->orq_url = url_hdup(home, sip->sip_request->rq_url); } else if (route_url && !orq->orq_user_tport) { invalid = nta_tpn_by_url(home, orq->orq_tpn, &scheme, &port, route_url); if (invalid >= 0) { explicit_transport = invalid > 0; if (override_tport) { /* Use transport protocol name from transport */ if (strcmp(orq->orq_tpn->tpn_proto, "*") == 0) orq->orq_tpn->tpn_proto = tport_name(override_tport)->tpn_proto; } resolved = tport_name_is_resolved(orq->orq_tpn); orq->orq_url = url_hdup(home, sip->sip_request->rq_url); if (route_url != (url_string_t *)agent->sa_default_proxy) orq->orq_route = url_hdup(home, route_url->us_url); } } else { invalid = nta_tpn_by_url(home, orq->orq_tpn, &scheme, &port, (url_string_t *)sip->sip_request->rq_url); if (invalid >= 0) { explicit_transport = invalid > 0; resolved = tport_name_is_resolved(orq->orq_tpn); msg_fragment_clear(sip->sip_request->rq_common); } orq->orq_url = url_hdup(home, sip->sip_request->rq_url); } if (!override_tport) orq->orq_tpn->tpn_ident = tp_ident; else orq->orq_tpn->tpn_ident = tport_name(override_tport)->tpn_ident; if (comp == NULL) orq->orq_tpn->tpn_comp = comp; if (orq->orq_user_via && su_strmatch(orq->orq_tpn->tpn_proto, "*")) { char const *proto = sip_via_transport(sip->sip_via); if (proto) orq->orq_tpn->tpn_proto = proto; } if (branch && branch != NONE) { if (su_casenmatch(branch, "branch=", 7)) branch = su_strdup(home, branch); else branch = su_sprintf(home, "branch=%s", branch); } else if (orq->orq_user_via && sip->sip_via->v_branch) branch = su_sprintf(home, "branch=%s", sip->sip_via->v_branch); else if (stateless) branch = stateless_branch(agent, msg, sip, orq->orq_tpn); else branch = stateful_branch(home, agent); orq->orq_branch = branch; orq->orq_via_branch = branch; if (orq->orq_method == sip_method_ack) { /* Find the original INVITE which we are ACKing */ if (ack_branch != NULL && ack_branch != NONE) { if (su_casenmatch(ack_branch, "branch=", 7)) orq->orq_branch = su_strdup(home, ack_branch); else orq->orq_branch = su_sprintf(home, "branch=%s", ack_branch); } else if (orq->orq_uas) { /* * ACK redirects further 2XX messages to it. * * Use orq_branch from INVITE, but put a different branch in topmost Via. */ nta_outgoing_t *invite = outgoing_find(agent, msg, sip, NULL); if (invite) { sip_t const *inv = sip_object(invite->orq_request); orq->orq_branch = su_strdup(home, invite->orq_branch); /* @RFC3261 section 13.2.2.4 - * The ACK MUST contain the same credentials as the INVITE. */ if (!sip->sip_proxy_authorization && !sip->sip_authorization) { if (inv->sip_proxy_authorization) sip_add_dup(msg, sip, (void *)inv->sip_proxy_authorization); if (inv->sip_authorization) sip_add_dup(msg, sip, (void *)inv->sip_authorization); } } else { SU_DEBUG_1(("outgoing_create: ACK without INVITE\n")); assert(!"INVITE found for ACK"); } } } #if HAVE_SOFIA_SRESOLV if (!resolved) orq->orq_tpn->tpn_port = port; orq->orq_resolved = resolved; #else orq->orq_resolved = resolved = 1; #endif orq->orq_sips = su_casematch(scheme, "sips"); if (invalid < 0 || !orq->orq_branch || msg_serialize(msg, (void *)sip) < 0) { SU_DEBUG_3(("nta outgoing create: %s\n", invalid < 0 ? "invalid URI" : !orq->orq_branch ? "no branch" : "invalid message")); outgoing_free(orq); return NULL; } /* Now we are committed in sending the transaction */ orq->orq_request = msg; agent->sa_stats->as_client_tr++; orq->orq_hash = NTA_HASH(sip->sip_call_id, sip->sip_cseq->cs_seq); if (orq->orq_user_tport) outgoing_send_via(orq, override_tport); else if (resolved) outgoing_prepare_send(orq); #if HAVE_SOFIA_SRESOLV else outgoing_resolve(orq, explicit_transport, res_order); #endif if (stateless && orq->orq_status >= 200 && callback == outgoing_default_cb) { void *retval; if (orq->orq_status < 300) retval = (void *)-1; /* NONE */ else retval = NULL, orq->orq_request = NULL; outgoing_free(orq); return retval; } assert(orq->orq_queue); outgoing_insert(agent, orq); return orq; } /** Prepare sending a request */ static void outgoing_prepare_send(nta_outgoing_t *orq) { nta_agent_t *sa = orq->orq_agent; tport_t *tp; tp_name_t *tpn = orq->orq_tpn; /* Select transport by scheme */ if (orq->orq_sips && strcmp(tpn->tpn_proto, "*") == 0) tpn->tpn_proto = "tls"; if (!tpn->tpn_port) tpn->tpn_port = ""; tp = tport_by_name(sa->sa_tports, tpn); if (tpn->tpn_port[0] == '\0') { if (orq->orq_sips || tport_has_tls(tp)) tpn->tpn_port = "5061"; else tpn->tpn_port = "5060"; } if (tp) { outgoing_send_via(orq, tp); } else if (orq->orq_sips) { SU_DEBUG_3(("nta outgoing create: no secure transport\n")); outgoing_reply(orq, SIP_416_UNSUPPORTED_URI, 1); } else { SU_DEBUG_3(("nta outgoing create: no transport protocol\n")); outgoing_reply(orq, 503, "No transport", 1); } } /** Send request using given transport */ static void outgoing_send_via(nta_outgoing_t *orq, tport_t *tp) { tport_t *old_tp = orq->orq_tport; orq->orq_tport = tport_ref(tp); if (orq->orq_pending && tp != old_tp) { tport_release(old_tp, orq->orq_pending, orq->orq_request, NULL, orq, 0); orq->orq_pending = 0; } if (old_tp) tport_unref(old_tp); if (outgoing_insert_via(orq, agent_tport_via(tp)) < 0) { SU_DEBUG_3(("nta outgoing create: cannot insert Via line\n")); outgoing_reply(orq, 503, "Cannot insert Via", 1); return; } #if HAVE_SOFIA_SMIME { sm_object_t *smime = sa->sa_smime; sip_t *sip = sip_object(orq->orq_request); if (sa->sa_smime && (sip->sip_request->rq_method == sip_method_invite || sip->sip_request->rq_method == sip_method_message)) { msg_prepare(orq->orq_request); if (sm_encode_message(smime, msg, sip, SM_ID_NULL) < 0) { outgoing_tport_error(sa, orq, NULL, orq->orq_request, su_errno()); return; } } } #endif orq->orq_prepared = 1; if (orq->orq_delayed) { SU_DEBUG_5(("nta: delayed sending %s (%u)\n", orq->orq_method_name, orq->orq_cseq->cs_seq)); outgoing_queue(orq->orq_agent->sa_out.delayed, orq); return; } outgoing_send(orq, 0); } /** Send a request */ static void outgoing_send(nta_outgoing_t *orq, int retransmit) { int err; tp_name_t const *tpn = orq->orq_tpn; msg_t *msg = orq->orq_request; nta_agent_t *agent = orq->orq_agent; tport_t *tp; int once = 0; su_time_t now = su_now(); tag_type_t tag = tag_skip; tag_value_t value = 0; struct sigcomp_compartment *cc; cc = NULL; /* tport can be NULL if we are just switching network */ if (orq->orq_tport == NULL) { outgoing_tport_error(agent, orq, NULL, orq->orq_request, ENETRESET); return; } if (orq->orq_user_tport && !tport_is_clear_to_send(orq->orq_tport)) { outgoing_tport_error(agent, orq, NULL, orq->orq_request, EPIPE); return; } if (!retransmit) orq->orq_sent = now; if (orq->orq_timestamp) { sip_t *sip = sip_object(msg); sip_timestamp_t *ts = sip_timestamp_format(msg_home(msg), "%lu.%06lu", now.tv_sec, now.tv_usec); if (ts) { if (sip->sip_timestamp) msg_header_remove(msg, (msg_pub_t *)sip, (msg_header_t *)sip->sip_timestamp); msg_header_insert(msg, (msg_pub_t *)sip, (msg_header_t *)ts); } } for (;;) { if (tpn->tpn_comp == NULL) { /* xyzzy */ } else if (orq->orq_cc) { cc = orq->orq_cc, orq->orq_cc = NULL; } else { cc = agent_compression_compartment(agent, orq->orq_tport, tpn, orq->orq_sigcomp_new); } if (orq->orq_try_udp_instead) tag = tptag_mtu, value = 65535; if (orq->orq_pending) { tport_release(orq->orq_tport, orq->orq_pending, orq->orq_request, NULL, orq, 0); orq->orq_pending = 0; } tp = tport_tsend(orq->orq_tport, msg, tpn, tag, value, IF_SIGCOMP_TPTAG_COMPARTMENT(cc) TAG_NEXT(orq->orq_tags)); if (tp) break; err = msg_errno(orq->orq_request); if (cc) nta_compartment_decref(&cc); if (orq->orq_user_tport) /* No retries */; /* RFC3261, 18.1.1 */ else if (err == EMSGSIZE && !orq->orq_try_tcp_instead) { if (su_casematch(tpn->tpn_proto, "udp") || su_casematch(tpn->tpn_proto, "*")) { outgoing_try_tcp_instead(orq); continue; } } else if (err == ECONNREFUSED && orq->orq_try_tcp_instead) { if (su_casematch(tpn->tpn_proto, "tcp") && msg_size(msg) <= 65535) { outgoing_try_udp_instead(orq, 0); continue; } } else if (err == EPIPE) { /* Connection was closed */ if (!once++) { orq->orq_retries++; continue; } } outgoing_tport_error(agent, orq, NULL, orq->orq_request, err); return; } agent->sa_stats->as_sent_msg++; agent->sa_stats->as_sent_request++; if (retransmit) agent->sa_stats->as_retry_request++; SU_DEBUG_5(("nta: %ssent %s (%u) to " TPN_FORMAT "\n", retransmit ? "re" : "", orq->orq_method_name, orq->orq_cseq->cs_seq, TPN_ARGS(tpn))); if (cc) { if (orq->orq_cc) nta_compartment_decref(&orq->orq_cc); } if (orq->orq_pending) { assert(orq->orq_tport); tport_release(orq->orq_tport, orq->orq_pending, orq->orq_request, NULL, orq, 0); orq->orq_pending = 0; } if (orq->orq_stateless) { outgoing_reply(orq, 202, NULL, 202); return; } if (orq->orq_method != sip_method_ack) { orq->orq_pending = tport_pend(tp, orq->orq_request, outgoing_tport_error, orq); if (orq->orq_pending < 0) orq->orq_pending = 0; } if (tp != orq->orq_tport) { tport_decref(&orq->orq_tport); orq->orq_tport = tport_ref(tp); } orq->orq_reliable = tport_is_reliable(tp); if (retransmit) return; outgoing_trying(orq); /* Timer B / F */ if (orq->orq_method == sip_method_ack) ; else if (!orq->orq_reliable) outgoing_set_timer(orq, agent->sa_t1); /* Timer A/E */ else if (orq->orq_try_tcp_instead && !tport_is_connected(tp)) outgoing_set_timer(orq, agent->sa_t4); /* Timer N3 */ } static void outgoing_try_tcp_instead(nta_outgoing_t *orq) { tport_t *tp; tp_name_t tpn[1]; assert(orq->orq_pending == 0); *tpn = *orq->orq_tpn; tpn->tpn_proto = "tcp"; orq->orq_try_tcp_instead = 1; tp = tport_by_name(orq->orq_agent->sa_tports, tpn); if (tp && tp != orq->orq_tport) { sip_t *sip = sip_object(orq->orq_request); msg_fragment_clear_chain((msg_header_t *)sip->sip_via); sip->sip_via->v_protocol = sip_transport_tcp; SU_DEBUG_5(("nta: %s (%u) too large for UDP, trying TCP\n", orq->orq_method_name, orq->orq_cseq->cs_seq)); orq->orq_tpn->tpn_proto = "tcp"; tport_decref(&orq->orq_tport); orq->orq_tport = tport_ref(tp); return; } /* No TCP - try again with UDP without SIP MTU limit */ tpn->tpn_proto = "udp"; orq->orq_try_udp_instead = 1; tp = tport_by_name(orq->orq_agent->sa_tports, tpn); if (tp && tp != orq->orq_tport) { SU_DEBUG_5(("nta: %s (%u) exceed normal UDP size limit\n", orq->orq_method_name, orq->orq_cseq->cs_seq)); tport_decref(&orq->orq_tport); orq->orq_tport = tport_ref(tp); } } static void outgoing_try_udp_instead(nta_outgoing_t *orq, int timeout) { tport_t *tp; tp_name_t tpn[1]; if (orq->orq_pending) { tport_release(orq->orq_tport, orq->orq_pending, orq->orq_request, NULL, orq, 0); orq->orq_pending = 0; } *tpn = *orq->orq_tpn; tpn->tpn_proto = "udp"; orq->orq_try_udp_instead = 1; tp = tport_by_name(orq->orq_agent->sa_tports, tpn); if (tp && tp != orq->orq_tport) { sip_t *sip = sip_object(orq->orq_request); msg_fragment_clear_chain((msg_header_t *)sip->sip_via); sip->sip_via->v_protocol = sip_transport_udp; SU_DEBUG_5(("nta: %s (%u) TCP %s, trying UDP\n", orq->orq_method_name, orq->orq_cseq->cs_seq, timeout ? "times out" : "refused")); orq->orq_tpn->tpn_proto = "udp"; tport_decref(&orq->orq_tport); orq->orq_tport = tport_ref(tp); } } /** @internal Report transport errors. */ void outgoing_tport_error(nta_agent_t *agent, nta_outgoing_t *orq, tport_t *tp, msg_t *msg, int error) { tp_name_t const *tpn = tp ? tport_name(tp) : orq->orq_tpn; if (orq->orq_pending) { assert(orq->orq_tport); tport_release(orq->orq_tport, orq->orq_pending, orq->orq_request, NULL, orq, 0); orq->orq_pending = 0; } if (error == EPIPE && orq->orq_retries++ == 0) { /* XXX - we should retry only if the transport is not newly created */ outgoing_print_tport_error(orq, 5, "retrying once after ", tpn, msg, error); outgoing_send(orq, 1); return; } else if (error == ECONNREFUSED && orq->orq_try_tcp_instead) { /* RFC3261, 18.1.1 */ if (su_casematch(tpn->tpn_proto, "tcp") && msg_size(msg) <= 65535) { outgoing_print_tport_error(orq, 5, "retrying with UDP after ", tpn, msg, error); outgoing_try_udp_instead(orq, 0); outgoing_remove(orq); /* Reset state - this is no resend! */ outgoing_send(orq, 0); /* Send */ return; } } if (outgoing_other_destinations(orq)) { outgoing_print_tport_error(orq, 5, "trying alternative server after ", tpn, msg, error); outgoing_try_another(orq); return; } outgoing_print_tport_error(orq, 3, "", tpn, msg, error); outgoing_reply(orq, SIP_503_SERVICE_UNAVAILABLE, 0); } static void outgoing_print_tport_error(nta_outgoing_t *orq, int level, char *todo, tp_name_t const *tpn, msg_t *msg, int error) { su_sockaddr_t const *su = msg_addr(msg); char addr[SU_ADDRSIZE]; su_llog(nta_log, level, "nta: %s (%u): %s%s (%u) with %s/[%s]:%u\n", orq->orq_method_name, orq->orq_cseq->cs_seq, todo, su_strerror(error), error, tpn->tpn_proto, su_inet_ntop(su->su_family, SU_ADDR(su), addr, sizeof(addr)), htons(su->su_port)); } /**@internal * Add features supported. */ static int outgoing_features(nta_agent_t *agent, nta_outgoing_t *orq, msg_t *msg, sip_t *sip, tagi_t *tags) { char const *supported[8]; int i; if (orq->orq_method != sip_method_invite) /* fast path for now */ return 0; supported[i = 0] = NULL; if (orq->orq_method == sip_method_invite) { int require_100rel = sip_has_feature(sip->sip_require, "100rel"); if (require_100rel) { orq->orq_must_100rel = 1; orq->orq_100rel = 1; } else if (sip_has_feature(sip->sip_supported, "100rel")) { orq->orq_100rel = 1; } else if (orq->orq_100rel) { supported[i++] = "100rel"; } } if (i) { supported[i] = NULL; if (sip->sip_supported) { su_home_t *home = msg_home(msg); return msg_list_append_items(home, sip->sip_supported, supported); } else { sip_supported_t s[1]; sip_supported_init(s); s->k_items = supported; return sip_add_dup(msg, sip, (sip_header_t *)s); } } return 0; } /**@internal * Insert outgoing request to agent hash table */ static void outgoing_insert(nta_agent_t *agent, nta_outgoing_t *orq) { if (outgoing_htable_is_full(agent->sa_outgoing)) outgoing_htable_resize(agent->sa_home, agent->sa_outgoing, 0); outgoing_htable_insert(agent->sa_outgoing, orq); orq->orq_inserted = 1; } /** @internal * Initialize a queue for outgoing transactions. */ static void outgoing_queue_init(outgoing_queue_t *queue, unsigned timeout) { memset(queue, 0, sizeof *queue); queue->q_tail = &queue->q_head; queue->q_timeout = timeout; } /** Change the timeout value of a queue */ static void outgoing_queue_adjust(nta_agent_t *sa, outgoing_queue_t *queue, unsigned timeout) { nta_outgoing_t *orq; uint32_t latest; if (timeout >= queue->q_timeout || !queue->q_head) { queue->q_timeout = timeout; return; } latest = set_timeout(sa, queue->q_timeout = timeout); for (orq = queue->q_head; orq; orq = orq->orq_next) { if (orq->orq_timeout == 0 || (int32_t)(orq->orq_timeout - latest) > 0) orq->orq_timeout = latest; } } /** @internal * Test if an outgoing transaction is in a queue. */ su_inline int outgoing_is_queued(nta_outgoing_t const *orq) { return orq && orq->orq_queue; } /** @internal * Insert an outgoing transaction into a queue. * * Insert a client transaction into a queue and set the corresponding * timeout at the same time. */ static void outgoing_queue(outgoing_queue_t *queue, nta_outgoing_t *orq) { if (orq->orq_queue == queue) { assert(queue->q_timeout == 0); return; } assert(!orq->orq_forked); if (outgoing_is_queued(orq)) outgoing_remove(orq); orq->orq_timeout = set_timeout(orq->orq_agent, queue->q_timeout); orq->orq_queue = queue; orq->orq_prev = queue->q_tail; *queue->q_tail = orq; queue->q_tail = &orq->orq_next; queue->q_length++; } /** @internal * Remove an outgoing transaction from a queue. */ su_inline void outgoing_remove(nta_outgoing_t *orq) { assert(outgoing_is_queued(orq)); assert(orq->orq_queue->q_length > 0); if ((*orq->orq_prev = orq->orq_next)) orq->orq_next->orq_prev = orq->orq_prev; else orq->orq_queue->q_tail = orq->orq_prev; orq->orq_queue->q_length--; orq->orq_next = NULL; orq->orq_prev = NULL; orq->orq_queue = NULL; orq->orq_timeout = 0; } /** Set retransmit timer (orq_retry). * * Set the retry timer (B/D) on the outgoing request (client transaction). */ su_inline void outgoing_set_timer(nta_outgoing_t *orq, uint32_t interval) { nta_outgoing_t **rq; assert(orq); if (interval == 0) { outgoing_reset_timer(orq); return; } if (orq->orq_rprev) { /* Remove transaction from retry dequeue, re-insert it later. */ if ((*orq->orq_rprev = orq->orq_rnext)) orq->orq_rnext->orq_rprev = orq->orq_rprev; if (orq->orq_agent->sa_out.re_t1 == &orq->orq_rnext) orq->orq_agent->sa_out.re_t1 = orq->orq_rprev; } else { orq->orq_agent->sa_out.re_length++; } orq->orq_retry = set_timeout(orq->orq_agent, orq->orq_interval = interval); /* Shortcut into queue at SIP T1 */ rq = orq->orq_agent->sa_out.re_t1; if (!(*rq) || (int32_t)((*rq)->orq_retry - orq->orq_retry) > 0) rq = &orq->orq_agent->sa_out.re_list; while (*rq && (int32_t)((*rq)->orq_retry - orq->orq_retry) <= 0) rq = &(*rq)->orq_rnext; if ((orq->orq_rnext = *rq)) orq->orq_rnext->orq_rprev = &orq->orq_rnext; *rq = orq; orq->orq_rprev = rq; if (interval == orq->orq_agent->sa_t1) orq->orq_agent->sa_out.re_t1 = rq; } static void outgoing_reset_timer(nta_outgoing_t *orq) { if (orq->orq_rprev) { if ((*orq->orq_rprev = orq->orq_rnext)) orq->orq_rnext->orq_rprev = orq->orq_rprev; if (orq->orq_agent->sa_out.re_t1 == &orq->orq_rnext) orq->orq_agent->sa_out.re_t1 = orq->orq_rprev; orq->orq_agent->sa_out.re_length--; } orq->orq_interval = 0, orq->orq_retry = 0; orq->orq_rnext = NULL, orq->orq_rprev = NULL; } /** @internal * Free resources associated with the request. */ static void outgoing_free(nta_outgoing_t *orq) { SU_DEBUG_9(("nta: outgoing_free(%p)\n", (void *)orq)); assert(orq->orq_forks == NULL && orq->orq_forking == NULL); outgoing_cut_off(orq); outgoing_reclaim(orq); } /** Remove outgoing request from hash tables */ su_inline void outgoing_cut_off(nta_outgoing_t *orq) { nta_agent_t *agent = orq->orq_agent; if (orq->orq_default) agent->sa_default_outgoing = NULL; if (orq->orq_inserted) outgoing_htable_remove(agent->sa_outgoing, orq), orq->orq_inserted = 0; if (outgoing_is_queued(orq)) outgoing_remove(orq); #if 0 if (orq->orq_forked) outgoing_remove_fork(orq); #endif outgoing_reset_timer(orq); if (orq->orq_pending) { tport_release(orq->orq_tport, orq->orq_pending, orq->orq_request, NULL, orq, 0); } orq->orq_pending = 0; if (orq->orq_cc) nta_compartment_decref(&orq->orq_cc); if (orq->orq_tport) tport_decref(&orq->orq_tport); } /** Reclaim outgoing request */ su_inline void outgoing_reclaim(nta_outgoing_t *orq) { if (orq->orq_status2b) *orq->orq_status2b = -1; if (orq->orq_request) msg_destroy(orq->orq_request), orq->orq_request = NULL; if (orq->orq_response) msg_destroy(orq->orq_response), orq->orq_response = NULL; #if HAVE_SOFIA_SRESOLV if (orq->orq_resolver) outgoing_destroy_resolver(orq); #endif su_free(orq->orq_agent->sa_home, orq); } /** Queue request to be freed */ su_inline void outgoing_free_queue(outgoing_queue_t *q, nta_outgoing_t *orq) { outgoing_cut_off(orq); outgoing_queue(q, orq); } /** Reclaim memory used by queue of requests */ static void outgoing_reclaim_queued(su_root_magic_t *rm, su_msg_r msg, union sm_arg_u *u) { outgoing_queue_t *q = u->a_outgoing_queue; nta_outgoing_t *orq, *orq_next; SU_DEBUG_9(("outgoing_reclaim_all(%p, %p, %p)\n", (void *)rm, (void *)msg, (void *)u)); for (orq = q->q_head; orq; orq = orq_next) { orq_next = orq->orq_next; outgoing_reclaim(orq); } } /** @internal Default callback for request */ int outgoing_default_cb(nta_outgoing_magic_t *magic, nta_outgoing_t *orq, sip_t const *sip) { if (sip == NULL || sip->sip_status->st_status >= 200) outgoing_destroy(orq); return 0; } /** @internal Destroy an outgoing transaction */ void outgoing_destroy(nta_outgoing_t *orq) { if (orq->orq_terminated || orq->orq_default) { if (!orq->orq_forking && !orq->orq_forks) { outgoing_free(orq); return; } } /* Application is expected to handle 200 OK statelessly => kill transaction immediately */ else if (orq->orq_method == sip_method_invite && !orq->orq_completed /* (unless transaction has been canceled) */ && !orq->orq_canceled /* or it has been forked */ && !orq->orq_forking && !orq->orq_forks) { orq->orq_destroyed = 1; outgoing_terminate(orq); return; } orq->orq_destroyed = 1; orq->orq_callback = outgoing_default_cb; orq->orq_magic = NULL; } /** @internal Outgoing transaction timer routine. * */ static void _nta_outgoing_timer(nta_agent_t *sa) { uint32_t now = sa->sa_millisec; nta_outgoing_t *orq; outgoing_queue_t rq[1]; size_t retransmitted = 0, terminated = 0, timeout = 0, destroyed; size_t total = sa->sa_outgoing->oht_used; size_t trying = sa->sa_out.re_length; size_t pending = sa->sa_out.trying->q_length + sa->sa_out.inv_calling->q_length; size_t completed = sa->sa_out.completed->q_length + sa->sa_out.inv_completed->q_length; outgoing_queue_init(sa->sa_out.free = rq, 0); while ((orq = sa->sa_out.re_list)) { if ((int32_t)(orq->orq_retry - now) > 0) break; if (retransmitted >= timer_max_retransmit) break; if (orq->orq_reliable) { outgoing_reset_timer(orq); if (!tport_is_connected(orq->orq_tport)) { /* * Timer N3: try to use UDP if trying to send via TCP * but no connection is established within SIP T4 */ SU_DEBUG_5(("nta: timer %s fired, %s %s (%u)\n", "N3", "try UDP instead for", orq->orq_method_name, orq->orq_cseq->cs_seq)); outgoing_try_udp_instead(orq, 1); outgoing_remove(orq); /* Reset state - this is no resend! */ outgoing_send(orq, 0); /* Send */ } continue; } assert(!orq->orq_reliable && orq->orq_interval != 0); SU_DEBUG_5(("nta: timer %s fired, %s %s (%u)\n", orq->orq_method == sip_method_invite ? "A" : "E", "retransmit", orq->orq_method_name, orq->orq_cseq->cs_seq)); outgoing_retransmit(orq); if (orq->orq_method == sip_method_invite || 2U * orq->orq_interval < sa->sa_t2) outgoing_set_timer(orq, 2U * orq->orq_interval); else outgoing_set_timer(orq, sa->sa_t2); if (++retransmitted % 5 == 0) su_root_yield(sa->sa_root); /* Handle received packets */ } terminated = outgoing_timer_dk(sa->sa_out.inv_completed, "D", now) + outgoing_timer_dk(sa->sa_out.completed, "K", now); timeout = outgoing_timer_bf(sa->sa_out.inv_calling, "B", now) + outgoing_timer_c(sa->sa_out.inv_proceeding, "C", now) + outgoing_timer_bf(sa->sa_out.trying, "F", now); destroyed = outgoing_mass_destroy(sa, rq); sa->sa_out.free = NULL; if (retransmitted || timeout || terminated || destroyed) { SU_DEBUG_5(("nta_outgoing_timer: " MOD_ZU"/"MOD_ZU" resent, " MOD_ZU"/"MOD_ZU" tout, " MOD_ZU"/"MOD_ZU" term, " MOD_ZU"/"MOD_ZU" free\n", retransmitted, trying, timeout, pending, terminated, completed, destroyed, total)); } } /** @internal Retransmit the outgoing request. */ void outgoing_retransmit(nta_outgoing_t *orq) { if (orq->orq_prepared && !orq->orq_delayed) { orq->orq_retries++; if (orq->orq_retries >= 4 && orq->orq_cc) { orq->orq_tpn->tpn_comp = NULL; if (orq->orq_retries == 4) { agent_close_compressor(orq->orq_agent, orq->orq_cc); nta_compartment_decref(&orq->orq_cc); } } outgoing_send(orq, 1); } } /** Trying a client transaction. */ static void outgoing_trying(nta_outgoing_t *orq) { if (orq->orq_forked) ; else if (orq->orq_method == sip_method_invite) outgoing_queue(orq->orq_agent->sa_out.inv_calling, orq); else outgoing_queue(orq->orq_agent->sa_out.trying, orq); } /** Handle timers B and F */ static size_t outgoing_timer_bf(outgoing_queue_t *q, char const *timer, uint32_t now) { nta_outgoing_t *orq; size_t timeout = 0; while ((orq = q->q_head)) { if ((int32_t)(orq->orq_timeout - now) > 0 || timeout >= timer_max_timeout) break; timeout++; SU_DEBUG_5(("nta: timer %s fired, %s %s (%u)\n", timer, orq->orq_method != sip_method_ack ? "timeout" : "terminating", orq->orq_method_name, orq->orq_cseq->cs_seq)); if (orq->orq_method != sip_method_ack) outgoing_timeout(orq, now); else outgoing_terminate(orq); assert(q->q_head != orq || (int32_t)(orq->orq_timeout - now) > 0); } return timeout; } /** Handle timer C */ static size_t outgoing_timer_c(outgoing_queue_t *q, char const *timer, uint32_t now) { nta_outgoing_t *orq; size_t timeout = 0; if (q->q_timeout == 0) return 0; while ((orq = q->q_head)) { if ((int32_t)(orq->orq_timeout - now) > 0 || timeout >= timer_max_timeout) break; timeout++; SU_DEBUG_5(("nta: timer %s fired, %s %s (%u)\n", timer, "CANCEL and timeout", orq->orq_method_name, orq->orq_cseq->cs_seq)); /* * If the client transaction has received a provisional response, the * proxy MUST generate a CANCEL request matching that transaction. */ nta_outgoing_tcancel(orq, NULL, NULL, TAG_NULL()); } return timeout; } /** @internal Signal transaction timeout to the application. */ void outgoing_timeout(nta_outgoing_t *orq, uint32_t now) { nta_outgoing_t *cancel = NULL; if (orq->orq_status || orq->orq_canceled) ; else if (outgoing_other_destinations(orq)) { SU_DEBUG_5(("%s(%p): %s\n", "nta", (void *)orq, "try next after timeout")); outgoing_try_another(orq); return; } cancel = orq->orq_cancel, orq->orq_cancel = NULL; orq->orq_agent->sa_stats->as_tout_request++; outgoing_reply(orq, SIP_408_REQUEST_TIMEOUT, 0); if (cancel) outgoing_timeout(cancel, now); } /** Complete a client transaction. * * @return True if transaction was free()d. */ static int outgoing_complete(nta_outgoing_t *orq) { orq->orq_completed = 1; outgoing_reset_timer(orq); /* Timer A / Timer E */ if (orq->orq_stateless) return outgoing_terminate(orq); if (orq->orq_forked) { outgoing_remove_fork(orq); return outgoing_terminate(orq); } if (orq->orq_reliable) { if (orq->orq_method != sip_method_invite || !orq->orq_uas) return outgoing_terminate(orq); } outgoing_cancel_resolver(orq); if (orq->orq_method == sip_method_invite) { if (orq->orq_queue != orq->orq_agent->sa_out.inv_completed) outgoing_queue(orq->orq_agent->sa_out.inv_completed, orq); /* Timer D */ } else { outgoing_queue(orq->orq_agent->sa_out.completed, orq); /* Timer K */ } return 0; } /** Handle timers D and K */ static size_t outgoing_timer_dk(outgoing_queue_t *q, char const *timer, uint32_t now) { nta_outgoing_t *orq; size_t terminated = 0; while ((orq = q->q_head)) { if ((int32_t)(orq->orq_timeout - now) > 0 || terminated >= timer_max_terminate) break; terminated++; SU_DEBUG_5(("nta: timer %s fired, %s %s (%u)\n", timer, "terminate", orq->orq_method_name, orq->orq_cseq->cs_seq)); if (orq->orq_method == sip_method_invite) outgoing_terminate_invite(orq); else outgoing_terminate(orq); } return terminated; } /** Terminate an INVITE client transaction. */ static void outgoing_terminate_invite(nta_outgoing_t *original) { nta_outgoing_t *orq = original; while (original->orq_forks) { orq = original->orq_forks; original->orq_forks = orq->orq_forks; assert(orq->orq_forking == original); SU_DEBUG_5(("nta: timer %s fired, %s %s (%u);tag=%s\n", "D", "terminate", orq->orq_method_name, orq->orq_cseq->cs_seq, orq->orq_tag)); orq->orq_forking = NULL, orq->orq_forks = NULL, orq->orq_forked = 0; if (outgoing_terminate(orq)) continue; if (orq->orq_status < 200) { /* Fork has timed out */ orq->orq_agent->sa_stats->as_tout_request++; outgoing_reply(orq, SIP_408_REQUEST_TIMEOUT, 0); } } if (outgoing_terminate(orq = original)) return; if (orq->orq_status < 200) { /* Original INVITE has timed out */ orq->orq_agent->sa_stats->as_tout_request++; outgoing_reply(orq, SIP_408_REQUEST_TIMEOUT, 0); } } static void outgoing_remove_fork(nta_outgoing_t *orq) { nta_outgoing_t **slot; for (slot = &orq->orq_forking->orq_forks; *slot; slot = &(*slot)->orq_forks) { if (orq == *slot) { *slot = orq->orq_forks; orq->orq_forks = NULL; orq->orq_forking = NULL; orq->orq_forked = 0; } } assert(orq == NULL); } /** Terminate a client transaction. */ static int outgoing_terminate(nta_outgoing_t *orq) { orq->orq_terminated = 1; outgoing_cancel_resolver(orq); if (!orq->orq_destroyed) { outgoing_queue(orq->orq_agent->sa_out.terminated, orq); return 0; } else if (orq->orq_agent->sa_out.free) { outgoing_free_queue(orq->orq_agent->sa_out.free, orq); return 1; } else { outgoing_free(orq); return 1; } } /** Mass destroy client transactions */ static size_t outgoing_mass_destroy(nta_agent_t *sa, outgoing_queue_t *q) { size_t destroyed = q->q_length; if (destroyed > 2 && *sa->sa_terminator) { su_msg_r m = SU_MSG_R_INIT; if (su_msg_create(m, su_clone_task(sa->sa_terminator), su_root_task(sa->sa_root), outgoing_reclaim_queued, sizeof(outgoing_queue_t)) == SU_SUCCESS) { outgoing_queue_t *mq = su_msg_data(m)->a_outgoing_queue; *mq = *q; if (su_msg_send(m) == SU_SUCCESS) q->q_length = 0; } } if (q->q_length) outgoing_reclaim_queued(NULL, NULL, (void*)q); return destroyed; } /** Find an outgoing request corresponging to a message and @Via line. * * Return an outgoing request object based on a message and the @Via line * given as argument. This function is used when doing loop checking: if we * have sent the request and it has been routed back to us. * * @param agent * @param msg * @param sip * @param v */ nta_outgoing_t *nta_outgoing_find(nta_agent_t const *agent, msg_t const *msg, sip_t const *sip, sip_via_t const *v) { if (agent == NULL || msg == NULL || sip == NULL || v == NULL) { su_seterrno(EFAULT); return NULL; } return outgoing_find(agent, msg, sip, v); } /**@internal * * Find an outgoing request corresponging to a message and @Via line. * */ nta_outgoing_t *outgoing_find(nta_agent_t const *sa, msg_t const *msg, sip_t const *sip, sip_via_t const *v) { nta_outgoing_t **oo, *orq; outgoing_htable_t const *oht = sa->sa_outgoing; sip_cseq_t const *cseq = sip->sip_cseq; sip_call_id_t const *i = sip->sip_call_id; hash_value_t hash; sip_method_t method, method2; unsigned short status = sip->sip_status ? sip->sip_status->st_status : 0; if (cseq == NULL) return NULL; hash = NTA_HASH(i, cseq->cs_seq); method = cseq->cs_method; /* Get original invite when ACKing */ if (sip->sip_request && method == sip_method_ack && v == NULL) method = sip_method_invite, method2 = sip_method_invalid; else if (sa->sa_is_a_uas && 200 <= status && status < 300 && method == sip_method_invite) method2 = sip_method_ack; else method2 = method; for (oo = outgoing_htable_hash(oht, hash); (orq = *oo); oo = outgoing_htable_next(oht, oo)) { if (orq->orq_stateless) continue; /* Accept terminated transactions when looking for original INVITE */ if (orq->orq_terminated && method2 != sip_method_invalid) continue; if (hash != orq->orq_hash) continue; if (orq->orq_call_id->i_hash != i->i_hash || strcmp(orq->orq_call_id->i_id, i->i_id)) continue; if (orq->orq_cseq->cs_seq != cseq->cs_seq) continue; if (method == sip_method_unknown && strcmp(orq->orq_cseq->cs_method_name, cseq->cs_method_name)) continue; if (orq->orq_method != method && orq->orq_method != method2) continue; if (su_strcasecmp(orq->orq_from->a_tag, sip->sip_from->a_tag)) continue; if (orq->orq_to->a_tag && su_strcasecmp(orq->orq_to->a_tag, sip->sip_to->a_tag)) continue; if (orq->orq_method == sip_method_ack && 300 <= status) continue; if (v && !su_casematch(orq->orq_branch + strlen("branch="), v->v_branch)) continue; break; /* match */ } return orq; } /** Process a response message. */ int outgoing_recv(nta_outgoing_t *_orq, int status, msg_t *msg, sip_t *sip) { nta_outgoing_t *orq = _orq->orq_forking ? _orq->orq_forking : _orq; nta_agent_t *sa = orq->orq_agent; int internal = sip == NULL || (sip->sip_flags & NTA_INTERNAL_MSG) != 0; assert(!internal || status >= 300); assert(orq == _orq || orq->orq_method == sip_method_invite); if (status < 100) status = 100; if (!internal && orq->orq_delay == UINT_MAX) outgoing_estimate_delay(orq, sip); if (orq->orq_cc) agent_accept_compressed(orq->orq_agent, msg, orq->orq_cc); if (orq->orq_cancel) { nta_outgoing_t *cancel; cancel = orq->orq_cancel; orq->orq_cancel = NULL; cancel->orq_delayed = 0; if (status < 200) { outgoing_send(cancel, 0); if (outgoing_complete(orq)) return 0; } else { outgoing_reply(cancel, SIP_481_NO_TRANSACTION, 0); } } if (orq->orq_pending) { tport_release(orq->orq_tport, orq->orq_pending, orq->orq_request, msg, orq, status < 200); if (status >= 200) orq->orq_pending = 0; } /* The state machines */ if (orq->orq_method == sip_method_invite) { nta_outgoing_t *original = orq; orq = _orq; if (orq->orq_destroyed && 200 <= status && status < 300) { if (orq->orq_uas && su_strcasecmp(sip->sip_to->a_tag, orq->orq_tag) != 0) { /* Orphan 200 Ok to INVITE. ACK and BYE it */ SU_DEBUG_5(("nta: Orphan 200 Ok send ACK&BYE\n")); return nta_msg_ackbye(sa, msg); } return -1; /* Proxy statelessly (RFC3261 section 16.11) */ } outgoing_reset_timer(original); /* Retransmission */ if (status < 200) { if (original->orq_status < 200) original->orq_status = status; if (orq->orq_status < 200) orq->orq_status = status; if (original->orq_queue == sa->sa_out.inv_calling) { outgoing_queue(sa->sa_out.inv_proceeding, original); } else if (original->orq_queue == sa->sa_out.inv_proceeding) { if (sa->sa_out.inv_proceeding->q_timeout) { outgoing_remove(original); outgoing_queue(sa->sa_out.inv_proceeding, original); } } /* Handle 100rel */ if (sip && sip->sip_rseq) { if (outgoing_recv_reliable(orq, msg, sip) < 0) { msg_destroy(msg); return 0; } } } else { /* Final response */ if (status >= 300 && !internal) outgoing_ack(original, sip); if (!original->orq_completed) { if (outgoing_complete(original)) return 0; if (orq->orq_uas && sip && orq == original) { /* * We silently discard duplicate final responses to INVITE below * with outgoing_duplicate() */ su_home_t *home = msg_home(orq->orq_request); orq->orq_tag = su_strdup(home, sip->sip_to->a_tag); } } /* Retransmission or response from another fork */ else if (orq->orq_status >= 200) { /* Once 2xx has been received, non-2xx will not be forwarded */ if (status >= 300) return outgoing_duplicate(orq, msg, sip); if (orq->orq_uas) { if (su_strcasecmp(sip->sip_to->a_tag, orq->orq_tag) == 0) /* Catch retransmission */ return outgoing_duplicate(orq, msg, sip); /* Orphan 200 Ok to INVITE. ACK and BYE it */ SU_DEBUG_5(("nta: Orphan 200 Ok send ACK&BYE")); return nta_msg_ackbye(sa, msg); } } orq->orq_status = status; } } else if (orq->orq_method != sip_method_ack) { /* Non-INVITE */ if (orq->orq_queue == sa->sa_out.trying || orq->orq_queue == sa->sa_out.resolving) { if (orq->orq_status >= 200) { /* hacked by freeswitch: this is being hit by options 404 status with 404 in orq->orq_status and orq_destroyed = 1, orq_completed = 1 */ /* assert(orq->orq_status < 200); */ msg_destroy(msg); return 0; } if (status < 200) { /* @RFC3261 17.1.2.1: * retransmissions continue for unreliable transports, * but at an interval of T2. * * @RFC4321 1.2: * Note that Timer E is not altered during the transition * to Proceeding. */ if (!orq->orq_reliable) orq->orq_interval = sa->sa_t2; #if notyet /* Destination has been already flushed */ if (orq->orq_queue == sa->sa_out.resolving) { /* A response from (previously resolved) destination? */ outgoing_cancel_resolver(orq); outgoing_trying(orq); } #endif } else if (outgoing_complete(orq)) { msg_destroy(msg); /* Transaction was terminated and destroyed */ return 0; } else { if (orq->orq_sigcomp_zap && orq->orq_tport && orq->orq_cc) agent_zap_compressor(orq->orq_agent, orq->orq_cc); } } else { /* Already completed or terminated */ assert(orq->orq_queue == sa->sa_out.completed || orq->orq_queue == sa->sa_out.terminated); assert(orq->orq_status >= 200); return outgoing_duplicate(orq, msg, sip); } orq->orq_status = status; } else { /* ACK */ if (sip && (sip->sip_flags & NTA_INTERNAL_MSG) == 0) /* Received re-transmitted final reply to INVITE, retransmit ACK */ outgoing_retransmit(orq); msg_destroy(msg); return 0; } if (100 >= status + orq->orq_pass_100) { msg_destroy(msg); return 0; } if (orq->orq_destroyed) { msg_destroy(msg); return 0; } if (orq->orq_response) msg_destroy(orq->orq_response); orq->orq_response = msg; /* Call callback */ orq->orq_callback(orq->orq_magic, orq, sip); return 0; } static void outgoing_default_recv(nta_outgoing_t *orq, int status, msg_t *msg, sip_t *sip) { assert(sip->sip_cseq); orq->orq_status = status; orq->orq_response = msg; orq->orq_callback(orq->orq_magic, orq, sip); orq->orq_response = NULL; orq->orq_status = 0; msg_destroy(msg); } static void outgoing_estimate_delay(nta_outgoing_t *orq, sip_t *sip) { su_time_t now = su_now(); double diff = 1000 * su_time_diff(now, orq->orq_sent); if (orq->orq_timestamp && sip->sip_timestamp) { double diff2, delay = 0.0; su_time_t timestamp = { 0, 0 }; char const *bad; sscanf(sip->sip_timestamp->ts_stamp, "%lu.%lu", ×tamp.tv_sec, ×tamp.tv_usec); diff2 = 1000 * su_time_diff(now, timestamp); if (diff2 < 0) bad = "negative"; else if (diff2 > diff + 1e-3) bad = "too large"; else { if (sip->sip_timestamp->ts_delay) sscanf(sip->sip_timestamp->ts_delay, "%lg", &delay); if (1000 * delay <= diff2) { diff = diff2 - 1000 * delay; orq->orq_delay = (unsigned)diff; SU_DEBUG_7(("nta_outgoing: RTT is %g ms, now is %lu.%06lu, " "Timestamp was %s %s\n", diff, now.tv_sec, now.tv_usec, sip->sip_timestamp->ts_stamp, sip->sip_timestamp->ts_delay ? sip->sip_timestamp->ts_delay : "")); return; } bad = "delay"; } SU_DEBUG_3(("nta_outgoing: %s Timestamp %lu.%06lu %g " "(sent %lu.%06lu, now is %lu.%06lu)\n", bad, timestamp.tv_sec, timestamp.tv_usec, delay, orq->orq_sent.tv_sec, orq->orq_sent.tv_usec, now.tv_sec, now.tv_usec)); } if (diff >= 0 && diff < (double)UINT_MAX) { orq->orq_delay = (unsigned)diff; SU_DEBUG_7(("nta_outgoing: RTT is %g ms\n", diff)); } } /**@typedef nta_response_f * * Callback for replies to outgoing requests. * * This is a callback function invoked by NTA when it has received a new * reply to an outgoing request. * * @param magic request context * @param request request handle * @param sip received status message * * @return * This callback function should return always 0. * */ /** Process duplicate responses */ static int outgoing_duplicate(nta_outgoing_t *orq, msg_t *msg, sip_t *sip) { sip_via_t *v; if (sip && (sip->sip_flags & NTA_INTERNAL_MSG) == 0) { v = sip->sip_via; SU_DEBUG_5(("nta: %u %s is duplicate response to %d %s\n", sip->sip_status->st_status, sip->sip_status->st_phrase, orq->orq_cseq->cs_seq, orq->orq_cseq->cs_method_name)); if (v) SU_DEBUG_5(("\tVia: %s %s%s%s%s%s%s%s%s%s\n", v->v_protocol, v->v_host, SIP_STRLOG(":", v->v_port), SIP_STRLOG(" ;received=", v->v_received), SIP_STRLOG(" ;maddr=", v->v_maddr), SIP_STRLOG(" ;branch=", v->v_branch))); } msg_destroy(msg); return 0; } /** @internal ACK to a final response (300..699). * These messages are ACK'ed via the original URL (and tport) */ void outgoing_ack(nta_outgoing_t *orq, sip_t *sip) { msg_t *ackmsg; assert(orq); /* Do not ack internally generated messages... */ if (sip == NULL || sip->sip_flags & NTA_INTERNAL_MSG) return; assert(sip); assert(sip->sip_status); assert(sip->sip_status->st_status >= 300); assert(orq->orq_tport); ackmsg = outgoing_ackmsg(orq, SIP_METHOD_ACK, SIPTAG_TO(sip->sip_to), TAG_END()); if (!ackmsg) return; if (!outgoing_create(orq->orq_agent, NULL, NULL, NULL, orq->orq_tpn, ackmsg, NTATAG_BRANCH_KEY(sip->sip_via->v_branch), NTATAG_USER_VIA(1), NTATAG_STATELESS(1), TAG_END())) msg_destroy(ackmsg); } /** Generate messages for hop-by-hop ACK or CANCEL. */ msg_t *outgoing_ackmsg(nta_outgoing_t *orq, sip_method_t m, char const *mname, tag_type_t tag, tag_value_t value, ...) { msg_t *msg = nta_msg_create(orq->orq_agent, 0); su_home_t *home = msg_home(msg); sip_t *sip = sip_object(msg); sip_t *old = sip_object(orq->orq_request); sip_via_t via[1]; if (!sip) return NULL; if (tag) { ta_list ta; ta_start(ta, tag, value); sip_add_tl(msg, sip, ta_tags(ta)); /* Bug sf.net # 173323: * Ensure that request-URI, topmost Via, From, To, Call-ID, CSeq, * Max-Forward, Route, Accept-Contact, Reject-Contact and * Request-Disposition are copied from original request */ if (sip->sip_from) sip_header_remove(msg, sip, (void *)sip->sip_from); if (sip->sip_to && m != sip_method_ack) sip_header_remove(msg, sip, (void *)sip->sip_to); if (sip->sip_call_id) sip_header_remove(msg, sip, (void *)sip->sip_call_id); while (sip->sip_route) sip_header_remove(msg, sip, (void *)sip->sip_route); while (sip->sip_accept_contact) sip_header_remove(msg, sip, (void *)sip->sip_accept_contact); while (sip->sip_reject_contact) sip_header_remove(msg, sip, (void *)sip->sip_reject_contact); if (sip->sip_request_disposition) sip_header_remove(msg, sip, (void *)sip->sip_request_disposition); while (sip->sip_via) sip_header_remove(msg, sip, (void *)sip->sip_via); if (sip->sip_max_forwards) sip_header_remove(msg, sip, (void *)sip->sip_max_forwards); ta_end(ta); } sip->sip_request = sip_request_create(home, m, mname, (url_string_t *)orq->orq_url, NULL); if (sip->sip_to == NULL) sip_add_dup(msg, sip, (sip_header_t *)old->sip_to); sip_add_dup(msg, sip, (sip_header_t *)old->sip_from); sip_add_dup(msg, sip, (sip_header_t *)old->sip_call_id); sip_add_dup(msg, sip, (sip_header_t *)old->sip_route); /* @RFC3841. Bug #1326727. */ sip_add_dup(msg, sip, (sip_header_t *)old->sip_accept_contact); sip_add_dup(msg, sip, (sip_header_t *)old->sip_reject_contact); sip_add_dup(msg, sip, (sip_header_t *)old->sip_request_disposition); sip_add_dup(msg, sip, (sip_header_t *)old->sip_max_forwards); if (old->sip_via) { /* Add only the topmost Via header */ *via = *old->sip_via; via->v_next = NULL; sip_add_dup(msg, sip, (sip_header_t *)via); } sip->sip_cseq = sip_cseq_create(home, old->sip_cseq->cs_seq, m, mname); if (sip->sip_request && sip->sip_to && sip->sip_from && sip->sip_call_id && (!old->sip_route || sip->sip_route) && sip->sip_cseq) return msg; msg_destroy(msg); return NULL; } static void outgoing_delayed_recv(su_root_magic_t *rm, su_msg_r msg, union sm_arg_u *u); /** Respond internally to a transaction. */ int outgoing_reply(nta_outgoing_t *orq, int status, char const *phrase, int delayed) { nta_agent_t *agent = orq->orq_agent; msg_t *msg = NULL; sip_t *sip = NULL; assert(status == 202 || status >= 400); if (orq->orq_pending) tport_release(orq->orq_tport, orq->orq_pending, orq->orq_request, NULL, orq, 0); orq->orq_pending = 0; orq->orq_delayed = 0; if (orq->orq_method == sip_method_ack) { if (status != delayed) SU_DEBUG_3(("nta(%p): responding %u %s to ACK!\n", (void *)orq, status, phrase)); orq->orq_status = status; if (orq->orq_queue == NULL) outgoing_trying(orq); /* Timer F */ return 0; } if (orq->orq_destroyed) { if (orq->orq_status < 200) orq->orq_status = status; outgoing_complete(orq); /* Timer D / Timer K */ return 0; } if (orq->orq_stateless) ; else if (orq->orq_queue == NULL || orq->orq_queue == orq->orq_agent->sa_out.resolving || orq->orq_queue == orq->orq_agent->sa_out.delayed) outgoing_trying(orq); /** Insert a dummy Via header */ if (!orq->orq_prepared) { tport_t *tp = tport_primaries(orq->orq_agent->sa_tports); outgoing_insert_via(orq, agent_tport_via(tp)); } /* Create response message, if needed */ if (!orq->orq_stateless && !(orq->orq_callback == outgoing_default_cb) && !(status == 408 && orq->orq_method != sip_method_invite && !orq->orq_agent->sa_timeout_408)) { char const *to_tag; msg = nta_msg_create(agent, NTA_INTERNAL_MSG); if (complete_response(msg, status, phrase, orq->orq_request) < 0) { assert(!"complete message"); return -1; } sip = sip_object(msg); assert(sip->sip_flags & NTA_INTERNAL_MSG); to_tag = nta_agent_newtag(msg_home(msg), "tag=%s", agent); if (status > 100 && sip->sip_to && !sip->sip_to->a_tag && sip->sip_cseq->cs_method != sip_method_cancel && sip_to_tag(msg_home(msg), sip->sip_to, to_tag) < 0) { assert(!"adding tag"); return -1; } if (status > 400 && agent->sa_blacklist) { sip_retry_after_t af[1]; sip_retry_after_init(af)->af_delta = agent->sa_blacklist; sip_add_dup(msg, sip, (sip_header_t *)af); } } if (orq->orq_inserted && !delayed) { outgoing_recv(orq, status, msg, sip); return 0; } else if (orq->orq_stateless && orq->orq_callback == outgoing_default_cb) { /* Xyzzy */ orq->orq_status = status; outgoing_complete(orq); } else { /* * The thread creating outgoing transaction must return to application * before transaction callback can be invoked. Therefore processing an * internally generated response message must be delayed until * transaction creation is completed. * * The internally generated message is transmitted using su_msg_send() * and it is delivered back to NTA when the application next time * executes the su_root_t event loop. */ nta_agent_t *agent = orq->orq_agent; su_root_t *root = agent->sa_root; su_msg_r su_msg = SU_MSG_R_INIT; if (su_msg_create(su_msg, su_root_task(root), su_root_task(root), outgoing_delayed_recv, sizeof(struct outgoing_recv_s)) == SU_SUCCESS) { struct outgoing_recv_s *a = su_msg_data(su_msg)->a_outgoing_recv; a->orq = orq; a->msg = msg; a->sip = sip; a->status = status; orq->orq_status2b = &a->status; if (su_msg_send(su_msg) == SU_SUCCESS) { return 0; } } } if (msg) msg_destroy(msg); return -1; } static void outgoing_delayed_recv(su_root_magic_t *rm, su_msg_r msg, union sm_arg_u *u) { struct outgoing_recv_s *a = u->a_outgoing_recv; if (a->status > 0) { a->orq->orq_status2b = 0; if (outgoing_recv(a->orq, a->status, a->msg, a->sip) >= 0) return; } msg_destroy(a->msg); } /* ====================================================================== */ /* 9) Resolving (SIP) URL */ #if HAVE_SOFIA_SRESOLV struct sipdns_query; /** DNS resolving for (SIP) URLs */ struct sipdns_resolver { tp_name_t sr_tpn[1]; /**< Copy of original transport name */ sres_query_t *sr_query; /**< Current DNS Query */ char const *sr_target; /**< Target for current query */ struct sipdns_query *sr_current; /**< Current query (with results) */ char **sr_results; /**< A/AAAA results to be used */ struct sipdns_query *sr_head; /**< List of intermediate results */ struct sipdns_query **sr_tail; /**< End of intermediate result list */ struct sipdns_query *sr_done; /**< Completed intermediate results */ struct sipdns_tport const *sr_tport; /**< Selected transport */ /** Transports to consider for this request */ struct sipdns_tport const *sr_tports[SIPDNS_TRANSPORTS + 1]; uint16_t sr_a_aaaa1, sr_a_aaaa2; /**< Order of A and/or AAAA queries. */ unsigned sr_use_naptr:1, sr_use_srv:1, sr_use_a_aaaa:1; }; /** Intermediate queries */ struct sipdns_query { struct sipdns_query *sq_next; char const *sq_proto; char const *sq_domain; char sq_port[6]; /* port number */ uint16_t sq_otype; /* origin type of query data (0 means request) */ uint16_t sq_type; /* query type */ uint16_t sq_priority; /* priority or preference */ uint16_t sq_weight; /* preference or weight */ uint16_t sq_grayish; /* candidate for graylisting */ }; static int outgoing_resolve_next(nta_outgoing_t *orq); static int outgoing_resolving(nta_outgoing_t *orq); static int outgoing_resolving_error(nta_outgoing_t *, int status, char const *phrase); static void outgoing_graylist(nta_outgoing_t *orq, struct sipdns_query *sq); static int outgoing_query_naptr(nta_outgoing_t *orq, char const *domain); static void outgoing_answer_naptr(sres_context_t *orq, sres_query_t *q, sres_record_t *answers[]); struct sipdns_tport const *outgoing_naptr_tport(nta_outgoing_t *orq, sres_record_t *answers[]); static int outgoing_make_srv_query(nta_outgoing_t *orq); static int outgoing_make_a_aaaa_query(nta_outgoing_t *orq); static void outgoing_query_all(nta_outgoing_t *orq); static int outgoing_query_srv(nta_outgoing_t *orq, struct sipdns_query *); static void outgoing_answer_srv(sres_context_t *orq, sres_query_t *q, sres_record_t *answers[]); #if SU_HAVE_IN6 static int outgoing_query_aaaa(nta_outgoing_t *orq, struct sipdns_query *); static void outgoing_answer_aaaa(sres_context_t *orq, sres_query_t *q, sres_record_t *answers[]); #endif static int outgoing_query_a(nta_outgoing_t *orq, struct sipdns_query *); static void outgoing_answer_a(sres_context_t *orq, sres_query_t *q, sres_record_t *answers[]); static void outgoing_query_results(nta_outgoing_t *orq, struct sipdns_query *sq, char *results[], size_t rlen); #define SIPDNS_503_ERROR 503, "DNS Error" /** Resolve a request destination */ static void outgoing_resolve(nta_outgoing_t *orq, int explicit_transport, enum nta_res_order_e res_order) { struct sipdns_resolver *sr = NULL; char const *tpname = orq->orq_tpn->tpn_proto; int tport_known = strcmp(tpname, "*") != 0; if (orq->orq_agent->sa_resolver) orq->orq_resolver = sr = su_zalloc(orq->orq_agent->sa_home, (sizeof *sr)); if (!sr) { outgoing_resolving_error(orq, SIP_500_INTERNAL_SERVER_ERROR); return; } *sr->sr_tpn = *orq->orq_tpn; sr->sr_use_srv = orq->orq_agent->sa_use_srv; sr->sr_use_naptr = orq->orq_agent->sa_use_naptr && sr->sr_use_srv; sr->sr_use_a_aaaa = 1; sr->sr_tail = &sr->sr_head; /* RFC 3263: If the TARGET was not a numeric IP address, but a port is present in the URI, the client performs an A or AAAA record lookup of the domain name. The result will be a list of IP addresses, each of which can be contacted at the specific port from the URI and transport protocol determined previously. The client SHOULD try the first record. If an attempt should fail, based on the definition of failure in Section 4.3, the next SHOULD be tried, and if that should fail, the next SHOULD be tried, and so on. This is a change from RFC 2543. Previously, if the port was explicit, but with a value of 5060, SRV records were used. Now, A or AAAA records will be used. */ if (sr->sr_tpn->tpn_port) sr->sr_use_naptr = 0, sr->sr_use_srv = 0; /* RFC3263: If [...] a transport was specified explicitly, the client performs an SRV query for that specific transport, */ if (explicit_transport) sr->sr_use_naptr = 0; { /* Initialize sr_tports */ tport_t *tport; char const *ident = sr->sr_tpn->tpn_ident; int i, j; for (tport = tport_primary_by_name(orq->orq_agent->sa_tports, orq->orq_tpn); tport; tport = tport_next(tport)) { tp_name_t const *tpn = tport_name(tport); if (tport_known && !su_casematch(tpn->tpn_proto, tpname)) continue; if (ident && (tpn->tpn_ident == NULL || strcmp(ident, tpn->tpn_ident))) continue; for (j = 0; j < SIPDNS_TRANSPORTS; j++) if (su_casematch(tpn->tpn_proto, sipdns_tports[j].name)) break; assert(j < SIPDNS_TRANSPORTS); if (j == SIPDNS_TRANSPORTS) /* Someone added transport but did not update sipdns_tports */ continue; for (i = 0; i < SIPDNS_TRANSPORTS; i++) { if (sipdns_tports + j == sr->sr_tports[i] || sr->sr_tports[i] == NULL) break; } sr->sr_tports[i] = sipdns_tports + j; if (tport_known) /* Looking for only one transport */ { sr->sr_tport = sipdns_tports + j; break; } } /* Nothing found */ if (!sr->sr_tports[0]) { SU_DEBUG_3(("nta(%p): transport %s is not supported%s%s\n", (void *)orq, tpname, ident ? " by interface " : "", ident ? ident : "")); outgoing_resolving_error(orq, SIPDNS_503_ERROR); return; } } switch (res_order) { default: case nta_res_ip6_ip4: sr->sr_a_aaaa1 = sres_type_aaaa, sr->sr_a_aaaa2 = sres_type_a; break; case nta_res_ip4_ip6: sr->sr_a_aaaa1 = sres_type_a, sr->sr_a_aaaa2 = sres_type_aaaa; break; case nta_res_ip6_only: sr->sr_a_aaaa1 = sres_type_aaaa, sr->sr_a_aaaa2 = sres_type_aaaa; break; case nta_res_ip4_only: sr->sr_a_aaaa1 = sres_type_a, sr->sr_a_aaaa2 = sres_type_a; break; } outgoing_resolve_next(orq); } /** Resolve next destination. */ static int outgoing_resolve_next(nta_outgoing_t *orq) { struct sipdns_resolver *sr = orq->orq_resolver; if (orq->orq_completed) return 0; if (sr == NULL) { outgoing_resolving_error(orq, SIP_500_INTERNAL_SERVER_ERROR); return 0; } if (sr->sr_results) { /* Use existing A/AAAA results */ su_free(msg_home(orq->orq_request), sr->sr_results[0]); sr->sr_results++; if (sr->sr_results[0]) { struct sipdns_query *sq = sr->sr_current; assert(sq); if (sq->sq_proto) orq->orq_tpn->tpn_proto = sq->sq_proto; if (sq->sq_port[0]) orq->orq_tpn->tpn_port = sq->sq_port; orq->orq_tpn->tpn_host = sr->sr_results[0]; outgoing_reset_timer(orq); outgoing_queue(orq->orq_agent->sa_out.resolving, orq); outgoing_prepare_send(orq); return 1; } else { sr->sr_current = NULL; sr->sr_results = NULL; } } if (sr->sr_head) outgoing_query_all(orq); else if (sr->sr_use_naptr) outgoing_query_naptr(orq, sr->sr_tpn->tpn_host); /* NAPTR */ else if (sr->sr_use_srv) outgoing_make_srv_query(orq); /* SRV */ else if (sr->sr_use_a_aaaa) outgoing_make_a_aaaa_query(orq); /* A/AAAA */ else return outgoing_resolving_error(orq, SIPDNS_503_ERROR); return 1; } /** Check if can we retry other destinations? */ static int outgoing_other_destinations(nta_outgoing_t const *orq) { struct sipdns_resolver *sr; if (orq->orq_completed) return 0; sr = orq->orq_resolver; if (!sr) return 0; if (sr->sr_use_a_aaaa || sr->sr_use_srv || sr->sr_use_naptr) return 1; if (sr->sr_results && sr->sr_results[1]) return 1; if (sr->sr_head) return 1; return 0; } /** Resolve a request destination */ static int outgoing_try_another(nta_outgoing_t *orq) { struct sipdns_resolver *sr = orq->orq_resolver; if (sr == NULL) return 0; *orq->orq_tpn = *sr->sr_tpn; orq->orq_try_tcp_instead = 0, orq->orq_try_udp_instead = 0; outgoing_reset_timer(orq); outgoing_queue(orq->orq_agent->sa_out.resolving, orq); if (orq->orq_status > 0) /* PP: don't hack priority if a preliminary response has been received */ ; else if (orq->orq_agent->sa_graylist == 0) /* PP: priority hacking disabled */ ; /* NetModule hack: * Move server that did not work to end of queue in sres cache * * the next request does not try to use the server that is currently down * * @TODO: fix cases with only A or AAAA answering, or all servers down. */ else if (sr && sr->sr_target) { struct sipdns_query *sq; /* find latest A/AAAA record */ sq = sr->sr_head; if (sq && sq->sq_type == sr->sr_a_aaaa2 && sr->sr_a_aaaa1 != sr->sr_a_aaaa2) { sq->sq_grayish = 1; } else { outgoing_graylist(orq, sr->sr_done); } } return outgoing_resolve_next(orq); } /** Graylist SRV records */ static void outgoing_graylist(nta_outgoing_t *orq, struct sipdns_query *sq) { struct sipdns_resolver *sr = orq->orq_resolver; char const *target = sq->sq_domain, *proto = sq->sq_proto; unsigned prio = sq->sq_priority, maxprio = prio; /* Don't know how to graylist but SRV records */ if (sq->sq_otype != sres_type_srv) return; SU_DEBUG_5(("nta: graylisting %s:%s;transport=%s\n", target, sq->sq_port, proto)); for (sq = sr->sr_head; sq; sq = sq->sq_next) if (sq->sq_otype == sres_type_srv && sq->sq_priority > maxprio) maxprio = sq->sq_priority; for (sq = sr->sr_done; sq; sq = sq->sq_next) if (sq->sq_otype == sres_type_srv && sq->sq_priority > maxprio) maxprio = sq->sq_priority; for (sq = sr->sr_done; sq; sq = sq->sq_next) { int modified; if (sq->sq_type != sres_type_srv || strcmp(proto, sq->sq_proto)) continue; /* modify the SRV record(s) corresponding to the latest A/AAAA record */ modified = sres_set_cached_srv_priority( orq->orq_agent->sa_resolver, sq->sq_domain, target, sq->sq_port[0] ? (uint16_t)strtoul(sq->sq_port, NULL, 10) : 0, orq->orq_agent->sa_graylist, maxprio + 1); if (modified >= 0) SU_DEBUG_3(("nta: reduced priority of %d %s SRV records (increase value to %u)\n", modified, sq->sq_domain, maxprio + 1)); else SU_DEBUG_3(("nta: failed to reduce %s SRV priority\n", sq->sq_domain)); } } /** Cancel resolver query */ su_inline void outgoing_cancel_resolver(nta_outgoing_t *orq) { struct sipdns_resolver *sr = orq->orq_resolver; if (sr && sr->sr_query) /* Cancel resolver query */ sres_query_bind(sr->sr_query, NULL, NULL), sr->sr_query = NULL; } /** Destroy resolver */ su_inline void outgoing_destroy_resolver(nta_outgoing_t *orq) { struct sipdns_resolver *sr = orq->orq_resolver; assert(orq->orq_resolver); if (sr->sr_query) /* Cancel resolver query */ sres_query_bind(sr->sr_query, NULL, NULL), sr->sr_query = NULL; su_free(orq->orq_agent->sa_home, sr); orq->orq_resolver = NULL; } /** Check if we are resolving. If not, return 503 response. */ static int outgoing_resolving(nta_outgoing_t *orq) { struct sipdns_resolver *sr = orq->orq_resolver; assert(orq->orq_resolver); if (!sr->sr_query) { return outgoing_resolving_error(orq, SIPDNS_503_ERROR); } else { outgoing_queue(orq->orq_agent->sa_out.resolving, orq); return 0; } } /** Return 503 response */ static int outgoing_resolving_error(nta_outgoing_t *orq, int status, char const *phrase) { orq->orq_resolved = 1; outgoing_reply(orq, status, phrase, 0); return -1; } /* Query SRV records (with the given tport). */ static int outgoing_make_srv_query(nta_outgoing_t *orq) { struct sipdns_resolver *sr = orq->orq_resolver; su_home_t *home = msg_home(orq->orq_request); struct sipdns_query *sq; char const *host, *prefix; int i; size_t hlen, plen; sr->sr_use_srv = 0; host = sr->sr_tpn->tpn_host; hlen = strlen(host) + 1; for (i = 0; sr->sr_tports[i]; i++) { if (sr->sr_tport && sr->sr_tports[i] != sr->sr_tport) continue; prefix = sr->sr_tports[i]->prefix; plen = strlen(prefix); sq = su_zalloc(home, (sizeof *sq) + plen + hlen); if (sq) { *sr->sr_tail = sq, sr->sr_tail = &sq->sq_next; sq->sq_domain = memcpy(sq + 1, prefix, plen); memcpy((char *)sq->sq_domain + plen, host, hlen); sq->sq_proto = sr->sr_tports[i]->name; sq->sq_type = sres_type_srv; sq->sq_priority = 1; sq->sq_weight = 1; } } outgoing_query_all(orq); return 0; } /* Query A/AAAA records. */ static int outgoing_make_a_aaaa_query(nta_outgoing_t *orq) { struct sipdns_resolver *sr = orq->orq_resolver; su_home_t *home = msg_home(orq->orq_request); tp_name_t *tpn = orq->orq_tpn; struct sipdns_query *sq; assert(sr); sr->sr_use_a_aaaa = 0; sq = su_zalloc(home, 2 * (sizeof *sq)); if (!sq) return outgoing_resolving(orq); sq->sq_type = sr->sr_a_aaaa1; sq->sq_domain = tpn->tpn_host; sq->sq_priority = 1; /* Append */ *sr->sr_tail = sq, sr->sr_tail = &sq->sq_next; outgoing_query_all(orq); return 0; } /** Start SRV/A/AAAA queries */ static void outgoing_query_all(nta_outgoing_t *orq) { struct sipdns_resolver *sr = orq->orq_resolver; struct sipdns_query *sq = sr->sr_head; if (sq == NULL) { outgoing_resolving_error(orq, SIP_500_INTERNAL_SERVER_ERROR); return; } /* Remove from intermediate list */ if (!(sr->sr_head = sq->sq_next)) sr->sr_tail = &sr->sr_head; if (sq->sq_type == sres_type_srv) outgoing_query_srv(orq, sq); #if SU_HAVE_IN6 else if (sq->sq_type == sres_type_aaaa) outgoing_query_aaaa(orq, sq); #endif else if (sq->sq_type == sres_type_a) outgoing_query_a(orq, sq); else outgoing_resolving_error(orq, SIP_500_INTERNAL_SERVER_ERROR); } /** Query NAPTR record. */ static int outgoing_query_naptr(nta_outgoing_t *orq, char const *domain) { struct sipdns_resolver *sr = orq->orq_resolver; sres_record_t **answers; sr->sr_use_naptr = 0; sr->sr_target = domain; answers = sres_cached_answers(orq->orq_agent->sa_resolver, sres_type_naptr, domain); SU_DEBUG_5(("nta: for \"%s\" query \"%s\" %s%s\n", orq->orq_tpn->tpn_host, domain, "NAPTR", answers ? " (cached)" : "")); if (answers) { outgoing_answer_naptr(orq, NULL, answers); return 0; } else { sr->sr_query = sres_query(orq->orq_agent->sa_resolver, outgoing_answer_naptr, orq, sres_type_naptr, domain); return outgoing_resolving(orq); } } /* Process NAPTR records */ static void outgoing_answer_naptr(sres_context_t *orq, sres_query_t *q, sres_record_t *answers[]) { int i, order = -1; size_t rlen; su_home_t *home = msg_home(orq->orq_request); struct sipdns_resolver *sr = orq->orq_resolver; tp_name_t tpn[1]; struct sipdns_query *sq, *selected = NULL, **tail = &selected, **at; assert(sr); sr->sr_query = NULL; *tpn = *sr->sr_tpn; /* The NAPTR results are sorted first by Order then by Preference */ sres_sort_answers(orq->orq_agent->sa_resolver, answers); if (sr->sr_tport == NULL) sr->sr_tport = outgoing_naptr_tport(orq, answers); for (i = 0; answers && answers[i]; i++) { sres_naptr_record_t const *na = answers[i]->sr_naptr; uint16_t type; int valid_tport; if (na->na_record->r_status) continue; if (na->na_record->r_type != sres_type_naptr) continue; /* Check if NAPTR matches our target */ if (!su_casenmatch(na->na_services, "SIP+", 4) && !su_casenmatch(na->na_services, "SIPS+", 5)) /* Not a SIP/SIPS service */ continue; /* Use NAPTR results, don't try extra SRV/A/AAAA records */ sr->sr_use_srv = 0, sr->sr_use_a_aaaa = 0; valid_tport = sr->sr_tport && su_casematch(na->na_services, sr->sr_tport->service); SU_DEBUG_5(("nta: %s IN NAPTR %u %u \"%s\" \"%s\" \"%s\" %s%s\n", na->na_record->r_name, na->na_order, na->na_prefer, na->na_flags, na->na_services, na->na_regexp, na->na_replace, order >= 0 && order != na->na_order ? " (out of order)" : valid_tport ? "" : " (tport not used)")); /* RFC 2915 p 4: * Order * A 16-bit unsigned integer specifying the order in which the * NAPTR records MUST be processed to ensure the correct ordering * of rules. Low numbers are processed before high numbers, and * once a NAPTR is found whose rule "matches" the target, the * client MUST NOT consider any NAPTRs with a higher value for * order (except as noted below for the Flags field). */ if (order >= 0 && order != na->na_order) continue; if (!valid_tport) continue; /* OK, we found matching NAPTR */ order = na->na_order; /* * The "S" flag means that the next lookup should be for SRV records * ... "A" means that the next lookup should be for either an A, AAAA, * or A6 record. */ if (na->na_flags[0] == 's' || na->na_flags[0] == 'S') type = sres_type_srv; /* SRV */ else if (na->na_flags[0] == 'a' || na->na_flags[0] == 'A') type = sr->sr_a_aaaa1; /* A / AAAA */ else continue; rlen = strlen(na->na_replace) + 1; sq = su_zalloc(home, (sizeof *sq) + rlen); if (sq == NULL) continue; *tail = sq, tail = &sq->sq_next; sq->sq_otype = sres_type_naptr; sq->sq_priority = na->na_prefer; sq->sq_weight = 1; sq->sq_type = type; sq->sq_domain = memcpy(sq + 1, na->na_replace, rlen); sq->sq_proto = sr->sr_tport->name; } sres_free_answers(orq->orq_agent->sa_resolver, answers); /* RFC2915: Preference [...] specifies the order in which NAPTR records with equal "order" values SHOULD be processed, low numbers being processed before high numbers. */ at = sr->sr_tail; while (selected) { sq = selected, selected = sq->sq_next; for (tail = at; *tail; tail = &(*tail)->sq_next) { if (sq->sq_priority < (*tail)->sq_priority) break; if (sq->sq_priority == (*tail)->sq_priority && sq->sq_weight < (*tail)->sq_weight) break; } /* Insert */ sq->sq_next = *tail, *tail = sq; if (!sq->sq_next) /* Last one */ sr->sr_tail = &sq->sq_next; } outgoing_resolve_next(orq); } /* Find first supported protocol in order and preference */ struct sipdns_tport const * outgoing_naptr_tport(nta_outgoing_t *orq, sres_record_t *answers[]) { int i, j, order, pref; int orders[SIPDNS_TRANSPORTS], prefs[SIPDNS_TRANSPORTS]; struct sipdns_tport const *tport; struct sipdns_resolver *sr = orq->orq_resolver; for (j = 0; sr->sr_tports[j]; j++) { tport = sr->sr_tports[j]; orders[j] = 65536, prefs[j] = 65536; /* Find transport order */ for (i = 0; answers && answers[i]; i++) { sres_naptr_record_t const *na = answers[i]->sr_naptr; if (na->na_record->r_status) continue; if (na->na_record->r_type != sres_type_naptr) continue; /* Check if NAPTR matches transport */ if (!su_casematch(na->na_services, tport->service)) continue; orders[j] = na->na_order; prefs[j] = na->na_prefer; break; } } tport = sr->sr_tports[0], order = orders[0], pref = prefs[0]; for (j = 1; sr->sr_tports[j]; j++) { if (orders[j] <= order && prefs[j] < pref) { tport = sr->sr_tports[j], order = orders[j], pref = prefs[j]; } } return tport; } /* Query SRV records */ static int outgoing_query_srv(nta_outgoing_t *orq, struct sipdns_query *sq) { struct sipdns_resolver *sr = orq->orq_resolver; sres_record_t **answers; sr->sr_target = sq->sq_domain; sr->sr_current = sq; answers = sres_cached_answers(orq->orq_agent->sa_resolver, sres_type_srv, sq->sq_domain); SU_DEBUG_5(("nta: for \"%s\" query \"%s\" %s%s\n", orq->orq_tpn->tpn_host, sq->sq_domain, "SRV", answers ? " (cached)" : "")); if (answers) { outgoing_answer_srv(orq, NULL, answers); return 0; } else { sr->sr_query = sres_query(orq->orq_agent->sa_resolver, outgoing_answer_srv, orq, sres_type_srv, sq->sq_domain); return outgoing_resolving(orq); } } /* Process SRV records */ static void outgoing_answer_srv(sres_context_t *orq, sres_query_t *q, sres_record_t *answers[]) { struct sipdns_resolver *sr = orq->orq_resolver; su_home_t *home = msg_home(orq->orq_request); struct sipdns_query *sq0, *sq, *selected = NULL, **tail = &selected, **at; int i; size_t tlen; sr->sr_query = NULL; sq0 = sr->sr_current; assert(sq0 && sq0->sq_type == sres_type_srv); assert(sq0->sq_domain); assert(sq0->sq_proto); /* Sort by priority, weight? */ sres_sort_answers(orq->orq_agent->sa_resolver, answers); for (i = 0; answers && answers[i]; i++) { sres_srv_record_t const *srv = answers[i]->sr_srv; if (srv->srv_record->r_status /* There was an error */ || srv->srv_record->r_type != sres_type_srv) continue; tlen = strlen(srv->srv_target) + 1; sq = su_zalloc(home, (sizeof *sq) + tlen); if (sq) { *tail = sq, tail = &sq->sq_next; sq->sq_otype = sres_type_srv; sq->sq_type = sr->sr_a_aaaa1; sq->sq_proto = sq0->sq_proto; sq->sq_domain = memcpy(sq + 1, srv->srv_target, tlen); snprintf(sq->sq_port, sizeof(sq->sq_port), "%u", srv->srv_port); sq->sq_priority = srv->srv_priority; sq->sq_weight = srv->srv_weight; } } sres_free_answers(orq->orq_agent->sa_resolver, answers); at = &sr->sr_head; /* Insert sorted by priority, randomly select by weigth */ while (selected) { unsigned long weight = 0; unsigned N = 0; uint16_t priority = selected->sq_priority; /* Total weight of entries with same priority */ for (sq = selected; sq && priority == sq->sq_priority; sq = sq->sq_next) { weight += sq->sq_weight; N ++; } tail = &selected; /* Select by weighted random. Entries with weight 0 are kept in order */ if (N > 1 && weight > 0) { unsigned rand = su_randint(0, weight - 1); while (rand >= (*tail)->sq_weight) { rand -= (*tail)->sq_weight; tail = &(*tail)->sq_next; } } /* Remove selected */ sq = *tail; *tail = sq->sq_next; assert(sq->sq_priority == priority); /* Append at *at */ sq->sq_next = *at; *at = sq; at = &sq->sq_next; if (!*at) sr->sr_tail = at; SU_DEBUG_5(("nta: %s IN SRV %u %u %s %s (%s)\n", sq0->sq_domain, (unsigned)sq->sq_priority, (unsigned)sq->sq_weight, sq->sq_port, sq->sq_domain, sq->sq_proto)); } /* This is not needed anymore (?) */ sr->sr_current = NULL; sq0->sq_next = sr->sr_done; sr->sr_done = sq0; outgoing_resolve_next(orq); } #if SU_HAVE_IN6 /* Query AAAA records */ static int outgoing_query_aaaa(nta_outgoing_t *orq, struct sipdns_query *sq) { struct sipdns_resolver *sr = orq->orq_resolver; sres_record_t **answers; sr->sr_target = sq->sq_domain; sr->sr_current = sq; answers = sres_cached_answers(orq->orq_agent->sa_resolver, sres_type_aaaa, sq->sq_domain); SU_DEBUG_5(("nta: for \"%s\" query \"%s\" %s%s\n", orq->orq_tpn->tpn_host, sq->sq_domain, "AAAA", answers ? " (cached)" : "")); if (answers) { outgoing_answer_aaaa(orq, NULL, answers); return 0; } sr->sr_query = sres_query(orq->orq_agent->sa_resolver, outgoing_answer_aaaa, orq, sres_type_aaaa, sq->sq_domain); return outgoing_resolving(orq); } /* Process AAAA records */ static void outgoing_answer_aaaa(sres_context_t *orq, sres_query_t *q, sres_record_t *answers[]) { struct sipdns_resolver *sr = orq->orq_resolver; su_home_t *home = msg_home(orq->orq_request); struct sipdns_query *sq = sr->sr_current; size_t i, j, found; char *result, **results = NULL; assert(sq); assert(sq->sq_type == sres_type_aaaa); sr->sr_query = NULL; for (i = 0, found = 0; answers && answers[i]; i++) { sres_aaaa_record_t const *aaaa = answers[i]->sr_aaaa; if (aaaa->aaaa_record->r_status == 0 && aaaa->aaaa_record->r_type == sres_type_aaaa) found++; } if (found > 1) results = su_zalloc(home, (found + 1) * (sizeof *results)); else if (found) results = &result; for (i = j = 0; results && answers && answers[i]; i++) { char addr[SU_ADDRSIZE]; sres_aaaa_record_t const *aaaa = answers[i]->sr_aaaa; if (aaaa->aaaa_record->r_status || aaaa->aaaa_record->r_type != sres_type_aaaa) continue; /* There was an error */ su_inet_ntop(AF_INET6, &aaaa->aaaa_addr, addr, sizeof(addr)); if (j == 0) SU_DEBUG_5(("nta(%p): %s IN AAAA %s\n", (void *)orq, aaaa->aaaa_record->r_name, addr)); else SU_DEBUG_5(("nta(%p): AAAA %s\n", (void *)orq, addr)); assert(j < found); results[j++] = su_strdup(home, addr); } sres_free_answers(orq->orq_agent->sa_resolver, answers); outgoing_query_results(orq, sq, results, found); } #endif /* SU_HAVE_IN6 */ /* Query A records */ static int outgoing_query_a(nta_outgoing_t *orq, struct sipdns_query *sq) { struct sipdns_resolver *sr = orq->orq_resolver; sres_record_t **answers; sr->sr_target = sq->sq_domain; sr->sr_current = sq; answers = sres_cached_answers(orq->orq_agent->sa_resolver, sres_type_a, sq->sq_domain); SU_DEBUG_5(("nta: for \"%s\" query \"%s\" %s%s\n", orq->orq_tpn->tpn_host, sq->sq_domain, "A", answers ? " (cached)" : "")); if (answers) { outgoing_answer_a(orq, NULL, answers); return 0; } sr->sr_query = sres_query(orq->orq_agent->sa_resolver, outgoing_answer_a, orq, sres_type_a, sq->sq_domain); return outgoing_resolving(orq); } /* Process A records */ static void outgoing_answer_a(sres_context_t *orq, sres_query_t *q, sres_record_t *answers[]) { struct sipdns_resolver *sr = orq->orq_resolver; su_home_t *home = msg_home(orq->orq_request); struct sipdns_query *sq = sr->sr_current; int i, j, found; char *result, **results = NULL; assert(sq); assert(sq->sq_type == sres_type_a); sr->sr_query = NULL; for (i = 0, found = 0; answers && answers[i]; i++) { sres_a_record_t const *a = answers[i]->sr_a; if (a->a_record->r_status == 0 && a->a_record->r_type == sres_type_a) found++; } if (found > 1) results = su_zalloc(home, (found + 1) * (sizeof *results)); else if (found) results = &result; if (results == NULL) found = 0; for (i = j = 0; results && answers && answers[i]; i++) { char addr[SU_ADDRSIZE]; sres_a_record_t const *a = answers[i]->sr_a; if (a->a_record->r_status || a->a_record->r_type != sres_type_a) continue; /* There was an error */ su_inet_ntop(AF_INET, &a->a_addr, addr, sizeof(addr)); if (j == 0) SU_DEBUG_5(("nta: %s IN A %s\n", a->a_record->r_name, addr)); else SU_DEBUG_5(("nta(%p): A %s\n", (void *)orq, addr)); assert(j < found); results[j++] = su_strdup(home, addr); } sres_free_answers(orq->orq_agent->sa_resolver, answers); outgoing_query_results(orq, sq, results, found); } /** Store A/AAAA query results */ static void outgoing_query_results(nta_outgoing_t *orq, struct sipdns_query *sq, char *results[], size_t rlen) { struct sipdns_resolver *sr = orq->orq_resolver; if (sq->sq_type == sr->sr_a_aaaa1 && sq->sq_type != sr->sr_a_aaaa2) { sq->sq_type = sr->sr_a_aaaa2; SU_DEBUG_7(("nta(%p): %s %s record still unresolved\n", (void *)orq, sq->sq_domain, sq->sq_type == sres_type_a ? "A" : "AAAA")); /* * Three possible policies: * 1) try each host for AAAA/A, then A/AAAA * 2) try everything first for AAAA/A, then everything for A/AAAA * 3) try one SRV record results for AAAA/A, then for A/AAAA, * then next SRV record */ /* We use now policy #1 */ if (!(sq->sq_next = sr->sr_head)) sr->sr_tail = &sq->sq_next; sr->sr_head = sq; } else { sq->sq_next = sr->sr_done, sr->sr_done = sq; if (rlen == 0 && sq->sq_grayish) outgoing_graylist(orq, sq); } if (rlen > 1) sr->sr_results = results; else sr->sr_current = NULL; if (orq->orq_completed) return; if (rlen > 0) { orq->orq_resolved = 1; orq->orq_tpn->tpn_host = results[0]; if (sq->sq_proto) orq->orq_tpn->tpn_proto = sq->sq_proto; if (sq->sq_port[0]) orq->orq_tpn->tpn_port = sq->sq_port; outgoing_prepare_send(orq); } else { outgoing_resolve_next(orq); } } #endif /* ====================================================================== */ /* 10) Reliable responses */ static nta_prack_f nta_reliable_destroyed; /** * Check that server transaction can be used to send reliable provisional * responses. */ su_inline int reliable_check(nta_incoming_t *irq) { if (irq == NULL || irq->irq_status >= 200 || !irq->irq_agent) return 0; if (irq->irq_reliable && irq->irq_reliable->rel_status >= 200) return 0; /* @RSeq is initialized to nonzero when request requires/supports 100rel */ if (irq->irq_rseq == 0) return 0; if (irq->irq_rseq == 0xffffffffU) /* already sent >> 2**31 responses */ return 0; return 1; } /** Respond reliably. * * @param irq * @param callback * @param rmagic * @param status * @param phrase * @param tag, value, .. */ nta_reliable_t *nta_reliable_treply(nta_incoming_t *irq, nta_prack_f *callback, nta_reliable_magic_t *rmagic, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...) { ta_list ta; msg_t *msg; sip_t *sip; nta_reliable_t *retval = NULL; if (!reliable_check(irq) || (status <= 100 || status >= 200)) return NULL; msg = nta_msg_create(irq->irq_agent, 0); sip = sip_object(msg); if (!sip) return NULL; ta_start(ta, tag, value); if (0 > nta_incoming_complete_response(irq, msg, status, phrase, ta_tags(ta))) msg_destroy(msg); else if (!(retval = reliable_mreply(irq, callback, rmagic, msg, sip))) msg_destroy(msg); ta_end(ta); return retval; } /** Respond reliably with @a msg. * * @note * The stack takes over the ownership of @a msg. (It is destroyed even if * sending the response fails.) * * @param irq * @param callback * @param rmagic * @param msg */ nta_reliable_t *nta_reliable_mreply(nta_incoming_t *irq, nta_prack_f *callback, nta_reliable_magic_t *rmagic, msg_t *msg) { sip_t *sip = sip_object(msg); if (!reliable_check(irq)) { msg_destroy(msg); return NULL; } if (sip == NULL || !sip->sip_status || sip->sip_status->st_status <= 100) { msg_destroy(msg); return NULL; } if (sip->sip_status->st_status >= 200) { incoming_final_failed(irq, msg); return NULL; } return reliable_mreply(irq, callback, rmagic, msg, sip); } static nta_reliable_t *reliable_mreply(nta_incoming_t *irq, nta_prack_f *callback, nta_reliable_magic_t *rmagic, msg_t *msg, sip_t *sip) { nta_reliable_t *rel; nta_agent_t *agent; agent = irq->irq_agent; if (callback == NULL) callback = nta_reliable_destroyed; rel = su_zalloc(agent->sa_home, sizeof(*rel)); if (rel) { rel->rel_irq = irq; rel->rel_callback = callback; rel->rel_magic = rmagic; rel->rel_unsent = msg; rel->rel_status = sip->sip_status->st_status; rel->rel_precious = sip->sip_payload != NULL; rel->rel_next = irq->irq_reliable; /* * If there already is a un-pr-acknowledged response, queue this one * until at least one response is pr-acknowledged. */ if (irq->irq_reliable && (irq->irq_reliable->rel_next == NULL || irq->irq_reliable->rel_rseq == 0)) { return irq->irq_reliable = rel; } if (reliable_send(irq, rel, msg_ref(msg), sip) < 0) { msg_destroy(msg); su_free(agent->sa_home, rel); return NULL; } irq->irq_reliable = rel; return callback ? rel : (nta_reliable_t *)-1; } msg_destroy(msg); return NULL; } static int reliable_send(nta_incoming_t *irq, nta_reliable_t *rel, msg_t *msg, sip_t *sip) { nta_agent_t *sa = irq->irq_agent; su_home_t *home = msg_home(msg); sip_rseq_t rseq[1]; sip_rseq_init(rseq); if (sip->sip_require) msg_header_replace_param(home, sip->sip_require->k_common, "100rel"); else sip_add_make(msg, sip, sip_require_class, "100rel"); rel->rel_rseq = rseq->rs_response = irq->irq_rseq; sip_add_dup(msg, sip, (sip_header_t *)rseq); if (!sip->sip_rseq || incoming_reply(irq, msg, sip) < 0) { msg_destroy(msg); return -1; } irq->irq_rseq++; if (irq->irq_queue == sa->sa_in.preliminary) /* Make sure we are moved to the tail */ incoming_remove(irq); incoming_queue(sa->sa_in.preliminary, irq); /* P1 */ incoming_set_timer(irq, sa->sa_t1); /* P2 */ return 0; } /** Queue final response when there are unsent precious preliminary responses */ static int reliable_final(nta_incoming_t *irq, msg_t *msg, sip_t *sip) { nta_reliable_t *r; unsigned already_in_callback; /* * We delay sending final response if it's 2XX and * an unpracked reliable response contains session description */ /* Get last unpracked response from queue */ if (sip->sip_status->st_status < 300) for (r = irq->irq_reliable; r; r = r->rel_next) if (r->rel_unsent && r->rel_precious) { /* Delay sending 2XX */ reliable_mreply(irq, NULL, NULL, msg, sip); return 0; } /* Flush unsent responses. */ already_in_callback = irq->irq_in_callback; irq->irq_in_callback = 1; reliable_flush(irq); irq->irq_in_callback = already_in_callback; if (!already_in_callback && irq->irq_terminated && irq->irq_destroyed) { incoming_free(irq); msg_destroy(msg); return 0; } return 1; } /** Get latest reliably sent response */ static msg_t *reliable_response(nta_incoming_t *irq) { nta_reliable_t *r, *rel; /* Get last unpracked response from queue */ for (rel = NULL, r = irq->irq_reliable; r; r = r->rel_next) if (!r->rel_pracked) rel = r; assert(rel); return rel->rel_unsent; } /* Find un-PRACKed responses */ static nta_reliable_t *reliable_find(nta_agent_t const *agent, sip_t const *sip) { incoming_htable_t const *iht = agent->sa_incoming; nta_incoming_t *irq, **ii; sip_call_id_t const *i = sip->sip_call_id; sip_rack_t const *rack = sip->sip_rack; hash_value_t hash = NTA_HASH(i, rack->ra_cseq); /* XXX - add own hash table for 100rel */ for (ii = incoming_htable_hash(iht, hash); (irq = *ii); ii = incoming_htable_next(iht, ii)) { if (hash == irq->irq_hash && irq->irq_call_id->i_hash == i->i_hash && irq->irq_cseq->cs_seq == rack->ra_cseq && irq->irq_method == sip_method_invite && strcmp(irq->irq_call_id->i_id, i->i_id) == 0 && (irq->irq_to->a_tag == NULL || su_casematch(irq->irq_to->a_tag, sip->sip_to->a_tag)) && su_casematch(irq->irq_from->a_tag, sip->sip_from->a_tag)) { nta_reliable_t const *rel; /* Found matching INVITE */ for (rel = irq->irq_reliable; rel; rel = rel->rel_next) if (rel->rel_rseq == rack->ra_response) return (nta_reliable_t *)rel; return NULL; } } return NULL; } /** Process incoming PRACK with matching @RAck field */ static int reliable_recv(nta_reliable_t *rel, msg_t *msg, sip_t *sip, tport_t *tp) { nta_incoming_t *irq = rel->rel_irq; nta_incoming_t *pr_irq; int status; rel->rel_pracked = 1; msg_unref(rel->rel_unsent), rel->rel_unsent = NULL; pr_irq = incoming_create(irq->irq_agent, msg, sip, tp, irq->irq_tag); if (!pr_irq) { mreply(irq->irq_agent, NULL, SIP_500_INTERNAL_SERVER_ERROR, msg, tp, 0, 0, NULL, TAG_END()); return 0; } if (irq->irq_status < 200) { incoming_queue(irq->irq_agent->sa_in.proceeding, irq); /* Reset P1 */ incoming_reset_timer(irq); /* Reset P2 */ } irq->irq_in_callback = pr_irq->irq_in_callback = 1; status = rel->rel_callback(rel->rel_magic, rel, pr_irq, sip); rel = NULL; irq->irq_in_callback = pr_irq->irq_in_callback = 0; if (pr_irq->irq_completed) { /* Already sent final response */ if (pr_irq->irq_terminated && pr_irq->irq_destroyed) incoming_free(pr_irq); } else if (status != 0) { if (status < 200 || status > 299) { SU_DEBUG_3(("nta_reliable(): invalid status %03d from callback\n", status)); status = 200; } nta_incoming_treply(pr_irq, status, "OK", TAG_END()); nta_incoming_destroy(pr_irq); } /* If there are queued unsent reliable responses, send them all. */ while (irq->irq_reliable && irq->irq_reliable->rel_rseq == 0) { nta_reliable_t *r; for (r = irq->irq_reliable; r; r = r->rel_next) if (r->rel_rseq == 0) rel = r; msg = rel->rel_unsent, sip = sip_object(msg); if (sip->sip_status->st_status < 200) { if (reliable_send(irq, rel, msg_ref(msg), sip) < 0) { assert(!"send reliable response"); } } else { /* * XXX * Final response should be delayed until a reliable provisional * response has been pracked */ rel->rel_unsent = NULL, rel->rel_rseq = (uint32_t)-1; if (incoming_reply(irq, msg, sip) < 0) { assert(!"send delayed final response"); } } } return 0; } /** Flush unacknowledged and unsent reliable responses */ void reliable_flush(nta_incoming_t *irq) { nta_reliable_t *r, *rel; do { for (r = irq->irq_reliable, rel = NULL; r; r = r->rel_next) if (r->rel_unsent) rel = r; if (rel) { rel->rel_pracked = 1; msg_unref(rel->rel_unsent), rel->rel_unsent = NULL; rel->rel_callback(rel->rel_magic, rel, NULL, NULL); } } while (rel); } void reliable_timeout(nta_incoming_t *irq, int timeout) { if (timeout) SU_DEBUG_5(("nta: response timeout with %u\n", irq->irq_status)); irq->irq_in_callback = 1; reliable_flush(irq); if (irq->irq_callback) irq->irq_callback(irq->irq_magic, irq, NULL); irq->irq_in_callback = 0; if (!timeout) return; if (irq->irq_completed && irq->irq_destroyed) incoming_free(irq), irq = NULL; else if (irq->irq_status < 200) nta_incoming_treply(irq, 503, "Reliable Response Time-Out", TAG_END()); } #if 0 /* Not needed, yet. */ /** Use this callback when normal leg callback is supposed to * process incoming PRACK requests */ int nta_reliable_leg_prack(nta_reliable_magic_t *magic, nta_reliable_t *rel, nta_incoming_t *irq, sip_t const *sip) { nta_agent_t *agent; nta_leg_t *leg; char const *method_name; url_t url[1]; int retval; if (irq == NULL || sip == NULL || rel == NULL || sip_object(irq->irq_request) != sip) return 500; agent = irq->irq_agent; method_name = sip->sip_request->rq_method_name; *url = *sip->sip_request->rq_url; url->url_params = NULL; agent_aliases(agent, url, irq->irq_tport); /* canonize urls */ if ((leg = leg_find(irq->irq_agent, method_name, url, sip->sip_call_id, sip->sip_from->a_tag, sip->sip_to->a_tag))) { /* Use existing dialog */ SU_DEBUG_5(("nta: %s (%u) %s\n", method_name, sip->sip_cseq->cs_seq, "PRACK processed by default callback, too")); retval = leg->leg_callback(leg->leg_magic, leg, irq, sip); } else { retval = 500; } nta_reliable_destroy(rel); return retval; } #endif /** Destroy a reliable response. * * Mark a reliable response object for destroyal and free it if possible. */ void nta_reliable_destroy(nta_reliable_t *rel) { if (rel == NULL || rel == NONE) return; if (rel->rel_callback == nta_reliable_destroyed) SU_DEBUG_1(("%s(%p): %s\n", __func__, (void *)rel, "already destroyed")); rel->rel_callback = nta_reliable_destroyed; if (rel->rel_response) return; nta_reliable_destroyed(NULL, rel, NULL, NULL); } /** Free and unallocate the nta_reliable_t structure. */ static int nta_reliable_destroyed(nta_reliable_magic_t *rmagic, nta_reliable_t *rel, nta_incoming_t *prack, sip_t const *sip) { nta_reliable_t **prev; assert(rel); assert(rel->rel_irq); for (prev = &rel->rel_irq->irq_reliable; *prev; prev = &(*prev)->rel_next) if (*prev == rel) break; if (!*prev) { assert(*prev); SU_DEBUG_1(("%s(%p): %s\n", __func__, (void *)rel, "not linked")); return 200; } *prev = rel->rel_next; if (rel->rel_unsent) msg_destroy(rel->rel_unsent), rel->rel_unsent = NULL; su_free(rel->rel_irq->irq_agent->sa_home, rel); return 200; } /** Validate a reliable response. */ int outgoing_recv_reliable(nta_outgoing_t *orq, msg_t *msg, sip_t *sip) { short status = sip->sip_status->st_status; char const *phrase = sip->sip_status->st_phrase; uint32_t rseq = sip->sip_rseq->rs_response; SU_DEBUG_7(("nta: %03u %s is reliably received with RSeq: %u\n", status, phrase, rseq)); /* Cannot handle reliable responses unless we have a full dialog */ if (orq->orq_rseq == 0 && !orq->orq_to->a_tag) { SU_DEBUG_5(("nta: %03u %s with initial RSeq: %u outside dialog\n", status, phrase, rseq)); return 0; } if (rseq <= orq->orq_rseq) { SU_DEBUG_3(("nta: %03u %s already received (RSeq: %u, expecting %u)\n", status, phrase, rseq, orq->orq_rseq + 1)); return -1; } if (orq->orq_rseq && orq->orq_rseq + 1 != rseq) { SU_DEBUG_3(("nta: %03d %s is not expected (RSeq: %u, expecting %u)\n", status, sip->sip_status->st_phrase, rseq, orq->orq_rseq + 1)); return -1; } return 0; } /** Create a tagged fork of outgoing request. * * When a dialog-creating INVITE request is forked, each response from * diffent fork will create an early dialog with a distinct tag in @To * header. When each fork should be handled separately, a tagged INVITE * request can be used. It will only receive responses from the specified * fork. Please note that the tagged transaction should be terminated with * the final response from another fork, too. * * @param orq * @param callback * @param magic * @param to_tag * @param rseq * * @bug Fix the memory leak - either one of the requests is left unreleased * for ever. */ nta_outgoing_t *nta_outgoing_tagged(nta_outgoing_t *orq, nta_response_f *callback, nta_outgoing_magic_t *magic, char const *to_tag, sip_rseq_t const *rseq) { nta_agent_t *agent; su_home_t *home; nta_outgoing_t *tagged; sip_to_t *to; if (orq == NULL || to_tag == NULL) return NULL; if (orq->orq_to->a_tag) { SU_DEBUG_1(("%s: transaction %p (CSeq: %s %u) already in dialog\n", __func__, (void *)orq, orq->orq_cseq->cs_method_name, orq->orq_cseq->cs_seq)); return NULL; } if (orq->orq_method != sip_method_invite) { SU_DEBUG_1(("%s: transaction %p (CSeq: %s %u) cannot be tagged\n", __func__, (void *)orq, orq->orq_cseq->cs_method_name, orq->orq_cseq->cs_seq)); return NULL; } if (orq->orq_status < 100) { SU_DEBUG_1(("%s: transaction %p (CSeq: %s %u) still calling\n", __func__, (void *)orq, orq->orq_cseq->cs_method_name, orq->orq_cseq->cs_seq)); return NULL; } assert(orq->orq_agent); assert(orq->orq_request); agent = orq->orq_agent; tagged = su_zalloc(agent->sa_home, sizeof(*tagged)); if (!tagged) return NULL; home = msg_home((msg_t *)orq->orq_request); tagged->orq_hash = orq->orq_hash; tagged->orq_agent = orq->orq_agent; tagged->orq_callback = callback; tagged->orq_magic = magic; tagged->orq_method = orq->orq_method; tagged->orq_method_name = orq->orq_method_name; tagged->orq_url = orq->orq_url; tagged->orq_from = orq->orq_from; sip_to_tag(home, to = sip_to_copy(home, orq->orq_to), to_tag); tagged->orq_to = to; tagged->orq_tag = to->a_tag; tagged->orq_cseq = orq->orq_cseq; tagged->orq_call_id = orq->orq_call_id; tagged->orq_request = msg_ref(orq->orq_request); tagged->orq_response = msg_ref(orq->orq_response); tagged->orq_status = orq->orq_status; tagged->orq_via_added = orq->orq_via_added; tagged->orq_prepared = orq->orq_prepared; tagged->orq_reliable = orq->orq_reliable; tagged->orq_sips = orq->orq_sips; tagged->orq_uas = orq->orq_uas; tagged->orq_pass_100 = orq->orq_pass_100; tagged->orq_must_100rel = orq->orq_must_100rel; tagged->orq_100rel = orq->orq_100rel; tagged->orq_route = orq->orq_route; *tagged->orq_tpn = *orq->orq_tpn; tagged->orq_tport = tport_ref(orq->orq_tport); if (orq->orq_cc) tagged->orq_cc = nta_compartment_ref(orq->orq_cc); tagged->orq_branch = orq->orq_branch; tagged->orq_via_branch = orq->orq_via_branch; if (tagged->orq_uas) { tagged->orq_forking = orq; tagged->orq_forks = orq->orq_forks; tagged->orq_forked = 1; orq->orq_forks = tagged; } outgoing_insert(agent, tagged); return tagged; } /**PRACK a provisional response. * * Create and send a PRACK request used to acknowledge a provisional * response. * * The request is sent using the route of the original request @a oorq. * * When NTA receives response to the prack request, it invokes the @a * callback function. * * @param leg dialog object * @param oorq original transaction request * @param callback callback function (may be @c NULL) * @param magic application context pointer * @param route_url optional URL used to route transaction requests * @param resp (optional) response message to be acknowledged * @param tag,value,... optional * * @return * If successful, return a pointer to newly created client transaction * object for PRACK request, NULL otherwise. * * @sa * nta_outgoing_tcreate(), nta_outgoing_tcancel(), nta_outgoing_destroy(). */ nta_outgoing_t *nta_outgoing_prack(nta_leg_t *leg, nta_outgoing_t *oorq, nta_response_f *callback, nta_outgoing_magic_t *magic, url_string_t const *route_url, sip_t const *resp, tag_type_t tag, tag_value_t value, ...) { ta_list ta; msg_t *msg; su_home_t *home; sip_t *sip; sip_to_t const *to = NULL; sip_route_t *route = NULL, r0[1]; nta_outgoing_t *orq = NULL; sip_rack_t *rack = NULL, rack0[1]; if (!leg || !oorq) { SU_DEBUG_1(("%s: invalid arguments\n", __func__)); return NULL; } sip_rack_init(rack0); if (resp) { if (!resp->sip_status) { SU_DEBUG_1(("%s: invalid arguments\n", __func__)); return NULL; } if (resp->sip_status->st_status <= 100 || resp->sip_status->st_status >= 200) { SU_DEBUG_1(("%s: %u response cannot be PRACKed\n", __func__, resp->sip_status->st_status)); return NULL; } if (!resp->sip_rseq) { SU_DEBUG_1(("%s: %u response missing RSeq\n", __func__, resp->sip_status->st_status)); return NULL; } if (resp->sip_rseq->rs_response <= oorq->orq_rseq) { SU_DEBUG_1(("%s: %u response RSeq does not match received RSeq\n", __func__, resp->sip_status->st_status)); return NULL; } if (!oorq->orq_must_100rel && !sip_has_feature(resp->sip_require, "100rel")) { SU_DEBUG_1(("%s: %u response does not require 100rel\n", __func__, resp->sip_status->st_status)); return NULL; } if (!resp->sip_to->a_tag) { SU_DEBUG_1(("%s: %u response has no To tag\n", __func__, resp->sip_status->st_status)); return NULL; } if (su_strcasecmp(resp->sip_to->a_tag, leg->leg_remote->a_tag) || su_strcasecmp(resp->sip_to->a_tag, oorq->orq_to->a_tag)) { SU_DEBUG_1(("%s: %u response To tag does not agree with dialog tag\n", __func__, resp->sip_status->st_status)); return NULL; } to = resp->sip_to; rack = rack0; rack->ra_response = resp->sip_rseq->rs_response; rack->ra_cseq = resp->sip_cseq->cs_seq; rack->ra_method = resp->sip_cseq->cs_method; rack->ra_method_name = resp->sip_cseq->cs_method_name; } msg = nta_msg_create(leg->leg_agent, 0); sip = sip_object(msg); home = msg_home(msg); if (!sip) return NULL; if (!leg->leg_route && resp) { /* Insert contact into route */ if (resp->sip_contact) { sip_route_init(r0)->r_url[0] = resp->sip_contact->m_url[0]; route = sip_route_dup(home, r0); } /* Reverse record route */ if (resp->sip_record_route) { sip_route_t *r, *r_next; for (r = sip_route_dup(home, resp->sip_record_route); r; r = r_next) { r_next = r->r_next, r->r_next = route, route = r; } } } ta_start(ta, tag, value); if (!resp) { tagi_t const *t; if ((t = tl_find(ta_args(ta), ntatag_rseq)) && t->t_value) { rack = rack0; rack->ra_response = (uint32_t)t->t_value; } if (rack) { rack->ra_cseq = oorq->orq_cseq->cs_seq; rack->ra_method = oorq->orq_cseq->cs_method; rack->ra_method_name = oorq->orq_cseq->cs_method_name; } } if (sip_add_tl(msg, sip, TAG_IF(rack, SIPTAG_RACK(rack)), TAG_IF(to, SIPTAG_TO(to)), ta_tags(ta)) < 0) ; else if (route && sip_add_dup(msg, sip, (sip_header_t *)route) < 0) ; else if (!sip->sip_rack) SU_DEBUG_1(("%s: RAck header missing\n", __func__)); else if (nta_msg_request_complete(msg, leg, SIP_METHOD_PRACK, (url_string_t *)oorq->orq_url) < 0) ; else orq = outgoing_create(leg->leg_agent, callback, magic, route_url, NULL, msg, ta_tags(ta)); ta_end(ta); if (!orq) msg_destroy(msg); else if (rack) oorq->orq_rseq = rack->ra_response; else if (sip->sip_rack) oorq->orq_rseq = sip->sip_rack->ra_response; return orq; } /** Get @RSeq value stored with client transaction. */ uint32_t nta_outgoing_rseq(nta_outgoing_t const *orq) { return orq ? orq->orq_rseq : 0; } /** Set @RSeq value stored with client transaction. * * @return 0 if rseq was set successfully * @return -1 if rseq is invalid or orq is NULL. */ int nta_outgoing_setrseq(nta_outgoing_t *orq, uint32_t rseq) { if (orq && orq->orq_rseq <= rseq) { orq->orq_rseq = rseq; return 0; } return -1; } /* ------------------------------------------------------------------------ */ /* 11) SigComp handling and public transport interface */ #include /** Return the master transport for the agent. * * @NEW_1_12_11 */ tport_t * nta_agent_tports(nta_agent_t *agent) { return agent ? agent->sa_tports : NULL; } su_inline tport_t * nta_transport_(nta_agent_t *agent, nta_incoming_t *irq, msg_t *msg) { if (irq) return irq->irq_tport; else if (agent && msg) return tport_delivered_by(agent->sa_tports, msg); errno = EINVAL; return NULL; } /** Return a new reference to the transaction transport. * * @note The referenced transport must be unreferenced with tport_unref() */ tport_t * nta_incoming_transport(nta_agent_t *agent, nta_incoming_t *irq, msg_t *msg) { return tport_ref(nta_transport_(agent, irq, msg)); } nta_compressor_t *nta_agent_init_sigcomp(nta_agent_t *sa) { if (!nta_compressor_vtable || !sa) return NULL; if (sa->sa_compressor == NULL) { char const * const *l = sa->sa_sigcomp_option_list; nta_compressor_t *comp; comp = nta_compressor_vtable->ncv_init_agent(sa, l); sa->sa_compressor = comp; } return sa->sa_compressor; } void nta_agent_deinit_sigcomp(nta_agent_t *sa) { if (nta_compressor_vtable && sa && sa->sa_compressor) { nta_compressor_vtable->ncv_deinit_agent(sa, sa->sa_compressor); sa->sa_compressor = NULL; } } struct sigcomp_compartment * nta_incoming_compartment(nta_incoming_t *irq) { if (nta_compressor_vtable && irq && irq->irq_cc) return nta_compressor_vtable->ncv_compartment_ref(irq->irq_cc); else return NULL; } tport_t * nta_outgoing_transport(nta_outgoing_t *orq) { if (orq) return tport_ref(orq->orq_tport); else return NULL; } struct sigcomp_compartment * nta_outgoing_compartment(nta_outgoing_t *orq) { if (nta_compressor_vtable && orq && orq->orq_cc) return nta_compressor_vtable->ncv_compartment_ref(orq->orq_cc); else return NULL; } struct sigcomp_compartment * nta_compartment_ref(struct sigcomp_compartment *cc) { if (nta_compressor_vtable) return nta_compressor_vtable->ncv_compartment_ref(cc); else return NULL; } void nta_compartment_decref(struct sigcomp_compartment **pcc) { if (nta_compressor_vtable && pcc && *pcc) nta_compressor_vtable->ncv_compartment_unref(*pcc), *pcc = NULL; } /** Get compartment for connection, create it when needed. */ static struct sigcomp_compartment * agent_compression_compartment(nta_agent_t *sa, tport_t *tp, tp_name_t const *tpn, int new_if_needed) { if (nta_compressor_vtable) { char const * const *l = sa->sa_sigcomp_option_list; return nta_compressor_vtable-> ncv_compartment(sa, tp, sa->sa_compressor, tpn, l, new_if_needed); } else return NULL; } static int agent_accept_compressed(nta_agent_t *sa, msg_t *msg, struct sigcomp_compartment *cc) { if (nta_compressor_vtable) { nta_compressor_t *msc = sa->sa_compressor; tport_compressor_t *sc = NULL; if (tport_delivered_with_comp(sa->sa_tports, msg, &sc) < 0) return 0; return nta_compressor_vtable->ncv_accept_compressed(sa, msc, sc, msg, cc); } else return 0; } /** Close compressor (lose its state). */ static int agent_close_compressor(nta_agent_t *sa, struct sigcomp_compartment *cc) { if (nta_compressor_vtable) return nta_compressor_vtable->ncv_close_compressor(sa, cc); return 0; } /** Close both compressor and decompressor */ static int agent_zap_compressor(nta_agent_t *sa, struct sigcomp_compartment *cc) { if (nta_compressor_vtable) return nta_compressor_vtable->ncv_zap_compressor(sa, cc); return 0; } /** Bind transport update callback */ int nta_agent_bind_tport_update(nta_agent_t *agent, nta_update_magic_t *magic, nta_update_tport_f *callback) { if (!agent) return su_seterrno(EFAULT); agent->sa_update_magic = magic; agent->sa_update_tport = callback; return 0; } /** Check if public transport binding is in progress */ int nta_agent_tport_is_updating(nta_agent_t *agent) { return agent && tport_is_updating(agent->sa_tports); } /** Initiate STUN keepalive controller to TPORT */ int nta_tport_keepalive(nta_outgoing_t *orq) { assert(orq); #if HAVE_SOFIA_STUN return tport_keepalive(orq->orq_tport, msg_addrinfo(orq->orq_request), TAG_END()); #else return -1; #endif } /** Close all transports. @since Experimental in @VERSION_1_12_2. */ int nta_agent_close_tports(nta_agent_t *agent) { size_t i; outgoing_htable_t *oht = agent->sa_outgoing; incoming_htable_t *iht = agent->sa_incoming; for (i = oht->oht_size; i-- > 0;) /* while */ if (oht->oht_table[i]) { nta_outgoing_t *orq = oht->oht_table[i]; if (orq->orq_pending && orq->orq_tport) tport_release(orq->orq_tport, orq->orq_pending, orq->orq_request, NULL, orq, 0); orq->orq_pending = 0; tport_unref(orq->orq_tport), orq->orq_tport = NULL; } for (i = iht->iht_size; i-- > 0;) /* while */ if (iht->iht_table[i]) { nta_incoming_t *irq = iht->iht_table[i]; tport_unref(irq->irq_tport), irq->irq_tport = NULL; } tport_destroy(agent->sa_tports), agent->sa_tports = NULL; msg_header_free(agent->sa_home, (void *)agent->sa_vias); agent->sa_vias = NULL; msg_header_free(agent->sa_home, (void *)agent->sa_public_vias); agent->sa_public_vias = NULL; return 0; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/nta.docs000066400000000000000000000533401223300710500217750ustar00rootroot00000000000000/* -*- c -*- */ /**@MODULEPAGE "nta" - SIP Transactions Module * * @section nta_meta Module Meta Information * * Sofia SIP Transaction API (nta) provides simple interface to the SIP * transaction, transport and message handling. The @b nta interface is * intended for both network and user elements. The public interface for @b * nta is mostly defined in , but tag parameters are * defined in . * * @CONTACT Pekka Pessi * * @STATUS @SofiaSIP Core library * * @LICENSE LGPL * * @section nta_objects NTA Objects * * The NTA deals with a few kinds of objects: @e agent (#nta_agent_t), @e * call @e legs (#nta_leg_t), @e outgoing @e client @e requests * (#nta_outgoing_t), and @e incoming @e server @e requests * (#nta_incoming_t). * * NTA also uses SIP message objects #msg_t and #sip_t for handling * messages, as defined in and , * respectively. The various SIP headers are also defined in * . * * @section nta_agent_t Creating an NTA Agent * * Most of the SIP entities, like @e user @e agent or @e proxy, consist of a * SIP server and a SIP client working together. The NTA provides a simple * interface to SIP server and client with the #nta_agent_t objects. * * The #nta_agent_t object is created by calling nta_agent_create(). The * object listens for incoming connections, receives messages, parses them, * and pass them to the application. It also takes care of resolving the * domain names and sending the messages. * * The agent needs a #su_root_t object to schedule its execution. A root * object is used to wait for the network events, schedule the timer * routines, and pass messages asyncronously. A root object can be created * by, e.g., the function su_root_create(). The root object can be have its * own thread, or its main loop can be executed by an application thread by * calling the function su_root_run(). The main loop can be terminated by * calling the function su_root_break(). * * A simple agent could be created as follows: * @code * registrar->reg_root = su_root_create(NULL); * * if (registrar->reg_root) { * registrar->reg_agent = nta_agent_create(registrar->reg_root, * (url_string_t*)argv[1], * NULL, * NULL, * NULL); * * if (registrar->reg_agent) { * su_root_run(registrar->reg_root); * nta_agent_destroy(registrar->reg_agent); * } * * su_root_destroy(registrar->reg_root); * } * @endcode * * @section nta_server SIP Server Action * * A SIP server responds to the transactions sent by a client. The SIP * server can operate in two modes; it can be stateless or stateful. This * section describes how a stateful SIP server uses NTA. * * @subsection nta_leg_t The NTA Legs * * A leg is required for stateful transaction processing. A default * leg is created like this: * @code * default_leg = nta_leg_tcreate(agent, process_requests, context, * URLTAG_URL(url), * NTATAG_NO_DIALOG(1), * TAG_END()); * @endcode * * The @a url parameter is used to specify which URLs match to the leg. If * it is given, only requests with requestURI matching are processed by the * leg. The nta_leg_tcreate() is a @ref tagarg "tagarg" function, taking a * tagged argument list as its arguments. * * Other, ordinary legs can be used to match incoming requests with existing * dialogs, calls or transaction contexts, or to provide outgoing requests * with consistent headers. When a call leg is created, it is provided with * @From and @To headers, and optionally with other headers like * @CallID, @Route, or @CSeq. * * A new call leg can be created as follows: * @code * call_leg = nta_leg_tcreate(agent, * process_call_requests, call_context, * SIPTAG_CALL_ID(sip->sip_call_id), * SIPTAG_TO(sip->sip_from), * SIPTAG_FROM(sip->sip_to), * TAG_END()); * @endcode * * @note In the example above, the @From and @To are reversed. This * happens if the headers are taken from an incoming request; the @From * and @To headers change direction when an outgoing request is initiated. * * @note An existing leg can be used in any direction, however. If the leg * was created for an incoming INVITE transaction, it is also possible to * use the leg for an outgoing BYE transaction. * * @subsection nta_leg_tag Tagging the Call Leg * * All the SIP UAS elements are required to tag the @To header in their * final responses. The function nta_leg_tag() adds a tag to the leg's local * address. Local address is used as the @To header in the reply messages, * and as the @From header in the requests. The function nta_incoming_tag() * adds a tag to a incoming transaction. They are usually used in together, * using the tag from initial response to the dialog, too: * e.g., * @code * if (!nta_leg_tag(leg, nta_incoming_tag(irq, NULL))) * nta_incoming_treply(irq, SIP_500_INTERNAL_SERVER_ERROR, TAG_END()); * @endcode * * @subsection nta_incoming_t Incoming Transactions * * An incoming transaction object (nta_incoming_t) is created by NTA for * each unique incoming request message. When NTA has created the incoming * transaction object, it invokes the callback function provided with * nta_leg_tcreate(). * * The simplest way to reply to the request is to return a valid status code * from the callback function. Valid status codes are in range of 100 to * 699, inclusive. If no automatic response is desired, the callback * function should return 0. * * @note If the status code is final, the incoming transaction object will * be destroyed immediately after the callback function returns. It can not * be used afterwards. * * @note It is not possible to respond with a 2xx status code to an incoming * INVITE transaction by returning the status code from the callback. * * Valid return values for callback function are as follows: * @li 0, 100 .. 699 for requests other than INVITE, and * @li 0, 100 .. 199, 300..699 for INVITE requests. * * All other return codes are interpreted as 500, that is, a @e 500 @e * Internal @e Server @e Error reply message is sent back to the client and * the request is immediately destroyed. * * The simple registrar/redirect server may have a incoming request callback * as follows: * @code * int process_request(server_t *server, * nta_leg_t *leg, * nta_incoming_t *irq, * sip_t const *sip) * { * sip_contact_t *m; * * switch (sip->sip_request->rq_method) { * case sip_method_register: * return registrar_add(server, leg, reply, sip); * * case sip_method_ack: * return 500; * * case sip_method_cancel: * return 200; * * default: * if (registrar_find(server, sip->sip_request->rq_url, &m) { * nta_incoming_treply(irq, SIP_302_MOVED_TEMPORARILY, * SIPTAG_CONTACT(m), TAG_END()); * return 302; * } * else { * nta_incoming_treply(irq, SIP_404_NOT_FOUND, TAG_END()); * return 404; * } * } * } * @endcode * * The default reply message will contain the status line with default * phrase, then @Via, @To, @From, @CallID, @CSeq, and @ContentLength headers. * If a more complex response message is required, the application should * respond using the function nta_incoming_treply(): * @code * nta_incoming_treply(reply, SIP_200_OK, * SIPTAG_CONTACT(contact), * SIPTAG_CONTENT_TYPE_STR("application/sdp"), * SIPTAG_PAYLOAD(sdp), * TAG_END()); * @endcode * * The nta_incoming_treply() is a @ref tagarg "tagarg" function, taking a * tagged argument list as its argument. * * @note It is possible to send provisional replies (containing 1xx status * codes) several times with nta_incoming_treply(), but only one final * reply (containing status codes 2xx..6xx) can be sent. However, with * INVITE requests, a proxy can send a final 2xx reply even after an error * reply (3xx..6xx). * * @section nta_100rel Reliable Provisional Responses - "100rel" * * The
100rel SIP extension * provides reliable provisional responses, provisional responses that are * retransmitted until a special acknowledgement request, PRACK, is * received. In addition the PRACK method, the extension defines two * headers, @RSeq and @RAck, that are used to identify different * response messages. PRACK method is usable on INVITE requests only. * * Using reliable responses is negotiated using the "100rel" option tag. The * UAC (party sending the INVITE) can include the option tag to the * @Supported or @Require header. In the first case, the UAC just * announces support for reliable responses, in the second case, the UAC * requires that the UAS (party responding to the call) always sends * provisional responses in reliable manner. * * When reliable responses are enabled with NTATAG_REL100() tag, the @b nta * engine automatically inserts the "100rel" option tag to the @Supported * header in the INVITE requests. * * @subsection nta_reliable_t Responding Reliably * * When a UAS wants to respond reliably to a INVITE request, instead of * familiar nta_incoming_treply() or nta_incoming_mreply() it uses the * functions nta_reliable_treply() or nta_reliable_mreply(). These functions * return a pointer to a special object, nta_reliable_t, that is used to * keep track of unacknowledged responses and respond to the the PRACK * acknowledgement request. * * Both the functions nta_reliable_treply () and nta_reliable_mreply() take * a callback funtion pointer and an application context pointer as their * arguments. The callback function is similar to the leg callback function. * The callback is invoked when a corresponding PRACK request is received, * or when there is a timeout. * * The @b nta takes care of assigning a serial number to each reliable * response and resending them if no PRACK request is received. It also * automatically adds the 100rel option tag to the @Require header. * * Also, if a request with 100rel in @Require header is responded with usual * nta_incoming_treply()/nta_incoming_mreply() functions, the @b nta creates * a reliable response object for each provisional response in behalf of * application. As the application can not provide a PRACK callback function * to @b nta, the PRACK requests are not delivered to the application. * * @subsection early_dialog UAC Receives a Reliable Response * * When a UAC receives a provisional response with a @RSeq header, it is * required to acknowledge it. In order to do that, it must establish an @e * early @e dialog with the UAS. In another view, a reliable response is * used to establish the early dialog. UAC establishes a leg object for the * early dialog by calling nta_leg_tcreate() with the parameters derived * from the response message. * * @code * int invite_callback(call_t *call, * nta_outgoing_t *orq, * sip_t const *sip) * { * int status = sip->sip_status->st_status; * * if (!call->has_dialog && * (status >= 200 || (status > 100 && sip->sip_rseq))) { * nta_leg_t *early = * nta_leg_tcreate(call->nta_agent, mid_dialog_request, call, * SIPTAG_TO(sip->sip_to), * SIPTAG_FROM(sip->sip_from), * SIPTAG_CALL_ID(sip->sip_call_id), * SIPTAG_CSEQ(sip->sip_cseq), * TAG_END()); * * nta_leg_client_route(early, * sip->sip_record_route, * sip->sip_contact); * * fork = call_fork(call, leg = early); * * if (!fork){ * handle error; * } * call = fork; * } * @endcode * * The original dialog object and client transaction object are used to * process other call forks. For instance, if the early dialog is * established with an announcement server it will never lead to an fully * established call, but an another dialog will be used when the call is * completed. * * @subsection nta_prack Acknowledging Reliable Response * * After an early dialog has been established, acknowledging the reliable * response is trivial. The application can create a PRACK client * transaction object by calling nta_outgoing_prack() * * @section nta_client SIP Client Action * * A SIP client initiates the transactions. In some cases, a SIP client is * also required to invoke additional transactions, like @b ACK or @b * CANCEL, to finalize the original transaction. This section describes how * a SIP client uses NTA to make transactions. * * @subsection client_nta_leg_t Creating the Call Leg * * If the client does not have a suitable call leg, it must create it by * calling the function nta_leg_tcreate(): * @code * context->leg = nta_leg_tcreate(agent, * callback, context, * SIPTAG_CALL_ID(call_id), * SIPTAG_FROM(from), * SIPTAG_TO(to), * TAG_END()); * @endcode * * The @p callback function and @p context pointer are used for incoming * transactions, and they may be @c NULL if no such transactions are * expected. If the callback is @c NULL, NTA responds to incoming * transactions with status @e 403 @e Forbidden. * * The @a call_id may be @c NULL or left out. In that case, NTA generates a * new call ID. * * The @a from and @a to are used in outgoing transactions. They are also * used to select which incoming messages belong to this leg. * * The initial sequence number can be supplied with SIPTAG_CSEQ() (taking a * @CSeq structure as parameter). * * The additional parameters (after @a to) are included in outgoing messages * using this leg. Currently, only @c SIPTAG_ROUTE() is supported. * * @note Additional tagged parameters are ignored. * * @subsection nta_outgoing_t Outgoing requests * * The outgoing request is created and sent by nta_outgoing_tcreate(). It * can be used as follows: * @code * oreq = nta_outgoing_tcreate(leg, response_to_register, reg, * proxy_url, * SIP_METHOD_REGISTER, * registrar_url, * SIPTAG_CONTACT(my_contact), * TAG_END()); * @endcode * * NTA invokes the callback function response_to_register() each time a * provisional answer is received, and when a final answer is received. * * @note There may be multiple final answers to the INVITE request. * * If NTA does not receive answer in timely manner, it will generate a * @e 408 @e Timeout response and hand that back to the application. * * @note After a provisional answer to the INVITE request, no timeout will * occur inside NTA. Application must itself timeout the INVITE * transactions if any answer has been received. * * The request can be destroyed with NTA function nta_outgoing_destroy(). * If no final answer has been received, the request is cancelled when it is * destroyed, too. The application can also cancel the outgoing request by * calling nta_outgoing_cancel(). * * @subsection nta_ack Acknowledging Answers to INVITE * * The final answers to the INVITE request must be acknowledged. NTA takes * care of acknowledging automatically the 3xx..6xx answers; the appliction * must explicitly create a separate acknowledge transaction to final 2xx * answers. * * The final answer can be acknowledged like this: * @code * url = sip->sip_contact ? sip->sip_contact->m_url : original_url; * ack = nta_outgoing_tcreate(leg, NULL, NULL, * SIP_METHOD_ACK, * (url_string_t*)url, * SIPTAG_CSEQ(sip->sip_cseq), * SIPTAG_PAYLOAD(sdp), * TAG_END()); * @endcode * * @note The ACK transaction should be sent to the @Contact specified in the * 2xx reply. * * * @section nta_stateless_callback Stateless Processing of SIP Messages * * When an NTA agent is created, it is possible to provide it with a * stateless callback function. The callback function will be called when an * incoming SIP request or response message does not match with an existing * transaction. * * Before invoking the stateless callback the agent will try to match the * incoming request message with an existing dialog or dialog-less leg (or * default leg). So, if you have created a default leg, all request messages * are processed statefully by it instead of being passed to the stateless * callback function. * * If you want to process request messages with stateless callback and still * use dialog-less legs (for instance, in order to look up domains with * nta_leg_by_uri()), you have to switch over to @em stateless @em mode by * including NTATAG_STATELESS(1) in nta_agent_create() or * nta_agent_set_params() arguments. * * Also, if a response message does not match with an existing client * transaction, the agent will try to use the default outgoing (client) * transaction. If you have created an default outgoing transaction, all * stray response messages are passed to it instead of the stateless * processing function. * * @section nta_message_f_example Stateless Callback Function * * In addition to the message (@a msg) and its * parsed contents (@a sip) the callback function gets the * application-specific context pointer (in this case, @a registrar) and a * pointer to the NTA agent (@a agent) as its arguments: * * @code * int process_message(nta_agent_context_t *registrar, * nta_agent_t *agent, * msg_t *msg, * sip_t *sip); * @endcode * * The application has three functions that can be used to process the * messages in stateless manner: * @li nta_msg_discard() ignores and destroys the message, * @li nta_msg_tsend() forwards a request or response message, and * @li nta_msg_treply() replies to a request message in a stateless way. * * Additionally, it is possible to process a request message statefully with * nta_incoming_create(). * * The functionality of the stateless callback function can vary greatly, * depending the purpose of the application. An user-agent, a proxy or a * registrar/redirect server each have very different callback functions. * * A simple redirect server could have a message callback function as * follows. * * @code * int process_message(redirect_t *r, * nta_agent_t *agent, * msg_t *msg, * sip_t *sip) * { * sip_contact_t *m; * sip_unsupported_t *u; * * @endcode * * The incoming response messages are simply ignored. The @b ACK requests can * safely be discarded, too, because the redirect server keeps no state. * * @code * if (!sip->sip_request || sip->sip_request->rq_method == sip_method_ack) { * nta_msg_discard(agent, msg); * return 0; * } * @endcode * * Next, the redirect server first checks if processing the request requires * a feature that is not supported by it: * @code * u = sip_unsupported(msg_home(msg), sip->sip_require, r->r_supported); * if (u) { * nta_msg_treply(agent, msg, SIP_420_BAD_EXTENSION, * SIPTAG_SUPPORTED(r->r_supported), * SIPTAG_UNSUPPORTED(u), * TAG_END()); * return 0; * } * @endcode * * The @b CANCEL requests terminate a transacton. A stateless redirect * server does not have transactions, so it redirect replies with a @e 481 * @e Call @e Leg/Transaction @e Does @e Not @e Exist message: * @code * if (sip->sip_request->rq_method == sip_method_cancel) { * nta_msg_treply(agent, msg, SIP_481_NO_TRANSACTION, TAG_END()); * return 0; * } * @endcode * * All other requests are answered normally with a 302 response. * The location service is * searched for the request uri, and if a matching address was found, a * list of active bindings is returned to the client. * @code * m = location_find(redirect, sip->sip_request->rq_url); * if (m) { * nta_msg_treply(agent, msg, SIP_302_MOVED_TEMPORARILY, * SIPTAG_CONTACT(m), * TAG_END()); * } * @endcode * * Otherwise, @e 404 @e Not @e Found is sent: * @code * else { * nta_msg_treply(agent, msg, SIP_404_NOT_FOUND, TAG_END()); * } * * return 0; * } * @endcode * */ /**@page internal NTA Semantics and Internal Data Flows * * NTA implements simple state machines at transaction level. The figure * below illustrates how a message is processed by NTA. * * @image html nta-receiving-message.gif "NTA processing incoming messages." * @image latex nta-receiving-message.eps "NTA processing incoming messages." * * */ int invite_callback(call_t *call, nta_outgoing_t *orq, sip_t const *sip) { int status = sip->sip_status->st_status; nta_leg_t *leg = call->leg; if (!call->has_dialog && (status >= 200 || (status > 100 && sip->sip_rseq))) { nta_leg_t *early = nta_leg_tcreate(call->nta_agent, mid_dialog_request, call, SIPTAG_TO(sip->sip_to), SIPTAG_FROM(sip->sip_from), SIPTAG_CALL_ID(sip->sip_call_id), SIPTAG_CSEQ(sip->sip_cseq), TAG_END()); nta_leg_client_route(early, sip->sip_record_route, sip->sip_contact); fork = call_fork(call, leg = early); if (!fork){ handle error; } call = fork; } if (status > 100 && status < 200 && sip->sip_rseq) { nta_outgoing_t *prack = nta_outgoing_prack(leg, orq, NULL, NULL, NULL, sip, TAG_END()); nta_outgoing_destroy(prack); return 0; } ... } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/nta_check.c000066400000000000000000000313731223300710500224260ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005, 2011 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE nta_check.c * @brief Checks for features, MIME types, session timer. * * @author Pekka Pessi * * @date Created: Wed Mar 8 16:35:05 EET 2006 ppessi */ #include "config.h" #include #include #include #include #include #include /* ======================================================================== */ /* Request validation */ static int internal_error(nta_incoming_t *irq) { if (irq) nta_incoming_treply(irq, SIP_500_INTERNAL_SERVER_ERROR, TAG_END()); return 500; } /**Check that we support all features which UAC requires. * * The list of supported features is compared with the list of features * required by the UAC. If some features are not listed as supported, return * 420. If @a irq is non-NULL, the 420 response message is sent to the * client along with list of unsupported features in the @Unsupported * header, too. * * @param irq incoming transaction object (may be NULL). * @param sip contents of the SIP message * @param supported list of protocol features supported * @param tag, value, ... optional list of tagged arguments used * when responding to the transaction * * @retval 0 if successful * @retval 420 if any of the required features is not supported by UAS * @retval 500 if an internal error occurred */ int nta_check_required(nta_incoming_t *irq, sip_t const *sip, sip_supported_t const *supported, tag_type_t tag, tag_value_t value, ...) { int status = 0; if (sip == NULL) return internal_error(irq); if (sip->sip_require) { su_home_t home[SU_HOME_AUTO_SIZE(512)]; sip_unsupported_t *us; su_home_auto(home, sizeof home); us = sip_has_unsupported(home, supported, sip->sip_require); if (us) { status = 420; if (irq) { ta_list ta; ta_start(ta, tag, value); nta_incoming_treply(irq, SIP_420_BAD_EXTENSION, SIPTAG_UNSUPPORTED(us), SIPTAG_SUPPORTED(supported), ta_tags(ta)); ta_end(ta); } } su_home_deinit(home); } return status; } /** Check that UAC supports all the required features. * * The list of required features is compared with the features supported by * the UAC. If some features are not supported, return 421. If @a irq is * non-NULL, the 421 response message is sent to the client, too. * * @param irq incoming transaction object (may be NULL). * @param sip contents of the SIP message * @param require list of required protocol features * @param tag, value, ... optional list of tagged arguments used * when responding to the transaction * * @retval 0 if successful * @retval 421 if any of the required features is not supported by UAC * @retval 500 if an internal error occurred */ int nta_check_supported(nta_incoming_t *irq, sip_t const *sip, sip_require_t *require, tag_type_t tag, tag_value_t value, ...) { if (sip == NULL) return internal_error(irq); if (!sip_has_unsupported(NULL, sip->sip_supported, require)) return 0; if (irq) { ta_list ta; ta_start(ta, tag, value); nta_incoming_treply(irq, SIP_421_EXTENSION_REQUIRED, SIPTAG_REQUIRE(require), ta_tags(ta)); ta_end(ta); } return 421; } /** Check that we allow the request method. * * The request-method is compared with the list of supported methods in @a * allow. If match is found, 0 is is returned. Otherwise, if the * request-method is well-known, 405 is returned. If the request-method is * unknown, 501 is returned. If @a irq is non-NULL, the 405 or 501 response * message is sent to the client, too. * * @param irq incoming transaction object (may be NULL). * @param sip contents of the SIP message * @param allow list of allowed methods * @param tag, value, ... optional list of tagged arguments used * when responding to the transaction * * @retval 0 if successful * @retval 405 is request-method is not allowed * @retval 501 if request-method is unknown * @retval 500 if an internal error occurred */ int nta_check_method(nta_incoming_t *irq, sip_t const *sip, sip_allow_t const *allow, tag_type_t tag, tag_value_t value, ...) { /* Check extensions */ sip_method_t method; char const *name; if (sip == NULL || sip->sip_request == NULL) return internal_error(irq); method = sip->sip_request->rq_method; name = sip->sip_request->rq_method_name; if (sip_is_allowed(allow, method, name)) return 0; if (irq) { ta_list ta; ta_start(ta, tag, value); if (method != sip_method_unknown) /* Well-known method */ nta_incoming_treply(irq, SIP_405_METHOD_NOT_ALLOWED, SIPTAG_ALLOW(allow), ta_tags(ta)); else /* Completeley unknown method */ nta_incoming_treply(irq, SIP_501_NOT_IMPLEMENTED, SIPTAG_ALLOW(allow), ta_tags(ta)); ta_end(ta); } return method != sip_method_unknown ? 405 : 501; } static sip_content_type_t const *application_sdp(void) { static sip_content_type_t *c; if (c == NULL) c = sip_content_type_make(NULL, "application/sdp"); return c; } /** Check that we understand session content in the request. * * If there is no @ContentDisposition header or the @ContentDisposition * header indicated "session", the message body and content-type is compared * with the acceptable session content-types listed in @a session_accepts. * (typically, @c "application/sdp"). If no match is found, a 415 is * returned. If @a irq is non-NULL, the 415 response message is sent to the * client, too. * * If the @ContentDisposition header indicates something else but "session", * and it does not contain "handling=optional" parameter, a 415 response is * returned, too. * * Also, the @ContentEncoding header is checked. If it is not empty * (indicating no content-encoding), a 415 response is returned, too. * * @param irq incoming (server) transaction object (may be NULL). * @param sip contents of the SIP message * @param session_accepts list of acceptable content-types for "session" * content disposition * @param tag, value, ... optional list of tagged arguments used * when responding to the transaction * * @retval 0 if successful * @retval 415 if Content-Type is not acceptable * @retval 500 if an internal error occurred */ int nta_check_session_content(nta_incoming_t *irq, sip_t const *sip, sip_accept_t const *session_accepts, tag_type_t tag, tag_value_t value, ...) { sip_content_disposition_t const *cd; int acceptable_type = 0, acceptable_encoding = 0; if (sip == NULL) return internal_error(irq); if (sip->sip_payload == NULL && sip->sip_multipart == NULL) return 0; cd = sip->sip_content_disposition; if (cd == NULL || su_casematch(cd->cd_type, "session")) { sip_content_type_t const *c = sip->sip_content_type; if (c == NULL && sip->sip_payload->pl_len > 3 && su_casenmatch(sip->sip_payload->pl_data, "v=0", 3)) /* Missing Content-Type, but it looks like SDP */ c = application_sdp(); if (msg_accept_match((msg_accept_t *)session_accepts, c)) acceptable_type = 1; } else if (cd->cd_optional) acceptable_type = 1; /* Empty or missing Content-Encoding */ if (!sip->sip_content_encoding || !sip->sip_content_encoding->k_items || !sip->sip_content_encoding->k_items[0] || !sip->sip_content_encoding->k_items[0][0]) acceptable_encoding = 1; if (acceptable_type && acceptable_encoding) return 0; if (irq) { ta_list ta; ta_start(ta, tag, value); nta_incoming_treply(irq, SIP_415_UNSUPPORTED_MEDIA, SIPTAG_ACCEPT(session_accepts), ta_tags(ta)); ta_end(ta); } return 415; } /**Check that UAC accepts one of listed MIME content-types. * * The list of acceptable content-types are compared with the acceptable * content-types. If match is found, it is returned in @a return_acceptable. * If no match is found, a 406 is returned. If @a irq is non-NULL, the 406 * response message is sent to the client, too. * * @param irq incoming transaction object (may be NULL). * @param sip contents of the SIP message * @param acceptable list of acceptable content types * @param return_acceptable optional return-value parameter for * matched content-type * @param tag, value, ... optional list of tagged arguments used * when responding to the transaction * * @retval 0 if successful * @retval 406 if no supported Content-Type is acceptable by client * @retval 500 if an internal error occurred * * @note * From @VERSION_UNRELEASED onwards, checks for wildcards, too. */ int nta_check_accept(nta_incoming_t *irq, sip_t const *sip, sip_accept_t const *acceptable, sip_accept_t const **return_acceptable, tag_type_t tag, tag_value_t value, ...) { ta_list ta; sip_accept_t const *ac, *ab; sip_method_t method; if (sip == NULL || (sip->sip_request == NULL && sip->sip_cseq == NULL)) return internal_error(irq); if (!acceptable) return 0; if (sip->sip_request) method = sip->sip_request->rq_method; else /* if (sip->sip_cseq) */ method = sip->sip_cseq->cs_method; /* * Missing Accept header implies support for SDP in INVITE and OPTIONS * (and PRACK and UPDATE?) */ if (!sip->sip_accept && (method == sip_method_invite || method == sip_method_options || method == sip_method_prack || method == sip_method_update)) { ab = (void *)msg_accept_match((void *)acceptable, application_sdp()); if (ab) { if (return_acceptable) *return_acceptable = ab; return 0; } } for (ac = sip->sip_accept; ac; ac = ac->ac_next) { if (msg_q_value(ac->ac_q) == 0 || !ac->ac_type) continue; if (su_strmatch(ac->ac_type, "*/*")) { ab = acceptable; } else if (su_strmatch(ac->ac_subtype, "*")) { for (ab = acceptable; ab; ab = ab->ac_next) { if (su_casenmatch(ab->ac_type, ac->ac_type, ac->ac_subtype - ac->ac_type)) break; } } else { ab = (void *)msg_accept_match((void *)acceptable, (msg_content_type_t *)ac); } if (ab) { if (return_acceptable) *return_acceptable = ab; return 0; } } if (irq) { ta_start(ta, tag, value); nta_incoming_treply(irq, SIP_406_NOT_ACCEPTABLE, SIPTAG_ACCEPT(acceptable), ta_tags(ta)); ta_end(ta); } return 406; } /**Check @SessionExpires header. * * If the proposed session-expiration time is smaller than @MinSE or our * minimal session expiration time, respond with 422 containing shortest * acceptable session expiration time in @MinSE header. * * @param irq incoming transaction object (may be NULL). * @param sip contents of the SIP message * @param my_min_se minimal session expiration time in seconds * @param tag, value, ... optional list of tagged arguments used * when responding to the transaction * * @retval 0 when successful * @retval 422 if session expiration time is too small * @retval 500 if an internal error occurred */ int nta_check_session_expires(nta_incoming_t *irq, sip_t const *sip, sip_time_t my_min_se, tag_type_t tag, tag_value_t value, ...) { unsigned long min_se = my_min_se; if (sip == NULL) return internal_error(irq); if (sip->sip_session_expires == NULL) return 0; if (sip->sip_min_se && min_se < sip->sip_min_se->min_delta) min_se = sip->sip_min_se->min_delta; if (sip->sip_session_expires->x_delta >= min_se) return 0; if (irq) { ta_list ta; sip_min_se_t min_se0[1]; ta_start(ta, tag, value); sip_min_se_init(min_se0)->min_delta = min_se; nta_incoming_treply(irq, SIP_422_SESSION_TIMER_TOO_SMALL, SIPTAG_MIN_SE(min_se0), ta_tags(ta)); ta_end(ta); } return 422; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/nta_internal.h000066400000000000000000000057541223300710500231760ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef NTA_INTERNAL_H /** Defined when has been included. */ #define NTA_INTERNAL_H /**@internal @file nta_internal.h * * @brief NTA internal interfaces. * * @author Pekka Pessi * * @date Created: Tue Jul 18 09:18:32 2000 ppessi */ SOFIA_BEGIN_DECLS /** A sip_flag telling that this message is internally generated. */ #define NTA_INTERNAL_MSG (1<<15) #include #include #include #include #if HAVE_SOFIA_SRESOLV #include #endif typedef struct nta_compressor nta_compressor_t; /* Virtual function table for plugging in SigComp */ typedef struct { int ncv_size; char const *ncv_name; nta_compressor_t *(*ncv_init_agent)(nta_agent_t *sa, char const * const *options); void (*ncv_deinit_agent)(nta_agent_t *sa, nta_compressor_t *); struct sigcomp_compartment *(*ncv_compartment)(nta_agent_t *sa, tport_t *tport, nta_compressor_t *msc, tp_name_t const *tpn, char const * const *options, int new_if_needed); int (*ncv_accept_compressed)(nta_agent_t *sa, nta_compressor_t *msc, tport_compressor_t *sc, msg_t *msg, struct sigcomp_compartment *cc); int (*ncv_close_compressor)(nta_agent_t *sa, struct sigcomp_compartment *cc); int (*ncv_zap_compressor)(nta_agent_t *sa, struct sigcomp_compartment *cc); struct sigcomp_compartment *(*ncv_compartment_ref) (struct sigcomp_compartment *); void (*ncv_compartment_unref)(struct sigcomp_compartment *); } nta_compressor_vtable_t; SOFIAPUBVAR nta_compressor_vtable_t *nta_compressor_vtable; SOFIAPUBFUN nta_compressor_t *nta_agent_init_sigcomp(nta_agent_t *sa); SOFIAPUBFUN void nta_agent_deinit_sigcomp(nta_agent_t *sa); /* ====================================================================== */ /* Debug log settings */ #define SU_LOG nta_log #ifdef SU_DEBUG_H #error included directly. #endif #include SOFIAPUBVAR su_log_t nta_log[]; SOFIA_END_DECLS #endif /* NTA_INTERNAL_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/nta_tag.c000066400000000000000000001670451223300710500221320ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE nta_tag.c * @brief Tags for Nokia SIP Transaction API * * @note This file is used to automatically generate * nta_tag_ref.c and nta_tag_dll.c * * @author Pekka Pessi * * @date Created: Tue Jul 24 22:28:34 2001 ppessi */ #include "config.h" #include #include #define TAG_NAMESPACE "nta" #include "sofia-sip/nta_tag.h" #include #include #include #include tag_typedef_t ntatag_any = NSTAG_TYPEDEF(*); /**@def NTATAG_MCLASS(x) * * Message class used by NTA. * * The nta can use a custom or extended parser created with * msg_mclass_clone(). * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * pointer to #msg_mclass_t. * * @par Values * - custom or extended parser created with msg_mclass_clone() * - NULL - use default parser * * @par Default Value * - Value returned by sip_default_mclass() * * @sa NTATAG_SIPFLAGS() */ tag_typedef_t ntatag_mclass = PTRTAG_TYPEDEF(mclass); /**@def NTATAG_BAD_REQ_MASK(x) * * Mask for bad request messages. * * If an incoming request has erroneous headers matching with the mask, nta * automatically returns a 400 Bad Message response to them. * * If mask ~0U (all bits set) is specified, all requests with any bad header * are dropped. By default only the requests with bad headers essential for * request processing or proxying are dropped. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * unsigned int * * @par Values * - bitwise or of enum #sip_bad_mask values * * @par Default Value * - sip_mask_response | sip_mask_ua | sip_mask_100rel |
* sip_mask_events | sip_mask_timer | sip_mask_publish * The following headers are considered essential by default: * - @ref sip_request \"request line\"", @From, @To, @CSeq, @CallID, * @ContentLength, @Via, @ContentType, @ContentDisposition, * @ContentEncoding, @Supported, @Contact, @Require, @RecordRoute, @RAck, * @RSeq, @Event, @Expires, @SubscriptionState, @SessionExpires, * @MinSE, @SIPETag, and @SIPIfMatch. * * @sa enum #sip_bad_mask, NTATAG_BAD_RESP_MASK() */ tag_typedef_t ntatag_bad_req_mask = UINTTAG_TYPEDEF(bad_req_mask); /**@def NTATAG_BAD_RESP_MASK(x) * * Mask for bad response messages. * * If an incoming response has erroneous headers matching with the mask, nta * drops the response message. * * If mask ~0U (all bits set) is specified, all responses with any bad header * are dropped. By default only the responses with bad headers essential for * response processing or proxying are dropped. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * unsigned int * * @par Values * - bitwise or of enum #sip_bad_mask values * * @sa enum #sip_bad_mask, NTATAG_BAD_REQ_MASK() * * @par Default Value * - sip_mask_response | sip_mask_ua | sip_mask_100rel |
* sip_mask_events | sip_mask_timer | sip_mask_publish * The following headers are considered essential by default: * - @ref sip_status \"status line\"", @From, @To, @CSeq, @CallID, * @ContentLength, @Via, @ContentType, @ContentDisposition, * @ContentEncoding, @Supported, @Contact, @Require, @RecordRoute, @RAck, * @RSeq, @Event, @Expires, @SubscriptionState, @SessionExpires, * @MinSE, @SIPETag, and @SIPIfMatch. */ tag_typedef_t ntatag_bad_resp_mask = UINTTAG_TYPEDEF(bad_resp_mask); /**@def NTATAG_DEFAULT_PROXY(x) * * URL for (default) proxy. * * The requests are sent towards the default outbound proxy regardless * the values of request-URI or @Route headers in the request. The URL of * the default proxy is not added to the request in the @Route header or in * the request-URI (against the recommendation of @RFC3261 section 8.1.2). * * The outbound proxy set by NTATAG_DEFAULT_PROXY() is used even if the * dialog had an established route set or registration provided User-Agent * with a @ServiceRoute set. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params(), * nta_outgoing_mcreate(), nta_outgoing_tcreate(), * nta_outgoing_tcancel(), nta_outgoing_prack(), nta_msg_tsend() * * @par Parameter type * Pointer to a url_t structure or a string containg a SIP or SIPS URI * * @par Values * - Valid SIP or SIPS URI */ tag_typedef_t ntatag_default_proxy = URLTAG_TYPEDEF(default_proxy); /**@def NTATAG_CONTACT(x) * * Contact used by NTA. */ tag_typedef_t ntatag_contact = SIPHDRTAG_NAMED_TYPEDEF(contact, contact); /** @def NTATAG_TARGET(x) * * Dialog target (contact) used by NTA. */ tag_typedef_t ntatag_target = SIPHDRTAG_NAMED_TYPEDEF(target, contact); /** @def NTATAG_ALIASES(x) * * Aliases used by NTA. * @deprecated */ tag_typedef_t ntatag_aliases = SIPHDRTAG_NAMED_TYPEDEF(aliases, contact); /**@def NTATAG_METHOD(x) * * Method name. * * Create a dialogless #nta_leg_t object matching only requests with * the specified method. * * @par Used with * nta_leg_tcreate() * * @par Parameter type * String containing method name. * * @par Values * - A SIP method name (e.g., "SUBSCRIBE"). * * @par Default Value * - None (i.e., all requests methods match with the leg) * */ tag_typedef_t ntatag_method = STRTAG_TYPEDEF(method); /**@def NTATAG_BRANCH_KEY(x) * * Branch ID to the topmost @Via header. * * The NTA generates a random branch ID for the topmost @Via header by default. * The application can the branch by itself, for intance, if it wants to * create a @RFC2543-era transaction. * * Note that according to @RFC3261 the branch ID must start with "z9hG4bK". * * @par Used with * nta_outgoing_mcreate(), nta_outgoing_tcreate(), * nta_outgoing_tcancel(), nta_outgoing_prack(), nta_msg_tsend() * * @par Parameter type * string * * @par Value * - The "branch" ID to to insert into topmost @Via header of the * request to be sent * * @par Default Value * - A token is generated, either by random when a client transaction is * created or by hashing the headers and contents of the request when * request is sent statelessly * * @sa @RFC3261 section 8.1.1.7 */ tag_typedef_t ntatag_branch_key = STRTAG_TYPEDEF(branch_key); /**@def NTATAG_ACK_BRANCH(x) * * Branch of the transaction to ACK. * * When creating a ACK transaction, the application should provide the * branch parameter from the original transaction to the stack. The ACK * transaction object then receives all the retransmitted 2XX responses to * the original INVITE transaction. * * @par Used with * nta_outgoing_mcreate(), nta_outgoing_tcreate() * * @par Parameter type * string * * @par Value * - "branch" ID used to store the ACK transaction in the nta hash * table for outgoing client transaction * * @par Default Value * - The INVITE transaction is looked from the hash table using the @CallID, * @CSeq, @From and @To tags and its branch ID is used */ tag_typedef_t ntatag_ack_branch = STRTAG_TYPEDEF(ack_branch); /**@def NTATAG_COMP(x) * * Compression algorithm. * * Set compression algorithm for request as described in @RFC3486. * * @note This tag is has no effect without a compression plugin. * * @par Used with * nta_outgoing_mcreate(), nta_outgoing_tcreate(), * nta_outgoing_tcancel(), nta_outgoing_prack(), nta_msg_tsend() * * @par * Note that NTATAG_COMP(NULL) can be used with nta_incoming_set_params() * and nta_incoming_treply(), too. It indicates that the response is sent * uncompressed, no matter what the client has in @a comp parameter of @Via * header. * * @par Parameter type * string * * @par Values * - name of the compression algorithm * * @par Default Value * - "sigcomp" * * @sa @RFC3320, @RFC3486, TPTAG_COMPARTMENT(), * NTATAG_SIGCOMP_ALGORITHM(), NTATAG_SIGCOMP_AWARE(), * NTATAG_SIGCOMP_CLOSE(), NTATAG_SIGCOMP_OPTIONS() */ tag_typedef_t ntatag_comp = CSTRTAG_TYPEDEF(comp); /**@def NTATAG_MSG(x) * * Pass a SIP message to treply()/tcreate() functions. * * @par Used with * nta_outgoing_tcreate(), nta_incoming_treply() * * @par Parameter type * #msg_t * * @par Values * - A message object which will be completed, serialized and encoded. * Note that the functions modify directly the message. * * @par Default Value * - A new message object is created and populated by the function call. * * @sa msg_copy(), msg_dup(), msg_create(), sip_default_mclass() */ tag_typedef_t ntatag_msg = PTRTAG_TYPEDEF(msg); /**@def NTATAG_TPORT(x) * * Pass a transport object. The transport object is used to send the request * or response message(s). * * @par Used with * nta_outgoing_tcreate(), nta_outgoing_mcreate(), nta_outgoing_tcancel(), * nta_incoming_create(), nta_msg_tsend(), nta_msg_mreply() * * @par Parameter type * - #tport_t * * @par Values * - A pointer to the transport object. Note that a new reference to the transport * is created. * * @par Default Value * - The transport is selected by resolving the outbound URI (specified with * NTATAG_DEFAULT_PROXY(), the topmost @Route URI or Request-URI. */ tag_typedef_t ntatag_tport = PTRTAG_TYPEDEF(tport); /**@def NTATAG_SMIME(x) * * Provide S/MIME context to NTA. * * @todo S/MIME is not implemented. */ tag_typedef_t ntatag_smime = PTRTAG_TYPEDEF(smime); /**@def NTATAG_REMOTE_CSEQ(x) * * Remote CSeq number. * * Specify remote command sequence number for a #nta_leg_t dialog object. If * an request is received matching with the dialog but with @CSeq number * less than the remote sequence number associated with the dialog, a 500 * Internal Server Error response is automatically returned to the client. * * @par Used with * nta_leg_tcreate() * * @par Parameter type * - uint32_t * * @par Values * - Remote command sequence number * * @par Default Value * - Initially 0, then determined by the received requests * */ tag_typedef_t ntatag_remote_cseq = UINTTAG_TYPEDEF(remote_cseq); /**@def NTATAG_MAXSIZE(x) * * Maximum size of incoming message. * * If the size of an incoming request message would exceed the * given limit, the stack will automatically respond with 413 Request * Entity Too Large. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * - #usize_t * * @par Values * - Maximum acceptable size of an incoming request message. * * @par Default Value * - 2097152 (bytes or 2 megabytes) * * @sa msg_maxsize(), NTATAG_UDP_MTU() */ tag_typedef_t ntatag_maxsize = USIZETAG_TYPEDEF(maxsize); /**@def NTATAG_MAX_PROCEEDING(x) * * Maximum size of proceeding queue. * * If the size of the proceedng message queue would exceed the * given limit, the stack will automatically respond with 503 * Service Unavailable. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * - #usize_t * * @par Values * - Maximum acceptable size of a queue (size_t). * * @NEW_1_12_9 */ tag_typedef_t ntatag_max_proceeding = USIZETAG_TYPEDEF(max_proceeding); /**@def NTATAG_UDP_MTU(x) * * Maximum size of outgoing UDP request. * * The maximum UDP request size is used to control use of UDP with overtly * large messages. The IETF requires that the SIP requests over 1300 bytes * are sent over congestion-controlled transport such as TCP. If a SIP * message size exceeds the UDP MTU, the TCP is tried instead of UDP. (If * the TCP connection is refused, the stack reverts back to UDP). * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * - unsigned * * @par Values * - Maximum size of an outgoing UDP request * * @par Default Value * - 1300 (bytes) * * @sa @RFC3261 section 18.1.1, NTATAG_MAXSIZE() */ tag_typedef_t ntatag_udp_mtu = UINTTAG_TYPEDEF(udp_mtu); /**@def NTATAG_MAX_FORWARDS(x) * * Default value for @MaxForwards header. * * The default value of @MaxForwards header added to the requests. The * initial value recommended by @RFC3261 is 70, but usually SIP proxies use * much lower default value, such as 24. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * unsigned * * @par Values * - Default value added to the @MaxForwards header in the sent requests * * @par Default Value * - 70 (hops) * * @since New in @VERSION_1_12_2. */ tag_typedef_t ntatag_max_forwards = UINTTAG_TYPEDEF(max_forwards); /**@def NTATAG_SIP_T1(x) * * Initial retransmission interval (in milliseconds) * * Set the T1 retransmission interval used by the SIP transaction engine. The * T1 is the initial duration used by request retransmission timers A and E * (UDP) as well as response retransmission timer G. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * unsigned int * * @par Values * - Value of SIP T1 in milliseconds * * @par Default Value * - #NTA_SIP_T1 or 500 (milliseconds) * * @sa @RFC3261 appendix A, #NTA_SIP_T1, NTATAG_SIP_T1X4(), NTATAG_SIP_T1(), NTATAG_SIP_T4() */ tag_typedef_t ntatag_sip_t1 = UINTTAG_TYPEDEF(sip_t1); /**@def NTATAG_SIP_T1X64(x) * * Transaction timeout (defaults to T1 * 64). * * Set the T1x64 timeout value used by the SIP transaction engine. The T1x64 is * duration used for timers B, F, H, and J (UDP) by the SIP transaction engine. * The timeout value T1x64 can be adjusted separately from the initial * retransmission interval T1, which is set with NTATAG_SIP_T1(). * * The default value for T1x64 is 64 times value of T1, or 32000 milliseconds. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * unsigned int * * @par Values * - Value of T1x64 in milliseconds * * @par Default Value * - 64 * #NTA_SIP_T1 or 32000 (milliseconds) * * @sa @RFC3261 appendix A, #NTA_SIP_T1, NTATAG_SIP_T1(), NTATAG_SIP_T2(), NTATAG_SIP_T4() * */ tag_typedef_t ntatag_sip_t1x64 = UINTTAG_TYPEDEF(sip_t1x64); /**@def NTATAG_SIP_T2(x) * * Maximum retransmission interval (in milliseconds) * * Set the maximum retransmission interval used by the SIP transaction * engine. The T2 is the maximum duration used for the timers E (UDP) and G * by the SIP transaction engine. Note that the timer A is not capped by T2. * Retransmission interval of INVITE requests grows exponentially until the * timer B fires. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * unsigned int * * @par Values * - Value of SIP T2 in milliseconds * * @par Default Value * - #NTA_SIP_T2 or 4000 (milliseconds) * * @sa @RFC3261 appendix A, #NTA_SIP_T2, NTATAG_SIP_T1(), NTATAG_SIP_T1X4(), NTATAG_SIP_T4() */ tag_typedef_t ntatag_sip_t2 = UINTTAG_TYPEDEF(sip_t2); /**@def NTATAG_SIP_T4(x) * * Transaction lifetime (in milliseconds) * * Set the lifetime for completed transactions used by the SIP transaction * engine. A completed transaction is kept around for the duration of T4 in * order to catch late responses. The T4 is the maximum duration for the * messages to stay in the network and the duration of SIP timer K. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * unsigned int * * @par Values * - Value of SIP T4 in milliseconds * * @par Default Value * - #NTA_SIP_T4 or 4000 (milliseconds) * * @sa @RFC3261 appendix A, #NTA_SIP_T4, NTATAG_SIP_T1(), NTATAG_SIP_T1X4(), NTATAG_SIP_T2() */ tag_typedef_t ntatag_sip_t4 = UINTTAG_TYPEDEF(sip_t4); /**@def NTATAG_PROGRESS(x) * * Progress timer for User-Agents (interval for retranmitting 1XXs). * * The UAS should retransmit preliminary responses to the INVITE * transactions every minute in order to re-set the timer C within the * intermediate proxies. * * The default value for the progress timer is 60000. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * unsigned int * * @par Values * Value of progress timer in milliseconds. * * @par Default Value * - 90000 (milliseconds, 1.5 minutes) * * @sa @RFC3261 sections 13.3.1.1, 16.7 and 16.8, NTATAG_TIMER_C(), * NTATAG_SIP_T1(), NTATAG_SIP_T1X4(), NTATAG_SIP_T2(), NTATAG_SIP_T4() */ tag_typedef_t ntatag_progress = UINTTAG_TYPEDEF(progress); /**@def NTATAG_TIMER_C(x) * * Value for timer C in milliseconds. * * By default the INVITE transaction will not timeout after a preliminary * response has been received. However, an intermediate proxy can timeout * the transaction using timer C. Timer C is reset every time a response * belonging to the transaction is received. * * The default value for the timer C is 185000 milliseconds (3 minutes and 5 * seconds). By default, timer C is not run on user agents (if NTATAG_UA(1) * without NTATAG_TIMER_C() is given). * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * unsigned int * * @par Values * Value of SIP timer C in milliseconds. The default value is used * instead if NTATAG_TIMER_C(0) is given. * * @par Default Value * - 185000 (milliseconds, 3 minutes) * * @sa @RFC3261 sections 13.3.1.1, 16.7 and 16.8, * NTATAG_UA(1), NTATAG_TIMER_C(), * NTATAG_SIP_T1(), NTATAG_SIP_T1X4(), NTATAG_SIP_T2(), NTATAG_SIP_T4() * * @NEW_1_12_7. */ tag_typedef_t ntatag_timer_c = UINTTAG_TYPEDEF(timer_c); /**@def NTATAG_GRAYLIST(x) * * Avoid failed servers. * * The NTATAG_GRAYLIST() provides the time that the servers are avoided * after a request sent to them has been failed. Avoiding means that if a * domain provides multiple servers, the failed servers are tried last. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * unsigned int * * @par Values * - Number of seconds that server is kept in graylist, from 0 to 86400. * * @par Default Value * - 600 (graylist server for 10 minutes) * * @sa NTATAG_BLACKLIST(), NTATAG_TIMEOUT_408() * * @NEW_1_12_8 */ tag_typedef_t ntatag_graylist = UINTTAG_TYPEDEF(graylist); /**@def NTATAG_BLACKLIST(x) * * Add Retry-After header to error responses returned to application. * * The NTATAG_BLACKLIST() provides a default value for @RetryAfter header * added to the internally generated responses such as 503 DNS Error * or 408 Timeout. The idea is that the application can retain its * current state and retry the operation after a while. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * unsigned int * * @par Values * - Value of @a delta-seconds in @RetryAfter header, from 0 to 86400 * * @par Default Value * - 0 (no @RetryAfter header is included) * * @sa NTATAG_TIMEOUT_408() */ tag_typedef_t ntatag_blacklist = UINTTAG_TYPEDEF(blacklist); /**@def NTATAG_DEBUG_DROP_PROB(x) * * Packet drop probability for debugging. * * The packet drop probability parameter is useful mainly for debugging * purposes. The stack drops an incoming message received over an unreliable * transport (such as UDP) with the given probability. The range is in 0 .. * 1000, 500 means p=0.5. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * unsigned integer * * @par Values * - Valid values are in range 0 ... 1000 * - Probablity to drop a given message is value / 1000. * * @par Default Value * - 0 (no packets are dropped) * * @sa TPTAG_DEBUG_DROP() */ tag_typedef_t ntatag_debug_drop_prob = UINTTAG_TYPEDEF(debug_drop_prob); /**@def NTATAG_SIGCOMP_OPTIONS(x) * * Semicolon-separated SigComp options. * * @note This tag is has no effect without a SigComp plugin. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params(), * nta_agent_add_tport() * * @par Parameter type * string * * @par Values * - semicolon-separated parameter-value pairs, passed to the SigComp plugin * * @sa NTATAG_COMP(), NTATAG_SIGCOMP_ALGORITHM(), NTATAG_SIGCOMP_AWARE(), * NTATAG_SIGCOMP_CLOSE(), @RFC3320 */ tag_typedef_t ntatag_sigcomp_options = STRTAG_TYPEDEF(sigcomp_options); /**@def NTATAG_SIGCOMP_CLOSE(x) * * Close SigComp compartment after completing transaction. * * @note This tag is has no effect without a SigComp plugin. * * @par Used with * nta_incoming_set_params(), nta_incoming_treply() * nta_outgoing_mcreate(), nta_outgoing_tcreate(), * nta_outgoing_tmcreate(), nta_outgoing_tcancel(), * nta_outgoing_prack(), nta_msg_tsend(), nta_msg_treply() * * @par Parameter type * boolean: true (non-zero or non-NULL pointer) * or false (zero or NULL pointer) * * @par Values * - true - application takes care of compartment management * - false - stack manages compartments * * @sa NTATAG_COMP(), TPTAG_COMPARTMENT(), * NTATAG_SIGCOMP_ALGORITHM(), NTATAG_SIGCOMP_AWARE(), * NTATAG_SIGCOMP_OPTIONS(), @RFC3320 */ tag_typedef_t ntatag_sigcomp_close = BOOLTAG_TYPEDEF(sigcomp_close); /**@def NTATAG_SIGCOMP_AWARE(x) * * Indicate that the application is SigComp-aware. * * @note This tag is has no effect without a SigComp plugin. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * boolean: true (non-zero or non-NULL pointer) * or false (zero or NULL pointer) * * @par Values * - true - application takes care of compartment management * - false - stack manages compartments * * @sa NTATAG_COMP(), NTATAG_SIGCOMP_ALGORITHM(), NTATAG_SIGCOMP_CLOSE(), * NTATAG_SIGCOMP_OPTIONS(), @RFC3320 */ tag_typedef_t ntatag_sigcomp_aware = BOOLTAG_TYPEDEF(sigcomp_aware); /**@def NTATAG_SIGCOMP_ALGORITHM(x) * * Specify SigComp algorithm. * * @note This tag is has no effect without a SigComp plugin. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params(), * nta_agent_add_tport() * * @par Parameter type * string * * @par Values * - opaque string passed to the SigComp plugin * * @sa NTATAG_COMP(), NTATAG_SIGCOMP_AWARE(), NTATAG_SIGCOMP_CLOSE(), * NTATAG_SIGCOMP_OPTIONS(), @RFC3320 */ tag_typedef_t ntatag_sigcomp_algorithm = STRTAG_TYPEDEF(sigcomp_algorithm); /**@def NTATAG_UA(x) * * If true, NTA acts as User Agent Server or Client by default. * * When acting as an UA, the NTA stack will * - respond with 481 to a PRACK request with no matching "100rel" response * - check for out-of-order CSeq headers for each #nta_leg_t dialog object * - if NTATAG_MERGE_482(1) is also used, return 482 Request Merged to * a duplicate request with same @CallID, @CSeq, @From tag but different * topmost @Via header (see @RFC3261 section 8.2.2.2 Merged Requests) * - silently discard duplicate final responses to INVITE * - retransmit preliminary responses (101..199) to INVITE request in regular * intervals ("timer N2") * - retransmit 2XX response to INVITE request with exponential intervals * - handle ACK sent in 2XX response to an INVITE using the * #nta_ack_cancel_f callback bound to #nta_incoming_t with * nta_incoming_bind() * - not use timer C unless its value has been explicitly set * * @note This NUTAG_UA(1) is set internally by nua_create() * * @par Used with * nta_agent_create() \n * nta_agent_set_params() \n * * @par Parameter type * boolean: true (non-zero or non-NULL pointer) * or false (zero or NULL pointer) * * @par Values * - true - act as an UA * - false - act as an proxy * * @par Default Value * - 0 (false) * * @sa NTATAG_MERGE_482() */ tag_typedef_t ntatag_ua = BOOLTAG_TYPEDEF(ua); /**@def NTATAG_STATELESS(x) * * Enable stateless processing. * * @par Server side * The incoming requests are processed statefully if there is a default leg * (created with nta_leg_default()). This option is provided for proxies or * other server elements that process requests statelessly. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Values * - true - do not pass incoming requests to default leg * - false - pass incoming requests to default leg, if it exists * * @par Default Value * - 0 (false, pass incoming requests to default leg) * * @par Client side * The outgoing requests can be sent statelessly, too, if the * NTATAG_STATELESS(1) is included in the tag list of nta_outgoing_tcreate(). * * @par Used with * nta_outgoing_mcreate(), nta_outgoing_tcreate(), * nta_outgoing_tcancel(), nta_outgoing_prack() * * @par Parameter type * boolean: true (non-zero or non-NULL pointer) * or false (zero or NULL pointer) * * @par Values * - true - create only a transient #nta_outgoing_t transaction object * - false - create an ordinary client transaction object * * @par Default Value * - 0 (false, create client transaction) * * @sa NTATAG_IS_UA(), nta_incoming_default(), nta_outgoing_default(), * nta_leg_default() */ tag_typedef_t ntatag_stateless = BOOLTAG_TYPEDEF(stateless); /**@def NTATAG_USER_VIA(x) * * Allow application to insert Via headers. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params(), * nta_outgoing_mcreate(), nta_outgoing_tcreate(), * nta_outgoing_tcancel(), nta_outgoing_prack(), nta_msg_tsend() * * @par Parameter type * boolean: true (non-zero or non-NULL pointer) * or false (zero or NULL pointer) * * @par Values * - true - do not add @Via header to the request (if it has one) * - false - always add a @Via header * * @par Default Value * - 0 (false, always add a @Via header) * * @sa NTATAG_BRANCH(), NTATAG_TPORT() */ tag_typedef_t ntatag_user_via = BOOLTAG_TYPEDEF(user_via); /**@def NTATAG_PASS_100(x) * * Pass "100 Trying" provisional answers to the application. * * By default, the stack silently processes the 100 Trying responses * from the server. Usually the 100 Trying responses are not * important to the application but rather sent by the outgoing proxy * immediately after it has received the request. However, the application * can ask nta for them by setting NTATAG_PASS_100(1) if, for instance, the * 100 Trying responses are needed for user feedback. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params(), * nta_outgoing_mcreate(), nta_outgoing_tcreate(), * nta_outgoing_tcancel(), nta_outgoing_prack(), nta_msg_tsend() * * @par Parameter type * boolean: true (non-zero or non-NULL pointer) * or false (zero or NULL pointer) * * @par Values * - true - pass 100 Trying to application * - false - silently process 100 Trying responses * * @par Default Value * - 0 (false, save application from seeing 100 Trying) * * @sa NTATAG_EXTRA_100(), NTATAG_DEFAULT_PROXY() */ tag_typedef_t ntatag_pass_100 = BOOLTAG_TYPEDEF(pass_100); /**@def NTATAG_EXTRA_100(x) * * Respond with "100 Trying" if application has not responded. * * As per recommended by @RFC4320, the stack can generate a 100 Trying * response to the non-INVITE requests if the application has not responded * to a request within half of the SIP T2 (the default value for T2 is 4000 * milliseconds, so the extra 100 Trying would be sent after 2 seconds). * * At agent level, this option applies to retransmissions of both non-INVITE * and INVITE transactions. * * At incoming request level, this option can disable sending the 100 Trying for * both retransmissions (if set at agent level) and N1 firings, for just a given * incoming request. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params(), * nta_incoming_set_params() * * @par Parameter type * boolean: true (non-zero or non-NULL pointer) * or false (zero or NULL pointer) * * @par Values * - true - send extra 100 Trying if application does not respond * - false - do not send 100 Trying * * @par Default Value at Agent level * - 0 (false, do not respond with 100 Trying to retransmissions) * * @par Default Value at incoming transaction level * - 1 (true, respond with 100 Trying to retransmissions and when N1 fired) * * @sa @RFC4320, NTATAG_PASS_408(), NTATAG_TIMEOUT_408() */ tag_typedef_t ntatag_extra_100 = BOOLTAG_TYPEDEF(extra_100); /**@def NTATAG_TIMEOUT_408(x) * * Generate "408 Request Timeout" response when request times out. * * This tag is used to prevent stack from generating extra 408 response * messages to non-INVITE requests upon timeout. As per recommended by * @RFC4320, the 408 Request Timeout responses to non-INVITE * transaction are not sent over the network to the client by default. The * application can ask stack to pass the 408 responses with * NTATAG_PASS_408(1). * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * boolean: true (non-zero or non-NULL pointer) * or false (zero or NULL pointer) * * @par Values * - true - generate 408 response * - false - invoke #nta_response_f callback with NULL sip pointer * when a non-INVITE transaction times out * * @sa @RFC4320, NTATAG_PASS_408(), NTATAG_EXTRA_100(), */ tag_typedef_t ntatag_timeout_408 = BOOLTAG_TYPEDEF(timeout_408); /**@def NTATAG_PASS_408(x) * * Pass "408 Request Timeout" responses to the client. * * As per recommended by @RFC4320, the 408 Request Timeout responses * to non-INVITE transaction are not sent over the network to the client by * default. The application can ask stack to pass the 408 responses with * NTATAG_PASS_408(1). * * Note that unlike NTATAG_PASS_100(), this tags changes the way server side * works. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * boolean: true (non-zero or non-NULL pointer) * or false (zero or NULL pointer) * * @par Values * - true - pass superfluous 408 responses * - false - discard superfluous 408 responses * * @sa @RFC4320, NTATAG_EXTRA_100(), NTATAG_TIMEOUT_408() * */ tag_typedef_t ntatag_pass_408 = BOOLTAG_TYPEDEF(pass_408); /**@def NTATAG_MERGE_482(x) * * Merge requests, send 482 to other requests. * * If an User-Agent receives a duplicate request with same @CallID, @CSeq, * @From tag but different topmost @Via header (see @RFC3261 section 8.2.2.2 * Merged Requests), it should return 482 Request Merged response to * the duplicate request. Such a duplicate request has been originally * generated by a forking proxy and usually routed via different route to * the User-Agent. The User-Agent should only respond meaningfully to the * first request and return the 482 response to the following forked * requests. * * Note that also NTATAG_UA(1) should be set before nta detects merges and * responds with 482 to them. * * @note If your application is an multi-lined user-agent, you may consider * disabling request merging. However, you have to somehow handle merging * within a single line. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * boolean: true (non-zero or non-NULL pointer) * or false (zero or NULL pointer) * * @par Values * - true - detect duplicate requests and respond with 482 to them * - false - process duplicate requests separately * * @sa NTATAG_UA(1) */ tag_typedef_t ntatag_merge_482 = BOOLTAG_TYPEDEF(merge_482); /**@def NTATAG_CANCEL_2543(x) * *Follow @RFC2543 semantics with CANCEL. * * By default, the nta follows "@RFC3261" semantics when CANCELing a * request. The CANCEL does not terminate transaction, rather, it is just a * hint to the server that it should respond immediately (with 487 * Request Terminated if it has no better response). Also, if the * original request was sent over unreliable transport such as UDP, the * CANCEL is delayed until the server has sent a preliminary response to the * original request. * * If NTATAG_CANCEL_2543(1) is given, the transaction is canceled * immediately internally (a 487 response is generated locally) and the * CANCEL request is sent without waiting for an provisional response. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * nta_outgoing_tcancel() * * @par Parameter type * boolean: true (non-zero or non-NULL pointer) * or false (zero or NULL pointer) * * @par Values * - true - follow "RFC 2543" semantics with CANCEL * - false - follow "RFC 3261" semantics with CANCEL * * @sa NTATAG_CANCEL_408() */ tag_typedef_t ntatag_cancel_2543 = BOOLTAG_TYPEDEF(cancel_2543); /**@def NTATAG_CANCEL_408(x) * * Do not send a CANCEL but just timeout the request. * * Calling nta_outgoing_tcancel() with this tag set marks request as * canceled but does not actually send a CANCEL request. If * NTATAG_CANCEL_2543(1) is also included, a 487 response is generated * internally. * * @par Used with * nta_outgoing_tcancel() \n * * @par Parameter type * boolean: true (non-zero or non-NULL pointer) * or false (zero or NULL pointer) * * @par Values * - true - do not send CANCEL * - false - let request to timeout * * @sa NTATAG_CANCEL_2543() */ tag_typedef_t ntatag_cancel_408 = BOOLTAG_TYPEDEF(cancel_408); /**@def NTATAG_CANCEL_487(x) * * When a CANCEL is received, automatically return 487 response to original request. * * When the CANCEL is received for an ongoing server transaction * #nta_incoming_t, the stack will automatically return a 487 Request * Terminated response to the client after returning from the * #nta_incoming_f callback bound to the transaction with * nta_incoming_bind() * * The application can delay sending the response to the original request * when NTATAG_CANCEL_408(0) is used. This is useful, for instance, with a * proxy that forwards the CANCEL downstream and the forwards the response * back to upstream. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * boolean: true (non-zero or non-NULL pointer) * or false (zero or NULL pointer) * * @par Values * - true - respond automatically to the CANCELed transaction * - false - application takes care of responding * * @sa NTATAG_CANCEL_2543(), nta_incoming_bind() */ tag_typedef_t ntatag_cancel_487 = BOOLTAG_TYPEDEF(cancel_487); /**@def NTATAG_TAG_3261(x) * * When responding to requests, use unique tags. * * If set the UA would generate an unique @From/@To tag for all dialogs. If * unset UA would reuse same tag in order to make it easier to re-establish * dialog state after a reboot. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * boolean: true (non-zero or non-NULL pointer) * or false (zero or NULL pointer) * * @par Values * - true - use different tag for each dialog * - false - use same tag for all dialogs * * @sa @RFC3261 section 12.2.2 */ tag_typedef_t ntatag_tag_3261 = BOOLTAG_TYPEDEF(tag_3261); /**@def NTATAG_REL100(x) * * Include rel100 in INVITE requests. * * Include feature tag "100rel" in @Supported header of the INVITE requests. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * boolean: true (non-zero or non-NULL pointer) * or false (zero or NULL pointer) * * @par Values * - true - include "100rel" * - false - do not include "100rel" * * @sa nta_outgoing_prack(), nta_reliable_treply(), nta_reliable_mreply() */ tag_typedef_t ntatag_rel100 = BOOLTAG_TYPEDEF(rel100); /**@def NTATAG_NO_DIALOG(x) * * Create a leg without dialog. */ tag_typedef_t ntatag_no_dialog = BOOLTAG_TYPEDEF(no_dialog); /**@def NTATAG_USE_TIMESTAMP(x) * * Use @Timestamp header. * * If set, a @Timestamp header would be added to stateful requests. The * header can be used to calculate the roundtrip transport latency between * client and server. * * @par Used with * nua_create(), * nta_agent_create(), * nta_agent_set_params(), * nta_outgoing_mcreate(), nta_outgoing_tcreate(), * nta_outgoing_tcancel(), and nta_outgoing_prack(). * * @par Parameter type * boolean: true (non-zero or non-NULL pointer) * or false (zero or NULL pointer) * * @par Values * - true - Add @Timestamp header * - false - do not add @Timestamp header * * @sa @RFC3261 section 8.2.6 */ tag_typedef_t ntatag_use_timestamp = BOOLTAG_TYPEDEF(use_timestamp); /**@def NTATAG_SIPFLAGS(x) * * Set SIP parser flags. * * The SIP parser flags affect how the messages are parsed and the result * presented to the application. They also control encoding of messages. * The most important flags are as follows: * - MSG_FLG_COMPACT - use compact form * (single-letter header names, minimum whitespace) * - MSG_FLG_EXTRACT_COPY - cache printable copy of headers when parsing. * Using this flag can speed up proxy processing considerably. It is * implied when the parsed messages are logged (because #TPORT_LOG * environment variable is set, or TPTAG_LOG() is used. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * unsigned int * * @par Values * - Bitwise OR of SIP parser flags (enum #msg_flg_user) * * @sa NTATAG_PRELOAD(), enum #msg_flg_user, sip_s::sip_flags */ tag_typedef_t ntatag_sipflags = UINTTAG_TYPEDEF(sipflags); /**@def NTATAG_CLIENT_RPORT(x) * * Enable client-side "rport". * * This tag controls @RFC3581 support on client side. The "rport" parameter * is used when the response has to be routed symmetrically through a NAT box. * * The client-side support involves just adding the "rport" parameter to the topmost * @Via header before the request is sent. * * @note By default, the client "rport" is disabled when nta is used, and * enabled when nua is used. * * @par Used with * nua_create() (nua uses NTATAG_CLIENT_RPORT(1) by default) \n * nta_agent_create() \n * nta_agent_set_params() \n * * @par Parameter type * boolean: true (non-zero or non-NULL pointer) * or false (zero or NULL pointer) * * @par Values * - true - add "rport" parameter * - false - do not add "rport" parameter * * @note The NTATAG_RPORT() is a synonym for this. * * @sa @RFC3581, NTATAG_SERVER_RPORT(), NTATAG_TCP_RPORT(), NTATAG_TLS_RPORT(), @Via */ tag_typedef_t ntatag_client_rport = BOOLTAG_TYPEDEF(client_rport); /**@def NTATAG_SERVER_RPORT(x) * * Use rport parameter at server. * * This tag controls @RFC3581 support on server side. The "rport" parameter * is used when the response has to be routed symmetrically through a NAT * box. * * If the topmost @Via header has an "rport" parameter, the server stores * the port number from which the request was sent in it. When sending the * response back to the client, the server uses the port number in the * "rport" parameter rather than the client-supplied port number in @Via * header. * * Note that on server-side the port number is stored regardless of the * transport protocol. (It is assumed that client supports rport if it * includes "rport" parameter in @Via field). * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * boolean: true (non-zero or non-NULL pointer) * or false (zero or NULL pointer) * * @par Values * - 3 - add "rport" parameter even if was not present in request * @b and if client User-Agent is "Polycom" * - 2 - add "rport" parameter even if was not present in request * - 1 - use "rport" parameter (default) * - 0 - do not use "rport" parameter * * @sa @RFC3581, NTATAG_CLIENT_RPORT(), NTATAG_TCP_RPORT(), NTATAG_TLS_RPORT(), @Via * * @since Tag type and NTATAG_SERVER_RPORT(2) was added in @VERSION_1_12_9. */ tag_typedef_t ntatag_server_rport = INTTAG_TYPEDEF(server_rport); /**@def NTATAG_TCP_RPORT(x) * * Use rport with TCP, too. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * boolean: true (non-zero or non-NULL pointer) * or false (zero or NULL pointer) * * @par Values * - true - include rport parameter in the TCP via line on client side * - false - do not include rport parameter in the TCP via line on client side * * @sa @RFC3581, NTATAG_CLIENT_RPORT(), NTATAG_SERVER_RPORT(), @Via */ tag_typedef_t ntatag_tcp_rport = BOOLTAG_TYPEDEF(tcp_rport); /**@def NTATAG_TLS_RPORT(x) * * Use rport with TLS, too. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * boolean: true (non-zero or non-NULL pointer) * or false (zero or NULL pointer) * * @par Values * - true - include rport parameter in the TLS via line on client side * - false - do not include rport parameter in the TLS via line * on client side * * @sa @RFC3581, NTATAG_CLIENT_RPORT(), NTATAG_SERVER_RPORT(), @Via * * @NEW_1_12_10 */ tag_typedef_t ntatag_tls_rport = BOOLTAG_TYPEDEF(tls_rport); /**@def NTATAG_PRELOAD(x) * * Preload by N bytes. * * When the memory block is allocated for an incoming request by the stack, * the stack can allocate some extra memory for the parser in addition to * the memory used by the actual message contents. * * While wasting some memory, this can speed up parsing considerably. * Recommended amount of preloading per packet is 1500 bytes. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * unsigned * * @par Values * Amount of extra per-message memory allocated for parser. * * @sa NTATAG_SIPFLAGS() and #MSG_FLG_EXTRACT_COPY */ tag_typedef_t ntatag_preload = UINTTAG_TYPEDEF(preload); /**@def NTATAG_USE_NAPTR(x) * * If true, try to use NAPTR records when resolving. * * The application can disable NTA from using NAPTR records when resolving * SIP URIs. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * boolean: true (non-zero or non-NULL pointer) * or false (zero or NULL pointer) * * @par Values * - true - enable NAPTR resolving * - false - disable NAPTR resolving * * @bug NAPTRs are not used with SIPS URIs in any case. * * @sa @RFC3263, NTATAG_USE_SRV() */ tag_typedef_t ntatag_use_naptr = BOOLTAG_TYPEDEF(naptr); /**@def NTATAG_USE_SRV(x) * * If true, try to use SRV records when resolving. * * The application can disable NTA from using SRV records when resolving * SIP URIs. * * @par Used with * nua_create(), nua_set_params(), * nta_agent_create(), nta_agent_set_params() * * @par Parameter type * boolean: true (non-zero or non-NULL pointer) * or false (zero or NULL pointer) * * @par Values * - true - enable SRV resolving * - false - disable SRV resolving * * @sa @RFC3263, NTATAG_USE_NAPTR() */ tag_typedef_t ntatag_use_srv = BOOLTAG_TYPEDEF(srv); /**@def NTATAG_RSEQ(x) * * @RSeq value for nta_outgoing_prack(). * * @par Used with * nta_outgoing_prack() * * @par Parameter type * @c unsigned @c int * * @par Values * Response sequence number from the @RSeq header. */ tag_typedef_t ntatag_rseq = UINTTAG_TYPEDEF(rseq); /* Status */ /**@def NTATAG_S_IRQ_HASH_REF(x) * * Get size of hash table for server-side transactions. * * Return number of transactions that fit in the hash table for server-side * transactions. * * @sa nta_agent_get_stats(), NTATAG_S_IRQ_HASH_USED_REF(), * NTATAG_S_ORQ_HASH_REFxs(), NTATAG_S_LEG_HASH_REF() */ tag_typedef_t ntatag_s_irq_hash = USIZETAG_TYPEDEF(s_irq_hash); /**@def NTATAG_S_ORQ_HASH_REF(x) * * Get size of hash table for client-side transactions. * * Return number of transactions that fit in the hash table for client-side * transactions. * * @sa nta_agent_get_stats(), NTATAG_S_ORQ_HASH_USED_REF(), * NTATAG_S_IRQ_HASH_REF(), NTATAG_S_LEG_HASH_REF() */ tag_typedef_t ntatag_s_orq_hash = USIZETAG_TYPEDEF(s_orq_hash); /**@def NTATAG_S_LEG_HASH_REF(x) * * Get size of hash table for dialogs. * * Return number of dialog objects that fit in the hash table for dialogs. * * @sa nta_agent_get_stats(), NTATAG_S_LEG_HASH_USED_REF(), * NTATAG_S_IRQ_HASH_REF(), NTATAG_S_ORQ_HASH_REF() */ tag_typedef_t ntatag_s_leg_hash = USIZETAG_TYPEDEF(s_leg_hash); /**@def NTATAG_S_IRQ_HASH_USED_REF(x) * * Get number of server-side transactions in the hash table. * * Return number of server-side transactions objects in the hash table. The * number includes all transactions destroyed by the application which have * not expired yet. * * @sa nta_agent_get_stats(), NTATAG_S_IRQ_HASH_REF(), * NTATAG_S_ORQ_HASH_USED_REF(), NTATAG_S_LEG_HASH_USED_REF() */ /**@def NTATAG_S_IRQ_HASH_USED_REF(x) * * Get number of server-side transactions in the hash table. * * Return number of server-side transactions objects in the hash table. The * number includes all transactions destroyed by the application which have * not expired yet. * * @sa nta_agent_get_stats(), NTATAG_S_IRQ_HASH_REF(), * NTATAG_S_ORQ_HASH_USED_REF(), NTATAG_S_LEG_HASH_USED_REF() */ tag_typedef_t ntatag_s_irq_hash_used = USIZETAG_TYPEDEF(s_irq_hash_used); /**@def NTATAG_S_ORQ_HASH_USED_REF(x) * * Get number of client-side transactions in the hash table. * * Return number of client-side transactions objects in the hash table. The * number includes all transactions destroyed by the application which have * not expired yet. * * @sa nta_agent_get_stats(), NTATAG_S_ORQ_HASH_REF(), * NTATAG_S_IRQ_HASH_USED_REF(), NTATAG_S_LEG_HASH_USED_REF() */ tag_typedef_t ntatag_s_orq_hash_used = USIZETAG_TYPEDEF(s_orq_hash_used); /**@def NTATAG_S_LEG_HASH_USED_REF(x) * * Get number of dialogs in the hash table. * * Return number of dialog objects in the hash table. Note that the * nta_leg_t objects created with NTATAG_NO_DIALOG(1) and this not * corresponding to a dialog are not included in the number. * * @sa nta_agent_get_stats(), NTATAG_S_LEG_HASH_REF(), * NTATAG_S_IRQ_HASH_USED_REF(), NTATAG_S_ORQ_HASH_USED_REF() */ tag_typedef_t ntatag_s_leg_hash_used = USIZETAG_TYPEDEF(s_leg_hash_used); /**@def NTATAG_S_RECV_MSG_REF(x) * * Get number of SIP messages received. * * Return number SIP messages that has been received. The number includes * also bad and unparsable messages. * * @sa nta_agent_get_stats(), NTATAG_S_BAD_MESSAGE_REF(), * NTATAG_S_RECV_REQUEST_REF(), NTATAG_S_RECV_RESPONSE_REF() */ tag_typedef_t ntatag_s_recv_msg = USIZETAG_TYPEDEF(s_recv_msg); /**@def NTATAG_S_RECV_REQUEST_REF(x) * * Get number of SIP requests received. * * Return number SIP requests that has been received. The number includes * also number of bad requests available with NTATAG_S_BAD_REQUEST_REF(). * * @sa nta_agent_get_stats(), NTATAG_S_BAD_REQUEST_REF(), * NTATAG_S_RECV_MSG_REF(), NTATAG_S_RECV_RESPONSE_REF() */ tag_typedef_t ntatag_s_recv_request = USIZETAG_TYPEDEF(s_recv_request); /**@def NTATAG_S_RECV_RESPONSE_REF(x) * * Get number of SIP responses received. * * Return number SIP responses that has been received. The number includes * also number of bad and unusable responses available with * NTATAG_S_BAD_RESPONSE_REF(). * * @sa nta_agent_get_stats(), NTATAG_S_BAD_RESPONSE_REF(), * NTATAG_S_RECV_MSG_REF(), NTATAG_S_RECV_REQUEST_REF() */ tag_typedef_t ntatag_s_recv_response = USIZETAG_TYPEDEF(s_recv_response); /**@def NTATAG_S_BAD_MESSAGE_REF(x) * * Get number of bad SIP messages received. * * Return number of bad SIP messages that has been received. * * @sa nta_agent_get_stats(), NTATAG_S_RECV_MSG_REF(), * NTATAG_S_BAD_REQUEST_REF(), NTATAG_S_BAD_RESPONSE_REF(). */ tag_typedef_t ntatag_s_bad_message = USIZETAG_TYPEDEF(s_bad_message); /**@def NTATAG_S_BAD_REQUEST_REF(x) * * Get number of bad SIP requests received. * * Return number of bad SIP requests that has been received. * * @sa nta_agent_get_stats(), NTATAG_S_BAD_MESSAGE_REF(), * NTATAG_S_BAD_RESPONSE_REF(). */ tag_typedef_t ntatag_s_bad_request = USIZETAG_TYPEDEF(s_bad_request); /**@def NTATAG_S_BAD_RESPONSE_REF(x) * * Get number of bad SIP responses received. * * Return number of bad SIP responses that has been received. * * @sa nta_agent_get_stats(), NTATAG_S_BAD_MESSAGE_REF(), * NTATAG_S_BAD_REQUEST_REF() */ tag_typedef_t ntatag_s_bad_response = USIZETAG_TYPEDEF(s_bad_response); /**@def NTATAG_S_DROP_REQUEST_REF(x) * * Get number of SIP requests dropped. * * Return number of SIP requests that has been randomly dropped after * receiving them because of NTATAG_DEBUG_DROP_PROB() has been set. * * @sa nta_agent_get_stats(), NTATAG_DEBUG_DROP_PROB(), * NTATAG_S_DROP_RESPONSE_REF() * * @note The value was not calculated before @VERSION_1_12_7. */ tag_typedef_t ntatag_s_drop_request = USIZETAG_TYPEDEF(s_drop_request); /**@def NTATAG_S_DROP_RESPONSE_REF(x) * * Get number of SIP responses dropped. * * Return number of SIP responses that has been randomly dropped after * receiving them because of NTATAG_DEBUG_DROP_PROB() has been set. * * @sa nta_agent_get_stats(), NTATAG_DEBUG_DROP_PROB(), * NTATAG_S_DROP_REQUEST_REF() * * @note The value was not calculated before @VERSION_1_12_7. */ tag_typedef_t ntatag_s_drop_response = USIZETAG_TYPEDEF(s_drop_response); /**@def NTATAG_S_CLIENT_TR_REF(x) * * Get number of client transactions created. * * Return number of client transactions created. The number also includes * client transactions with which stack failed to send the request because * the DNS resolving failed or the transport failed. * * @note The number include stateless requests sent with nta_msg_tsend(), * too. * * @sa nta_agent_get_stats(), NTATAG_S_SENT_REQUEST_REF(), * NTATAG_S_SERVER_TR_REF(). */ tag_typedef_t ntatag_s_client_tr = USIZETAG_TYPEDEF(s_client_tr); /**@def NTATAG_S_SERVER_TR_REF(x) * * Get number of server transactions created. * * Return number of server transactions created. * * @sa nta_agent_get_stats(), NTATAG_S_RECV_RESPONSE_REF(), * NTATAG_S_CLIENT_TR_REF(), NTATAG_S_DIALOG_TR_REF(), */ tag_typedef_t ntatag_s_server_tr = USIZETAG_TYPEDEF(s_server_tr); /**@def NTATAG_S_DIALOG_TR_REF(x) * * Get number of in-dialog server transactions created. * * Return number of in-dialog server transactions created. The number * includes only those transactions that were correlated with a dialog * object. * * @sa nta_agent_get_stats(), NTATAG_S_SERVER_TR_REF(), * NTATAG_S_CLIENT_TR_REF(), NTATAG_S_RECV_RESPONSE_REF(). */ tag_typedef_t ntatag_s_dialog_tr = USIZETAG_TYPEDEF(s_dialog_tr); /**@def NTATAG_S_ACKED_TR_REF(x) * * Get number of server transactions that have received ACK. * * Return number of INVITE server transactions for which an ACK request has * been received. * * @sa nta_agent_get_stats(), NTATAG_S_SERVER_TR_REF(), * NTATAG_S_CANCELED_TR_REF() */ tag_typedef_t ntatag_s_acked_tr = USIZETAG_TYPEDEF(s_acked_tr); /**@def NTATAG_S_CANCELED_TR_REF(x) * * Get number of server transactions that have been CANCELed. * * Return number of server transactions for which an CANCEL request has been * received. Currently, the count includes only INVITE server transactions * that have been CANCELed. * * @sa nta_agent_get_stats(), NTATAG_S_SERVER_TR_REF(), * NTATAG_S_ACKED_TR_REF(). */ tag_typedef_t ntatag_s_canceled_tr = USIZETAG_TYPEDEF(s_canceled_tr); /**@def NTATAG_S_TRLESS_REQUEST_REF(x) * * Get number of requests that were processed stateless. * * Return number of received requests that were processed statelessly, * either with #nta_message_f message callback given with the * nta_agent_create() or, missing the callback, by returning a 501 Not * Implemented response to the request. * * @sa nta_agent_get_stats(), , * nta_agent_create(), #nta_message_f, NTATAG_S_TRLESS_TO_TR_REF(), * NTATAG_S_TRLESS_RESPONSE_REF() */ tag_typedef_t ntatag_s_trless_request = USIZETAG_TYPEDEF(s_trless_request); /**@def NTATAG_S_TRLESS_TO_TR_REF(x) * * Get number of requests converted to transactions by message callback. * * Return number of requests that were converted to a server transaction * with nta_incoming_create(). * * @sa nta_agent_get_stats(), nta_incoming_create(), nta_agent_create(), * #nta_message_f, NTATAG_S_TRLESS_REQUEST_REF() */ tag_typedef_t ntatag_s_trless_to_tr = USIZETAG_TYPEDEF(s_trless_to_tr); /**@def NTATAG_S_TRLESS_RESPONSE_REF(x) * * Get number of responses without matching request. * * Return number of received responses for which no matching client * transaction was found. Such responses are processed either by the * client transaction created with nta_outgoing_default(), the * #nta_message_f message callback given to nta_agent_create(), or, missing * both the default client transaction and message callback, they are * silently discarded. * * The NTATAG_S_TRLESS_200_REF() counter counts those successful 2XX * responses to the INVITE without client transaction which are silently * discarded. * * @sa nta_agent_get_stats(), nta_outgoing_default(), nta_agent_create(), * , #nta_message_f, nta_msg_ackbye(), * NTATAG_S_TRLESS_REQUEST_REF(), NTATAG_S_TRLESS_200_REF(). */ tag_typedef_t ntatag_s_trless_response = USIZETAG_TYPEDEF(s_trless_response); /**@def NTATAG_S_TRLESS_200_REF(x) * * Get number of successful responses missing INVITE client transaction. * * Return number of received 2XX responses to INVITE transaction for which * no matching client transaction was found nor which were processed by a * default client transaction created with nta_outgoing_default() or * #nta_message_f message callback given to nta_agent_create(). * * @sa nta_agent_get_stats(), nta_outgoing_default(), nta_agent_create(), * , #nta_message_f, nta_msg_ackbye(), * NTATAG_S_TRLESS_RESPONSE_REF(). */ tag_typedef_t ntatag_s_trless_200 = USIZETAG_TYPEDEF(s_trless_200); /**@def NTATAG_S_MERGED_REQUEST_REF(x) * * Get number of requests merged by UAS. * * Return number of requests for which UAS already has returned a response * and which were merged (that is, returned a 482 Request Merged * response). * * @sa nta_agent_get_stats(), NTATAG_UA(1), @RFC3261 section 8.2.2.2 */ tag_typedef_t ntatag_s_merged_request = USIZETAG_TYPEDEF(s_merged_request); /**@def NTATAG_S_SENT_MSG_REF(x) * * Get number of SIP messages sent by stack. * * Return number of SIP messages given to the transport layer for * transmission by the SIP stack. The number includes also messages which * the transport layer failed to send for different reasons. * * @sa nta_agent_get_stats(), NTATAG_S_RECV_MSG_REF(), * NTATAG_S_SENT_REQUEST_REF(), NTATAG_S_SENT_RESPONSE_REF() */ tag_typedef_t ntatag_s_sent_msg = USIZETAG_TYPEDEF(s_sent_msg); /**@def NTATAG_S_SENT_REQUEST_REF(x) * * Get number of SIP requests sent by stack. * * Return number of SIP requests given to the transport layer for * transmission by the SIP stack. The number includes retransmissions and * messages which the transport layer failed to send for different reasons. * * @sa nta_agent_get_stats(), NTATAG_S_RECV_REQUEST_REF(), * NTATAG_S_SENT_MSG_REF(), NTATAG_S_SENT_RESPONSE_REF() */ tag_typedef_t ntatag_s_sent_request = USIZETAG_TYPEDEF(s_sent_request); /**@def NTATAG_S_SENT_RESPONSE_REF(x) * * Get number of SIP responses sent by stack. * * Return number of SIP responses given to the transport layer for * transmission by the SIP stack. The number includes retransmissions and * messages which the transport layer failed to send for different reasons. * * @sa nta_agent_get_stats(), NTATAG_S_RECV_RESPONSE_REF(), * NTATAG_S_SENT_MSG_REF(), NTATAG_S_SENT_REQUEST_REF() */ tag_typedef_t ntatag_s_sent_response = USIZETAG_TYPEDEF(s_sent_response); /**@def NTATAG_S_RETRY_REQUEST_REF(x) * * Get number of SIP requests retransmitted by stack. * * Return number of SIP requests given to the transport layer for * retransmission by the SIP stack. The number includes messages which the * transport layer failed to send for different reasons. * * @sa nta_agent_get_stats(), NTATAG_S_SENT_MSG_REF(), * NTATAG_S_SENT_REQUEST_REF(), NTATAG_S_RETRY_RESPONSE_REF() */ tag_typedef_t ntatag_s_retry_request = USIZETAG_TYPEDEF(s_retry_request); /**@def NTATAG_S_RETRY_RESPONSE_REF(x) * * Get number of SIP responses retransmitted by stack. * * Return number of SIP responses given to the transport layer for * retransmission by the SIP stack. The number includes messages which the * transport layer failed to send for different reasons. * * @sa nta_agent_get_stats(), NTATAG_S_SENT_MSG_REF(), * NTATAG_S_SENT_REQUEST_REF(), NTATAG_S_RETRY_REQUEST_REF() */ tag_typedef_t ntatag_s_retry_response = USIZETAG_TYPEDEF(s_retry_response); /**@def NTATAG_S_RECV_RETRY_REF(x) * * Get number of retransmitted SIP requests received by stack. * * Return number of SIP requests received by the stack. This number only * includes retransmission for which a matching server transaction object * was found. * * @sa nta_agent_get_stats(), NTATAG_S_RETRY_REQUEST_REF(). */ tag_typedef_t ntatag_s_recv_retry = USIZETAG_TYPEDEF(s_recv_retry); /**@def NTATAG_S_TOUT_REQUEST_REF(x) * * Get number of SIP client transactions that has timeout. * * Return number of SIP client transactions that has timeout. * * @sa nta_agent_get_stats(), NTATAG_S_TOUT_RESPONSE_REF(). */ tag_typedef_t ntatag_s_tout_request = USIZETAG_TYPEDEF(s_tout_request); /**@def NTATAG_S_TOUT_RESPONSE_REF(x) * * Get number of SIP server transactions that has timeout. * * Return number of SIP server transactions that has timeout. The number * includes only the INVITE transactions for which the stack has received no * ACK requests. * * @sa nta_agent_get_stats(), NTATAG_S_TOUT_REQUEST_REF(). */ tag_typedef_t ntatag_s_tout_response = USIZETAG_TYPEDEF(s_tout_response); /* Internal */ tag_typedef_t ntatag_delay_sending = BOOLTAG_TYPEDEF(delay_sending); tag_typedef_t ntatag_incomplete = BOOLTAG_TYPEDEF(incomplete); sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/portbind.c000066400000000000000000000132141223300710500223220ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@internal @file portbind.c * @brief Bind a socket to an UDP/TCP port and return the port number * * @author Pekka Pessi * * @date Created: Thu Mar 25 12:12:25 2004 ppessi */ #include "config.h" char const name[] = "portbind"; #include #include #include #include #include #include #if HAVE_SYS_SOCKET_T #include #endif #if HAVE_NETINET_IN_H #include #endif #if HAVE_NETDB_H #include #endif #include "sofia-sip/su.h" #if !defined(IPPROTO_SCTP) #define IPPROTO_SCTP (132) #endif static char const helptext[] = "usage: portbind OPTIONS [port]\n" " where OPTIONS are\n" " [-t] bind to TCP\n" " [-u] bind to UDP\n" " [-s] bind to SCTP\n" #if HAVE_SIN6 " [-6] bind to IPv6 only\n" " [-4] bind to IPv4 only\n" " By default, portbind binds to UDP and TCP on IPv6 and IPv4.\n" #else " By default, portbind binds to UDP and TCP.\n" #endif ; void usage(int returncode) { fprintf(returncode ? stderr : stdout, helptext); exit(returncode); } int main(int argc, char *argv[]) { char *o_port = "0", *o_protocol = NULL; int o_tcp = 0, o_udp = 0, o_sctp = 0; char *names[5] = { NULL }; int protos[5] = { 0 }; int types[5] = { 0 }; int n, N = 0; unsigned long portno; unsigned short port; int af; su_socket_t s; socklen_t salen; union { struct sockaddr sa[1]; struct sockaddr_in sin[1]; struct sockaddr_storage ss[1]; #if HAVE_SIN6 struct sockaddr_in6 sin6[1]; #endif } addr; struct sockaddr_storage *ss = addr.ss; struct sockaddr *sa = addr.sa; struct sockaddr_in *sin = addr.sin; #if HAVE_SIN6 int o_ip6 = 0, o_ip4 = 0; struct sockaddr_in6 *sin6 = addr.sin6; #endif for (argv++; *argv && **argv == '-';) { char *opt = *argv++ + 1; if (strcmp(opt, "-") == 0) break; else if (strcmp(opt, "P") == 0 && *argv) o_protocol = *argv++; else if (strcmp(opt, "u") == 0) o_udp = 1; else if (strcmp(opt, "t") == 0) o_tcp = 1; else if (strcmp(opt, "s") == 0) o_sctp = 1; else if (strcmp(opt, "h") == 0) usage(0); else if (strcmp(opt, "-help") == 0) usage(0); #if HAVE_SIN6 else if (strcmp(opt, "6") == 0) o_ip6 = AF_INET6; else if (strcmp(opt, "4") == 0) o_ip4 = 0; #endif else usage(1); } if (argv[0]) { char *s = NULL; portno = strtoul(argv[0], &s, 10); if (portno != (portno & 65535) || s == argv[0] || *s) { fprintf(stderr, "%s: invalid port %s\n", name, argv[0]); exit(1); } } else { portno = 0; } #if HAVE_SIN6 if (o_ip6) af = AF_INET6; else if (o_ip4) af = AF_INET; else af = AF_INET6; #else af = AF_INET; #endif memset(ss, 0, sizeof *ss); if (!o_tcp || !o_udp || !o_sctp || !o_protocol) o_tcp = o_udp = 1; if (o_protocol) { struct protoent *pent = getprotobyname(o_protocol); if (!pent) { fprintf(stderr, "%s: %s\n", o_protocol, "unknown protocol"); exit(1); } names[N] = pent->p_name, protos[N] = pent->p_proto, types[N++] = SOCK_RAW; } if (o_tcp) names[N] = "TCP", protos[N] = IPPROTO_TCP, types[N++] = SOCK_STREAM; if (o_udp) names[N] = "UDP", protos[N] = IPPROTO_UDP, types[N++] = SOCK_DGRAM; if (o_sctp) names[N] = "SCTP", protos[N] = IPPROTO_SCTP, types[N++] = SOCK_SEQPACKET; assert(N != 0); port = portno; for (n = 0; n < N;) { s = su_socket(sa->sa_family = af, types[n], protos[n]); #if HAVE_SIN6 if (s == INVALID_SOCKET && af == AF_INET6 && !o_ip6) s = su_socket(sa->sa_family = af = AF_INET, types[n], protos[n]); #endif if (s == INVALID_SOCKET) { fprintf(stderr, "%s: socket(AF_INET%s, 0, %s): %s\n", name, af == AF_INET ? "" : "6", names[n], strerror(errno)); exit(1); } #if HAVE_SIN6 if (af == AF_INET6 && !o_ip6 && !o_ip4) o_ip6 = o_ip4; if (af == AF_INET6) salen = sizeof *sin6; else #endif salen = sizeof *sin; sin->sin_port = htons(port); if (bind(s, sa, salen) == -1) { if (errno == EADDRINUSE) { if (++port == 0) port = 1024; if (port != portno) { close(s); n = 0; continue; } } fprintf(stderr, "%s: bind(%s): %s\n", name, o_port, strerror(errno)); exit(1); } if (portno == 0) { union { struct sockaddr sa[1]; struct sockaddr_in sin[1]; struct sockaddr_storage ss[1]; } addr; struct sockaddr *sa = addr.sa; struct sockaddr_in *sin = addr.sin; salen = sizeof addr; if (getsockname(s, sa, &salen) == -1) { fprintf(stderr, "%s: getsockname(): %s\n", name, strerror(errno)); exit(1); } portno = port = ntohs(sin->sin_port); } close(s); n++; } printf("%u\n", ntohs(sin->sin_port)); return 0; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/run_check_nta000077500000000000000000000000511223300710500230610ustar00rootroot00000000000000#!/bin/sh $VALGRIND exec ./check_nta "$@"sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/run_test_nta000077500000000000000000000122521223300710500227710ustar00rootroot00000000000000#! /bin/sh # # Run nta_test with our own name server # # -------------------------------------------------------------------- # # This file is part of the Sofia-SIP package # # Copyright (C) 2005 Nokia Corporation. # # Contact: Pekka Pessi # # 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 # # -------------------------------------------------------------------- # # Author: Pekka Pessi . # #set -x s=${0%/*} resolvfile=.test$$.resolv.conf namedfile=.test$$.named.conf pidfile=.test$$.named.pid zonefile=.test$$.example.zone test x$s = x$0 && s=`pwd` test -z "$srcdir" && srcdir=$s export srcdir PATH=/usr/sbin:/usr/local/sbin:/sbin:$PATH export PATH me6="::1" if ../su/localinfo -6 -n -g -s > /dev/null 2>&1 ; then ipv6=true aaaa=aaaa v6flag=-6 me6=$(../su/localinfo -6 -n -s -g | awk '{print $1; exit(0); }') else if ! ../su/localinfo '--help' > /dev/null 2>&1 ; then echo "warning: $0: missing 'localinfo', cannot test IPv6" else echo "warning: $0: no valid IPv6 addresses available" fi ipv6=false aaaa=a fi if type named > /dev/null 2>&1 && ./portbind --help > /dev/null 2>&1 then port=$(./portbind $v6flag) sink=$port port=$(./portbind $v6flag $((port + 1))) down=$port port=$(./portbind $v6flag $((port + 1))) bind=$port port=$(./portbind $v6flag $((port + 1))) contact=$port port=$(./portbind $v6flag $((port + 1))) sips=$port # Disable IPv6 resolver for now if false && eval $ipv6 ; then listen="listen-on-v6 port $bind { any; };" ns=$me6 else listen="listen-on port $bind { 127.0.0.1; };" ns="127.0.0.1" fi cat > $resolvfile < $namedfile < $zonefile << EOF ; ; Zone file for example.org ; SIP targets: example.org ; srv.example.org ; down.example.org ; na.example.org ; ipv6-20-80.example.org ; ipv.example.org ; \$TTL 60 @ IN SOA ns root ( 2002042901 ; SERIAL 7200 ; REFRESH 600 ; RETRY 36000000 ; EXPIRE 60 ; MINIMUM ) NS ns ;; order pref flags service regexp replacement NAPTR 20 15 "s" "SIP+D2U" "" _sip._udp NAPTR 40 25 "s" "SIPS+D2T" "" _sips._tcp NAPTR 40 50 "s" "SIP+D2T" "" _sip._tcp ns AAAA $me6 A 127.0.0.1 _sip._udp SRV 1 100 $contact me _sips._tcp SRV 3 100 $sips me _sip._tcp SRV 2 100 $contact me _sip._udp.srv SRV 1 100 $contact a _sips._tcp.srv SRV 3 100 $sips a _sip._tcp.srv SRV 2 100 $contact $aaaa _sip._udp.srv2 SRV 1 200 $contact c SRV 1 100 $contact b SRV 1 50 $contact a me AAAA $me6 A 127.0.0.1 a A 127.0.0.1 b A 0.0.0.2 c A 0.0.0.3 aaaa AAAA $me6 ; Directly from NAPTR to A/AAAA (Test 1.6c) na NAPTR 20 15 "a" "SIP+D2T" "" a2 ; No sensible NAPTR match (and we get 503) na503 NAPTR 20 15 "S" "SIP+D2F" "" a2 ; No SIP NAPTR match nona NAPTR 20 15 "S" "ZIP+D2U" "" a2 _sip._udp.nona SRV 1 10 $contact ip4 ; First SIP SRV is not found nosrv NAPTR 20 1 "s" "SIP+D2U" "" _sip._udp.nosrv NAPTR 20 2 "s" "SIP+D2T" "" _sip._tcp.nosrv NAPTR 20 3 "s" "SIP+D2U" "" _sip._udp.srv NAPTR 20 4 "s" "SIP+D2T" "" _sip._tcp.srv ; Redirect with TLS ; This fails (and we get 503) a2 A 127.0.0.2 ; IP6 should get 80%, IP4 20% ipv6-20-80 NAPTR 20 15 "s" "SIP+D2U" "" _sip._udp.ipv6-20-80 _sip._udp.ipv6-20-80 SRV 1 80 $contact ip6 SRV 1 20 $contact ip4 _sip._udp.ipv SRV 1 100 $contact ip6 _sip._udp.ipv SRV 1 100 $contact ip4 ip6 AAAA $me6 ip4 A 127.0.0.1 ; SRV failover to me... down NAPTR 20 15 "s" "SIP+D2U" "" _sip._udp.down _sip._udp.down SRV 1 100 $down me _sip._udp.down SRV 2 100 $contact me ; A failover down2 A 0.0.0.2 A 0.0.0.3 A 127.0.0.1 EOF # -g is also very nice option for named named -f -c $namedfile & pid=$! while ! test -r $pidfile && kill -0 $! 2>/dev/null do sleep 1 done if test -r $pidfile ; then # export SOFIA_DEBUG=9 sink=$sink down=$down \ ipv6=$ipv6 \ SIPCONTACT="sip:*:$contact;comp=sigcomp" \ SIPSCONTACT="sips:*:$sips;comp=sigcomp" \ TEST_NTA_CERTDIR=$srcdir/../tport/ \ $VALGRIND ./test_nta "$@" - $resolvfile exit=$? kill $(cat $pidfile) rm $pidfile $zonefile $resolvfile $namedfile 2>/dev/null exit $exit else echo "$0: cannot start named (check apparmor/selinux)" ipv6=$ipv6 $VALGRIND exec ./test_nta "$@" fi else # not having BIND and portbind ipv6=$ipv6 $VALGRIND exec ./test_nta "$@" fi sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/run_test_nta_api000077500000000000000000000021761223300710500236260ustar00rootroot00000000000000#! /bin/sh # # Run test_nta_api # # -------------------------------------------------------------------- # # This file is part of the Sofia-SIP package # # Copyright (C) 2005 Nokia Corporation. # # Contact: Pekka Pessi # # 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 # # -------------------------------------------------------------------- # # Author: Pekka Pessi . # #set -x s=${0%/*} exec $VALGRIND ./test_nta_api "$@" sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/sl_read_payload.c000066400000000000000000000054101223300710500236220ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@ingroup sl_utils * @CFILE sl_read_payload.c * * @brief Functions for reading SIP message payload from a file. * * @author Pekka Pessi * * @date Created: Thu Sep 5 00:44:34 2002 ppessi */ #include "config.h" #include #include #include #include #include #include /** Read payload from named file. * * The function sl_read_payload() reads the contents to a SIP payload * structure from a the named file. If @a fname is NULL, the payload * contents are read from standard input. */ sip_payload_t *sl_read_payload(su_home_t *home, char const *fname) { FILE *f; sip_payload_t *pl; if (fname == NULL || strcmp(fname, "-") == 0) f = stdin, fname = ""; else f = fopen(fname, "rb"); if (f == NULL) return NULL; pl = sl_fread_payload(home, f); if (f != stdin) fclose(f); return pl; } sip_payload_t *sl_fread_payload(su_home_t *home, FILE *f) { sip_payload_t *pl; size_t n; char *buf; char const *who; size_t used, size; if (f == NULL) { errno = EINVAL; return NULL; } pl = sip_payload_create(home, NULL, 0); if (pl == NULL) return NULL; /* Read block by block */ used = 0; size = 4096; buf = malloc(size); who = "sl_fread_payload: malloc"; while (buf) { n = fread(buf + used, 1, size - used, f); used += n; if (n < size - used) { if (feof(f)) ; else if (ferror(f)) { free(buf); buf = NULL; who = "sl_fread_payload: fread"; } break; } buf = realloc(buf, size = 2 * size); if (buf == NULL) who = "sl_fread_payload: realloc"; } if (buf == NULL) { perror(who); su_free(home, pl); return NULL; } if (used < size) buf[used] = '\0'; pl->pl_common->h_data = pl->pl_data = buf; pl->pl_common->h_len = pl->pl_len = used; return pl; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/sl_utils.docs000066400000000000000000000003121223300710500230400ustar00rootroot00000000000000/* -*- c -*- */ /**@defgroup sl_utils SIP Library Utilities - "sl_utils" * * SIP library utilities provide some simple utility functions for printing * and managing SIP headers or messages. * */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/sl_utils_log.c000066400000000000000000000174271223300710500232120ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@ingroup sl_utils * * @CFILE sl_utils_log.c * @brief Implementation of SIP library utility logging functions. * * @author Pekka Pessi * * @date Created: Thu Oct 5 15:38:39 2000 ppessi */ #include "config.h" #include #include #include #include #include #include #include #include "sofia-sip/sl_utils.h" /**Log a SIP message. * * The function sl_message_log() logs shorthand information identifying * the SIP message to the given @a log at level @a level. The shorthand * information include the method and URL by default. If @a details is * nonzero, topmost @Via, @CSeq, @To @b and @@From is included, too. * * @param log output log (if @c NULL, su_default_log() is used). * @param level log level * @param prefix string logged before the first line. *@param sip message to be logged. * @param details flag specifying if detailed output is desired. */ void sl_sip_log(su_log_t *log, int level, char const *prefix, sip_t const *sip, int details) { sip_cseq_t const *cs = sip->sip_cseq; if (log == NULL) log = su_log_default; assert(cs); if (sip->sip_request) { su_llog(log, level, "%s%s "URL_FORMAT_STRING" (CSeq %d %s)\n", prefix, sip->sip_request->rq_method_name, URL_PRINT_ARGS(sip->sip_request->rq_url), cs->cs_seq, cs->cs_method_name); if (!details) return; if (sip->sip_via) { char const *received = sip->sip_via->v_received; char const *port = sip->sip_via->v_port; su_llog(log, level, "\tvia %s%s%s%s%s%s\n", sip->sip_via->v_host, port ? ":" : "", port ? port : "", received ? " (" : "", received ? received : "", received ? ")" : ""); } } else { su_llog(log, level, "%s%03u %s (CSeq %d %s)\n", prefix, sip->sip_status->st_status, sip->sip_status->st_phrase, cs->cs_seq, cs->cs_method_name); if (!details) return; } if (sip->sip_from) sl_from_log(log, level, "\tFrom: %s\n", sip->sip_from); if (sip->sip_to) sl_to_log(log, level, "\tTo: %s\n", sip->sip_to); } /**Log a @From header. * * The function sl_from_log() logs the contents of @a from header to * the output @a log. The @a fmt specifies the output format, where %s * is replaced with header contents. If @a fmt is @c NULL, only the header * contents are logged. * * @param log output log * @param level logging level of output * @param fmt output format * @param from @From header */ void sl_from_log(su_log_t *log, int level, char const *fmt, sip_from_t const *from) { sip_addr_t a[1]; if (from == NULL) return; memcpy(a, from, sizeof a); a->a_params = NULL; if (!a->a_display) a->a_display = ""; sl_header_log(log, level, fmt, (sip_header_t *)a); } /**Log a @To header. * * The function sl_to_log() logs the contents of @a to header to the * log @a log with given @a level. The @a fmt specifies the output format, * where %s is replaced with header contents. If @a fmt is @c NULL, only the * header contents are logged. * * @param log output log * @param level logging level of output * @param fmt output format * @param to @To header */ void sl_to_log(su_log_t *log, int level, char const *fmt, sip_to_t const *to) { sl_from_log(log, level, fmt, (sip_from_t const *)to); } /**Log a @Contact header. * * The function sl_contact_log() logs the contents of @a contact header * to the log @a log with given @a level. The @a fmt specifies the output * format, where %s is replaced with header contents. If @a fmt is @c NULL, * only the header contents are logged. * * @param log output log * @param level logging level of output * @param fmt output format * @param contact @Contact header */ void sl_contact_log(su_log_t *log, int level, char const *fmt, sip_contact_t const *m) { sl_from_log(log, level, fmt, (sip_from_t const *)m); } /**Log an @Allow header(s). * * The function sl_allow_log() logs the contents of @a allow header to * the log @a log with given @a level. The @a fmt specifies the output * format, where %s is replaced with header contents. If @a fmt is @c NULL, * only the header contents are logged. * * @param log output log * @param level logging level of output * @param fmt output format * @param allow @Allow header * */ void sl_allow_log(su_log_t *log, int level, char const *fmt, sip_allow_t const *allow) { sl_header_log(log, level, fmt, (sip_header_t *)allow); } /**Log a @Via header. * * The function sl_via_log() logs the contents of @a via header to * the @a log. The @a fmt specifies the output format, where %s * is replaced with header contents. If @a fmt is @c NULL, only the header * contents are logged. * * @param log output log * @param fmt format used when logging * @param v via header */ void sl_via_log(su_log_t *log, int level, char const *fmt, sip_via_t const *v) { sl_header_log(log, level, fmt, (sip_header_t *)v); } /**Log message payload. * * The function sl_payload_log() logs the contents of @a payload object * to the output @a log. Each line in the payload is prepended with the * @a prefix. If @a prefix is @c NULL, only the header contents are logged. * For each line in payload, only first 70 charactes are logged, rest is * replaced with "...". * * @param log output log * @param level logging level of output * @param prefix prefix appended to each payload line * @param pl payload object */ void sl_payload_log(su_log_t *log, int level, char const *prefix, sip_payload_t const *pl) { char *s = pl->pl_data, *end = pl->pl_data + pl->pl_len; char line[74]; if (log == NULL) log = su_log_default; while (s < end && *s != '\0') { size_t n = su_strncspn(s, end - s, "\r\n"); size_t crlf = su_strnspn(s + n, end - s - n, "\r\n"); if (n < 70) { memcpy(line, s, n); line[n] = '\0'; } else { memcpy(line, s, 70); strcpy(line + 70, "..."); } su_llog(log, level, "%s%s\n", prefix, line); s += n + crlf; } } /** Log a header. * * Logs the contents of an header to the output @a stream. The @a fmt * specifies the output format, where %s is replaced with header contents. * If @a fmt is @c NULL, only the header contents are logged. * * @param stream output stream * @param fmt output format * @param h a SIP header object */ void sl_header_log(su_log_t *log, int level, char const *fmt, sip_header_t const *h) { char *s, b[1024]; issize_t len; len = sip_header_field_e(s = b, sizeof b, h, 0); if (len == -1) return; if ((size_t)len >= sizeof b) { s = malloc(len + 1); if (!s) return; sip_header_field_e(s, len + 1, h, 0); } s[len] = '\0'; if (fmt == NULL) fmt = "%s\n"; su_llog(log, level, fmt, s); if (s != b) free(s); } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/sl_utils_print.c000066400000000000000000000201341223300710500235520ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@ingroup sl_utils * * @CFILE sl_utils_print.c * @brief Implementation of SIP library utility print functions. * * @author Pekka Pessi * * @date Created: Thu Oct 5 15:38:39 2000 ppessi */ #include "config.h" #include #include #include #include #include #include "sofia-sip/sl_utils.h" /**Print a SIP message. * * The function sl_message_log() prints shorthand information identifying * the SIP message to the given output @a stream. The shorthand information * include the method and URL by default. If @a details is nonzero, topmost * @Via, @CSeq, @To and @From is included, too. * * @param stream output stream (if @c NULL, @c stdout is used). * @param prefix string printed before the first line. *@param sip message to be logged. * @param details flag specifying if detailed output is desired. */ void sl_message_log(FILE *stream, char const *prefix, sip_t const *sip, int details) { sip_cseq_t const *cs = sip->sip_cseq; if (stream == NULL) stream = stdout; assert(cs); if (sip->sip_request) { fprintf(stream, "%s%s "URL_FORMAT_STRING" (CSeq %d %s)\n", prefix, sip->sip_request->rq_method_name, URL_PRINT_ARGS(sip->sip_request->rq_url), cs->cs_seq, cs->cs_method_name); if (!details) return; if (sip->sip_via) { fputs(prefix, stream); sl_via_print(stream, "Via: %s\n", sip->sip_via); } } else { fprintf(stream, "%s%03u %s (CSeq %d %s)\n", prefix, sip->sip_status->st_status, sip->sip_status->st_phrase, cs->cs_seq, cs->cs_method_name); if (!details) return; } if (sip->sip_from) sl_from_print(stream, "\tFrom: %s\n", sip->sip_from); if (sip->sip_to) sl_to_print(stream, "\tTo: %s\n", sip->sip_to); } /** Print @From header. * * The function sl_from_print() prints the contents of @a from header to * the output @a stream. The @a fmt specifies the output format, where %s * is replaced with header contents. If @a fmt is @c NULL, only the header * contents are printed. * * @param stream output stream * @param fmt output format * @param from header object * * @return * The function sl_from_print() returns number of bytes printed, * or -1 upon an error. */ issize_t sl_from_print(FILE *stream, char const *fmt, sip_from_t const *from) { sip_addr_t a[1]; if (from == NULL) return -1; memcpy(a, from, sizeof a); a->a_params = NULL; if (!a->a_display) a->a_display = ""; return sl_header_print(stream, fmt, (sip_header_t *)a); } /** Print @To header. * * The function sl_to_print() prints the contents of @a to header to * the output @a stream. The @a fmt specifies the output format, where %s * is replaced with header contents. If @a fmt is @c NULL, only the header * contents are printed. * * @param stream output stream * @param fmt output format * @param to header object * * @return * The function sl_to_print() returns number of bytes printed, * or -1 upon an error. */ issize_t sl_to_print(FILE *stream, char const *fmt, sip_to_t const *to) { return sl_from_print(stream, fmt, (sip_from_t const *)to); } /** Print @Contact header. * * The function sl_contact_print() prints the contents of @a contact * header to the output @a stream. The @a fmt specifies the output format, * where %s is replaced with header contents. If @a fmt is @c NULL, only the * header contents are printed. * * @param stream output stream * @param fmt output format * @param contact header object * * @return * The function sl_contact_print() returns number of bytes printed, * or -1 upon an error. */ issize_t sl_contact_print(FILE *stream, char const *fmt, sip_contact_t const *m) { return sl_from_print(stream, fmt, (sip_from_t const *)m); } /** Print @Allow header(s). * * The function sl_allow_print() prints the contents of @a allow header to * the output @a stream. The @a fmt specifies the output format, where %s * is replaced with header contents. If @a fmt is @c NULL, only the header * contents are printed. * * @param stream output stream * @param fmt output format * @param allow header object * * @return * The function sl_allow_print() returns number of bytes printed, * or -1 upon an error. */ issize_t sl_allow_print(FILE *stream, char const *fmt, sip_allow_t const *allow) { return sl_header_print(stream, fmt, (sip_header_t *)allow); } /** Print message payload. * * The function sl_payload_print() prints the contents of @a payload * object to the output @a stream. The @a fmt specifies the output format, * where %s is replaced with header contents. If @a fmt is @c NULL, only the * header contents are printed. * * @param stream output stream * @param prefix prefix appended to each payload line * @param pl payload object * * @return * The function sl_payload_print() returns number of bytes printed, * or -1 upon an error. */ issize_t sl_payload_print(FILE *stream, char const *prefix, sip_payload_t const *pl) { char *s = pl->pl_data, *end = pl->pl_data + pl->pl_len; size_t n, total = 0, crlf = 1; while (s < end && *s != '\0') { n = su_strncspn(s, end - s, "\r\n"); crlf = su_strnspn(s + n, end - s - n, "\r\n"); if (prefix) fputs(prefix, stream), total += strlen(prefix); if (fwrite(s, 1, n + crlf, stream) < n + crlf) return (issize_t)-1; s += n + crlf; total += n + crlf; } if (crlf == 0) fputs("\n", stream), total++; return (issize_t)total; } /** Print @Via header. * * The function sl_via_print() prints the contents of @a via header to * the output @a stream. The @a fmt specifies the output format, where %s * is replaced with header contents. If @a fmt is @c NULL, only the header * contents are printed. * * @param stream output stream * @param fmt output format * @param v header object * * @return * The function sl_via_print() returns number of bytes printed, * or -1 upon an error. */ issize_t sl_via_print(FILE *stream, char const *fmt, sip_via_t const *v) { char s[1024]; sip_header_field_e(s, sizeof(s), (sip_header_t const *)v, 0); s[sizeof(s) - 1] = '\0'; if (fmt && strcmp(fmt, "%s")) return fprintf(stream, fmt, s); if (fputs(s, stream) >= 0) return (issize_t)strlen(s); return -1; } /** Print a header. * * Prints the contents of an header to the output @a stream. The @a fmt * specifies the output format, where %s is replaced with header contents. * If @a fmt is @c NULL, only the header contents are printed. * * @param stream output stream * @param fmt output format * @param v header object * * @return * Number of bytes logged, or -1 upon an error. */ issize_t sl_header_print(FILE *stream, char const *fmt, sip_header_t const *h) { char *s, b[1024]; issize_t len; len = sip_header_field_e(s = b, sizeof b, h, 0); if (len == -1) return len; if ((size_t)len >= sizeof b) { s = malloc(len + 1); if (!s) return -1; sip_header_field_e(s, len + 1, h, 0); } s[len] = '\0'; if (fmt != NULL && strcmp(fmt, "%s") != 0) len = fprintf(stream, fmt, s); else if (fputs(s, stream) < 0) len = -1; if (s != b) free(s); return len; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/sofia-sip/000077500000000000000000000000001223300710500222265ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/sofia-sip/nta.h000066400000000000000000000377111223300710500231720ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef NTA_H /** Defined when has been included. */ #define NTA_H /**@file sofia-sip/nta.h @brief Nokia Transaction API for SIP * * @author Pekka Pessi * * @date Created: Tue Jul 18 09:18:32 2000 ppessi */ #ifndef SU_WAIT_H #include #endif #ifndef SIP_H #include #endif #ifndef NTA_TAG_H #include #endif SOFIA_BEGIN_DECLS /* ---------------------------------------------------------------------- * 1) Types */ /** NTA agent */ typedef struct nta_agent_s nta_agent_t; /** NTA call leg */ typedef struct nta_leg_s nta_leg_t; /** NTA outgoing request */ typedef struct nta_outgoing_s nta_outgoing_t; /** NTA incoming request */ typedef struct nta_incoming_s nta_incoming_t; #ifndef NTA_AGENT_MAGIC_T /** Default type of application context for NTA agents. * Application may define this to appropriate type before including * . */ #define NTA_AGENT_MAGIC_T struct nta_agent_magic_s #endif #ifndef NTA_LEG_MAGIC_T /** Default type of application context for NTA call legs. * Application may define this to appropriate type before including * . */ #define NTA_LEG_MAGIC_T struct nta_leg_magic_s #endif #ifndef NTA_OUTGOING_MAGIC_T /** Default type of application context for outgoing NTA requests. * Application may define this to appropriate type before including * . */ #define NTA_OUTGOING_MAGIC_T struct nta_outgoing_magic_s #endif #ifndef NTA_INCOMING_MAGIC_T /** Default type of application context for incoming NTA requests. * Application may define this to appropriate type before including * . */ #define NTA_INCOMING_MAGIC_T struct nta_incoming_magic_s #endif /** Application context for NTA agents */ typedef NTA_AGENT_MAGIC_T nta_agent_magic_t; /** Application context for NTA call legs */ typedef NTA_LEG_MAGIC_T nta_leg_magic_t; /** Application context for outgoing NTA requests */ typedef NTA_OUTGOING_MAGIC_T nta_outgoing_magic_t; /** Application context for incoming NTA requests */ typedef NTA_INCOMING_MAGIC_T nta_incoming_magic_t; /* ---------------------------------------------------------------------- * 2) Constants */ /** NTA API version number */ #define NTA_VERSION "2.0" /** NTA module version */ SOFIAPUBVAR char const nta_version[]; enum { /* Stack parameters */ NTA_SIP_T1 = 500, /**< SIP T1, 500 milliseconds. */ NTA_SIP_T2 = 4000, /**< SIP T2, 4 seconds. */ NTA_SIP_T4 = 5000, /**< SIP T4, 5 seconds. */ NTA_TIME_MAX = 15 * 24 * 3600 * 1000 /**< Maximum value for timers. */ }; /* ---------------------------------------------------------------------- * 3) Agent-level prototypes */ typedef int nta_message_f(nta_agent_magic_t *context, nta_agent_t *agent, msg_t *msg, sip_t *sip); SOFIAPUBFUN nta_agent_t *nta_agent_create(su_root_t *root, url_string_t const *name, nta_message_f *callback, nta_agent_magic_t *magic, tag_type_t tag, tag_value_t value, ...); SOFIAPUBFUN void nta_agent_destroy(nta_agent_t *agent); SOFIAPUBFUN char const *nta_agent_version(nta_agent_t const *a); SOFIAPUBFUN nta_agent_magic_t *nta_agent_magic(nta_agent_t const *a); SOFIAPUBFUN int nta_agent_add_tport(nta_agent_t *agent, url_string_t const *url, tag_type_t tag, tag_value_t value, ...); SOFIAPUBFUN int nta_agent_close_tports(nta_agent_t *agent); SOFIAPUBFUN sip_contact_t *nta_agent_contact(nta_agent_t const *a); SOFIAPUBFUN sip_via_t *nta_agent_via(nta_agent_t const *a); SOFIAPUBFUN sip_via_t *nta_agent_public_via(nta_agent_t const *a); SOFIAPUBFUN char const *nta_agent_newtag(su_home_t *, char const *fmt, nta_agent_t *); SOFIAPUBFUN int nta_agent_set_params(nta_agent_t *agent, tag_type_t tag, tag_value_t value, ...); SOFIAPUBFUN int nta_agent_get_params(nta_agent_t *agent, tag_type_t tag, tag_value_t value, ...); SOFIAPUBFUN int nta_agent_get_stats(nta_agent_t *agent, tag_type_t tag, tag_value_t value, ...); /* ---------------------------------------------------------------------- * 4) Message-level prototypes */ SOFIAPUBFUN msg_t *nta_msg_create(nta_agent_t *self, int flags); SOFIAPUBFUN int nta_msg_complete(msg_t *msg); SOFIAPUBFUN int nta_msg_request_complete(msg_t *msg, nta_leg_t *leg, sip_method_t method, char const *method_name, url_string_t const *req_url); SOFIAPUBFUN int nta_msg_is_internal(msg_t const *msg); SOFIAPUBFUN int nta_sip_is_internal(sip_t const *sip); /* ---------------------------------------------------------------------- * 5) Leg-level prototypes */ typedef int nta_request_f(nta_leg_magic_t *lmagic, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip); SOFIAPUBFUN nta_leg_t *nta_leg_tcreate(nta_agent_t *agent, nta_request_f *req_callback, nta_leg_magic_t *magic, tag_type_t tag, tag_value_t value, ...); SOFIAPUBFUN void nta_leg_destroy(nta_leg_t *leg); SOFIAPUBFUN nta_leg_t *nta_default_leg(nta_agent_t const *agent); SOFIAPUBFUN nta_leg_magic_t *nta_leg_magic(nta_leg_t const *leg, nta_request_f *callback); SOFIAPUBFUN void nta_leg_bind(nta_leg_t *leg, nta_request_f *callback, nta_leg_magic_t *); /** Add local tag. */ SOFIAPUBFUN char const *nta_leg_tag(nta_leg_t *leg, char const *tag); /** Get local tag. */ SOFIAPUBFUN char const *nta_leg_get_tag(nta_leg_t const *leg); /** Add remote tag. */ SOFIAPUBFUN char const *nta_leg_rtag(nta_leg_t *leg, char const *tag); /** Get remote tag. */ SOFIAPUBFUN char const *nta_leg_get_rtag(nta_leg_t const *leg); /** Get local request sequence number. @NEW_1_12_9 */ SOFIAPUBFUN uint32_t nta_leg_get_seq(nta_leg_t const *leg); /** Get remote request sequence number. @NEW_1_12_9 */ SOFIAPUBFUN uint32_t nta_leg_get_rseq(nta_leg_t const *leg); SOFIAPUBFUN int nta_leg_client_route(nta_leg_t *leg, sip_record_route_t const *route, sip_contact_t const *contact); SOFIAPUBFUN int nta_leg_client_reroute(nta_leg_t *leg, sip_record_route_t const *route, sip_contact_t const *contact, int initial); SOFIAPUBFUN int nta_leg_server_route(nta_leg_t *leg, sip_record_route_t const *route, sip_contact_t const *contact); /** Get route */ SOFIAPUBFUN int nta_leg_get_route(nta_leg_t *leg, sip_route_t const **return_route, sip_contact_t const **return_target); /** Get leg by destination */ SOFIAPUBFUN nta_leg_t *nta_leg_by_uri(nta_agent_t const *, url_string_t const *); /** Get leg by dialog */ SOFIAPUBFUN nta_leg_t *nta_leg_by_dialog(nta_agent_t const *agent, url_t const *request_uri, sip_call_id_t const *call_id, char const *from_tag, url_t const *from_url, char const *to_tag, url_t const *to_url); /** Generate Replaces header */ SOFIAPUBFUN sip_replaces_t *nta_leg_make_replaces(nta_leg_t *leg, su_home_t *home, int early_only); /** Get dialog leg by Replaces header */ SOFIAPUBFUN nta_leg_t *nta_leg_by_replaces(nta_agent_t *, sip_replaces_t const *); /** Get dialog leg by CallID */ SOFIAPUBFUN nta_leg_t *nta_leg_by_call_id(nta_agent_t *sa, const char *call_id); /* ---------------------------------------------------------------------- * 6) Prototypes for incoming transactions */ SOFIAPUBFUN nta_incoming_t *nta_incoming_create(nta_agent_t *agent, nta_leg_t *leg, msg_t *msg, sip_t *sip, tag_type_t tag, tag_value_t value, ...); SOFIAPUBFUN nta_incoming_t *nta_incoming_default(nta_agent_t *agent); typedef int nta_ack_cancel_f(nta_incoming_magic_t *imagic, nta_incoming_t *irq, sip_t const *sip); SOFIAPUBFUN void nta_incoming_bind(nta_incoming_t *irq, nta_ack_cancel_f *callback, nta_incoming_magic_t *imagic); SOFIAPUBFUN nta_incoming_magic_t *nta_incoming_magic(nta_incoming_t *irq, nta_ack_cancel_f *callback); SOFIAPUBFUN nta_incoming_t *nta_incoming_find(nta_agent_t const *agent, sip_t const *sip, sip_via_t const *v); SOFIAPUBFUN char const *nta_incoming_tag(nta_incoming_t *irq, char const *tag); SOFIAPUBFUN char const *nta_incoming_gettag(nta_incoming_t const *irq); SOFIAPUBFUN int nta_incoming_status(nta_incoming_t const *irq); SOFIAPUBFUN sip_method_t nta_incoming_method(nta_incoming_t const *irq); SOFIAPUBFUN char const *nta_incoming_method_name(nta_incoming_t const *irq); SOFIAPUBFUN url_t const *nta_incoming_url(nta_incoming_t const *irq); SOFIAPUBFUN uint32_t nta_incoming_cseq(nta_incoming_t const *irq); SOFIAPUBFUN sip_time_t nta_incoming_received(nta_incoming_t *irq, su_nanotime_t *nano); SOFIAPUBFUN int nta_incoming_set_params(nta_incoming_t *irq, tag_type_t tag, tag_value_t value, ...); SOFIAPUBFUN msg_t *nta_incoming_getrequest(nta_incoming_t *irq); SOFIAPUBFUN msg_t *nta_incoming_getrequest_ackcancel(nta_incoming_t *irq); SOFIAPUBFUN msg_t *nta_incoming_getresponse(nta_incoming_t *irq); SOFIAPUBFUN int nta_incoming_complete_response(nta_incoming_t *irq, msg_t *msg, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...); SOFIAPUBFUN msg_t *nta_incoming_create_response(nta_incoming_t *irq, int status, char const *phrase); SOFIAPUBFUN int nta_incoming_treply(nta_incoming_t *ireq, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...); SOFIAPUBFUN int nta_incoming_mreply(nta_incoming_t *irq, msg_t *msg); SOFIAPUBFUN void nta_incoming_destroy(nta_incoming_t *irq); /* Functions for feature, method, mime, session-timer negotation */ SOFIAPUBFUN int nta_check_required(nta_incoming_t *irq, sip_t const *sip, sip_supported_t const *supported, tag_type_t tag, tag_value_t value, ...); SOFIAPUBFUN int nta_check_supported(nta_incoming_t *irq, sip_t const *sip, sip_require_t *require, tag_type_t tag, tag_value_t value, ...); SOFIAPUBFUN int nta_check_method(nta_incoming_t *irq, sip_t const *sip, sip_allow_t const *allow, tag_type_t tag, tag_value_t value, ...); SOFIAPUBFUN int nta_check_session_content(nta_incoming_t *irq, sip_t const *sip, sip_accept_t const *session_accepts, tag_type_t tag, tag_value_t value, ...); SOFIAPUBFUN int nta_check_accept(nta_incoming_t *irq, sip_t const *sip, sip_accept_t const *acceptable, sip_accept_t const **return_acceptable, tag_type_t tag, tag_value_t value, ...); SOFIAPUBFUN int nta_check_session_expires(nta_incoming_t *irq, sip_t const *sip, sip_time_t my_min_se, tag_type_t tag, tag_value_t value, ...); /* ---------------------------------------------------------------------- * 7) Prototypes for outgoing transactions */ typedef int nta_response_f(nta_outgoing_magic_t *magic, nta_outgoing_t *request, sip_t const *sip); SOFIAPUBFUN nta_outgoing_t *nta_outgoing_tcreate(nta_leg_t *leg, nta_response_f *callback, nta_outgoing_magic_t *magic, url_string_t const *route_url, sip_method_t method, char const *method_name, url_string_t const *request_uri, tag_type_t tag, tag_value_t value, ...); SOFIAPUBFUN nta_outgoing_t *nta_outgoing_mcreate(nta_agent_t *agent, nta_response_f *callback, nta_outgoing_magic_t *magic, url_string_t const *route_url, msg_t *msg, tag_type_t tag, tag_value_t value, ...); SOFIAPUBFUN nta_outgoing_t *nta_outgoing_default(nta_agent_t *agent, nta_response_f *callback, nta_outgoing_magic_t *magic); SOFIAPUBFUN int nta_outgoing_bind(nta_outgoing_t *orq, nta_response_f *callback, nta_outgoing_magic_t *magic); SOFIAPUBFUN nta_outgoing_magic_t *nta_outgoing_magic(nta_outgoing_t const *orq, nta_response_f *callback); SOFIAPUBFUN int nta_outgoing_status(nta_outgoing_t const *orq); SOFIAPUBFUN sip_method_t nta_outgoing_method(nta_outgoing_t const *orq); SOFIAPUBFUN char const *nta_outgoing_method_name(nta_outgoing_t const *orq); SOFIAPUBFUN uint32_t nta_outgoing_cseq(nta_outgoing_t const *orq); SOFIAPUBFUN char const *nta_outgoing_branch(nta_outgoing_t const *orq); SOFIAPUBFUN unsigned nta_outgoing_delay(nta_outgoing_t const *orq); SOFIAPUBFUN url_t const *nta_outgoing_request_uri(nta_outgoing_t const *orq); SOFIAPUBFUN url_t const *nta_outgoing_route_uri(nta_outgoing_t const *orq); SOFIAPUBFUN msg_t *nta_outgoing_getresponse(nta_outgoing_t *orq); SOFIAPUBFUN msg_t *nta_outgoing_getrequest(nta_outgoing_t *orq); SOFIAPUBFUN nta_outgoing_t *nta_outgoing_tagged(nta_outgoing_t *orq, nta_response_f *callback, nta_outgoing_magic_t *magic, char const *to_tag, sip_rseq_t const *rseq); SOFIAPUBFUN int nta_outgoing_cancel(nta_outgoing_t *); SOFIAPUBFUN nta_outgoing_t *nta_outgoing_tcancel(nta_outgoing_t *orq, nta_response_f *callback, nta_outgoing_magic_t *magic, tag_type_t, tag_value_t, ...); SOFIAPUBFUN void nta_outgoing_destroy(nta_outgoing_t *); SOFIAPUBFUN nta_outgoing_t *nta_outgoing_find(nta_agent_t const *sa, msg_t const *msg, sip_t const *sip, sip_via_t const *v); SOFIAPUBFUN int nta_tport_keepalive(nta_outgoing_t *orq); /* ---------------------------------------------------------------------- * 8) Reliable provisional responses (100rel) */ /* UAC side */ SOFIAPUBFUN nta_outgoing_t *nta_outgoing_prack(nta_leg_t *leg, nta_outgoing_t *oorq, nta_response_f *callback, nta_outgoing_magic_t *magic, url_string_t const *route_url, sip_t const *response_to_prack, tag_type_t, tag_value_t, ...); SOFIAPUBFUN uint32_t nta_outgoing_rseq(nta_outgoing_t const *orq); SOFIAPUBFUN int nta_outgoing_setrseq(nta_outgoing_t *orq, uint32_t rseq); /* UAS side */ /** NTA reliable response */ typedef struct nta_reliable_s nta_reliable_t; #ifndef NTA_RELIABLE_MAGIC_T /** Default type of application context for reliable preliminary responses. * Application may define this to appropriate type before including * . */ #define NTA_RELIABLE_MAGIC_T struct nta_reliable_magic_s #endif /** Application context for reliable preliminary responses. */ typedef NTA_RELIABLE_MAGIC_T nta_reliable_magic_t; typedef int nta_prack_f(nta_reliable_magic_t *rmagic, nta_reliable_t *rel, nta_incoming_t *prack, sip_t const *sip); SOFIAPUBFUN nta_reliable_t *nta_reliable_treply(nta_incoming_t *ireq, nta_prack_f *callback, nta_reliable_magic_t *rmagic, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...); SOFIAPUBFUN nta_reliable_t *nta_reliable_mreply(nta_incoming_t *irq, nta_prack_f *callback, nta_reliable_magic_t *rmagic, msg_t *msg); SOFIAPUBFUN void nta_reliable_destroy(nta_reliable_t *); /* ---------------------------------------------------------------------- * Backward-compatibility stuff - going away soon */ #define nta_outgoing_tmcreate nta_outgoing_mcreate #define nta_msg_response_complete(msg, irq, status, phrase) \ nta_incoming_complete_response((irq), (msg), (status), (phrase), TAG_END()) SOFIAPUBFUN void nta_msg_discard(nta_agent_t *agent, msg_t *msg); SOFIAPUBFUN int nta_is_internal_msg(msg_t const *msg); SOFIA_END_DECLS #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/sofia-sip/nta_stateless.h000066400000000000000000000062031223300710500252510ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef NTA_STATELESS_H /** Defined when has been included. */ #define NTA_STATELESS_H /**@file sofia-sip/nta_stateless.h * @brief NTA functions for stateless SIP processing. * * @author Pekka Pessi * * @date Created: Tue Sep 4 15:54:57 2001 ppessi */ #ifndef NTA_H #include #endif SOFIA_BEGIN_DECLS /**@typedef int nta_message_f(nta_agent_magic_t *context, * nta_agent_t *agent, * msg_t *msg, * sip_t *sip); * * Callback for incoming messages. * * The typedef nta_message_f() defines prototype for the callback functions * invoked by NTA when it has received an incoming message that will be * processed statelessly. * * The application can either discard the message by calling * nta_msg_discard(), forward it by calling nta_msg_tsend() or reply to the * message by calling nta_msg_treply(). When application wants to process a * request statefully, it passes the message to a leg with the function * nta_leg_stateful(). A new leg can be created by calling the function * nta_leg_tcreate(). * * @par Prototype * @code * int message_callback(nta_agent_magic_t *context, * nta_agent_t *agent, * msg_t *msg, * sip_t *sip); * @endcode * * @param context agent context * @param agent agent handle * @param msg received message * @param sip contents of message * * @return * This callback function should always return 0. */ /** Forward a request or response message. */ SOFIAPUBFUN int nta_msg_tsend(nta_agent_t *agent, msg_t *msg, url_string_t const *u, tag_type_t tag, tag_value_t value, ...); /** Reply to a request message. */ SOFIAPUBFUN int nta_msg_mreply(nta_agent_t *agent, msg_t *reply, sip_t *sip, int status, char const *phrase, msg_t *req_msg, tag_type_t tag, tag_value_t value, ...); /** Reply to a request message. */ SOFIAPUBFUN int nta_msg_treply(nta_agent_t *self, msg_t *msg, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...); /** ACK and BYE an unknown 200 OK response to INVITE. */ SOFIAPUBFUN int nta_msg_ackbye(nta_agent_t *a, msg_t *msg); SOFIA_END_DECLS #endif /* !defined(NTA_STATELESS_H) */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/sofia-sip/nta_tag.h000066400000000000000000000555321223300710500240260ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef NTA_TAG_H /** Defined when has been included. */ #define NTA_TAG_H /**@file sofia-sip/nta_tag.h * @brief NTA tags * * @author Pekka Pessi * * @date Created: Tue Sep 4 15:54:57 2001 ppessi */ #ifndef SU_TAG_H #include #endif #ifndef SIP_TAG_H #include #endif #ifndef URL_TAG_H #include #endif SOFIA_BEGIN_DECLS /** List of all nta tags. */ NTA_DLL extern tag_type_t nta_tag_list[]; /** Filter tag matching any nta tag. */ #define NTATAG_ANY() ntatag_any, ((tag_value_t)0) NTA_DLL extern tag_typedef_t ntatag_any; /* Tags for parameters */ NTA_DLL extern tag_typedef_t ntatag_mclass; #define NTATAG_MCLASS(x) ntatag_mclass, tag_cptr_v((x)) NTA_DLL extern tag_typedef_t ntatag_mclass_ref; #define NTATAG_MCLASS_REF(x) ntatag_mclass_ref, tag_cptr_vr(&(x), (x)) NTA_DLL extern tag_typedef_t ntatag_bad_req_mask; #define NTATAG_BAD_REQ_MASK(x) ntatag_bad_req_mask, tag_uint_v((x)) NTA_DLL extern tag_typedef_t ntatag_bad_req_mask_ref; #define NTATAG_BAD_REQ_MASK_REF(x) ntatag_bad_req_mask_ref, tag_uint_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_bad_resp_mask; #define NTATAG_BAD_RESP_MASK(x) ntatag_bad_resp_mask, tag_uint_v((x)) NTA_DLL extern tag_typedef_t ntatag_bad_resp_mask_ref; #define NTATAG_BAD_RESP_MASK_REF(x) ntatag_bad_resp_mask_ref, tag_uint_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_default_proxy; #define NTATAG_DEFAULT_PROXY(x) ntatag_default_proxy, urltag_url_v((x)) NTA_DLL extern tag_typedef_t ntatag_default_proxy_ref; #define NTATAG_DEFAULT_PROXY_REF(x) \ ntatag_default_proxy_ref, urltag_url_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_contact; #define NTATAG_CONTACT(x) ntatag_contact, siptag_contact_v((x)) NTA_DLL extern tag_typedef_t ntatag_contact_ref; #define NTATAG_CONTACT_REF(x) ntatag_contact_ref, siptag_contact_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_target; #define NTATAG_TARGET(x) ntatag_target, siptag_contact_v((x)) NTA_DLL extern tag_typedef_t ntatag_target_ref; #define NTATAG_TARGET_REF(x) ntatag_target_ref, siptag_contact_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_aliases; #define NTATAG_ALIASES(x) ntatag_aliases, siptag_contact_v((x)) NTA_DLL extern tag_typedef_t ntatag_aliases_ref; #define NTATAG_ALIASES_REF(x) ntatag_aliases_ref, siptag_contact_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_branch_key; #define NTATAG_BRANCH_KEY(x) ntatag_branch_key, tag_str_v((x)) NTA_DLL extern tag_typedef_t ntatag_branch_key_ref; #define NTATAG_BRANCH_KEY_REF(x) \ ntatag_branch_key_ref, tag_str_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_ack_branch; #define NTATAG_ACK_BRANCH(x) ntatag_ack_branch, tag_str_v((x)) NTA_DLL extern tag_typedef_t ntatag_ack_branch_ref; #define NTATAG_ACK_BRANCH_REF(x) ntatag_ack_branch_ref, tag_str_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_comp; #define NTATAG_COMP(x) ntatag_comp, tag_str_v((x)) NTA_DLL extern tag_typedef_t ntatag_comp_ref; #define NTATAG_COMP_REF(x) ntatag_comp_ref, tag_str_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_msg; #define NTATAG_MSG(x) ntatag_msg, tag_ptr_v((x)) NTA_DLL extern tag_typedef_t ntatag_msg_ref; #define NTATAG_MSG_REF(x) ntatag_msg_ref, tag_ptr_vr(&(x), (x)) NTA_DLL extern tag_typedef_t ntatag_tport; #define NTATAG_TPORT(x) ntatag_tport, tag_ptr_v((x)) NTA_DLL extern tag_typedef_t ntatag_tport_ref; #define NTATAG_TPORT_REF(x) ntatag_tport_ref, tag_ptr_vr(&(x), (x)) NTA_DLL extern tag_typedef_t ntatag_remote_cseq; #define NTATAG_REMOTE_CSEQ(x) ntatag_remote_cseq, tag_uint_v((x)) NTA_DLL extern tag_typedef_t ntatag_remote_cseq_ref; #define NTATAG_REMOTE_CSEQ_REF(x) ntatag_remote_cseq_ref, tag_uint_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_smime; #define NTATAG_SMIME(x) ntatag_smime, tag_ptr_v((x)) NTA_DLL extern tag_typedef_t ntatag_smime_ref; #define NTATAG_SMIME_REF(x) ntatag_smime_ref, tag_ptr_vr(&(x), (x)) NTA_DLL extern tag_typedef_t ntatag_maxsize; #define NTATAG_MAXSIZE(x) ntatag_maxsize, tag_usize_v((x)) NTA_DLL extern tag_typedef_t ntatag_maxsize_ref; #define NTATAG_MAXSIZE_REF(x) ntatag_maxsize_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_udp_mtu; #define NTATAG_UDP_MTU(x) ntatag_udp_mtu, tag_uint_v((x)) NTA_DLL extern tag_typedef_t ntatag_udp_mtu_ref; #define NTATAG_UDP_MTU_REF(x) ntatag_udp_mtu_ref, tag_uint_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_max_proceeding; #define NTATAG_MAX_PROCEEDING(x) ntatag_max_proceeding, tag_usize_v((x)) NTA_DLL extern tag_typedef_t ntatag_max_proceeding_ref; #define NTATAG_MAX_PROCEEDING_REF(x) ntatag_max_proceeding_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_max_forwards; #define NTATAG_MAX_FORWARDS(x) ntatag_max_forwards, tag_uint_v((x)) NTA_DLL extern tag_typedef_t ntatag_max_forwards_ref; #define NTATAG_MAX_FORWARDS_REF(x) ntatag_max_forwards_ref, tag_uint_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_sip_t1; #define NTATAG_SIP_T1(x) ntatag_sip_t1, tag_uint_v((x)) NTA_DLL extern tag_typedef_t ntatag_sip_t1_ref; #define NTATAG_SIP_T1_REF(x) ntatag_sip_t1_ref, tag_uint_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_sip_t1x64; #define NTATAG_SIP_T1X64(x) ntatag_sip_t1x64, tag_uint_v((x)) NTA_DLL extern tag_typedef_t ntatag_sip_t1x64_ref; #define NTATAG_SIP_T1X64_REF(x) ntatag_sip_t1x64_ref, tag_uint_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_sip_t2; #define NTATAG_SIP_T2(x) ntatag_sip_t2, tag_uint_v((x)) NTA_DLL extern tag_typedef_t ntatag_sip_t2_ref; #define NTATAG_SIP_T2_REF(x) ntatag_sip_t2_ref, tag_uint_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_sip_t4; #define NTATAG_SIP_T4(x) ntatag_sip_t4, tag_uint_v((x)) NTA_DLL extern tag_typedef_t ntatag_sip_t4_ref; #define NTATAG_SIP_T4_REF(x) ntatag_sip_t4_ref, tag_uint_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_progress; #define NTATAG_PROGRESS(x) ntatag_progress, tag_uint_v((x)) NTA_DLL extern tag_typedef_t ntatag_progress_ref; #define NTATAG_PROGRESS_REF(x) ntatag_progress_ref, tag_uint_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_timer_c; #define NTATAG_TIMER_C(x) ntatag_timer_c, tag_uint_v((x)) NTA_DLL extern tag_typedef_t ntatag_timer_c_ref; #define NTATAG_TIMER_C_REF(x) ntatag_timer_c_ref, tag_uint_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_graylist; #define NTATAG_GRAYLIST(x) ntatag_graylist, tag_uint_v((x)) NTA_DLL extern tag_typedef_t ntatag_graylist_ref; #define NTATAG_GRAYLIST_REF(x) ntatag_graylist_ref, tag_uint_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_blacklist; #define NTATAG_BLACKLIST(x) ntatag_blacklist, tag_uint_v((x)) NTA_DLL extern tag_typedef_t ntatag_blacklist_ref; #define NTATAG_BLACKLIST_REF(x) ntatag_blacklist_ref, tag_uint_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_debug_drop_prob; #define NTATAG_DEBUG_DROP_PROB(x) ntatag_debug_drop_prob, tag_uint_v((x)) NTA_DLL extern tag_typedef_t ntatag_debug_drop_prob_ref; #define NTATAG_DEBUG_DROP_PROB_REF(x) ntatag_debug_drop_prob_ref, tag_uint_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_sigcomp_options; #define NTATAG_SIGCOMP_OPTIONS(x) ntatag_sigcomp_options, tag_str_v((x)) NTA_DLL extern tag_typedef_t ntatag_sigcomp_options_ref; #define NTATAG_SIGCOMP_OPTIONS_REF(x) ntatag_sigcomp_options_ref, tag_str_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_sigcomp_close; #define NTATAG_SIGCOMP_CLOSE(x) ntatag_sigcomp_close, tag_bool_v((x)) NTA_DLL extern tag_typedef_t ntatag_sigcomp_close_ref; #define NTATAG_SIGCOMP_CLOSE_REF(x) ntatag_sigcomp_close_ref, tag_bool_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_sigcomp_aware; #define NTATAG_SIGCOMP_AWARE(x) ntatag_sigcomp_aware, tag_bool_v((x)) NTA_DLL extern tag_typedef_t ntatag_sigcomp_aware_ref; #define NTATAG_SIGCOMP_AWARE_REF(x) ntatag_sigcomp_aware_ref, tag_bool_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_sigcomp_algorithm; #define NTATAG_SIGCOMP_ALGORITHM(x) ntatag_sigcomp_algorithm, tag_str_v((x)) NTA_DLL extern tag_typedef_t ntatag_sigcomp_algorithm_ref; #define NTATAG_SIGCOMP_ALGORITHM_REF(x) \ ntatag_sigcomp_algorithm_ref, tag_str_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_ua; #define NTATAG_UA(x) ntatag_ua, tag_bool_v((x)) NTA_DLL extern tag_typedef_t ntatag_ua_ref; #define NTATAG_UA_REF(x) ntatag_ua_ref, tag_bool_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_stateless; #define NTATAG_STATELESS(x) ntatag_stateless, tag_bool_v((x)) NTA_DLL extern tag_typedef_t ntatag_stateless_ref; #define NTATAG_STATELESS_REF(x) ntatag_stateless_ref, tag_bool_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_user_via; #define NTATAG_USER_VIA(x) ntatag_user_via, tag_bool_v((x)) NTA_DLL extern tag_typedef_t ntatag_user_via_ref; #define NTATAG_USER_VIA_REF(x) ntatag_user_via_ref, tag_bool_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_extra_100; #define NTATAG_EXTRA_100(x) ntatag_extra_100, tag_bool_v((x)) NTA_DLL extern tag_typedef_t ntatag_extra_100_ref; #define NTATAG_EXTRA_100_REF(x) ntatag_extra_100_ref, tag_bool_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_pass_100; #define NTATAG_PASS_100(x) ntatag_pass_100, tag_bool_v((x)) NTA_DLL extern tag_typedef_t ntatag_pass_100_ref; #define NTATAG_PASS_100_REF(x) ntatag_pass_100_ref, tag_bool_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_timeout_408; #define NTATAG_TIMEOUT_408(x) ntatag_timeout_408, tag_bool_v((x)) NTA_DLL extern tag_typedef_t ntatag_timeout_408_ref; #define NTATAG_TIMEOUT_408_REF(x) ntatag_timeout_408_ref, tag_bool_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_pass_408; #define NTATAG_PASS_408(x) ntatag_pass_408, tag_bool_v((x)) NTA_DLL extern tag_typedef_t ntatag_pass_408_ref; #define NTATAG_PASS_408_REF(x) ntatag_pass_408_ref, tag_bool_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_no_dialog; #define NTATAG_NO_DIALOG(x) ntatag_no_dialog, tag_bool_v((x)) NTA_DLL extern tag_typedef_t ntatag_no_dialog_ref; #define NTATAG_NO_DIALOG_REF(x) ntatag_no_dialog_ref, tag_bool_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_merge_482; #define NTATAG_MERGE_482(x) ntatag_merge_482, tag_bool_v((x)) NTA_DLL extern tag_typedef_t ntatag_merge_482_ref; #define NTATAG_MERGE_482_REF(x) ntatag_merge_482_ref, tag_bool_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_cancel_2543; #define NTATAG_CANCEL_2543(x) ntatag_cancel_2543, tag_bool_v((x)) NTA_DLL extern tag_typedef_t ntatag_cancel_2543_ref; #define NTATAG_CANCEL_2543_REF(x) ntatag_cancel_2543_ref, tag_bool_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_cancel_408; #define NTATAG_CANCEL_408(x) ntatag_cancel_408, tag_bool_v((x)) NTA_DLL extern tag_typedef_t ntatag_cancel_408_ref; #define NTATAG_CANCEL_408_REF(x) ntatag_cancel_408_ref, tag_bool_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_tag_3261; #define NTATAG_TAG_3261(x) ntatag_tag_3261, tag_bool_v((x)) NTA_DLL extern tag_typedef_t ntatag_tag_3261_ref; #define NTATAG_TAG_3261_REF(x) ntatag_tag_3261_ref, tag_bool_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_use_timestamp; #define NTATAG_USE_TIMESTAMP(x) ntatag_use_timestamp, tag_bool_v((x)) NTA_DLL extern tag_typedef_t ntatag_use_timestamp_ref; #define NTATAG_USE_TIMESTAMP_REF(x) ntatag_use_timestamp_ref, tag_bool_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_method; #define NTATAG_METHOD(x) ntatag_method, tag_str_v((x)) NTA_DLL extern tag_typedef_t ntatag_method_ref; #define NTATAG_METHOD_REF(x) ntatag_method_ref, tag_str_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_cancel_487; #define NTATAG_CANCEL_487(x) ntatag_cancel_487, tag_bool_v((x)) NTA_DLL extern tag_typedef_t ntatag_cancel_487_ref; #define NTATAG_CANCEL_487_REF(x) ntatag_cancel_487_ref, tag_bool_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_rel100; #define NTATAG_REL100(x) ntatag_rel100, tag_bool_v((x)) NTA_DLL extern tag_typedef_t ntatag_rel100_ref; #define NTATAG_REL100_REF(x) ntatag_rel100_ref, tag_bool_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_sipflags; #define NTATAG_SIPFLAGS(x) ntatag_sipflags, tag_uint_v((x)) NTA_DLL extern tag_typedef_t ntatag_sipflags_ref; #define NTATAG_SIPFLAGS_REF(x) ntatag_sipflags_ref, tag_uint_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_client_rport; #define NTATAG_CLIENT_RPORT(x) ntatag_client_rport, tag_bool_v((x)) NTA_DLL extern tag_typedef_t ntatag_client_rport_ref; #define NTATAG_CLIENT_RPORT_REF(x) ntatag_client_rport_ref, tag_bool_vr(&(x)) #define NTATAG_RPORT(x) ntatag_client_rport, tag_bool_v((x)) #define NTATAG_RPORT_REF(x) ntatag_client_rport_ref, tag_bool_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_server_rport; #define NTATAG_SERVER_RPORT(x) ntatag_server_rport, tag_int_v((x)) NTA_DLL extern tag_typedef_t ntatag_server_rport_ref; #define NTATAG_SERVER_RPORT_REF(x) ntatag_server_rport_ref, tag_int_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_tcp_rport; #define NTATAG_TCP_RPORT(x) ntatag_tcp_rport, tag_bool_v((x)) NTA_DLL extern tag_typedef_t ntatag_tcp_rport_ref; #define NTATAG_TCP_RPORT_REF(x) ntatag_tcp_rport_ref, tag_bool_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_tls_rport; #define NTATAG_TLS_RPORT(x) ntatag_tls_rport, tag_bool_v((x)) NTA_DLL extern tag_typedef_t ntatag_tls_rport_ref; #define NTATAG_TLS_RPORT_REF(x) ntatag_tls_rport_ref, tag_bool_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_preload; #define NTATAG_PRELOAD(x) ntatag_preload, tag_uint_v((x)) NTA_DLL extern tag_typedef_t ntatag_preload_ref; #define NTATAG_PRELOAD_REF(x) ntatag_preload_ref, tag_uint_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_use_naptr; #define NTATAG_USE_NAPTR(x) ntatag_use_naptr, tag_bool_v((x)) NTA_DLL extern tag_typedef_t ntatag_use_naptr_ref; #define NTATAG_USE_NAPTR_REF(x) ntatag_use_naptr_ref, tag_bool_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_use_srv; #define NTATAG_USE_SRV(x) ntatag_use_srv, tag_bool_v((x)) NTA_DLL extern tag_typedef_t ntatag_use_srv_ref; #define NTATAG_USE_SRV_REF(x) ntatag_use_srv_ref, tag_bool_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_rseq; #define NTATAG_RSEQ(x) ntatag_rseq, tag_uint_v((x)) NTA_DLL extern tag_typedef_t ntatag_rseq_ref; #define NTATAG_RSEQ_REF(x) ntatag_rseq_ref, tag_uint_vr(&(x)) /* ====================================================================== */ /* Tags for statistics. */ NTA_DLL extern tag_typedef_t ntatag_s_irq_hash; #define NTATAG_S_IRQ_HASH(x) ntatag_s_irq_hash, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_irq_hash_ref; #define NTATAG_S_IRQ_HASH_REF(x) ntatag_s_irq_hash_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_orq_hash; #define NTATAG_S_ORQ_HASH(x) ntatag_s_orq_hash, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_orq_hash_ref; #define NTATAG_S_ORQ_HASH_REF(x) ntatag_s_orq_hash_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_leg_hash; #define NTATAG_S_LEG_HASH(x) ntatag_s_leg_hash, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_leg_hash_ref; #define NTATAG_S_LEG_HASH_REF(x) ntatag_s_leg_hash_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_irq_hash_used; #define NTATAG_S_IRQ_HASH_USED(x) ntatag_s_irq_hash_used, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_irq_hash_used_ref; #define NTATAG_S_IRQ_HASH_USED_REF(x) ntatag_s_irq_hash_used_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_orq_hash_used; #define NTATAG_S_ORQ_HASH_USED(x) ntatag_s_orq_hash_used, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_orq_hash_used_ref; #define NTATAG_S_ORQ_HASH_USED_REF(x) ntatag_s_orq_hash_used_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_leg_hash_used; #define NTATAG_S_LEG_HASH_USED(x) ntatag_s_leg_hash_used, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_leg_hash_used_ref; #define NTATAG_S_LEG_HASH_USED_REF(x) ntatag_s_leg_hash_used_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_recv_msg; #define NTATAG_S_RECV_MSG(x) ntatag_s_recv_msg, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_recv_msg_ref; #define NTATAG_S_RECV_MSG_REF(x) ntatag_s_recv_msg_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_recv_request; #define NTATAG_S_RECV_REQUEST(x) ntatag_s_recv_request, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_recv_request_ref; #define NTATAG_S_RECV_REQUEST_REF(x) ntatag_s_recv_request_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_recv_response; #define NTATAG_S_RECV_RESPONSE(x) ntatag_s_recv_response, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_recv_response_ref; #define NTATAG_S_RECV_RESPONSE_REF(x) ntatag_s_recv_response_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_bad_message; #define NTATAG_S_BAD_MESSAGE(x) ntatag_s_bad_message, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_bad_message_ref; #define NTATAG_S_BAD_MESSAGE_REF(x) ntatag_s_bad_message_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_bad_request; #define NTATAG_S_BAD_REQUEST(x) ntatag_s_bad_request, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_bad_request_ref; #define NTATAG_S_BAD_REQUEST_REF(x) ntatag_s_bad_request_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_bad_response; #define NTATAG_S_BAD_RESPONSE(x) ntatag_s_bad_response, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_bad_response_ref; #define NTATAG_S_BAD_RESPONSE_REF(x) ntatag_s_bad_response_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_drop_request; #define NTATAG_S_DROP_REQUEST(x) ntatag_s_drop_request, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_drop_request_ref; #define NTATAG_S_DROP_REQUEST_REF(x) ntatag_s_drop_request_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_drop_response; #define NTATAG_S_DROP_RESPONSE(x) ntatag_s_drop_response, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_drop_response_ref; #define NTATAG_S_DROP_RESPONSE_REF(x) ntatag_s_drop_response_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_client_tr; #define NTATAG_S_CLIENT_TR(x) ntatag_s_client_tr, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_client_tr_ref; #define NTATAG_S_CLIENT_TR_REF(x) ntatag_s_client_tr_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_server_tr; #define NTATAG_S_SERVER_TR(x) ntatag_s_server_tr, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_server_tr_ref; #define NTATAG_S_SERVER_TR_REF(x) ntatag_s_server_tr_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_dialog_tr; #define NTATAG_S_DIALOG_TR(x) ntatag_s_dialog_tr, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_dialog_tr_ref; #define NTATAG_S_DIALOG_TR_REF(x) ntatag_s_dialog_tr_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_acked_tr; #define NTATAG_S_ACKED_TR(x) ntatag_s_acked_tr, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_acked_tr_ref; #define NTATAG_S_ACKED_TR_REF(x) ntatag_s_acked_tr_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_canceled_tr; #define NTATAG_S_CANCELED_TR(x) ntatag_s_canceled_tr, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_canceled_tr_ref; #define NTATAG_S_CANCELED_TR_REF(x) ntatag_s_canceled_tr_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_trless_request; #define NTATAG_S_TRLESS_REQUEST(x) ntatag_s_trless_request, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_trless_request_ref; #define NTATAG_S_TRLESS_REQUEST_REF(x) ntatag_s_trless_request_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_trless_to_tr; #define NTATAG_S_TRLESS_TO_TR(x) ntatag_s_trless_to_tr, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_trless_to_tr_ref; #define NTATAG_S_TRLESS_TO_TR_REF(x) ntatag_s_trless_to_tr_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_trless_response; #define NTATAG_S_TRLESS_RESPONSE(x) ntatag_s_trless_response, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_trless_response_ref; #define NTATAG_S_TRLESS_RESPONSE_REF(x) ntatag_s_trless_response_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_trless_200; #define NTATAG_S_TRLESS_200(x) ntatag_s_trless_200, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_trless_200_ref; #define NTATAG_S_TRLESS_200_REF(x) ntatag_s_trless_200_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_merged_request; #define NTATAG_S_MERGED_REQUEST(x) ntatag_s_merged_request, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_merged_request_ref; #define NTATAG_S_MERGED_REQUEST_REF(x) ntatag_s_merged_request_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_sent_msg; #define NTATAG_S_SENT_MSG(x) ntatag_s_sent_msg, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_sent_msg_ref; #define NTATAG_S_SENT_MSG_REF(x) ntatag_s_sent_msg_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_sent_request; #define NTATAG_S_SENT_REQUEST(x) ntatag_s_sent_request, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_sent_request_ref; #define NTATAG_S_SENT_REQUEST_REF(x) ntatag_s_sent_request_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_sent_response; #define NTATAG_S_SENT_RESPONSE(x) ntatag_s_sent_response, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_sent_response_ref; #define NTATAG_S_SENT_RESPONSE_REF(x) ntatag_s_sent_response_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_retry_request; #define NTATAG_S_RETRY_REQUEST(x) ntatag_s_retry_request, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_retry_request_ref; #define NTATAG_S_RETRY_REQUEST_REF(x) ntatag_s_retry_request_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_retry_response; #define NTATAG_S_RETRY_RESPONSE(x) ntatag_s_retry_response, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_retry_response_ref; #define NTATAG_S_RETRY_RESPONSE_REF(x) ntatag_s_retry_response_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_recv_retry; #define NTATAG_S_RECV_RETRY(x) ntatag_s_recv_retry, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_recv_retry_ref; #define NTATAG_S_RECV_RETRY_REF(x) ntatag_s_recv_retry_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_tout_request; #define NTATAG_S_TOUT_REQUEST(x) ntatag_s_tout_request, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_tout_request_ref; #define NTATAG_S_TOUT_REQUEST_REF(x) ntatag_s_tout_request_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_tout_response; #define NTATAG_S_TOUT_RESPONSE(x) ntatag_s_tout_response, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_tout_response_ref; #define NTATAG_S_TOUT_RESPONSE_REF(x) ntatag_s_tout_response_ref, tag_usize_vr(&(x)) SOFIA_END_DECLS #endif /* !defined(nta_tag_h) */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/sofia-sip/nta_tport.h000066400000000000000000000044411223300710500244140ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef NTA_TPORT_H /** Defined when has been included. */ #define NTA_TPORT_H /** * @file sofia-sip/nta_tport.h * @brief Transport and SigComp handling * * @author Pekka Pessi * * @date Created: Thu Oct 7 20:04:39 2004 ppessi * */ #ifndef NTA_H #include #endif SOFIA_BEGIN_DECLS struct tport_s; #ifndef TPORT_T #define TPORT_T struct tport_s typedef TPORT_T tport_t; #endif #ifndef NTA_UPDATE_MAGIC_T #define NTA_UPDATE_MAGIC_T void #endif typedef NTA_UPDATE_MAGIC_T nta_update_magic_t; struct sigcomp_compartment; struct sigcomp_udvm; #define nta_transport nta_incoming_transport SOFIAPUBFUN tport_t *nta_agent_tports(nta_agent_t *agent); SOFIAPUBFUN tport_t *nta_incoming_transport(nta_agent_t *, nta_incoming_t *, msg_t *msg); SOFIAPUBFUN int nta_agent_tport_is_updating(nta_agent_t *agent); SOFIAPUBFUN struct sigcomp_compartment *nta_incoming_compartment(nta_incoming_t *irq); SOFIAPUBFUN tport_t *nta_outgoing_transport(nta_outgoing_t *orq); SOFIAPUBFUN struct sigcomp_compartment * nta_outgoing_compartment(nta_outgoing_t *orq); SOFIAPUBFUN void nta_compartment_decref(struct sigcomp_compartment **); typedef void nta_update_tport_f(nta_update_magic_t *, nta_agent_t *); SOFIAPUBFUN int nta_agent_bind_tport_update(nta_agent_t *agent, nta_update_magic_t *magic, nta_update_tport_f *); SOFIA_END_DECLS #endif /* !defined NTA_TPORT_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/sofia-sip/sl_utils.h000066400000000000000000000053651223300710500242460ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef SL_UTILS_H /** Defined when has been included. */ #define SL_UTILS_H /**@ingroup sl_utils * * @file sofia-sip/sl_utils.h @brief Prototypes for SIP helper functions. * * @author Pekka Pessi * * @date Created: Thu Oct 5 15:38:39 2000 ppessi */ #include #ifndef STRING0_H #include #endif #ifndef SIP_H #include #endif SOFIA_BEGIN_DECLS #ifndef SU_LOG_T #define SU_LOG_T typedef struct su_log_s su_log_t; #endif /* Read from file */ SOFIAPUBFUN sip_payload_t *sl_read_payload(su_home_t *home, char const *fname); SOFIAPUBFUN sip_payload_t *sl_fread_payload(su_home_t *home, FILE *); /* Printing functions */ SOFIAPUBFUN void sl_message_log(FILE *, char const *prefix, sip_t const *, int details); SOFIAPUBFUN issize_t sl_header_print(FILE *, char const *fmt, sip_header_t const *h), sl_from_print(FILE *, char const *fmt, sip_from_t const *from), sl_to_print(FILE *, char const *fmt, sip_to_t const *to), sl_contact_print(FILE *, char const *fmt, sip_contact_t const *m), sl_allow_print(FILE *, char const *fmt, sip_allow_t const *g), sl_payload_print(FILE *, char const *prefix, sip_payload_t const *pl), sl_via_print(FILE *, char const *fmt, sip_via_t const *v); /* Logging functions */ SOFIAPUBFUN void sl_sip_log(su_log_t*, int lvl, char const *, sip_t const *, int details), sl_header_log(su_log_t *, int lvl, char const *, sip_header_t const *h), sl_from_log(su_log_t *, int lvl, char const *, sip_from_t const *from), sl_to_log(su_log_t *, int lvl, char const *, sip_to_t const *to), sl_contact_log(su_log_t *, int lvl, char const *, sip_contact_t const *m), sl_allow_log(su_log_t *, int, char const *, sip_allow_t const *g), sl_via_log(su_log_t *, int, char const *, sip_via_t const *v), sl_payload_log(su_log_t *, int, char const *, sip_payload_t const *pl); SOFIA_END_DECLS #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/test_nta.c000066400000000000000000003105721223300710500223310ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@internal * @CFILE test_nta.c * * Test functions for NTA. * * @author Pekka Pessi * * @date Created: Tue Aug 21 15:18:26 2001 ppessi */ #include "config.h" typedef struct agent_t agent_t; typedef struct client_t client_t; #define SU_ROOT_MAGIC_T agent_t #include #include #define NTA_AGENT_MAGIC_T agent_t #define NTA_LEG_MAGIC_T agent_t #define NTA_OUTGOING_MAGIC_T client_t #define NTA_INCOMING_MAGIC_T agent_t #define NTA_RELIABLE_MAGIC_T agent_t #include "sofia-sip/nta.h" #include "sofia-sip/nta_tport.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "s2util.h" #if HAVE_OPEN_C #include #endif SOFIAPUBVAR su_log_t nta_log[]; SOFIAPUBVAR su_log_t tport_log[]; int tstflags = 0; #define TSTFLAGS tstflags #include #if HAVE_FUNC #elif HAVE_FUNCTION #define __func__ __FUNCTION__ #else #define __func__ name #endif #define NONE ((void *)-1) int expensive_checks, test_nta_sips; #define EXPENSIVE_CHECKS (expensive_checks) struct sigcomp_compartment; char const name[] = "test_nta"; typedef struct invite_client_t invite_client_t; typedef int client_check_f(client_t *, nta_outgoing_t *, sip_t const *); typedef int client_deinit_f(client_t *); struct client_t { agent_t *c_ag; char const *c_name; client_check_f * c_check; client_check_f * const * c_checks; client_deinit_f * c_deinit; void *c_extra; nta_outgoing_t *c_orq; int c_status; int c_final; int c_errors; }; struct invite_client_t { client_t ic_client[1]; nta_outgoing_t *ic_orq; /* Original INVITE transaction */ int ic_tag_status; /* Status for current branch */ char *ic_tag; }; struct agent_t { su_home_t ag_home[1]; int ag_flags; su_root_t *ag_root; msg_mclass_t *ag_mclass; nta_agent_t *ag_agent; url_string_t *ag_obp; /**< Outbound proxy. */ nta_leg_t *ag_server_leg; /**< Leg for sip:%@% */ nta_leg_t *ag_default_leg; /**< Leg for rest */ unsigned ag_drop; nta_outgoing_t *ag_orq; unsigned ag_running :1, ag_canceled:1, ag_acked:1, :0; char const *ag_comp; struct sigcomp_compartment *ag_client_compartment; /* Server side */ int ag_response; /**< What we answer by default */ nta_incoming_t *ag_irq; struct sigcomp_compartment *ag_server_compartment; char const *ag_m; sip_contact_t const *ag_contact; sip_from_t *ag_alice; sip_to_t *ag_bob; sip_contact_t *ag_m_alice; sip_contact_t *ag_m_bob; sip_contact_t *ag_aliases; nta_leg_t *ag_alice_leg; nta_leg_t *ag_bob_leg; msg_t *ag_request; nta_leg_t *ag_expect_leg; nta_leg_t *ag_latest_leg; nta_leg_t *ag_call_leg; nta_reliable_t *ag_reliable; sip_via_t *ag_in_via; /**< Incoming via */ sip_content_type_t *ag_content_type; sip_payload_t *ag_payload; msg_t *ag_probe_msg; su_sockaddr_t ag_su_nta[1]; socklen_t ag_su_nta_len; /* Dummy servers */ char const *ag_sink_port; su_socket_t ag_sink_socket, ag_down_socket; su_wait_t ag_sink_wait[1]; }; static int test_init(agent_t *ag, char const *resolv_conf); static int test_deinit(agent_t *ag); static int test_bad_messages(agent_t *ag); static int test_routing(agent_t *ag); static int test_tports(agent_t *ag); static int test_resolv(agent_t *ag, char const *resolv_conf); static int test_dialog(agent_t *ag); static int test_call(agent_t *ag); static int test_prack(agent_t *ag); static int test_fix_467(agent_t *ag); static int test_for_ack(agent_t *ag, nta_incoming_t *irq, sip_t const *sip); static int test_for_ack_or_timeout(agent_t *ag, nta_incoming_t *irq, sip_t const *sip); static int wait_for_ack_or_cancel(agent_t *ag, nta_incoming_t *irq, sip_t const *sip); int agent_callback(agent_t *ag, nta_agent_t *nta, msg_t *msg, sip_t *sip) { if (tstflags & tst_verbatim) { if (sip->sip_request) { printf("%s: %s: %s " URL_PRINT_FORMAT " %s\n", name, __func__, sip->sip_request->rq_method_name, URL_PRINT_ARGS(sip->sip_request->rq_url), sip->sip_request->rq_version); } else { printf("%s: %s: %s %03d %s\n", name, __func__, sip->sip_status->st_version, sip->sip_status->st_status, sip->sip_status->st_phrase); } } msg_destroy(msg); return 0; } static void leg_match(agent_t *ag, nta_leg_t *leg, int always, char const *func) { char const *match = "unknown leg"; if (!always && (tstflags & tst_verbatim) != tst_verbatim) return; if (leg == ag->ag_default_leg) match = "ag_default_leg"; else if (leg == ag->ag_server_leg) match = "ag_server_leg"; else if (leg == ag->ag_alice_leg) match = "ag_alice_leg"; else if (leg == ag->ag_bob_leg) match = "ag_bob_leg"; printf("%s: %s: %smatched with %s\n", name, func, always ? "mis" : "", match); } static void leg_zap(agent_t *ag, nta_leg_t *leg) { if (leg == ag->ag_default_leg) ag->ag_default_leg = NULL; else if (leg == ag->ag_server_leg) ag->ag_server_leg = NULL; else if (leg == ag->ag_alice_leg) ag->ag_alice_leg = NULL; else if (leg == ag->ag_bob_leg) ag->ag_bob_leg = NULL; else printf("%s:%u: %s: did not exist\n", __FILE__, __LINE__, __func__); nta_leg_destroy(leg); } int leg_callback_200(agent_t *ag, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip) { if (tstflags & tst_verbatim) { printf("%s: %s: %s " URL_PRINT_FORMAT " %s\n", name, __func__, sip->sip_request->rq_method_name, URL_PRINT_ARGS(sip->sip_request->rq_url), sip->sip_request->rq_version); } if (!sip->sip_content_length || !sip->sip_via || !sip->sip_from || !sip->sip_from->a_tag) return 500; if (ag->ag_in_via == NULL) ag->ag_in_via = sip_via_dup(ag->ag_home, sip->sip_via); if (ag->ag_request == NULL) ag->ag_request = nta_incoming_getrequest(irq); ag->ag_latest_leg = leg; if (ag->ag_expect_leg && leg != ag->ag_expect_leg) { leg_match(ag, leg, 1, __func__); return 500; } leg_match(ag, leg, 0, __func__); if (sip->sip_request->rq_method == sip_method_bye) { leg_zap(ag, leg); } return 200; } int leg_callback_500(agent_t *ag, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip) { if (tstflags & tst_verbatim) { printf("%s: %s: %s " URL_PRINT_FORMAT " %s\n", name, __func__, sip->sip_request->rq_method_name, URL_PRINT_ARGS(sip->sip_request->rq_url), sip->sip_request->rq_version); } return 500; } int new_leg_callback_200(agent_t *ag, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip) { if (tstflags & tst_verbatim) { printf("%s: %s: %s " URL_PRINT_FORMAT " %s\n", name, __func__, sip->sip_request->rq_method_name, URL_PRINT_ARGS(sip->sip_request->rq_url), sip->sip_request->rq_version); } if (!sip->sip_content_length || !sip->sip_via || !sip->sip_from || !sip->sip_from->a_tag) return 500; ag->ag_latest_leg = leg; if (ag->ag_expect_leg && leg != ag->ag_expect_leg) { leg_match(ag, leg, 1, __func__); return 500; } leg_match(ag, leg, 0, __func__); ag->ag_bob_leg = nta_leg_tcreate(ag->ag_agent, leg_callback_200, ag, URLTAG_URL(sip->sip_request->rq_url), SIPTAG_CALL_ID(sip->sip_call_id), SIPTAG_FROM(sip->sip_to), SIPTAG_TO(sip->sip_from), TAG_END()); if (!ag->ag_bob_leg || !nta_leg_tag(ag->ag_bob_leg, NULL) || !nta_leg_get_tag(ag->ag_bob_leg) || !nta_incoming_tag(irq, nta_leg_get_tag(ag->ag_bob_leg))) return 500; return 200; } int new_leg_callback_180(agent_t *ag, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip) { int status = new_leg_callback_200(ag, leg, irq, sip); if (status == 200) { ag->ag_irq = irq; status = 180; } return status; } static client_check_f client_check_to_tag; static client_check_f * const default_checks[] = { client_check_to_tag, NULL }; static client_check_f * const no_default_checks[] = { NULL }; /** Callback from client transaction */ int outgoing_callback(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) { agent_t *ag = ctx->c_ag; int status = nta_outgoing_status(orq); client_check_f * const *checks; if (tstflags & tst_verbatim) { if (sip) printf("%s: %s: response %s %03d %s\n", name, ctx->c_name, sip->sip_status->st_version, sip->sip_status->st_status, sip->sip_status->st_phrase); else printf("%s: %s: callback %03d\n", name, ctx->c_name, status); } if (status >= 200 && ag->ag_comp) { /* XXX */ nta_compartment_decref(&ag->ag_client_compartment); ag->ag_client_compartment = nta_outgoing_compartment(ctx->c_orq); } if (status > ctx->c_status) ctx->c_status = status; if (status >= 200) ctx->c_final = 1; if (ctx->c_check && ctx->c_check(ctx, orq, sip)) ctx->c_errors++; checks = ctx->c_checks; for (checks = checks ? checks : default_checks; *checks; checks++) if ((*checks)(ctx, ctx->c_orq, sip)) ctx->c_errors++; return 0; } /** Deinit client. Return nonzero if client checks failed. */ static int client_deinit(client_t *c) { int errors = c->c_errors; if (c->c_deinit && c->c_deinit(c)) errors++; if (c->c_orq) nta_outgoing_destroy(c->c_orq), c->c_orq = NULL; c->c_errors = 0; c->c_status = 0; return errors; } static void nta_test_run(agent_t *ag) { for (ag->ag_running = 1; ag->ag_running;) { if (tstflags & tst_verbatim) { fputs(".", stdout); fflush(stdout); } su_root_step(ag->ag_root, 500L); } } /** Run client test. Return nonzero if client checks failed. */ static int client_run_with(client_t *c, int expected, void (*runner)(client_t *c)) { int resulting; TEST_1(c->c_orq != NULL); runner(c); resulting = c->c_status; if (client_deinit(c)) return 1; if (expected) TEST(resulting, expected); return 0; } static void until_final_received(client_t *c) { for (c->c_final = 0; !c->c_final; ) { if (tstflags & tst_verbatim) { fputs(".", stdout); fflush(stdout); } su_root_step(c->c_ag->ag_root, 500L); } } static void fast_final_received(client_t *c) { for (c->c_final = 0; !c->c_final; ) { if (tstflags & tst_verbatim) { fputs(".", stdout); fflush(stdout); } s2_fast_forward(500, c->c_ag->ag_root); } } static int client_run(client_t *c, int expected) { return client_run_with(c, expected, until_final_received); } static void until_server_acked(client_t *c) { agent_t *ag = c->c_ag; for (ag->ag_acked = 0; !ag->ag_acked;) { if (tstflags & tst_verbatim) { fputs(".", stdout); fflush(stdout); } su_root_step(ag->ag_root, 500L); } } static int client_run_until_acked(client_t *c, int expected) { return client_run_with(c, expected, until_server_acked); } void until_server_canceled(client_t *c) { agent_t *ag = c->c_ag; for (ag->ag_canceled = 0; !ag->ag_canceled || c->c_status < 200;) { if (tstflags & tst_verbatim) { fputs(".", stdout); fflush(stdout); } su_root_step(ag->ag_root, 500L); } } static int client_run_until_canceled(client_t *c, int expected) { return client_run_with(c, expected, until_server_canceled); } #include int test_init(agent_t *ag, char const *resolv_conf) { char const *contact = "sip:*:*;comp=sigcomp"; su_sockaddr_t su; socklen_t sulen, sulen0; su_socket_t s; int af, err = -1; BEGIN(); ag->ag_root = su_root_create(ag); TEST_1(ag->ag_root); ag->ag_mclass = msg_mclass_clone(sip_default_mclass(), 0, 0); TEST_1(ag->ag_mclass); #if SU_HAVE_IN6 if (su_strmatch(getenv("ipv6"), "true")) { contact = "sip:[::]:*;comp=sigcomp"; af = AF_INET6, sulen0 = sizeof (struct sockaddr_in6); } else { af = AF_INET, sulen0 = sizeof (struct sockaddr_in); contact = "sip:0.0.0.0:*;comp=sigcomp"; } #else af = AF_INET, sulen0 = sizeof (struct sockaddr_in); contact = "sip:0.0.0.0:*;comp=sigcomp"; #endif if (ag->ag_m) contact = ag->ag_m; else if (getenv("SIPCONTACT")) contact = getenv("SIPCONTACT"); /* Sink server */ s = su_socket(af, SOCK_DGRAM, 0); TEST_1(s != INVALID_SOCKET); memset(&su, 0, sulen = sulen0); su.su_family = af; if (getenv("sink")) { su.su_port = htons(atoi(getenv("sink"))); } TEST_1(bind(s, &su.su_sa, sulen) < 0 ? (perror("bind"), 0) : 1); TEST_1(getsockname(s, &su.su_sa, &sulen) == 0); ag->ag_sink_socket = s; su_wait_init(ag->ag_sink_wait); su_wait_create(ag->ag_sink_wait, ag->ag_sink_socket, SU_WAIT_IN); ag->ag_sink_port = su_sprintf(ag->ag_home, "%u", ntohs(su.su_sin.sin_port)); /* Down server */ s = su_socket(af, SOCK_STREAM, 0); TEST_1(s != INVALID_SOCKET); memset(&su, 0, sulen = sulen0); su.su_family = af; if (getenv("down")) { su.su_port = htons(atoi(getenv("down"))); } TEST_1(bind(s, &su.su_sa, sulen) < 0 ? (perror("bind"), 0) : 1); ag->ag_down_socket = s; /* Create agent */ ag->ag_agent = nta_agent_create(ag->ag_root, (url_string_t *)contact, NULL, NULL, NTATAG_MCLASS(ag->ag_mclass), NTATAG_USE_TIMESTAMP(1), SRESTAG_RESOLV_CONF(resolv_conf), NTATAG_USE_NAPTR(0), NTATAG_USE_SRV(0), NTATAG_PRELOAD(2048), TAG_END()); TEST_1(ag->ag_agent); contact = getenv("SIPSCONTACT"); if (contact) { if (nta_agent_add_tport(ag->ag_agent, URL_STRING_MAKE(contact), TPTAG_CERTIFICATE(getenv("TEST_NTA_CERTDIR")), TPTAG_TLS_VERIFY_POLICY(TPTLS_VERIFY_NONE), TAG_END()) == 0) test_nta_sips = 1; } { /* Initialize our headers */ sip_from_t from[1]; sip_to_t to[1]; sip_contact_t m[1]; su_sockaddr_t *su = ag->ag_su_nta; sip_from_init(from); sip_to_init(to); sip_contact_init(m); TEST_1(ag->ag_contact = nta_agent_contact(ag->ag_agent)); *m->m_url = *ag->ag_contact->m_url; if (host_is_ip4_address(m->m_url->url_host)) { su_inet_pton(su->su_family = AF_INET, m->m_url->url_host, &su->su_sin.sin_addr); ag->ag_su_nta_len = (sizeof su->su_sin); } else { TEST_1(host_is_ip_address(m->m_url->url_host)); su_inet_pton(su->su_family = AF_INET6, m->m_url->url_host, &su->su_sin6.sin6_addr); ag->ag_su_nta_len = (sizeof su->su_sin6); } su->su_port = htons(5060); if (m->m_url->url_port && strlen(m->m_url->url_port)) { unsigned long port = strtoul(m->m_url->url_port, NULL, 10); su->su_port = htons(port); } TEST_1(su->su_port != 0); m->m_url->url_user = "bob"; TEST_1(ag->ag_m_bob = sip_contact_dup(ag->ag_home, m)); to->a_display = "Bob"; *to->a_url = *ag->ag_contact->m_url; to->a_url->url_user = "bob"; to->a_url->url_port = NULL; TEST_1(ag->ag_bob = sip_to_dup(ag->ag_home, to)); *m->m_url = *ag->ag_contact->m_url; m->m_url->url_user = "alice"; TEST_1(ag->ag_m_alice = sip_contact_dup(ag->ag_home, m)); from->a_display = "Alice"; *from->a_url = *ag->ag_contact->m_url; from->a_url->url_user = "alice"; from->a_url->url_port = NULL; TEST_1(ag->ag_alice = sip_from_dup(ag->ag_home, from)); } { char const data[] = "v=0\r\n" "o=- 425432 423412 IN IP4 127.0.0.1\r\n" "s= \r\n" "c=IN IP4 127.0.0.1\r\n" "m=5004 audio 8 0\r\n"; ag->ag_content_type = sip_content_type_make(ag->ag_home, "application/sdp"); ag->ag_payload = sip_payload_make(ag->ag_home, data); } { sip_contact_t *m; ag->ag_aliases = sip_contact_make(ag->ag_home, "sip:127.0.0.1, sip:localhost, sip:[::1]"); TEST_1(ag->ag_aliases); TEST_1(ag->ag_aliases->m_next); TEST_1(ag->ag_aliases->m_next->m_next); TEST_P(ag->ag_aliases->m_next->m_next->m_next, NULL); for (m = ag->ag_aliases; m; m = m->m_next) m->m_url->url_port = ag->ag_contact->m_url->url_port; TEST_1(m = sip_contact_dup(ag->ag_home, ag->ag_contact)); m->m_next = ag->ag_aliases; ag->ag_aliases = m; err = nta_agent_set_params(ag->ag_agent, NTATAG_ALIASES(ag->ag_aliases), NTATAG_REL100(1), NTATAG_UA(1), NTATAG_MERGE_482(1), NTATAG_USE_NAPTR(1), NTATAG_USE_SRV(1), NTATAG_MAX_FORWARDS(20), TAG_END()); TEST(err, 7); err = nta_agent_set_params(ag->ag_agent, NTATAG_ALIASES(ag->ag_aliases), NTATAG_DEFAULT_PROXY("sip:127.0.0.1"), TAG_END()); TEST(err, 2); err = nta_agent_set_params(ag->ag_agent, NTATAG_ALIASES(ag->ag_aliases), NTATAG_DEFAULT_PROXY(NULL), TAG_END()); TEST(err, 2); err = nta_agent_set_params(ag->ag_agent, NTATAG_DEFAULT_PROXY("tel:+35878008000"), TAG_END()); TEST(err, -1); } { url_t url[1]; /* Create the server leg */ *url = *ag->ag_aliases->m_url; url->url_user = "%"; ag->ag_server_leg = nta_leg_tcreate(ag->ag_agent, leg_callback_200, ag, NTATAG_NO_DIALOG(1), URLTAG_URL(url), TAG_END()); TEST_1(ag->ag_server_leg); } END(); } int test_reinit(agent_t *ag) { BEGIN(); /* Create a new default leg */ nta_leg_destroy(ag->ag_default_leg), ag->ag_default_leg = NULL; TEST_1(ag->ag_default_leg = nta_leg_tcreate(ag->ag_agent, leg_callback_200, ag, NTATAG_NO_DIALOG(1), TAG_END())); END(); } int test_deinit(agent_t *ag) { BEGIN(); if (ag->ag_request) msg_destroy(ag->ag_request), ag->ag_request = NULL; su_free(ag->ag_home, ag->ag_in_via), ag->ag_in_via = NULL; nta_leg_destroy(ag->ag_alice_leg); nta_leg_destroy(ag->ag_bob_leg); nta_leg_destroy(ag->ag_default_leg); nta_leg_destroy(ag->ag_server_leg); nta_agent_destroy(ag->ag_agent); su_root_destroy(ag->ag_root); if (ag->ag_sink_port) { su_free(ag->ag_home, (void *)ag->ag_sink_port), ag->ag_sink_port = NULL; su_wait_destroy(ag->ag_sink_wait); su_close(ag->ag_sink_socket); } free(ag->ag_mclass), ag->ag_mclass = NULL; END(); } static int readfile(FILE *f, void **contents) { /* Read in whole (binary!) file */ char *buffer = NULL; long size; size_t len; /* Read whole file in */ if (fseek(f, 0, SEEK_END) < 0 || (size = ftell(f)) < 0 || fseek(f, 0, SEEK_SET) < 0 || (long)(len = (size_t)size) != size) { fprintf(stderr, "%s: unable to determine file size (%s)\n", __func__, strerror(errno)); return -1; } if (!(buffer = malloc(len + 2)) || fread(buffer, 1, len, f) != len) { fprintf(stderr, "%s: unable to read file (%s)\n", __func__, strerror(errno)); if (buffer) free(buffer); return -1; } buffer[len] = '\0'; *contents = buffer; return (int)len; } #if HAVE_DIRENT_H #include #endif static int test_bad_messages(agent_t *ag) { BEGIN(); #if HAVE_DIRENT_H DIR *dir; struct dirent *d; char name[PATH_MAX + 1] = "../sip/tests/"; size_t offset; char const *host, *port; su_addrinfo_t *ai, hints[1]; su_socket_t s; su_sockaddr_t su[1]; socklen_t sulen; char via[64]; size_t vlen; int i; dir = opendir(name); if (dir == NULL && getenv("srcdir")) { strncpy(name, getenv("srcdir"), PATH_MAX); strncat(name, "/../sip/tests/", PATH_MAX); dir = opendir(name); } if (dir == NULL) { fprintf(stderr, "test_nta: cannot find sip torture messages\n"); fprintf(stderr, "test_nta: tried %s\n", name); } offset = strlen(name); TEST_1(ag->ag_default_leg = nta_leg_tcreate(ag->ag_agent, leg_callback_500, ag, NTATAG_NO_DIALOG(1), TAG_END())); host = ag->ag_contact->m_url->url_host; if (host_is_ip6_reference(host)) { host = strcpy(via, host + 1); via[strlen(via) - 1] = '\0'; } port = url_port(ag->ag_contact->m_url); memset(hints, 0, sizeof hints); hints->ai_socktype = SOCK_DGRAM; hints->ai_protocol = IPPROTO_UDP; TEST(su_getaddrinfo(host, port, hints, &ai), 0); TEST_1(ai); s = su_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); TEST_1(s != -1); memset(su, 0, sulen = ai->ai_addrlen); su->su_len = sizeof su; su->su_family = ai->ai_family; TEST_1(bind(s, &su->su_sa, sulen) == 0); TEST_1(getsockname(s, &su->su_sa, &sulen) == 0); sprintf(via, "v: SIP/2.0/UDP is.invalid:%u\r\n", ntohs(su->su_port)); vlen = strlen(via); for (d = dir ? readdir(dir) : NULL; d; d = readdir(dir)) { size_t len = strlen(d->d_name); FILE *f; int blen, n; void *buffer; char *r; if (len < strlen(".txt")) continue; if (strcmp(d->d_name + len - strlen(".txt"), ".txt")) continue; strncpy(name + offset, d->d_name, PATH_MAX - offset); TEST_1(f = fopen(name, "rb")); TEST_1((blen = readfile(f, &buffer)) > 0); fclose(f); r = buffer; if (strncmp(r, "JUNK ", 5) == 0) { TEST_SIZE(su_sendto(s, r, blen, 0, ai->ai_addr, ai->ai_addrlen), blen); } else if (strncmp(r, "INVITE ", 7) != 0) { su_iovec_t vec[3]; n = strcspn(r, "\r\n"); n += strspn(r + n, "\r\n"); vec[0].siv_base = r, vec[0].siv_len = n; vec[1].siv_base = via, vec[1].siv_len = vlen; vec[2].siv_base = r + n, vec[2].siv_len = blen - n; TEST_SIZE(su_vsend(s, vec, 3, 0, (void *)ai->ai_addr, ai->ai_addrlen), blen + vlen); } free(buffer); su_root_step(ag->ag_root, 1); } TEST_SIZE(su_sendto(s, "\r\n\r\n", 4, 0, (void *)ai->ai_addr, ai->ai_addrlen), 4); su_root_step(ag->ag_root, 1); TEST_SIZE(su_sendto(s, "", 0, 0, ai->ai_addr, ai->ai_addrlen), 0); su_close(s); for (i = 0; i < 20; i++) su_root_step(ag->ag_root, 1); nta_leg_destroy(ag->ag_default_leg), ag->ag_default_leg = NULL; if (dir) closedir(dir); #endif /* HAVE_DIRENT_H */ END(); } static unsigned char const code[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; #include sip_payload_t *test_payload(su_home_t *home, size_t size) { sip_payload_t *pl = sip_payload_create(home, NULL, (isize_t)size); if (pl) { size_t i; char *data = (char *)pl->pl_data; for (i = 0; i < size; i++) { if ((i & 63) != 63) data[i] = code[su_randint(0, 63)]; else data[i] = '\n'; } } return pl; } static int client_check_to_tag(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) { if (sip) TEST_1(sip->sip_to && sip->sip_to->a_tag); return 0; } static int check_magic_branch(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) { if (sip) { TEST_1(sip->sip_via); TEST_S(sip->sip_via->v_branch, "MagicalBranch"); } return 0; } static int check_via_with_sigcomp(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) { if (sip && sip->sip_via) { TEST_S(sip->sip_via->v_comp, "sigcomp"); } return 0; } static int check_via_without_sigcomp(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) { if (sip && sip->sip_via) { TEST_1(sip->sip_via->v_comp == NULL); } return 0; } static int check_via_with_tcp(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) { if (sip && sip->sip_via) { TEST_S(sip->sip_via->v_protocol, "SIP/2.0/TCP"); } return 0; } static int check_via_with_sctp(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) { if (sip && sip->sip_via) { TEST_S(sip->sip_via->v_protocol, "SIP/2.0/SCTP"); } return 0; } static int check_via_with_udp(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) { if (sip && sip->sip_via) { TEST_S(sip->sip_via->v_protocol, "SIP/2.0/UDP"); } return 0; } static int save_and_check_tcp(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) { if (ctx->c_status >= 200 && ctx->c_extra) { tport_t *tport = nta_outgoing_transport(orq); TEST_1(tport); *(tport_t **)ctx->c_extra = tport; } return check_via_with_tcp(ctx, orq, sip); } /* Test transports */ int test_tports(agent_t *ag) { int udp = 0, tcp = 0, sctp = 0, tls = 0; sip_via_t const *v, *v_udp_only = NULL; char const *udp_comp = NULL; char const *tcp_comp = NULL; tport_t *tcp_tport = NULL; url_t url[1]; BEGIN(); nta_leg_bind(ag->ag_server_leg, leg_callback_200, ag); *url = *ag->ag_contact->m_url; url->url_port = "*"; url->url_params = "transport=tcp"; url->url_params = "transport=udp"; TEST_1(nta_agent_add_tport(ag->ag_agent, (url_string_t *)url, TAG_END()) == 0); TEST_1(v = nta_agent_via(ag->ag_agent)); for (; v; v = v->v_next) { if (su_casematch(v->v_protocol, sip_transport_udp)) { if (udp) v_udp_only = v; udp = 1; if (udp_comp == NULL) udp_comp = v->v_comp; } else if (su_casematch(v->v_protocol, sip_transport_tcp)) { tcp = 1; if (tcp_comp == NULL) tcp_comp = v->v_comp; } else if (su_casematch(v->v_protocol, sip_transport_sctp)) { sctp = 1; } else if (su_casematch(v->v_protocol, sip_transport_tls)) { tls = 1; } } *url = *ag->ag_aliases->m_url; url->url_user = "bob"; if (udp_comp || tcp_comp) ag->ag_comp = "sigcomp"; { /* Test 0.1 * Send a message from default leg to default leg */ char const p_acid[] = "P-Access-Network-Info: IEEE-802.11g\n"; url_t url[1]; client_t ctx[1] = {{ ag, "Test 0.1", check_via_without_sigcomp }}; *url = *ag->ag_contact->m_url; url->url_params = NULL; ag->ag_expect_leg = ag->ag_default_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), SIPTAG_CONTACT(ag->ag_m_alice), SIPTAG_HEADER_STR(p_acid), TAG_END()); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); TEST_1(ag->ag_request); msg_destroy(ag->ag_request), ag->ag_request = NULL; nta_leg_bind(ag->ag_default_leg, leg_callback_200, ag); } { /* Test 0.1.2: test url_headers * * Send a message from default leg to default leg. */ url_t url[1]; sip_t *sip; client_t ctx[1] = {{ ag, "Test 0.1.2", check_via_without_sigcomp }}; *url = *ag->ag_contact->m_url; /* Test that method parameter is stripped and headers in query are used */ url->url_params = "method=MESSAGE;user=IP"; url->url_headers = "organization=United%20Testers"; ag->ag_expect_leg = ag->ag_default_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), SIPTAG_CONTACT(ag->ag_m_alice), TAG_END()); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); TEST_1(ag->ag_request); TEST_1(sip = sip_object(ag->ag_request)); TEST_1(sip->sip_organization); TEST_S(sip->sip_organization->g_string, "United Testers"); TEST_S(sip->sip_request->rq_url->url_params, "user=IP"); nta_leg_bind(ag->ag_default_leg, leg_callback_200, ag); } /* Test 0.1.3 * Send a message from Bob to Alice using SIGCOMP and TCP */ if (tcp_comp) { url_t url[1]; sip_payload_t *pl; size_t size = 1024; client_t ctx[1] = {{ ag, "Test 0.1.3", check_via_with_sigcomp }}; *url = *ag->ag_aliases->m_url; url->url_user = "alice"; if (url->url_params) url->url_params = su_sprintf(NULL, "%s;transport=tcp", url->url_params); else url->url_params = "transport=tcp"; TEST_1(pl = test_payload(ag->ag_home, size)); ag->ag_expect_leg = ag->ag_server_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)url, NTATAG_COMP("sigcomp"), SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_bob), SIPTAG_TO(ag->ag_alice), SIPTAG_CONTACT(ag->ag_m_bob), SIPTAG_PAYLOAD(pl), TAG_END()); su_free(ag->ag_home, pl); TEST_1(!client_run(ctx, 200)); TEST_1(ag->ag_client_compartment); nta_compartment_decref(&ag->ag_client_compartment); TEST_P(ag->ag_latest_leg, ag->ag_server_leg); } /* Test 0.2 * Send a message from Bob to Alice * This time specify a TCP URI, and include a large payload * of 512 kB */ if (tcp) { client_t ctx[1] = {{ ag, "Test 0.2", save_and_check_tcp, }}; url_t url[1]; sip_payload_t *pl; usize_t size = 512 * 1024; ctx->c_extra = &tcp_tport; *url = *ag->ag_aliases->m_url; url->url_user = "alice"; url->url_params = "transport=tcp"; TEST_1(pl = test_payload(ag->ag_home, size)); ag->ag_expect_leg = ag->ag_server_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, NULL, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_bob), SIPTAG_TO(ag->ag_alice), SIPTAG_CONTACT(ag->ag_m_bob), SIPTAG_PAYLOAD(pl), NTATAG_DEFAULT_PROXY(ag->ag_obp), TAG_END()); su_free(ag->ag_home, pl); TEST_1(!client_run(ctx, 200)); TEST_1(tcp_tport); TEST_P(ag->ag_latest_leg, ag->ag_server_leg); } if (tcp_tport) { /* Test 0.2.1 - always use transport connection from NTATAG_TPORT() * * Test bug reported by geaaru * - NTATAG_TPORT() is not used if NTATAG_DEFAULT_PROXY() is given */ client_t ctx[1] = {{ ag, "Test 0.2.1", save_and_check_tcp }}; url_t url[1]; sip_payload_t *pl; tport_t *used_tport = NULL; ctx->c_extra = &used_tport; *url = *ag->ag_aliases->m_url; url->url_user = "alice"; TEST(tport_shutdown(tcp_tport, 1), 0); /* Not going to send anymore */ TEST_1(pl = test_payload(ag->ag_home, 512)); ag->ag_expect_leg = ag->ag_server_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, NULL, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_bob), SIPTAG_TO(ag->ag_alice), SIPTAG_CONTACT(ag->ag_m_bob), SIPTAG_PAYLOAD(pl), NTATAG_DEFAULT_PROXY(ag->ag_obp), NTATAG_TPORT(tcp_tport), TAG_END()); su_free(ag->ag_home, pl); TEST_1(!client_run(ctx, 503)); TEST_P(ag->ag_latest_leg, ag->ag_server_leg); TEST_1(used_tport == tcp_tport); tport_unref(tcp_tport), tcp_tport = NULL; if (v_udp_only) /* Prepare for next test */ TEST_1(tcp_tport = tport_ref(tport_parent(used_tport))); tport_unref(used_tport); } if (tcp_tport) { /* test 0.2.2 - select transport protocol using NTATAG_TPORT() * * Use primary NTATAG_TPORT() to select transport */ client_t ctx[1] = {{ ag, "Test 0.2.2", save_and_check_tcp }}; url_t url[1]; sip_payload_t *pl; tport_t *used_tport = NULL; ctx->c_extra = &used_tport; TEST_1(tport_is_primary(tcp_tport)); TEST_1(pl = test_payload(ag->ag_home, 512)); *url = *ag->ag_aliases->m_url; url->url_user = "alice"; url->url_host = v_udp_only->v_host; url->url_port = v_udp_only->v_port; url->url_params = NULL; /* No sigcomp */ ag->ag_expect_leg = ag->ag_server_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, (url_string_t *)url, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_bob), SIPTAG_TO(ag->ag_alice), SIPTAG_CONTACT(ag->ag_m_bob), SIPTAG_PAYLOAD(pl), NTATAG_TPORT(tcp_tport), TAG_END()); su_free(ag->ag_home, pl); TEST_1(!client_run(ctx, 503)); TEST_P(ag->ag_latest_leg, ag->ag_server_leg); TEST_1(used_tport); TEST_1(tport_is_tcp(used_tport)); tport_unref(used_tport); tport_unref(tcp_tport), tcp_tport = NULL; } /* Test 0.3 * Send a message from Bob to Alice * This time include a large payload of 512 kB, let NTA choose transport. */ if (tcp) { client_t ctx[1] = {{ ag, "Test 0.3" }}; url_t url[1]; sip_payload_t *pl; usize_t size = 512 * 1024; *url = *ag->ag_aliases->m_url; url->url_user = "alice"; TEST_1(pl = test_payload(ag->ag_home, size)); ag->ag_expect_leg = ag->ag_server_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_bob), SIPTAG_TO(ag->ag_alice), SIPTAG_CONTACT(ag->ag_m_bob), SIPTAG_PAYLOAD(pl), TAG_END()); su_free(ag->ag_home, pl); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_server_leg); } /* Test 0.4.1: * Send a message from Bob to Alice * This time include a payload of 2 kB, let NTA choose transport. */ { client_t ctx[1] = {{ ag, "Test 0.4.1", check_via_with_tcp }}; url_t url[1]; sip_payload_t *pl; usize_t size = 2 * 1024; *url = *ag->ag_aliases->m_url; url->url_user = "alice"; TEST_1(pl = test_payload(ag->ag_home, size)); ag->ag_expect_leg = ag->ag_server_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_bob), SIPTAG_TO(ag->ag_alice), SIPTAG_CONTACT(ag->ag_m_bob), SIPTAG_PAYLOAD(pl), TAG_END()); su_free(ag->ag_home, pl); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_server_leg); su_free(ag->ag_home, ag->ag_in_via), ag->ag_in_via = NULL; } /* Test 0.4.2: * Send a message from Bob to Alices UDP-only address * This time include a payload of 2 kB, let NTA choose transport. */ if (v_udp_only) { client_t ctx[1] = {{ ag, "Test 0.4.2", check_via_with_udp }}; url_t url[1]; sip_payload_t *pl; usize_t size = 2 * 1024; *url = *ag->ag_aliases->m_url; url->url_user = "alice"; url->url_host = v_udp_only->v_host; url->url_port = v_udp_only->v_port; url->url_params = NULL; /* No sigcomp */ TEST_1(pl = test_payload(ag->ag_home, size)); ag->ag_expect_leg = ag->ag_default_leg; su_free(ag->ag_home, ag->ag_in_via), ag->ag_in_via = NULL; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_bob), SIPTAG_TO(ag->ag_alice), SIPTAG_CONTACT(ag->ag_m_bob), SIPTAG_PAYLOAD(pl), TAG_END()); su_free(ag->ag_home, pl); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); TEST_1(ag->ag_in_via); TEST_1(su_casematch(ag->ag_in_via->v_protocol, "SIP/2.0/UDP")); su_free(ag->ag_home, ag->ag_in_via), ag->ag_in_via = NULL; } /* Test 0.5: * Send a message from Bob to Alice * This time include a payload of 2 kB, try to use UDP. */ if (udp) { client_t ctx[1] = {{ ag, "Test 0.5", check_via_with_udp }}; url_t url[1]; sip_payload_t *pl; usize_t size = 2 * 1024; *url = *ag->ag_aliases->m_url; url->url_user = "alice"; TEST_1(pl = test_payload(ag->ag_home, size)); ag->ag_expect_leg = ag->ag_server_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_bob), SIPTAG_TO(ag->ag_alice), SIPTAG_CONTACT(ag->ag_m_bob), SIPTAG_PAYLOAD(pl), TPTAG_MTU(0xffffffff), TAG_END()); su_free(ag->ag_home, pl); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_server_leg); } if (udp) { /* Test 0.6 * Send a message from default leg to server leg * using a prefilled Via header */ client_t ctx[1] = {{ ag, "Test 0.6", check_magic_branch }}; sip_via_t via[1]; sip_via_init(via); via->v_protocol = sip_transport_udp; via->v_host = ag->ag_contact->m_url->url_host; via->v_port = ag->ag_contact->m_url->url_port; sip_via_add_param(ag->ag_home, via, "branch=MagicalBranch"); nta_agent_set_params(ag->ag_agent, NTATAG_ALIASES(ag->ag_aliases), NTATAG_USER_VIA(1), TAG_END()); ag->ag_expect_leg = ag->ag_server_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), SIPTAG_CONTACT(ag->ag_m_alice), SIPTAG_VIA(via), TAG_END()); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_server_leg); nta_agent_set_params(ag->ag_agent, NTATAG_USER_VIA(0), TAG_END()); } /* Test 0.7 * Send a message from Bob to Alice using SCTP */ if (sctp) { url_t url[1]; sip_payload_t *pl; usize_t size = 16 * 1024; client_t ctx[1] = {{ ag, "Test 0.7", check_via_with_sctp }}; *url = *ag->ag_aliases->m_url; url->url_user = "alice"; #if 0 if (url->url_params) url->url_params = su_sprintf(NULL, "%s;transport=sctp", url->url_params); else #endif url->url_params = "transport=sctp"; TEST_1(pl = test_payload(ag->ag_home, size)); ag->ag_expect_leg = ag->ag_server_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_bob), SIPTAG_TO(ag->ag_alice), SIPTAG_CONTACT(ag->ag_m_bob), SIPTAG_PAYLOAD(pl), TAG_END()); su_free(ag->ag_home, pl); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_server_leg); } /* Test 0.8: Send a too large message */ if (tcp) { url_t url[1]; sip_payload_t *pl; usize_t size = 128 * 1024; client_t ctx[1] = {{ ag, "Test 0.8" }}; nta_agent_set_params(ag->ag_agent, NTATAG_MAXSIZE(65536), TAG_END()); *url = *ag->ag_aliases->m_url; url->url_user = "alice"; TEST_1(pl = test_payload(ag->ag_home, size)); ag->ag_expect_leg = ag->ag_server_leg; ag->ag_latest_leg = NULL; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_bob), SIPTAG_TO(ag->ag_alice), SIPTAG_CONTACT(ag->ag_m_bob), SIPTAG_PAYLOAD(pl), TAG_END()); su_free(ag->ag_home, pl); TEST_1(!client_run(ctx, 413)); TEST_P(ag->ag_latest_leg, NULL); nta_agent_set_params(ag->ag_agent, NTATAG_MAXSIZE(2 * 1024 * 1024), TAG_END()); } /* Test 0.9: Timeout */ { url_t url[1]; client_t ctx[1] = {{ ag, "Test 0.9" }}; nta_agent_set_params(ag->ag_agent, NTATAG_TIMEOUT_408(1), TAG_END()); *url = *ag->ag_aliases->m_url; url->url_user = "timeout"; url->url_port = ag->ag_sink_port; ag->ag_expect_leg = ag->ag_server_leg; ag->ag_latest_leg = NULL; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_bob), SIPTAG_TO(ag->ag_alice), SIPTAG_CONTACT(ag->ag_m_bob), TAG_END()); TEST_1(!client_run_with(ctx, 408, fast_final_received)); TEST_P(ag->ag_latest_leg, NULL); nta_agent_set_params(ag->ag_agent, TAG_END()); } END(); } int leg_callback_destroy(agent_t *ag, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip) { if (tstflags & tst_verbatim) { printf("%s: %s: %s " URL_PRINT_FORMAT " %s\n", name, __func__, sip->sip_request->rq_method_name, URL_PRINT_ARGS(sip->sip_request->rq_url), sip->sip_request->rq_version); } ag->ag_latest_leg = leg; nta_incoming_destroy(irq); return 0; } int leg_callback_save(agent_t *ag, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip) { if (tstflags & tst_verbatim) { printf("%s: %s: %s " URL_PRINT_FORMAT " %s\n", name, __func__, sip->sip_request->rq_method_name, URL_PRINT_ARGS(sip->sip_request->rq_url), sip->sip_request->rq_version); } ag->ag_latest_leg = leg; ag->ag_irq = irq; ag->ag_running = 0; return 0; } int test_destroy_incoming(agent_t *ag) { BEGIN(); url_t url[1]; *url = *ag->ag_contact->m_url; { client_t ctx[1] = {{ ag, "Test 3.1" }}; /* Test 3.1 * Check that when a incoming request is destroyed in callback, * a 500 response is sent */ ag->ag_expect_leg = ag->ag_default_leg; nta_leg_bind(ag->ag_default_leg, leg_callback_destroy, ag); ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), TAG_END()); TEST_1(!client_run(ctx, 500)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); } { /* Test 3.2 * Check that when an incoming request is destroyed, a 500 response is sent */ client_t ctx[1] = {{ ag, "Test 3.2" }}; nta_leg_bind(ag->ag_default_leg, leg_callback_save, ag); ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), TAG_END()); TEST_1(ctx->c_orq); nta_test_run(ag); TEST(ctx->c_status, 0); TEST_1(ag->ag_irq); TEST_1(ctx->c_orq); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); nta_incoming_destroy(ag->ag_irq), ag->ag_irq = NULL; TEST_1(!client_run(ctx, 500)); } END(); } int test_resolv(agent_t *ag, char const *resolv_conf) { int udp = 0, tcp = 0, sctp = 0, tls = 0; sip_via_t const *v; url_t *url; if (!resolv_conf) return 0; BEGIN(); nta_leg_bind(ag->ag_default_leg, leg_callback_200, ag); nta_agent_set_params(ag->ag_agent, NTATAG_SIP_T1(8 * 25), NTATAG_SIP_T1X64(64 * 25), NTATAG_SIP_T4(10 * 25), TAG_END()); TEST_1(v = nta_agent_via(ag->ag_agent)); for (; v; v = v->v_next) { if (su_casematch(v->v_protocol, sip_transport_udp)) udp = 1; else if (su_casematch(v->v_protocol, sip_transport_tcp)) tcp = 1; else if (su_casematch(v->v_protocol, sip_transport_sctp)) sctp = 1; else if (su_casematch(v->v_protocol, sip_transport_tls)) tls = 1; } url = url_hdup(ag->ag_home, (void *)"sip:example.org"); TEST_1(url); { /* Test 1.1 * Send a message to sip:example.org */ client_t ctx[1] = {{ ag, "Test 1.1" }}; ag->ag_expect_leg = ag->ag_default_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), SIPTAG_CONTACT(ag->ag_m_alice), TAG_END()); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); } { /* Test 1.2 * Send a message to sip:srv.example.org */ client_t ctx[1] = {{ ag, "Test 1.2" }}; url->url_host = "srv.example.org"; ag->ag_expect_leg = ag->ag_default_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), SIPTAG_CONTACT(ag->ag_m_alice), TAG_END()); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); } { /* Test 1.3 * Send a message to sip:ipv.example.org */ client_t ctx[1] = {{ ag, "Test 1.3" }}; url->url_host = "ipv.example.org"; ag->ag_expect_leg = ag->ag_default_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), SIPTAG_CONTACT(ag->ag_m_alice), TAG_END()); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); } { /* Test 1.4.1 * Send a message to sip:down.example.org */ client_t ctx[1] = {{ ag, "Test 1.4.1" }}; url->url_host = "down.example.org"; ag->ag_expect_leg = ag->ag_default_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), SIPTAG_CONTACT(ag->ag_m_alice), TAG_END()); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); } { /* Test 1.4.2 * Send a message to sip:na503.example.org */ client_t ctx[1] = {{ ag, "Test 1.4.2" }}; url->url_host = "na503.example.org"; ag->ag_expect_leg = ag->ag_default_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), SIPTAG_CONTACT(ag->ag_m_alice), TAG_END()); TEST_1(!client_run(ctx, 503)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); } { /* Test 1.4.3 * Send a message to sip:nona.example.org */ client_t ctx[1] = {{ ag, "Test 1.4.3" }}; url->url_host = "nona.example.org"; ag->ag_expect_leg = ag->ag_default_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), SIPTAG_CONTACT(ag->ag_m_alice), TAG_END()); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); } { /* Test 1.4.4 * Send a message to sip:nosrv.example.org * After failing to find _sip._udp.nosrv.example.org, * second SRV with _sip._udp.srv.example.org succeeds */ client_t ctx[1] = {{ ag, "Test 1.4.4" }}; url->url_host = "nosrv.example.org"; ag->ag_expect_leg = ag->ag_default_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), SIPTAG_CONTACT(ag->ag_m_alice), TAG_END()); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); } { /* Test 1.5.1 * Send a message to sip:srv.example.org;transport=tcp * Test outgoing_make_srv_query() */ client_t ctx[1] = {{ ag, "Test 1.5.1: outgoing_make_srv_query()" }}; url->url_host = "srv.example.org"; url->url_params = "transport=tcp"; ag->ag_expect_leg = ag->ag_default_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), SIPTAG_CONTACT(ag->ag_m_alice), TAG_END()); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); url->url_params = NULL; } { /* Test 1.5.2 * Send a message to sip:srv.example.org;transport=udp * Test outgoing_make_srv_query() */ client_t ctx[1] = {{ ag, "Test 1.5.2: outgoing_make_srv_query()" }}; url->url_host = "srv.example.org"; url->url_params = "transport=udp"; ag->ag_expect_leg = ag->ag_default_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), SIPTAG_CONTACT(ag->ag_m_alice), TAG_END()); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); url->url_params = NULL; } { /* Test 1.5.3 * Send a message to sip:srv2.example.org;transport=udp * Test outgoing_query_srv_a() */ client_t ctx[1] = {{ ag, "Test 1.5: outgoing_query_srv_a()" }}; url->url_host = "srv2.example.org"; url->url_params = "transport=udp"; ag->ag_expect_leg = ag->ag_default_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), SIPTAG_CONTACT(ag->ag_m_alice), TAG_END()); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); url->url_params = NULL; } { /* Test 1.6.1 * Send a message to sip:srv.example.org:$port * Test outgoing_make_a_aaaa_query() */ client_t ctx[1] = {{ ag, "Test 1.6.1: outgoing_make_a_aaaa_query()" }}; url->url_host = "srv.example.org"; url->url_port = ag->ag_contact->m_url->url_port; ag->ag_expect_leg = ag->ag_default_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), SIPTAG_CONTACT(ag->ag_m_alice), TAG_END()); TEST_1(!client_run(ctx, 503)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); } { /* Test 1.6.2 * Send a message to sip:a.example.org:$port * Test outgoing_make_a_aaaa_query() */ client_t ctx[1] = {{ ag, "Test 1.6.2: outgoing_make_a_aaaa_query()" }}; url->url_host = "a.example.org"; url->url_port = ag->ag_contact->m_url->url_port; ag->ag_expect_leg = ag->ag_default_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), SIPTAG_CONTACT(ag->ag_m_alice), TAG_END()); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); url->url_port = NULL; } #if 0 /* This must be run on host *without* proxy */ { /* Test 1.6c * Send a message to sip:na.example.org * Test outgoing_query_all() with NAPTR "A" flag */ client_t ctx[1] = {{ ag, "Test 1.6c" }}; url->url_host = "na.example.org"; ag->ag_expect_leg = ag->ag_default_leg; TEST_1(ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), SIPTAG_CONTACT(ag->ag_m_alice), TAG_END())); TEST_1(!client_run(ctx, 503)); TEST(ag->ag_latest_leg, ag->ag_default_leg); } #endif { /* Test 1.7 * Send a message to sip:down2.example.org:$port * Test A record failover. */ client_t ctx[1] = {{ ag, "Test 1.7: outgoing_make_a_aaaa_query()" }}; url->url_host = "down2.example.org"; url->url_port = ag->ag_contact->m_url->url_port; ag->ag_expect_leg = ag->ag_default_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), SIPTAG_CONTACT(ag->ag_m_alice), TAG_END()); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); url->url_params = NULL; } if (test_nta_sips) { /* Test 1.8 - Send a message to sips:example.org * * Tests sf.net bug #1292657 (SIPS resolving with NAPTR). */ client_t ctx[1] = {{ ag, "Test 1.8" }}; ag->ag_expect_leg = ag->ag_default_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)"sips:example.org", SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), SIPTAG_CONTACT(ag->ag_m_alice), TAG_END()); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); } nta_agent_set_params(ag->ag_agent, NTATAG_SIP_T1(500), NTATAG_SIP_T1X64(64 * 500), NTATAG_SIP_T2(NTA_SIP_T2), NTATAG_SIP_T4(NTA_SIP_T4), TAG_END()); END(); } /* Test default routing */ int test_routing(agent_t *ag) { url_t url[1]; *url = *ag->ag_aliases->m_url; url->url_user = "bob"; nta_leg_bind(ag->ag_default_leg, leg_callback_200, ag); nta_agent_set_params(ag->ag_agent, NTATAG_MAXSIZE(2 * 1024 * 1024), TAG_END()); BEGIN(); { /* * Send a message from default leg to default leg * * We are now using url with an explicit port that does not match with * our own port number. */ url_t url2[1]; client_t ctx[1] = {{ ag, "Test 1.2" }}; *url2 = *url; url2->url_port = "9"; /* discard service */ ag->ag_expect_leg = ag->ag_default_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, (url_string_t *)url, SIP_METHOD_MESSAGE, (url_string_t *)url2, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), SIPTAG_CONTACT(ag->ag_m_alice), TAG_END()); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); } END(); } /* Test dialogs and the tag handling */ int test_dialog(agent_t *ag) { BEGIN(); /* * Test establishing a dialog * * Alice sends a message to Bob, then Bob back to the Alice, and again * Alice to Bob. */ ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, leg_callback_200, ag, SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), TAG_END()); TEST_1(ag->ag_alice_leg); TEST_1(nta_leg_tag(ag->ag_alice_leg, NULL)); { client_t ctx[1] = {{ ag, "Test 2.1" }}; nta_leg_bind(ag->ag_server_leg, new_leg_callback_200, ag); /* Send message from Alice to Bob establishing the dialog */ ag->ag_expect_leg = ag->ag_server_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_alice_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)ag->ag_m_bob->m_url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), SIPTAG_CONTACT(ag->ag_m_alice), TAG_END()); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_server_leg); TEST_1(ag->ag_bob_leg != NULL); } { /* Send message from Bob to Alice */ client_t ctx[1] = {{ ag, "Test 2.2" }}; nta_leg_bind(ag->ag_server_leg, leg_callback_200, ag); ag->ag_expect_leg = ag->ag_alice_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_bob_leg, outgoing_callback, ctx, NULL, SIP_METHOD_MESSAGE, (url_string_t *)ag->ag_m_alice->m_url, SIPTAG_SUBJECT_STR(ctx->c_name), TAG_END()); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_alice_leg); } { /* Send again message from Alice to Bob */ client_t ctx[1] = {{ ag, "Test 2.3" }}; ag->ag_expect_leg = ag->ag_bob_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_alice_leg, outgoing_callback, ctx, NULL, SIP_METHOD_MESSAGE, (url_string_t *)ag->ag_m_bob->m_url, SIPTAG_SUBJECT_STR(ctx->c_name), TAG_END()); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_bob_leg); } { /* Send message from Bob to Alice * This time, however, specify request URI */ client_t ctx[1] = {{ ag, "Test 2.4" }}; ag->ag_expect_leg = ag->ag_alice_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_bob_leg, outgoing_callback, ctx, NULL, SIP_METHOD_MESSAGE, (url_string_t *)ag->ag_m_alice->m_url, SIPTAG_SUBJECT_STR(ctx->c_name), TAG_END()); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_alice_leg); } nta_leg_destroy(ag->ag_alice_leg), ag->ag_alice_leg = NULL; nta_leg_destroy(ag->ag_bob_leg), ag->ag_bob_leg = NULL; END(); } #ifndef MSG_TRUNC #define MSG_TRUNC 0 #endif static ssize_t recv_udp(agent_t *ag, void *b, size_t size) { ssize_t n; memset(b, 0, size); for (;;) { su_root_step(ag->ag_root, 10L); if (su_wait(ag->ag_sink_wait, 1, 0) == 0) { n = su_recv(ag->ag_sink_socket, b, size, MSG_TRUNC); if (n > 0) return n; } } } /* Test merging */ int test_merging(agent_t *ag) { BEGIN(); /* * Test merging: send two messages with same * from tag/call-id/cseq number to nta, * expect 200 and 408. */ char const rfc3261prefix[] = "z9hG4bK"; char const template[] = "%s " URL_PRINT_FORMAT " SIP/2.0\r\n" "Via: SIP/2.0/UDP 127.0.0.1:%s;branch=%s.%p\r\n" "Via: SIP/2.0/TCP fake.address.for.via.example.net;branch=z9hG4bK.%p\r\n" "CSeq: %u %s\r\n" "Call-ID: dfsjfhsduifhsjfsfjkfsd.%p@dfsdhfsjkhsdjk\r\n" "From: Evil Forker ;tag=test_nta-%s\r\n" "To: Bob the Builder %s\r\n" "Content-Length: 0\r\n" "\r\n"; url_t u1[1], u2[2]; char m1[1024], m2[1024]; char r1[1024], r2[1024]; size_t len, l1, l2; su_sockaddr_t *su = ag->ag_su_nta; socklen_t sulen = ag->ag_su_nta_len; /* Empty sink socket */ su_setblocking(ag->ag_sink_socket, 0); while (su_recv(ag->ag_sink_socket, m1, sizeof m1, MSG_TRUNC) >= 0) ; su_wait(ag->ag_sink_wait, 1, 0); su_wait(ag->ag_sink_wait, 1, 0); { /* RFC 3261 8.2.2.2 Merged Requests: If the request has no tag in the To header field, the UAS core MUST check the request against ongoing transactions. If the From tag, Call-ID, and CSeq exactly match those associated with an ongoing transaction, but the request does not match that transaction (based on the matching rules in Section 17.2.3), the UAS core SHOULD generate a 482 (Loop Detected) response and pass it to the server transaction. */ nta_leg_bind(ag->ag_server_leg, leg_callback_200, ag); ag->ag_expect_leg = ag->ag_server_leg; ag->ag_latest_leg = NULL; *u1 = *ag->ag_m_bob->m_url; snprintf(m1, sizeof m1, template, "MESSAGE", URL_PRINT_ARGS(u1), /* Via */ ag->ag_sink_port, rfc3261prefix, (void *)m1, /* 2nd Via */ (void *)ag, /* CSeq */ 13, "MESSAGE", /* Call-ID */ (void *)ag, /* From tag */ "2.5.1", /* To tag */ ""); l1 = strlen(m1); *u2 = *ag->ag_m_bob->m_url; snprintf(m2, sizeof m2, template, "MESSAGE", URL_PRINT_ARGS(u2), /* Via */ ag->ag_sink_port, rfc3261prefix, (void *)m2, /* 2nd Via */ (void *)ag, /* CSeq */ 13, "MESSAGE", /* Call-ID */ (void *)ag, /* From tag */ "2.5.1", /* To tag */ ""); l2 = strlen(m2); TEST_1((size_t)su_sendto(ag->ag_sink_socket, m1, l1, 0, su, sulen) == l1); TEST_1((size_t)su_sendto(ag->ag_sink_socket, m2, l2, 0, su, sulen) == l2); recv_udp(ag, r1, sizeof r1); recv_udp(ag, r2, sizeof r2); len = strlen("SIP/2.0 200 "); TEST_1(memcmp(r1, "SIP/2.0 200 ", len) == 0); TEST_1(memcmp(r2, "SIP/2.0 482 ", len) == 0); TEST_P(ag->ag_latest_leg, ag->ag_server_leg); } while (su_recv(ag->ag_sink_socket, m1, sizeof m1, MSG_TRUNC) >= 0) ; { /* * Check that request with same call-id, cseq and from-tag * are not merged if the method is different. */ nta_leg_bind(ag->ag_server_leg, leg_callback_200, ag); ag->ag_expect_leg = ag->ag_server_leg; ag->ag_latest_leg = NULL; *u1 = *ag->ag_m_bob->m_url; snprintf(m1, sizeof m1, template, "MESSAGE", URL_PRINT_ARGS(u1), /* Via */ ag->ag_sink_port, rfc3261prefix, (void *)m1, /* 2nd Via */ (void *)ag, /* CSeq */ 14, "MESSAGE", /* Call-ID */ (void *)ag, /* From tag */ "2.5.2", /* To tag */ ""); l1 = strlen(m1); *u2 = *ag->ag_m_bob->m_url; snprintf(m2, sizeof m2, template, "OPTIONS", URL_PRINT_ARGS(u2), /* Via */ ag->ag_sink_port, rfc3261prefix, (void *)m2, /* 2nd Via */ (void *)ag, /* CSeq */ 14, "OPTIONS", /* Call-ID */ (void *)ag, /* From tag */ "2.5.2", /* To tag */ ""); l2 = strlen(m2); TEST_1((size_t)su_sendto(ag->ag_sink_socket, m1, l1, 0, su, sulen) == l1); TEST_1((size_t)su_sendto(ag->ag_sink_socket, m2, l2, 0, su, sulen) == l2); recv_udp(ag, r1, sizeof r1); recv_udp(ag, r2, sizeof r2); len = strlen("SIP/2.0 200 "); TEST_1(memcmp(r1, "SIP/2.0 200 ", len) == 0); TEST_1(memcmp(r2, "SIP/2.0 482 ", len) != 0); TEST_P(ag->ag_latest_leg, ag->ag_server_leg); } while (su_recv(ag->ag_sink_socket, m1, sizeof m1, MSG_TRUNC) >= 0) ; { /* test with rfc2543 */ snprintf(m1, sizeof m1, template, "MASSAGE", URL_PRINT_ARGS(u1), /* Via */ ag->ag_sink_port, "0.", (void *)0, /* 2nd Via */ (void *)ag, /* CSeq */ 14, "MASSAGE", /* Call-ID */ (void *)(ag + 1), /* From tag */ "2.5.3", /* To tag */ ""); l1 = strlen(m1); u2->url_user = "bob+2"; snprintf(m2, sizeof m2, template, "MASSAGE", URL_PRINT_ARGS(u2), /* Via */ ag->ag_sink_port, "0.", (void *)0, /* 2nd Via */ (void *)ag, /* CSeq */ 14, "MASSAGE", /* Call-ID */ (void *)(ag + 1), /* From tag */ "2.5.3", /* To tag */ ""); l2 = strlen(m2); TEST_1((size_t)su_sendto(ag->ag_sink_socket, m1, l1, 0, su, sulen) == l1); TEST_1((size_t)su_sendto(ag->ag_sink_socket, m2, l2, 0, su, sulen) == l2); recv_udp(ag, r1, sizeof r1); recv_udp(ag, r2, sizeof r2); l1 = strlen("SIP/2.0 200 "); TEST_1(memcmp(r1, "SIP/2.0 200 ", l1) == 0); TEST_1(memcmp(r2, "SIP/2.0 482 ", l1) == 0); TEST_P(ag->ag_latest_leg, ag->ag_server_leg); } while (su_recv(ag->ag_sink_socket, m1, sizeof m1, MSG_TRUNC) >= 0) ; { /* test with to-tag */ snprintf(m1, sizeof m1, template, "MESSAGE", URL_PRINT_ARGS(u1), /* Via */ ag->ag_sink_port, rfc3261prefix, (void *)m1, /* 2nd Via */ (void *)ag, /* CSeq */ 15, "MESSAGE", /* Call-ID */ (void *)(ag + 2), /* From tag */ "2.5.4", /* To tag */ ";tag=in-dialog"); l1 = strlen(m1); u2->url_user = "bob+2"; snprintf(m2, sizeof m2, template, "MESSAGE", URL_PRINT_ARGS(u2), /* Via */ ag->ag_sink_port, rfc3261prefix, (void *)m2, /* 2nd Via */ (void *)ag, /* CSeq */ 15, "MESSAGE", /* Call-ID */ (void *)(ag + 2), /* From tag */ "2.5.4", /* To tag */ ";tag=in-dialog"); l2 = strlen(m2); TEST_1((size_t)su_sendto(ag->ag_sink_socket, m1, l1, 0, su, sulen) == l1); TEST_1((size_t)su_sendto(ag->ag_sink_socket, m2, l2, 0, su, sulen) == l2); recv_udp(ag, r1, sizeof r1); recv_udp(ag, r2, sizeof r2); l1 = strlen("SIP/2.0 200 "); TEST_1(memcmp(r1, "SIP/2.0 200 ", l1) == 0); TEST_1(memcmp(r2, "SIP/2.0 482 ", l1) != 0); TEST_P(ag->ag_latest_leg, ag->ag_server_leg); } while (su_recv(ag->ag_sink_socket, m1, sizeof m1, MSG_TRUNC) >= 0) ; { /* test with rfc2543 and to-tag */ snprintf(m1, sizeof m1, template, "MESSAGE", URL_PRINT_ARGS(u1), /* Via */ ag->ag_sink_port, "0.", (void *)0, /* 2nd Via */ (void *)ag, /* CSeq */ 15, "MESSAGE", /* Call-ID */ (void *)(ag + 2), /* From tag */ "2.5.5", /* To tag */ ";tag=in-dialog"); l1 = strlen(m1); snprintf(m2, sizeof m2, template, "MESSAGE", URL_PRINT_ARGS(u2), /* Via */ ag->ag_sink_port, "0.", (void *)0, /* 2nd Via */ (void *)ag, /* CSeq */ 15, "MESSAGE", /* Call-ID */ (void *)(ag + 2), /* From tag */ "2.5.5", /* To tag */ ";tag=in-dialog"); l2 = strlen(m2); TEST_1((size_t)su_sendto(ag->ag_sink_socket, m1, l1, 0, su, sulen) == l1); TEST_1((size_t)su_sendto(ag->ag_sink_socket, m2, l2, 0, su, sulen) == l2); recv_udp(ag, r1, sizeof r1); recv_udp(ag, r2, sizeof r2); l1 = strlen("SIP/2.0 200 "); TEST_1(memcmp(r1, "SIP/2.0 200 ", l1) == 0); TEST_1(memcmp(r2, "SIP/2.0 482 ", l1) != 0); TEST_P(ag->ag_latest_leg, ag->ag_server_leg); } while (su_recv(ag->ag_sink_socket, m1, sizeof m1, MSG_TRUNC) >= 0) ; { /* test INVITE/CANCEL with rfc2543 */ char const template2[] = "%s " URL_PRINT_FORMAT " SIP/2.0\r\n" "Via: SIP/2.0/UDP 127.0.0.1:%s;x-kuik=%p\r\n" "CSeq: %u %s\r\n" "Call-ID: %p.dfsdhfsjkhsdjk.dfsjfhsduifhsjfsfjkfsd\r\n" "From: Evil Forker ;tag=test_nta-%s\r\n" "To: Bob the Builder %s\r\n" "Content-Length: 0\r\n" "\r\n"; nta_leg_bind(ag->ag_server_leg, new_leg_callback_180, ag); snprintf(m1, sizeof m1, template2, "INVITE", URL_PRINT_ARGS(u1), /* Via */ ag->ag_sink_port, m1, /* CSeq */ 15, "INVITE", /* Call-ID */ (void *)(ag + 2), /* From tag */ "2.6.1", /* To tag */ ""); l1 = strlen(m1); TEST_1((size_t)su_sendto(ag->ag_sink_socket, m1, l1, 0, su, sulen) == l1); recv_udp(ag, r1, sizeof r1); l1 = strlen("SIP/2.0 180 "); TEST_1(memcmp(r1, "SIP/2.0 180 ", l1) == 0); TEST_1(ag->ag_irq); nta_incoming_bind(ag->ag_irq, wait_for_ack_or_cancel, ag); snprintf(m2, sizeof m2, template2, "CANCEL", URL_PRINT_ARGS(u1), /* Via */ ag->ag_sink_port, m1, /* CSeq */ 15, "CANCEL", /* Call-ID */ (void *)(ag + 2), /* From tag */ "2.6.1", /* To tag */ ""); l2 = strlen(m2); TEST_1((size_t)su_sendto(ag->ag_sink_socket, m2, l2, 0, su, sulen) == l2); recv_udp(ag, r1, sizeof r1); recv_udp(ag, r2, sizeof r2); l1 = strlen("SIP/2.0 200 "); TEST_1(strstr(r1, "15 CANCEL")); TEST_1(memcmp(r1, "SIP/2.0 200 ", l1) == 0); TEST_1(strstr(r2, "15 INVITE")); TEST_1(memcmp(r2, "SIP/2.0 487 ", l1) == 0); TEST_1(nta_incoming_status(ag->ag_irq) == 487); snprintf(m2, sizeof m2, template2, "ACK", URL_PRINT_ARGS(u1), /* Via */ ag->ag_sink_port, m1, /* CSeq */ 15, "ACK", /* Call-ID */ (void *)(ag + 2), /* From tag */ "2.6.1", /* To tag */ ""); l2 = strlen(m2); TEST_1((size_t)su_sendto(ag->ag_sink_socket, m2, l2, 0, su, sulen) == l2); nta_leg_destroy(ag->ag_bob_leg); ag->ag_bob_leg = NULL; } while (su_recv(ag->ag_sink_socket, m1, sizeof m1, MSG_TRUNC) >= 0) ; END(); } static int wait_for_ack_or_cancel(agent_t *ag, nta_incoming_t *irq, sip_t const *sip) { sip_method_t method; method = sip ? sip->sip_request->rq_method : sip_method_unknown; if (method == sip_method_cancel) { nta_incoming_treply(ag->ag_irq, SIP_487_REQUEST_CANCELLED, TAG_END()); } else if (method == sip_method_ack) { nta_incoming_destroy(irq); ag->ag_irq = NULL; ag->ag_running = 0; } else { /* Timeout */ nta_incoming_destroy(irq); ag->ag_irq = NULL; ag->ag_running = 0; } return 0; } /* ---------------------------------------------------------------------- */ /* Test INVITE, dialogs */ static int test_for_ack(agent_t *ag, nta_incoming_t *irq, sip_t const *sip) { sip_method_t method; BEGIN(); method = sip ? sip->sip_request->rq_method : sip_method_unknown; nta_incoming_destroy(irq); TEST_P(irq, ag->ag_irq); ag->ag_irq = NULL; TEST(method, sip_method_ack); ag->ag_running = 0; END(); } static int test_for_prack(agent_t *ag, nta_reliable_t *rel, nta_incoming_t *prack, sip_t const *sip) { sip_method_t method = sip ? sip->sip_request->rq_method : sip_method_unknown; nta_incoming_treply(ag->ag_irq, SIP_200_OK, SIPTAG_CONTACT(ag->ag_m_alice), TAG_END()); TEST(method, sip_method_prack); return 200; } int alice_leg_callback(agent_t *ag, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip) { BEGIN(); if (tstflags & tst_verbatim) { printf("%s: %s: %s " URL_PRINT_FORMAT " %s\n", name, __func__, sip->sip_request->rq_method_name, URL_PRINT_ARGS(sip->sip_request->rq_url), sip->sip_request->rq_version); } TEST_1(sip->sip_content_length); TEST_1(sip->sip_via); TEST_1(sip->sip_from && sip->sip_from->a_tag); if (sip->sip_request->rq_method == sip_method_prack) return 481; ag->ag_latest_leg = leg; if (leg != ag->ag_alice_leg) { leg_match(ag, leg, 1, __func__); return 500; } if (sip->sip_request->rq_method == sip_method_invite) { TEST_1(sip_has_feature(sip->sip_supported, "100rel")); nta_incoming_bind(irq, test_for_ack, ag); nta_incoming_treply(irq, SIP_100_TRYING, TAG_END()); nta_agent_set_params(ag->ag_agent, NTATAG_DEBUG_DROP_PROB(ag->ag_drop), TAG_END()); ag->ag_reliable = nta_reliable_treply(irq, NULL, NULL, SIP_183_SESSION_PROGRESS, SIPTAG_CONTENT_TYPE(ag->ag_content_type), SIPTAG_PAYLOAD(ag->ag_payload), SIPTAG_CONTACT(ag->ag_m_alice), TAG_END()); TEST_1(ag->ag_reliable); ag->ag_reliable = nta_reliable_treply(irq, NULL, NULL, 184, "Next", SIPTAG_CONTACT(ag->ag_m_alice), TAG_END()); TEST_1(ag->ag_reliable); ag->ag_reliable = nta_reliable_treply(irq, test_for_prack, ag, 185, "Last", SIPTAG_CONTACT(ag->ag_m_alice), TAG_END()); TEST_1(ag->ag_reliable); ag->ag_irq = irq; return 0; } if (sip->sip_request->rq_method == sip_method_bye) { leg_zap(ag, leg); } if (sip) return 200; END(); } int bob_leg_callback(agent_t *ag, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip) { BEGIN(); if (tstflags & tst_verbatim) { printf("%s: %s: %s " URL_PRINT_FORMAT " %s\n", name, __func__, sip->sip_request->rq_method_name, URL_PRINT_ARGS(sip->sip_request->rq_url), sip->sip_request->rq_version); } TEST_1(sip->sip_content_length); TEST_1(sip->sip_via); TEST_1(sip->sip_from && sip->sip_from->a_tag); if (sip->sip_request->rq_method == sip_method_prack) return 481; ag->ag_latest_leg = leg; if (ag->ag_bob_leg && leg != ag->ag_bob_leg) { leg_match(ag, leg, 1, __func__); return 500; } if (ag->ag_bob_leg == NULL) { nta_leg_bind(leg, leg_callback_500, ag); ag->ag_bob_leg = nta_leg_tcreate(ag->ag_agent, bob_leg_callback, ag, SIPTAG_CALL_ID(sip->sip_call_id), SIPTAG_FROM(sip->sip_to), SIPTAG_TO(sip->sip_from), TAG_END()); TEST_1(ag->ag_bob_leg); TEST_1(nta_leg_tag(ag->ag_bob_leg, NULL)); TEST_1(nta_leg_get_tag(ag->ag_bob_leg)); TEST_1(nta_incoming_tag(irq, nta_leg_get_tag(ag->ag_bob_leg))); TEST(nta_leg_server_route(ag->ag_bob_leg, sip->sip_record_route, sip->sip_contact), 0); } if (sip->sip_request->rq_method != sip_method_invite) { return 200; } else { nta_incoming_bind(irq, test_for_ack, ag); #if 1 nta_incoming_treply(irq, SIP_180_RINGING, SIPTAG_CONTACT(ag->ag_m_bob), TAG_END()); nta_incoming_treply(irq, SIP_180_RINGING, SIPTAG_CONTACT(ag->ag_m_bob), TAG_END()); #endif nta_incoming_treply(irq, SIP_200_OK, SIPTAG_CONTENT_TYPE(ag->ag_content_type), SIPTAG_PAYLOAD(ag->ag_payload), SIPTAG_CONTACT(ag->ag_m_bob), TAG_END()); ag->ag_irq = irq; } END(); } static int invite_client_deinit(client_t *c) { agent_t *ag = c->c_ag; invite_client_t *ic = (invite_client_t *)c; if (ic->ic_orq) nta_outgoing_destroy(ic->ic_orq), ic->ic_orq = NULL; if (ic->ic_tag) su_free(ag->ag_home, ic->ic_tag), ic->ic_tag = NULL; return 0; } static int check_prack_sending(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) { agent_t *ag = ctx->c_ag; int status = ctx->c_status; if (100 < status && status < 200) { if (sip->sip_require && sip_has_feature(sip->sip_require, "100rel")) { nta_outgoing_t *prack = NULL; TEST_1(sip->sip_rseq); prack = nta_outgoing_prack(ag->ag_call_leg, orq, NULL, NULL, NULL, sip, TAG_END()); nta_outgoing_destroy(prack); TEST_1(prack != NULL); } } return 0; } static int check_leg_tagging(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) { agent_t *ag = ctx->c_ag; int status = ctx->c_status; if (200 <= status && status < 300) { TEST_1(nta_leg_rtag(ag->ag_call_leg, sip->sip_to->a_tag)); TEST(nta_leg_client_route(ag->ag_call_leg, sip->sip_record_route, sip->sip_contact), 0); } return 0; } static int check_tu_ack(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) { agent_t *ag = ctx->c_ag; int status = ctx->c_status; if (200 <= status && status < 300) { nta_outgoing_t *ack; ack = nta_outgoing_tcreate(ag->ag_call_leg, NULL, NULL, NULL, SIP_METHOD_ACK, NULL, SIPTAG_CSEQ(sip->sip_cseq), TAG_END()); nta_outgoing_destroy(ack); TEST_1(ack); } return 0; } static int check_final_error(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) { agent_t *ag = ctx->c_ag; int status = ctx->c_status; if (status >= 300) ag->ag_call_leg = NULL; return 0; } /** Cancel call after receiving 1XX response */ static int cancel_invite(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) { int status = ctx->c_status; if (100 < status && status < 200) { nta_outgoing_cancel(orq); ctx->c_status = 0; } else if (status >= 200) { TEST_1(status == 487 || status == 504); } return 0; } static client_check_f * const checks_for_invite[] = { client_check_to_tag, check_leg_tagging, check_tu_ack, check_final_error, NULL, }; static client_check_f * const checks_for_reinvite[] = { client_check_to_tag, check_prack_sending, check_leg_tagging, check_tu_ack, NULL, }; int test_call(agent_t *ag) { sip_content_type_t *ct = ag->ag_content_type; sip_payload_t *sdp = ag->ag_payload; nta_leg_t *old_leg; sip_replaces_t *r1, *r2; BEGIN(); { invite_client_t ic[1] = {{{{ ag, "Call 1", NULL, checks_for_invite, invite_client_deinit }}}}; client_t *ctx = ic->ic_client; /* * Test establishing a call * * Alice sends a INVITE to Bob, then Bob sends 200 Ok. */ ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, alice_leg_callback, ag, SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), TAG_END()); TEST_1(ag->ag_alice_leg); TEST_1(nta_leg_tag(ag->ag_alice_leg, NULL)); nta_leg_bind(ag->ag_server_leg, bob_leg_callback, ag); /* Send INVITE */ ag->ag_expect_leg = ag->ag_server_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_alice_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_INVITE, (url_string_t *)ag->ag_m_bob->m_url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_CONTACT(ag->ag_m_alice), SIPTAG_CONTENT_TYPE(ct), SIPTAG_ACCEPT_CONTACT_STR("*;audio"), SIPTAG_PAYLOAD(sdp), NTATAG_USE_TIMESTAMP(1), NTATAG_PASS_100(1), TAG_END()); TEST_1(ctx->c_orq); /* Try to CANCEL it immediately */ TEST_1(nta_outgoing_cancel(ctx->c_orq) == 0); /* As Bob immediately answers INVITE with 200 Ok, cancel should be answered with 481 and 200 Ok is returned to INVITE. */ TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_server_leg); TEST_1(ag->ag_bob_leg != NULL); } TEST_1(r1 = nta_leg_make_replaces(ag->ag_alice_leg, ag->ag_home, 0)); TEST_1(r2 = sip_replaces_format(ag->ag_home, "%s;from-tag=%s;to-tag=%s", r1->rp_call_id, r1->rp_to_tag, r1->rp_from_tag)); TEST_P(ag->ag_alice_leg, nta_leg_by_replaces(ag->ag_agent, r2)); TEST_P(ag->ag_bob_leg, nta_leg_by_replaces(ag->ag_agent, r1)); { invite_client_t ic[1] = {{{{ ag, "Re-INVITE in Call 1", NULL, checks_for_reinvite, invite_client_deinit }}}}; client_t *ctx = ic->ic_client; /* Re-INVITE from Bob to Alice. * * Alice first sends 183, waits for PRACK, then sends 184 and 185, * waits for PRACKs, then sends 200, waits for ACK. */ ag->ag_expect_leg = ag->ag_alice_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_bob_leg, outgoing_callback, ctx, NULL, SIP_METHOD_INVITE, NULL, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_CONTACT(ag->ag_m_bob), SIPTAG_SUPPORTED_STR("foo"), SIPTAG_CONTENT_TYPE(ct), SIPTAG_PAYLOAD(sdp), TAG_END()); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_alice_leg); } { client_t ctx[1] = {{ ag, "Hangup" }}; nta_agent_set_params(ag->ag_agent, NTATAG_DEBUG_DROP_PROB(0), TAG_END()); /* Send BYE from Bob to Alice */ old_leg = ag->ag_expect_leg = ag->ag_alice_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_bob_leg, outgoing_callback, ctx, NULL, SIP_METHOD_BYE, NULL, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), SIPTAG_CONTACT(ag->ag_m_alice), SIPTAG_CONTENT_TYPE(ct), SIPTAG_PAYLOAD(sdp), TAG_END()); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, old_leg); TEST_P(ag->ag_alice_leg, NULL); } nta_leg_destroy(ag->ag_bob_leg), ag->ag_bob_leg = NULL; ag->ag_latest_leg = NULL; ag->ag_call_leg = NULL; END(); } /* ========================================================================== */ /* Test early dialogs, PRACK */ int test_for_ack_or_timeout(agent_t *ag, nta_incoming_t *irq, sip_t const *sip) { BEGIN(); sip_method_t method = sip ? sip->sip_request->rq_method : sip_method_unknown; if (method == sip_method_ack) { TEST(method, sip_method_ack); ag->ag_acked = 1; } else if (method == sip_method_cancel) { nta_incoming_treply(irq, SIP_487_REQUEST_CANCELLED, TAG_END()); ag->ag_canceled = 1; } else { if (ag->ag_bob_leg) { nta_leg_destroy(ag->ag_bob_leg), ag->ag_bob_leg = NULL; } } nta_incoming_destroy(irq); TEST_P(irq, ag->ag_irq); ag->ag_irq = NULL; END(); } /* */ int bob_leg_callback2(agent_t *ag, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip) { BEGIN(); if (tstflags & tst_verbatim) { printf("%s: %s: %s " URL_PRINT_FORMAT " %s\n", name, __func__, sip->sip_request->rq_method_name, URL_PRINT_ARGS(sip->sip_request->rq_url), sip->sip_request->rq_version); } TEST_1(sip->sip_content_length); TEST_1(sip->sip_via); TEST_1(sip->sip_from && sip->sip_from->a_tag); ag->ag_latest_leg = leg; if (ag->ag_bob_leg && leg != ag->ag_bob_leg) { leg_match(ag, leg, 1, __func__); return 500; } if (ag->ag_bob_leg == NULL) { nta_leg_bind(leg, leg_callback_500, ag); ag->ag_bob_leg = nta_leg_tcreate(ag->ag_agent, bob_leg_callback, ag, SIPTAG_CALL_ID(sip->sip_call_id), SIPTAG_FROM(sip->sip_to), SIPTAG_TO(sip->sip_from), TAG_END()); TEST_1(ag->ag_bob_leg); TEST_1(nta_leg_tag(ag->ag_bob_leg, NULL)); TEST_1(nta_leg_get_tag(ag->ag_bob_leg)); TEST_1(nta_incoming_tag(irq, nta_leg_get_tag(ag->ag_bob_leg))); TEST(nta_leg_server_route(ag->ag_bob_leg, sip->sip_record_route, sip->sip_contact), 0); } if (sip->sip_request->rq_method != sip_method_invite) { return 200; } nta_incoming_bind(irq, test_for_ack_or_timeout, ag); nta_incoming_treply(irq, SIP_183_SESSION_PROGRESS, SIPTAG_CONTENT_TYPE(ag->ag_content_type), SIPTAG_PAYLOAD(ag->ag_payload), SIPTAG_CONTACT(ag->ag_m_bob), TAG_END()); if (0) nta_incoming_treply(irq, SIP_180_RINGING, SIPTAG_CONTENT_TYPE(ag->ag_content_type), SIPTAG_PAYLOAD(ag->ag_payload), SIPTAG_CONTACT(ag->ag_m_bob), TAG_END()); nta_incoming_treply(irq, SIP_200_OK, SIPTAG_CONTACT(ag->ag_m_bob), TAG_END()); ag->ag_irq = irq; END(); } /** Fork the original INVITE. */ static int check_orq_tagging(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) { agent_t *ag = ctx->c_ag; int status = ctx->c_status; invite_client_t *ic = (invite_client_t *)ctx; if (100 < status && status < 200) { TEST_1(sip->sip_rseq); TEST_1(sip->sip_to->a_tag); TEST_1(orq == ctx->c_orq); TEST_1(ic); TEST_1(ic->ic_orq == NULL); TEST_1(ic->ic_tag == NULL); ic->ic_orq = orq; ic->ic_tag = su_strdup(ag->ag_home, sip->sip_to->a_tag); TEST_1(ic->ic_tag); ic->ic_tag_status = status; TEST_S(nta_leg_rtag(ag->ag_call_leg, ic->ic_tag), ic->ic_tag); TEST(nta_leg_client_route(ag->ag_call_leg, sip->sip_record_route, sip->sip_contact), 0); orq = nta_outgoing_tagged(orq, outgoing_callback, ctx, ic->ic_tag, sip->sip_rseq); TEST_1(orq); if (ic->ic_orq != ctx->c_orq) nta_outgoing_destroy(ctx->c_orq); ctx->c_orq = orq; TEST_1(ctx->c_checks && ctx->c_checks[0] == check_orq_tagging); ctx->c_checks++; } return 0; } static client_check_f * const checks_for_100rel[] = { check_orq_tagging, client_check_to_tag, check_prack_sending, check_leg_tagging, check_tu_ack, NULL, }; static int process_prack(nta_reliable_magic_t *arg, nta_reliable_t *rel, nta_incoming_t *irq, sip_t const *sip) { agent_t *ag = (agent_t *)arg; if (irq) { return 200; } else if (ag->ag_irq) { nta_incoming_treply(ag->ag_irq, 504, "Reliable Response Timeout", TAG_END()); nta_incoming_destroy(ag->ag_irq); return 487; } return 487; } /* respond with 183 when receiving invite */ int bob_leg_callback3(agent_t *ag, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip) { BEGIN(); if (tstflags & tst_verbatim) { printf("%s: %s: %s " URL_PRINT_FORMAT " %s\n", name, __func__, sip->sip_request->rq_method_name, URL_PRINT_ARGS(sip->sip_request->rq_url), sip->sip_request->rq_version); } TEST_1(sip->sip_content_length); TEST_1(sip->sip_via); TEST_1(sip->sip_from && sip->sip_from->a_tag); ag->ag_latest_leg = leg; if (ag->ag_bob_leg && leg != ag->ag_bob_leg) { leg_match(ag, leg, 1, __func__); return 500; } if (ag->ag_bob_leg == NULL) { nta_leg_bind(leg, leg_callback_500, ag); ag->ag_bob_leg = nta_leg_tcreate(ag->ag_agent, bob_leg_callback, ag, SIPTAG_CALL_ID(sip->sip_call_id), SIPTAG_FROM(sip->sip_to), SIPTAG_TO(sip->sip_from), TAG_END()); TEST_1(ag->ag_bob_leg); TEST_1(nta_leg_tag(ag->ag_bob_leg, NULL)); TEST_1(nta_leg_get_tag(ag->ag_bob_leg)); TEST_1(nta_incoming_tag(irq, nta_leg_get_tag(ag->ag_bob_leg))); TEST(nta_leg_server_route(ag->ag_bob_leg, sip->sip_record_route, sip->sip_contact), 0); } if (sip->sip_request->rq_method != sip_method_invite) { return 200; } else { nta_reliable_t *rel; nta_incoming_bind(irq, test_for_ack_or_timeout, ag); rel = nta_reliable_treply(irq, process_prack, ag, SIP_183_SESSION_PROGRESS, SIPTAG_CONTENT_TYPE(ag->ag_content_type), SIPTAG_PAYLOAD(ag->ag_payload), SIPTAG_CONTACT(ag->ag_m_bob), TAG_END()); ag->ag_irq = irq; } END(); } /* * Test establishing a call with an early dialog / 100 rel / timeout * * Alice sends a INVITE to Bob, then Bob sends 183, Alice sends PRACK, * Bob sends 200 to PRACK, Bob sends 200 to INVITE. * Bob sends BYE, Alice 200. */ int test_prack(agent_t *ag) { BEGIN(); sip_content_type_t *ct = ag->ag_content_type; sip_payload_t *sdp = ag->ag_payload; nta_leg_t *old_leg; { /* Send a PRACK from default leg, NTA responds to it with error */ url_t url[1]; client_t ctx[1] = {{ ag, "Test 1.1" }}; *url = *ag->ag_aliases->m_url; url->url_user = "bob"; ag->ag_expect_leg = ag->ag_server_leg; ag->ag_latest_leg = NULL; ctx->c_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_PRACK, (url_string_t *)url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), SIPTAG_CONTACT(ag->ag_m_alice), SIPTAG_RACK_STR("1432432 42332432 INVITE"), TAG_END()); TEST_1(!client_run(ctx, 481)); TEST_P(ag->ag_latest_leg, NULL); } ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, alice_leg_callback, ag, SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), TAG_END()); TEST_1(ag->ag_alice_leg); TEST_1(nta_leg_tag(ag->ag_alice_leg, NULL)); /* Send INVITE */ { invite_client_t ic[1] = {{{{ ag, "Call 2", NULL, checks_for_100rel, invite_client_deinit }}}}; client_t *ctx = ic->ic_client; nta_leg_bind(ag->ag_server_leg, bob_leg_callback2, ag); ag->ag_expect_leg = ag->ag_server_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_alice_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_INVITE, (url_string_t *)ag->ag_m_bob->m_url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_CONTACT(ag->ag_m_alice), SIPTAG_REQUIRE_STR("100rel"), SIPTAG_CONTENT_TYPE(ct), SIPTAG_PAYLOAD(sdp), TAG_END()); TEST_1(!client_run_until_acked(ctx, 200)); /*TEST(ic->ic_tag_status, 183); */ TEST_P(ag->ag_latest_leg, ag->ag_server_leg); TEST_1(ag->ag_bob_leg != NULL); } { client_t ctx[1] = {{ ag, "Hangup" }}; /* Send BYE from Bob to Alice */ old_leg = ag->ag_expect_leg = ag->ag_alice_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_bob_leg, outgoing_callback, ctx, NULL, SIP_METHOD_BYE, NULL, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), SIPTAG_CONTACT(ag->ag_m_alice), SIPTAG_CONTENT_TYPE(ct), SIPTAG_PAYLOAD(sdp), TAG_END()); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, old_leg); TEST_P(ag->ag_alice_leg, NULL); } nta_leg_destroy(ag->ag_bob_leg), ag->ag_bob_leg = NULL; ag->ag_latest_leg = NULL; ag->ag_call_leg = NULL; /* Test CANCELing a call after receiving 100rel response */ ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, alice_leg_callback, ag, SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), TAG_END()); TEST_1(ag->ag_alice_leg); TEST_1(nta_leg_tag(ag->ag_alice_leg, NULL)); { invite_client_t ic[1] = {{{{ ag, "Call 2b", cancel_invite, checks_for_invite, invite_client_deinit }}}}; client_t *ctx = ic->ic_client; /* Send INVITE */ nta_leg_bind(ag->ag_server_leg, bob_leg_callback3, ag); ag->ag_expect_leg = ag->ag_server_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_alice_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_INVITE, (url_string_t *)ag->ag_m_bob->m_url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_CONTACT(ag->ag_m_alice), SIPTAG_REQUIRE_STR("100rel"), SIPTAG_CONTENT_TYPE(ct), SIPTAG_PAYLOAD(sdp), TAG_END()); TEST_1(!client_run(ctx, 0)); } TEST_P(ag->ag_latest_leg, ag->ag_server_leg); TEST_1(ag->ag_bob_leg != NULL); nta_leg_destroy(ag->ag_bob_leg), ag->ag_bob_leg = NULL; ag->ag_latest_leg = NULL; ag->ag_call_leg = NULL; if (EXPENSIVE_CHECKS) { printf("%s: starting 100rel timeout test, test will complete in 4 seconds\n", name); TEST(nta_agent_set_params(ag->ag_agent, NTATAG_SIP_T1(25), NTATAG_SIP_T1X64(64 * 25), TAG_END()), 2); ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, alice_leg_callback, ag, SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), TAG_END()); TEST_1(ag->ag_alice_leg); TEST_1(nta_leg_tag(ag->ag_alice_leg, NULL)); { invite_client_t ic[1] = {{{{ ag, "Call 3", NULL, checks_for_invite, invite_client_deinit }}}}; client_t *ctx = ic->ic_client; /* Send INVITE, * send precious provisional response * do not send PRACK, * timeout (after 64 * t1 ~ 3.2 seconds), */ nta_leg_bind(ag->ag_server_leg, bob_leg_callback2, ag); ag->ag_expect_leg = ag->ag_server_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_alice_leg, outgoing_callback, ctx, ag->ag_obp, SIP_METHOD_INVITE, (url_string_t *)ag->ag_m_bob->m_url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_CONTACT(ag->ag_m_alice), SIPTAG_REQUIRE_STR("100rel"), SIPTAG_CONTENT_TYPE(ct), SIPTAG_PAYLOAD(sdp), TAG_END()); TEST_1(ctx->c_orq); nta_test_run(ag); TEST(ctx->c_status, 503); TEST_P(ctx->c_orq, NULL); TEST_P(ag->ag_latest_leg, ag->ag_server_leg); TEST_1(ag->ag_bob_leg == NULL); } TEST(nta_agent_set_params(ag->ag_agent, NTATAG_SIP_T1(500), NTATAG_SIP_T1X64(64 * 500), TAG_END()), 2); } if (EXPENSIVE_CHECKS || 1) { /* * client sends INVITE, * server sends provisional response, * client PRACKs it, * client timeouts after timer C */ invite_client_t ic[1] = {{{{ ag, "Call 4", NULL, checks_for_100rel, invite_client_deinit }}}}; client_t *ctx = ic->ic_client; printf("%s: starting timer C, test will complete in 1 seconds\n", name); TEST(nta_agent_set_params(ag->ag_agent, NTATAG_TIMER_C(1000), TAG_END()), 1); TEST_1(ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, alice_leg_callback, ag, SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), TAG_END())); TEST_1(nta_leg_tag(ag->ag_alice_leg, NULL)); nta_leg_bind(ag->ag_server_leg, bob_leg_callback3, ag); ag->ag_expect_leg = ag->ag_server_leg; TEST_1(ctx->c_orq = nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_alice_leg, outgoing_callback, ic->ic_client, ag->ag_obp, SIP_METHOD_INVITE, (url_string_t *)ag->ag_m_bob->m_url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_CONTACT(ag->ag_m_alice), SIPTAG_REQUIRE_STR("100rel"), SIPTAG_CONTENT_TYPE(ct), SIPTAG_PAYLOAD(sdp), TAG_END())); /* Run until 1) server gets CANCEL and 2) client gets 487 */ /* Note: this has been changed in 1.12.11 */ TEST_1(!client_run_until_canceled(ctx, 487)); TEST_1(ag->ag_canceled != 0); TEST_P(ag->ag_latest_leg, ag->ag_server_leg); TEST_1(ag->ag_bob_leg); nta_leg_destroy(ag->ag_bob_leg), ag->ag_bob_leg = NULL; TEST(nta_agent_set_params(ag->ag_agent, NTATAG_TIMER_C(185 * 1000), TAG_END()), 1); nta_leg_destroy(ag->ag_bob_leg), ag->ag_bob_leg = NULL; ag->ag_latest_leg = NULL; ag->ag_call_leg = NULL; } END(); } int alice_leg_callback2(agent_t *ag, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip) { BEGIN(); if (tstflags & tst_verbatim) { printf("%s: %s: %s " URL_PRINT_FORMAT " %s\n", name, __func__, sip->sip_request->rq_method_name, URL_PRINT_ARGS(sip->sip_request->rq_url), sip->sip_request->rq_version); } TEST_1(sip->sip_content_length); TEST_1(sip->sip_via); TEST_1(sip->sip_from && sip->sip_from->a_tag); if (sip->sip_request->rq_method == sip_method_prack) return 481; ag->ag_latest_leg = leg; if (leg != ag->ag_alice_leg) { leg_match(ag, leg, 1, __func__); return 500; } if (sip->sip_request->rq_method == sip_method_invite) { TEST_1(sip_has_feature(sip->sip_supported, "100rel")); nta_incoming_bind(irq, test_for_ack, ag); nta_incoming_treply(irq, SIP_100_TRYING, TAG_END()); nta_agent_set_params(ag->ag_agent, NTATAG_DEBUG_DROP_PROB(ag->ag_drop), TAG_END()); ag->ag_reliable = nta_reliable_treply(irq, NULL, NULL, SIP_183_SESSION_PROGRESS, SIPTAG_CONTENT_TYPE(ag->ag_content_type), SIPTAG_PAYLOAD(ag->ag_payload), SIPTAG_CONTACT(ag->ag_m_alice), TAG_END()); TEST_1(ag->ag_reliable); ag->ag_reliable = nta_reliable_treply(irq, NULL, NULL, 184, "Next", SIPTAG_CONTACT(ag->ag_m_alice), TAG_END()); TEST_1(ag->ag_reliable); ag->ag_reliable = nta_reliable_treply(irq, NULL, NULL, 185, "Last", SIPTAG_CONTACT(ag->ag_m_alice), TAG_END()); TEST_1(ag->ag_reliable); TEST(nta_incoming_treply(irq, SIP_200_OK, TAG_END()), 0); ag->ag_irq = irq; return 0; } if (sip->sip_request->rq_method == sip_method_bye) { leg_zap(ag, leg); } if(sip) return 200; END(); } /* * Test establishing a call with an early dialog / 100 rel / timeout * * Alice sends a INVITE to Bob, then Bob sends 183, 184, 185, and 200. * Bob sends BYE, Alice 200. * * See bug #467. */ int test_fix_467(agent_t *ag) { sip_content_type_t *ct = ag->ag_content_type; sip_payload_t *sdp = ag->ag_payload; nta_leg_t *old_leg; BEGIN(); ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, alice_leg_callback2, ag, SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), TAG_END()); TEST_1(ag->ag_alice_leg); TEST_1(nta_leg_tag(ag->ag_alice_leg, NULL)); ag->ag_bob_leg = NULL; { invite_client_t ic[1] = {{{{ ag, "Call 5", NULL, checks_for_100rel, invite_client_deinit }}}}; client_t *ctx = ic->ic_client; /* Send INVITE */ nta_leg_bind(ag->ag_server_leg, bob_leg_callback2, ag); ag->ag_expect_leg = ag->ag_server_leg; ctx->c_orq = nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_alice_leg, outgoing_callback, ic->ic_client, ag->ag_obp, SIP_METHOD_INVITE, (url_string_t *)ag->ag_m_bob->m_url, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_CONTACT(ag->ag_m_alice), SIPTAG_REQUIRE_STR("100rel"), SIPTAG_CONTENT_TYPE(ct), SIPTAG_PAYLOAD(sdp), TAG_END()); TEST_1(!client_run(ctx, 200)); /*TEST(ag->ag_tag_status, 183);*/ TEST_P(ag->ag_latest_leg, ag->ag_server_leg); TEST_1(ag->ag_bob_leg != NULL); } old_leg = ag->ag_expect_leg = ag->ag_alice_leg; { client_t ctx[1] = {{ ag, "Hangup" }}; /* Send BYE from Bob to Alice */ ctx->c_orq = nta_outgoing_tcreate(ag->ag_bob_leg, outgoing_callback, ctx, NULL, SIP_METHOD_BYE, NULL, SIPTAG_SUBJECT_STR(ctx->c_name), SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), SIPTAG_CONTACT(ag->ag_m_alice), SIPTAG_CONTENT_TYPE(ct), SIPTAG_PAYLOAD(sdp), TAG_END()); TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, old_leg); TEST_P(ag->ag_alice_leg, NULL); } END(); /* nta_leg_destroy(ag->ag_bob_leg), ag->ag_bob_leg = NULL; ag->ag_latest_leg = NULL; ag->ag_call_leg = NULL; */ } #if HAVE_ALARM #include #include static RETSIGTYPE sig_alarm(int s) { fprintf(stderr, "%s: FAIL! test timeout!\n", name); exit(1); } #endif static char const nta_test_usage[] = "usage: %s OPTIONS\n" "where OPTIONS are\n" " -v | --verbose be verbose\n" " -a | --abort abort() on error\n" " -q | --quiet be quiet\n" " --expensive run expensive tests, too\n" " -1 quit on first error\n" " -l level set logging level (0 by default)\n" " -p uri specify uri of outbound proxy\n" " -m uri bind to local uri\n" " --attach print pid, wait for a debugger to be attached\n" #if HAVE_ALARM " --no-alarm don't ask for guard ALARM\n" #endif ; void usage(int exitcode) { fprintf(stderr, nta_test_usage, name); exit(exitcode); } #if HAVE_OPEN_C int posix_main(int argc, char *argv[]); int main(int argc, char *argv[]) { int retval; tstflags |= tst_verbatim; su_log_set_level(su_log_default, 9); su_log_set_level(nta_log, 9); su_log_set_level(tport_log, 9); retval = posix_main(argc, argv); sleep(7); return retval; } #define main posix_main #endif int main(int argc, char *argv[]) { int retval = 0, quit_on_single_failure = 0; int i, o_attach = 0, o_alarm = 1; agent_t ag[1] = {{ { SU_HOME_INIT(ag) }, 0, NULL }}; expensive_checks = getenv("EXPENSIVE_CHECKS") != NULL; for (i = 1; argv[i]; i++) { if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) tstflags |= tst_verbatim; else if (strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "--abort") == 0) tstflags |= tst_abort; else if (strcmp(argv[i], "-q") == 0 || strcmp(argv[i], "--quiet") == 0) tstflags &= ~tst_verbatim; else if (strcmp(argv[i], "--expensive") == 0) expensive_checks = 1; else if (strcmp(argv[i], "-1") == 0) quit_on_single_failure = 1; else if (strncmp(argv[i], "-l", 2) == 0) { int level = 3; char *rest = NULL; if (argv[i][2]) level = strtol(argv[i] + 2, &rest, 10); else if (argv[i + 1]) level = strtol(argv[i + 1], &rest, 10), i++; else level = 3, rest = ""; if (rest == NULL || *rest) usage(1); su_log_set_level(nta_log, level); su_log_set_level(tport_log, level); } else if (strncmp(argv[i], "-p", 2) == 0) { if (argv[i][2]) ag->ag_obp = (url_string_t *)(argv[i] + 2); else if (argv[i + 1]) ag->ag_obp = (url_string_t *)(argv[++i]); else usage(1); } else if (strncmp(argv[i], "-m", 2) == 0) { if (argv[i][2]) ag->ag_m = argv[i] + 2; else if (argv[i + 1]) ag->ag_m = argv[++i]; else usage(1); } else if (strcmp(argv[i], "--attach") == 0) { o_attach = 1; } else if (strcmp(argv[i], "--no-alarm") == 0) { o_alarm = 0; } else if (strcmp(argv[i], "-") == 0) { i++; break; } else if (argv[i][0] != '-') { break; } else usage(1); } if (o_attach) { char line[10], *got; printf("nua_test: pid %u\n", getpid()); printf("\n"); got = fgets(line, sizeof line, stdin); (void)got; } #if HAVE_ALARM else if (o_alarm) { alarm(60); signal(SIGALRM, sig_alarm); } #endif su_init(); if (!(TSTFLAGS & tst_verbatim)) { su_log_soft_set_level(nta_log, 0); su_log_soft_set_level(tport_log, 0); } #define SINGLE_FAILURE_CHECK() \ do { fflush(stdout); \ if (retval && quit_on_single_failure) { su_deinit(); return retval; } \ } while(0) retval |= test_init(ag, argv[i]); SINGLE_FAILURE_CHECK(); if (retval == 0) { retval |= test_bad_messages(ag); SINGLE_FAILURE_CHECK(); retval |= test_reinit(ag); SINGLE_FAILURE_CHECK(); retval |= test_merging(ag); SINGLE_FAILURE_CHECK(); retval |= test_tports(ag); SINGLE_FAILURE_CHECK(); retval |= test_destroy_incoming(ag); SINGLE_FAILURE_CHECK(); retval |= test_resolv(ag, argv[i]); SINGLE_FAILURE_CHECK(); retval |= test_routing(ag); SINGLE_FAILURE_CHECK(); retval |= test_dialog(ag); SINGLE_FAILURE_CHECK(); retval |= test_call(ag); SINGLE_FAILURE_CHECK(); retval |= test_prack(ag); SINGLE_FAILURE_CHECK(); retval |= test_fix_467(ag); SINGLE_FAILURE_CHECK(); } s2_fast_forward(64000, ag->ag_root); retval |= test_deinit(ag); fflush(stdout); su_home_deinit(ag->ag_home); su_deinit(); return retval; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nta/test_nta_api.c000066400000000000000000001244421223300710500231610ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@internal * @CFILE test_nta_api.c * * Test functions for NTA. * * @author Pekka Pessi * * @date Created: Tue Aug 21 15:18:26 2001 ppessi */ #include "config.h" typedef struct agent_t agent_t; #define SU_ROOT_MAGIC_T agent_t #include #include #define NTA_AGENT_MAGIC_T agent_t #define NTA_LEG_MAGIC_T agent_t #define NTA_OUTGOING_MAGIC_T agent_t #define NTA_INCOMING_MAGIC_T agent_t #define NTA_RELIABLE_MAGIC_T agent_t #include "sofia-sip/nta.h" #include "nta_internal.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern su_log_t nta_log[]; extern su_log_t tport_log[]; int tstflags = 0; #define TSTFLAGS tstflags char const name[] = "test_nta_api"; #include #if HAVE_FUNC #elif HAVE_FUNCTION #define __func__ __FUNCTION__ #else #define __func__ name #endif #define NONE ((void *)-1) struct sigcomp_compartment; struct agent_t { su_home_t ag_home[1]; int ag_flags; su_root_t *ag_root; msg_mclass_t *ag_mclass; nta_agent_t *ag_agent; nta_leg_t *ag_default_leg; /**< Leg for rest */ nta_leg_t *ag_server_leg; /**< Leg for ;methods=;events= */ unsigned ag_drop; nta_outgoing_t *ag_orq; int ag_status; msg_t *ag_response; /* Server side */ nta_incoming_t *ag_irq; sip_contact_t const *ag_contact; sip_from_t *ag_alice; sip_to_t *ag_bob; sip_contact_t *ag_m_alice; sip_contact_t *ag_m_bob; sip_contact_t *ag_aliases; nta_leg_t *ag_alice_leg; nta_leg_t *ag_bob_leg; msg_t *ag_request; nta_leg_t *ag_expect_leg; nta_leg_t *ag_latest_leg; nta_leg_t *ag_call_leg; nta_leg_t *ag_tag_remote; /**< If this is set, outgoing_callback() * tags it with the tag from remote. */ int ag_tag_status; /**< Which response established dialog */ msg_param_t ag_call_tag; /**< Tag used to establish dialog */ nta_reliable_t *ag_reliable; sip_via_t *ag_out_via; /**< Outgoing via */ sip_via_t *ag_in_via; /**< Incoming via */ sip_content_type_t *ag_content_type; sip_payload_t *ag_payload; msg_t *ag_probe_msg; }; static int incoming_callback_1(agent_t *ag, nta_incoming_t *irq, sip_t const *sip) { return 0; } static int incoming_callback_2(agent_t *ag, nta_incoming_t *irq, sip_t const *sip) { return 0; } int agent_callback(agent_t *ag, nta_agent_t *nta, msg_t *msg, sip_t *sip) { msg_destroy(msg); return 0; } int leg_callback(agent_t *ag, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip) { BEGIN(); msg_t *msg; char const *tag; if (tstflags & tst_verbatim) { printf("%s: %s: %s " URL_PRINT_FORMAT " %s\n", name, __func__, sip->sip_request->rq_method_name, URL_PRINT_ARGS(sip->sip_request->rq_url), sip->sip_request->rq_version); } TEST_1(sip->sip_content_length); TEST_1(sip->sip_via); TEST_1(sip->sip_from && sip->sip_from->a_tag); TEST_VOID(nta_incoming_bind(irq, incoming_callback_1, ag)); TEST_P(nta_incoming_magic(irq, incoming_callback_1), ag); TEST_P(nta_incoming_magic(irq, incoming_callback_2), 0); TEST_1(tag = nta_incoming_tag(irq, "tag=foofaa")); TEST_S(nta_incoming_gettag(irq), tag); TEST_S(tag, "foofaa"); TEST_1(tag = nta_incoming_tag(irq, "foofaa")); TEST(nta_incoming_status(irq), 0); TEST(nta_incoming_method(irq), sip_method_message); TEST_S(nta_incoming_method_name(irq), "MESSAGE"); TEST_1(nta_incoming_url(irq) != NULL); TEST_1(nta_incoming_cseq(irq) != 0); TEST(nta_incoming_set_params(irq, TAG_END()), 0); TEST_1(msg = nta_incoming_getrequest(irq)); msg_destroy(msg); TEST_P(nta_incoming_getrequest_ackcancel(irq), NULL); TEST_P(nta_incoming_getresponse(irq), NULL); TEST(nta_incoming_treply(irq, SIP_100_TRYING, TAG_END()), 0); TEST_1(msg = nta_incoming_getresponse(irq)); msg_destroy(msg); msg = nta_msg_create(ag->ag_agent, 0); TEST(nta_incoming_complete_response(irq, msg, SIP_200_OK, TAG_END()), 0); TEST(nta_incoming_mreply(irq, msg), 0); END(); } int outgoing_callback(agent_t *ag, nta_outgoing_t *orq, sip_t const *sip) { BEGIN(); msg_t *msg; int status = sip->sip_status->st_status; if (tstflags & tst_verbatim) { printf("%s: %s: %s %03d %s\n", name, __func__, sip->sip_status->st_version, sip->sip_status->st_status, sip->sip_status->st_phrase); } ag->ag_status = status; if (status < 200) return 0; TEST_1(sip->sip_to && sip->sip_to->a_tag); /* Test API functions */ TEST(nta_outgoing_status(orq), status); TEST_1(nta_outgoing_request_uri(orq)); TEST_1(!nta_outgoing_route_uri(orq)); TEST(nta_outgoing_method(orq), sip_method_message); TEST_S(nta_outgoing_method_name(orq), "MESSAGE"); TEST(nta_outgoing_cseq(orq), sip->sip_cseq->cs_seq); TEST_1(nta_outgoing_delay(orq) < UINT_MAX); TEST_1(msg = nta_outgoing_getresponse(orq)); msg_destroy(msg); TEST_1(msg = nta_outgoing_getrequest(orq)); msg_destroy(msg); nta_outgoing_destroy(orq); /* Call it twice */ nta_outgoing_destroy(orq); ag->ag_orq = NULL; END(); } void nta_test_run(agent_t *ag) { time_t now = time(NULL); for (ag->ag_status = 0; ag->ag_status < 200;) { if (tstflags & tst_verbatim) { fputs(".", stdout); fflush(stdout); } su_root_step(ag->ag_root, 500L); if (!getenv("NTA_TEST_DEBUG") && time(NULL) > now + 5) { fprintf(stderr, "nta_test_run: timeout\n"); return; } } } int api_test_init(agent_t *ag) { BEGIN(); char const *contact = NULL; if (getenv("SIPCONTACT")) contact = getenv("SIPCONTACT"); if (contact == NULL || contact[0] == '\0') contact = "sip:0.0.0.0:*;comp=sigcomp"; TEST_1(ag->ag_root = su_root_create(ag)); TEST_1(ag->ag_mclass = msg_mclass_clone(sip_default_mclass(), 0, 0)); /* Create agent */ TEST_1(ag->ag_agent = nta_agent_create(ag->ag_root, (url_string_t *)contact, NULL, NULL, NTATAG_MCLASS(ag->ag_mclass), NTATAG_USE_TIMESTAMP(1), NTATAG_USE_NAPTR(0), NTATAG_USE_SRV(0), NTATAG_PRELOAD(2048), TAG_END())); /* Create a default leg */ TEST_1(ag->ag_default_leg = nta_leg_tcreate(ag->ag_agent, leg_callback, ag, NTATAG_NO_DIALOG(1), TAG_END())); { /* Initialize our headers */ sip_from_t from[1]; sip_to_t to[1]; sip_contact_t m[1]; sip_from_init(from); sip_to_init(to); sip_contact_init(m); TEST_1(ag->ag_contact = nta_agent_contact(ag->ag_agent)); *m->m_url = *ag->ag_contact->m_url; m->m_url->url_user = "bob"; TEST_1(ag->ag_m_bob = sip_contact_dup(ag->ag_home, m)); to->a_display = "Bob"; *to->a_url = *ag->ag_contact->m_url; to->a_url->url_user = "bob"; to->a_url->url_port = NULL; TEST_1(ag->ag_bob = sip_to_dup(ag->ag_home, to)); url_strip_transport(ag->ag_bob->a_url); *m->m_url = *ag->ag_contact->m_url; m->m_url->url_user = "alice"; TEST_1(ag->ag_m_alice = sip_contact_dup(ag->ag_home, m)); from->a_display = "Alice"; *from->a_url = *ag->ag_contact->m_url; from->a_url->url_user = "alice"; from->a_url->url_port = NULL; TEST_1(ag->ag_alice = sip_from_dup(ag->ag_home, from)); url_strip_transport(ag->ag_alice->a_url); } { char const data[] = "v=0\r\n" "o=- 425432 423412 IN IP4 127.0.0.1\r\n" "s= \r\n" "c=IN IP4 127.0.0.1\r\n" "m=5004 audio 8 0\r\n"; ag->ag_content_type = sip_content_type_make(ag->ag_home, "application/sdp"); ag->ag_payload = sip_payload_make(ag->ag_home, data); } { sip_contact_t *m; ag->ag_aliases = sip_contact_make(ag->ag_home, "sip:127.0.0.1, sip:localhost, sip:[::1]"); TEST_1(ag->ag_aliases); TEST_1(ag->ag_aliases->m_next); TEST_1(ag->ag_aliases->m_next->m_next); TEST_P(ag->ag_aliases->m_next->m_next->m_next, NULL); for (m = ag->ag_aliases; m; m = m->m_next) m->m_url->url_port = ag->ag_contact->m_url->url_port; TEST_1(m = sip_contact_dup(ag->ag_home, ag->ag_contact)); m->m_next = ag->ag_aliases; ag->ag_aliases = m; TEST(nta_agent_set_params(ag->ag_agent, NTATAG_ALIASES(ag->ag_aliases), NTATAG_REL100(1), NTATAG_UA(1), NTATAG_USE_NAPTR(1), NTATAG_USE_SRV(1), TAG_END()), 5); TEST(nta_agent_set_params(ag->ag_agent, NTATAG_ALIASES(ag->ag_aliases), NTATAG_DEFAULT_PROXY("sip:127.0.0.1"), TAG_END()), 2); TEST(nta_agent_set_params(ag->ag_agent, NTATAG_ALIASES(ag->ag_aliases), NTATAG_DEFAULT_PROXY(NULL), TAG_END()), 2); TEST(nta_agent_set_params(ag->ag_agent, NTATAG_DEFAULT_PROXY("tel:+35878008000"), TAG_END()), -1); } { url_t url[1]; /* Create the server leg */ *url = *ag->ag_aliases->m_url; url->url_user = "%"; TEST_1(ag->ag_server_leg = nta_leg_tcreate(ag->ag_agent, leg_callback, ag, NTATAG_NO_DIALOG(1), URLTAG_URL(url), TAG_END())); } END(); } int api_test_deinit(agent_t *ag) { BEGIN(); if (ag->ag_request) msg_destroy(ag->ag_request), ag->ag_request = NULL; if (ag->ag_response) msg_destroy(ag->ag_response), ag->ag_response = NULL; su_free(ag->ag_home, ag->ag_in_via), ag->ag_in_via = NULL; nta_leg_destroy(ag->ag_alice_leg); nta_leg_destroy(ag->ag_bob_leg); nta_leg_destroy(ag->ag_default_leg); nta_leg_destroy(ag->ag_server_leg); nta_agent_destroy(ag->ag_agent); su_root_destroy(ag->ag_root); free(ag->ag_mclass), ag->ag_mclass = NULL; END(); } static int api_test_destroy(agent_t *ag) { nta_agent_t *nta; su_root_t *root; su_home_t home[1]; nta_outgoing_t *orq; nta_leg_t *leg; int i; BEGIN(); memset(home, 0, sizeof home); home->suh_size = sizeof home; su_home_init(home); TEST_1(root = su_root_create(NULL)); for (i = 0; i < 2; i++) { TEST_1(nta = nta_agent_create(root, (url_string_t *)"sip:*:*", NULL, NULL, TAG_END())); TEST_1(leg = nta_leg_tcreate(nta, NULL, NULL, NTATAG_NO_DIALOG(1), TAG_END())); /* This creates a delayed response message */ orq = nta_outgoing_tcreate(leg, outgoing_callback, ag, NULL, SIP_METHOD_MESSAGE, URL_STRING_MAKE("sip:foo.bar;transport=none"), SIPTAG_FROM_STR(""), SIPTAG_TO_STR(""), TAG_END()); TEST_1(orq); TEST_VOID(nta_outgoing_destroy(orq)); TEST_VOID(nta_leg_destroy(leg)); TEST_VOID(nta_agent_destroy(nta)); } TEST_VOID(su_root_destroy(root)); TEST_VOID(su_home_deinit(home)); END(); } /* Get and check parameters */ int api_test_params(agent_t *ag) { BEGIN(); nta_agent_t *nta; sip_contact_t const *aliases = (void *)-1; msg_mclass_t *mclass = (void *)-1; sip_contact_t const *contact = (void *)-1; url_string_t const *default_proxy = (void *)-1; void *smime = (void *)-1; unsigned blacklist = -1; unsigned debug_drop_prob = -1; unsigned max_forwards = -1; usize_t maxsize = -1; unsigned preload = -1; unsigned progress = -1; unsigned sip_t1 = -1; unsigned sip_t2 = -1; unsigned sip_t4 = -1; unsigned timer_c = -1; unsigned udp_mtu = -1; int cancel_2543 = -1; int cancel_487 = -1; int client_rport = -1; int extra_100 = -1; int merge_482 = -1; int pass_100 = -1; int pass_408 = -1; int rel100 = -1; int server_rport = -1; int stateless = -1; int tag_3261 = -1; int timeout_408 = -1; int ua = -1; int use_naptr = -1; int use_srv = -1; int use_timestamp = -1; int user_via = -1; char const *s = NONE; TEST_1(nta = nta_agent_create(ag->ag_root, (url_string_t *)"sip:*:*", NULL, NULL, TAG_END())); TEST(nta_agent_get_params(nta, NTATAG_ALIASES_REF(aliases), NTATAG_BLACKLIST_REF(blacklist), NTATAG_CANCEL_2543_REF(cancel_2543), NTATAG_CANCEL_487_REF(cancel_487), NTATAG_CLIENT_RPORT_REF(client_rport), NTATAG_CONTACT_REF(contact), NTATAG_DEBUG_DROP_PROB_REF(debug_drop_prob), NTATAG_DEFAULT_PROXY_REF(default_proxy), NTATAG_EXTRA_100_REF(extra_100), NTATAG_MAXSIZE_REF(maxsize), NTATAG_MAX_FORWARDS_REF(max_forwards), NTATAG_MCLASS_REF(mclass), NTATAG_MERGE_482_REF(merge_482), NTATAG_PASS_100_REF(pass_100), NTATAG_PASS_408_REF(pass_408), NTATAG_PRELOAD_REF(preload), NTATAG_PROGRESS_REF(progress), NTATAG_REL100_REF(rel100), NTATAG_SERVER_RPORT_REF(server_rport), NTATAG_SIP_T1_REF(sip_t1), NTATAG_SIP_T2_REF(sip_t2), NTATAG_SIP_T4_REF(sip_t4), NTATAG_SMIME_REF(smime), NTATAG_STATELESS_REF(stateless), NTATAG_TAG_3261_REF(tag_3261), NTATAG_TIMEOUT_408_REF(timeout_408), NTATAG_TIMER_C_REF(timer_c), NTATAG_UA_REF(ua), NTATAG_UDP_MTU_REF(udp_mtu), NTATAG_USER_VIA_REF(user_via), NTATAG_USE_NAPTR_REF(use_naptr), NTATAG_USE_SRV_REF(use_srv), NTATAG_USE_TIMESTAMP_REF(use_timestamp), TAG_END()), /* Number of parameters */ 33); TEST_P(mclass, sip_default_mclass()); TEST_P(aliases, NULL); TEST_1(contact != (void *)-1 && contact != NULL); TEST_1(default_proxy == NULL); TEST_1(smime == NULL); TEST_1(blacklist != (unsigned)-1); TEST(debug_drop_prob, 0); TEST_1(max_forwards >= 20); TEST_1(maxsize >= 65536); TEST_1(preload != (unsigned)-1); TEST_1(progress <= 60 * 1000); TEST(sip_t1, NTA_SIP_T1); TEST(sip_t2, NTA_SIP_T2); TEST(sip_t4, NTA_SIP_T4); TEST_1(timer_c > 180 * 1000); TEST(udp_mtu, 1300); TEST_1(cancel_2543 != -1); TEST_1(cancel_487 != -1); TEST_1(client_rport != -1); TEST_1(extra_100 != -1); TEST_1(merge_482 != -1); TEST_1(pass_100 != -1); TEST_1(pass_408 != -1); TEST_1(rel100 != -1); TEST_1(server_rport != -1); TEST_1(stateless == 0); TEST_1(timeout_408 != -1); TEST_1(ua == 0); TEST_1(use_naptr != -1); TEST_1(use_srv != -1); TEST_1(use_timestamp != -1); TEST_1(user_via == 0); TEST(nta_agent_set_params(NULL, NTATAG_PRELOAD(2048), TAG_END()), -1); TEST(nta_agent_get_params(NULL, NTATAG_PRELOAD_REF(preload), TAG_END()), -1); TEST(nta_agent_set_params(nta, NTATAG_PRELOAD(2048), TAG_END()), 1); TEST(nta_agent_get_params(nta, NTATAG_PRELOAD_REF(preload), TAG_END()), 1); TEST(preload, 2048); TEST(nta_agent_set_params(nta, NTATAG_SIGCOMP_OPTIONS("sip"), TAG_END()), 1); TEST(nta_agent_set_params(nta, NTATAG_SIGCOMP_OPTIONS(","), TAG_END()), -1); TEST(nta_agent_set_params(nta, NTATAG_SIGCOMP_OPTIONS("sip;dms=16384"), TAG_END()), 1); s = NONE; TEST(nta_agent_get_params(nta, NTATAG_SIGCOMP_OPTIONS_REF(s), TAG_END()), 1); TEST_S(s, "sip;dms=16384"); TEST_VOID(nta_agent_destroy(nta)); END(); } int api_test_stats(agent_t *ag) { BEGIN(); nta_agent_t *nta; usize_t irq_hash = -1, orq_hash = -1, leg_hash = -1; usize_t recv_msg = -1, sent_msg = -1; usize_t recv_request = -1, recv_response = -1; usize_t bad_message = -1, bad_request = -1, bad_response = -1; usize_t drop_request = -1, drop_response = -1; usize_t client_tr = -1, server_tr = -1, dialog_tr = -1; usize_t acked_tr = -1, canceled_tr = -1; usize_t trless_request = -1, trless_to_tr = -1, trless_response = -1; usize_t trless_200 = -1, merged_request = -1; usize_t sent_request = -1, sent_response = -1; usize_t retry_request = -1, retry_response = -1, recv_retry = -1; usize_t tout_request = -1, tout_response = -1; TEST_1(nta = nta_agent_create(ag->ag_root, (url_string_t *)"sip:*:*", NULL, NULL, TAG_END())); TEST(nta_agent_get_stats(NULL, NTATAG_S_TOUT_REQUEST_REF(tout_request), NTATAG_S_TOUT_RESPONSE_REF(tout_response), TAG_END()), -1); TEST(nta_agent_get_stats(nta, NTATAG_S_IRQ_HASH_REF(irq_hash), NTATAG_S_ORQ_HASH_REF(orq_hash), NTATAG_S_LEG_HASH_REF(leg_hash), NTATAG_S_RECV_MSG_REF(recv_msg), NTATAG_S_SENT_MSG_REF(sent_msg), NTATAG_S_RECV_REQUEST_REF(recv_request), NTATAG_S_RECV_RESPONSE_REF(recv_response), NTATAG_S_BAD_MESSAGE_REF(bad_message), NTATAG_S_BAD_REQUEST_REF(bad_request), NTATAG_S_BAD_RESPONSE_REF(bad_response), NTATAG_S_DROP_REQUEST_REF(drop_request), NTATAG_S_DROP_RESPONSE_REF(drop_response), NTATAG_S_CLIENT_TR_REF(client_tr), NTATAG_S_SERVER_TR_REF(server_tr), NTATAG_S_DIALOG_TR_REF(dialog_tr), NTATAG_S_ACKED_TR_REF(acked_tr), NTATAG_S_CANCELED_TR_REF(canceled_tr), NTATAG_S_TRLESS_REQUEST_REF(trless_request), NTATAG_S_TRLESS_TO_TR_REF(trless_to_tr), NTATAG_S_TRLESS_RESPONSE_REF(trless_response), NTATAG_S_TRLESS_200_REF(trless_200), NTATAG_S_MERGED_REQUEST_REF(merged_request), NTATAG_S_SENT_REQUEST_REF(sent_request), NTATAG_S_SENT_RESPONSE_REF(sent_response), NTATAG_S_RETRY_REQUEST_REF(retry_request), NTATAG_S_RETRY_RESPONSE_REF(retry_response), NTATAG_S_RECV_RETRY_REF(recv_retry), NTATAG_S_TOUT_REQUEST_REF(tout_request), NTATAG_S_TOUT_RESPONSE_REF(tout_response), TAG_END()), 29); TEST_1(irq_hash == HTABLE_MIN_SIZE); TEST_1(orq_hash == HTABLE_MIN_SIZE); TEST_1(leg_hash == HTABLE_MIN_SIZE); TEST_1(recv_msg == 0); TEST_1(sent_msg == 0); TEST_1(recv_request == 0); TEST_1(recv_response == 0); TEST_1(bad_message == 0); TEST_1(bad_request == 0); TEST_1(bad_response == 0); TEST_1(drop_request == 0); TEST_1(drop_response == 0); TEST_1(client_tr == 0); TEST_1(server_tr == 0); TEST_1(dialog_tr == 0); TEST_1(acked_tr == 0); TEST_1(canceled_tr == 0); TEST_1(trless_request == 0); TEST_1(trless_to_tr == 0); TEST_1(trless_response == 0); TEST_1(trless_200 == 0); TEST_1(merged_request == 0); TEST_1(sent_request == 0); TEST_1(sent_response == 0); TEST_1(retry_request == 0); TEST_1(retry_response == 0); TEST_1(recv_retry == 0); TEST_1(tout_request == 0); TEST_1(tout_response == 0); TEST_VOID(nta_agent_destroy(nta)); END(); } /* Test handling transports */ int api_test_tport(agent_t *ag) { sip_via_t const *v; url_t url[1]; BEGIN(); nta_agent_t *agent; sip_contact_t const *m; *url = *ag->ag_contact->m_url; url->url_port = "*"; url->url_params = "transport=tcp"; TEST_1(agent = nta_agent_create(ag->ag_root, NONE, NULL, NULL, TAG_END())); TEST_1(!nta_agent_via(agent)); TEST_1(!nta_agent_public_via(agent)); TEST_1(!nta_agent_contact(agent)); TEST_1(nta_agent_add_tport(agent, (url_string_t *)url, TAG_END()) == 0); TEST_1(v = nta_agent_via(agent)); TEST_1(!v->v_next); TEST(!su_casematch(v->v_protocol, sip_transport_tcp), 0); TEST_1(m = nta_agent_contact(agent)); TEST_S(m->m_url->url_params, "transport=tcp"); TEST_1(nta_agent_add_tport(agent, (url_string_t *)url, TPTAG_SERVER(0), TAG_END()) == 0); TEST_1(v = nta_agent_public_via(agent)); TEST_1(!v->v_next); TEST(!su_casematch(v->v_protocol, sip_transport_tcp), 0); TEST_1(host_has_domain_invalid(v->v_host)); TEST_1(m = nta_agent_contact(agent)); TEST_S(m->m_url->url_params, "transport=tcp"); url->url_params = "transport=udp"; TEST_1(nta_agent_add_tport(agent, (url_string_t *)url, TAG_END()) == 0); TEST_1(v = nta_agent_via(agent)); TEST_1(v = v->v_next); TEST(!su_casematch(v->v_protocol, sip_transport_udp), 0); TEST_VOID(nta_agent_destroy(agent)); TEST_1(agent = nta_agent_create(ag->ag_root, NONE, NULL, NULL, TAG_END())); TEST_1(nta_agent_add_tport(agent, (url_string_t *)url, TAG_END()) == 0); TEST_1(v = nta_agent_via(agent)); TEST_1(!v->v_next); TEST(!su_casematch(v->v_protocol, sip_transport_udp), 0); TEST_1(m = nta_agent_contact(agent)); TEST_S(m->m_url->url_params, "transport=udp"); TEST_VOID(nta_agent_destroy(agent)); url->url_params = "transport=tcp,udp"; TEST_1(agent = nta_agent_create(ag->ag_root, NONE, NULL, NULL, TAG_END())); TEST_1(nta_agent_add_tport(agent, (url_string_t *)url, TAG_END()) == 0); TEST_1(v = nta_agent_via(agent)); TEST(!su_casematch(v->v_protocol, sip_transport_tcp), 0); TEST_1(v = v->v_next); TEST(!su_casematch(v->v_protocol, sip_transport_udp), 0); TEST_1(m = nta_agent_contact(agent)); TEST_1(!m->m_url->url_params); TEST_VOID(nta_agent_destroy(agent)); url->url_params = NULL; TEST_1(agent = nta_agent_create(ag->ag_root, NONE, NULL, NULL, TAG_END())); TEST_1(nta_agent_add_tport(agent, (url_string_t *)url, TAG_END()) == 0); TEST_1(v = nta_agent_via(agent)); TEST(!su_casematch(v->v_protocol, sip_transport_udp), 0); TEST_1(v = v->v_next); TEST(!su_casematch(v->v_protocol, sip_transport_tcp), 0); TEST_1(m = nta_agent_contact(agent)); TEST_1(!m->m_url->url_params); TEST_VOID(nta_agent_destroy(agent)); END(); } static int api_test_dialogs(agent_t *ag) { BEGIN(); #if 0 { /* Test 0.1 * Send a message from default leg to default leg */ char const p_acid[] = "P-Access-Network-Info: IEEE-802.11g\n"; msg_t *msg; ag->ag_expect_leg = ag->ag_default_leg; TEST_1(ag->ag_orq = nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, ag->ag_obp, SIP_METHOD_MESSAGE, (url_string_t *)ag->ag_contact->m_url, SIPTAG_SUBJECT_STR("Test 0.1"), SIPTAG_FROM(ag->ag_alice), SIPTAG_TO(ag->ag_bob), SIPTAG_CONTACT(ag->ag_m_alice), SIPTAG_HEADER_STR(p_acid), TAG_END())); TEST(nta_outgoing_getresponse(ag->ag_orq), NULL); TEST_1(msg = nta_outgoing_getrequest(ag->ag_orq)); TEST(nta_outgoing_method(ag->ag_orq), sip_method_message); TEST_S(nta_outgoing_method_name(ag->ag_orq), "MESSAGE"); msg_destroy(msg); TEST(nta_outgoing_delay(ag->ag_orq), UINT_MAX); nta_test_run(ag); TEST(ag->ag_status, 200); TEST(ag->ag_orq, NULL); TEST(ag->ag_latest_leg, ag->ag_default_leg); TEST_1(ag->ag_request); nta_leg_bind(ag->ag_default_leg, leg_callback_200, ag); } #endif END(); } /* Test that NULL host and/or port fields of user supplied Via header are filled in automatically */ int api_test_user_via_fillin(agent_t *ag) { su_home_t home[1]; su_root_t *root; nta_agent_t *nta; nta_leg_t *leg; nta_outgoing_t *orq0, *orq1; msg_t *msg0, *msg1; sip_t *sip0, *sip1; sip_via_t *via0, *via1; sip_via_t via[1]; static char *via_params[] = { "param1=value1", "param2=value2" }; size_t i; BEGIN(); memset(home, 0, sizeof home); su_home_init(home); TEST_1(root = su_root_create(NULL)); TEST_1(nta = nta_agent_create(root, (url_string_t *)"sip:*:*", NULL, NULL, TAG_END())); TEST_1(leg = nta_leg_tcreate(nta, NULL, NULL, NTATAG_NO_DIALOG(1), TAG_END())); /* This creates a delayed response message */ orq0 = nta_outgoing_tcreate(leg, outgoing_callback, ag, NULL, SIP_METHOD_MESSAGE, URL_STRING_MAKE("sip:foo.bar;transport=none"), SIPTAG_FROM_STR(""), SIPTAG_TO_STR(""), TAG_END()); TEST_1(orq0); TEST_1(msg0 = nta_outgoing_getrequest(orq0)); TEST_1(sip0 = sip_object(msg0)); TEST_1(via0 = sip0->sip_via); /* create user Via template to be filled in by NTA */ sip_via_init(via); via->v_protocol = "*"; for (i = 0; i < sizeof(via_params) / sizeof(via_params[0]); i++) sip_via_add_param(home, via, via_params[i]); /* add param to the template */ /* This creates a delayed response message */ orq1 = nta_outgoing_tcreate(leg, outgoing_callback, ag, NULL, SIP_METHOD_MESSAGE, URL_STRING_MAKE("sip:foo.bar;transport=none"), SIPTAG_FROM_STR(""), SIPTAG_TO_STR(""), NTATAG_USER_VIA(1), SIPTAG_VIA(via), TAG_END()); TEST_1(orq1); TEST_1(msg1 = nta_outgoing_getrequest(orq1)); TEST_1(sip1 = sip_object(msg1)); TEST_1(via1 = sip1->sip_via); /* check that template has been filled correctly */ TEST_S(via0->v_protocol, via1->v_protocol); TEST_S(via0->v_host, via1->v_host); TEST_S(via0->v_port, via1->v_port); /* check that the parameter has been preserved */ for (i = 0; i < sizeof(via_params)/sizeof(via_params[0]); i++) TEST_S(via1->v_params[i], via_params[i]); TEST_VOID(nta_outgoing_destroy(orq0)); TEST_VOID(nta_outgoing_destroy(orq1)); TEST_VOID(nta_leg_destroy(leg)); TEST_VOID(nta_agent_destroy(nta)); TEST_VOID(su_root_destroy(root)); TEST_VOID(su_home_deinit(home)); END(); } int outgoing_default(agent_t *ag, nta_outgoing_t *orq, sip_t const *sip) { BEGIN(); msg_t *msg; int status = sip->sip_status->st_status; ag->ag_status = status; if (status < 200) return 0; /* Test API functions */ TEST(nta_outgoing_status(orq), status); TEST_1(!nta_outgoing_request_uri(orq)); TEST_1(!nta_outgoing_route_uri(orq)); TEST(nta_outgoing_method(orq), sip_method_invalid); TEST_S(nta_outgoing_method_name(orq), "*"); TEST(nta_outgoing_cseq(orq), 0); TEST_1(nta_outgoing_delay(orq) == UINT_MAX); TEST_1(msg = nta_outgoing_getresponse(orq)); if (ag->ag_response == NULL) ag->ag_response = msg; else msg_destroy(msg); TEST_1(!nta_outgoing_getrequest(orq)); END(); } /* Test default incoming and outgoing */ static int api_test_default(agent_t *ag) { BEGIN(); nta_agent_t *nta; nta_incoming_t *irq; nta_outgoing_t *orq; sip_via_t via[1]; su_nanotime_t nano; TEST_1(nta = ag->ag_agent); TEST_1(irq = nta_incoming_default(nta)); TEST_VOID(nta_incoming_bind(irq, incoming_callback_1, ag)); TEST_P(nta_incoming_magic(irq, incoming_callback_1), ag); TEST_P(nta_incoming_magic(irq, incoming_callback_2), 0); TEST_P(nta_incoming_tag(irq, NULL), NULL); TEST_P(nta_incoming_gettag(irq), NULL); TEST(nta_incoming_status(irq), 0); TEST(nta_incoming_method(irq), sip_method_invalid); TEST_S(nta_incoming_method_name(irq), "*"); TEST_P(nta_incoming_url(irq), NULL); TEST(nta_incoming_cseq(irq), 0); TEST(nta_incoming_received(irq, &nano), nano / 1000000000); TEST(nta_incoming_set_params(irq, TAG_END()), 0); TEST_P(nta_incoming_getrequest(irq), NULL); TEST_P(nta_incoming_getrequest_ackcancel(irq), NULL); TEST_P(nta_incoming_getresponse(irq), NULL); TEST(nta_incoming_complete_response(irq, NULL, SIP_200_OK, TAG_END()), -1); TEST(nta_incoming_treply(irq, SIP_200_OK, TAG_END()), -1); TEST(nta_incoming_mreply(irq, NULL), -1); TEST_VOID(nta_incoming_destroy(irq)); TEST_1(orq = nta_outgoing_default(nta, outgoing_default, ag)); TEST(nta_outgoing_status(orq), 0); TEST(nta_outgoing_method(orq), sip_method_invalid); TEST_S(nta_outgoing_method_name(orq), "*"); TEST(nta_outgoing_cseq(orq), 0); TEST(nta_outgoing_delay(orq), UINT_MAX); TEST_P(nta_outgoing_request_uri(orq), NULL); TEST_P(nta_outgoing_route_uri(orq), NULL); TEST_P(nta_outgoing_getresponse(orq), NULL); TEST_P(nta_outgoing_getrequest(orq), NULL); TEST_P(nta_outgoing_tagged(orq, NULL, NULL, NULL, NULL), NULL); TEST(nta_outgoing_cancel(orq), -1); TEST_P(nta_outgoing_tcancel(orq, NULL, NULL, TAG_END()), NULL); TEST_VOID(nta_outgoing_destroy(orq)); TEST_1(irq = nta_incoming_default(nta)); TEST_1(orq = nta_outgoing_default(nta, outgoing_default, ag)); via[0] = nta_agent_via(nta)[0]; via->v_next = NULL; TEST_1(nta_incoming_treply (irq, SIP_200_OK, SIPTAG_VIA(via), SIPTAG_CALL_ID_STR("oishciucnkrcoihciunskcisj"), SIPTAG_CSEQ_STR("1 MESSAGE"), SIPTAG_FROM_STR("Arska ;tag=aiojcidscd0i"), SIPTAG_TO_STR("Jaska ;tag=iajf8wru"), TAG_END()) == 0); for (ag->ag_status = 0; ag->ag_status < 200; ) { su_root_step(ag->ag_root, 200); } TEST(nta_outgoing_status(orq), 0); TEST_VOID(nta_outgoing_destroy(orq)); TEST_VOID(nta_incoming_destroy(irq)); END(); } /** Test API for errors */ static int api_test_errors(agent_t *ag) { nta_agent_t *nta; su_root_t *root; su_home_t home[1]; su_nanotime_t nano; BEGIN(); memset(home, 0, sizeof home); home->suh_size = sizeof home; su_home_init(home); TEST_P(nta_agent_create(NULL, (url_string_t *)"sip:*:*", NULL, NULL, TAG_END()), NULL); TEST_1(root = su_root_create(NULL)); TEST_P(nta_agent_create(root, (url_string_t *)"http://localhost:*/invalid/bind/url", NULL, NULL, TAG_END()), NULL); TEST_P(nta_agent_create(root, (url_string_t *)"sip:*:*;transport=XXX", NULL, NULL, TAG_END()), NULL); TEST_1(nta = nta_agent_create(root, (url_string_t *)"sip:*:*", NULL, NULL, TAG_END())); TEST_VOID(nta_agent_destroy(NULL)); TEST_VOID(nta_agent_destroy(nta)); TEST_1(nta = nta_agent_create(root, (url_string_t *)"sip:*:*", agent_callback, ag, TAG_END())); TEST_P(nta_agent_contact(NULL), NULL); TEST_P(nta_agent_via(NULL), NULL); TEST_S(nta_agent_version(nta), nta_agent_version(NULL)); TEST_P(nta_agent_magic(NULL), NULL); TEST_P(nta_agent_magic(nta), (void *)ag); TEST(nta_agent_add_tport(NULL, NULL, TAG_END()), -1); TEST_P(nta_agent_newtag(home, "tag=%s", NULL), NULL); TEST_1(nta_agent_newtag(home, "tag=%s", nta)); { msg_t *msg; TEST_1(nta_msg_create(NULL, 0) == NULL); TEST(nta_msg_complete(NULL), -1); TEST_1(msg = nta_msg_create(nta, 0)); TEST(nta_msg_complete(msg), -1); TEST(nta_msg_request_complete(msg, NULL, sip_method_unknown, "FOO", NULL), -1); TEST(nta_is_internal_msg(NULL), 0); TEST(nta_is_internal_msg(msg), 0); TEST_1(msg_set_flags(msg, NTA_INTERNAL_MSG)); TEST(nta_is_internal_msg(msg), 1); TEST_VOID(msg_destroy(msg)); } TEST_P(nta_leg_tcreate(NULL, NULL, NULL, TAG_END()), NULL); TEST_VOID(nta_leg_destroy(NULL)); TEST_P(nta_leg_magic(NULL, NULL), NULL); TEST_VOID(nta_leg_bind(NULL, NULL, NULL)); TEST_P(nta_leg_tag(NULL, "fidsafsa"), NULL); TEST_P(nta_leg_rtag(NULL, "fidsafsa"), NULL); TEST_P(nta_leg_get_tag(NULL), NULL); TEST(nta_leg_client_route(NULL, NULL, NULL), -1); TEST(nta_leg_server_route(NULL, NULL, NULL), -1); TEST_P(nta_leg_by_uri(NULL, NULL), NULL); TEST_P(nta_leg_by_dialog(NULL, NULL, NULL, NULL, NULL, NULL, NULL), NULL); TEST_P(nta_leg_by_dialog(nta, NULL, NULL, NULL, NULL, NULL, NULL), NULL); TEST_P(nta_leg_make_replaces(NULL, NULL, 1), NULL); TEST_P(nta_leg_by_replaces(NULL, NULL), NULL); TEST_P(nta_incoming_create(NULL, NULL, NULL, NULL, TAG_END()), NULL); TEST_P(nta_incoming_create(nta, NULL, NULL, NULL, TAG_END()), NULL); TEST_VOID(nta_incoming_bind(NULL, NULL, NULL)); TEST_P(nta_incoming_magic(NULL, NULL), NULL); TEST_P(nta_incoming_find(NULL, NULL, NULL), NULL); TEST_P(nta_incoming_find(nta, NULL, NULL), NULL); TEST_P(nta_incoming_tag(NULL, NULL), NULL); TEST_P(nta_incoming_gettag(NULL), NULL); TEST(nta_incoming_status(NULL), 400); TEST(nta_incoming_method(NULL), sip_method_invalid); TEST_P(nta_incoming_method_name(NULL), NULL); TEST_P(nta_incoming_url(NULL), NULL); TEST(nta_incoming_cseq(NULL), 0); TEST(nta_incoming_received(NULL, &nano), 0); TEST64(nano, 0); TEST(nta_incoming_set_params(NULL, TAG_END()), -1); TEST_P(nta_incoming_getrequest(NULL), NULL); TEST_P(nta_incoming_getrequest_ackcancel(NULL), NULL); TEST_P(nta_incoming_getresponse(NULL), NULL); TEST(nta_incoming_complete_response(NULL, NULL, 800, "foo", TAG_END()), -1); TEST(nta_incoming_treply(NULL, SIP_200_OK, TAG_END()), -1); TEST(nta_incoming_mreply(NULL, NULL), -1); TEST_VOID(nta_incoming_destroy(NULL)); TEST_P(nta_outgoing_tcreate(NULL, outgoing_callback, ag, URL_STRING_MAKE("sip:localhost"), SIP_METHOD_MESSAGE, URL_STRING_MAKE("sip:localhost"), TAG_END()), NULL); TEST_P(nta_outgoing_mcreate(NULL, outgoing_callback, ag, URL_STRING_MAKE("sip:localhost"), NULL, TAG_END()), NULL); TEST_P(nta_outgoing_default(NULL, NULL, NULL), NULL); TEST(nta_outgoing_status(NULL), 500); TEST(nta_outgoing_method(NULL), sip_method_invalid); TEST_P(nta_outgoing_method_name(NULL), NULL); TEST(nta_outgoing_cseq(NULL), 0); TEST(nta_outgoing_delay(NULL), UINT_MAX); TEST_P(nta_outgoing_request_uri(NULL), NULL); TEST_P(nta_outgoing_route_uri(NULL), NULL); TEST_P(nta_outgoing_getresponse(NULL), NULL); TEST_P(nta_outgoing_getrequest(NULL), NULL); TEST_P(nta_outgoing_tagged(NULL, NULL, NULL, NULL, NULL), NULL); TEST(nta_outgoing_cancel(NULL), -1); TEST_P(nta_outgoing_tcancel(NULL, NULL, NULL, TAG_END()), NULL); TEST_VOID(nta_outgoing_destroy(NULL)); TEST_P(nta_outgoing_find(NULL, NULL, NULL, NULL), NULL); TEST_P(nta_outgoing_find(nta, NULL, NULL, NULL), NULL); TEST(nta_outgoing_status(NONE), 500); TEST(nta_outgoing_method(NONE), sip_method_invalid); TEST_P(nta_outgoing_method_name(NONE), NULL); TEST(nta_outgoing_cseq(NONE), 0); TEST(nta_outgoing_delay(NONE), UINT_MAX); TEST_P(nta_outgoing_request_uri(NONE), NULL); TEST_P(nta_outgoing_route_uri(NONE), NULL); TEST_P(nta_outgoing_getresponse(NONE), NULL); TEST_P(nta_outgoing_getrequest(NONE), NULL); TEST_P(nta_outgoing_tagged(NONE, NULL, NULL, NULL, NULL), NULL); TEST(nta_outgoing_cancel(NONE), -1); TEST_P(nta_outgoing_tcancel(NONE, NULL, NULL, TAG_END()), NULL); TEST_VOID(nta_outgoing_destroy(NONE)); TEST_P(nta_reliable_treply(NULL, NULL, NULL, 0, NULL, TAG_END()), NULL); TEST_P(nta_reliable_mreply(NULL, NULL, NULL, NULL), NULL); TEST_VOID(nta_reliable_destroy(NULL)); TEST_VOID(nta_agent_destroy(nta)); TEST_VOID(su_root_destroy(root)); TEST_VOID(su_home_deinit(home)); END(); } static int api_test_dialog_matching(agent_t *ag) { nta_agent_t *nta; su_root_t *root; su_home_t home[1]; nta_leg_t *leg, *dialog1, *dialog2, *dst, *defdst; sip_from_t *a1, *a2; sip_call_id_t *i; BEGIN(); memset(home, 0, sizeof home); home->suh_size = sizeof home; su_home_init(home); TEST_1(root = su_root_create(NULL)); TEST_1(nta = nta_agent_create(root, (url_string_t *)"sip:*:*", NULL, NULL, TAG_END())); TEST_1(dst = nta_leg_tcreate(nta, NULL, NULL, NTATAG_NO_DIALOG(1), URLTAG_URL("sip:joe@localhost"), TAG_END())); TEST_1(defdst = nta_leg_tcreate(nta, NULL, NULL, NTATAG_NO_DIALOG(1), TAG_END())); TEST_1(dialog1 = nta_leg_tcreate(nta, NULL, NULL, URLTAG_URL("sip:pc.al.us"), SIPTAG_CALL_ID_STR("foobarbaz"), /* local */ SIPTAG_FROM_STR(";tag=foo"), /* remote */ SIPTAG_TO_STR(""), TAG_END())); TEST_1(a1 = sip_from_make(home, ";tag=foo")); TEST_1(a2 = sip_from_make(home, ";tag=al")); TEST_1(i = sip_call_id_make(home, "foobarbaz")); TEST_1(dialog2 = nta_leg_tcreate(nta, NULL, NULL, SIPTAG_CALL_ID(i), /* local */ SIPTAG_FROM(a2), /* remote */ SIPTAG_TO(a1), TAG_END())); TEST_1(!nta_leg_by_dialog(nta, NULL, NULL, a1->a_tag, a1->a_url, a2->a_tag, a2->a_url)); TEST_1(!nta_leg_by_dialog(NULL, NULL, i, a1->a_tag, a1->a_url, a2->a_tag, a2->a_url)); TEST_1(!nta_leg_by_dialog(nta, (void *)"sip:no.such.url", i, a2->a_tag, a2->a_url, a1->a_tag, a1->a_url)); TEST_1(!nta_leg_by_dialog(nta, a2->a_url, i, a2->a_tag, a2->a_url, a1->a_tag, a1->a_url)); TEST_P(leg = nta_leg_by_dialog(nta, NULL, i, /* local */ a1->a_tag, a1->a_url, /* remote */ a2->a_tag, a2->a_url), dialog2); TEST_P(leg = nta_leg_by_dialog(nta, (void *)"sip:no.such.url", i, /* local */ a1->a_tag, a1->a_url, /* remote */ a2->a_tag, a2->a_url), dialog2); TEST_P(leg = nta_leg_by_dialog(nta, a2->a_url, i, a1->a_tag, a1->a_url, a2->a_tag, a2->a_url), dialog2); TEST_P(leg = nta_leg_by_dialog(nta, NULL, i, a2->a_tag, a2->a_url, a1->a_tag, a1->a_url), dialog1); TEST_P(leg = nta_leg_by_dialog(nta, (url_t *)"sip:pc.al.us", i, a2->a_tag, a2->a_url, a1->a_tag, a1->a_url), dialog1); /* local tag is required because there is tag */ TEST_P(leg = nta_leg_by_dialog(nta, (url_t *)"sip:pc.al.us", i, a2->a_tag, a2->a_url, "xyzzy", a1->a_url), NULL); /* local URI is ignored because we have tag */ TEST_P(leg = nta_leg_by_dialog(nta, (url_t *)"sip:pc.al.us", i, a2->a_tag, a2->a_url, a1->a_tag, a2->a_url), dialog1); /* remote tag is ignored because there is no tag */ TEST_P(leg = nta_leg_by_dialog(nta, (url_t *)"sip:pc.al.us", i, "xyzzy", a2->a_url, a1->a_tag, a1->a_url), dialog1); #if nomore /* remote url is required */ TEST_P(leg = nta_leg_by_dialog(nta, (url_t *)"sip:pc.al.us", i, a2->a_tag, a1->a_url, a1->a_tag, a1->a_url), NULL); #endif TEST_P(leg = nta_leg_by_dialog(nta, (url_t *)"sip:pc.al.us", i, a2->a_tag, NULL, a1->a_tag, a1->a_url), dialog1); /* local url is used if there is no local tag */ /* XXX - not really */ TEST_P(leg = nta_leg_by_dialog(nta, (url_t *)"sip:pc.al.us", i, a2->a_tag, a2->a_url, NULL, NULL), NULL); nta_leg_tag(dialog1, "al"); TEST_P(leg = nta_leg_by_dialog(nta, (url_t *)"sip:pc.al.us", i, a2->a_tag, a2->a_url, a1->a_tag, a1->a_url), dialog1); TEST_P(leg = nta_leg_by_dialog(nta, (url_t *)"sip:pc.al.us", i, a2->a_tag, a2->a_url, "xyzzy", a1->a_url), NULL); TEST_P(leg = nta_leg_by_dialog(nta, (url_t *)"sip:pc.al.us", i, a2->a_tag, a2->a_url, a1->a_tag, a1->a_url), dialog1); TEST_P(leg = nta_leg_by_dialog(nta, (url_t *)"sip:pc.al.us", i, a2->a_tag, a2->a_url, NULL, a1->a_url), NULL); nta_leg_destroy(defdst); nta_leg_destroy(dst); nta_leg_destroy(dialog1); nta_leg_destroy(dialog2); TEST_VOID(nta_agent_destroy(nta)); TEST_VOID(su_root_destroy(root)); TEST_VOID(su_home_deinit(home)); END(); } #if HAVE_ALARM #include #include static RETSIGTYPE sig_alarm(int s) { fprintf(stderr, "%s: FAIL! test timeout!\n", name); exit(1); } #endif static char const nta_test_api_usage[] = "usage: %s OPTIONS\n" "where OPTIONS are\n" " -v | --verbose be verbose\n" " -a | --abort abort() on error\n" " -q | --quiet be quiet\n" " -1 quit on first error\n" " -l level set logging level (0 by default)\n" " --attach print pid, wait for a debugger to be attached\n" #if HAVE_ALARM " --no-alarm don't ask for guard ALARM\n" #endif ; void usage(int exitcode) { fprintf(stderr, nta_test_api_usage, name); exit(exitcode); } int main(int argc, char *argv[]) { int retval = 0, quit_on_single_failure = 0; int i, o_attach = 0, o_alarm = 1; agent_t ag[1] = {{ { SU_HOME_INIT(ag) }, 0, NULL }}; for (i = 1; argv[i]; i++) { if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) tstflags |= tst_verbatim; else if (strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "--abort") == 0) tstflags |= tst_abort; else if (strcmp(argv[i], "-q") == 0 || strcmp(argv[i], "--quiet") == 0) tstflags &= ~tst_verbatim; else if (strcmp(argv[i], "-1") == 0) quit_on_single_failure = 1; else if (strncmp(argv[i], "-l", 2) == 0) { int level = 3; char *rest = NULL; if (argv[i][2]) level = strtol(argv[i] + 2, &rest, 10); else if (argv[i + 1]) level = strtol(argv[i + 1], &rest, 10), i++; else level = 3, rest = ""; if (rest == NULL || *rest) usage(1); su_log_set_level(nta_log, level); su_log_set_level(tport_log, level); } else if (strcmp(argv[i], "--attach") == 0) { o_attach = 1; } else if (strcmp(argv[i], "--no-alarm") == 0) { o_alarm = 0; } else if (strcmp(argv[i], "-") == 0) { i++; break; } else if (argv[i][0] != '-') { break; } else usage(1); } if (o_attach) { char *response, line[10]; printf("nua_test: pid %lu\n", (unsigned long)getpid()); printf("\n"); response = fgets(line, sizeof line, stdin); } #if HAVE_ALARM else if (o_alarm) { alarm(60); signal(SIGALRM, sig_alarm); } #endif su_init(); if (!(TSTFLAGS & tst_verbatim)) { su_log_soft_set_level(nta_log, 0); su_log_soft_set_level(tport_log, 0); } #define SINGLE_FAILURE_CHECK() \ do { fflush(stderr); fflush(stdout); \ if (retval && quit_on_single_failure) { su_deinit(); return retval; } \ } while(0) retval |= api_test_init(ag); fflush(stdout); SINGLE_FAILURE_CHECK(); if (retval == 0) { retval |= api_test_errors(ag); SINGLE_FAILURE_CHECK(); retval |= api_test_destroy(ag); SINGLE_FAILURE_CHECK(); retval |= api_test_params(ag); SINGLE_FAILURE_CHECK(); retval |= api_test_stats(ag); SINGLE_FAILURE_CHECK(); retval |= api_test_dialog_matching(ag); SINGLE_FAILURE_CHECK(); retval |= api_test_tport(ag); SINGLE_FAILURE_CHECK(); retval |= api_test_dialogs(ag); SINGLE_FAILURE_CHECK(); retval |= api_test_default(ag); SINGLE_FAILURE_CHECK(); retval |= api_test_user_via_fillin(ag); SINGLE_FAILURE_CHECK(); } retval |= api_test_deinit(ag); fflush(stdout); su_home_deinit(ag->ag_home); su_deinit(); return retval; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nth/000077500000000000000000000000001223300710500203435ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nth/ChangeLog000066400000000000000000000002751223300710500221210ustar00rootroot000000000000002005-08-10 Pekka Pessi * Added agent.pem and cafile.pem. 2005-07-18 Kai Vehmanen * Initial import of the module to Sofia-SIP tree. sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nth/Doxyfile.in000066400000000000000000000007321223300710500224600ustar00rootroot00000000000000PROJECT_NAME = "nth" OUTPUT_DIRECTORY = ../docs/html/nth INPUT = @srcdir@/nth.docs @srcdir@/sofia-sip @srcdir@ . @INCLUDE_PATH = . @srcdir@ @INCLUDE = ../docs/Doxyfile.conf TAGFILES += \ "../docs/su.doxytags=../su" \ "../docs/ipt.doxytags=../ipt" \ "../docs/bnf.doxytags=../bnf" \ "../docs/url.doxytags=../url" \ "../docs/msg.doxytags=../msg" \ "../docs/http.doxytags=../http" \ GENERATE_TAGFILE = ../docs/nth.doxytags ALIASES += sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nth/Makefile.am000066400000000000000000000033551223300710500224050ustar00rootroot00000000000000# # Makefile.am for nth module # # Copyright (C) 2005,2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # ---------------------------------------------------------------------- # Header paths INCLUDES = -I$(srcdir)/../ipt -I../ipt \ -I$(srcdir)/../iptsec -I../iptsec \ -I$(srcdir)/../msg -I../msg \ -I$(srcdir)/../bnf -I../bnf \ -I$(srcdir)/../http -I../http \ -I$(srcdir)/../sresolv -I../sresolv \ -I$(srcdir)/../tport -I../tport \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su # ---------------------------------------------------------------------- # Build targets noinst_LTLIBRARIES = libnth.la check_PROGRAMS = test_nth http-client http-server TESTS = test_nth CLEANFILES = tmp_sippasswd.* # ---------------------------------------------------------------------- # Rules for building the targets BUILT_SOURCES = nth_tag_ref.c nobase_include_sofia_HEADERS = \ sofia-sip/nth.h sofia-sip/nth_tag.h libnth_la_SOURCES = nth_client.c nth_server.c nth_tag.c nth_tag_ref.c COVERAGE_INPUT = $(libnth_la_SOURCES) $(include_sofia_HEADERS) LDADD = libnth.la \ ../iptsec/libiptsec.la \ ../ipt/libipt.la \ ../http/libhttp.la \ ../sresolv/libsresolv.la \ ../tport/libtport.la \ ../stun/libstun.la \ ../sresolv/libsresolv.la \ ../url/liburl.la \ ../msg/libmsg.la \ ../bnf/libbnf.la \ ../su/libsu.la test_nth_LDFLAGS = -static # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST = nth.docs $(BUILT_SOURCES) \ agent.pem cafile.pem # ---------------------------------------------------------------------- # Sofia specific rules include $(top_srcdir)/rules/sofia.am sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nth/Makefile.in000066400000000000000000001367701223300710500224260ustar00rootroot00000000000000# Makefile.in generated by automake 1.14 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 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 nth module # # Copyright (C) 2005,2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # ---------------------------------------------------------------------- # Header paths # common Makefile targets for libsofia-sip-ua(-glib) modules # ---------------------------------------------------------- # # run tests with valgrind # # Copyright (C) 2007 Nokia Corporation. # 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 file contains free software from Makefile.in by the Free Software # Foundation: # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 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. # # Generate lcov output # # # Copyright (C) 2007 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # # Silent compilation w/ Automake 1.9 or 1.10 # ---------------------------------------------------------- # Automake 1.9.6 is not clever enough to override suffix rules within if # if SOFIA_COMPILE_SILENT VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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@ check_PROGRAMS = test_nth$(EXEEXT) http-client$(EXEEXT) \ http-server$(EXEEXT) TESTS = test_nth$(EXEEXT) DIST_COMMON = $(top_srcdir)/rules/sofia.am \ $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am \ $(top_srcdir)/rules/silent.am $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(srcdir)/Doxyfile.in \ $(top_srcdir)/depcomp $(nobase_include_sofia_HEADERS) \ $(top_srcdir)/test-driver ChangeLog # Use with --enable-ndebug @NDEBUG_TRUE@am__append_1 = -DNDEBUG @HAVE_GENPNG_TRUE@@HAVE_LCOV_TRUE@am__append_2 = --frames @HAVE_LCOV_TRUE@am__append_3 = lcov lcov-report lcov-rerun clean-lcov covcheck uncovered subdir = libsofia-sip-ua/nth ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(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)/m4/sac-coverage.m4 \ $(top_srcdir)/m4/sac-general.m4 \ $(top_srcdir)/m4/sac-openssl.m4 \ $(top_srcdir)/m4/sac-pkg-config.m4 $(top_srcdir)/m4/sac-su2.m4 \ $(top_srcdir)/m4/sac-tport.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libsofia-sip-ua/su/sofia-sip/su_configure.h CONFIG_CLEAN_FILES = Doxyfile CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libnth_la_LIBADD = am_libnth_la_OBJECTS = nth_client.lo nth_server.lo nth_tag.lo \ nth_tag_ref.lo libnth_la_OBJECTS = $(am_libnth_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 = http_client_SOURCES = http-client.c http_client_OBJECTS = http-client.$(OBJEXT) http_client_LDADD = $(LDADD) am__DEPENDENCIES_1 = http_client_DEPENDENCIES = libnth.la ../iptsec/libiptsec.la \ ../ipt/libipt.la ../http/libhttp.la ../sresolv/libsresolv.la \ ../tport/libtport.la ../stun/libstun.la \ ../sresolv/libsresolv.la ../url/liburl.la ../msg/libmsg.la \ ../bnf/libbnf.la ../su/libsu.la $(am__DEPENDENCIES_1) http_server_SOURCES = http-server.c http_server_OBJECTS = http-server.$(OBJEXT) http_server_LDADD = $(LDADD) http_server_DEPENDENCIES = libnth.la ../iptsec/libiptsec.la \ ../ipt/libipt.la ../http/libhttp.la ../sresolv/libsresolv.la \ ../tport/libtport.la ../stun/libstun.la \ ../sresolv/libsresolv.la ../url/liburl.la ../msg/libmsg.la \ ../bnf/libbnf.la ../su/libsu.la $(am__DEPENDENCIES_1) test_nth_SOURCES = test_nth.c test_nth_OBJECTS = test_nth.$(OBJEXT) test_nth_LDADD = $(LDADD) test_nth_DEPENDENCIES = libnth.la ../iptsec/libiptsec.la \ ../ipt/libipt.la ../http/libhttp.la ../sresolv/libsresolv.la \ ../tport/libtport.la ../stun/libstun.la \ ../sresolv/libsresolv.la ../url/liburl.la ../msg/libmsg.la \ ../bnf/libbnf.la ../su/libsu.la $(am__DEPENDENCIES_1) test_nth_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(test_nth_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) -I$(top_builddir)/libsofia-sip-ua/su/sofia-sip depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f 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) 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 = $(libnth_la_SOURCES) http-client.c http-server.c test_nth.c DIST_SOURCES = $(libnth_la_SOURCES) http-client.c http-server.c \ test_nth.c 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)$(include_sofiadir)" HEADERS = $(nobase_include_sofia_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)` 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=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ 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_DRIVER = $(SHELL) $(top_srcdir)/test-driver 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) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CHECK_CFLAGS = @CHECK_CFLAGS@ CHECK_LIBS = @CHECK_LIBS@ COVERAGE_FLAGS = @COVERAGE_FLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CWFLAG = @CWFLAG@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV = @GCOV@ GENHTML = @GENHTML@ GENPNG = @GENPNG@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GLIB_VERSION = @GLIB_VERSION@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVER_SOFIA_SIP_UA_AGE = @LIBVER_SOFIA_SIP_UA_AGE@ LIBVER_SOFIA_SIP_UA_CUR = @LIBVER_SOFIA_SIP_UA_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_AGE = @LIBVER_SOFIA_SIP_UA_GLIB_AGE@ LIBVER_SOFIA_SIP_UA_GLIB_CUR = @LIBVER_SOFIA_SIP_UA_GLIB_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_REV = @LIBVER_SOFIA_SIP_UA_GLIB_REV@ LIBVER_SOFIA_SIP_UA_GLIB_SOVER = @LIBVER_SOFIA_SIP_UA_GLIB_SOVER@ LIBVER_SOFIA_SIP_UA_REV = @LIBVER_SOFIA_SIP_UA_REV@ LIBVER_SOFIA_SIP_UA_SOVER = @LIBVER_SOFIA_SIP_UA_SOVER@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MINGW_ENVIRONMENT = @MINGW_ENVIRONMENT@ MKDIR_P = @MKDIR_P@ MOSTLYCLEANFILES = @MOSTLYCLEANFILES@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ RANLIB = @RANLIB@ REPLACE_LIBADD = @REPLACE_LIBADD@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ SOFIA_GLIB_CFLAGS = @SOFIA_GLIB_CFLAGS@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ SOFIA_PLAT_CFLAGS = @SOFIA_PLAT_CFLAGS@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ VERSION = @VERSION@ VER_LIBSOFIA_SIP_UA_MAJOR_MINOR = @VER_LIBSOFIA_SIP_UA_MAJOR_MINOR@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ include_sofiadir = @include_sofiadir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ openssl_CFLAGS = @openssl_CFLAGS@ openssl_LIBS = @openssl_LIBS@ 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@ INCLUDES = -I$(srcdir)/../ipt -I../ipt \ -I$(srcdir)/../iptsec -I../iptsec \ -I$(srcdir)/../msg -I../msg \ -I$(srcdir)/../bnf -I../bnf \ -I$(srcdir)/../http -I../http \ -I$(srcdir)/../sresolv -I../sresolv \ -I$(srcdir)/../tport -I../tport \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su # ---------------------------------------------------------------------- # Build targets noinst_LTLIBRARIES = libnth.la CLEANFILES = tmp_sippasswd.* # ---------------------------------------------------------------------- # Rules for building the targets BUILT_SOURCES = nth_tag_ref.c nobase_include_sofia_HEADERS = \ sofia-sip/nth.h sofia-sip/nth_tag.h libnth_la_SOURCES = nth_client.c nth_server.c nth_tag.c nth_tag_ref.c COVERAGE_INPUT = $(libnth_la_SOURCES) $(include_sofia_HEADERS) LDADD = libnth.la ../iptsec/libiptsec.la ../ipt/libipt.la \ ../http/libhttp.la ../sresolv/libsresolv.la \ ../tport/libtport.la ../stun/libstun.la \ ../sresolv/libsresolv.la ../url/liburl.la ../msg/libmsg.la \ ../bnf/libbnf.la ../su/libsu.la $(openssl_LIBS) test_nth_LDFLAGS = -static # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST = nth.docs $(BUILT_SOURCES) \ agent.pem cafile.pem sofiasrcdir = ${top_srcdir}/libsofia-sip-ua sofiabuilddir = ${top_builddir}/libsofia-sip-ua AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(SOFIA_CFLAGS) \ $(openssl_CFLAGS) $(SOFIA_PLAT_CFLAGS) $(am__append_1) SOFIA_COVERAGE = $(COVERAGE_FLAGS) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files TAG_AWK = ${sofiasrcdir}/su/tag_dll.awk SUFFIXES = _tag_ref.c _tag.c INTERNAL_INCLUDES = \ -I${sofiasrcdir}/features -I${sofiabuilddir}/features \ -I${sofiasrcdir}/ipt -I${sofiabuilddir}/ipt \ -I${sofiasrcdir}/iptsec -I${sofiabuilddir}/iptsec \ -I${sofiasrcdir}/bnf -I${sofiabuilddir}/bnf \ -I${sofiasrcdir}/http -I${sofiabuilddir}/http \ -I${sofiasrcdir}/msg -I${sofiabuilddir}/msg \ -I${sofiasrcdir}/nth -I${sofiabuilddir}/nth \ -I${sofiasrcdir}/nta -I${sofiabuilddir}/nta \ -I${sofiasrcdir}/nea -I${sofiabuilddir}/nea \ -I${sofiasrcdir}/nua -I${sofiabuilddir}/nua \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sdp -I${sofiabuilddir}/sdp \ -I${sofiasrcdir}/sip -I${sofiabuilddir}/sip \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sresolv -I${sofiabuilddir}/sresolv \ -I${sofiasrcdir}/tport -I${sofiabuilddir}/tport \ -I${sofiasrcdir}/stun -I${sofiabuilddir}/stun \ -I${sofiasrcdir}/url -I${sofiabuilddir}/url \ -I${sofiasrcdir}/su -I${sofiabuilddir}/su PHONY = built-sources clean-built-sources $(am__append_3) VALGRIND = valgrind VALGRINDFLAGS = --tool=memcheck # Scripts @HAVE_LCOV_TRUE@LCOV_UNCOVERED = ${top_srcdir}/scripts/uncovered @HAVE_LCOV_TRUE@LCOV_REPORT = ${top_srcdir}/scripts/lcov-report # Report directory @HAVE_LCOV_TRUE@lcovdir = ${top_builddir}/lcov # Options @HAVE_LCOV_TRUE@GENHTML_OPTIONS = --show-details --legend \ @HAVE_LCOV_TRUE@ $(am__append_2) # Fancy shell command that expands to directory relative to top_builddir @HAVE_LCOV_TRUE@expand_subdir = `pwd|sed "s'\`cd ${top_builddir};pwd\`''"` SOFIA_SILENT = @ LIBTOOL_FLAGS = --silent # From Automake 1.9.6 - LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(LIBTOOL_FLAGS) \ $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) LINK = ${SOFIA_SILENT}test "${SOFIA_SILENT}" != @ || echo ' LINK $@'; \ $(LIBTOOL) --tag=CC --mode=link $(LIBTOOL_FLAGS) \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: _tag_ref.c _tag.c .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.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 libsofia-sip-ua/nth/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu libsofia-sip-ua/nth/Makefile .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.am: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): Doxyfile: $(top_builddir)/config.status $(srcdir)/Doxyfile.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ 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}; \ } libnth.la: $(libnth_la_OBJECTS) $(libnth_la_DEPENDENCIES) $(EXTRA_libnth_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libnth_la_OBJECTS) $(libnth_la_LIBADD) $(LIBS) 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 http-client$(EXEEXT): $(http_client_OBJECTS) $(http_client_DEPENDENCIES) $(EXTRA_http_client_DEPENDENCIES) @rm -f http-client$(EXEEXT) $(AM_V_CCLD)$(LINK) $(http_client_OBJECTS) $(http_client_LDADD) $(LIBS) http-server$(EXEEXT): $(http_server_OBJECTS) $(http_server_DEPENDENCIES) $(EXTRA_http_server_DEPENDENCIES) @rm -f http-server$(EXEEXT) $(AM_V_CCLD)$(LINK) $(http_server_OBJECTS) $(http_server_LDADD) $(LIBS) test_nth$(EXEEXT): $(test_nth_OBJECTS) $(test_nth_DEPENDENCIES) $(EXTRA_test_nth_DEPENDENCIES) @rm -f test_nth$(EXEEXT) $(AM_V_CCLD)$(test_nth_LINK) $(test_nth_OBJECTS) $(test_nth_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-client.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-server.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nth_client.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nth_server.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nth_tag.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nth_tag_ref.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_nth.Po@am__quote@ .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.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) '$<'` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-nobase_include_sofiaHEADERS: $(nobase_include_sofia_HEADERS) @$(NORMAL_INSTALL) @list='$(nobase_include_sofia_HEADERS)'; test -n "$(include_sofiadir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(include_sofiadir)'"; \ $(MKDIR_P) "$(DESTDIR)$(include_sofiadir)" || exit 1; \ fi; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo " $(MKDIR_P) '$(DESTDIR)$(include_sofiadir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(include_sofiadir)/$$dir"; }; \ echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(include_sofiadir)/$$dir'"; \ $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(include_sofiadir)/$$dir" || exit $$?; }; \ done uninstall-nobase_include_sofiaHEADERS: @$(NORMAL_UNINSTALL) @list='$(nobase_include_sofia_HEADERS)'; test -n "$(include_sofiadir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ dir='$(DESTDIR)$(include_sofiadir)'; $(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; \ else \ 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 $(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_nth.log: test_nth$(EXEEXT) @p='test_nth$(EXEEXT)'; \ b='test_nth'; \ $(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: $(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: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(include_sofiadir)"; 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: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) -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) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) 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) @HAVE_LCOV_FALSE@clean-local: clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libtool clean-local \ clean-noinstLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -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-nobase_include_sofiaHEADERS 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 -rf ./$(DEPDIR) -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-nobase_include_sofiaHEADERS .MAKE: all check check-am install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libtool clean-local \ 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-nobase_include_sofiaHEADERS 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 \ uninstall-nobase_include_sofiaHEADERS built-sources: $(BUILT_SOURCES) clean-built-sources: -rm -rf $(BUILT_SOURCES) $(BUILT_SOURCES:%=$(srcdir)/%) *_tag_ref.c: $(TAG_AWK) _tag.c_tag_ref.c: $(AWK) -f $(TAG_AWK) NODLL=1 $(TAG_DLL_FLAGS) REF=$@ $< ../bnf/libbnf.la ../http/libhttp.la ../ipt/libipt.la ../iptsec/libiptsec.la \ ../msg/libmsg.la ../nea/libnea.la ../nta/libnta.la ../nth/libnth.la \ ../nua/libnua.la ../sdp/libsdp.la ../sip/libsip.la ../soa/libsoa.la \ ../sresolv/libsresolv.la ../stun/libstun.la ../su/libsu.la \ ../tport/libtport.la ../url/liburl.la: cd $(@D) && $(MAKE) $(@F) checklib: $(noinst_LTLIBRARIES) $(check_LTLIBRARIES) valcheck: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) valcheck-am valcheck-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS # Run tests with valgrind in valcheck-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ list='$(TESTS)'; \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ if case $$tst in \ run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ $${dir}$$tst ;; \ esac ; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ echo "XPASS: $$tst"; \ ;; \ *) \ echo "PASS: $$tst"; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xfail=`expr $$xfail + 1`; \ echo "XFAIL: $$tst"; \ ;; \ *) \ failed=`expr $$failed + 1`; \ echo "FAIL: $$tst"; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ echo "SKIP: $$tst"; \ fi; \ done; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="All $$all tests passed"; \ else \ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all tests failed"; \ else \ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ skipped="($$skip tests were not run)"; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ report=""; \ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ report="Please report to $(PACKAGE_BUGREPORT)"; \ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ echo "$$dashes"; \ echo "$$banner"; \ test -z "$$skipped" || echo "$$skipped"; \ test -z "$$report" || echo "$$report"; \ echo "$$dashes"; \ test "$$failed" -eq 0; \ else :; fi # # Generate pretty coverage report (unless it has been already done) # @HAVE_LCOV_TRUE@lcov: @HAVE_LCOV_TRUE@ @-test -r ${lcovdir}${expand_subdir}/lcov.info \ @HAVE_LCOV_TRUE@ || make lcov-report # Generate pretty coverage report based on current coverage data @HAVE_LCOV_TRUE@lcov-report: @HAVE_LCOV_TRUE@ sub=${expand_subdir} odir=${lcovdir}$$sub ; \ @HAVE_LCOV_TRUE@ rm -rf $$odir ; mkdir -p $$odir && \ @HAVE_LCOV_TRUE@ ${LCOV_REPORT} ${GENHTML_OPTIONS} \ @HAVE_LCOV_TRUE@ --title "${PACKAGE_NAME}-${PACKAGE_VERSION}$$sub" \ @HAVE_LCOV_TRUE@ --srcdir=${srcdir} -o $$odir # Rerun checks before generating report @HAVE_LCOV_TRUE@lcov-rerun: clean-lcov @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) lcov-report # Show all uncovered lines as errors @HAVE_LCOV_TRUE@uncovered: @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} # Run check in current dir and show all uncovered lines as errors @HAVE_LCOV_TRUE@covcheck: @HAVE_LCOV_TRUE@ -find . -name "*.gcda" | xargs rm -rf @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} @HAVE_LCOV_TRUE@clean-local:: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true @HAVE_LCOV_TRUE@clean-lcov: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true # Rules from depend2.am (GENERIC = TRUE, SUBDIROBJ = FALSE, %FASTDEP% = am_fastdepCC) silenced. .c.o: @test "${SOFIA_SILENT}" != @ || echo ' COMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(COMPILE) -c -o $@ $< .c.lo: @test "${SOFIA_SILENT}" != @ || echo ' LTCOMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(LTCOMPILE) -c -o $@ $< # endif # ---------------------------------------------------------------------- # Sofia specific rules # 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: sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nth/agent.pem000066400000000000000000000040271223300710500221470ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIDPjCCAqegAwIBAgIHJQIBAZACBjANBgkqhkiG9w0BAQUFADBwMQswCQYDVQQG EwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTERMA8GA1UEBxMIU2FuIEpvc2UxDjAM BgNVBAoTBXNpcGl0MSkwJwYDVQQLEyBTaXBpdCBUZXN0IENlcnRpZmljYXRlIEF1 dGhvcml0eTAeFw0wMzEyMDMxODMwMjJaFw0wNjEyMDIxODMwMjJaMGUxCzAJBgNV BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMREwDwYDVQQHEwhTYW4gSm9zZTEO MAwGA1UEChMFc2lwaXQxHjAcBgNVBAMTFXBla2thLm5va2lhLnNpcGl0Lm5ldDCB nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsdJn/O6JoIC1I2iXOVJLQypmt9sN HmvB84853Qx9KS+xqP3U2nqNMnDQby6ZmTsRHNGAK5QuGugU11wocmYNP0/TQFaz KNLhNt0pMBOfpAV9vG6pCSkocObsUo2XFULPTEB/SzGcvE1G1em3XmwRfPA178y9 L2+sVNT5Vtt5KfMCAwEAAaOB7DCB6TAgBgNVHREEGTAXghVwZWtrYS5ub2tpYS5z aXBpdC5uZXQwCQYDVR0TBAIwADAdBgNVHQ4EFgQU1OjdL9cdA0NNbxPDQ9xZUZG6 NnIwgZoGA1UdIwSBkjCBj4AUa0YXFOqUdiWAVG4TVNqh41QUobahdKRyMHAxCzAJ BgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMREwDwYDVQQHEwhTYW4gSm9z ZTEOMAwGA1UEChMFc2lwaXQxKTAnBgNVBAsTIFNpcGl0IFRlc3QgQ2VydGlmaWNh dGUgQXV0aG9yaXR5ggEAMA0GCSqGSIb3DQEBBQUAA4GBADCO35LJqgiK5OUR+DuT N4CfUhsn9T5kDSf2rikna4ZFbuS7smc/oVu4g26HHjt6DKs4UEx9OmyXFslSENZ+ tFNeVClpHJrPsNwjk/uyjhfeW1NezhXMIi6q8DYcwE5I7r+Uz2XST+jWCTb4obPY 10ysI7e7/rgCoITe+qO2U35D -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQCx0mf87omggLUjaJc5UktDKma32w0ea8HzjzndDH0pL7Go/dTa eo0ycNBvLpmZOxEc0YArlC4a6BTXXChyZg0/T9NAVrMo0uE23SkwE5+kBX28bqkJ KShw5uxSjZcVQs9MQH9LMZy8TUbV6bdebBF88DXvzL0vb6xU1PlW23kp8wIDAQAB AoGAVtICT64vqBvvVPB2FVimwo5rRI1BJH88XSyq9dBpM7jDp1z3lgyL7/rA6ef4 uqXqPwXS7HQW5rA1rMikPuawxE5UG31OG3U0+H/OGl0xwAq57mEtRDR8464jSUPY l9bzkRpjnEgdUtkLnogm8F4mALexdc3KxIgg3uo/OOg0N5ECQQDZon1JBNEYWxEF GBNbEvQthPy7rRLmxontgcsfhRvm5lSbuC+VP1uRHibwwIrXOUZD8uuEVdVZNzfV bGPdh70HAkEA0Ss6HyAWczRBzrvC8eVvPmkI9XihdLqUFLTDL0R1sMCISwW/FEeH X9yFqOY+y6EJAitzhxtol+0k+UsIJl5ctQJAXU0L6QHnokloQobPxXuasukQcGUC dW0oNGowapLmI1cbbqbHv3QqDUyf5Rambx5ewUKjNViW3miNxzFwnshSgQJAINuQ gskwnaJM4CPgqM0o333yeVUcz9BraKFItAkmD8D+6AIcFRxzaJykpnac0LIYTy3y NPwaPxtynnKp8hUKrQJBAM1i5051UzJVFuRedwtPdGDrfkNwoJm27fwWozSQcBC6 G5VnTrQ6V8VCJglNzVhy9b2WqlqfWV3D5BCgxyuH984= -----END RSA PRIVATE KEY----- sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nth/cafile.pem000066400000000000000000000021771223300710500223000ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIDJDCCAo2gAwIBAgIBADANBgkqhkiG9w0BAQUFADBwMQswCQYDVQQGEwJVUzET MBEGA1UECBMKQ2FsaWZvcm5pYTERMA8GA1UEBxMIU2FuIEpvc2UxDjAMBgNVBAoT BXNpcGl0MSkwJwYDVQQLEyBTaXBpdCBUZXN0IENlcnRpZmljYXRlIEF1dGhvcml0 eTAeFw0wMzA3MTgxMjIxNTJaFw0xMzA3MTUxMjIxNTJaMHAxCzAJBgNVBAYTAlVT MRMwEQYDVQQIEwpDYWxpZm9ybmlhMREwDwYDVQQHEwhTYW4gSm9zZTEOMAwGA1UE ChMFc2lwaXQxKTAnBgNVBAsTIFNpcGl0IFRlc3QgQ2VydGlmaWNhdGUgQXV0aG9y aXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDIh6DkcUDLDyK9BEUxkud +nJ4xrCVGKfgjHm6XaSuHiEtnfELHM+9WymzkBNzZpJu30yzsxwfKoIKugdNUrD4 N3viCicwcN35LgP/KnbN34cavXHr4ZlqxH+OdKB3hQTpQa38A7YXdaoz6goW2ft5 Mi74z03GNKP/G9BoKOGd5QIDAQABo4HNMIHKMB0GA1UdDgQWBBRrRhcU6pR2JYBU bhNU2qHjVBShtjCBmgYDVR0jBIGSMIGPgBRrRhcU6pR2JYBUbhNU2qHjVBShtqF0 pHIwcDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExETAPBgNVBAcT CFNhbiBKb3NlMQ4wDAYDVQQKEwVzaXBpdDEpMCcGA1UECxMgU2lwaXQgVGVzdCBD ZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0B AQUFAAOBgQCWbRvv1ZGTRXxbH8/EqkdSCzSoUPrs+rQqR0xdQac9wNY/nlZbkR3O qAezG6Sfmklvf+DOg5RxQq/+Y6I03LRepc7KeVDpaplMFGnpfKsibETMipwzayNQ QgUf4cKBiF+65Ue7hZuDJa2EMv8qW4twEhGDYclpFU9YozyS1OhvUg== -----END CERTIFICATE----- sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nth/http-client.c000066400000000000000000000227421223300710500227510ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@file http-client.c Simple HTTP tool. * * @author Pekka Pessi . * * @date Created: Fri Mar 30 12:05:21 2001 ppessi */ #include "config.h" /**@page http_client Make HTTP request * * @par Name * http-client - HTTP request tool * * @par Synopsis * * http-client [OPTIONS] url * * @par Description * * The @em http-client utility sends a HTTP request to an HTTP server or proxy. * * @par * * The @em http-client tool will print out status line and interesting * headers from the response. The message body is also printed. * * @par Options * * The @e http-client utility accepts following command line options: *
*
--method=name
*
Specify the request method name (GET by default). *
*
--proxy=url
*
Specifies the proxy via which the request will be sent. *
*
--ua=value
*
Specifies the User-Agent header field. *
*
--mf=n
*
Specify the initial Max-Forwards count. *
*
--pipe
*
Use pipelining (do not shutdown client connection after request). *
*
--extra
*
Insert standard input to the requests. *
*
* * @par Examples * * You want to query supported features of http://connecting.nokia.com: * @code * $ http-client --method OPTIONS http://connecting.nokia.com * @endcode * * @par Environment * @c NTH_DEBUG, @c TPORT_DEBUG, @c TPORT_LOG. * * @author Pekka Pessi * *
*/ #include #include #include #include #include typedef struct context_s context_t; #define NTH_CLIENT_MAGIC_T context_t #include #include #include #include #include struct context_s { su_home_t c_home[1]; su_root_t *c_root; nth_engine_t *c_engine; nth_client_t *c_clnt; char const *c_user; char const *c_pass; auth_client_t *c_auth; int c_pre; int c_pending; }; static char const name[] = "http-client"; static int header_print(FILE *stream, char const *fmt, http_header_t const *h) { char s[1024]; msg_header_field_e(s, sizeof(s), (msg_header_t*)h, 0); s[sizeof(s) - 1] = '\0'; if (fmt && strcmp(fmt, "%s")) return fprintf(stream, fmt, s); if (fputs(s, stream) >= 0) return strlen(s); return -1; } static int payload_print(FILE *stream, msg_payload_t const *pl) { for (; pl; pl = pl->pl_next) { fprintf(stream, "%.*s", (int)pl->pl_len, pl->pl_data); } return 0; } static char *read_file(FILE *stream) { int n; char *buf; off_t used, size; if (stream == NULL) { errno = EINVAL; return NULL; } /* Read block by block */ used = 0; size = 512; buf = malloc(size); while (buf) { n = fread(buf + used, 1, size - used - 1, stream); used += n; if (n < size - used - 1) { if (feof(stream)) ; else if (ferror(stream)) free(buf), buf = NULL; break; } buf = realloc(buf, 2 * size); } if (buf) if (used < size) buf[used] = '\0'; return buf; } char const _usage[] = "usage: %s [OPTIONS] url\n" " where OPTIONS are as follows\n" " --method=name\n" " --proxy=url\n" " --user=user:password\n" " --ua=value\n" " --mf=n\n" " --pipe\n" " --extra\n"; static void usage(int rc) { fprintf(stderr, _usage, name); exit(rc); } static int response(context_t *context, nth_client_t *oreq, http_t const *http); int main(int argc, char *argv[]) { su_home_t *home; context_t context[1] = {{{SU_HOME_INIT(context)}}}; http_method_t method; char *o_proxy = NULL, *o_user = NULL, *o_max_forwards = NULL, *o_method_name = "GET", *o_user_agent = "http-client/1.0 " "nth/" NTH_VERSION; int o_pipe = 0, o_extra = 0; char *extra = NULL; char *v; #define MATCH(s, o) \ ((strcmp(s, o) == 0)) #define MATCH1(s, o) \ ((strncmp(s, o, strlen(o)) == 0) && \ (v = (s[strlen(o)] ? s + strlen(o) : argv++[1]))) #define MATCH2(s, o) \ ((strncmp(s, o, strlen(o)) == 0) && \ (s[strlen(o)] == '=' || s[strlen(o)] == '\0') && \ (v = s[strlen(o)] ? s + strlen(o) + 1 : argv++[1])) while ((v = argv++[1])) { if (v[0] != '-') { argv--; break; } else if (MATCH(v, "-")) { break; } else if (MATCH2(v, "--method")) { o_method_name = v; continue; } else if (MATCH2(v, "--mf")) { o_max_forwards = v; continue; } else if (MATCH2(v, "--proxy")) { o_proxy = v; continue; } else if (MATCH2(v, "--user")) { o_user = v; continue; } else if (MATCH2(v, "--ua")) { o_user_agent = v; continue; } else if (MATCH(v, "--pipe")) { o_pipe = 1; continue; } else if (MATCH(v, "--extra")) { o_extra = 1; continue; } else if (MATCH(v, "--help")) { usage(0); continue; } else usage(1); } if (!argv[1]) usage(1); method = http_method_code(o_method_name); if (o_user) { char *pass = strchr(o_user, ':'); if (pass) *pass++ = '\0'; context->c_user = o_user, context->c_pass = pass; } su_init(); su_home_init(home = context->c_home); if (o_extra) { if (isatty(0)) fprintf(stderr, "Type extra HTTP headers, empty line then HTTP message body " "(^D when complete):\n"); fflush(stderr); extra = read_file(stdin); } context->c_root = su_root_create(context); if (context->c_root) { context->c_engine = nth_engine_create(context->c_root, NTHTAG_ERROR_MSG(0), TAG_END()); if (context->c_engine) { while ((v = argv++[1])) { nth_client_t *clnt; clnt = nth_client_tcreate(context->c_engine, response, context, method, o_method_name, URL_STRING_MAKE(v), NTHTAG_PROXY(o_proxy), HTTPTAG_USER_AGENT_STR(o_user_agent), HTTPTAG_MAX_FORWARDS_STR(o_max_forwards), TPTAG_REUSE(o_pipe), HTTPTAG_HEADER_STR(extra), TAG_END()); if (clnt) context->c_pending++; } if (context->c_pending) su_root_run(context->c_root); nth_engine_destroy(context->c_engine), context->c_engine = NULL; } su_root_destroy(context->c_root); } su_deinit(); return 0; } /** Handle responses to request */ static int response(context_t *c, nth_client_t *clnt, http_t const *http) { nth_client_t *newclnt = NULL; int status; if (http) { status = http->http_status->st_status; } else { status = nth_client_status(clnt); fprintf(stderr, "HTTP/1.1 %u Error\n", status); } if (http && (c->c_pre || status >= 200)) { http_header_t *h = (http_header_t *)http->http_status; char hname[64]; for (; h; h = (http_header_t *)h->sh_succ) { if (h == (http_header_t *)http->http_payload) continue; else if (h == (http_header_t *)http->http_separator) continue; else if (!h->sh_class->hc_name) header_print(stdout, NULL, h); else if (h->sh_class->hc_name[0]) { snprintf(hname, sizeof hname, "%s: %%s\n", h->sh_class->hc_name); header_print(stdout, hname, h); } else { header_print(stdout, "%s\n", h); } } printf("\n"); if (http->http_payload) payload_print(stdout, http->http_payload); fflush(stdout); } if (status < 200) return 0; if (status == 401 && http->http_www_authenticate) { char const *user = c->c_user; char const *pass = c->c_pass; if (!user || !pass) { url_t const *url = nth_client_url(clnt); if (url) { user = url->url_user, pass = url->url_password; } } //if (user && pass && if ( auc_challenge(&c->c_auth, c->c_home, http->http_www_authenticate, http_authorization_class) > 0) { char const *scheme = NULL; char const *realm = NULL; scheme = http->http_www_authenticate->au_scheme; realm = msg_params_find(http->http_www_authenticate->au_params, "realm="); if (auc_all_credentials(&c->c_auth, scheme, realm, user, pass) >= 0) newclnt = nth_client_tcreate(c->c_engine, NULL, NULL, HTTP_NO_METHOD, NULL, NTHTAG_AUTHENTICATION(&c->c_auth), NTHTAG_TEMPLATE(clnt), TAG_END()); } } if (status == 302 && http->http_location) { url_t loc[1]; *loc = *http->http_location->loc_url; newclnt = nth_client_tcreate(c->c_engine, NULL, NULL, HTTP_NO_METHOD, (url_string_t *)loc, NTHTAG_TEMPLATE(clnt), TAG_END()); } if (newclnt) c->c_pending++; nth_client_destroy(clnt); if (c->c_pending-- == 1) su_root_break(c->c_root); return 0; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nth/http-server.c000066400000000000000000000154701223300710500230010ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@nofile http-server.c * @brief Test HTTP server * * @author Pekka Pessi . * * @date Created: Sat Oct 19 02:56:23 2002 ppessi * */ #include "config.h" #include #include #include #include #include #if HAVE_SIGNAL #include #endif typedef struct context_s context_t; #define NTH_SITE_MAGIC_T context_t #define SU_ROOT_MAGIC_T context_t #include #include #include struct context_s { su_home_t c_home[1]; su_root_t *c_root; nth_site_t *c_site; char const *c_server; char const *c_expires; char const *c_content_type; http_content_length_t *c_content_length; msg_payload_t *c_body; }; char const name[] = "http-server"; static void usage(int rc) { fprintf(rc ? stderr : stdout, "usage: %s OPTIONS url [content]\n", name ); exit(rc); } static int request(context_t *context, nth_site_t *site, nth_request_t *req, http_t const *http, char const *path); su_msg_r server_intr_msg = SU_MSG_R_INIT; #if HAVE_SIGNAL static RETSIGTYPE server_intr_handler(int signum); #endif static void server_break(context_t *c, su_msg_r msg, su_msg_arg_t *arg); static msg_payload_t *read_payload(su_home_t *home, char const *fname); static msg_payload_t *fread_payload(su_home_t *home, FILE *f); int main(int argc, char *argv[]) { su_home_t *home; context_t *c, context[1] = {{{SU_HOME_INIT(context)}}}; char *o_url = NULL, *o_body = NULL; int o_extra = 0; int o_timeout = 300; char *s; c = context; su_init(); su_home_init(home = context->c_home); #define MATCH(s, v) \ ((strncmp(s, v, strlen(v)) == 0)) #define MATCH1(s, v) \ ((strncmp(s, v, strlen(v)) == 0) && \ (s = (s[strlen(v)] ? s + strlen(v) : argv++[1]))) #define MATCH2(s, v) \ ((strncmp(s, v, strlen(v)) == 0) && \ (s[strlen(v)] == '=' ? (s = s + strlen(v) + 1) : (s = argv++[1]))) while ((s = argv++[1])) { if (*s != '-') break; s++; if (MATCH2(s, "-expires")) { c->c_expires = s; continue; } else if (MATCH2(s, "-tcp-timeout")) { o_timeout = strtoul(s, &s, 0); continue; } else if (MATCH2(s, "-ct")) { c->c_content_type = s; continue; } else if (MATCH2(s, "-content-type")) { c->c_content_type = s; continue; } else if (MATCH2(s, "-server")) { c->c_server = s; continue; } else if (MATCH(s, "-help")) { usage(0); continue; } else if (MATCH(s, "x")||MATCH(s, "-extra")) { o_extra = 1; continue; } else usage(2); } if (!(o_url = s)) usage(1); else o_body = argv++[1]; context->c_root = su_root_create(context); context->c_body = read_payload(context->c_home, o_body); if (!context->c_body) { perror("contents"); exit(1); } context->c_content_length = msg_content_length_create(context->c_home, context->c_body->pl_len); su_msg_create(server_intr_msg, su_root_task(context->c_root), su_root_task(context->c_root), server_break, 0); #if HAVE_SIGNAL signal(SIGINT, server_intr_handler); #if HAVE_SIGQUIT signal(SIGQUIT, server_intr_handler); signal(SIGHUP, server_intr_handler); #endif #endif if (context->c_root) { context->c_site = nth_site_create(NULL, /* This is a top-level site */ request, context, (url_string_t *)o_url, NTHTAG_ROOT(context->c_root), TPTAG_TIMEOUT(o_timeout * 1000), TAG_END()); if (context->c_site) { su_root_run(context->c_root); nth_site_destroy(context->c_site); } su_root_destroy(context->c_root); } su_deinit(); return 0; } static void server_break(context_t *c, su_msg_r msg, su_msg_arg_t *arg) { fprintf(stderr, "%s: received signal, exiting\n", name); su_root_break(c->c_root); } static RETSIGTYPE server_intr_handler(int signum) { su_msg_send(server_intr_msg); } static int request(context_t *c, nth_site_t *site, nth_request_t *req, http_t const *http, char const *path) { fprintf(stderr, "request to /%s\n", path); if (path && strlen(path)) return 404; if (http->http_request->rq_method != http_method_get) { nth_request_treply(req, HTTP_405_NOT_ALLOWED, HTTPTAG_ALLOW_STR("GET"), TAG_END()); return 405; } nth_request_treply(req, HTTP_200_OK, HTTPTAG_SERVER_STR(c->c_server), HTTPTAG_EXPIRES_STR(c->c_expires), HTTPTAG_CONTENT_TYPE_STR(c->c_content_type), HTTPTAG_CONTENT_LENGTH(c->c_content_length), HTTPTAG_PAYLOAD(c->c_body), TAG_END()); return 200; } /** Read message body from named file. * * The function read_payload() reads the contents to a SIP payload * structure from a the named file. If @a fname is NULL, the payload * contents are read from standard input. */ msg_payload_t *read_payload(su_home_t *home, char const *fname) { FILE *f; msg_payload_t *pl; if (fname == NULL || strcmp(fname, "-") == 0) f = stdin, fname = ""; else f = fopen(fname, "rb"); if (f == NULL) return NULL; pl = fread_payload(home, f); if (f != stdin) fclose(f); return pl; } msg_payload_t *fread_payload(su_home_t *home, FILE *f) { msg_payload_t *pl; int n; char *buf; off_t used, size; if (f == NULL) { errno = EINVAL; return NULL; } pl = msg_payload_create(home, NULL, 0); if (pl == NULL) return NULL; /* Read block by block */ used = 0; size = 4096; buf = malloc(size); while (buf) { n = fread(buf + used, 1, size - used, f); used += n; if (n < size - used) { if (feof(f)) ; else if (ferror(f)) buf = NULL; break; } buf = realloc(buf, size = 2 * size); } if (buf == NULL) { perror("fread_payload: realloc"); return NULL; } if (used < size) buf[used] = '\0'; pl->pl_common->h_data = pl->pl_data = buf; pl->pl_common->h_len = pl->pl_len = used; return pl; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nth/nth.docs000066400000000000000000000010301223300710500220000ustar00rootroot00000000000000/* -*- c -*- */ /**@MODULEPAGE "nth" - HTTP Transactions Module * * @section nth_meta Module Meta Information * * NTH provides interface to simple HTTP transaction engines for both HTTP * servers and clients. The transaction interface for both client and server * is available through , tags controlling the options in * . * * @CONTACT Pekka Pessi * * @STATUS @SofiaSIP Core library * * @LICENSE LGPL * * @author Pekka Pessi . * */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nth/nth_client.c000066400000000000000000000742021223300710500226430ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE nth_client.c * @brief HTTP Client implementhtion * * Copyright (c) 2002 Nokia Research Center. All rights reserved. * * This source file has been divided into following sections: * 1) engine * 2) tport handling * 3) client transactions * * @author Pekka Pessi * * @date Created: Tue Jun 13 02:57:51 2000 ppessi */ #include "config.h" #include #include #include #include #include #include #include /** @internal SU message argument structure type */ #define SU_MSG_ARG_T union sm_arg_u /** @internal SU timer argument pointer type */ #define SU_TIMER_ARG_T struct nth_engine_s #define MSG_HDR_T union http_header_u #define MSG_PUB_T struct http_s #include "sofia-sip/nth.h" #include #include #include #include #include #include #include /* We are customer of tport_t */ #define TP_STACK_T nth_engine_t #define TP_MAGIC_T void #define TP_CLIENT_T nth_client_t #ifndef TPORT_H #include #endif #include #define HE_TIMER HE_TIMER enum { HE_TIMER = 1000 }; /** @c http_flag telling that this message is internally generated. */ #define NTH_INTERNAL_MSG (1<<16) HTABLE_DECLARE_WITH(hc_htable, hct, nth_client_t, uintptr_t, size_t); struct nth_engine_s { su_home_t he_home[1]; su_root_t *he_root; su_timer_t *he_timer; int he_mflags; /**< Message flags */ msg_mclass_t const *he_mclass; tport_t *he_tports; url_t *he_default_proxy; unsigned he_now; unsigned he_expires; /* Attributes */ unsigned he_streaming:1; /**< Enable streaming */ unsigned he_error_msg:1; unsigned:0; /* Statistics */ struct { uint32_t st_requests; /**< Sent requests */ uint32_t st_1xxresponses; /**< Received 1XX responses */ uint32_t st_responses; /**< Received responses */ uint32_t st_tp_errors; /**< Transport errors */ uint32_t st_timeouts; /**< Timeouts */ uint32_t st_bad; /**< Bad responses*/ } he_stats[1]; /** Table for client transactions */ hc_htable_t he_clients[1]; }; struct nth_client_s { nth_engine_t *hc_engine; nth_response_f *hc_callback; nth_client_magic_t *hc_magic; http_method_t hc_method; char const *hc_method_name; url_t const *hc_url; /**< Original RequestURI */ unsigned hc_timeout; /**< Client timeout */ unsigned hc_expires; /**< Client expires */ /* Request state */ unsigned short hc_status; unsigned hc_destroyed:1; unsigned hc_completed:1; unsigned hc_inserted:1; unsigned hc_is_streaming:1; /**< Currently streaming response */ /* Attributes */ unsigned hc_streaming:1; /**< Enable streaming */ unsigned hc_error_msg:1; unsigned /* pad */:0; url_string_t const *hc_route_url; tp_name_t hc_tpn[1]; /**< Where to send requests */ tport_t *hc_tport; int hc_pending; /**< Request is pending in tport */ tagi_t *hc_tags; /**< Transport tags */ auth_client_t **hc_auc; /**< List of authenticators */ msg_t *hc_request; msg_t *hc_response; }; /* ====================================================================== */ /* Debug log settings */ #define SU_LOG nth_client_log #ifdef SU_DEBUG_H #error included directly. #endif #include /**@var NTH_DEBUG * * Environment variable determining the debug log level for @b nth * module. * * The NTH_DEBUG environment variable is used to determine the debug * logging level for @b nth module. The default level is 1. * * @sa , nth_client_log, #SOFIA_DEBUG */ extern char const NTH_DEBUG[]; #ifndef SU_DEBUG #define SU_DEBUG 1 #endif /**Debug log for @b nth module. * * The nth_client_log is the log object used by @b nth client. The level of * #nth_client_log is set using #NTH_DEBUG environment variable. */ su_log_t nth_client_log[] = { SU_LOG_INIT("nth", "NTH_DEBUG", SU_DEBUG) }; #if HAVE_FUNC #elif HAVE_FUNCTION #define __func__ __FUNCTION__ #else static char const __func__[] = "nth"; #endif /* ====================================================================== */ /* Internal message passing */ union sm_arg_u { struct hc_recv_s { nth_client_t *hc; msg_t *msg; http_t *http; } hc_recv[1]; }; /* ====================================================================== */ /* Internal prototypes */ tagi_t nth_client_tags[] = { {nthtag_mclass, 0}, {nthtag_message, 0}, {nthtag_mflags, 0}, {nthtag_proxy, 0}, {nthtag_error_msg, 0}, {nthtag_template, 0}, {nthtag_authentication, 0}, {TAG_NEXT(tport_tags)} }; /* ====================================================================== */ /* Internal prototypes */ static int he_create_tports(nth_engine_t * he, tagi_t *tags); static int he_timer_init(nth_engine_t * he); static void he_timer(su_root_magic_t *, su_timer_t *, nth_engine_t * he); static void hc_timer(nth_engine_t * he, nth_client_t * hc, uint32_t now); static uint32_t he_now(nth_engine_t const *he); static void he_recv_message(nth_engine_t * he, tport_t * tport, msg_t *msg, void *arg, su_time_t now); static msg_t *he_msg_create(nth_engine_t * he, int flags, char const data[], usize_t dlen, tport_t const *tport, nth_client_t * hc); static void he_tp_error(nth_engine_t * he, tport_t * tport, int errcode, char const *remote); static int hc_recv(nth_client_t * hc, msg_t *msg, http_t * http); HTABLE_PROTOS_WITH(hc_htable, hct, nth_client_t, uintptr_t, size_t); #define HTABLE_HASH_CLIENT(hc) ((uintptr_t)(hc)->hc_tport) HTABLE_BODIES_WITH(hc_htable, hct, nth_client_t, HTABLE_HASH_CLIENT, uintptr_t, size_t); static url_string_t const *hc_request_complete(nth_client_t * hc, msg_t *msg, http_t * http, http_method_t method, char const *name, url_string_t const *url, char const *version, url_t const *parent); static int hc_request_authenticate(nth_client_t * hc, msg_t *msg, http_t * http, url_string_t const *uri, auth_client_t **auc); static nth_client_t *hc_create(nth_engine_t * he, nth_response_f * callback, nth_client_magic_t * magic, msg_t *msg, tag_type_t tag, tag_value_t value, ...); static int hc_resolve_and_send(nth_client_t * hc); static nth_client_t *hc_send(nth_client_t * hc); static void hc_insert(nth_engine_t * he, nth_client_t * hc); static void hc_free(nth_client_t * hc); static void hc_tport_error(nth_engine_t *, nth_client_t * hc, tport_t * tp, msg_t *msg, int error); static int hc_reply(nth_client_t * hc, int status, char const *phrase); static int hc_default_cb(nth_client_magic_t * magic, nth_client_t * request, http_t const *http); /* ---------------------------------------------------------------------- */ char const *nth_engine_version(void) { return "sofia-http-client/" NTH_CLIENT_VERSION; } /* ---------------------------------------------------------------------- */ nth_engine_t *nth_engine_create(su_root_t *root, tag_type_t tag, tag_value_t value, ...) { nth_engine_t *he; ta_list ta; if ((he = su_home_new(sizeof(*he)))) { he->he_root = root; he->he_mflags = MSG_DO_CANONIC; he->he_mclass = http_default_mclass(); he->he_expires = 32000; ta_start(ta, tag, value); if (hc_htable_resize(he->he_home, he->he_clients, 0) < 0 || he_create_tports(he, ta_args(ta)) < 0 || he_timer_init(he) < 0 || nth_engine_set_params(he, ta_tags(ta)) < 0) { nth_engine_destroy(he), he = NULL; } ta_end(ta); } return he; } void nth_engine_destroy(nth_engine_t * he) { if (he) { size_t i; hc_htable_t *hct = he->he_clients; for (i = 0; i < hct->hct_size; i++) hc_free(hct->hct_table[i]); tport_destroy(he->he_tports); su_timer_destroy(he->he_timer), he->he_timer = NULL; su_home_unref(he->he_home); } } int nth_engine_set_params(nth_engine_t * he, tag_type_t tag, tag_value_t value, ...) { int n; ta_list ta; unsigned expires; int error_msg; msg_mclass_t const *mclass; int mflags; int streaming; url_string_t const *proxy; if (he == NULL) return (errno = EINVAL), -1; ta_start(ta, tag, value); expires = he->he_expires; error_msg = he->he_error_msg; mclass = he->he_mclass; mflags = he->he_mflags; streaming = he->he_streaming; proxy = (void *) he->he_default_proxy; n = tl_gets(ta_args(ta), NTHTAG_EXPIRES_REF(expires), NTHTAG_ERROR_MSG_REF(error_msg), NTHTAG_MCLASS_REF(mclass), NTHTAG_MFLAGS_REF(mflags), NTHTAG_STREAMING_REF(streaming), NTHTAG_PROXY_REF(proxy), TAG_END()); if (n > 0) { if (proxy->us_url != he->he_default_proxy) { url_t *copy = url_hdup(he->he_home, proxy->us_url); if (proxy && !copy) { n = -1; } else { su_free(he->he_home, (void *) he->he_default_proxy); he->he_default_proxy = copy; } } } if (n > 0) { he->he_expires = expires; he->he_error_msg = error_msg != 0; if (mclass) he->he_mclass = mclass; else he->he_mclass = http_default_mclass(); he->he_mflags = mflags; he->he_streaming = streaming != 0; } ta_end(ta); return n; } int nth_engine_get_params(nth_engine_t const *he, tag_type_t tag, tag_value_t value, ...) { int n; ta_list ta; msg_mclass_t const *mclass; if (he == NULL) return (errno = EINVAL), -1; if (he->he_mclass != http_default_mclass()) mclass = he->he_mclass; else mclass = NULL; ta_start(ta, tag, value); n = tl_tgets(ta_args(ta), NTHTAG_ERROR_MSG(he->he_error_msg), NTHTAG_MCLASS(mclass), NTHTAG_MFLAGS(he->he_mflags), NTHTAG_EXPIRES(he->he_expires), NTHTAG_STREAMING(he->he_streaming), NTHTAG_PROXY((url_string_t *) he->he_default_proxy), TAG_END()); ta_end(ta); return n; } int nth_engine_get_stats(nth_engine_t const *he, tag_type_t tag, tag_value_t value, ...) { int n; ta_list ta; if (he == NULL) return (errno = EINVAL), -1; ta_start(ta, tag, value); n = tl_tgets(ta_args(ta), TAG_END()); ta_end(ta); return n; } static tp_name_t he_name[1] = { {"*", "*", "*", "*"} }; static char const *const he_tports[] = { "tcp", "tls", NULL }; static char const *const he_no_tls_tports[] = { "tcp", NULL }; static tp_stack_class_t http_client_class[1] = { { sizeof(http_client_class), he_recv_message, he_tp_error, he_msg_create} }; /** Create transports for client engine */ static int he_create_tports(nth_engine_t * he, tagi_t *tags) { he->he_tports = tport_tcreate(he, http_client_class, he->he_root, TAG_END()); if (!he->he_tports) return -1; if (tport_tbind(he->he_tports, he_name, he_tports, TPTAG_SERVER(0), TAG_NEXT(tags)) >= 0) return 0; return tport_tbind(he->he_tports, he_name, he_no_tls_tports, TPTAG_SERVER(0), TAG_NEXT(tags)); } /** Initialize engine timer. */ static int he_timer_init(nth_engine_t * he) { he->he_timer = su_timer_create(su_root_task(he->he_root), HE_TIMER); return su_timer_set(he->he_timer, he_timer, he); } /** * Engine timer routine. */ static void he_timer(su_root_magic_t *rm, su_timer_t *timer, nth_engine_t * he) { unsigned i; uint32_t now; hc_htable_t *hct = he->he_clients; now = su_time_ms(su_now()); now += now == 0; he->he_now = now; if (hct) for (i = hct->hct_size; i > 0;) if (hct->hct_table[--i]) hc_timer(he, hct->hct_table[i], now); su_timer_set(timer, he_timer, he); he->he_now = 0; } /** Get current timestamp in milliseconds */ static uint32_t he_now(nth_engine_t const *he) { if (he->he_now) return he->he_now; else return su_time_ms(su_now()); } static void he_recv_message(nth_engine_t * he, tport_t * tport, msg_t *msg, void *arg, su_time_t now) { nth_client_t *hc, **hcp; tp_name_t const *tpn; for (hcp = hc_htable_hash(he->he_clients, (hash_value_t)(uintptr_t) tport); (hc = *hcp); hcp = hc_htable_next(he->he_clients, hcp)) { if (hc->hc_tport == tport) { if (hc_recv(hc, msg, http_object(msg)) < 0) msg_destroy(msg); return; } } /* Extra response? Framing error? */ tpn = tport_name(tport); if (msg_size(msg)) SU_DEBUG_3(("nth client: received extra data ("MOD_ZU" bytes) " "from %s/%s:%s\n", (size_t)msg_size(msg), tpn->tpn_proto, tpn->tpn_host, tpn->tpn_port)); else SU_DEBUG_3(("nth client: received extra data from %s/%s:%s\n", tpn->tpn_proto, tpn->tpn_host, tpn->tpn_port)); msg_destroy(msg); tport_shutdown(tport, 2); } /** Report error from transport */ static void he_tp_error(nth_engine_t * he, tport_t * tport, int errcode, char const *remote) { su_log("\nth: tport: %s%s%s\n", remote ? remote : "", remote ? ": " : "", su_strerror(errcode)); } /** Create a new message. */ msg_t *nth_engine_msg_create(nth_engine_t * he, int flags) { if (he == NULL) { errno = EINVAL; return NULL; } flags |= he->he_mflags; if (he->he_streaming) flags |= MSG_FLG_STREAMING; else flags &= ~MSG_FLG_STREAMING; return msg_create(he->he_mclass, flags); } /** Create a new message for transport */ static msg_t *he_msg_create(nth_engine_t * he, int flags, char const data[], usize_t dlen, tport_t const *tport, nth_client_t * hc) { flags |= he->he_mflags; if (he->he_streaming) flags |= MSG_FLG_STREAMING; else flags &= ~MSG_FLG_STREAMING; if (hc == NULL) { nth_client_t **slot; for (slot = hc_htable_hash(he->he_clients, (hash_value_t)(uintptr_t) tport); (hc = *slot); slot = hc_htable_next(he->he_clients, slot)) if (hc->hc_tport == tport) break; } if (hc) { if (hc->hc_method == http_method_head) { flags &= ~MSG_FLG_STREAMING; flags |= HTTP_FLG_NO_BODY; } } return msg_create(he->he_mclass, flags); } /** Get destination name from Host header and request URI. */ static int tpn_by_host(tp_name_t * tpn, http_host_t const *h, url_t const *url) { if (!h || !url) return -1; tpn->tpn_proto = url_tport_default((enum url_type_e)url->url_type); tpn->tpn_canon = h->h_host; tpn->tpn_host = h->h_host; if (h->h_port) tpn->tpn_port = h->h_port; else tpn->tpn_port = url_port_default((enum url_type_e)url->url_type); return 0; } /* ---------------------------------------------------------------------- */ nth_client_t *nth_client_tcreate(nth_engine_t * engine, nth_response_f * callback, nth_client_magic_t * magic, http_method_t method, char const *name, url_string_t const *uri, tag_type_t tag, tag_value_t value, ...) { nth_client_t *hc = NULL; ta_list ta; if (engine) { void *none = &none; msg_t *msg = none; http_t *http; char const *version = http_version_1_1; nth_client_t const *template = NULL; auth_client_t **auc = none; unsigned expires = engine->he_expires; int ok = 0; ta_start(ta, tag, value); tl_gets(ta_args(ta), NTHTAG_TEMPLATE_REF(template), NTHTAG_AUTHENTICATION_REF(auc), NTHTAG_MESSAGE_REF(msg), NTHTAG_EXPIRES_REF(expires), HTTPTAG_VERSION_REF(version), TAG_END()); if (msg == none) { if (template && template->hc_request) msg = msg_copy(template->hc_request); else msg = msg_create(engine->he_mclass, engine->he_mflags); } http = http_object(msg); if (template) { if (callback == NULL) callback = template->hc_callback; if (magic == NULL) magic = template->hc_magic; if (name == NULL) method = template->hc_method, name = template->hc_method_name; if (uri == NULL) uri = (url_string_t *) template->hc_url; if (auc == none) auc = template->hc_auc; } else if (auc == none) { auc = NULL; } hc = hc_create(engine, callback, magic, msg, ta_tags(ta)); if (hc) hc->hc_expires = expires; if (hc == NULL) ; else if (http_add_tl(msg, http, ta_tags(ta)) < 0) ; else if (!(uri = hc_request_complete(hc, msg, http, method, name, uri, version, nth_client_url(template)))) ; else if (auc && hc_request_authenticate(hc, msg, http, uri, auc) <= 0) ; else if (hc_resolve_and_send(hc) < 0) ; else ok = 1; if (!ok) { if (hc) hc_free(hc); else msg_destroy(msg); hc = NULL; } ta_end(ta); } return hc; } static url_string_t const *hc_request_complete(nth_client_t * hc, msg_t *msg, http_t * http, http_method_t method, char const *name, url_string_t const *uri, char const *version, url_t const *parent) { su_home_t *home = msg_home(msg); http_host_t *host = http->http_host; void *tbf = NULL; url_t const *url; url_t u[1]; if (uri == NULL && http->http_request) uri = (url_string_t *) http->http_request->rq_url; if (uri == NULL) uri = (url_string_t *) parent; url = url_string_p(uri) ? (tbf = url_hdup(NULL, uri->us_url)) : uri->us_url; if (!url) return NULL; *u = *url; if (u->url_type == url_unknown && u->url_path && !u->url_host) { if (parent) { *u = *parent; u->url_path = url->url_path; /* XXX - relative URLs! */ u->url_params = url->url_params; u->url_headers = url->url_headers; /* Query */ } } if (!hc->hc_route_url && u->url_type != url_http && u->url_type != url_https) hc->hc_route_url = (url_string_t *) u; if (host && (host_cmp(host->h_host, u->url_host) || su_strcmp(host->h_port, u->url_port))) host = NULL; if (host == NULL && u->url_host) { host = http_host_create(home, u->url_host, u->url_port); msg_header_insert(msg, http, (http_header_t *) host); } if (u->url_host || hc->hc_route_url || host) hc->hc_url = url_hdup(home, u); if (hc->hc_route_url == (url_string_t *) u) hc->hc_route_url = (url_string_t *) hc->hc_url; if (hc->hc_url) { http_request_t *rq = http->http_request; if (rq && !method && !name) method = rq->rq_method, name = rq->rq_method_name; else if (rq && method && method != rq->rq_method) rq = NULL; else if (rq && name && strcmp(name, rq->rq_method_name)) rq = NULL; if (rq && version && !su_casematch(version, rq->rq_version)) rq = NULL; if (!hc->hc_route_url) { u->url_type = url_unknown, u->url_scheme = NULL; u->url_user = NULL, u->url_password = NULL; u->url_host = NULL, u->url_port = NULL; u->url_root = '/'; if (!u->url_path) u->url_path = ""; u->url_fragment = NULL; } if (rq && http_url_cmp(u, rq->rq_url)) rq = NULL; if (!rq) { if (http->http_request) msg_header_remove(msg, http, (msg_header_t *) http->http_request); http->http_request = http_request_create(home, method, name, (url_string_t *) u, version); if (!http->http_request) uri = NULL; } } else { uri = NULL; } if (http_message_complete(msg, http) < 0) uri = NULL; if (tbf) su_free(NULL, tbf); if (uri) { hc->hc_method = http->http_request->rq_method; hc->hc_method_name = http->http_request->rq_method_name; } return uri; } static int hc_request_authenticate(nth_client_t * hc, msg_t *msg, http_t * http, url_string_t const *uri, auth_client_t **auc) { return auc_authorization(auc, msg, http, http->http_request->rq_method_name, uri->us_url, http->http_payload); } static nth_client_t *hc_create(nth_engine_t * he, nth_response_f * callback, nth_client_magic_t * magic, msg_t *msg, tag_type_t tag, tag_value_t value, ...) { nth_client_t *hc; su_home_t *home = msg_home(msg); if (!(hc = su_zalloc(he->he_home, sizeof(*hc)))) return NULL; if (!callback) callback = hc_default_cb; { int error_msg = he->he_error_msg; int streaming = he->he_streaming; url_string_t const *route_url = NULL; ta_list ta; ta_start(ta, tag, value); route_url = (url_string_t *) he->he_default_proxy; tl_gets(ta_args(ta), NTHTAG_PROXY_REF(route_url), NTHTAG_ERROR_MSG_REF(error_msg), NTHTAG_STREAMING_REF(streaming), TAG_END()); hc->hc_engine = he; hc->hc_callback = callback; hc->hc_magic = magic; hc->hc_tags = tl_afilter(home, tport_tags, ta_args(ta)); hc->hc_error_msg = error_msg; hc->hc_streaming = streaming; hc->hc_route_url = route_url; ta_end(ta); } hc->hc_request = msg; return hc; } static int hc_resolve_and_send(nth_client_t * hc) { msg_t *msg = hc->hc_request; http_t *http = http_object(msg); su_home_t *home = msg_home(msg); int resolved = -1; if (hc->hc_route_url) { resolved = tport_name_by_url(home, hc->hc_tpn, hc->hc_route_url); } else { resolved = tpn_by_host(hc->hc_tpn, http->http_host, hc->hc_url); } if (resolved < 0) { SU_DEBUG_3(("nth client resolve: %s\n", "cannot resolve URL")); return -1; } hc->hc_route_url = NULL; hc->hc_tport = tport_by_name(hc->hc_engine->he_tports, hc->hc_tpn); if (!hc->hc_tport) { assert(hc->hc_tport); SU_DEBUG_3(("nth client create: %s\n", !hc->hc_tport ? "no transport" : "invalid message")); return -1; } if (msg_serialize(msg, http) < 0) { assert(hc->hc_tport); SU_DEBUG_3(("nth client create: invalid message")); return -1; } hc_send(hc); hc_insert(hc->hc_engine, hc); return 0; } /**@internal * Insert client request to the hash table */ static void hc_insert(nth_engine_t * he, nth_client_t * hc) { if (hc_htable_is_full(he->he_clients)) hc_htable_resize(he->he_home, he->he_clients, 0); hc_htable_insert(he->he_clients, hc); hc->hc_inserted = 1; } /**@internal * Remove client request from the hash table */ static void hc_remove(nth_engine_t * he, nth_client_t * hc) { if (hc->hc_inserted) hc_htable_remove(he->he_clients, hc); hc->hc_inserted = 0; } /** Destroy client request. */ void nth_client_destroy(nth_client_t * hc) { if (hc == NULL) ; else if (hc->hc_completed) hc_free(hc); else hc->hc_callback = hc_default_cb; } /**@internal Free client request. */ void hc_free(nth_client_t * hc) { if (hc) { if (hc->hc_pending) tport_release(hc->hc_tport, hc->hc_pending, hc->hc_request, NULL, hc, 0); tport_decref(&hc->hc_tport); msg_destroy(hc->hc_request); msg_destroy(hc->hc_response); su_free(hc->hc_engine->he_home, hc); } } /** * Gets client status. * * @param hc pointer to a nth client object * * @return * Returns the status code from the response message if it has been * received. A status code below 100 indicates that no response has been * received. If request timeouts, the connection is closed and the status * code is set to 408. If @a hc is NULL, returns 400 (Bad Request). */ int nth_client_status(nth_client_t const *hc) { return hc ? hc->hc_status : 400; } /** * Gets client method. * * @param hc pointer to a nth client object * * @return * Returns the HTTP method from the request. * If @a hc is NULL, returns #http_method_invalid. */ http_method_t nth_client_method(nth_client_t const *hc) { return hc ? hc->hc_method : http_method_invalid; } /** Get original Request-URI */ url_t const *nth_client_url(nth_client_t const *hc) { return hc ? hc->hc_url : NULL; } /** Get request message. */ msg_t *nth_client_request(nth_client_t * hc) { msg_t *request = NULL; if (hc) request = hc->hc_request, hc->hc_request = NULL; return request; } /** Get response message. */ msg_t *nth_client_response(nth_client_t const *hc) { if (hc) return msg_ref(hc->hc_response); else return NULL; } /** Is client streaming response? */ int nth_client_is_streaming(nth_client_t const *hc) { return hc && hc->hc_is_streaming; } /** Send request. */ static nth_client_t *hc_send(nth_client_t * hc) { nth_engine_t *he = hc->hc_engine; tport_t *tp; he->he_stats->st_requests++; tp = tport_tsend(hc->hc_tport, hc->hc_request, hc->hc_tpn, TAG_NEXT(hc->hc_tags)); if (tp == NULL) { he->he_stats->st_tp_errors++; hc_reply(hc, HTTP_503_NO_SERVICE); return hc; } hc->hc_tport = tport_incref(tp); hc->hc_pending = tport_pend(tp, hc->hc_request, hc_tport_error, hc); if (hc->hc_pending == -1) hc->hc_pending = 0; if (hc->hc_expires) { hc->hc_timeout = he_now(he) + hc->hc_expires; /* XXX */ if (hc->hc_timeout == 0) hc->hc_timeout++; } return hc; } /** @internal Report transport errors. */ void hc_tport_error(nth_engine_t * he, nth_client_t * hc, tport_t * tp, msg_t *msg, int error) { su_sockaddr_t const *su = msg_addr(msg); tp_name_t const *tpn = tp ? tport_name(tp) : hc->hc_tpn; char addr[SU_ADDRSIZE]; char const *errmsg; if (error) errmsg = su_strerror(error); else errmsg = "Remote end closed connection"; su_log("nth: %s: %s (%u) with %s@%s:%u\n", hc->hc_method_name, errmsg, error, tpn->tpn_proto, su_inet_ntop(su->su_family, SU_ADDR(su), addr, sizeof(addr)), htons(su->su_port)); he->he_stats->st_tp_errors++; hc_reply(hc, HTTP_503_NO_SERVICE); } static void hc_delayed_recv(su_root_magic_t *rm, su_msg_r msg, union sm_arg_u *u); /** Respond internally to a transaction. */ int hc_reply(nth_client_t * hc, int status, char const *phrase) { nth_engine_t *he = hc->hc_engine; msg_t *msg = NULL; http_t *http = NULL; assert(status >= 400); SU_DEBUG_5(("nth: hc_reply(%p, %u, %s)\n", (void *)hc, status, phrase)); if (hc->hc_pending) { tport_release(hc->hc_tport, hc->hc_pending, hc->hc_request, NULL, hc, status < 200); if (status >= 200) hc->hc_pending = 0; } tport_shutdown(hc->hc_tport, 2); hc->hc_completed = 1; hc->hc_timeout = 0; if (hc->hc_callback == hc_default_cb) { hc_free(hc); return 0; } /* Create response message, if needed */ if (hc->hc_error_msg) { msg = he_msg_create(he, NTH_INTERNAL_MSG, NULL, 0, NULL, hc); http = http_object(msg); http_complete_response(msg, status, phrase, http_object(hc->hc_request)); } else hc->hc_status = status; if (hc->hc_inserted) { hc_recv(hc, msg, http); return 0; } else { /* * The thread creating outgoing transaction must return to application * before transaction callback can be invoked. Processing an internally * generated response message must be delayed until transaction creation * is completed. * * The internally generated message is transmitted using su_msg_send() * and it is delivered back to NTA when the application next time * executes the su_root_t event loop. */ su_root_t *root = he->he_root; su_msg_r su_msg = SU_MSG_R_INIT; if (su_msg_create(su_msg, su_root_task(root), su_root_task(root), hc_delayed_recv, sizeof(struct hc_recv_s)) == SU_SUCCESS) { struct hc_recv_s *a = su_msg_data(su_msg)->hc_recv; a->hc = hc; a->msg = msg; a->http = http; if (su_msg_send(su_msg) == SU_SUCCESS) return 0; } } if (msg) msg_destroy(msg); return -1; } static void hc_delayed_recv(su_root_magic_t *rm, su_msg_r msg, union sm_arg_u *u) { struct hc_recv_s *a = u->hc_recv; if (hc_recv(a->hc, a->msg, a->http) < 0 && a->msg) msg_destroy(a->msg); } /** Receive response to transaction. */ int hc_recv(nth_client_t * hc, msg_t *msg, http_t * http) { short status; int streaming = msg_is_streaming(msg); int shutdown = 0; if (http && http->http_status) { status = http->http_status->st_status; if (status < 100) status = 100; if (streaming && !hc->hc_streaming) { /* Disable streaming for this msg */ msg_set_streaming(msg, (enum msg_streaming_status)0); return 0; /* Wait for complete message */ } hc->hc_status = status; } else if (http) status = hc->hc_status = 500, streaming = 0, http = NULL; else status = hc->hc_status, streaming = 0; if (status == 400 || (http && (http->http_flags & MSG_FLG_ERROR))) shutdown = 2; if (!streaming || shutdown) msg_set_streaming(msg, (enum msg_streaming_status)0); if (hc->hc_pending) { tport_release(hc->hc_tport, hc->hc_pending, hc->hc_request, msg, hc, streaming || status < 200); if (!streaming && status >= 200) hc->hc_pending = 0; } if (!streaming && status >= 200) { /* Completed. */ hc->hc_completed = 1; hc_remove(hc->hc_engine, hc); if (shutdown || !http || (http->http_status->st_version == http_version_1_1 && http->http_connection && msg_params_find(http->http_connection->k_items, "close")) || (http->http_status->st_version == http_version_1_0)) shutdown = 2; } if (shutdown) { if (status < 200) status = 400; tport_shutdown(hc->hc_tport, shutdown); } if (msg_is_complete(msg)) { if (status < 200) hc->hc_engine->he_stats->st_1xxresponses++; else hc->hc_engine->he_stats->st_responses++; } if (hc->hc_response) msg_destroy(hc->hc_response); hc->hc_response = msg; hc->hc_is_streaming = streaming; /* Call callback */ hc->hc_callback(hc->hc_magic, hc, http); return 0; } /** @internal Default callback for request */ int hc_default_cb(nth_client_magic_t * magic, nth_client_t * hc, http_t const *http) { if (http == NULL || http->http_status->st_status >= 200) hc_free(hc); return 0; } /** @internal Client transaction timer routine. */ static void hc_timer(nth_engine_t * he, nth_client_t * hc, uint32_t now) { if (hc->hc_timeout == 0) return; if ((int)hc->hc_timeout - (int)now > 0) return; hc_reply(hc, HTTP_408_TIMEOUT); } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nth/nth_server.c000066400000000000000000001007771223300710500227020ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@internal @file nth_server.c * @brief HTTP server. * * @author Pekka Pessi * * @date Created: Sat Oct 19 01:37:36 2002 ppessi */ #include "config.h" #include #include typedef struct server_s server_t; /** @internal SU timer argument pointer type */ #define SU_TIMER_ARG_T server_t #include #include #include #include "sofia-sip/nth.h" #include #include #include #include /* We are customer of tport_t */ #define TP_STACK_T server_t #define TP_MAGIC_T void #include #include #include #include #include #include #include #include #include #ifndef UINT32_MAX #define UINT32_MAX (0xffffffffU) #endif enum { SERVER_TICK = 1000 }; #define SERVER_VERSION "nth/" NTH_VERSION HTABLE_DECLARE(hc_htable, hct, nth_client_t); struct server_s { su_home_t srv_home[1]; su_root_t *srv_root; su_timer_t *srv_timer; unsigned srv_now; msg_mclass_t const*srv_mclass; int srv_mflags; /**< Message flags */ tport_t *srv_tports; unsigned srv_queuesize; /**< Maximum number of queued responses */ size_t srv_max_bodylen; /**< Maximum accepted length */ unsigned srv_persistent:1; /**< Allow persistent connections */ /** Sites */ nth_site_t *srv_sites; /* Statistics */ struct { uint32_t st_requests; /**< Received requests */ uint32_t st_responses; /**< Sent responses */ uint32_t st_bad; /**< Bad requests */ } srv_stats[1]; http_server_t *srv_server; /**< Server header */ }; struct nth_site_s { nth_site_t *site_next, **site_prev; nth_site_t *site_kids; server_t *site_server; auth_mod_t *site_auth; url_t *site_url; char const *site_path; size_t site_path_len; nth_request_f *site_callback; nth_site_magic_t *site_magic; su_time_t site_access; /**< Last request served */ /** Host header must match with server name */ unsigned site_strict : 1; /** Site can have kids */ unsigned site_isdir : 1; /** Site does not have domain name */ unsigned site_wildcard : 1; }; struct nth_request_s { server_t *req_server; http_method_t req_method; char const *req_method_name; url_t const *req_url; /**< RequestURI */ char const *req_version; tport_t *req_tport; msg_t *req_request; msg_t *req_response; auth_status_t *req_as; unsigned short req_status; unsigned req_close : 1; /**< Client asked for close */ unsigned req_in_callback : 1; unsigned req_destroyed : 1; }; /* ====================================================================== */ /* Debug log settings */ #define SU_LOG nth_server_log #ifdef SU_DEBUG_H #error included directly. #endif #include /**Environment variable determining the debug log level for @b nth * module. * * The NTH_DEBUG environment variable is used to determine the debug * logging level for @b nth module. The default level is 1. * * @sa , nth_server_log, SOFIA_DEBUG */ extern char const NTH_DEBUG[]; #ifndef SU_DEBUG #define SU_DEBUG 1 #endif /**Debug log for @b nth module. * * The nth_server_log is the log object used by @b nth module. The level of * #nth_server_log is set using #NTH_DEBUG environment variable. */ su_log_t nth_server_log[] = { SU_LOG_INIT("nth", "NTH_DEBUG", SU_DEBUG) }; #if HAVE_FUNC #elif HAVE_FUNCTION #define __func__ __FUNCTION__ #else static char const __func__[] = "nth"; #endif /* ====================================================================== */ /** Server side */ static server_t *server_create(url_t const *url, tag_type_t tag, tag_value_t value, ...); void server_destroy(server_t *srv); su_inline int server_timer_init(server_t *srv); static void server_timer(su_root_magic_t *rm, su_timer_t *timer, server_t *srv); su_inline uint32_t server_now(server_t const *srv); static void server_request(server_t *srv, tport_t *tport, msg_t *msg, void *arg, su_time_t now); static nth_site_t **site_get_host(nth_site_t **, char const *host, char const *port); static nth_site_t **site_get_rslot(nth_site_t *parent, char *path, char **return_rest); static nth_site_t *site_get_subdir(nth_site_t *parent, char const *path, char const **res); static void server_tport_error(server_t *srv, tport_t *tport, int errcode, char const *remote); static msg_t *server_msg_create(server_t *srv, int flags, char const data[], usize_t dlen, tport_t const *tp, tp_client_t *tpc); static void server_reply(server_t *srv, tport_t *tport, msg_t *request, msg_t *response, int status, char const *phrase); static void nth_site_request(server_t *srv, nth_site_t *site, tport_t *tport, msg_t *request, http_t *http, char const *path, msg_t *response); /* ---------------------------------------------------------------------- * 5) Site functions */ /** Create a http site object. * * The function nth_site_create() allocates and initializes a web site * object. A web site object can be either * - a primary http server (@a parent is NULL), * - a virtual http server (@a address contains hostpart), or * - a site within a server * (@a address does not have hostpart, only path part). * * @param parent pointer to parent site * (NULL when creating a primary server object) * @param callback pointer to callback function called when * a request is received * @param magic application context included in callback parameters * @param address absolute or relative URI specifying the address of * site * @param tag, value, ... list of tagged parameters * * @TAGS * If the @a parent is NULL, the list of tagged parameters must contain * NTHTAG_ROOT() used to create the server engine. Tags supported when @a * parent is NULL are NTHTAG_ROOT(), NTHTAG_MCLASS(), TPTAG_REUSE(), * HTTPTAG_SERVER(), and HTTPTAG_SERVER_STR(). All the tags are passed to * tport_tcreate() and tport_tbind(), too. * * @since Support for multiple sites was added to @VERSION_1_12_4 */ nth_site_t *nth_site_create(nth_site_t *parent, nth_request_f *callback, nth_site_magic_t *magic, url_string_t const *address, tag_type_t tag, tag_value_t value, ...) { nth_site_t *site = NULL, **prev = NULL; su_home_t home[SU_HOME_AUTO_SIZE(256)]; url_t *url, url0[1]; server_t *srv = NULL; ta_list ta; char *path = NULL; size_t usize; int is_host, is_path, wildcard = 0; su_home_auto(home, sizeof home); if (parent && url_is_string(address)) { char const *s = (char const *)address; size_t sep = strcspn(s, "/:"); if (parent->site_path) { /* subpath */ url_init(url0, (enum url_type_e)parent->site_url->url_type); url0->url_path = s; address = (url_string_t*)url0; } else if (s[sep] == ':') /* absolute URL with scheme */; else if (s[sep] == '\0' && strchr(s, '.') && host_is_valid(s)) { /* looks like a domain name */; url_init(url0, (enum url_type_e)parent->site_url->url_type); url0->url_host = s; address = (url_string_t*)url0; } else { /* looks like a path */ url_init(url0, (enum url_type_e)parent->site_url->url_type); url0->url_path = s; address = (url_string_t*)url0; } } url = url_hdup(home, address->us_url); if (!url || !callback) return NULL; is_host = url->url_host != NULL; is_path = url->url_path != NULL; if (is_host && is_path) { SU_DEBUG_3(("nth_site_create(): virtual host and path simultanously\n")); errno = EINVAL; goto error; } if (!parent && !is_host) { SU_DEBUG_3(("nth_site_create(): host is required\n")); errno = EINVAL; goto error; } if (parent) { if (!parent->site_isdir) { SU_DEBUG_3(("nth_site_create(): invalid parent resource \n")); errno = EINVAL; goto error; } srv = parent->site_server; assert(srv); if (is_host) { prev = site_get_host(&srv->srv_sites, url->url_host, url->url_port); if (prev == NULL) { SU_DEBUG_3(("nth_site_create(): host %s:%s already exists\n", url->url_host, url->url_port ? url->url_port : "")); errno = EEXIST; goto error; } } else { size_t i, j; path = (char *)url->url_path; while (path[0] == '/') path++; /* Remove duplicate // */ for (i = j = 0; path[i];) { while (path[i] == '/' && path[i + 1] == '/') i++; path[j++] = path[i++]; } path[j] = path[i]; url = url0, *url = *parent->site_url; if (url->url_path) { url->url_path = su_strcat(home, url->url_path, path); if (!url->url_path) goto error; path = (char *)url->url_path + strlen(parent->site_url->url_path); } else url->url_path = path; prev = site_get_rslot(parent, path, &path); if (!prev || path[0] == '\0') { SU_DEBUG_3(("nth_site_create(): directory \"%s\" already exists\n", url->url_path)); errno = EEXIST; goto error; } } } if (!parent) { if (strcmp(url->url_host, "*") == 0 || host_cmp(url->url_host, "0.0.0.0") == 0 || host_cmp(url->url_host, "::") == 0) wildcard = 1, url->url_host = "*"; } usize = sizeof(*url) + url_xtra(url); ta_start(ta, tag, value); if (!parent) { srv = server_create(url, ta_tags(ta)); prev = &srv->srv_sites; } if (srv && (site = su_zalloc(srv->srv_home, (sizeof *site) + usize))) { site->site_url = (url_t *)(site + 1); url_dup((void *)(site->site_url + 1), usize - sizeof(*url), site->site_url, url); assert(prev); if ((site->site_next = *prev)) site->site_next->site_prev = &site->site_next; *prev = site, site->site_prev = prev; site->site_server = srv; if (path) { size_t path_len; site->site_path = site->site_url->url_path + (path - url->url_path); path_len = strlen(site->site_path); assert(path_len > 0); if (path_len > 0 && site->site_path[path_len - 1] == '/') path_len--, site->site_isdir = 1; site->site_path_len = path_len; } else { site->site_isdir = is_host; site->site_path = ""; site->site_path_len = 0; } site->site_wildcard = wildcard; site->site_callback = callback; site->site_magic = magic; if (parent) site->site_auth = parent->site_auth; nth_site_set_params(site, ta_tags(ta)); } ta_end(ta); error: su_home_deinit(home); return site; } void nth_site_destroy(nth_site_t *site) { if (site == NULL) return; if (site->site_auth) auth_mod_unref(site->site_auth), site->site_auth = NULL; if (site->site_server->srv_sites == site) { server_destroy(site->site_server); } } nth_site_magic_t *nth_site_magic(nth_site_t const *site) { return site ? site->site_magic : NULL; } void nth_site_bind(nth_site_t *site, nth_request_f *callback, nth_site_magic_t *magic) { if (site) { site->site_callback = callback; site->site_magic = magic; } } /** Get the site URL. @NEW_1_12_4. */ url_t const *nth_site_url(nth_site_t const *site) { return site ? site->site_url : NULL; } /** Return server name and version */ char const *nth_site_server_version(void) { return "nth/" NTH_VERSION; } /** Get the time last time served. @NEW_1_12_4. */ su_time_t nth_site_access_time(nth_site_t const *site) { su_time_t const never = { 0, 0 }; return site ? site->site_access : never; } int nth_site_set_params(nth_site_t *site, tag_type_t tag, tag_value_t value, ...) { int n; ta_list ta; server_t *server; int master; msg_mclass_t const *mclass; int mflags; auth_mod_t *am; if (site == NULL) return (errno = EINVAL), -1; server = site->site_server; master = site == server->srv_sites; am = site->site_auth; mclass = server->srv_mclass; mflags = server->srv_mflags; ta_start(ta, tag, value); n = tl_gets(ta_args(ta), TAG_IF(master, NTHTAG_MCLASS_REF(mclass)), TAG_IF(master, NTHTAG_MFLAGS_REF(mflags)), NTHTAG_AUTH_MODULE_REF(am), TAG_END()); if (n > 0) { if (mclass) server->srv_mclass = mclass; else server->srv_mclass = http_default_mclass(); server->srv_mflags = mflags; auth_mod_ref(am), auth_mod_unref(site->site_auth), site->site_auth = am; } ta_end(ta); return n; } int nth_site_get_params(nth_site_t const *site, tag_type_t tag, tag_value_t value, ...) { int n; ta_list ta; server_t *server; int master; msg_mclass_t const *mclass; if (site == NULL) return (errno = EINVAL), -1; server = site->site_server; master = site == server->srv_sites; if (master && server->srv_mclass != http_default_mclass()) mclass = server->srv_mclass; else mclass = NULL; ta_start(ta, tag, value); n = tl_tgets(ta_args(ta), TAG_IF(master, NTHTAG_MCLASS(mclass)), TAG_IF(master, NTHTAG_MFLAGS(server->srv_mflags)), TAG_END()); ta_end(ta); return n; } int nth_site_get_stats(nth_site_t const *site, tag_type_t tag, tag_value_t value, ...) { int n; ta_list ta; if (site == NULL) return (errno = EINVAL), -1; ta_start(ta, tag, value); n = tl_tgets(ta_args(ta), TAG_END()); ta_end(ta); return n; } static nth_site_t **site_get_host(nth_site_t **list, char const *host, char const *port) { nth_site_t *site; assert(host); for (; (site = *list); list = &site->site_next) { if (host_cmp(host, site->site_url->url_host) == 0 && su_strcmp(port, site->site_url->url_port) == 0) { break; } } return list; } /** Find a place to insert site from the hierarchy. * * A resource can be either a 'dir' (name ends with '/') or 'file'. * When a resource */ static nth_site_t **site_get_rslot(nth_site_t *parent, char *path, char **return_rest) { nth_site_t *site, **prev; size_t len; int cmp; assert(path); if (path[0] == '\0') return errno = EEXIST, NULL; for (prev = &parent->site_kids; (site = *prev); prev = &site->site_next) { cmp = strncmp(path, site->site_path, len = site->site_path_len); if (cmp > 0) break; if (cmp < 0) continue; if (path[len] == '\0') { if (site->site_isdir) return *return_rest = path, prev; return errno = EEXIST, NULL; } if (path[len] != '/' || site->site_path[len] != '/') continue; while (path[++len] == '/') ; return site_get_rslot(site, path + len, return_rest); } *return_rest = path; return prev; } static char const site_nodir_match[] = ""; /** Find a subdir from site hierarchy */ static nth_site_t *site_get_subdir(nth_site_t *parent, char const *path, char const **return_rest) { nth_site_t *site; size_t len; int cmp; assert(path); while (path[0] == '/') /* Skip multiple slashes */ path++; if (path[0] == '\0') return *return_rest = path, parent; for (site = parent->site_kids; site; site = site->site_next) { cmp = strncmp(path, site->site_path, len = site->site_path_len); if (cmp > 0) break; if (cmp < 0) continue; if (path[len] == '\0') return *return_rest = site_nodir_match, site; if (site->site_path[len] == '/' && path[len] == '/') return site_get_subdir(site, path + len + 1, return_rest); } return *return_rest = path, parent; } /* ---------------------------------------------------------------------- * Server functions */ static char const * const http_tports[] = { "tcp", "tls", NULL }; static char const * const http_no_tls_tports[] = { "tcp", NULL }; static tp_stack_class_t nth_server_class[1] = {{ sizeof(nth_server_class), server_request, server_tport_error, server_msg_create }}; server_t *server_create(url_t const *url, tag_type_t tag, tag_value_t value, ...) { server_t *srv; msg_mclass_t const *mclass = NULL; tp_name_t tpn[1] = {{ NULL }}; su_root_t *root = NULL; http_server_t const *server = NULL; int persistent = 0; char const *server_str = SERVER_VERSION; ta_list ta; ta_start(ta, tag, value); tl_gets(ta_args(ta), NTHTAG_ROOT_REF(root), NTHTAG_MCLASS_REF(mclass), TPTAG_REUSE_REF(persistent), HTTPTAG_SERVER_REF(server), HTTPTAG_SERVER_STR_REF(server_str), TAG_END()); if (!root || !url || (url->url_type != url_http && url->url_type != url_https) || !(srv = su_home_new(sizeof(*srv)))) { ta_end(ta); return NULL; } tpn->tpn_proto = url_tport_default((enum url_type_e)url->url_type); tpn->tpn_canon = url->url_host; tpn->tpn_host = url->url_host; tpn->tpn_port = url_port(url); srv->srv_tports = tport_tcreate(srv, nth_server_class, root, TPTAG_IDLE(600000), TPTAG_TIMEOUT(300000), ta_tags(ta)); srv->srv_persistent = persistent; srv->srv_max_bodylen = 1 << 30; /* 1 GB */ if (tport_tbind(srv->srv_tports, tpn, http_tports, TAG_END()) >= 0 || tport_tbind(srv->srv_tports, tpn, http_no_tls_tports, TAG_END()) >= 0) { srv->srv_root = root; srv->srv_mclass = mclass ? mclass : http_default_mclass(); srv->srv_mflags = MSG_DO_CANONIC; if (server) srv->srv_server = http_server_dup(srv->srv_home, server); else srv->srv_server = http_server_make(srv->srv_home, server_str); tport_get_params(srv->srv_tports, TPTAG_QUEUESIZE_REF(srv->srv_queuesize), TAG_END()); } else { SU_DEBUG_1(("nth_server_create: cannot bind transports " URL_FORMAT_STRING "\n", URL_PRINT_ARGS(url))); server_destroy(srv), srv = NULL; } ta_end(ta); return srv; } void server_destroy(server_t *srv) { tport_destroy(srv->srv_tports); su_timer_destroy(srv->srv_timer); su_home_unref(srv->srv_home); } /** Initialize server timer. */ su_inline int server_timer_init(server_t *srv) { if (0) { srv->srv_timer = su_timer_create(su_root_task(srv->srv_root), SERVER_TICK); return su_timer_set(srv->srv_timer, server_timer, srv); } return 0; } /** * Server timer routine. */ static void server_timer(su_root_magic_t *rm, su_timer_t *timer, server_t *srv) { uint32_t now; su_timer_set(timer, server_timer, srv); now = su_time_ms(su_now()); now += now == 0; srv->srv_now = now; /* Xyzzy */ srv->srv_now = 0; } /** Get current timestamp in milliseconds */ su_inline uint32_t server_now(server_t const *srv) { if (srv->srv_now) return srv->srv_now; else return su_time_ms(su_now()); } /** Process incoming request message */ static void server_request(server_t *srv, tport_t *tport, msg_t *request, void *arg, su_time_t now) { nth_site_t *site = NULL, *subsite = NULL; msg_t *response; http_t *http = http_object(request); http_host_t *h; char const *host, *port, *path, *subpath = NULL; /* Disable streaming */ if (msg_is_streaming(request)) { msg_set_streaming(request, (enum msg_streaming_status)0); return; } /* Create a response message */ response = server_msg_create(srv, 0, NULL, 0, NULL, NULL); tport_tqueue(tport, response, TAG_END()); if (http && http->http_flags & MSG_FLG_TIMEOUT) { server_reply(srv, tport, request, response, 400, "Request timeout"); return; } else if (http && http->http_flags & MSG_FLG_TOOLARGE) { server_reply(srv, tport, request, response, HTTP_413_ENTITY_TOO_LARGE); return; } else if (!http || !http->http_request || (http->http_flags & MSG_FLG_ERROR)) { server_reply(srv, tport, request, response, HTTP_400_BAD_REQUEST); return; } if (http->http_request->rq_version != http_version_1_0 && http->http_request->rq_version != http_version_1_1) { server_reply(srv, tport, request, response, HTTP_505_HTTP_VERSION); return; } h = http->http_host; if (h) { host = h->h_host, port = h->h_port; } else if (http->http_request->rq_url->url_host) { host = http->http_request->rq_url->url_host; port = http->http_request->rq_url->url_port; } else host = NULL, port = NULL; path = http->http_request->rq_url->url_path; if (host) site = *site_get_host(&srv->srv_sites, host, port); if (site == NULL && !srv->srv_sites->site_strict) site = srv->srv_sites; if (path == NULL) path = ""; if (path[0]) subsite = site_get_subdir(site, path, &subpath); if (subsite) subsite->site_access = now; else site->site_access = now; if (subsite && subsite->site_isdir && subpath == site_nodir_match) { /* Answer with 301 */ http_location_t loc[1]; http_location_init(loc); *loc->loc_url = *site->site_url; if (site->site_wildcard) { if (http->http_host) { loc->loc_url->url_host = http->http_host->h_host; loc->loc_url->url_port = http->http_host->h_port; } else { tp_name_t const *tpn = tport_name(tport); assert(tpn); loc->loc_url->url_host = tpn->tpn_canon; if (strcmp(url_port_default((enum url_type_e)loc->loc_url->url_type), tpn->tpn_port)) loc->loc_url->url_port = tpn->tpn_port; } } loc->loc_url->url_root = 1; loc->loc_url->url_path = subsite->site_url->url_path; msg_header_add_dup(response, NULL, (msg_header_t *)loc); server_reply(srv, tport, request, response, HTTP_301_MOVED_PERMANENTLY); } else if (subsite) nth_site_request(srv, subsite, tport, request, http, subpath, response); else if (site) nth_site_request(srv, site, tport, request, http, path, response); else /* Answer with 404 */ server_reply(srv, tport, request, response, HTTP_404_NOT_FOUND); } static void server_tport_error(server_t *srv, tport_t *tport, int errcode, char const *remote) { su_log("\nth: tport: %s%s%s\n", remote ? remote : "", remote ? ": " : "", su_strerror(errcode)); } /** Respond without creating a request structure */ static void server_reply(server_t *srv, tport_t *tport, msg_t *request, msg_t *response, int status, char const *phrase) { http_t *http; http_payload_t *pl; int close; http_status_t st[1]; char const *req_version = NULL; if (status < 200 || status >= 600) status = 500, phrase = http_500_internal_server; http = http_object(request); if (http && http->http_request) req_version = http->http_request->rq_version; close = status >= 200 && (!srv->srv_persistent || status == 400 || (http && http->http_request && http->http_request->rq_version != http_version_1_1) || (http && http->http_connection && msg_params_find(http->http_connection->k_items, "close"))); msg_destroy(request); http = http_object(response); pl = http_payload_format(msg_home(response), "\n" "%u %s\n" "

%u %s

\n" "\n", status, phrase, status, phrase); msg_header_insert(response, (msg_pub_t *)http, (msg_header_t *)pl); if (req_version != http_version_0_9) { http_status_init(st); st->st_version = http_version_1_1; st->st_status = status; st->st_phrase = phrase; http_add_tl(response, http, HTTPTAG_STATUS(st), HTTPTAG_SERVER(srv->srv_server), HTTPTAG_CONTENT_TYPE_STR("text/html"), HTTPTAG_SEPARATOR_STR("\r\n"), TAG_IF(close, HTTPTAG_CONNECTION_STR("close")), TAG_END()); msg_serialize(response, (msg_pub_t *)http); } else { /* Just send the response */ *msg_chain_head(response) = (msg_header_t *)pl; close = 1; } if (tport_tqsend(tport, response, NULL, TPTAG_CLOSE_AFTER(close), TAG_END()) == -1) { SU_DEBUG_3(("server_reply(): cannot queue response\n")); tport_shutdown(tport, 2); } msg_destroy(response); } /** Create a new message for transport */ static msg_t *server_msg_create(server_t *srv, int flags, char const data[], usize_t dlen, tport_t const *tp, tp_client_t *tpc) { msg_t *msg = msg_create(srv->srv_mclass, srv->srv_mflags | flags); return msg; } /* ---------------------------------------------------------------------- * 6) Server transactions */ struct auth_info { nth_site_t *site; nth_request_t *req; http_t const *http; char const *path; }; static void nth_authentication_result(void *ai0, auth_status_t *as); static void nth_site_request(server_t *srv, nth_site_t *site, tport_t *tport, msg_t *request, http_t *http, char const *path, msg_t *response) { auth_mod_t *am = site->site_auth; nth_request_t *req; auth_status_t *as; struct auth_info *ai; size_t size = (am ? (sizeof *as) + (sizeof *ai) : 0) + (sizeof *req); int status; req = su_zalloc(srv->srv_home, size); if (req == NULL) { server_reply(srv, tport, request, response, HTTP_500_INTERNAL_SERVER); return; } if (am) as = auth_status_init(req + 1, sizeof *as), ai = (void *)(as + 1); else as = NULL, ai = NULL; req->req_server = srv; req->req_method = http->http_request->rq_method; req->req_method_name = http->http_request->rq_method_name; req->req_url = http->http_request->rq_url; req->req_version = http->http_request->rq_version; req->req_tport = tport_incref(tport); req->req_request = request; req->req_response = response; req->req_status = 100; req->req_close = !srv->srv_persistent || http->http_request->rq_version != http_version_1_1 || (http->http_connection && msg_params_find(http->http_connection->k_items, "close")); if (am) { static auth_challenger_t const http_server_challenger[] = {{ HTTP_401_UNAUTHORIZED, http_www_authenticate_class }}; req->req_as = as; as->as_method = http->http_request->rq_method_name; as->as_uri = path; if (http->http_payload) { as->as_body = http->http_payload->pl_data; as->as_bodylen = http->http_payload->pl_len; } auth_mod_check_client(am, as, http->http_authorization, http_server_challenger); if (as->as_status == 100) { /* Stall transport - do not read more requests */ if (tport_queuelen(tport) * 2 >= srv->srv_queuesize) tport_stall(tport); as->as_callback = nth_authentication_result; as->as_magic = ai; ai->site = site; ai->req = req; ai->http = http; ai->path = path; return; } else if (as->as_status) { assert(as->as_status >= 200); nth_request_treply(req, as->as_status, as->as_phrase, HTTPTAG_HEADER((http_header_t *)as->as_response), HTTPTAG_HEADER((http_header_t *)as->as_info), TAG_END()); nth_request_destroy(req); return; } } req->req_in_callback = 1; status = site->site_callback(site->site_magic, site, req, http, path); req->req_in_callback = 0; if (status != 0 && (status < 100 || status >= 600)) status = 500; if (status != 0 && req->req_status < 200) { nth_request_treply(req, status, NULL, TAG_END()); } if (req->req_status < 100) { /* Stall transport - do not read more requests */ if (tport_queuelen(tport) * 2 >= srv->srv_queuesize) tport_stall(tport); } if (status >= 200 || req->req_destroyed) nth_request_destroy(req); } static void nth_authentication_result(void *ai0, auth_status_t *as) { struct auth_info *ai = ai0; nth_request_t *req = ai->req; int status; if (as->as_status != 0) { assert(as->as_status >= 300); nth_request_treply(req, status = as->as_status, as->as_phrase, HTTPTAG_HEADER((http_header_t *)as->as_response), TAG_END()); } else { req->req_in_callback = 1; status = ai->site->site_callback(ai->site->site_magic, ai->site, ai->req, ai->http, ai->path); req->req_in_callback = 0; if (status != 0 && (status < 100 || status >= 600)) status = 500; if (status != 0 && req->req_status < 200) { nth_request_treply(req, status, NULL, TAG_END()); } } if (status >= 200 || req->req_destroyed) nth_request_destroy(req); } void nth_request_destroy(nth_request_t *req) { if (req == NULL) return; if (req->req_status < 200) nth_request_treply(req, HTTP_500_INTERNAL_SERVER, TAG_END()); req->req_destroyed = 1; if (req->req_in_callback) return; if (req->req_as) su_home_deinit(req->req_as->as_home); tport_decref(&req->req_tport), req->req_tport = NULL; msg_destroy(req->req_request), req->req_request = NULL; msg_destroy(req->req_response), req->req_response = NULL; su_free(req->req_server->srv_home, req); } /** Return request authentication status. * * @param req pointer to HTTP request object * * @retval Status code * * @since New in @VERSION_1_12_4 */ int nth_request_status(nth_request_t const *req) { return req ? req->req_status : 400; } /** Return request authentication status. * * @param req pointer to HTTP request object * * @retval Pointer to authentication status struct * * @note The authentication status struct is freed when the #nth_request_t * object is destroyed. * * @since New in @VERSION_1_12_4 * * @sa AUTH */ auth_status_t *nth_request_auth(nth_request_t const *req) { return req ? req->req_as : NULL; } http_method_t nth_request_method(nth_request_t const *req) { return req ? req->req_method : http_method_invalid; } msg_t *nth_request_message(nth_request_t *req) { msg_t *retval = NULL; if (req) retval = msg_ref(req->req_request); return retval; } int nth_request_treply(nth_request_t *req, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...) { msg_t *response, *next = NULL; http_t *http; int retval = -1; int req_close, close; ta_list ta; http_header_t const *as_info = NULL; if (req == NULL || status < 100 || status >= 600) { return -1; } response = req->req_response; http = http_object(response); if (status >= 200 && req->req_as) as_info = (http_header_t const *)req->req_as->as_info; ta_start(ta, tag, value); http_add_tl(response, http, HTTPTAG_SERVER(req->req_server->srv_server), HTTPTAG_HEADER(as_info), ta_tags(ta)); if (http->http_payload && !http->http_content_length) { http_content_length_t *l; http_payload_t *pl; size_t len = 0; for (pl = http->http_payload; pl; pl = pl->pl_next) len += pl->pl_len; if (len > UINT32_MAX) goto fail; l = http_content_length_create(msg_home(response), (uint32_t)len); msg_header_insert(response, (msg_pub_t *)http, (msg_header_t *)l); } if (req->req_method == http_method_head && http->http_payload) { http_payload_t *pl; for (pl = http->http_payload; pl; pl = pl->pl_next) msg_header_remove(response, (msg_pub_t *)http, (msg_header_t *)pl); } http_complete_response(response, status, phrase, http_object(req->req_request)); if (!http->http_date) { http_date_t date[1]; http_date_init(date)->d_time = msg_now(); msg_header_add_dup(response, (msg_pub_t *)http, (msg_header_t*)date); } if (status < 200) { close = 0; next = server_msg_create(req->req_server, 0, NULL, 0, NULL, NULL); } else { req_close = req->req_close; close = (http->http_connection && msg_params_find(http->http_connection->k_items, "close")); if (req_close && !close && status >= 200) { close = 1; http_add_tl(response, http, HTTPTAG_CONNECTION_STR("close"), TAG_END()); } } msg_serialize(response, (msg_pub_t *)http); retval = tport_tqsend(req->req_tport, response, next, TAG_IF(close, TPTAG_CLOSE_AFTER(1)), ta_tags(ta)); fail: ta_end(ta); if (retval == 0) req->req_status = status; return retval; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nth/nth_tag.c000066400000000000000000000052551223300710500221420ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE nth_tag.c * @brief Tags for HTTP Transaction API * * @note This file is used to automatically generate * nth_tag_ref.c and nth_tag_dll.c * * @author Pekka Pessi * * @date Created: Tue Jul 24 22:28:34 2001 ppessi */ #include "config.h" #include #include #define TAG_NAMESPACE "nth" #include "sofia-sip/nth_tag.h" #include #include #include #include tag_typedef_t nthtag_any = NSTAG_TYPEDEF(*); /* Common */ tag_typedef_t nthtag_mclass = PTRTAG_TYPEDEF(mclass); tag_typedef_t nthtag_message = PTRTAG_TYPEDEF(message); tag_typedef_t nthtag_mflags = INTTAG_TYPEDEF(mflags); tag_typedef_t nthtag_streaming = BOOLTAG_TYPEDEF(streaming); /* Client */ tag_typedef_t nthtag_proxy = URLTAG_TYPEDEF(proxy); tag_typedef_t nthtag_expires = UINTTAG_TYPEDEF(expires); tag_typedef_t nthtag_error_msg = BOOLTAG_TYPEDEF(error_msg); tag_typedef_t nthtag_template = PTRTAG_TYPEDEF(template); tag_typedef_t nthtag_authentication = PTRTAG_TYPEDEF(authentication); /* Server */ tag_typedef_t nthtag_root = PTRTAG_TYPEDEF(root); tag_typedef_t nthtag_strict_host = BOOLTAG_TYPEDEF(scrict_host); /**@def NTHTAG_AUTH_MODULE() * * Pointer to authentication module. * * A site requires authentication from the clients if passed an * authentication module pointer with NTHTAG_AUTH_MODULE(). Incoming client * request is challenged with 401, upon successful authentication the * authenticated username is stored in the #auth_status_t structure * associated with the #nth_request_t object. It is up to application to * authorize the user. * * @sa nth_site_create(), nth_site_set_params(), nth_request_auth(). */ tag_typedef_t nthtag_auth_module = PTRTAG_TYPEDEF(auth_module); sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nth/sofia-sip/000077500000000000000000000000001223300710500222355ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nth/sofia-sip/nth.h000066400000000000000000000140271223300710500232030ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@file sofia-sip/nth.h * @brief Transaction API for HTTP * * @author Pekka Pessi . * * @date Created: Wed Jun 5 19:25:18 2002 ppessi */ /* ---------------------------------------------------------------------- * 1) Types */ #ifndef NTH_H_TYPES #define NTH_H_TYPES /** NTH engine */ typedef struct nth_engine_s nth_engine_t; /** NTH client request */ typedef struct nth_client_s nth_client_t; /** NTH (virtual) hosts or site(s) */ typedef struct nth_site_s nth_site_t; /** Server transaction */ typedef struct nth_request_s nth_request_t; #ifndef NTH_CLIENT_MAGIC_T /** Default type of application context for client NTH requests. * Application may define this to appropriate type before including * . */ #define NTH_CLIENT_MAGIC_T struct nth_client_magic_s #endif /** Application context for client requests */ typedef NTH_CLIENT_MAGIC_T nth_client_magic_t; #ifndef NTH_SITE_MAGIC_T /** Default type of application context for NTH servers. * Application may define this to appropriate type before including * . */ #define NTH_SITE_MAGIC_T struct nth_site_magic_s #endif /** Application context for NTH servers */ typedef NTH_SITE_MAGIC_T nth_site_magic_t; #endif #ifndef NTH_H /** Defined when has been included. */ #define NTH_H /* ---------------------------------------------------------------------- * 2) Constants */ /** Version number */ #define NTH_VERSION "1.0" #define NTH_CLIENT_VERSION NTH_VERSION #define NTH_SERVER_VERSION NTH_VERSION /* ---------------------------------------------------------------------- * 3) Other include files */ #include #include #include #include #ifndef NTH_TAG_H #include #endif /* ---------------------------------------------------------------------- * 3) Engine prototypes */ SOFIA_BEGIN_DECLS NTH_DLL char const *nth_engine_version(void); NTH_DLL nth_engine_t *nth_engine_create(su_root_t *root, tag_type_t tag, tag_value_t value, ...); NTH_DLL void nth_engine_destroy(nth_engine_t *engine); NTH_DLL int nth_engine_set_params(nth_engine_t *engine, tag_type_t tag, tag_value_t value, ...); NTH_DLL int nth_engine_get_params(nth_engine_t const *engine, tag_type_t tag, tag_value_t value, ...); NTH_DLL int nth_engine_get_stats(nth_engine_t const *engine, tag_type_t tag, tag_value_t value, ...); NTH_DLL msg_t *nth_engine_msg_create(nth_engine_t *he, int flags); /* ---------------------------------------------------------------------- * 4) Prototypes for client transactions */ typedef int nth_response_f(nth_client_magic_t *magic, nth_client_t *request, http_t const *http); NTH_DLL nth_client_t *nth_client_tcreate(nth_engine_t *engine, nth_response_f *callback, nth_client_magic_t *magic, http_method_t method, char const *method_name, url_string_t const *request_uri, tag_type_t tag, tag_value_t value, ...); NTH_DLL int nth_client_status(nth_client_t const *clnt); NTH_DLL http_method_t nth_client_method(nth_client_t const *cnlt); NTH_DLL int nth_client_is_streaming(nth_client_t const *hc); NTH_DLL url_t const *nth_client_url(nth_client_t const *clnt); NTH_DLL msg_t *nth_client_request(nth_client_t *clnt); NTH_DLL msg_t *nth_client_response(nth_client_t const *clnt); NTH_DLL void nth_client_destroy(nth_client_t *clnt); /* ---------------------------------------------------------------------- * 5) Server side prototypes */ typedef int nth_request_f(nth_site_magic_t *lmagic, nth_site_t *server, nth_request_t *req, http_t const *http, char const *path); char const *nth_site_server_version(void); NTH_DLL nth_site_t *nth_site_create(nth_site_t *parent, nth_request_f *req_callback, nth_site_magic_t *magic, url_string_t const *address, tag_type_t tag, tag_value_t value, ...); NTH_DLL void nth_site_destroy(nth_site_t *site); NTH_DLL nth_site_magic_t *nth_site_magic(nth_site_t const *site); NTH_DLL void nth_site_bind(nth_site_t *site, nth_request_f *callback, nth_site_magic_t *); NTH_DLL su_time_t nth_site_access_time(nth_site_t const *site); NTH_DLL int nth_site_set_params(nth_site_t *site, tag_type_t tag, tag_value_t value, ...); NTH_DLL int nth_site_get_params(nth_site_t const *site, tag_type_t tag, tag_value_t value, ...); NTH_DLL int nth_site_get_stats(nth_site_t const *site, tag_type_t tag, tag_value_t value, ...); NTH_DLL url_t const *nth_site_url(nth_site_t const *site); /* ---------------------------------------------------------------------- * 6) Prototypes for server transactions */ NTH_DLL int nth_request_status(nth_request_t const *req); NTH_DLL http_method_t nth_request_method(nth_request_t const *req); NTH_DLL msg_t *nth_request_message(nth_request_t *req); NTH_DLL int nth_request_treply(nth_request_t *ireq, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...); NTH_DLL void nth_request_destroy(nth_request_t *req); NTH_DLL struct auth_status_t *nth_request_auth(nth_request_t const *req); SOFIA_END_DECLS #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nth/sofia-sip/nth_tag.h000066400000000000000000000144761223300710500240460ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef NTH_TAG_H /** Defined when has been included. */ #define NTH_TAG_H /**@file sofia-sip/nth_tag.h * @brief Tags for @b nth, HTTP engine module. * * @author Pekka Pessi * * @date Created: Sun Oct 13 22:23:48 2002 ppessi */ #ifndef SU_TAG_H #include #endif #ifndef URL_TAG_H #include #endif #ifndef HTTP_TAG_H #include #endif SOFIA_BEGIN_DECLS /** List of all nth tags */ NTH_DLL extern tagi_t nth_client_tags[]; /** Filter tag matching any nth tag. */ #define NTHTAG_ANY() nthtag_any, ((tag_value_t)0) NTH_DLL extern tag_typedef_t nthtag_any; /* Common tags */ NTH_DLL extern tag_typedef_t nthtag_mclass; /** Pointer to a mclass, message factory object. @HI */ #define NTHTAG_MCLASS(x) nthtag_mclass, tag_cptr_v((x)) NTH_DLL extern tag_typedef_t nthtag_mclass_ref; #define NTHTAG_MCLASS_REF(x) nthtag_mclass_ref, tag_cptr_vr(&(x), (x)) NTH_DLL extern tag_typedef_t nthtag_mflags; /** Message flags used by nth_engine_msg_create()/nth_site_msg(). @HI */ #define NTHTAG_MFLAGS(x) nthtag_mflags, tag_int_v((x)) NTH_DLL extern tag_typedef_t nthtag_mflags_ref; #define NTHTAG_MFLAGS_REF(x) nthtag_mflags_ref, tag_int_vr(&(x)) NTH_DLL extern tag_typedef_t nthtag_streaming; /** Enable streaming. @HI */ #define NTHTAG_STREAMING(x) nthtag_streaming, tag_bool_v((x)) NTH_DLL extern tag_typedef_t nthtag_streaming_ref; #define NTHTAG_STREAMING_REF(x) nthtag_streaming_ref, tag_bool_vr(&(x)) /* Client-only tags */ NTH_DLL extern tag_typedef_t nthtag_proxy; /** URL for (default) proxy. @HI */ #define NTHTAG_PROXY(x) nthtag_proxy, urltag_url_v((x)) NTH_DLL extern tag_typedef_t nthtag_proxy_ref; #define NTHTAG_PROXY_REF(x) nthtag_proxy_ref, urltag_url_vr(&(x)) NTH_DLL extern tag_typedef_t nthtag_expires; /** Expires in milliseconds for client transactions. @HI */ #define NTHTAG_EXPIRES(x) nthtag_expires, tag_uint_v((x)) NTH_DLL extern tag_typedef_t nthtag_expires_ref; #define NTHTAG_EXPIRES_REF(x) nthtag_expires_ref, tag_uint_vr(&(x)) NTH_DLL extern tag_typedef_t nthtag_error_msg; /** If true, nth engine generates complete error messages. @HI */ #define NTHTAG_ERROR_MSG(x) nthtag_error_msg, tag_bool_v((x)) NTH_DLL extern tag_typedef_t nthtag_error_msg_ref; #define NTHTAG_ERROR_MSG_REF(x) nthtag_error_msg_ref, tag_bool_vr(&(x)) #if SU_INLINE_TAG_CAST struct nth_client_s; su_inline tag_value_t nthtag_template_v(struct nth_client_s const *v) { return (tag_value_t)v; } su_inline tag_value_t nthtag_template_vr(struct nth_client_s const **vp) {return(tag_value_t)vp;} #else #define nthtag_template_v(v) ((tag_value_t)(v)) #define nthtag_template_vr(vp) ((tag_value_t)(vp)) #endif NTH_DLL extern tag_typedef_t nthtag_template; /** Use existing client request as template. @HI */ #define NTHTAG_TEMPLATE(x) nthtag_template, nthtag_template_v((x)) NTH_DLL extern tag_typedef_t nthtag_template_ref; #define NTHTAG_TEMPLATE_REF(x) nthtag_template_ref, nthtag_template_vr(&(x)) #if SU_INLINE_TAG_CAST su_inline tag_value_t nthtag_message_v(struct msg_s *v) { return (tag_value_t)v; } su_inline tag_value_t nthtag_message_vr(struct msg_s **vp) { return(tag_value_t)vp; } #else #define nthtag_message_v(v) ((tag_value_t)(v)) #define nthtag_message_vr(vp) ((tag_value_t)(vp)) #endif NTH_DLL extern tag_typedef_t nthtag_message; /** Use existing request message. @HI */ #define NTHTAG_MESSAGE(x) nthtag_message, nthtag_message_v((x)) NTH_DLL extern tag_typedef_t nthtag_message_ref; #define NTHTAG_MESSAGE_REF(x) nthtag_message_ref, nthtag_message_vr(&(x)) #if SU_HAVE_INLINE struct auth_client_s; su_inline tag_value_t nthtag_authentication_v(struct auth_client_s **v) { return (tag_value_t)v; } su_inline tag_value_t nthtag_authentication_vr(struct auth_client_s ***vp) {return(tag_value_t)vp;} #else #define nthtag_authentication_v(v) ((tag_value_t)(v)) #define nthtag_authentication_vr(vp) ((tag_value_t)(vp)) #endif NTH_DLL extern tag_typedef_t nthtag_authentication; /** Use stack of authenticators. @HI */ #define NTHTAG_AUTHENTICATION(x) \ nthtag_authentication, nthtag_authentication_v((x)) NTH_DLL extern tag_typedef_t nthtag_authentication_ref; #define NTHTAG_AUTHENTICATION_REF(x) \ nthtag_authentication_ref, nthtag_authentication_vr(&(x)) NTH_DLL extern tag_typedef_t nthtag_max_retry_after; /** Maximum value for retry interval. @HI */ #define NTHTAG_MAX_RETRY_AFTER(x) nthtag_max_retry_after, tag_int_v((x)) NTH_DLL extern tag_typedef_t nthtag_max_retry_after_ref; #define NTHTAG_MAX_RETRY_AFTER_REF(x) \ nthtag_max_retry_after_ref, tag_int_vr(&(x)) /* Server-side tags */ NTH_DLL extern tag_typedef_t nthtag_root; /** Pointer to root reactor object. @HI */ #define NTHTAG_ROOT(x) nthtag_root, tag_ptr_v((x)) NTH_DLL extern tag_typedef_t nthtag_root_ref; #define NTHTAG_ROOT_REF(x) nthtag_root_ref, tag_ptr_vr(&(x), (x)) NTH_DLL extern tag_typedef_t nthtag_strict_host; /** Do not serve requests to mismatching hosts by default host. @HI */ #define NTHTAG_STRICT_HOST(x) nthtag_strict_host, tag_bool_v((x)) NTH_DLL extern tag_typedef_t nthtag_strict_host_ref; #define NTHTAG_STRICT_HOST_REF(x) nthtag_strict_host_ref, tag_bool_vr(&(x)) NTH_DLL extern tag_typedef_t nthtag_auth_module; /** Pointer to authentication module. @HI. @NEW_1_12_4. */ #define NTHTAG_AUTH_MODULE(x) nthtag_auth_module, tag_ptr_v((x)) NTH_DLL extern tag_typedef_t nthtag_auth_module_ref; #define NTHTAG_AUTH_MODULE_REF(x) nthtag_auth_module_ref, tag_ptr_vr(&(x), (x)) SOFIA_END_DECLS #endif /* !defined NTH_TAG_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nth/test_nth.c000066400000000000000000000554471223300710500223560ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@file test_nth.c * @brief Tests for nth module * * @author Pekka Pessi * * @date Created: Tue Oct 22 20:52:37 2002 ppessi */ #include "config.h" #include #include #include #include #include #if HAVE_ALARM #include #include #endif typedef struct tester tester_t; typedef struct site site_t; typedef struct client client_t; #define SU_ROOT_MAGIC_T tester_t #include #include #define NTH_CLIENT_MAGIC_T client_t #define NTH_SITE_MAGIC_T site_t #include "sofia-sip/nth.h" #include #include #include #include int tstflags = 0; #define TSTFLAGS tstflags #include #if HAVE_FUNC #elif HAVE_FUNCTION #define __func__ __FUNCTION__ #else #define __func__ name #endif char const name[] = "test_nth"; static int init_test(tester_t *t); static int deinit_test(tester_t *t); static int test_nth_client_api(tester_t *t); static int test_nth_server_api(tester_t *t); static int init_server(tester_t *t); static int test_requests(tester_t *t); static int init_engine(tester_t *t); struct site { site_t *s_next, *s_parent; tester_t *s_tester; url_string_t *s_url; nth_site_t *s_ns; int s_called; int s_status; char const *s_phrase; tagi_t *s_tags; }; struct client { unsigned c_status; }; struct tester { su_home_t t_home[1]; su_root_t *t_root; msg_mclass_t *t_mclass; url_string_t *t_proxy; nth_engine_t *t_engine; char const *t_srcdir; char const *t_pem; su_sockaddr_t t_addr[1]; socklen_t t_addrlen; su_socket_t t_sink; url_string_t *t_sinkuri; su_sockaddr_t t_sinkaddr[1]; socklen_t t_sinkaddrlen; site_t *t_sites; site_t *t_master; }; static int test_site(site_t *t, nth_site_t *server, nth_request_t *req, http_t const *http, char const *path); static site_t *site_create(tester_t *t, site_t *parent, char const *url, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...) { nth_site_t *pns = parent ? parent->s_ns : NULL; site_t *s; ta_list ta; if (url == NULL) return NULL; s = su_zalloc(t->t_home, sizeof *s); if (s == NULL) return NULL; s->s_url = URL_STRING_MAKE(url); s->s_tester = t; s->s_next = t->t_sites; s->s_status = status; s->s_phrase = phrase; ta_start(ta, tag, value); s->s_tags = tl_adup(t->t_home, ta_args(ta)); if (s->s_tags) s->s_ns = nth_site_create(pns, test_site, s, (url_string_t *)s->s_url, NTHTAG_ROOT(t->t_root), ta_tags(ta)); ta_end(ta); if (s->s_ns == NULL) return NULL; t->t_sites = s; return s; } static int init_test(tester_t *t) { su_socket_t s; BEGIN(); t->t_root = su_root_create(t); TEST_1(t->t_root); t->t_mclass = msg_mclass_clone(http_default_mclass(), 0, 0); TEST_1(t->t_mclass); t->t_addr->su_len = (sizeof t->t_addr->su_sin); s = su_socket(t->t_addr->su_family = AF_INET, SOCK_STREAM, 0); TEST_1(s != INVALID_SOCKET); TEST_1(su_inet_pton(AF_INET, "127.0.0.1", &t->t_addr->su_sin.sin_addr) >= 0); TEST_1(bind(s, &t->t_addr->su_sa, t->t_addrlen = (sizeof t->t_addr->su_sin)) != -1); TEST_1(getsockname(s, &t->t_addr->su_sa, &t->t_addrlen) != -1); TEST_1(t->t_addr->su_port != 0); TEST_1(su_close(s) != -1); t->t_pem = su_sprintf(t->t_home, "%s/agent.pem", t->t_srcdir); END(); } static int deinit_test(tester_t *t) { site_t *s, *s_next; BEGIN(); nth_engine_destroy(t->t_engine); for (s = t->t_sites; s; s = s_next) { s_next = s->s_next; nth_site_destroy(s->s_ns), s->s_ns = NULL; su_free(t->t_home, s); } su_root_destroy(t->t_root); su_home_deinit(t->t_home); memset(t, 0, sizeof t); END(); } static int test_nth_client_api(tester_t *t) { char const *s; BEGIN(); s = nth_engine_version(); TEST_1(s); TEST_1(strlen(s)); TEST_S(s, "sofia-http-client/" NTH_CLIENT_VERSION); TEST_1(nth_engine_create(NULL, TAG_END()) == NULL); TEST(errno, EINVAL); TEST_VOID(nth_engine_destroy(NULL)); TEST_1(nth_engine_get_params(NULL, TAG_END()) == -1); TEST_1(nth_engine_set_params(NULL, TAG_END()) == -1); TEST_1(!nth_client_tcreate(NULL, NULL, NULL, HTTP_METHOD_OPTIONS, URL_STRING_MAKE("*"), TAG_END())); TEST(nth_client_status(NULL), 400); TEST(nth_client_method(NULL), http_method_invalid); TEST(nth_client_is_streaming(NULL), 0); TEST_P(nth_client_url(NULL), NULL); TEST_P(nth_client_request(NULL), NULL); TEST_P(nth_client_response(NULL), NULL); TEST_VOID(nth_client_destroy(NULL)); t->t_engine = nth_engine_create(t->t_root, NTHTAG_ERROR_MSG(2), NTHTAG_MCLASS(t->t_mclass), NTHTAG_MFLAGS(MSG_DO_CANONIC|MSG_DO_COMPACT), NTHTAG_STREAMING(0), NTHTAG_PROXY("http://localhost:8888"), TAG_END()); TEST_1(t->t_engine); { int error_msg = -1; msg_mclass_t const *mclass = (void *)-1; int mflags = -1; unsigned expires = -1; int streaming = -1; url_string_t const *proxy = (void *)-1; char *proxy_str; TEST(nth_engine_get_params(t->t_engine, NTHTAG_ERROR_MSG_REF(error_msg), NTHTAG_MCLASS_REF(mclass), NTHTAG_MFLAGS_REF(mflags), NTHTAG_EXPIRES_REF(expires), NTHTAG_STREAMING_REF(streaming), NTHTAG_PROXY_REF(proxy), TAG_END()), 6); TEST(error_msg, 1); TEST_P(mclass, t->t_mclass); TEST(mflags, MSG_DO_CANONIC|MSG_DO_COMPACT); TEST(expires, 32000); TEST(streaming, 0); TEST_1(proxy != NULL); TEST_1(proxy_str = url_as_string(t->t_home, proxy->us_url)); TEST_S(proxy_str, "http://localhost:8888"); proxy = URL_STRING_MAKE("http://127.0.0.1:80"); TEST(nth_engine_set_params(t->t_engine, NTHTAG_ERROR_MSG(0), NTHTAG_MCLASS(http_default_mclass()), NTHTAG_MFLAGS(0), NTHTAG_EXPIRES(10000), NTHTAG_STREAMING(2), NTHTAG_PROXY(proxy), TAG_END()), 6); error_msg = -1; mclass = (void *)-1; mflags = -1; expires = (unsigned)-1; streaming = -1; proxy = (void *)-1; TEST(nth_engine_get_params(t->t_engine, NTHTAG_ERROR_MSG_REF(error_msg), NTHTAG_MCLASS_REF(mclass), NTHTAG_MFLAGS_REF(mflags), NTHTAG_EXPIRES_REF(expires), NTHTAG_STREAMING_REF(streaming), NTHTAG_PROXY_REF(proxy), TAG_END()), 6); TEST(error_msg, 0); TEST_P(mclass, NULL); TEST(mflags, 0); TEST(expires, 10000); TEST(streaming, 1); TEST_1(proxy != NULL); TEST_1(proxy_str = url_as_string(t->t_home, proxy->us_url)); TEST_S(proxy_str, "http://127.0.0.1:80"); } TEST_1(nth_engine_get_stats(NULL, TAG_END()) == -1); { msg_t *msg; http_t *http; TEST_1(nth_engine_msg_create(NULL, -1) == NULL); TEST_1(msg = nth_engine_msg_create(t->t_engine, -1)); TEST_1(http = http_object(msg)); TEST(http->http_flags, MSG_FLG_USERMASK); msg_destroy(msg); /* Use mflags set by set_params (+ streaming flag) */ TEST_1(msg = nth_engine_msg_create(t->t_engine, 0)); TEST_1(http = http_object(msg)); TEST(http->http_flags, MSG_FLG_STREAMING | t->t_mclass->mc_flags); msg_destroy(msg); } TEST_VOID(nth_engine_destroy(t->t_engine)); t->t_engine = NULL; END(); } static int site_check_all(site_t *t, nth_site_t *server, nth_request_t *req, http_t const *http, char const *path); static int test_nth_server_api(tester_t *t) { char const *v; site_t s[1]; BEGIN(); memset(s, 0, sizeof s); v = nth_site_server_version(); TEST_1(v); TEST_1(strlen(v)); TEST_S(v, "nth/" NTH_SERVER_VERSION); /* Fails because no parent site, no root */ TEST_1(!nth_site_create(NULL, test_site, s, URL_STRING_MAKE("http://127.0.0.1:8888"), TAG_END())); /* Fails because url specifies both host and path */ TEST_1(!nth_site_create(NULL, site_check_all, s, URL_STRING_MAKE("http://127.0.0.1:8888/foo/"), NTHTAG_ROOT(t->t_root), TAG_END())); TEST_VOID(nth_site_destroy(NULL)); TEST_P(nth_site_magic(NULL), NULL); TEST_VOID(nth_site_bind(NULL, test_site, s)); TEST_1(nth_site_set_params(NULL, TAG_END()) == -1); TEST_1(nth_site_get_params(NULL, TAG_END()) == -1); TEST_1(nth_site_get_stats(NULL, TAG_END()) == -1); TEST(nth_request_status(NULL), 400); TEST(nth_request_method(NULL), http_method_invalid); TEST_P(nth_request_message(NULL), NULL); TEST_1(nth_request_treply(NULL, HTTP_200_OK, TAG_END()) == -1); TEST_VOID(nth_request_destroy(NULL)); END(); } static int test_site(site_t *s, nth_site_t *ns, nth_request_t *req, http_t const *http, char const *path) { if (s == NULL || ns == NULL || req == NULL) return 500; TEST_1(nth_request_treply(req, s->s_status, s->s_phrase, TAG_NEXT(s->s_tags)) != -1); TEST_VOID(nth_request_destroy(req)); return s->s_status; } static int site_check_all(site_t *s, nth_site_t *ns, nth_request_t *req, http_t const *http, char const *path) { msg_t *msg; auth_status_t *as; TEST_1(s); TEST_1(ns); TEST_1(req); TEST_1(http); TEST_1(path); if (s == NULL || ns == NULL || req == NULL) return 500; TEST(nth_request_status(req), 0); TEST(nth_request_method(req), http_method_get); TEST_1(msg = nth_request_message(req)); msg_destroy(msg); as = nth_request_auth(req); TEST_1(nth_request_treply(req, s->s_status, s->s_phrase, TAG_NEXT(s->s_tags)) != -1); TEST_VOID(nth_request_destroy(req)); return s->s_status; } static char passwd_name[] = "tmp_sippasswd.XXXXXX"; static void remove_tmp(void) { if (passwd_name[0]) unlink(passwd_name); } static char const passwd[] = "alice:secret:\n" "bob:secret:\n" "charlie:secret:\n"; static int init_server(tester_t *t) { BEGIN(); site_t *m = t->t_master, *sub2; auth_mod_t *am; int temp; TEST_1(t->t_master = m = site_create(t, NULL, su_sprintf(t->t_home, "HTTP://127.0.0.1:%u", htons(t->t_addr->su_port)), HTTP_200_OK, HTTPTAG_CONTENT_TYPE_STR("text/html"), HTTPTAG_PAYLOAD_STR("Hello\n"), TPTAG_CERTIFICATE(t->t_pem), TAG_END())); TEST_1(site_create(t, m, "/sub/sub", HTTP_200_OK, HTTPTAG_CONTENT_TYPE_STR("text/html"), HTTPTAG_PAYLOAD_STR ("sub/sub\n"), TAG_END())); TEST_1(site_create(t, m, "/sub/", HTTP_200_OK, HTTPTAG_CONTENT_TYPE_STR("text/html"), HTTPTAG_PAYLOAD_STR("sub/\n"), TAG_END())); TEST_1(site_create(t, m, "/sub/sub/", HTTP_200_OK, HTTPTAG_CONTENT_TYPE_STR("text/html"), HTTPTAG_PAYLOAD_STR ("sub/sub/\n"), TAG_END())); TEST_1(sub2 = site_create(t, m, "/sub2/", HTTP_200_OK, HTTPTAG_CONTENT_TYPE_STR("text/html"), HTTPTAG_PAYLOAD_STR("sub2/\n"), TAG_END())); TEST_1(site_create(t, sub2, "sub/", HTTP_200_OK, HTTPTAG_CONTENT_TYPE_STR("text/html"), HTTPTAG_PAYLOAD_STR ("sub2/sub/\n"), TAG_END())); #ifndef _WIN32 temp = mkstemp(passwd_name); #else temp = open(passwd_name, O_WRONLY|O_CREAT|O_TRUNC, 666); #endif TEST_1(temp != -1); atexit(remove_tmp); /* Make sure temp file is unlinked */ TEST_SIZE(write(temp, passwd, strlen(passwd)), strlen(passwd)); TEST_1(close(temp) == 0); am = auth_mod_create(t->t_root, AUTHTAG_METHOD("Digest"), AUTHTAG_REALM("auth"), AUTHTAG_DB(passwd_name), TAG_END()); TEST_1(am); TEST_1(site_create(t, m, "auth/", HTTP_200_OK, HTTPTAG_CONTENT_TYPE_STR("text/html"), HTTPTAG_PAYLOAD_STR ("auth/\n"), NTHTAG_AUTH_MODULE(am), TAG_END())); auth_mod_unref(am); am = auth_mod_create(t->t_root, AUTHTAG_METHOD("Delayed+Basic"), AUTHTAG_REALM("auth2"), AUTHTAG_DB(passwd_name), TAG_END()); TEST_1(am); TEST_1(site_create(t, m, "auth2/", HTTP_200_OK, HTTPTAG_CONTENT_TYPE_STR("text/html"), HTTPTAG_PAYLOAD_STR ("auth/\n"), NTHTAG_AUTH_MODULE(am), TAG_END())); auth_mod_unref(am); END(); } static int send_request(tester_t *t, char const *req, size_t reqlen, int close_socket, char reply[], int rlen, int *return_len) { static su_socket_t c = INVALID_SOCKET; int m, r; su_wait_t w[1]; BEGIN(); if (c == INVALID_SOCKET) { c = su_socket(t->t_addr->su_family, SOCK_STREAM, 0); TEST_1(c != SOCK_STREAM); TEST_1(su_setblocking(c, 1) != -1); TEST_1(connect(c, &t->t_addr->su_sa, t->t_addrlen) != -1); while (su_root_step(t->t_root, 1) == 0); } if (reqlen == (size_t)-1) reqlen = strlen(req); TEST_SIZE(su_send(c, req, reqlen, 0), reqlen); if (close_socket == 1) shutdown(c, 1); TEST(su_wait_create(w, c, SU_WAIT_IN), 0); while (su_root_step(t->t_root, 1) == 0 || su_wait(w, 1, 0) < 0); for (r = 0;;) { TEST_1((m = recv(c, reply, rlen - r - 1, 0)) != -1); r += m; if (m == 0 || r == rlen - 1) break; } reply[r] = '\0'; if (close_socket != -1) su_close(c), c = -1; *return_len = r; END(); } int sspace(char const *buffer) { int m = strcspn(buffer, " "); if (buffer[m]) m += 1 + strcspn(buffer + m + 1, " "); return m; } #define CRLF "\r\n" static int test_requests(tester_t *t) { char buffer[4096 + 1]; int m; BEGIN(); { static char const get[] = "GET / HTTP/1.1" CRLF "Host: 127.0.0.1" CRLF "User-Agent: Test-Tool" CRLF "Connection: close" CRLF CRLF; TEST(send_request(t, get, -1, 0, buffer, sizeof(buffer), &m), 0); m = sspace(buffer); buffer[m] = '\0'; TEST_S(buffer, "HTTP/1.1 200"); } { static char const get[] = "GET / HTTP/1.1" CRLF "Host: 127.0.0.1" CRLF "User-Agent: Test-Tool" CRLF "Connection: close" CRLF CRLF; TEST(send_request(t, get, -1, 0, buffer, sizeof(buffer), &m), 0); m = strcspn(buffer, CRLF); buffer[m] = '\0'; TEST_S(buffer, "HTTP/1.1 200 OK"); } { static char const request[] = "GET %s HTTP/1.1" CRLF "Host: 127.0.0.1" CRLF "User-Agent: Test-Tool" CRLF "Connection: close" CRLF CRLF; char *get; get = su_sprintf(NULL, request, "/sub"); TEST(send_request(t, get, -1, 0, buffer, sizeof(buffer), &m), 0); m = sspace(buffer); buffer[m++] = '\0'; TEST_S(buffer, "HTTP/1.1 301"); m += strcspn(buffer + m, CRLF) + 1; free(get); get = su_sprintf(NULL, request, "/sub/"); TEST(send_request(t, get, -1, 0, buffer, sizeof(buffer), &m), 0); m = strcspn(buffer, CRLF); buffer[m++] = '\0'; TEST_S(buffer, "HTTP/1.1 200 OK"); TEST_1(strstr(buffer + m, "sub/")); free(get); get = su_sprintf(NULL, request, "/sub2/"); TEST(send_request(t, get, -1, 0, buffer, sizeof(buffer), &m), 0); m = strcspn(buffer, CRLF); buffer[m++] = '\0'; TEST_S(buffer, "HTTP/1.1 200 OK"); TEST_1(strstr(buffer + m, "sub2/")); free(get); get = su_sprintf(NULL, request, "/sub2/hub"); TEST(send_request(t, get, -1, 0, buffer, sizeof(buffer), &m), 0); m = strcspn(buffer, CRLF); buffer[m++] = '\0'; TEST_S(buffer, "HTTP/1.1 200 OK"); TEST_1(strstr(buffer + m, "sub2/")); free(get); /* Test that absolute path for subdir site is calculated correctly */ get = su_sprintf(NULL, request, "/sub2/sub"); TEST(send_request(t, get, -1, 0, buffer, sizeof(buffer), &m), 0); m = sspace(buffer); buffer[m++] = '\0'; TEST_S(buffer, "HTTP/1.1 301"); TEST_1(strstr(buffer + m, "/sub2/sub/" CRLF)); free(get); get = su_sprintf(NULL, request, "/sub2/sub/"); TEST(send_request(t, get, -1, 0, buffer, sizeof(buffer), &m), 0); m = strcspn(buffer, CRLF); buffer[m++] = '\0'; TEST_S(buffer, "HTTP/1.1 200 OK"); TEST_1(strstr(buffer + m, "sub2/sub/")); free(get); get = su_sprintf(NULL, request, "/sub/sub"); TEST(send_request(t, get, -1, 0, buffer, sizeof(buffer), &m), 0); m = strcspn(buffer, CRLF); buffer[m++] = '\0'; TEST_S(buffer, "HTTP/1.1 200 OK"); TEST_1(strstr(buffer + m, "sub/sub")); free(get); get = su_sprintf(NULL, request, "/auth/"); TEST(send_request(t, get, -1, 0, buffer, sizeof(buffer), &m), 0); m = sspace(buffer); buffer[m++] = '\0'; TEST_S(buffer, "HTTP/1.1 401"); free(get); get = su_sprintf(NULL, request, "/auth2/"); TEST(send_request(t, get, -1, 0, buffer, sizeof(buffer), &m), 0); m = sspace(buffer); buffer[m++] = '\0'; TEST_S(buffer, "HTTP/1.1 401"); free(get); } { static char const get[] = "GET /auth2/ HTTP/1.1" CRLF "Host: 127.0.0.1" CRLF "User-Agent: Test-Tool" CRLF "Connection: close" CRLF /* alice:secret in base64 */ "Authorization: Basic YWxpY2U6c2VjcmV0" CRLF CRLF; TEST(send_request(t, get, -1, 0, buffer, sizeof(buffer), &m), 0); m = sspace(buffer); buffer[m++] = '\0'; TEST_S(buffer, "HTTP/1.1 200"); } { static char const kuik[] = "kuik" CRLF CRLF; TEST(send_request(t, kuik, -1, 0, buffer, sizeof(buffer), &m), 0); m = sspace(buffer); buffer[m] = '\0'; TEST_S(buffer, "HTTP/1.1 400"); } { static char const kuik[] = "POST / HTTP/1.1" CRLF "Host: 127.0.0.1" CRLF "Content-Length: 4294967296" CRLF CRLF; TEST(send_request(t, kuik, -1, 1, buffer, sizeof(buffer), &m), 0); m = sspace(buffer); buffer[m] = '\0'; TEST_S(buffer, "HTTP/1.1 400"); } { static char const get[] = "GET / HTTP/10.10" CRLF "Host: 127.0.0.1" CRLF "User-Agent: Test-Tool" CRLF "Connection: close" CRLF CRLF; TEST(send_request(t, get, -1, 0, buffer, sizeof(buffer), &m), 0); m = sspace(buffer); buffer[m] = '\0'; TEST_S(buffer, "HTTP/1.1 505"); } { static char const get[] = "GET /" CRLF; TEST(send_request(t, get, -1, 1, buffer, sizeof(buffer) - 1, &m), 0); buffer[6] = '\0'; TEST_S(buffer, ""); } if (0) { static char const post[] = "POST /foo HTTP/1.1" CRLF "Host: 127.0.0.1" CRLF "User-Agent: Test-Tool" CRLF "Connection: close" CRLF "Content-Length: 7" CRLF "Expect: 100-continue" CRLF CRLF; static char const body[] = ""; TEST(send_request(t, post, -1, -1, buffer, sizeof(buffer) - 1, &m), 0); m = sspace(buffer); buffer[m] = '\0'; TEST_S(buffer, "HTTP/1.1 100"); TEST(send_request(t, body, -1, 0, buffer, sizeof(buffer) - 1, &m), 0); m = sspace(buffer); buffer[m] = '\0'; TEST_S(buffer, "HTTP/1.1 200"); } END(); } static int init_engine(tester_t *t) { BEGIN(); su_socket_t s; t->t_engine = nth_engine_create(t->t_root, NTHTAG_STREAMING(0), TAG_END()); TEST_1(t->t_engine); t->t_sink = s = su_socket(AF_INET, SOCK_STREAM, 0); TEST_1(s != -1); TEST(bind(s, &t->t_sinkaddr->su_sa, t->t_sinkaddrlen = (sizeof t->t_sinkaddr->su_sin)), 0); TEST_1(getsockname(s, &t->t_sinkaddr->su_sa, &t->t_sinkaddrlen) != -1); TEST(listen(t->t_sink, 5), 0); TEST_1(t->t_sinkuri = (url_string_t *) su_sprintf(t->t_home, "HTTP://127.0.0.1:%u", htons(t->t_sinkaddr->su_port))); END(); } static int response_to_client(client_t *c, nth_client_t *hc, http_t const *http) { if (http) { c->c_status = http->http_status->st_status; } else { c->c_status = nth_client_status(hc); } return 0; } static int test_client(tester_t *t) { BEGIN(); nth_client_t *hc; char *uri; client_t client[1]; memset(client, 0, sizeof client); TEST_1(uri = su_strcat(NULL, t->t_master->s_url->us_str, "/")); TEST_1(hc = nth_client_tcreate(t->t_engine, response_to_client, client, HTTP_METHOD_GET, URL_STRING_MAKE(uri), TAG_END())); while (client->c_status == 0) su_root_step(t->t_root, 1); TEST(client->c_status, 200); nth_client_destroy(hc); su_free(NULL, uri); memset(client, 0, sizeof client); TEST_1(hc = nth_client_tcreate(t->t_engine, response_to_client, client, HTTP_METHOD_GET, URL_STRING_MAKE(t->t_sinkuri), NTHTAG_EXPIRES(1000), TAG_END())); while (client->c_status == 0) su_root_step(t->t_root, 1); TEST(client->c_status, 408); nth_client_destroy(hc); END(); } #if HAVE_ALARM static RETSIGTYPE sig_alarm(int s) { fprintf(stderr, "%s: FAIL! test timeout!\n", name); exit(1); } #endif void usage(int exitcode) { fprintf(stderr, "usage: %s [-v|-q] [-a] [-p proxy-uri]\n", name); exit(exitcode); } int main(int argc, char **argv) { int i; int retval = 0; int o_alarm = 1; tester_t t[1] = {{{ SU_HOME_INIT(t) }}}; char const *srcdir = getenv("srcdir"); if (srcdir == NULL) srcdir = "."; for (i = 1; argv[i]; i++) { if (strcmp(argv[i], "-v") == 0) tstflags |= tst_verbatim; else if (strcmp(argv[i], "-a") == 0) tstflags |= tst_abort; else if (strcmp(argv[i], "-q") == 0) tstflags &= ~tst_verbatim; else if (strcmp(argv[i], "-p") == 0 && argv[i + 1]) t->t_proxy = (url_string_t *)argv[++i]; else if (strcmp(argv[i], "-s") == 0 && argv[i + 1]) srcdir = argv[++i]; else if (strcmp(argv[i], "--no-alarm") == 0) { o_alarm = 0; } else if (strcmp(argv[i], "-") == 0) { i++; break; } else if (argv[i][0] != '-') { break; } else usage(1); } t->t_srcdir = srcdir; #if HAVE_ALARM if (o_alarm) { alarm(60); signal(SIGALRM, sig_alarm); } #endif su_init(); retval |= init_test(t); retval |= test_nth_client_api(t); retval |= test_nth_server_api(t); retval |= init_server(t); retval |= test_requests(t); retval |= init_engine(t); retval |= test_client(t); retval |= deinit_test(t); su_deinit(); return retval; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/000077500000000000000000000000001223300710500203355ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/ChangeLog000066400000000000000000000312551223300710500221150ustar00rootroot000000000000002005-11-15 Kai Vehmanen * Removed obsolete NUTAG_MEDIA* tags. 2005-11-03 Pekka Pessi * Indicate the response status with the nua_i_. Now returning the status of the returned response in nua_i_ events. The application can determine from status code if it has to respond. * Added NUTAG_ALLOW() and NUTAG_ALLOW_REF() to nua. * Try to catch more errors when responding to invite in nua. * Fixed call state events with UPDATE in nua. Fixed the order the nua_i_update and nua_i_state events are sent. Now we are using session-timer headers in responses, too. * Added NUTAG_ALLOW() and NUTAG_ALLOW_REF() to nua. * Renamed NUTAG_USE_LEG() as NUTAG_USE_DIALOG() in nua. 2005-10-21 Pekka Pessi * Fixed challenge header checking in nua/nua_stack.c when receiving 401/407. Now checking for Proxy-Authenticate header when receiving 407 and WWW-Authenticate header when receiving 401. M ./libsofia-sip-ua/nua/nua_stack.c -2 +2 * Added test case for 407 followed by 401. M ./libsofia-sip-ua/nua/test_nua.c -3 +53 2005-10-18 Pekka Pessi * Test case numbering. M ./libsofia-sip-ua/nua/test_nua.c -1 +1 * Log level setting. M ./libsofia-sip-ua/nua/test_nua.c -1 +2 * Added a basic session timer test. M ./libsofia-sip-ua/nua/test_nua.c +121 * Fixed session-timer role selection at uas end. M ./libsofia-sip-ua/nua/nua_stack.c -10 +13 * Added -s option. M ./libsofia-sip-ua/nua/test_nua.c -2 +10 * Simplified test_basic_call(). M ./libsofia-sip-ua/nua/test_nua.c -18 +1 * Added test case for nua_authenticate. M ./libsofia-sip-ua/nua/test_nua.c +187 * Fixed response to 401. We are now not terminating call when application is expected to authenticate request. Should we add M ./libsofia-sip-ua/nua/nua_stack.c -10 +28 * Renumbered test cases. Split reject tests into separate functions. M ./libsofia-sip-ua/nua/test_nua.c -135 +159 * Added aliases for SOATAG_MSS_POINTER and SOATAG_MSS_SESSION. M ./libsofia-sip-ua/nua/nua_tag.h -27 +9 2005-10-17 Pekka Pessi * Using port 5060 by default. M ./libsofia-sip-ua/nua/nua_stack.c -7 +13 * Fixed race condition in 302 test. M ./libsofia-sip-ua/nua/test_nua.c -2 +2 * Silenced some gcc4 warnings. M ./libsofia-sip-ua/nua/nua_stack.c -10 +11 M ./libsofia-sip-ua/nua/test_nua.c -10 +10 2005-10-15 Pekka Pessi * Relay real CANCEL response to application. M ./libsofia-sip-ua/nua/nua_stack.c -8 +31 * Added CANCEL and early BYE tests. Added headings for test cases. Added more command-line options, too. M ./libsofia-sip-ua/nua/test_nua.c -26 +476 * Fixed process_bye(). M ./libsofia-sip-ua/nua/nua_stack.c -1 +15 * Fixed ua_bye(). Not mark session as terminated if we have an ongoing INVITE (just as terminating). Instead of sending BYE, send CANCEL, if we have no dialog. M ./libsofia-sip-ua/nua/nua_stack.c -24 +34 * Let nh_init() call soa_set_params() in ua_update(). M ./libsofia-sip-ua/nua/nua_stack.c -3 M ./libsofia-sip-ua/nua/nua_stack.c -7 +4 * Using new soa API in signal_call_state_change(). M ./libsofia-sip-ua/nua/nua_stack.c -17 +11 * Cleaned indentation. M ./libsofia-sip-ua/nua/nua_stack.c -4 +11 * Replaced ancient nta_msg_discard() with msg_destroy(). M ./libsofia-sip-ua/nua/nua_stack.c -3 +3 * Refactored nh_create_from_incoming(). M ./libsofia-sip-ua/nua/nua_stack.c -15 +14 * Made ua_set_params() and nh_init() to return -1 upon an error. M ./libsofia-sip-ua/nua/nua_stack.c -18 +27 * Updated soa_get_local_sdp() API. M ./libsofia-sip-ua/nua/nua_stack.c -2 +2 * Zapped annoying last modified. M ./libsofia-sip-ua/nua/nua.c -1 M ./libsofia-sip-ua/nua/nua.h -1 M ./libsofia-sip-ua/nua/nua_common.c -1 M ./libsofia-sip-ua/nua/nua_stack.c -1 M ./libsofia-sip-ua/nua/nua_stack.h -1 M ./libsofia-sip-ua/nua/nua_tag.c -1 M ./libsofia-sip-ua/nua/nua_tag.h -1 * Fixed logging options. Allow multithreaded, unsynchronised execution. M ./libsofia-sip-ua/nua/test_nua.c -115 +162 2005-10-12 Pekka Pessi * Fixed logging options. Allow multithreaded, unsynchronised execution. M ./libsofia-sip-ua/nua/test_nua.c -115 +162 2005-10-12 Pekka Pessi * Added test for call hold. M ./libsofia-sip-ua/nua/test_nua.c +241 * Added better logging functions. M ./libsofia-sip-ua/nua/test_nua.c -77 +149 * LDADD now have dependencies. M ./libsofia-sip-ua/nua/Makefile.am -15 +15 * Added call reject cases. M ./libsofia-sip-ua/nua/test_nua.c -62 +461 * When call is retried or terminated, always send nua_i_state after nua_r_invite(). M ./libsofia-sip-ua/nua/nua_stack.c -53 +55 * Fixed reference counting bug in process_ack(). M ./libsofia-sip-ua/nua/nua_stack.c -6 +2 2005-10-11 Pekka Pessi * Used picture-mode (cleaned up whitespace at eol). M ./libsofia-sip-ua/nua/test_nua.c -23 +23 * Testing call flow on client side, too. M ./libsofia-sip-ua/nua/test_nua.c -17 +94 * Transitions terminating call. Added letter C, S, and T to transitions. M ./libsofia-sip-ua/nua/nua.docs -72 +159 2005-10-10 Pekka Pessi * Fixed basic call test run. M ./libsofia-sip-ua/nua/test_nua.c -8 +11 * It is nua_callstate_completed, not nua_callstate_complete. M ./libsofia-sip-ua/nua/nua_common.c -1 +1 M ./libsofia-sip-ua/nua/nua_stack.c -1 +1 M ./libsofia-sip-ua/nua/test_nua.c -2 +2 * Running a basic call test case. M ./libsofia-sip-ua/nua/test_nua.c -24 +109 * Added separate nua_i_ack event. Generating it after ACK is received. M ./libsofia-sip-ua/nua/nua.h -1 +2 M ./libsofia-sip-ua/nua/nua_common.c -1 +3 M ./libsofia-sip-ua/nua/nua_stack.c -11 +24 M ./libsofia-sip-ua/nua/nua_stack.h -1 +4 * ua_invite2() crashed if there was problem creating SIP message. M ./libsofia-sip-ua/nua/nua_stack.c -1 +1 * Fixed indenting in nua_stack.c. M ./libsofia-sip-ua/nua/nua_stack.c -3 +6 * Including nua_callstate_terminated in the NUTAG_CALLSTATE always when call is terminated. M ./libsofia-sip-ua/nua/nua_stack.c -2 +2 * nua_handle_has_streaming() is obsolete. M ./libsofia-sip-ua/nua/nua.h -2 +3 * Using nua_callstate_complete. M ./libsofia-sip-ua/nua/nua_stack.c -8 +10 * Added nua_callstate_completing and nua_callstate_completed. M ./libsofia-sip-ua/nua/nua_common.c +2 M ./libsofia-sip-ua/nua/nua_tag.h -1 +3 * Added nua_call_model @page. M ./libsofia-sip-ua/nua/nua.docs -1 +355 * Used picture-mode here. M ./libsofia-sip-ua/nua/nua.docs -227 +227 * Fixed nua_set_hparams() documentation. M ./libsofia-sip-ua/nua/nua.c -1 +1 * Exposed struct event_s as nua_event_data_t. Replaced clumsy nua_info_event() with nua_event_data(). Added tests for new function. M ./libsofia-sip-ua/nua/nua.c -31 +6 M ./libsofia-sip-ua/nua/nua.h -10 +14 M ./libsofia-sip-ua/nua/nua_stack.h -10 M ./libsofia-sip-ua/nua/test_nua.c -60 +182 * Fixed nua_set_hparams()/nua_get_hparams(). M ./libsofia-sip-ua/nua/nua_stack.c -4 +6 M ./libsofia-sip-ua/nua/test_nua.c -6 +5 * nua_set_(h)params() now also returns an event. M ./libsofia-sip-ua/nua/nua.h -1 +1 M ./libsofia-sip-ua/nua/nua_stack.c -13 +33 * Removed superfluous tags from nua_tag.h and from documentation. M ./libsofia-sip-ua/nua/nua.c -21 +19 M ./libsofia-sip-ua/nua/nua_tag.c -1 M ./libsofia-sip-ua/nua/nua_tag.h -19 * Renamed nua_set/get_handle_params() as nua_set/get_hparams(). M ./libsofia-sip-ua/nua/nua.c -4 +2 M ./libsofia-sip-ua/nua/nua.h -3 +3 M ./libsofia-sip-ua/nua/test_nua.c -2 +2 * Added test for nua_set_params() and nua_get_params(). M ./libsofia-sip-ua/nua/test_nua.c -75 +420 * Fixed ua_set_params(), added SIPTAG_FROM_STR() to ua_get_params(). M ./libsofia-sip-ua/nua/nua_stack.c -19 +23 * Fixed prototypes of nua_save_event() and nua_info_event(). M ./libsofia-sip-ua/nua/nua.c -1 +1 M ./libsofia-sip-ua/nua/nua.h -2 +2 * Using nua_any_refresher. M ./libsofia-sip-ua/nua/nua_stack.c -7 +9 * Fixed user_agent handling in ua_set_params() M ./libsofia-sip-ua/nua/nua_stack.c -2 +2 * Added NUTAG_RETRY_COUNT() and NUTAG_MAX_SUBSCRIPTIONS(). M ./libsofia-sip-ua/nua/nua_stack.c -4 +4 M ./libsofia-sip-ua/nua/nua_tag.c -1 +4 M ./libsofia-sip-ua/nua/nua_tag.h -4 +54 * Added nua_set_handle_params() and nua_get_handle_params(). Revised the internal handling of parameters. They can be now set at handle or user agent level. Once a parameter is set at handle level, changes at user agent level does modify its value within a handle. M ./libsofia-sip-ua/nua/nua.c -7 +90 M ./libsofia-sip-ua/nua/nua.h -1 +8 M ./libsofia-sip-ua/nua/nua_common.c +2 M ./libsofia-sip-ua/nua/nua_stack.c -378 +486 M ./libsofia-sip-ua/nua/nua_stack.h -64 +113 * Silenced test run. Disabled debug output from nua functions getting invalid input during test run. M ./libsofia-sip-ua/nua/nua.c -2 +2 M ./libsofia-sip-ua/nua/test_nua.c -5 +10 2005-10-04 Kai Vehmanen * nua.h (nua_invite_respond): Removed, no implementation available. 2005-10-04 Pekka Pessi * Fixed soa_set_params() in respond_to_invite(). M ./libsofia-sip-ua/nua/nua_stack.c -1 +1 2005-10-03 Pekka Pessi * Added soa_set_params() to respond_to_invite(). M ./libsofia-sip-ua/nua/nua_stack.c +3 * Added API for saving nua events. M ./libsofia-sip-ua/nua/nua.c -4 +80 M ./libsofia-sip-ua/nua/nua.h +20 M ./libsofia-sip-ua/nua/nua_stack.h +2 2005-09-29 Pekka Pessi * Added nua_callstate_name(). M ./libsofia-sip-ua/nua/nua_common.c +17 M ./libsofia-sip-ua/nua/nua_tag.h +3 * Responding with 504 if 100rel times out. M ./libsofia-sip-ua/nua/nua_stack.c -2 +2 * Using SOATAG_ACTIVE_*. M ./libsofia-sip-ua/nua/nua_stack.h -8 +8 * Using offer/answer tags. M ./libsofia-sip-ua/nua/nua_stack.c +11 * Commenting. M ./libsofia-sip-ua/nua/nua_tag.h +9 * Added NUTAG_OFFER_RECV(), NUTAG_ANSWER_SENT(), NUTAG_OFFER_SENT(), NUTAG_ANSWER_RECV(). M ./libsofia-sip-ua/nua/nua_tag.c +4 M ./libsofia-sip-ua/nua/nua_tag.h +64 * Using SOATAG_ACTIVE_*(). M ./libsofia-sip-ua/nua/nua_tag.c -3 M ./libsofia-sip-ua/nua/nua_tag.h -91 +32 * Updated signal_call_state_change() to take more versatile args. M ./libsofia-sip-ua/nua/nua_stack.c -302 +375 * Added NUTAG_CALLSTATE(), enum nua_callstate. M ./libsofia-sip-ua/nua/nua_stack.h -20 +8 M ./libsofia-sip-ua/nua/nua_tag.c +1 M ./libsofia-sip-ua/nua/nua_tag.h -1 +38 * Added sdp_session_t and SDP_MIME_TYPE. M ./libsofia-sip-ua/nua/nua_stack.c +9 * Moved nua_event_name() to nua_common.c M ./libsofia-sip-ua/nua/nua.h +1 M ./libsofia-sip-ua/nua/nua_common.c +62 M ./libsofia-sip-ua/nua/nua_stack.c -58 * Removed SRTP things (they are in soa). M ./libsofia-sip-ua/nua/nua_stack.c -10 M ./libsofia-sip-ua/nua/nua_stack.h -3 * Added nua_unpublish() M ./libsofia-sip-ua/nua/nua.c -4 +28 M ./libsofia-sip-ua/nua/nua.h +1 M ./libsofia-sip-ua/nua/nua_stack.c +1 2005-09-28 Pekka Pessi * Including in . M ./libsofia-sip-ua/nua/nua_tag.h -3 +3 * Compiled with new soa. M ./libsofia-sip-ua/nua/nua_stack.c -63 +61 * Do not pass soa handle to application. M ./libsofia-sip-ua/nua/nua_stack.c -3 +3 2005-09-23 Kai Vehmanen * nua_stack.c: Fix delivering nua_i_active. 2005-09-22 Kai Vehmanen * nua.docs: Updated event documentation. * nua_stack.c: Unused nua_i_terminate event removed. * nua_tag.h: Removed NUTAG_MEDIA_SUBSYSTEM. * nua.h: Added nua_i_state_change event. Removed nua_i_media_update (replaced by nua_i_state_change). 2005-09-21 Kai Vehmanen * nua_stack.h, nua_common.c, nua.c: Removed obsolete code related to old media subsystem interface (HAVE_MSS). Added nua_i_media_update event. Removed code related to ring-tone generation (HAVE_HERBIE). 2005-09-20 Kai Vehmanen * nua.h, nua.c: Removed implementation for obsolete media param functions. Added dummy implementations that print a warning to users of the removed interfaces. * nua_stack.c: Removed obsolete media param code. 2005-07-18 Kai Vehmanen * Initial import of the module to Sofia-SIP tree. sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/Doxyfile.in000066400000000000000000000031351223300710500224520ustar00rootroot00000000000000PROJECT_NAME = "nua" OUTPUT_DIRECTORY = ../docs/html/nua INPUT = @srcdir@/nua.docs @srcdir@/sofia-sip @srcdir@ . @INCLUDE_PATH = . @srcdir@ @INCLUDE = ../docs/Doxyfile.conf TAGFILES += ../docs/docs.doxytags=../docs TAGFILES += ../docs/su.doxytags=../su TAGFILES += ../docs/ipt.doxytags=../ipt TAGFILES += ../docs/bnf.doxytags=../bnf TAGFILES += ../docs/url.doxytags=../url TAGFILES += ../docs/msg.doxytags=../msg TAGFILES += ../docs/sip.doxytags=../sip TAGFILES += ../docs/sresolv.doxytags=../sresolv TAGFILES += ../docs/tport.doxytags=../tport TAGFILES += ../docs/nta.doxytags=../nta TAGFILES += ../docs/soa.doxytags=../soa TAGFILES += ../docs/nea.doxytags=../nea TAGFILES += ../docs/sdp.doxytags=../sdp GENERATE_TAGFILE = ../docs/nua.doxytags ALIASES += CFILE="@internal @file" IFILE="@internal @file" ALIASES += nua="@ref index \"nua\"" # When GENERATE_TAGFILE=YES, we should use \ref main #ALIASES += nua="@ref main \"nua\"" ALIASES += NUA_EVENT="@var nua_event_e::" ALIASES += END_NUA_EVENT="@par  " ALIASES += \ NUA_HPARAM_CALLS="nua_method(), nua_respond(), nua_invite(), nua_ack(), nua_cancel(), nua_prack(), nua_update(), nua_info(), nua_bye(), nua_options(), nua_message(), nua_register(), nua_unregister(), nua_publish(), nua_refer(), nua_subscribe(), nua_unsubscribe(), nua_notify(), nua_notifier()" VERBATIM_HEADERS = NO @INCLUDE = ../sip/sip.doxyaliases sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/Makefile.am000066400000000000000000000042401223300710500223710ustar00rootroot00000000000000# # Makefile.am for nua module # # Copyright (C) 2005,2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # ---------------------------------------------------------------------- # Header paths # ---------------------------------------------------------------------- # Build targets noinst_LTLIBRARIES = libnua.la check_PROGRAMS = TESTS = if HAVE_CHECK check_PROGRAMS += check_nua TESTS += check_nua endif # ---------------------------------------------------------------------- # Rules for building the targets BUILT_SOURCES = nua_tag_ref.c nobase_include_sofia_HEADERS = \ sofia-sip/nua.h sofia-sip/nua_tag.h libnua_la_SOURCES = nua.c nua_stack.h nua_common.c nua_stack.c \ nua_server.h nua_server.c \ nua_client.h nua_client.c \ nua_extension.c nua_types.h \ nua_dialog.c nua_dialog.h \ outbound.c outbound.h \ nua_params.c nua_params.h \ nua_register.c nua_registrar.c \ nua_session.c nua_options.c \ nua_message.c nua_publish.c nua_subnotref.c \ nua_notifier.c \ nua_event_server.c \ nua_tag.c nua_tag_ref.c COVERAGE_INPUT = $(libnua_la_SOURCES) $(include_sofia_HEADERS) LDADD = libnua.la \ ../iptsec/libiptsec.la \ ../ipt/libipt.la \ ../nea/libnea.la \ ../nta/libnta.la \ ../sresolv/libsresolv.la \ ../tport/libtport.la \ ../stun/libstun.la \ ../soa/libsoa.la \ ../sdp/libsdp.la \ ../sip/libsip.la \ ../http/libhttp.la \ ../msg/libmsg.la \ ../url/liburl.la \ ../bnf/libbnf.la \ ../su/libsu.la # ---------------------------------------------------------------------- check_nua_SOURCES = check_nua.c check_nua.h \ check_session.c check_register.c \ check_etsi.c check_simple.c check_nua_LDADD = $(LDADD) ${top_builddir}/s2check/libs2.a \ @CHECK_LIBS@ # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST = nua.docs $(BUILT_SOURCES) # ---------------------------------------------------------------------- # Sofia specific rules include $(top_srcdir)/rules/sofia.am INCLUDES = ${INTERNAL_INCLUDES} -I$(top_srcdir)/s2check TAG_DLL_FLAGS = LIST=nua_tag_list sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/Makefile.in000066400000000000000000001405261223300710500224120ustar00rootroot00000000000000# Makefile.in generated by automake 1.14 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 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 nua module # # Copyright (C) 2005,2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # ---------------------------------------------------------------------- # Header paths # ---------------------------------------------------------------------- # Build targets # common Makefile targets for libsofia-sip-ua(-glib) modules # ---------------------------------------------------------- # # run tests with valgrind # # Copyright (C) 2007 Nokia Corporation. # 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 file contains free software from Makefile.in by the Free Software # Foundation: # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 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. # # Generate lcov output # # # Copyright (C) 2007 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # # Silent compilation w/ Automake 1.9 or 1.10 # ---------------------------------------------------------- # Automake 1.9.6 is not clever enough to override suffix rules within if # if SOFIA_COMPILE_SILENT VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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@ check_PROGRAMS = $(am__EXEEXT_1) TESTS = $(am__EXEEXT_1) @HAVE_CHECK_TRUE@am__append_1 = check_nua @HAVE_CHECK_TRUE@am__append_2 = check_nua DIST_COMMON = $(top_srcdir)/rules/sofia.am \ $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am \ $(top_srcdir)/rules/silent.am $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(srcdir)/Doxyfile.in \ $(top_srcdir)/depcomp $(nobase_include_sofia_HEADERS) \ $(top_srcdir)/test-driver ChangeLog # Use with --enable-ndebug @NDEBUG_TRUE@am__append_3 = -DNDEBUG @HAVE_GENPNG_TRUE@@HAVE_LCOV_TRUE@am__append_4 = --frames @HAVE_LCOV_TRUE@am__append_5 = lcov lcov-report lcov-rerun clean-lcov covcheck uncovered subdir = libsofia-sip-ua/nua ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(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)/m4/sac-coverage.m4 \ $(top_srcdir)/m4/sac-general.m4 \ $(top_srcdir)/m4/sac-openssl.m4 \ $(top_srcdir)/m4/sac-pkg-config.m4 $(top_srcdir)/m4/sac-su2.m4 \ $(top_srcdir)/m4/sac-tport.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libsofia-sip-ua/su/sofia-sip/su_configure.h CONFIG_CLEAN_FILES = Doxyfile CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libnua_la_LIBADD = am_libnua_la_OBJECTS = nua.lo nua_common.lo nua_stack.lo nua_server.lo \ nua_client.lo nua_extension.lo nua_dialog.lo outbound.lo \ nua_params.lo nua_register.lo nua_registrar.lo nua_session.lo \ nua_options.lo nua_message.lo nua_publish.lo nua_subnotref.lo \ nua_notifier.lo nua_event_server.lo nua_tag.lo nua_tag_ref.lo libnua_la_OBJECTS = $(am_libnua_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 = @HAVE_CHECK_TRUE@am__EXEEXT_1 = check_nua$(EXEEXT) am_check_nua_OBJECTS = check_nua.$(OBJEXT) check_session.$(OBJEXT) \ check_register.$(OBJEXT) check_etsi.$(OBJEXT) \ check_simple.$(OBJEXT) check_nua_OBJECTS = $(am_check_nua_OBJECTS) am__DEPENDENCIES_1 = am__DEPENDENCIES_2 = libnua.la ../iptsec/libiptsec.la ../ipt/libipt.la \ ../nea/libnea.la ../nta/libnta.la ../sresolv/libsresolv.la \ ../tport/libtport.la ../stun/libstun.la ../soa/libsoa.la \ ../sdp/libsdp.la ../sip/libsip.la ../http/libhttp.la \ ../msg/libmsg.la ../url/liburl.la ../bnf/libbnf.la \ ../su/libsu.la $(am__DEPENDENCIES_1) check_nua_DEPENDENCIES = $(am__DEPENDENCIES_2) \ ${top_builddir}/s2check/libs2.a 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) -I$(top_builddir)/libsofia-sip-ua/su/sofia-sip depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f 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) 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 = $(libnua_la_SOURCES) $(check_nua_SOURCES) DIST_SOURCES = $(libnua_la_SOURCES) $(check_nua_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)$(include_sofiadir)" HEADERS = $(nobase_include_sofia_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)` 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=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ 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_DRIVER = $(SHELL) $(top_srcdir)/test-driver 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) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CHECK_CFLAGS = @CHECK_CFLAGS@ CHECK_LIBS = @CHECK_LIBS@ COVERAGE_FLAGS = @COVERAGE_FLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CWFLAG = @CWFLAG@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV = @GCOV@ GENHTML = @GENHTML@ GENPNG = @GENPNG@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GLIB_VERSION = @GLIB_VERSION@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVER_SOFIA_SIP_UA_AGE = @LIBVER_SOFIA_SIP_UA_AGE@ LIBVER_SOFIA_SIP_UA_CUR = @LIBVER_SOFIA_SIP_UA_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_AGE = @LIBVER_SOFIA_SIP_UA_GLIB_AGE@ LIBVER_SOFIA_SIP_UA_GLIB_CUR = @LIBVER_SOFIA_SIP_UA_GLIB_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_REV = @LIBVER_SOFIA_SIP_UA_GLIB_REV@ LIBVER_SOFIA_SIP_UA_GLIB_SOVER = @LIBVER_SOFIA_SIP_UA_GLIB_SOVER@ LIBVER_SOFIA_SIP_UA_REV = @LIBVER_SOFIA_SIP_UA_REV@ LIBVER_SOFIA_SIP_UA_SOVER = @LIBVER_SOFIA_SIP_UA_SOVER@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MINGW_ENVIRONMENT = @MINGW_ENVIRONMENT@ MKDIR_P = @MKDIR_P@ MOSTLYCLEANFILES = @MOSTLYCLEANFILES@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ RANLIB = @RANLIB@ REPLACE_LIBADD = @REPLACE_LIBADD@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ SOFIA_GLIB_CFLAGS = @SOFIA_GLIB_CFLAGS@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ SOFIA_PLAT_CFLAGS = @SOFIA_PLAT_CFLAGS@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ VERSION = @VERSION@ VER_LIBSOFIA_SIP_UA_MAJOR_MINOR = @VER_LIBSOFIA_SIP_UA_MAJOR_MINOR@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ include_sofiadir = @include_sofiadir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ openssl_CFLAGS = @openssl_CFLAGS@ openssl_LIBS = @openssl_LIBS@ 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@ noinst_LTLIBRARIES = libnua.la # ---------------------------------------------------------------------- # Rules for building the targets BUILT_SOURCES = nua_tag_ref.c nobase_include_sofia_HEADERS = \ sofia-sip/nua.h sofia-sip/nua_tag.h libnua_la_SOURCES = nua.c nua_stack.h nua_common.c nua_stack.c \ nua_server.h nua_server.c \ nua_client.h nua_client.c \ nua_extension.c nua_types.h \ nua_dialog.c nua_dialog.h \ outbound.c outbound.h \ nua_params.c nua_params.h \ nua_register.c nua_registrar.c \ nua_session.c nua_options.c \ nua_message.c nua_publish.c nua_subnotref.c \ nua_notifier.c \ nua_event_server.c \ nua_tag.c nua_tag_ref.c COVERAGE_INPUT = $(libnua_la_SOURCES) $(include_sofia_HEADERS) LDADD = libnua.la ../iptsec/libiptsec.la ../ipt/libipt.la \ ../nea/libnea.la ../nta/libnta.la ../sresolv/libsresolv.la \ ../tport/libtport.la ../stun/libstun.la ../soa/libsoa.la \ ../sdp/libsdp.la ../sip/libsip.la ../http/libhttp.la \ ../msg/libmsg.la ../url/liburl.la ../bnf/libbnf.la \ ../su/libsu.la $(openssl_LIBS) # ---------------------------------------------------------------------- check_nua_SOURCES = check_nua.c check_nua.h \ check_session.c check_register.c \ check_etsi.c check_simple.c check_nua_LDADD = $(LDADD) ${top_builddir}/s2check/libs2.a \ @CHECK_LIBS@ # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST = nua.docs $(BUILT_SOURCES) sofiasrcdir = ${top_srcdir}/libsofia-sip-ua sofiabuilddir = ${top_builddir}/libsofia-sip-ua AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(SOFIA_CFLAGS) \ $(openssl_CFLAGS) $(SOFIA_PLAT_CFLAGS) $(am__append_3) SOFIA_COVERAGE = $(COVERAGE_FLAGS) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files TAG_AWK = ${sofiasrcdir}/su/tag_dll.awk SUFFIXES = _tag_ref.c _tag.c INTERNAL_INCLUDES = \ -I${sofiasrcdir}/features -I${sofiabuilddir}/features \ -I${sofiasrcdir}/ipt -I${sofiabuilddir}/ipt \ -I${sofiasrcdir}/iptsec -I${sofiabuilddir}/iptsec \ -I${sofiasrcdir}/bnf -I${sofiabuilddir}/bnf \ -I${sofiasrcdir}/http -I${sofiabuilddir}/http \ -I${sofiasrcdir}/msg -I${sofiabuilddir}/msg \ -I${sofiasrcdir}/nth -I${sofiabuilddir}/nth \ -I${sofiasrcdir}/nta -I${sofiabuilddir}/nta \ -I${sofiasrcdir}/nea -I${sofiabuilddir}/nea \ -I${sofiasrcdir}/nua -I${sofiabuilddir}/nua \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sdp -I${sofiabuilddir}/sdp \ -I${sofiasrcdir}/sip -I${sofiabuilddir}/sip \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sresolv -I${sofiabuilddir}/sresolv \ -I${sofiasrcdir}/tport -I${sofiabuilddir}/tport \ -I${sofiasrcdir}/stun -I${sofiabuilddir}/stun \ -I${sofiasrcdir}/url -I${sofiabuilddir}/url \ -I${sofiasrcdir}/su -I${sofiabuilddir}/su PHONY = built-sources clean-built-sources $(am__append_5) VALGRIND = valgrind VALGRINDFLAGS = --tool=memcheck # Scripts @HAVE_LCOV_TRUE@LCOV_UNCOVERED = ${top_srcdir}/scripts/uncovered @HAVE_LCOV_TRUE@LCOV_REPORT = ${top_srcdir}/scripts/lcov-report # Report directory @HAVE_LCOV_TRUE@lcovdir = ${top_builddir}/lcov # Options @HAVE_LCOV_TRUE@GENHTML_OPTIONS = --show-details --legend \ @HAVE_LCOV_TRUE@ $(am__append_4) # Fancy shell command that expands to directory relative to top_builddir @HAVE_LCOV_TRUE@expand_subdir = `pwd|sed "s'\`cd ${top_builddir};pwd\`''"` SOFIA_SILENT = @ LIBTOOL_FLAGS = --silent # From Automake 1.9.6 - LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(LIBTOOL_FLAGS) \ $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) LINK = ${SOFIA_SILENT}test "${SOFIA_SILENT}" != @ || echo ' LINK $@'; \ $(LIBTOOL) --tag=CC --mode=link $(LIBTOOL_FLAGS) \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ # ---------------------------------------------------------------------- # Sofia specific rules INCLUDES = ${INTERNAL_INCLUDES} -I$(top_srcdir)/s2check TAG_DLL_FLAGS = LIST=nua_tag_list all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: _tag_ref.c _tag.c .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.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 libsofia-sip-ua/nua/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu libsofia-sip-ua/nua/Makefile .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.am: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): Doxyfile: $(top_builddir)/config.status $(srcdir)/Doxyfile.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ 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}; \ } libnua.la: $(libnua_la_OBJECTS) $(libnua_la_DEPENDENCIES) $(EXTRA_libnua_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libnua_la_OBJECTS) $(libnua_la_LIBADD) $(LIBS) 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 check_nua$(EXEEXT): $(check_nua_OBJECTS) $(check_nua_DEPENDENCIES) $(EXTRA_check_nua_DEPENDENCIES) @rm -f check_nua$(EXEEXT) $(AM_V_CCLD)$(LINK) $(check_nua_OBJECTS) $(check_nua_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check_etsi.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check_nua.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check_register.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check_session.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check_simple.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nua.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nua_client.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nua_common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nua_dialog.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nua_event_server.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nua_extension.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nua_message.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nua_notifier.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nua_options.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nua_params.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nua_publish.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nua_register.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nua_registrar.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nua_server.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nua_session.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nua_stack.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nua_subnotref.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nua_tag.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nua_tag_ref.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/outbound.Plo@am__quote@ .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.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) '$<'` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-nobase_include_sofiaHEADERS: $(nobase_include_sofia_HEADERS) @$(NORMAL_INSTALL) @list='$(nobase_include_sofia_HEADERS)'; test -n "$(include_sofiadir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(include_sofiadir)'"; \ $(MKDIR_P) "$(DESTDIR)$(include_sofiadir)" || exit 1; \ fi; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo " $(MKDIR_P) '$(DESTDIR)$(include_sofiadir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(include_sofiadir)/$$dir"; }; \ echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(include_sofiadir)/$$dir'"; \ $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(include_sofiadir)/$$dir" || exit $$?; }; \ done uninstall-nobase_include_sofiaHEADERS: @$(NORMAL_UNINSTALL) @list='$(nobase_include_sofia_HEADERS)'; test -n "$(include_sofiadir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ dir='$(DESTDIR)$(include_sofiadir)'; $(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; \ else \ 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 $(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 $$? check_nua.log: check_nua$(EXEEXT) @p='check_nua$(EXEEXT)'; \ b='check_nua'; \ $(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: $(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: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(include_sofiadir)"; 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: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) -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: 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) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) 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) @HAVE_LCOV_FALSE@clean-local: clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libtool clean-local \ clean-noinstLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -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-nobase_include_sofiaHEADERS 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 -rf ./$(DEPDIR) -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-nobase_include_sofiaHEADERS .MAKE: all check check-am install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libtool clean-local \ 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-nobase_include_sofiaHEADERS 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 \ uninstall-nobase_include_sofiaHEADERS built-sources: $(BUILT_SOURCES) clean-built-sources: -rm -rf $(BUILT_SOURCES) $(BUILT_SOURCES:%=$(srcdir)/%) *_tag_ref.c: $(TAG_AWK) _tag.c_tag_ref.c: $(AWK) -f $(TAG_AWK) NODLL=1 $(TAG_DLL_FLAGS) REF=$@ $< ../bnf/libbnf.la ../http/libhttp.la ../ipt/libipt.la ../iptsec/libiptsec.la \ ../msg/libmsg.la ../nea/libnea.la ../nta/libnta.la ../nth/libnth.la \ ../nua/libnua.la ../sdp/libsdp.la ../sip/libsip.la ../soa/libsoa.la \ ../sresolv/libsresolv.la ../stun/libstun.la ../su/libsu.la \ ../tport/libtport.la ../url/liburl.la: cd $(@D) && $(MAKE) $(@F) checklib: $(noinst_LTLIBRARIES) $(check_LTLIBRARIES) valcheck: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) valcheck-am valcheck-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS # Run tests with valgrind in valcheck-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ list='$(TESTS)'; \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ if case $$tst in \ run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ $${dir}$$tst ;; \ esac ; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ echo "XPASS: $$tst"; \ ;; \ *) \ echo "PASS: $$tst"; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xfail=`expr $$xfail + 1`; \ echo "XFAIL: $$tst"; \ ;; \ *) \ failed=`expr $$failed + 1`; \ echo "FAIL: $$tst"; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ echo "SKIP: $$tst"; \ fi; \ done; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="All $$all tests passed"; \ else \ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all tests failed"; \ else \ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ skipped="($$skip tests were not run)"; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ report=""; \ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ report="Please report to $(PACKAGE_BUGREPORT)"; \ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ echo "$$dashes"; \ echo "$$banner"; \ test -z "$$skipped" || echo "$$skipped"; \ test -z "$$report" || echo "$$report"; \ echo "$$dashes"; \ test "$$failed" -eq 0; \ else :; fi # # Generate pretty coverage report (unless it has been already done) # @HAVE_LCOV_TRUE@lcov: @HAVE_LCOV_TRUE@ @-test -r ${lcovdir}${expand_subdir}/lcov.info \ @HAVE_LCOV_TRUE@ || make lcov-report # Generate pretty coverage report based on current coverage data @HAVE_LCOV_TRUE@lcov-report: @HAVE_LCOV_TRUE@ sub=${expand_subdir} odir=${lcovdir}$$sub ; \ @HAVE_LCOV_TRUE@ rm -rf $$odir ; mkdir -p $$odir && \ @HAVE_LCOV_TRUE@ ${LCOV_REPORT} ${GENHTML_OPTIONS} \ @HAVE_LCOV_TRUE@ --title "${PACKAGE_NAME}-${PACKAGE_VERSION}$$sub" \ @HAVE_LCOV_TRUE@ --srcdir=${srcdir} -o $$odir # Rerun checks before generating report @HAVE_LCOV_TRUE@lcov-rerun: clean-lcov @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) lcov-report # Show all uncovered lines as errors @HAVE_LCOV_TRUE@uncovered: @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} # Run check in current dir and show all uncovered lines as errors @HAVE_LCOV_TRUE@covcheck: @HAVE_LCOV_TRUE@ -find . -name "*.gcda" | xargs rm -rf @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} @HAVE_LCOV_TRUE@clean-local:: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true @HAVE_LCOV_TRUE@clean-lcov: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true # Rules from depend2.am (GENERIC = TRUE, SUBDIROBJ = FALSE, %FASTDEP% = am_fastdepCC) silenced. .c.o: @test "${SOFIA_SILENT}" != @ || echo ' COMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(COMPILE) -c -o $@ $< .c.lo: @test "${SOFIA_SILENT}" != @ || echo ' LTCOMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(LTCOMPILE) -c -o $@ $< # endif # 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: sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/check_etsi.c000066400000000000000000000232471223300710500226120ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2008 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE check_etsi.c * * @brief ETSI test cases * * @author Pekka Pessi * @author Paulo Pizarro * * @copyright (C) 2008 Nokia Corporation. */ #include "config.h" #undef NDEBUG #include "check_nua.h" #include #include #include #include #include #include #include #include #include /* ====================================================================== */ /* define XXX as 1 in order to see all failing test cases */ #ifndef XXX #define XXX (0) #endif /* ====================================================================== */ static nua_t *nua; static soa_session_t *soa = NULL; static struct dialog *d1 = NULL; static struct dialog *d2 = NULL; #define CRLF "\r\n" static void etsi_setup(void) { nua = s2_nua_setup("ETSI", NUTAG_OUTBOUND("no-options-keepalive, no-validate"), TAG_END()); soa = soa_create(NULL, s2base->root, NULL); fail_if(!soa); soa_set_params(soa, SOATAG_USER_SDP_STR("m=audio 5008 RTP/AVP 8 0" CRLF "m=video 5010 RTP/AVP 34" CRLF), TAG_END()); d1 = su_home_new(sizeof *d1); fail_if(!d1); d2 = su_home_new(sizeof *d2); fail_if(!d2); } static void etsi_thread_setup(void) { s2_nua_thread = 1; etsi_setup(); } static void etsi_threadless_setup(void) { s2_nua_thread = 0; etsi_setup(); } static void etsi_teardown(void) { s2_teardown_started("ETSI"); mark_point(); nua_shutdown(nua); fail_unless_event(nua_r_shutdown, 200); s2_nua_teardown(); } static void save_sdp_to_soa(struct message *message) { sip_payload_t *pl; char const *body; isize_t bodylen; fail_if(!message); fail_if(!message->sip->sip_content_length); fail_if(!message->sip->sip_content_type); fail_if(strcmp(message->sip->sip_content_type->c_type, "application/sdp")); fail_if(!message->sip->sip_payload); pl = message->sip->sip_payload; body = pl->pl_data, bodylen = pl->pl_len; fail_if(soa_set_remote_sdp(soa, NULL, body, (issize_t)bodylen) < 0); } static void process_offer(struct message *message) { save_sdp_to_soa(message); fail_if(soa_generate_answer(soa, NULL) < 0); } static void respond_with_sdp(struct message *request, struct dialog *dialog, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...) { ta_list ta; char const *body; isize_t bodylen; fail_if(soa_get_local_sdp(soa, NULL, &body, &bodylen) != 1); ta_start(ta, tag, value); s2_sip_respond_to(request, dialog, status, phrase, SIPTAG_CONTENT_TYPE_STR("application/sdp"), SIPTAG_PAYLOAD_STR(body), SIPTAG_CONTENT_DISPOSITION_STR("session"), ta_tags(ta)); ta_end(ta); } static struct message * invite_sent_by_nua(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { ta_list ta; ta_start(ta, tag, value); nua_invite(nh, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), ta_tags(ta)); ta_end(ta); fail_unless(s2_check_callstate(nua_callstate_calling)); return s2_sip_wait_for_request(SIP_METHOD_INVITE); } static void bye_by_nua(struct dialog *dialog, nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { ta_list ta; struct message *bye; ta_start(ta, tag, value); nua_bye(nh, ta_tags(ta)); ta_end(ta); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_sip_respond_to(bye, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(bye); fail_unless_event(nua_r_bye, 200); fail_unless(s2_check_callstate(nua_callstate_terminated)); } /* ====================================================================== */ /* 6 - ETSI cases */ /* 6.1 Call Control - Originating Endpoint - Call Establishment */ START_TEST(SIP_CC_OE_CE_V_019) { nua_handle_t *nh; struct message *invite; struct message *bye; S2_CASE("6.1.1", "SIP_CC_OE_CE_V_019", "Ensure that the IUT when an INVITE client transaction " "is in the Calling state, on receipt of Success (200 OK) " "responses differing only on the tag in the To header, " "sends an ACK request with a To header identical to the " "received one for each received Success (200 OK) responses."); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite = invite_sent_by_nua(nh, TAG_END()); process_offer(invite); respond_with_sdp(invite, d1, SIP_200_OK, TAG_END()); fail_unless_event(nua_r_invite, 200); fail_unless(s2_check_callstate(nua_callstate_ready)); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); respond_with_sdp(invite, d2, SIP_200_OK, TAG_END()); s2_sip_free_message(invite); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_sip_respond_to(bye, d2, SIP_200_OK, TAG_END()); s2_sip_free_message(bye); bye_by_nua(d1, nh, TAG_END()); nua_handle_destroy(nh); } END_TEST START_TEST(SIP_CC_OE_CE_TI_008) { nua_handle_t *nh; struct message *invite; S2_CASE("6.1.2", "SIP_CC_OE_CE_TI_008", "If an unreliable transport is used, ensure that " "the IUT, when an INVITE client transaction is in " "the Completed state, on receipt of final responses " "that matches the transaction, still answer with an " "ACK request until timer D set to at least 32 second expires."); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite = invite_sent_by_nua(nh, TAG_END()); s2_sip_respond_to(invite, d1, 404, "First not found", TAG_END()); fail_unless_event(nua_r_invite, 404); fail_unless(s2_check_callstate(nua_callstate_terminated)); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); s2_nua_fast_forward(5, s2base->root); s2_sip_respond_to(invite, d1, 404, "Not found after 5 seconds", TAG_END()); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); s2_nua_fast_forward(5, s2base->root); s2_sip_respond_to(invite, d1, 404, "Not found after 10 seconds", TAG_END()); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); s2_nua_fast_forward(21, s2base->root); s2_sip_respond_to(invite, d1, 404, "Not found after 31 seconds", TAG_END()); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); s2_nua_fast_forward(5, s2base->root); /* Wake up nua thread and let it time out INVITE transaction */ nua_set_params(s2->nua, TAG_END()); fail_unless_event(nua_r_set_params, 0); s2_sip_respond_to(invite, d1, 404, "Not found after 32 seconds", TAG_END()); s2_sip_free_message(invite); fail_if(s2_sip_check_request_timeout(SIP_METHOD_ACK, 3)); nua_handle_destroy(nh); } END_TEST START_TEST(SIP_CC_OE_CE_TI_011_012) { nua_handle_t *nh; struct message *invite; S2_CASE("6.1.2", "SIP_CC_OE_CE_TI_011_012", "Ensure that the IUT, when an INVITE client transaction " "has been in the Terminated state, on receipt of a " "retransmitted Success (200 OK) responses sends an ACK " "request until 64*T1 duration expires, after this, " "on receipt of a retransmitted Success (200 OK) " "responses does not send an ACK request."); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite = invite_sent_by_nua(nh, TAG_END()); process_offer(invite); respond_with_sdp(invite, d1, SIP_200_OK, TAG_END()); fail_unless_event(nua_r_invite, 200); fail_unless(s2_check_callstate(nua_callstate_ready)); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); s2_nua_fast_forward(5, s2base->root); respond_with_sdp(invite, d1, SIP_200_OK, TAG_END()); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); s2_nua_fast_forward(5, s2base->root); respond_with_sdp(invite, d1, SIP_200_OK, TAG_END()); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); s2_nua_fast_forward(20, s2base->root); respond_with_sdp(invite, d1, SIP_200_OK, TAG_END()); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); /* Stack times out the INVITE transaction */ s2_nua_fast_forward(5, s2base->root); respond_with_sdp(invite, d1, SIP_200_OK, SIPTAG_SUBJECT_STR("Stray 200 OK"), TAG_END()); s2_sip_free_message(invite); mark_point(); fail_if(s2_sip_check_request_timeout(SIP_METHOD_ACK, 3)); bye_by_nua(d1, nh, TAG_END()); nua_handle_destroy(nh); } END_TEST TCase *sip_cc_oe_ce_tcase(int threading) { TCase *tc = tcase_create("6.1 - ETSI CC OE - Call Establishment"); void (*setup)(void) = threading ? etsi_thread_setup : etsi_threadless_setup; tcase_add_checked_fixture(tc, setup, etsi_teardown); { tcase_add_test(tc, SIP_CC_OE_CE_V_019); tcase_add_test(tc, SIP_CC_OE_CE_TI_008); tcase_add_test(tc, SIP_CC_OE_CE_TI_011_012); } return tc; } /* ====================================================================== */ void check_etsi_cases(Suite *suite, int threading) { suite_add_tcase(suite, sip_cc_oe_ce_tcase(threading)); } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/check_nua.c000066400000000000000000000317561223300710500224350ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2007 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE check_nua.c * * @brief Check-driven tester for Sofia SIP User Agent library * * @author Pekka Pessi * * @copyright (C) 2007 Nokia Corporation. */ #include "config.h" #undef NDEBUG #include "check_nua.h" #include "s2dns.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int s2_nua_deferrable_timers; static int s2_nua_print_events; static void usage(int exitcode) { fprintf(exitcode ? stderr : stdout, "usage: %s [--xml=logfile] case,...\n", s2_tester); exit(exitcode); } int main(int argc, char *argv[]) { int i, failed = 0, selected = 0; int threading, single_thread, multi_thread; char const *xml = NULL; Suite *suite = suite_create("Unit tests for Sofia-SIP UA Engine"); SRunner *runner; s2_tester = "check_nua"; s2_suite("N2"); if (getenv("CHECK_NUA_VERBOSE")) s2_start_stop = strtoul(getenv("CHECK_NUA_VERBOSE"), NULL, 10); if (getenv("CHECK_NUA_EVENTS")) s2_nua_print_events = 1; if (getenv("CHECK_NUA_DEFERRABLE_TIMERS")) s2_nua_deferrable_timers = 1; for (i = 1; argv[i]; i++) { if (su_strnmatch(argv[i], "--xml=", strlen("--xml="))) { xml = argv[i] + strlen("--xml="); } else if (su_strmatch(argv[i], "--xml")) { if (!(xml = argv[++i])) usage(2); } else if (su_strmatch(argv[i], "-v")) { s2_start_stop = 1; } else if (su_strmatch(argv[i], "-?") || su_strmatch(argv[i], "-h") || su_strmatch(argv[i], "--help")) usage(0); else { s2_select_tests(argv[i]); selected = 1; } } if (!selected) s2_select_tests(getenv("CHECK_NUA_CASES")); if (getenv("CHECK_NUA_THREADING")) { single_thread = strcmp(getenv("CHECK_NUA_THREADING"), "no"); multi_thread = !single_thread; } else { single_thread = multi_thread = 1; } if (single_thread) { check_register_cases(suite, threading = 0); check_simple_cases(suite, threading = 0); check_session_cases(suite, threading = 0); check_etsi_cases(suite, threading = 0); } if (multi_thread) { check_register_cases(suite, threading = 1); check_session_cases(suite, threading = 1); check_etsi_cases(suite, threading = 1); check_simple_cases(suite, threading = 1); } runner = srunner_create(suite); if (xml) srunner_set_xml(runner, argv[1]); srunner_run_all(runner, CK_ENV); failed = srunner_ntests_failed(runner); srunner_free(runner); exit(failed ? EXIT_FAILURE : EXIT_SUCCESS); } /* ---------------------------------------------------------------------- */ /* -- Globals -------------------------------------------------------------- */ struct s2nua *s2; int s2_nua_thread = 0; su_nanotime_t s2_nua_started; unsigned s2_default_registration_duration = 3600; char const s2_auth_digest_str[] = "Digest realm=\"s2test\", " "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", " "qop=\"auth\", " "algorithm=\"MD5\""; char const s2_auth_credentials[] = "Digest:\"s2test\":abc:abc"; char const s2_auth2_digest_str[] = "Digest realm=\"s2test2\", " "nonce=\"fb0c093dcd98b7102dd2f0e8b11d0f600b\", " "qop=\"auth\", " "algorithm=\"MD5\""; char const s2_auth2_credentials[] = "Digest:\"s2test2\":abc:abc"; char const s2_auth3_digest_str[] = "Digest realm=\"s2test3\", " "nonce=\"e8b11d0f600bfb0c093dcd98b7102dd2f0\", " "qop=\"auth-int\", " "algorithm=\"MD5-sess\""; char const s2_auth3_credentials[] = "Digest:\"s2test3\":abc:abc"; /* -- NUA events -------------------------------------------------------- */ struct event *s2_remove_event(struct event *e) { if ((*e->prev = e->next)) e->next->prev = e->prev; e->prev = NULL, e->next = NULL; return e; } void s2_free_event(struct event *e) { if (e) { if (e->prev) { if ((*e->prev = e->next)) e->next->prev = e->prev; } nua_destroy_event(e->event); nua_handle_unref(e->nh); free(e); } } void s2_flush_events(void) { while (s2->events) { s2_free_event(s2->events); } } int s2_next_thing(struct event **event, struct message **message) { for (;;) { if (s2->events) { *event = s2_remove_event(s2->events); return 0; } if (s2sip->received) { *message = s2_sip_remove_message(s2sip->received); return 1; } s2_step(); } } struct event *s2_next_event(void) { for (;;) { if (s2->events) return s2_remove_event(s2->events); su_root_step(s2base->root, 100); } } struct event *s2_wait_for_event(nua_event_t event, int status) { struct event *e; for (;;) { for (e = s2->events; e; e = e->next) { if (event != nua_i_none && event != e->data->e_event) continue; if (status && e->data->e_status != status) continue; return s2_remove_event(e); } su_root_step(s2base->root, 100); } } int s2_check_event(nua_event_t event, int status) { struct event *e = s2_wait_for_event(event, status); s2_free_event(e); return e != NULL; } enum nua_callstate s2_event_callstate(struct event *e) { if (e) { tagi_t const *tagi = tl_find(e->data->e_tags, nutag_callstate); if (tagi) return (enum nua_callstate) tagi->t_value; } return -1; } int s2_check_callstate(enum nua_callstate state) { int retval = 0; struct event *e; e = s2_wait_for_event(nua_i_state, 0); retval = state == s2_event_callstate(e); s2_free_event(e); return retval; } int s2_check_substate(struct event *e, enum nua_substate state) { int retval = 0; tagi_t const *tagi; tagi = tl_find(e->data->e_tags, nutag_substate); if (tagi) { retval = (tag_value_t)state == tagi->t_value; } return retval; } static void s2_nua_callback(nua_event_t event, int status, char const *phrase, nua_t *nua, nua_magic_t *_t, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]) { struct event *e, **prev; if (event == nua_i_active || event == nua_i_terminated) return; e = calloc(1, sizeof *e); nua_save_event(nua, e->event); e->nh = nua_handle_ref(nh); e->data = nua_event_data(e->event); e->sip = sip_object(e->data->e_msg); if (s2_nua_print_events) { su_nanotime_t now; char timestamp[32]; su_nanotime(&now); if (s2_nua_started == 0) s2_nua_started = now; now -= s2_nua_started; now /= 1000000; snprintf(timestamp, sizeof timestamp, "%03u.%03u", (unsigned)(now / 1000), (unsigned)(now % 1000)); fprintf(stderr, "%s: event %s status %u %s\n", timestamp, nua_event_name(event), status, phrase); tl_print(stderr, "", tags); } for (prev = &s2->events; *prev; prev = &(*prev)->next) ; *prev = e, e->prev = prev; } /* ====================================================================== */ SOFIAPUBVAR su_log_t nua_log[]; SOFIAPUBVAR su_log_t soa_log[]; SOFIAPUBVAR su_log_t nea_log[]; SOFIAPUBVAR su_log_t nta_log[]; SOFIAPUBVAR su_log_t tport_log[]; SOFIAPUBVAR su_log_t su_log_default[]; void s2_setup_logs(int level) { su_log_soft_set_level(nua_log, level); su_log_soft_set_level(soa_log, level); su_log_soft_set_level(su_log_default, level); su_log_soft_set_level(nea_log, level); su_log_soft_set_level(nta_log, level); su_log_soft_set_level(tport_log, level); if (getenv("TPORT_LOG") == NULL && getenv("S2_TPORT_LOG") == NULL) { if (s2sip) tport_set_params(s2sip->master, TPTAG_LOG(level > 1), TAG_END()); } } nua_t *s2_nua_setup(char const *label, tag_type_t tag, tag_value_t value, ...) { ta_list ta; s2_setup(label); s2 = su_home_new(sizeof *s2); s2_dns_setup(s2base->root); s2_setup_logs(0); s2_sip_setup("example.org", NULL, TAG_END()); assert(s2sip->contact); s2_dns_domain("example.org", 1, "s2", 1, s2sip->udp.contact->m_url, "s2", 1, s2sip->tcp.contact->m_url, NULL); /* enable/disable multithreading */ su_root_threading(s2base->root, s2_nua_thread); su_nanotime(&s2_nua_started); ta_start(ta, tag, value); s2->nua = nua_create(s2base->root, s2_nua_callback, s2, SIPTAG_FROM_STR("Alice "), /* NUTAG_PROXY((url_string_t *)s2sip->contact->m_url), */ /* Use internal DNS server */ NUTAG_PROXY("sip:example.org"), /* Force sresolv to use localhost and s2dns as DNS server */ #if HAVE_WIN32 SRESTAG_RESOLV_CONF("NUL"), #else SRESTAG_RESOLV_CONF("/dev/null"), #endif NUTAG_DEFERRABLE_TIMERS(s2_nua_deferrable_timers), ta_tags(ta)); ta_end(ta); return s2->nua; } void s2_nua_fast_forward(unsigned long seconds, su_root_t *steproot) { s2_fast_forward(seconds, NULL); if (s2_nua_thread) /* Wake up nua thread */ nua_handle_by_call_id(s2->nua, NULL); if (steproot) su_root_step(steproot, 0); } void s2_nua_teardown(void) { if (s2) { struct s2nua *zap = s2; nua_destroy(s2->nua), s2->nua = NULL; s2 = NULL; su_home_unref(zap->home); } s2_dns_teardown(); s2_sip_teardown(); s2_teardown(); } /* ====================================================================== */ /** Register NUA user. * *
 *  A                  B
 *  |-----REGISTER---->|
 *  |<-----200 OK------|
 *  |                  |
 * 
*/ void s2_register_setup(void) { nua_handle_t *nh; struct message *m; assert(s2 && s2->nua); assert(!s2->registration->nh); nh = nua_handle(s2->nua, NULL, TAG_END()); nua_register(nh, TAG_END()); m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); assert(m); s2_save_register(m); s2_sip_respond_to(m, NULL, SIP_200_OK, SIPTAG_CONTACT(s2->registration->contact), TAG_END()); s2_sip_free_message(m); assert(s2->registration->contact != NULL); fail_unless_event(nua_r_register, 200); s2->registration->nh = nh; } /** Un-register NUA user. * *
 *  A                  B
 *  |-----REGISTER---->|
 *  |<-----200 OK------|
 *  |                  |
 * 
*/ void s2_register_teardown(void) { if (s2 && s2->registration->nh) { nua_handle_t *nh = s2->registration->nh; struct message *m; nua_unregister(nh, TAG_END()); m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); assert(m); s2_save_register(m); s2_sip_respond_to(m, NULL, SIP_200_OK, SIPTAG_CONTACT(s2->registration->contact), TAG_END()); assert(s2->registration->contact == NULL); s2_sip_free_message(m); fail_unless_event(nua_r_unregister, 200); nua_handle_destroy(nh); s2->registration->nh = NULL; } } int s2_save_register(struct message *rm) { sip_contact_t *contact, *m, **m_prev; sip_expires_t const *ex; sip_date_t const *date; sip_time_t now = rm->when.tv_sec, expires; msg_header_free_all(s2->home, (msg_header_t *)s2->registration->aor); msg_header_free_all(s2->home, (msg_header_t *)s2->registration->contact); tport_unref(s2->registration->tport); s2->registration->aor = NULL; s2->registration->contact = NULL; s2->registration->tport = NULL; if (rm == NULL) return 0; assert(rm && rm->sip && rm->sip->sip_request); assert(rm->sip->sip_request->rq_method == sip_method_register); ex = rm->sip->sip_expires; date = rm->sip->sip_date; contact = sip_contact_dup(s2->home, rm->sip->sip_contact); for (m_prev = &contact; *m_prev;) { m = *m_prev; expires = sip_contact_expires(m, ex, date, s2_default_registration_duration, now); if (expires) { char *p = su_sprintf(s2->home, "expires=%lu", (unsigned long)expires); msg_header_add_param(s2->home, m->m_common, p); m_prev = &m->m_next; } else { *m_prev = m->m_next; m->m_next = NULL; msg_header_free(s2->home, (msg_header_t *)m); } } if (contact == NULL) return 0; s2->registration->aor = sip_to_dup(s2->home, rm->sip->sip_to); s2->registration->contact = contact; s2->registration->tport = tport_ref(rm->tport); s2sip->sut.aor = s2->registration->aor; s2sip->sut.contact = s2->registration->contact; s2sip->sut.tport = s2->registration->tport; return 0; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/check_nua.h000066400000000000000000000060251223300710500224310ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2008 Nokia Corporation. * * Contact: Pekka Pessi * * 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 */ #ifndef CHECK_NUA_H #include #include #include #include #include #include "s2base.h" #include "s2util.h" #include "s2sip.h" struct s2nua { su_home_t home[1]; nua_t *nua; int shutdown; struct event { struct event *next, **prev; nua_saved_event_t event[1]; nua_handle_t *nh; sip_t *sip; nua_event_data_t const *data; su_time_t when; } *events; struct { nua_handle_t *nh; sip_to_t *aor; sip_contact_t *contact; tport_t *tport; } registration[1]; }; extern unsigned s2_default_registration_duration; extern char const s2_auth_digest_str[]; extern char const s2_auth_credentials[]; extern char const s2_auth2_digest_str[]; extern char const s2_auth2_credentials[]; extern char const s2_auth3_digest_str[]; extern char const s2_auth3_credentials[]; extern int s2_nua_thread; extern struct s2nua *s2; void s2_setup_logs(int level); struct event *s2_remove_event(struct event *); void s2_free_event(struct event *); void s2_flush_events(void); int s2_next_thing(struct event **event, struct message **message); struct event *s2_next_event(void); struct event *s2_wait_for_event(nua_event_t event, int status); int s2_check_event(nua_event_t event, int status); enum nua_callstate s2_event_callstate(struct event *e); int s2_check_callstate(enum nua_callstate state); int s2_check_substate(struct event *e, enum nua_substate state); #define fail_unless_event(event, status) \ fail_unless(s2_check_event(event, status)) #define SIP_METHOD_UNKNOWN sip_method_unknown, NULL void s2_flush_all(void); nua_t *s2_nua_setup(char const *label, tag_type_t tag, tag_value_t value, ...); void s2_nua_teardown(void); void s2_nua_fast_forward(unsigned long seconds, su_root_t *steproot); int s2_save_register(struct message *m); void s2_register_setup(void); void s2_register_teardown(void); #include void check_session_cases(Suite *suite, int threading); void check_register_cases(Suite *suite, int threading); void check_etsi_cases(Suite *suite, int threading); void check_simple_cases(Suite *suite, int threading); #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/check_register.c000066400000000000000000000660151223300710500234720ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2008 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE check_register.c * * @brief Check-driven tester for Sofia SIP User Agent library * * @author Pekka Pessi * * @copyright (C) 2008 Nokia Corporation. */ #include "config.h" #undef NDEBUG #include "check_nua.h" #include #include #include #include #include #include #include #include #include SOFIAPUBVAR su_log_t tport_log[]; static nua_t *nua; static void register_setup(void) { nua = s2_nua_setup("register", TAG_END()); } static void register_thread_setup(void) { s2_nua_thread = 1; register_setup(); } static void register_threadless_setup(void) { s2_nua_thread = 0; register_setup(); } static void pingpong_setup(void) { nua = s2_nua_setup("register with pingpong", TPTAG_PINGPONG(20000), TPTAG_KEEPALIVE(10000), TAG_END()); tport_set_params(s2sip->tcp.tport, TPTAG_PONG2PING(1), TAG_END()); } static void pingpong_thread_setup(void) { s2_nua_thread = 1; pingpong_setup(); } static void pingpong_threadless_setup(void) { s2_nua_thread = 0; pingpong_setup(); } static void register_teardown(void) { s2_teardown_started("register"); nua_shutdown(nua); fail_unless_event(nua_r_shutdown, 200); s2_nua_teardown(); } static void add_register_fixtures(TCase *tc, int threading, int pingpong) { void (*setup)(void); if (pingpong) setup = threading ? pingpong_thread_setup : pingpong_threadless_setup; else setup = threading ? register_thread_setup : register_threadless_setup; tcase_add_checked_fixture(tc, setup, register_teardown); } /* ---------------------------------------------------------------------- */ START_TEST(register_1_0_1) { nua_handle_t *nh = nua_handle(nua, NULL, TAG_END()); struct message *m; S2_CASE("1.0.1", "Failed Register", "REGISTER returned 403 response"); nua_register(nh, TAG_END()); fail_unless((m = s2_sip_wait_for_request(SIP_METHOD_REGISTER)) != NULL, NULL); s2_sip_respond_to(m, NULL, SIP_403_FORBIDDEN, TAG_END()); s2_sip_free_message(m); nua_handle_destroy(nh); } END_TEST START_TEST(register_1_1_1) { S2_CASE("1.1.1", "Basic Register", "REGISTER returning 200 OK"); s2_register_setup(); s2_register_teardown(); } END_TEST START_TEST(register_1_1_2) { nua_handle_t *nh; struct message *m; S2_CASE("1.1.2", "Register with dual authentication", "Register, authenticate"); nh = nua_handle(nua, NULL, TAG_END()); nua_register(nh, TAG_END()); m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); fail_if(!m); s2_sip_respond_to(m, NULL, SIP_407_PROXY_AUTH_REQUIRED, SIPTAG_PROXY_AUTHENTICATE_STR(s2_auth_digest_str), TAG_END()); s2_sip_free_message(m); fail_unless_event(nua_r_register, 407); nua_authenticate(nh, NUTAG_AUTH(s2_auth_credentials), TAG_END()); m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); fail_if(!m); s2_sip_respond_to(m, NULL, SIP_401_UNAUTHORIZED, SIPTAG_WWW_AUTHENTICATE_STR(s2_auth2_digest_str), SIPTAG_PROXY_AUTHENTICATE_STR(s2_auth_digest_str), TAG_END()); s2_sip_free_message(m); fail_unless_event(nua_r_register, 401); nua_authenticate(nh, NUTAG_AUTH(s2_auth2_credentials), TAG_END()); m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); fail_if(!m); fail_if(!m->sip->sip_authorization); fail_if(!m->sip->sip_proxy_authorization); s2_save_register(m); s2_sip_respond_to(m, NULL, SIP_200_OK, SIPTAG_CONTACT(s2->registration->contact), TAG_END()); s2_sip_free_message(m); assert(s2->registration->contact != NULL); fail_unless_event(nua_r_register, 200); s2->registration->nh = nh; s2_register_teardown(); } END_TEST /* ---------------------------------------------------------------------- */ static char const receive_natted[] = "received=4.255.255.9"; static char const receive_natted2[] = "received=4.255.255.10"; /* Return Via that looks very natted */ static sip_via_t *natted_via(struct message *m, const char *receive_natted) { su_home_t *h; sip_via_t *via; h = msg_home(m->msg); via = sip_via_dup(h, m->sip->sip_via); msg_header_replace_param(h, via->v_common, receive_natted); if (via->v_protocol == sip_transport_udp) msg_header_replace_param(h, via->v_common, "rport=9"); if (via->v_protocol == sip_transport_tcp && via->v_rport) { tp_name_t const *tpn = tport_name(m->tport); char *rport = su_sprintf(h, "rport=%s", tpn->tpn_port); msg_header_replace_param(h, via->v_common, rport); } return via; } /* ---------------------------------------------------------------------- */ START_TEST(register_1_2_1) { nua_handle_t *nh; struct message *m; S2_CASE("1.2.1", "Register behind NAT", "Register through NAT, detect NAT, re-REGISTER"); nh = nua_handle(nua, NULL, TAG_END()); nua_register(nh, TAG_END()); m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); fail_if(!m); fail_if(!m->sip->sip_contact || m->sip->sip_contact->m_next); s2_save_register(m); s2_sip_respond_to(m, NULL, SIP_200_OK, SIPTAG_CONTACT(s2->registration->contact), SIPTAG_VIA(natted_via(m, receive_natted)), TAG_END()); s2_sip_free_message(m); assert(s2->registration->contact != NULL); fail_unless_event(nua_r_register, 100); m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); fail_if(!m); fail_if(!m->sip->sip_contact || !m->sip->sip_contact->m_next); s2_save_register(m); s2_sip_respond_to(m, NULL, SIP_200_OK, SIPTAG_CONTACT(s2->registration->contact), SIPTAG_VIA(natted_via(m, receive_natted)), TAG_END()); s2_sip_free_message(m); fail_unless(s2->registration->contact != NULL); fail_if(s2->registration->contact->m_next != NULL); fail_unless_event(nua_r_register, 200); s2->registration->nh = nh; s2_register_teardown(); } END_TEST static nua_handle_t *make_auth_natted_register( nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { struct message *m; ta_list ta; ta_start(ta, tag, value); nua_register(nh, ta_tags(ta)); ta_end(ta); m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); fail_if(!m); s2_sip_respond_to(m, NULL, SIP_401_UNAUTHORIZED, SIPTAG_WWW_AUTHENTICATE_STR(s2_auth_digest_str), SIPTAG_VIA(natted_via(m, receive_natted)), TAG_END()); s2_sip_free_message(m); fail_unless_event(nua_r_register, 401); /* NAT detected event */ fail_unless_event(nua_i_outbound, 101); nua_authenticate(nh, NUTAG_AUTH(s2_auth_credentials), TAG_END()); m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); fail_if(!m); fail_if(!m->sip->sip_authorization); /* should not unregister the previous contact * as it has not been successfully registered */ fail_if(!m->sip->sip_contact); fail_if(m->sip->sip_contact->m_next); s2_save_register(m); s2_sip_respond_to(m, NULL, SIP_200_OK, SIPTAG_CONTACT(s2->registration->contact), SIPTAG_VIA(natted_via(m, receive_natted)), TAG_END()); s2_sip_free_message(m); assert(s2->registration->contact != NULL); fail_unless_event(nua_r_register, 200); return nh; } START_TEST(register_1_2_2_1) { nua_handle_t *nh = nua_handle(nua, NULL, TAG_END()); S2_CASE("1.2.2.1", "Register behind NAT", "Authenticate, outbound activated"); mark_point(); make_auth_natted_register(nh, TAG_END()); s2->registration->nh = nh; s2_register_teardown(); } END_TEST START_TEST(register_1_2_2_2) { nua_handle_t *nh = nua_handle(nua, NULL, TAG_END()); struct message *m; S2_CASE("1.2.2.2", "Register behind NAT", "Authenticate, outbound activated, " "authenticate OPTIONS probe, " "NAT binding change"); mark_point(); make_auth_natted_register(nh, TAG_END()); s2->registration->nh = nh; mark_point(); m = s2_sip_wait_for_request(SIP_METHOD_OPTIONS); fail_if(!m); s2_sip_respond_to(m, NULL, SIP_407_PROXY_AUTH_REQUIRED, SIPTAG_VIA(natted_via(m, receive_natted)), SIPTAG_PROXY_AUTHENTICATE_STR(s2_auth_digest_str), TAG_END()); s2_sip_free_message(m); mark_point(); m = s2_sip_wait_for_request(SIP_METHOD_OPTIONS); fail_if(!m); fail_if(!m->sip->sip_proxy_authorization); s2_sip_respond_to(m, NULL, SIP_200_OK, SIPTAG_VIA(natted_via(m, receive_natted)), TAG_END()); s2_sip_free_message(m); su_root_step(s2base->root, 20); su_root_step(s2base->root, 20); s2_nua_fast_forward(120, s2base->root); /* Default keepalive interval */ mark_point(); m = s2_sip_wait_for_request(SIP_METHOD_OPTIONS); s2_sip_respond_to(m, NULL, SIP_200_OK, SIPTAG_VIA(natted_via(m, receive_natted)), TAG_END()); s2_sip_free_message(m); su_root_step(s2base->root, 20); su_root_step(s2base->root, 20); s2_nua_fast_forward(120, s2base->root); /* Default keepalive interval */ mark_point(); m = s2_sip_wait_for_request(SIP_METHOD_OPTIONS); s2_sip_respond_to(m, NULL, SIP_200_OK, SIPTAG_VIA(natted_via(m, receive_natted2)), TAG_END()); s2_sip_free_message(m); fail_unless_event(nua_i_outbound, 0); m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); fail_if(!m); fail_if(!m->sip->sip_authorization); fail_if(!m->sip->sip_contact || !m->sip->sip_contact->m_next); s2_save_register(m); s2_sip_respond_to(m, NULL, SIP_200_OK, SIPTAG_CONTACT(s2->registration->contact), SIPTAG_VIA(natted_via(m, receive_natted2)), TAG_END()); s2_sip_free_message(m); fail_unless_event(nua_r_register, 200); fail_unless(s2->registration->contact != NULL); fail_if(s2->registration->contact->m_next != NULL); s2_register_teardown(); } END_TEST START_TEST(register_1_2_2_3) { nua_handle_t *nh = nua_handle(nua, NULL, TAG_END()); struct message *m; S2_CASE("1.2.2.3", "Register behind NAT", "Authenticate, outbound activated, " "detect NAT binding change when re-REGISTERing"); mark_point(); make_auth_natted_register(nh, NUTAG_OUTBOUND("no-options-keepalive, no-validate"), TAG_END()); s2->registration->nh = nh; s2_nua_fast_forward(3600, s2base->root); mark_point(); m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); fail_if(!m); fail_if(!m->sip->sip_authorization); s2_save_register(m); s2_sip_respond_to(m, NULL, SIP_200_OK, SIPTAG_CONTACT(s2->registration->contact), SIPTAG_VIA(natted_via(m, receive_natted2)), TAG_END()); s2_sip_free_message(m); fail_unless_event(nua_r_register, 100); m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); fail_if(!m); fail_if(!m->sip->sip_authorization); fail_if(!m->sip->sip_contact || !m->sip->sip_contact->m_next); s2_save_register(m); s2_sip_respond_to(m, NULL, SIP_200_OK, SIPTAG_CONTACT(s2->registration->contact), SIPTAG_VIA(natted_via(m, receive_natted2)), TAG_END()); s2_sip_free_message(m); fail_unless(s2->registration->contact != NULL); fail_if(s2->registration->contact->m_next != NULL); fail_unless_event(nua_r_register, 200); s2_register_teardown(); } END_TEST START_TEST(register_1_2_3) { nua_handle_t *nh; struct message *m; S2_CASE("1.2.3", "Register behind NAT", "Outbound activated by error response"); nh = nua_handle(nua, NULL, TAG_END()); nua_register(nh, TAG_END()); mark_point(); m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); fail_if(!m); fail_if(!m->sip->sip_contact || m->sip->sip_contact->m_next); s2_sip_respond_to(m, NULL, 400, "Bad Contact", SIPTAG_VIA(natted_via(m, receive_natted)), TAG_END()); s2_sip_free_message(m); fail_unless_event(nua_r_register, 100); m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); fail_if(!m); s2_save_register(m); s2_sip_respond_to(m, NULL, SIP_200_OK, SIPTAG_CONTACT(s2->registration->contact), SIPTAG_VIA(natted_via(m, receive_natted)), TAG_END()); s2_sip_free_message(m); fail_unless(s2->registration->contact != NULL); fail_if(s2->registration->contact->m_next != NULL); fail_unless_event(nua_r_register, 200); s2->registration->nh = nh; s2_register_teardown(); } END_TEST #include START_TEST(register_1_2_4) { nua_handle_t *nh = nua_handle(nua, NULL, TAG_END()); struct message *m; struct event *e; unsigned t1, n; S2_CASE("1.2.4", "Register behind NAT", "Authenticate, outbound activated, " "drop OPTIONS, check that OPTIONS is not retried"); mark_point(); make_auth_natted_register(nh, TAG_END()); s2->registration->nh = nh; mark_point(); t1 = 500; for (t1 = 500, n = 0; n < 20; n++) { e = NULL, m = NULL; s2_next_thing(&e, &m); if (e) break; fail_if(!m); fail_if(!m->sip->sip_request); fail_if(m->sip->sip_request->rq_method != sip_method_options); s2_sip_free_message(m); mark_point(); s2_nua_fast_forward((t1 + 500) / 1000, s2base->root); t1 *= 2; if (t1 > 4000) t1 = 4000; } fail_unless(e != NULL); fail_unless(e->data->e_event == nua_i_outbound); fail_unless(e->data->e_status == 408); s2_free_event(e); s2_sip_flush_messages(); s2_nua_fast_forward(3600, s2base->root); m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); fail_if(!m); fail_if(!m->sip->sip_authorization); fail_if(!m->sip->sip_contact); s2_default_registration_duration = 120; s2_save_register(m); s2_sip_respond_to(m, NULL, SIP_200_OK, SIPTAG_CONTACT(s2->registration->contact), TAG_END()); s2_sip_free_message(m); fail_unless_event(nua_r_register, 200); fail_unless(s2->registration->contact != NULL); fail_if(s2->registration->contact->m_next != NULL); s2_sip_flush_messages(); while (s2sip->received == NULL) { s2_nua_fast_forward(10, s2base->root); } m = s2_sip_remove_message(s2sip->received); fail_if(!m); fail_unless(m->sip->sip_request->rq_method == sip_method_register); fail_if(!m->sip->sip_authorization); fail_if(!m->sip->sip_contact); s2_save_register(m); s2_sip_respond_to(m, NULL, SIP_200_OK, SIPTAG_CONTACT(s2->registration->contact), TAG_END()); s2_sip_free_message(m); fail_unless_event(nua_r_register, 200); s2_register_teardown(); } END_TEST /* ---------------------------------------------------------------------- */ START_TEST(register_1_3_1) { nua_handle_t *nh; struct message *m; S2_CASE("1.3.1", "Register over TCP via NAT", "REGISTER via TCP, detect NTA, re-REGISTER"); nh = nua_handle(nua, NULL, TAG_END()); nua_register(nh, NUTAG_PROXY(s2sip->tcp.contact->m_url), TAG_END()); m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); fail_if(!m); fail_if(!m->sip->sip_contact || m->sip->sip_contact->m_next); fail_if(!tport_is_tcp(m->tport)); s2_save_register(m); s2_sip_respond_to(m, NULL, SIP_200_OK, SIPTAG_CONTACT(s2->registration->contact), SIPTAG_VIA(natted_via(m, receive_natted)), TAG_END()); s2_sip_free_message(m); assert(s2->registration->contact != NULL); fail_unless_event(nua_r_register, 100); m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); fail_if(!m); fail_if(!m->sip->sip_contact || !m->sip->sip_contact->m_next); s2_save_register(m); s2_sip_respond_to(m, NULL, SIP_200_OK, SIPTAG_CONTACT(s2->registration->contact), SIPTAG_VIA(natted_via(m, receive_natted)), TAG_END()); s2_sip_free_message(m); fail_unless(s2->registration->contact != NULL); fail_if(s2->registration->contact->m_next != NULL); fail_unless( url_has_param(s2->registration->contact->m_url, "transport=tcp")); fail_unless_event(nua_r_register, 200); s2->registration->nh = nh; s2_register_teardown(); } END_TEST START_TEST(register_1_3_2_1) { nua_handle_t *nh = nua_handle(nua, NULL, TAG_END()); S2_CASE("1.3.2.1", "Register behind NAT", "Authenticate, outbound activated"); mark_point(); s2->registration->nh = nh; make_auth_natted_register(nh, NUTAG_PROXY(s2sip->tcp.contact->m_url), TAG_END()); fail_if(!tport_is_tcp(s2->registration->tport)); s2_register_teardown(); } END_TEST START_TEST(register_1_3_2_2) { nua_handle_t *nh = nua_handle(nua, NULL, TAG_END()); struct message *m; S2_CASE("1.3.2.2", "Register behind NAT with TCP", "Detect NAT over TCP using rport. " "Authenticate, detect NAT, " "close TCP at server, wait for re-REGISTERs."); nua_set_params(nua, NTATAG_TCP_RPORT(1), TAG_END()); fail_unless_event(nua_r_set_params, 200); mark_point(); s2->registration->nh = nh; make_auth_natted_register( nh, NUTAG_PROXY(s2sip->tcp.contact->m_url), NUTAG_OUTBOUND("no-options-keepalive, no-validate"), TAG_END()); fail_if(!tport_is_tcp(s2->registration->tport)); tport_shutdown(s2->registration->tport, 2); m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); fail_if(!m); fail_if(!m->sip->sip_authorization); s2_save_register(m); s2_sip_respond_to(m, NULL, SIP_200_OK, SIPTAG_CONTACT(s2->registration->contact), SIPTAG_VIA(natted_via(m, receive_natted)), TAG_END()); s2_sip_free_message(m); /* The "NAT binding" changed when new TCP connection is established */ /* => NUA re-REGISTERs with newly detected contact */ fail_unless_event(nua_r_register, 100); m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); fail_if(!m); fail_if(!m->sip->sip_authorization); fail_if(!m->sip->sip_contact || !m->sip->sip_contact->m_next); s2_save_register(m); s2_sip_respond_to(m, NULL, SIP_200_OK, SIPTAG_CONTACT(s2->registration->contact), SIPTAG_VIA(natted_via(m, receive_natted)), TAG_END()); s2_sip_free_message(m); fail_unless_event(nua_r_register, 200); fail_unless(s2->registration->contact != NULL); fail_if(s2->registration->contact->m_next != NULL); s2_register_teardown(); } END_TEST #if nomore START_TEST(register_1_3_3_1) { nua_handle_t *nh = nua_handle(nua, NULL, TAG_END()); struct message *m; tport_t *tcp; S2_CASE("1.3.3.1", "Register behind NAT with UDP and TCP", "Register with UDP, UDP time-outing, then w/ TCP using rport. "); nua_set_params(nua, NTATAG_TCP_RPORT(1), TAG_END()); fail_unless_event(nua_r_set_params, 200); mark_point(); s2->registration->nh = nh; nua_register(nh, NUTAG_OUTBOUND("no-options-keepalive, no-validate"), TAG_END()); /* NTA tries with UDP, we drop them */ for (;;) { m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); fail_if(!m); if (!tport_is_udp(m->tport)) /* Drop UDP */ break; s2_sip_free_message(m); s2_nua_fast_forward(4, s2base->root); } tcp = tport_ref(m->tport); /* Respond to request over TCP */ s2_sip_respond_to(m, NULL, SIP_401_UNAUTHORIZED, SIPTAG_WWW_AUTHENTICATE_STR(s2_auth_digest_str), SIPTAG_VIA(natted_via(m, receive_natted)), TAG_END()); s2_sip_free_message(m); fail_unless_event(nua_r_register, 401); nua_authenticate(nh, NUTAG_AUTH(s2_auth_credentials), TAG_END()); /* Turn off pong */ tport_set_params(tcp, TPTAG_PONG2PING(0), TAG_END()); /* Now request over UDP ... registering TCP contact! */ m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); fail_if(!m); fail_if(!m->sip->sip_authorization); s2_save_register(m); fail_unless( url_has_param(s2->registration->contact->m_url, "transport=tcp")); s2_sip_respond_to(m, NULL, SIP_200_OK, SIPTAG_CONTACT(s2->registration->contact), SIPTAG_VIA(natted_via(m, receive_natted)), TAG_END()); s2_sip_free_message(m); /* NUA detects oops... re-registers UDP */ fail_unless_event(nua_r_register, 100); m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); fail_if(!m); fail_if(!m->sip->sip_authorization); fail_if(!m->sip->sip_contact || !m->sip->sip_contact->m_next); s2_save_register(m); s2_sip_respond_to(m, NULL, SIP_200_OK, SIPTAG_CONTACT(s2->registration->contact), SIPTAG_VIA(natted_via(m, receive_natted)), TAG_END()); s2_sip_free_message(m); fail_unless_event(nua_r_register, 200); fail_unless(s2->registration->contact != NULL); fail_if(s2->registration->contact->m_next != NULL); /* Wait until ping-pong failure closes the TCP connection */ { int i; for (i = 0; i < 5; i++) { su_root_step(s2base->root, 5); su_root_step(s2base->root, 5); su_root_step(s2base->root, 5); s2_nua_fast_forward(5, s2base->root); } } s2_register_teardown(); } END_TEST #endif START_TEST(register_1_3_3_2) { nua_handle_t *nh = nua_handle(nua, NULL, TAG_END()); struct message *m; tport_t *tcp; int i; S2_CASE("1.3.3.2", "Register behind NAT with TCP", "Register w/ TCP using rport, pingpong. "); nua_set_params(nua, NTATAG_TCP_RPORT(1), TAG_END()); fail_unless_event(nua_r_set_params, 200); mark_point(); s2->registration->nh = nh; nua_register(nh, NUTAG_PROXY(s2sip->tcp.contact->m_url), NUTAG_OUTBOUND("no-options-keepalive, no-validate"), TAG_END()); m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); fail_if(!m); fail_unless(tport_is_tcp(m->tport)); tcp = tport_ref(m->tport); /* Respond to request over TCP */ s2_sip_respond_to(m, NULL, SIP_401_UNAUTHORIZED, SIPTAG_WWW_AUTHENTICATE_STR(s2_auth_digest_str), SIPTAG_VIA(natted_via(m, receive_natted)), TAG_END()); s2_sip_free_message(m); fail_unless_event(nua_r_register, 401); nua_authenticate(nh, NUTAG_AUTH(s2_auth_credentials), TAG_END()); m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); fail_if(!m); fail_if(!m->sip->sip_authorization); fail_if(!m->sip->sip_contact); s2_save_register(m); s2_sip_respond_to(m, NULL, SIP_200_OK, SIPTAG_CONTACT(s2->registration->contact), SIPTAG_VIA(natted_via(m, receive_natted)), TAG_END()); s2_sip_free_message(m); fail_unless_event(nua_r_register, 200); fail_unless(s2->registration->contact != NULL); fail_if(s2->registration->contact->m_next != NULL); /* Turn off pong */ tport_set_params(tcp, TPTAG_PONG2PING(0), TAG_END()); /* Wait until ping-pong failure closes the TCP connection */ for (i = 0; i < 100; i++) { s2_nua_fast_forward(5, s2base->root); if (tport_is_closed(tcp)) break; } m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); fail_unless(tport_is_tcp(m->tport)); fail_unless(tcp != m->tport); fail_if(!m); fail_if(!m->sip->sip_authorization); fail_if(!m->sip->sip_contact); s2_save_register(m); s2_sip_respond_to(m, NULL, SIP_200_OK, SIPTAG_CONTACT(s2->registration->contact), SIPTAG_VIA(natted_via(m, receive_natted)), TAG_END()); s2_sip_free_message(m); tport_unref(tcp); /* Contact changed */ fail_unless_event(nua_r_register, 100); m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); fail_if(!m); fail_if(!m->sip->sip_authorization); fail_if(!m->sip->sip_contact); fail_if(!m->sip->sip_contact->m_next); s2_save_register(m); s2_sip_respond_to(m, NULL, SIP_200_OK, SIPTAG_CONTACT(s2->registration->contact), SIPTAG_VIA(natted_via(m, receive_natted)), TAG_END()); s2_sip_free_message(m); fail_unless_event(nua_r_register, 200); s2_register_teardown(); } END_TEST /* ---------------------------------------------------------------------- */ TCase *register_tcase(int threading) { TCase *tc = tcase_create("1 - REGISTER"); add_register_fixtures(tc, threading, 0); { tcase_add_test(tc, register_1_0_1); tcase_add_test(tc, register_1_1_1); tcase_add_test(tc, register_1_1_2); tcase_add_test(tc, register_1_2_1); tcase_add_test(tc, register_1_2_2_1); tcase_add_test(tc, register_1_2_2_2); tcase_add_test(tc, register_1_2_2_3); tcase_add_test(tc, register_1_2_3); tcase_add_test(tc, register_1_2_4); tcase_add_test(tc, register_1_3_1); tcase_add_test(tc, register_1_3_2_1); tcase_add_test(tc, register_1_3_2_2); } tcase_set_timeout(tc, 10); return tc; } TCase *pingpong_tcase(int threading) { TCase *tc = tcase_create("1 - REGISTER (with PingPong)"); add_register_fixtures(tc, threading, 1); { tcase_add_test(tc, register_1_3_3_2); } tcase_set_timeout(tc, 10); return tc; } /* ---------------------------------------------------------------------- */ START_TEST(client_1_4_1) { nua_handle_t *nh; struct message *message; struct event *response; S2_CASE("1.4.1", "Simple client transaction", "Send MESSAGE"); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); nua_message(nh, SIPTAG_CONTENT_TYPE_STR("text/plain"), SIPTAG_PAYLOAD_STR("hello"), TAG_END()); message = s2_sip_wait_for_request(SIP_METHOD_MESSAGE); s2_sip_respond_to(message, NULL, SIP_202_ACCEPTED, TAG_END()); s2_sip_free_message(message); response = s2_wait_for_event(nua_r_message, 202); s2_free_event(response); nua_handle_destroy(nh); } END_TEST START_TEST(client_1_4_2) { nua_handle_t *nh; struct message *message; struct event *response; S2_CASE("1.4.2", "Retry-After a delay", "Retry MESSAGE after a delay"); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); nua_message(nh, SIPTAG_CONTENT_TYPE_STR("text/plain"), SIPTAG_PAYLOAD_STR("hello"), TAG_END()); message = s2_sip_wait_for_request(SIP_METHOD_MESSAGE); s2_sip_respond_to(message, NULL, SIP_503_SERVICE_UNAVAILABLE, SIPTAG_RETRY_AFTER_STR("3"), TAG_END()); s2_sip_free_message(message); response = s2_wait_for_event(nua_r_message, 100); s2_free_event(response); s2_fast_forward(32, NULL); /* Too long delay */ message = s2_sip_wait_for_request(SIP_METHOD_MESSAGE); s2_sip_respond_to(message, NULL, SIP_503_SERVICE_UNAVAILABLE, SIPTAG_RETRY_AFTER_STR("32"), TAG_END()); s2_sip_free_message(message); response = s2_wait_for_event(nua_r_message, 503); s2_free_event(response); nua_set_params(nua, NUTAG_MAX_RETRY_AFTER(0), TAG_END()); fail_unless_event(nua_r_set_params, 200); /* Disable feature */ nua_message(nh, SIPTAG_CONTENT_TYPE_STR("text/plain"), SIPTAG_PAYLOAD_STR("hello"), TAG_END()); message = s2_sip_wait_for_request(SIP_METHOD_MESSAGE); s2_sip_respond_to(message, NULL, SIP_503_SERVICE_UNAVAILABLE, SIPTAG_RETRY_AFTER_STR("3"), TAG_END()); s2_sip_free_message(message); response = s2_wait_for_event(nua_r_message, 503); s2_free_event(response); nua_handle_destroy(nh); } END_TEST static TCase *client_tcase(int threading) { TCase *tc = tcase_create(threading ? "1.4 - client (MT)" : "1.4 - client"); void (*setup)(void); setup = threading ? register_thread_setup : register_threadless_setup; tcase_add_checked_fixture(tc, setup, register_teardown); tcase_add_test(tc, client_1_4_1); tcase_add_test(tc, client_1_4_2); return tc; } void check_register_cases(Suite *suite, int threading) { suite_add_tcase(suite, register_tcase(threading)); suite_add_tcase(suite, pingpong_tcase(threading)); suite_add_tcase(suite, client_tcase(threading)); } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/check_session.c000066400000000000000000003152131223300710500233260ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2008 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE check_session.c * * @brief NUA module tests for SIP session handling * * @author Pekka Pessi * * @copyright (C) 2008 Nokia Corporation. */ #include "config.h" #undef NDEBUG #include "check_nua.h" #include #include #include #include #include #include #include #include #include /* define XXX as 1 in order to see all failing test cases */ #ifndef XXX #define XXX (0) #endif /* ====================================================================== */ static nua_t *nua; static soa_session_t *soa = NULL, *soa2 = NULL; static struct dialog *dialog = NULL, *dialog2 = NULL; /* Variables changing test sequence */ static int fake_multipart; static int s2_nua_auto100 = 1; #define CRLF "\r\n" static void endpoint_setup(void) { soa = soa_create(NULL, s2base->root, NULL); fail_if(!soa); soa_set_params(soa, SOATAG_USER_SDP_STR("m=audio 5008 RTP/AVP 8 0" CRLF "m=video 5010 RTP/AVP 34" CRLF), TAG_END()); dialog = su_home_new(sizeof *dialog); fail_if(!dialog); } static void call_setup(void) { nua = s2_nua_setup("call", SIPTAG_ORGANIZATION_STR("Pussy Galore's Flying Circus"), NUTAG_OUTBOUND("no-options-keepalive, no-validate"), NUTAG_ACCEPT_MULTIPART(1), TAG_END()); endpoint_setup(); s2_register_setup(); } static void call_thread_setup(void) { s2_nua_thread = 1; call_setup(); } static void call_teardown(void) { s2_teardown_started("call"); mark_point(); fake_multipart = 0; s2_nua_auto100 = 1; s2_register_teardown(); if (s2->shutdown == 0) { mark_point(); nua_shutdown(nua); fail_unless_event(nua_r_shutdown, 200); } mark_point(); s2_nua_teardown(); } static void add_call_fixtures(TCase *tc, int threading) { if (threading) tcase_add_checked_fixture(tc, call_thread_setup, call_teardown); else tcase_add_checked_fixture(tc, call_setup, call_teardown); } static void save_sdp_to_soa(struct message *message) { sip_payload_t *pl; char const *body; isize_t bodylen; fail_if(!message); fail_if(!message->sip->sip_content_length); fail_if(!message->sip->sip_content_type); fail_if(strcmp(message->sip->sip_content_type->c_type, "application/sdp")); fail_if(!message->sip->sip_payload); pl = message->sip->sip_payload; body = pl->pl_data, bodylen = pl->pl_len; fail_if(soa_set_remote_sdp(soa, NULL, body, (issize_t)bodylen) < 0); } static void process_offer(struct message *message) { save_sdp_to_soa(message); fail_if(soa_generate_answer(soa, NULL) < 0); } static void process_answer(struct message *message) { save_sdp_to_soa(message); fail_if(soa_process_answer(soa, NULL) < 0); } /* Return true if answer is sent */ static inline int is_answer_sent(tagi_t const *tags) { tagi_t const *ti = tl_find(tags, nutag_answer_sent); return ti ? ti->t_value : 0; } /* Return true if offer is recv */ static inline int is_offer_recv(tagi_t const *tags) { tagi_t const *ti = tl_find(tags, nutag_offer_recv); return ti ? ti->t_value : 0; } /* Return true if answer is recv */ static inline int is_answer_recv(tagi_t const *tags) { tagi_t const *ti = tl_find(tags, nutag_answer_recv); return ti ? ti->t_value : 0; } static void respond_with_sdp(struct message *request, struct dialog *dialog, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...) { ta_list ta; char const *body; isize_t bodylen; char *mp = NULL; fail_if(soa_get_local_sdp(soa, NULL, &body, &bodylen) != 1); if (fake_multipart) { su_strlst_t *lst; lst = su_strlst_create_with(dialog->home, "Extra text\r\n", "--2iEl5G4DV4E\r\n", "Content-Type: text/plain\r\n", "--2iEl5G4DV4E\r\n", "Content-Type: application/sdp++\r\n" "Content-Disposition: session\r\n" "\r\n", "v=1", body + 3, "\r\n", "--2iEl5G4DV4E\r\n", "Content-Type: application/sdp\r\n" "Content-Disposition: session\r\n" "\r\n", body, "\r\n", "--2iEl5G4DV4E--\r\n", NULL); mp = su_strlst_join(lst, dialog->home, ""); fail_unless(mp != NULL); su_strlst_destroy(lst); body = mp; } ta_start(ta, tag, value); s2_sip_respond_to(request, dialog, status, phrase, SIPTAG_PAYLOAD_STR(body), SIPTAG_CONTENT_TYPE_STR( fake_multipart ? "multipart/alternative" : "application/sdp"), TAG_IF(!fake_multipart, SIPTAG_CONTENT_DISPOSITION_STR("session")), ta_tags(ta)); ta_end(ta); su_free(dialog->home, mp); } static void request_with_sdp(struct dialog *dialog, sip_method_t method, char const *name, tport_t *tport, tag_type_t tag, tag_value_t value, ...) { ta_list ta; char const *body; isize_t bodylen; char *mp = NULL; fail_if(soa_get_local_sdp(soa, NULL, &body, &bodylen) != 1); if (fake_multipart) { su_strlst_t *lst; lst = su_strlst_create_with(dialog->home, "Extra text\r\n", "--2iEl5G4DV4E\r\n", "Content-Type: text/plain\r\n", "--2iEl5G4DV4E\r\n", "Content-Type: application/sdp++\r\n" "Content-Disposition: session" " ;handling=optional\r\n" "\r\n", "v=1", body + 3, "\r\n", "--2iEl5G4DV4E\r\n", "Content-Type: application/sdp\r\n" "Content-Disposition: session" " ;handling=optional\r\n" "\r\n", body, "--2iEl5G4DV4E--\r\n", NULL); mp = su_strlst_join(lst, dialog->home, ""); fail_unless(mp != NULL); su_strlst_destroy(lst); body = mp; } ta_start(ta, tag, value); fail_if( s2_sip_request_to(dialog, method, name, tport, SIPTAG_CONTENT_TYPE_STR(fake_multipart ? "multipart/alternative" : "application/sdp"), SIPTAG_PAYLOAD_STR(body), ta_tags(ta))); ta_end(ta); su_free(dialog->home, mp); } static struct message * invite_sent_by_nua(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { ta_list ta; ta_start(ta, tag, value); nua_invite(nh, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), ta_tags(ta)); ta_end(ta); fail_unless(s2_check_callstate(nua_callstate_calling)); return s2_sip_wait_for_request(SIP_METHOD_INVITE); } static uint32_t s2_rseq; static struct message * respond_with_100rel(struct message *invite, struct dialog *d, int with_sdp, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...) { ta_list ta; sip_rseq_t rs[1]; assert(100 < status && status < 200); sip_rseq_init(rs); rs->rs_response = ++s2_rseq; ta_start(ta, tag, value); if (with_sdp) { respond_with_sdp( invite, dialog, status, phrase, SIPTAG_REQUIRE_STR("100rel"), SIPTAG_RSEQ(rs), ta_tags(ta)); } else { s2_sip_respond_to( invite, dialog, status, phrase, SIPTAG_REQUIRE_STR("100rel"), SIPTAG_RSEQ(rs), ta_tags(ta)); } ta_end(ta); fail_unless_event(nua_r_invite, status); return s2_sip_wait_for_request(SIP_METHOD_PRACK); } static void invite_by_nua(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { struct message *invite; struct event *i_state; ta_list ta; ta_start(ta, tag, value); invite = invite_sent_by_nua(nh, ta_tags(ta)); ta_end(ta); process_offer(invite); respond_with_sdp( invite, dialog, SIP_180_RINGING, SIPTAG_CONTENT_DISPOSITION_STR("session;handling=optional"), TAG_END()); fail_unless_event(nua_r_invite, 180); fail_unless(s2_check_callstate(nua_callstate_proceeding)); respond_with_sdp(invite, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(invite); fail_unless_event(nua_r_invite, 200); i_state = s2_wait_for_event(nua_i_state, 0); fail_unless(i_state != NULL); fail_if(is_answer_recv(i_state->data->e_tags)); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); } static nua_handle_t * invite_to_nua(tag_type_t tag, tag_value_t value, ...) { ta_list ta; struct event *invite; struct message *response; nua_handle_t *nh; soa_generate_offer(soa, 1, NULL); ta_start(ta, tag, value); request_with_sdp(dialog, SIP_METHOD_INVITE, NULL, ta_tags(ta)); ta_end(ta); invite = s2_wait_for_event(nua_i_invite, 100); fail_unless(invite != NULL); fail_unless(s2_check_callstate(nua_callstate_received)); nh = invite->nh; fail_if(!nh); s2_free_event(invite); if (s2_nua_auto100) { response = s2_sip_wait_for_response(100, SIP_METHOD_INVITE); fail_if(!response); } nua_respond(nh, SIP_180_RINGING, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), TAG_END()); fail_unless(s2_check_callstate(nua_callstate_early)); response = s2_sip_wait_for_response(180, SIP_METHOD_INVITE); fail_if(!response); s2_sip_update_dialog(dialog, response); process_answer(response); s2_sip_free_message(response); nua_respond(nh, SIP_200_OK, TAG_END()); fail_unless(s2_check_callstate(nua_callstate_completed)); response = s2_sip_wait_for_response(200, SIP_METHOD_INVITE); fail_if(!response); s2_sip_update_dialog(dialog, response); s2_sip_free_message(response); fail_if(s2_sip_request_to(dialog, SIP_METHOD_ACK, NULL, TAG_END())); fail_unless_event(nua_i_ack, 200); fail_unless(s2_check_callstate(nua_callstate_ready)); return nh; } static void bye_by_nua(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { ta_list ta; struct message *bye; ta_start(ta, tag, value); nua_bye(nh, ta_tags(ta)); ta_end(ta); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_sip_respond_to(bye, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(bye); fail_unless_event(nua_r_bye, 200); fail_unless(s2_check_callstate(nua_callstate_terminated)); } static void bye_by_nua_challenged(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { ta_list ta; struct message *bye; s2_flush_events(); ta_start(ta, tag, value); nua_bye(nh, ta_tags(ta)); ta_end(ta); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_sip_respond_to(bye, dialog, SIP_407_PROXY_AUTH_REQUIRED, SIPTAG_PROXY_AUTHENTICATE_STR(s2_auth_digest_str), TAG_END()); s2_sip_free_message(bye); fail_unless_event(nua_r_bye, 407); nua_authenticate(nh, NUTAG_AUTH("Digest:\"s2test\":abc:abc"), TAG_END()); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_sip_respond_to(bye, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(bye); fail_unless_event(nua_r_bye, 200); fail_unless(s2_check_callstate(nua_callstate_terminated)); fail_if(s2->events); } static void cancel_by_nua(nua_handle_t *nh, struct message *invite, struct dialog *dialog, tag_type_t tag, tag_value_t value, ...) { ta_list ta; struct message *cancel; ta_start(ta, tag, value); nua_cancel(nh, ta_tags(ta)); ta_end(ta); cancel = s2_sip_wait_for_request(SIP_METHOD_CANCEL); fail_if(!cancel); s2_sip_respond_to(cancel, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(cancel); fail_unless_event(nua_r_cancel, 200); s2_sip_respond_to(invite, dialog, SIP_487_REQUEST_CANCELLED, TAG_END()); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); fail_unless_event(nua_r_invite, 487); } static void bye_to_nua(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { ta_list ta; ta_start(ta, tag, value); fail_if(s2_sip_request_to(dialog, SIP_METHOD_BYE, NULL, ta_tags(ta))); ta_end(ta); fail_unless_event(nua_i_bye, 200); fail_unless(s2_check_callstate(nua_callstate_terminated)); fail_unless(s2_sip_check_response(200, SIP_METHOD_BYE)); } /* ====================================================================== */ /* 2 - Call cases */ /* 2.1 - Basic call cases */ START_TEST(call_2_1_1) { nua_handle_t *nh; S2_CASE("2.1.1", "Basic call", "NUA sends INVITE, NUA sends BYE"); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite_by_nua(nh, TAG_END()); bye_by_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST START_TEST(call_2_1_2_1) { nua_handle_t *nh; S2_CASE("2.1.2.1", "Basic call", "NUA sends INVITE, NUA receives BYE"); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite_by_nua(nh, TAG_END()); bye_to_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST START_TEST(call_2_1_2_2) { nua_handle_t *nh; S2_CASE("2.1.2.2", "Basic call over TCP", "NUA sends INVITE, NUA receives BYE"); s2_nua_auto100 = 0; nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite_by_nua(nh, NUTAG_PROXY(s2sip->tcp.contact->m_url), TAG_END()); bye_to_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST START_TEST(call_2_1_2_3) { nua_handle_t *nh; struct message *invite; struct event *i_state; S2_CASE("2.1.1", "Outgoing call with two answers", "NUA sends INVITE, receives 180 and 200 with different SDP"); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite = invite_sent_by_nua( nh, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 4 3" CRLF "m=video 5006 RTP/AVP 31" CRLF), TAG_END()); process_offer(invite); respond_with_sdp( invite, dialog, SIP_180_RINGING, SIPTAG_CONTENT_DISPOSITION_STR("session;handling=optional"), TAG_END()); fail_unless_event(nua_r_invite, 180); i_state = s2_wait_for_event(nua_i_state, 0); fail_unless(i_state != NULL); fail_unless(s2_event_callstate(i_state) == nua_callstate_proceeding); fail_if(!is_answer_recv(i_state->data->e_tags)); s2_free_event(i_state); dialog2 = dialog, dialog = NULL; soa2 = soa, soa = NULL; endpoint_setup(); soa_set_params(soa, SOATAG_USER_SDP_STR("m=audio 5008 RTP/AVP 4" CRLF "m=video 5010 RTP/AVP 31" CRLF), TAG_END()); /* Now from another endpoint */ process_offer(invite); respond_with_sdp( invite, dialog, SIP_180_RINGING, SIPTAG_CONTENT_DISPOSITION_STR("session;handling=optional"), TAG_END()); fail_unless_event(nua_r_invite, 180); i_state = s2_wait_for_event(nua_i_state, 0); fail_unless(i_state != NULL); fail_unless(s2_event_callstate(i_state) == nua_callstate_proceeding); fail_if(is_answer_recv(i_state->data->e_tags)); s2_free_event(i_state); respond_with_sdp(invite, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(invite); fail_unless_event(nua_r_invite, 200); i_state = s2_wait_for_event(nua_i_state, 0); fail_unless(i_state != NULL); fail_if(!is_answer_recv(i_state->data->e_tags)); s2_free_event(i_state); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); bye_by_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST START_TEST(call_2_1_3_1) { nua_handle_t *nh; S2_CASE("2.1.3.1", "Incoming call", "NUA receives INVITE and BYE"); nh = invite_to_nua(TAG_END()); bye_to_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST START_TEST(call_2_1_3_2) { nua_handle_t *nh; S2_CASE("2.1.3.2", "Incoming call over TCP", "NUA receives INVITE and BYE"); dialog->tport = s2sip->tcp.tport; nh = invite_to_nua(TAG_END()); bye_to_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST START_TEST(call_2_1_4) { nua_handle_t *nh; S2_CASE("2.1.4", "Incoming call", "NUA receives INVITE and sends BYE"); nh = invite_to_nua(TAG_END()); bye_by_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST START_TEST(call_2_1_5) { nua_handle_t *nh; S2_CASE("2.1.5", "Incoming call", "NUA receives INVITE and sends BYE, BYE is challenged"); nh = invite_to_nua(TAG_END()); bye_by_nua_challenged(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST START_TEST(call_2_1_6) { nua_handle_t *nh; struct message *bye; struct event *invite; struct message *response; S2_CASE("2.1.6", "Basic call", "NUA received INVITE, " "NUA responds (and saves proxy for dialog), " "NUA sends BYE"); soa_generate_offer(soa, 1, NULL); request_with_sdp(dialog, SIP_METHOD_INVITE, NULL, TAG_END()); invite = s2_wait_for_event(nua_i_invite, 100); fail_unless(invite != NULL); fail_unless(s2_check_callstate(nua_callstate_received)); nh = invite->nh; fail_if(!nh); s2_free_event(invite); response = s2_sip_wait_for_response(100, SIP_METHOD_INVITE); fail_if(!response); nua_respond(nh, SIP_180_RINGING, /* Dialog-specific proxy is saved */ NUTAG_PROXY(s2sip->tcp.contact->m_url), SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), TAG_END()); fail_unless(s2_check_callstate(nua_callstate_early)); response = s2_sip_wait_for_response(180, SIP_METHOD_INVITE); fail_if(!response); s2_sip_update_dialog(dialog, response); process_answer(response); s2_sip_free_message(response); nua_respond(nh, SIP_200_OK, TAG_END()); fail_unless(s2_check_callstate(nua_callstate_completed)); response = s2_sip_wait_for_response(200, SIP_METHOD_INVITE); fail_if(!response); s2_sip_update_dialog(dialog, response); s2_sip_free_message(response); fail_if(s2_sip_request_to(dialog, SIP_METHOD_ACK, NULL, TAG_END())); fail_unless_event(nua_i_ack, 200); fail_unless(s2_check_callstate(nua_callstate_ready)); nua_bye(nh, TAG_END()); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); /* Check that NUA used dialog-specific proxy with BYE */ fail_unless(tport_is_tcp(bye->tport)); s2_sip_respond_to(bye, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(bye); fail_unless_event(nua_r_bye, 200); fail_unless(s2_check_callstate(nua_callstate_terminated)); nua_handle_destroy(nh); } END_TEST START_TEST(call_2_1_7) { nua_handle_t *nh, *nh2; sip_replaces_t *replaces; S2_CASE("2.1.7", "Call lookup", "Test dialog and call-id lookup"); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite_by_nua(nh, TAG_END()); nh2 = nua_handle_by_call_id(nua, dialog->call_id->i_id); fail_if(!nh2); fail_if(nh != nh2); nua_handle_unref(nh2); replaces = sip_replaces_format(NULL, "%s;from-tag=%s;to-tag=%s", dialog->call_id->i_id, dialog->local->a_tag, dialog->remote->a_tag); fail_if(!replaces); nh2 = nua_handle_by_replaces(nua, replaces); fail_if(!nh2); fail_if(nh != nh2); nua_handle_unref(nh2); msg_header_free_all(NULL, (msg_header_t *)replaces); bye_by_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST START_TEST(call_2_1_8) { nua_handle_t *nh; struct message *invite, *ack; S2_CASE("2.1.8", "Call using NUTAG_PROXY()", "Test handle-specific NUTAG_PROXY()."); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite = invite_sent_by_nua( nh, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), NUTAG_PROXY(s2sip->tcp.contact->m_url), TAG_END()); process_offer(invite); respond_with_sdp( invite, dialog, SIP_180_RINGING, SIPTAG_CONTENT_DISPOSITION_STR("session;handling=optional"), TAG_END()); fail_unless_event(nua_r_invite, 180); fail_unless(s2_check_callstate(nua_callstate_proceeding)); respond_with_sdp(invite, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(invite); fail_unless_event(nua_r_invite, 200); fail_unless(s2_check_callstate(nua_callstate_ready)); ack = s2_sip_wait_for_request(SIP_METHOD_ACK); fail_unless(ack && tport_is_tcp(ack->tport)); bye_by_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST START_TEST(call_2_1_9_1) { nua_handle_t *nh; S2_CASE("2.1.9.1", "Incoming call", "NUA receives INVITE with multipart and BYE"); fake_multipart = 1; nh = invite_to_nua(TAG_END()); bye_to_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST START_TEST(call_2_1_9_2) { nua_handle_t *nh; S2_CASE("2.1.9.2", "Outgoing call", "NUA receives response to INVITE with multipart"); fake_multipart = 1; nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite_by_nua(nh, TAG_END()); bye_to_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST TCase *invite_tcase(int threading) { TCase *tc = tcase_create("2.1 - Basic INVITE"); add_call_fixtures(tc, threading); { tcase_add_test(tc, call_2_1_1); tcase_add_test(tc, call_2_1_2_1); tcase_add_test(tc, call_2_1_2_2); tcase_add_test(tc, call_2_1_2_3); tcase_add_test(tc, call_2_1_3_1); tcase_add_test(tc, call_2_1_3_2); tcase_add_test(tc, call_2_1_4); tcase_add_test(tc, call_2_1_5); tcase_add_test(tc, call_2_1_6); tcase_add_test(tc, call_2_1_7); tcase_add_test(tc, call_2_1_8); tcase_add_test(tc, call_2_1_9_1); tcase_add_test(tc, call_2_1_9_2); } return tc; } /* ---------------------------------------------------------------------- */ /* 2.2 - Call CANCEL cases */ START_TEST(cancel_2_2_1) { nua_handle_t *nh; struct message *invite, *cancel; S2_CASE("2.2.1", "Cancel call", "NUA is caller, NUA sends CANCEL immediately"); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); nua_invite(nh, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), TAG_END()); fail_unless(s2_check_callstate(nua_callstate_calling)); nua_cancel(nh, TAG_END()); invite = s2_sip_wait_for_request(SIP_METHOD_INVITE); fail_if(!invite); fail_if(s2sip->received != NULL); s2_sip_respond_to(invite, dialog, SIP_100_TRYING, TAG_END()); cancel = s2_sip_wait_for_request(SIP_METHOD_CANCEL); fail_if(!cancel); s2_sip_respond_to(invite, dialog, SIP_487_REQUEST_CANCELLED, TAG_END()); s2_sip_respond_to(cancel, dialog, SIP_200_OK, TAG_END()); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); fail_unless_event(nua_r_invite, 487); fail_unless(s2_check_callstate(nua_callstate_terminated)); fail_unless_event(nua_r_cancel, 200); fail_if(s2->events != NULL); nua_handle_destroy(nh); } END_TEST START_TEST(cancel_2_2_2) { nua_handle_t *nh; struct message *invite; S2_CASE("2.2.2", "Canceled call", "NUA is caller, NUA sends CANCEL after receiving 100"); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); nua_invite(nh, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), TAG_END()); fail_unless(s2_check_callstate(nua_callstate_calling)); invite = s2_sip_wait_for_request(SIP_METHOD_INVITE); process_offer(invite); s2_sip_respond_to(invite, dialog, SIP_100_TRYING, TAG_END()); cancel_by_nua(nh, invite, dialog, TAG_END()); fail_unless(s2_check_callstate(nua_callstate_terminated)); nua_handle_destroy(nh); } END_TEST START_TEST(cancel_2_2_3) { nua_handle_t *nh; struct message *invite; S2_CASE("2.2.3", "Canceled call", "NUA is caller, NUA sends CANCEL after receiving 180"); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); nua_invite(nh, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), TAG_END()); fail_unless(s2_check_callstate(nua_callstate_calling)); invite = s2_sip_wait_for_request(SIP_METHOD_INVITE); process_offer(invite); respond_with_sdp( invite, dialog, SIP_180_RINGING, SIPTAG_CONTENT_DISPOSITION_STR("session;handling=optional"), TAG_END()); fail_unless_event(nua_r_invite, 180); fail_unless(s2_check_callstate(nua_callstate_proceeding)); cancel_by_nua(nh, invite, dialog, TAG_END()); fail_unless(s2_check_callstate(nua_callstate_terminated)); nua_handle_destroy(nh); } END_TEST START_TEST(cancel_2_2_4) { nua_handle_t *nh; struct message *invite, *cancel; S2_CASE("2.2.4", "Cancel and 200 OK glare", "NUA is caller, NUA sends CANCEL after receiving 180 " "but UAS already sent 200 OK."); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); nua_invite(nh, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), TAG_END()); fail_unless(s2_check_callstate(nua_callstate_calling)); invite = s2_sip_wait_for_request(SIP_METHOD_INVITE); process_offer(invite); respond_with_sdp( invite, dialog, SIP_180_RINGING, SIPTAG_CONTENT_DISPOSITION_STR("session;handling=optional"), TAG_END()); fail_unless_event(nua_r_invite, 180); fail_unless(s2_check_callstate(nua_callstate_proceeding)); nua_cancel(nh, TAG_END()); cancel = s2_sip_wait_for_request(SIP_METHOD_CANCEL); fail_if(!cancel); respond_with_sdp(invite, dialog, SIP_200_OK, TAG_END()); s2_sip_respond_to(cancel, dialog, SIP_481_NO_TRANSACTION, TAG_END()); s2_sip_free_message(cancel); fail_unless_event(nua_r_cancel, 481); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); fail_unless(s2_check_callstate(nua_callstate_ready)); bye_by_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST START_TEST(cancel_2_2_5) { nua_handle_t *nh; struct message *invite, *cancel, *bye; S2_CASE( "2.2.5", "Cancel and 200 OK glare", "NUA is caller, " "NUA uses nua_bye() to send CANCEL after receiving 180\n" "but UAS already sent 200 OK.\n" "Test case checks that NUA really sends BYE after nua_bye() is called\n"); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); nua_invite(nh, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), NUTAG_AUTOACK(0), TAG_END()); fail_unless(s2_check_callstate(nua_callstate_calling)); invite = s2_sip_wait_for_request(SIP_METHOD_INVITE); process_offer(invite); respond_with_sdp( invite, dialog, SIP_180_RINGING, SIPTAG_CONTENT_DISPOSITION_STR("session;handling=optional"), TAG_END()); fail_unless_event(nua_r_invite, 180); fail_unless(s2_check_callstate(nua_callstate_proceeding)); nua_bye(nh, TAG_END()); cancel = s2_sip_wait_for_request(SIP_METHOD_CANCEL); fail_if(!cancel); respond_with_sdp(invite, dialog, SIP_200_OK, TAG_END()); s2_sip_respond_to(cancel, dialog, SIP_481_NO_TRANSACTION, TAG_END()); s2_sip_free_message(cancel); fail_unless_event(nua_r_cancel, 481); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); fail_unless(s2_check_callstate(nua_callstate_terminating)); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_sip_respond_to(bye, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(bye); fail_unless_event(nua_r_bye, 200); fail_unless(s2_check_callstate(nua_callstate_terminated)); nua_handle_destroy(nh); } END_TEST START_TEST(cancel_2_2_6) { nua_handle_t *nh; struct event *invite; struct message *response; S2_CASE("2.2.6", "Cancel call", "NUA is callee, sends 100, 180, INVITE gets canceled"); soa_generate_offer(soa, 1, NULL); request_with_sdp(dialog, SIP_METHOD_INVITE, NULL, TAG_END()); invite = s2_wait_for_event(nua_i_invite, 100); fail_unless(invite != NULL); fail_unless(s2_check_callstate(nua_callstate_received)); nh = invite->nh; fail_if(!nh); s2_free_event(invite); response = s2_sip_wait_for_response(100, SIP_METHOD_INVITE); fail_if(!response); nua_respond(nh, SIP_180_RINGING, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), TAG_END()); fail_unless(s2_check_callstate(nua_callstate_early)); response = s2_sip_wait_for_response(180, SIP_METHOD_INVITE); fail_if(!response); s2_sip_update_dialog(dialog, response); process_answer(response); s2_sip_free_message(response); fail_if(s2_sip_request_to(dialog, SIP_METHOD_CANCEL, NULL, TAG_END())); fail_unless_event(nua_i_cancel, 200); fail_unless(s2_check_callstate(nua_callstate_terminated)); response = s2_sip_wait_for_response(200, SIP_METHOD_CANCEL); fail_if(!response); s2_sip_free_message(response); response = s2_sip_wait_for_response(487, SIP_METHOD_INVITE); fail_if(s2_sip_request_to(dialog, SIP_METHOD_ACK, NULL, SIPTAG_VIA(sip_object(dialog->invite)->sip_via), TAG_END())); nua_handle_destroy(nh); } END_TEST START_TEST(cancel_2_2_7) { nua_handle_t *nh; struct event *invite; struct message *response; char const *via = "SIP/2.0/UDP host.in.invalid;rport"; S2_CASE("2.2.7", "Call gets canceled", "NUA is callee, sends 100, 180, INVITE gets canceled. " "Using RFC 2543 dialog and transaction matching."); soa_generate_offer(soa, 1, NULL); request_with_sdp(dialog, SIP_METHOD_INVITE, NULL, SIPTAG_VIA_STR(via), TAG_END()); invite = s2_wait_for_event(nua_i_invite, 100); fail_unless(invite != NULL); fail_unless(s2_check_callstate(nua_callstate_received)); nh = invite->nh; fail_if(!nh); s2_free_event(invite); response = s2_sip_wait_for_response(100, SIP_METHOD_INVITE); fail_if(!response); nua_respond(nh, SIP_180_RINGING, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), TAG_END()); fail_unless(s2_check_callstate(nua_callstate_early)); response = s2_sip_wait_for_response(180, SIP_METHOD_INVITE); fail_if(!response); s2_sip_update_dialog(dialog, response); process_answer(response); s2_sip_free_message(response); fail_if(s2_sip_request_to(dialog, SIP_METHOD_CANCEL, NULL, TAG_END())); fail_unless_event(nua_i_cancel, 200); fail_unless(s2_check_callstate(nua_callstate_terminated)); response = s2_sip_wait_for_response(200, SIP_METHOD_CANCEL); fail_if(!response); s2_sip_free_message(response); response = s2_sip_wait_for_response(487, SIP_METHOD_INVITE); fail_if(s2_sip_request_to(dialog, SIP_METHOD_ACK, NULL, SIPTAG_VIA(sip_object(dialog->invite)->sip_via), TAG_END())); nua_handle_destroy(nh); } END_TEST START_TEST(cancel_2_2_8) { nua_handle_t *nh; struct message *invite, *cancel; int timeout; S2_CASE("2.2.8", "CANCEL and INVITE times out", "NUA is caller, NUA sends CANCEL after receiving 180 " "but UAS never responds."); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); nua_invite(nh, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), TAG_END()); fail_unless(s2_check_callstate(nua_callstate_calling)); invite = s2_sip_wait_for_request(SIP_METHOD_INVITE); process_offer(invite); respond_with_sdp( invite, dialog, SIP_180_RINGING, SIPTAG_CONTENT_DISPOSITION_STR("session;handling=optional"), TAG_END()); fail_unless_event(nua_r_invite, 180); fail_unless(s2_check_callstate(nua_callstate_proceeding)); nua_cancel(nh, TAG_END()); cancel = s2_sip_wait_for_request(SIP_METHOD_CANCEL); s2_sip_free_message(cancel); fail_if(!cancel); /* Now, time out both CANCEL and INVITE */ for (timeout = 0; timeout < 34; timeout++) { s2_nua_fast_forward(1, s2base->root); cancel = s2_sip_next_request(SIP_METHOD_CANCEL); if (cancel) s2_sip_free_message(cancel); } fail_unless_event(nua_r_cancel, 408); fail_unless_event(nua_r_invite, 408); fail_unless(s2_check_callstate(nua_callstate_terminated)); nua_handle_destroy(nh); } END_TEST START_TEST(cancel_2_2_9) { nua_handle_t *nh; struct message *invite, *cancel; int timeout; S2_CASE("2.2.9", "CANCEL a RFC2543 UA", "NUA is caller, NUA sends CANCEL after receiving 180, " "UAS sends 200 OK to CANCEL but no response to INVITE."); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); nua_invite(nh, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), TAG_END()); fail_unless(s2_check_callstate(nua_callstate_calling)); invite = s2_sip_wait_for_request(SIP_METHOD_INVITE); process_offer(invite); respond_with_sdp( invite, dialog, SIP_180_RINGING, SIPTAG_CONTENT_DISPOSITION_STR("session;handling=optional"), TAG_END()); fail_unless_event(nua_r_invite, 180); fail_unless(s2_check_callstate(nua_callstate_proceeding)); nua_cancel(nh, TAG_END()); cancel = s2_sip_wait_for_request(SIP_METHOD_CANCEL); fail_if(!cancel); s2_sip_respond_to(cancel, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(cancel); /* Time out INVITE */ for (timeout = 0; timeout < 34; timeout++) { s2_nua_fast_forward(1, s2base->root); } fail_unless_event(nua_r_invite, 408); fail_unless(s2_check_callstate(nua_callstate_terminated)); nua_handle_destroy(nh); } END_TEST START_TEST(cancel_2_2_10) { nua_handle_t *nh; struct message *invite, *cancel; struct event *event; int timeout; S2_CASE("2.2.10", "CANCEL and INVITE times out", "NUA is caller, NUA sends CANCEL after receiving 180 " "but UAS never responds."); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); nua_invite(nh, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), TAG_END()); fail_unless(s2_check_callstate(nua_callstate_calling)); invite = s2_sip_wait_for_request(SIP_METHOD_INVITE); process_offer(invite); respond_with_sdp( invite, dialog, SIP_180_RINGING, SIPTAG_CONTENT_DISPOSITION_STR("session;handling=optional"), TAG_END()); fail_unless_event(nua_r_invite, 180); fail_unless(s2_check_callstate(nua_callstate_proceeding)); nua_cancel(nh, TAG_END()); cancel = s2_sip_wait_for_request(SIP_METHOD_CANCEL); s2_sip_free_message(cancel); fail_if(!cancel); nua_cancel(nh, TAG_END()); cancel = s2_sip_wait_for_request(SIP_METHOD_CANCEL); fail_if(!cancel); s2_sip_respond_to(cancel, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(cancel); /* emulate network gone bad below zap registration handle here so that s2_register_teardown() does not hang */ s2->registration->nh = NULL; nua_set_params(s2->nua, NUTAG_SHUTDOWN_EVENTS(1), TAG_END()); fail_unless_event(nua_r_set_params, 200); nua_shutdown(s2->nua); event = s2_wait_for_event(nua_r_shutdown, 100); fail_unless(event != NULL); s2_free_event(event); /* Time out */ for (timeout = 0; timeout < 34; timeout++) { s2_nua_fast_forward(5, s2base->root); nua_shutdown(s2->nua); event = s2_wait_for_event(nua_r_shutdown, 0); fail_unless(event != NULL); if (event->data->e_status >= 200) break; } s2->shutdown = 200; } END_TEST TCase *cancel_tcase(int threading) { TCase *tc = tcase_create("2.2 - CANCEL"); add_call_fixtures(tc, threading); tcase_add_test(tc, cancel_2_2_1); tcase_add_test(tc, cancel_2_2_2); tcase_add_test(tc, cancel_2_2_3); tcase_add_test(tc, cancel_2_2_4); if (XXX) tcase_add_test(tc, cancel_2_2_5); tcase_add_test(tc, cancel_2_2_6); tcase_add_test(tc, cancel_2_2_7); tcase_add_test(tc, cancel_2_2_8); tcase_add_test(tc, cancel_2_2_9); tcase_add_test(tc, cancel_2_2_10); return tc; } /* ---------------------------------------------------------------------- */ /* 2.3 - Session timers */ /* Wait for invite from NUA */ static struct message * invite_timer_round(nua_handle_t *nh, char const *session_expires, sip_record_route_t *rr) { struct message *invite, *ack; fail_unless(s2_check_callstate(nua_callstate_calling)); invite = s2_sip_wait_for_request(SIP_METHOD_INVITE); process_offer(invite); /* Check that INVITE contains Session-Expires header with refresher=uac */ fail_unless(invite->sip->sip_session_expires != NULL); fail_unless(su_casematch(invite->sip->sip_session_expires->x_refresher, "uac")); respond_with_sdp( invite, dialog, SIP_200_OK, SIPTAG_SESSION_EXPIRES_STR(session_expires), SIPTAG_REQUIRE_STR("timer"), SIPTAG_RECORD_ROUTE(rr), TAG_END()); s2_sip_free_message(invite); fail_unless_event(nua_r_invite, 200); fail_unless(s2_check_callstate(nua_callstate_ready)); ack = s2_sip_wait_for_request(SIP_METHOD_ACK); if (rr == NULL) s2_sip_free_message(ack); return ack; } START_TEST(call_2_3_1) { nua_handle_t *nh; sip_record_route_t rr[1]; struct message *ack; sip_record_route_init(rr); *rr->r_url = *s2sip->contact->m_url; rr->r_url->url_user = "record"; rr->r_url->url_params = "lr"; S2_CASE("2.3.1", "Incoming call with call timers", "NUA receives INVITE, " "activates call timers, " "sends re-INVITE twice, " "sends BYE."); nh = invite_to_nua( SIPTAG_SESSION_EXPIRES_STR("300;refresher=uas"), SIPTAG_REQUIRE_STR("timer"), TAG_END()); s2_nua_fast_forward(300, s2base->root); ack = invite_timer_round(nh, "300;refresher=uac", rr); fail_if(ack->sip->sip_route && su_strmatch(ack->sip->sip_route->r_url->url_user, "record")); s2_nua_fast_forward(300, s2base->root); invite_timer_round(nh, "300;refresher=uac", NULL); bye_by_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST START_TEST(call_2_3_2) { nua_handle_t *nh; S2_CASE("2.3.2", "Incoming call with call timers", "NUA receives INVITE, " "activates call timers, " "sends re-INVITE, " "sends BYE."); nh = invite_to_nua( SIPTAG_SESSION_EXPIRES_STR("300;refresher=uas"), SIPTAG_REQUIRE_STR("timer"), TAG_END()); s2_nua_fast_forward(300, s2base->root); invite_timer_round(nh, "300;refresher=uac", NULL); s2_nua_fast_forward(300, s2base->root); invite_timer_round(nh, "300;refresher=uac", NULL); bye_by_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST TCase *session_timer_tcase(int threading) { TCase *tc = tcase_create("2.3 - Session timers"); add_call_fixtures(tc, threading); { tcase_add_test(tc, call_2_3_1); tcase_add_test(tc, call_2_3_2); } return tc; } /* ====================================================================== */ /* 2.4 - 100rel */ START_TEST(call_2_4_1) { nua_handle_t *nh; struct message *invite, *prack, *ack; int with_sdp; sip_record_route_t rr[1]; S2_CASE("2.4.1", "Call with 100rel", "NUA sends INVITE, " "receives 183, sends PRACK, receives 200 for it, " "receives 180, sends PRACK, receives 200 for it, " "receives 200, send ACK."); sip_record_route_init(rr); *rr->r_url = *s2sip->contact->m_url; rr->r_url->url_user = "record"; rr->r_url->url_params = "lr"; nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite = invite_sent_by_nua( nh, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), TAG_END()); process_offer(invite); prack = respond_with_100rel(invite, dialog, with_sdp = 1, SIP_183_SESSION_PROGRESS, SIPTAG_RECORD_ROUTE(rr), TAG_END()); s2_sip_respond_to(prack, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(prack), prack = NULL; fail_unless(s2_check_callstate(nua_callstate_proceeding)); fail_unless_event(nua_r_prack, 200); prack = respond_with_100rel(invite, dialog, with_sdp = 0, SIP_180_RINGING, TAG_END()); fail_unless(prack->sip->sip_route != NULL); fail_unless(su_strmatch(prack->sip->sip_route->r_url->url_user, "record")); s2_sip_respond_to(prack, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(prack), prack = NULL; fail_unless(s2_check_callstate(nua_callstate_proceeding)); fail_unless_event(nua_r_prack, 200); /* Change the record-route */ rr->r_url->url_user = "record2"; s2_sip_respond_to(invite, dialog, SIP_200_OK, SIPTAG_RECORD_ROUTE(rr), TAG_END()); s2_sip_free_message(invite); fail_unless_event(nua_r_invite, 200); fail_unless(s2_check_callstate(nua_callstate_ready)); ack = s2_sip_wait_for_request(SIP_METHOD_ACK); fail_if(!ack); fail_unless(su_strmatch(ack->sip->sip_route->r_url->url_user, "record2")); s2_sip_free_message(ack); bye_to_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST START_TEST(call_2_4_2) { nua_handle_t *nh; struct message *invite, *prack; int with_sdp; S2_CASE("2.4.2", "Call with 100rel", "NUA sends INVITE, " "receives 183, sends PRACK, receives 200 for it, " "receives 180, sends PRACK, receives 200 for it, " "receives 200, send ACK."); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite = invite_sent_by_nua( nh, NUTAG_MEDIA_ENABLE(0), SIPTAG_CONTENT_TYPE_STR("application/sdp"), SIPTAG_PAYLOAD_STR( "v=0" CRLF "o=- 6805647540234172778 5821668777690722690 IN IP4 127.0.0.1" CRLF "s=-" CRLF "c=IN IP4 127.0.0.1" CRLF "m=audio 5004 RTP/AVP 0 8" CRLF), TAG_END()); prack = respond_with_100rel(invite, dialog, with_sdp = 0, SIP_183_SESSION_PROGRESS, TAG_END()); s2_sip_respond_to(prack, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(prack), prack = NULL; fail_unless(s2_check_callstate(nua_callstate_proceeding)); fail_unless_event(nua_r_prack, 200); prack = respond_with_100rel(invite, dialog, with_sdp = 0, SIP_180_RINGING, TAG_END()); s2_sip_respond_to(prack, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(prack), prack = NULL; fail_unless(s2_check_callstate(nua_callstate_proceeding)); fail_unless_event(nua_r_prack, 200); s2_sip_respond_to(invite, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(invite); fail_unless_event(nua_r_invite, 200); fail_unless(s2_check_callstate(nua_callstate_ready)); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); bye_to_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST START_TEST(call_2_4_3) { struct message *response; S2_CASE("2.4.3", "Call without 100rel", "NUA receives INVITE with Required: 100rel, " "rejects it with 420"); nua_set_params(s2->nua, SIPTAG_SUPPORTED(SIP_NONE), SIPTAG_SUPPORTED_STR("timer"), TAG_END()); fail_unless_event(nua_r_set_params, 200); soa_generate_offer(soa, 1, NULL); request_with_sdp(dialog, SIP_METHOD_INVITE, NULL, SIPTAG_REQUIRE_STR("100rel"), TAG_END()); response = s2_sip_wait_for_response(420, SIP_METHOD_INVITE); fail_if(!response); fail_if(s2_sip_request_to(dialog, SIP_METHOD_ACK, NULL, TAG_END())); } END_TEST START_TEST(call_2_4_4) { nua_handle_t *nh; struct event *invite; struct message *response; S2_CASE("2.4.3", "Call without 100rel", "NUA receives INVITE with Supported: 100rel, " "proceeds normally"); nua_set_params(s2->nua, SIPTAG_SUPPORTED(SIP_NONE), SIPTAG_SUPPORTED_STR("timer"), TAG_END()); fail_unless_event(nua_r_set_params, 200); soa_generate_offer(soa, 1, NULL); request_with_sdp(dialog, SIP_METHOD_INVITE, NULL, SIPTAG_SUPPORTED_STR("100rel"), TAG_END()); invite = s2_wait_for_event(nua_i_invite, 100); fail_unless(invite != NULL); fail_unless(s2_check_callstate(nua_callstate_received)); nh = invite->nh; fail_if(!nh); s2_free_event(invite); response = s2_sip_wait_for_response(100, SIP_METHOD_INVITE); fail_if(!response); nua_respond(nh, SIP_183_SESSION_PROGRESS, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), TAG_END()); fail_unless(s2_check_callstate(nua_callstate_early)); response = s2_sip_wait_for_response(183, SIP_METHOD_INVITE); fail_if(!response); fail_if(response->sip->sip_require); s2_sip_update_dialog(dialog, response); process_answer(response); s2_sip_free_message(response); nua_respond(nh, SIP_200_OK, TAG_END()); fail_unless(s2_check_callstate(nua_callstate_completed)); response = s2_sip_wait_for_response(200, SIP_METHOD_INVITE); fail_if(!response); s2_sip_update_dialog(dialog, response); s2_sip_free_message(response); fail_if(s2_sip_request_to(dialog, SIP_METHOD_ACK, NULL, TAG_END())); fail_unless_event(nua_i_ack, 200); fail_unless(s2_check_callstate(nua_callstate_ready)); bye_to_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST START_TEST(call_2_4_5) { nua_handle_t *nh; struct message *invite, *prack, *cancel; int i; int with_sdp; sip_from_t *branch1, *branch2; /* Testcase for bug FSCORE-338 - forked transactions getting canceled and terminated properly. */ S2_CASE("2.4.5", "Destroy proceeding call with 100rel", "NUA sends INVITE, " "receives 183, sends PRACK, receives 200 for it, " "receives 180, sends PRACK, receives 200 for it, " "handle is destroyed."); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite = invite_sent_by_nua( nh, NUTAG_PROXY(s2sip->tcp.contact->m_url), NUTAG_MEDIA_ENABLE(0), NUTAG_AUTOACK(0), SIPTAG_CONTENT_TYPE_STR("application/sdp"), SIPTAG_PAYLOAD_STR( "v=0" CRLF "o=- 6805647540234172778 5821668777690722690 IN IP4 127.0.0.1" CRLF "s=-" CRLF "c=IN IP4 127.0.0.1" CRLF "m=audio 5004 RTP/AVP 0 8" CRLF), TAG_END()); prack = respond_with_100rel(invite, dialog, with_sdp = 0, SIP_183_SESSION_PROGRESS, SIPTAG_CONTACT(s2sip->tcp.contact), TAG_END()); s2_sip_respond_to(prack, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(prack), prack = NULL; fail_unless(s2_check_callstate(nua_callstate_proceeding)); fail_unless_event(nua_r_prack, 200); prack = respond_with_100rel(invite, dialog, with_sdp = 0, SIP_180_RINGING, SIPTAG_CONTACT(s2sip->tcp.contact), TAG_END()); s2_sip_respond_to(prack, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(prack), prack = NULL; fail_unless(s2_check_callstate(nua_callstate_proceeding)); fail_unless_event(nua_r_prack, 200); branch1 = dialog->local; branch2 = dialog->local = sip_from_dup(dialog->home, invite->sip->sip_to); sip_from_tag(dialog->home, dialog->local, s2_sip_generate_tag(dialog->home)); nua_handle_destroy(nh), nh = NULL; cancel = s2_sip_wait_for_request(SIP_METHOD_CANCEL); s2_sip_respond_to(cancel, dialog, SIP_200_OK, TAG_END()); for (i = 1; i < 4; i++) { s2_nua_fast_forward(1, s2base->root); } s2_sip_respond_to(invite, dialog, SIP_487_REQUEST_CANCELLED, TAG_END()); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); /* Time out requests */ for (i = 1; i < 128; i++) { s2_nua_fast_forward(1, s2base->root); } } END_TEST START_TEST(call_2_4_6) { nua_handle_t *nh; struct message *invite, *prack; int with_sdp; S2_CASE("2.4.6", "Call with 100rel and delayed offer", "NUA sends INVITE without SDP offer, " "receives 183 with SDP offer, sends PRACK with SDP answer, receives 200 for it, " "receives 180, sends PRACK, receives 200 for it, " "receives 200, send ACK."); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite = invite_sent_by_nua(nh, SOATAG_DELAYED_OFFER_ENABLE(1), SOATAG_USER_SDP_STR("m=audio 5008 RTP/AVP 8 0" CRLF "m=video 5010 RTP/AVP 34" CRLF), TAG_END()); soa_generate_offer(soa, 1, NULL); prack = respond_with_100rel(invite, dialog, with_sdp = 1, SIP_183_SESSION_PROGRESS, TAG_END()); process_answer(prack); s2_sip_respond_to(prack, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(prack), prack = NULL; fail_unless(s2_check_callstate(nua_callstate_proceeding)); fail_unless_event(nua_r_prack, 200); prack = respond_with_100rel(invite, dialog, with_sdp = 0, SIP_180_RINGING, TAG_END()); s2_sip_respond_to(prack, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(prack), prack = NULL; fail_unless(s2_check_callstate(nua_callstate_proceeding)); fail_unless_event(nua_r_prack, 200); s2_sip_respond_to(invite, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(invite); fail_unless_event(nua_r_invite, 200); fail_unless(s2_check_callstate(nua_callstate_ready)); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); bye_to_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST TCase *invite_100rel_tcase(int threading) { TCase *tc = tcase_create("2.4 - INVITE with 100rel"); add_call_fixtures(tc, threading); { tcase_add_test(tc, call_2_4_1); tcase_add_test(tc, call_2_4_2); tcase_add_test(tc, call_2_4_3); tcase_add_test(tc, call_2_4_4); tcase_add_test(tc, call_2_4_5); tcase_add_test(tc, call_2_4_6); } return tc; } /* ====================================================================== */ /* 2.5 - Call with preconditions */ START_TEST(call_2_5_1) { nua_handle_t *nh; struct message *invite, *prack, *update; int with_sdp; S2_CASE("2.5.1", "Call with preconditions", "NUA sends INVITE, " "receives 183, sends PRACK, receives 200 for it, " "sends UPDATE, receives 200 for it, " "receives 180, sends PRACK, receives 200 for it, " "receives 200, send ACK."); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite = invite_sent_by_nua( nh, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), SIPTAG_REQUIRE_STR("precondition"), TAG_END()); process_offer(invite); prack = respond_with_100rel(invite, dialog, with_sdp = 1, SIP_183_SESSION_PROGRESS, TAG_END()); fail_unless(s2_check_callstate(nua_callstate_proceeding)); process_offer(prack); respond_with_sdp( prack, dialog, SIP_200_OK, SIPTAG_REQUIRE_STR("100rel"), TAG_END()); s2_sip_free_message(prack), prack = NULL; fail_unless_event(nua_r_prack, 200); fail_unless(s2_check_callstate(nua_callstate_proceeding)); update = s2_sip_wait_for_request(SIP_METHOD_UPDATE); /* UPDATE sent by stack, stack sends event for it */ fail_unless(s2_check_callstate(nua_callstate_proceeding)); process_offer(update); respond_with_sdp( update, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(update), update = NULL; fail_unless_event(nua_r_update, 200); fail_unless(s2_check_callstate(nua_callstate_proceeding)); prack = respond_with_100rel(invite, dialog, with_sdp = 0, SIP_180_RINGING, TAG_END()); s2_sip_respond_to(prack, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(prack), prack = NULL; fail_unless(s2_check_callstate(nua_callstate_proceeding)); fail_unless_event(nua_r_prack, 200); s2_sip_respond_to(invite, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(invite); fail_unless_event(nua_r_invite, 200); fail_unless(s2_check_callstate(nua_callstate_ready)); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); bye_to_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST START_TEST(call_2_5_2) { nua_handle_t *nh; struct message *invite, *prack, *update; sip_rseq_t rs[1]; sip_rack_t rack[1]; S2_CASE("2.5.2", "Call with preconditions - send 200 w/ ongoing PRACK ", "NUA sends INVITE, " "receives 183, sends PRACK, " "receives 200 to INVITE, " "receives 200 to PRACK, " "sends ACK, " "sends UPDATE, " "receives 200 to UPDATE."); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite = invite_sent_by_nua( nh, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), SIPTAG_REQUIRE_STR("precondition"), NUTAG_APPL_METHOD("PRACK"), TAG_END()); process_offer(invite); sip_rseq_init(rs)->rs_response = ++s2_rseq; respond_with_sdp( invite, dialog, SIP_183_SESSION_PROGRESS, SIPTAG_REQUIRE_STR("100rel"), SIPTAG_RSEQ(rs), TAG_END()); fail_unless_event(nua_r_invite, 183); fail_unless(s2_check_callstate(nua_callstate_proceeding)); sip_rack_init(rack)->ra_response = s2_rseq; rack->ra_cseq = invite->sip->sip_cseq->cs_seq; rack->ra_method = invite->sip->sip_cseq->cs_method; rack->ra_method_name = invite->sip->sip_cseq->cs_method_name; nua_prack(nh, SIPTAG_RACK(rack), TAG_END()); prack = s2_sip_wait_for_request(SIP_METHOD_PRACK); process_offer(prack); s2_sip_respond_to(invite, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(invite); fail_unless_event(nua_r_invite, 200); fail_unless(s2_check_callstate(nua_callstate_completing)); respond_with_sdp( prack, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(prack), prack = NULL; fail_unless_event(nua_r_prack, 200); fail_unless(s2_check_callstate(nua_callstate_ready)); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); update = s2_sip_wait_for_request(SIP_METHOD_UPDATE); /* UPDATE sent by stack, stack sends event for it */ fail_unless(s2_check_callstate(nua_callstate_calling)); process_offer(update); respond_with_sdp( update, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(update), update = NULL; fail_unless_event(nua_r_update, 200); fail_unless(s2_check_callstate(nua_callstate_ready)); bye_to_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST START_TEST(call_2_5_3) { nua_handle_t *nh; struct message *invite, *prack, *update; sip_rseq_t rs[1]; sip_rack_t rack[1]; S2_CASE("2.5.3", "Call with preconditions - send 200 w/ ongoing UPDATE ", "NUA sends INVITE, " "receives 183, sends PRACK, receives 200 to PRACK, " "sends UPDATE, " "receives 200 to INVITE, " "receives 200 to UPDATE, " "sends ACK."); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite = invite_sent_by_nua( nh, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), SIPTAG_REQUIRE_STR("precondition"), NUTAG_APPL_METHOD("PRACK"), TAG_END()); process_offer(invite); sip_rseq_init(rs)->rs_response = ++s2_rseq; respond_with_sdp( invite, dialog, SIP_183_SESSION_PROGRESS, SIPTAG_REQUIRE_STR("100rel"), SIPTAG_RSEQ(rs), TAG_END()); fail_unless_event(nua_r_invite, 183); fail_unless(s2_check_callstate(nua_callstate_proceeding)); sip_rack_init(rack)->ra_response = s2_rseq; rack->ra_cseq = invite->sip->sip_cseq->cs_seq; rack->ra_method = invite->sip->sip_cseq->cs_method; rack->ra_method_name = invite->sip->sip_cseq->cs_method_name; nua_prack(nh, SIPTAG_RACK(rack), TAG_END()); prack = s2_sip_wait_for_request(SIP_METHOD_PRACK); process_offer(prack); respond_with_sdp( prack, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(prack), prack = NULL; fail_unless_event(nua_r_prack, 200); fail_unless(s2_check_callstate(nua_callstate_proceeding)); update = s2_sip_wait_for_request(SIP_METHOD_UPDATE); /* UPDATE sent by stack, stack sends event for it */ fail_unless(s2_check_callstate(nua_callstate_proceeding)); s2_sip_respond_to(invite, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(invite); fail_unless_event(nua_r_invite, 200); fail_unless(s2_check_callstate(nua_callstate_completing)); process_offer(update); respond_with_sdp( update, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(update), update = NULL; fail_unless_event(nua_r_update, 200); fail_unless(s2_check_callstate(nua_callstate_ready)); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); bye_to_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST TCase *invite_precondition_tcase(int threading) { TCase *tc = tcase_create("2.5 - Call with preconditions"); add_call_fixtures(tc, threading); { tcase_add_test(tc, call_2_5_1); tcase_add_test(tc, call_2_5_2); tcase_add_test(tc, call_2_5_3); } return tc; } /* ====================================================================== */ /* 2.6 - Re-INVITEs */ START_TEST(call_2_6_1) { nua_handle_t *nh; struct message *invite, *ack; int i; S2_CASE("2.6.1", "Queued re-INVITEs", "NUA receives INVITE, " "sends re-INVITE twice, " "sends BYE."); nh = invite_to_nua(TAG_END()); nua_invite(nh, TAG_END()); nua_invite(nh, TAG_END()); for (i = 0; i < 2; i++) { fail_unless(s2_check_callstate(nua_callstate_calling)); invite = s2_sip_wait_for_request(SIP_METHOD_INVITE); fail_if(!invite); process_offer(invite); respond_with_sdp(invite, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(invite); ack = s2_sip_wait_for_request(SIP_METHOD_ACK); fail_if(!ack); s2_sip_free_message(ack); fail_unless_event(nua_r_invite, 200); fail_unless(s2_check_callstate(nua_callstate_ready)); } bye_by_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST START_TEST(call_2_6_2) { nua_handle_t *nh; struct message *invite, *ack, *response; S2_CASE("2.6.2", "Re-INVITE glare", "NUA sends re-INVITE and then receives re-INVITE, " "sends BYE."); nh = invite_to_nua(TAG_END()); nua_invite(nh, TAG_END()); fail_unless(s2_check_callstate(nua_callstate_calling)); soa_generate_offer(soa, 1, NULL); request_with_sdp(dialog, SIP_METHOD_INVITE, NULL, TAG_END()); invite = s2_sip_wait_for_request(SIP_METHOD_INVITE); fail_if(!invite); s2_sip_respond_to(invite, dialog, SIP_500_INTERNAL_SERVER_ERROR, SIPTAG_RETRY_AFTER_STR("8"), TAG_END()); s2_sip_free_message(invite); ack = s2_sip_wait_for_request(SIP_METHOD_ACK); fail_if(!ack); s2_sip_free_message(ack); response = s2_sip_wait_for_response(491, SIP_METHOD_INVITE); fail_if(!response); fail_if(s2_sip_request_to(dialog, SIP_METHOD_ACK, NULL, SIPTAG_VIA(sip_object(dialog->invite)->sip_via), TAG_END())); s2_sip_free_message(response); fail_if(soa_process_reject(soa, NULL) < 0); /* We get nua_r_invite with 100 trying (and 500 in sip->sip_status) */ fail_unless_event(nua_r_invite, 100); s2_nua_fast_forward(10, s2base->root); fail_unless(s2_check_callstate(nua_callstate_calling)); invite = s2_sip_wait_for_request(SIP_METHOD_INVITE); process_offer(invite); respond_with_sdp(invite, dialog, SIP_200_OK, TAG_END()); fail_unless_event(nua_r_invite, 200); fail_unless(s2_check_callstate(nua_callstate_ready)); ack = s2_sip_wait_for_request(SIP_METHOD_ACK); fail_if(!ack); s2_sip_free_message(ack); bye_by_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST START_TEST(call_2_6_3) { nua_handle_t *nh; struct message *response; S2_CASE("2.6.3", "Handling re-INVITE without SDP gracefully", "NUA receives INVITE, " "re-INVITE without SDP (w/o NUTAG_REFRESH_WITHOUT_SDP(), " "re-INVITE without SDP (using NUTAG_REFRESH_WITHOUT_SDP(), " "sends BYE."); nh = invite_to_nua( TAG_END()); s2_sip_request_to(dialog, SIP_METHOD_INVITE, NULL, SIPTAG_USER_AGENT_STR("evil (evil) evil"), TAG_END()); nua_respond(nh, SIP_200_OK, TAG_END()); fail_unless(s2_check_callstate(nua_callstate_completed)); response = s2_sip_wait_for_response(200, SIP_METHOD_INVITE); fail_if(!response); s2_sip_update_dialog(dialog, response); fail_if(!response->sip->sip_content_type); s2_sip_free_message(response); fail_if(s2_sip_request_to(dialog, SIP_METHOD_ACK, NULL, TAG_END())); fail_unless_event(nua_i_ack, 200); fail_unless(s2_check_callstate(nua_callstate_ready)); s2_nua_fast_forward(10, s2base->root); nua_set_hparams(nh, NUTAG_REFRESH_WITHOUT_SDP(1), TAG_END()); fail_unless_event(nua_r_set_params, 200); s2_sip_request_to(dialog, SIP_METHOD_INVITE, NULL, SIPTAG_USER_AGENT_STR("evil (evil) evil"), TAG_END()); nua_respond(nh, SIP_200_OK, TAG_END()); fail_unless(s2_check_callstate(nua_callstate_completed)); response = s2_sip_wait_for_response(200, SIP_METHOD_INVITE); fail_if(!response); s2_sip_update_dialog(dialog, response); fail_if(response->sip->sip_content_type); s2_sip_free_message(response); fail_if(s2_sip_request_to(dialog, SIP_METHOD_ACK, NULL, TAG_END())); fail_unless_event(nua_i_ack, 200); fail_unless(s2_check_callstate(nua_callstate_ready)); bye_by_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST START_TEST(call_2_6_4) { nua_handle_t *nh; struct message *invite, *ack; S2_CASE("2.6.4", "re-INVITEs w/o SDP", "NUA sends re-INVITE w/o SDP, " "receives SDP w/ offer, " "sends ACK w/ answer, " "sends BYE."); /* Bug reported by Liu Yang 2009-01-11 */ nh = invite_to_nua(TAG_END()); nua_invite(nh, SIPTAG_PAYLOAD_STR(""), TAG_END()); fail_unless(s2_check_callstate(nua_callstate_calling)); invite = s2_sip_wait_for_request(SIP_METHOD_INVITE); fail_if(!invite); fail_if(invite->sip->sip_content_type); soa_generate_offer(soa, 1, NULL); respond_with_sdp(invite, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(invite); ack = s2_sip_wait_for_request(SIP_METHOD_ACK); fail_if(!ack); process_answer(ack); s2_sip_free_message(ack); fail_unless_event(nua_r_invite, 200); fail_unless(s2_check_callstate(nua_callstate_ready)); bye_by_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST START_TEST(call_2_6_5) { nua_handle_t *nh; struct event *reinvite; struct message *invite, *ack, *response; /* Test case for FreeSwitch bugs #SFSIP-135, #SFSIP-137 */ S2_CASE("2.6.5", "Re-INVITE glare and 500 Retry-After", "NUA receives re-INVITE, replies with 200, " "sends re-INVITE, gets 500, gets ACK, retrys INVITE," "sends BYE."); nh = invite_to_nua(TAG_END()); soa_generate_offer(soa, 1, NULL); request_with_sdp(dialog, SIP_METHOD_INVITE, NULL, TAG_END()); reinvite = s2_wait_for_event(nua_i_invite, 200); fail_unless(reinvite != NULL); fail_unless(s2_check_callstate(nua_callstate_completed)); response = s2_sip_wait_for_response(200, SIP_METHOD_INVITE); fail_if(!response); s2_sip_update_dialog(dialog, response); process_answer(response); s2_sip_free_message(response); nua_invite(nh, TAG_END()); fail_unless(s2_check_callstate(nua_callstate_calling)); invite = s2_sip_wait_for_request(SIP_METHOD_INVITE); fail_if(!invite); s2_sip_respond_to(invite, dialog, SIP_500_INTERNAL_SERVER_ERROR, SIPTAG_RETRY_AFTER_STR("7"), TAG_END()); s2_sip_free_message(invite); ack = s2_sip_wait_for_request(SIP_METHOD_ACK); fail_if(!ack); s2_sip_free_message(ack); /* We get nua_r_invite with 100 trying (and 500 in sip->sip_status) */ fail_unless_event(nua_r_invite, 100); fail_if(s2_sip_request_to(dialog, SIP_METHOD_ACK, NULL, TAG_END())); fail_unless_event(nua_i_ack, 200); fail_unless(s2_check_callstate(nua_callstate_ready)); s2_nua_fast_forward(10, s2base->root); fail_unless(s2_check_callstate(nua_callstate_calling)); invite = s2_sip_wait_for_request(SIP_METHOD_INVITE); process_offer(invite); respond_with_sdp(invite, dialog, SIP_200_OK, TAG_END()); fail_unless_event(nua_r_invite, 200); fail_unless(s2_check_callstate(nua_callstate_ready)); ack = s2_sip_wait_for_request(SIP_METHOD_ACK); fail_if(!ack); s2_sip_free_message(ack); bye_by_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST START_TEST(call_2_6_6) { nua_handle_t *nh; struct message *invite, *ack; S2_CASE("2.6.6", "Re-INVITE", "NUA send INVITE, " "then sends re-INVITE, " "sends BYE."); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite_by_nua(nh, TAG_END()); nua_invite(nh, TAG_END()); fail_unless(s2_check_callstate(nua_callstate_calling)); invite = s2_sip_wait_for_request(SIP_METHOD_INVITE); fail_if(!invite); process_offer(invite); respond_with_sdp(invite, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(invite); ack = s2_sip_wait_for_request(SIP_METHOD_ACK); fail_if(!ack); s2_sip_free_message(ack); fail_unless_event(nua_r_invite, 200); fail_unless(s2_check_callstate(nua_callstate_ready)); bye_by_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST TCase *reinvite_tcase(int threading) { TCase *tc = tcase_create("2.6 - re-INVITEs"); add_call_fixtures(tc, threading); { tcase_add_test(tc, call_2_6_1); tcase_add_test(tc, call_2_6_2); tcase_add_test(tc, call_2_6_3); tcase_add_test(tc, call_2_6_4); tcase_add_test(tc, call_2_6_5); tcase_add_test(tc, call_2_6_6); } return tc; } /* ====================================================================== */ /* 3.1 - Call error cases */ START_TEST(call_3_1_1) { nua_handle_t *nh; struct message *invite, *ack; S2_CASE("3.1.1", "Call failure", "Call fails with 403 response"); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); nua_invite(nh, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), TAG_END()); fail_unless(s2_check_callstate(nua_callstate_calling)); invite = s2_sip_wait_for_request(SIP_METHOD_INVITE); fail_if(!invite); s2_sip_respond_to(invite, NULL, SIP_403_FORBIDDEN, SIPTAG_TO_STR("UAS Changed "), TAG_END()); s2_sip_free_message(invite); ack = s2_sip_wait_for_request(SIP_METHOD_ACK); fail_if(!ack); fail_if(strcmp(ack->sip->sip_to->a_display, "UAS Changed")); s2_sip_free_message(ack); fail_unless_event(nua_r_invite, 403); fail_unless(s2_check_callstate(nua_callstate_terminated)); nua_handle_destroy(nh); } END_TEST START_TEST(call_3_1_2) { nua_handle_t *nh; struct message *invite; int i; S2_CASE("3.1.2", "Call fails after too many retries", "Call fails after 4 times 500 Retry-After"); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), NUTAG_RETRY_COUNT(3), TAG_END()); nua_invite(nh, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), TAG_END()); for (i = 0;; i++) { fail_unless(s2_check_callstate(nua_callstate_calling)); invite = s2_sip_wait_for_request(SIP_METHOD_INVITE); fail_if(!invite); s2_sip_respond_to(invite, NULL, SIP_500_INTERNAL_SERVER_ERROR, SIPTAG_RETRY_AFTER_STR("5"), TAG_END()); s2_sip_free_message(invite); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); if (i == 3) break; fail_unless_event(nua_r_invite, 100); s2_nua_fast_forward(5, s2base->root); } fail_unless_event(nua_r_invite, 500); fail_unless(s2_check_callstate(nua_callstate_terminated)); nua_handle_destroy(nh); } END_TEST START_TEST(call_3_2_1) { nua_handle_t *nh; struct message *invite; S2_CASE("3.2.1", "Re-INVITE failure", "Re-INVITE fails with 403 response"); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite_by_nua(nh, TAG_END()); nua_invite(nh, TAG_END()); fail_unless(s2_check_callstate(nua_callstate_calling)); invite = s2_sip_wait_for_request(SIP_METHOD_INVITE); fail_if(!invite); s2_sip_respond_to(invite, NULL, SIP_403_FORBIDDEN, TAG_END()); s2_sip_free_message(invite); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); fail_unless_event(nua_r_invite, 403); /* Return to previous state */ fail_unless(s2_check_callstate(nua_callstate_ready)); bye_by_nua(nh, TAG_END()); } END_TEST START_TEST(call_3_2_2) { nua_handle_t *nh; struct message *invite, *bye; int i; S2_CASE("3.2.2", "Re-INVITE fails after too many retries", "Call fails after 4 times 500 Retry-After"); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), NUTAG_RETRY_COUNT(3), TAG_END()); invite_by_nua(nh, TAG_END()); nua_invite(nh, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), TAG_END()); for (i = 0;; i++) { fail_unless(s2_check_callstate(nua_callstate_calling)); invite = s2_sip_wait_for_request(SIP_METHOD_INVITE); fail_if(!invite); s2_sip_respond_to(invite, NULL, SIP_500_INTERNAL_SERVER_ERROR, SIPTAG_RETRY_AFTER_STR("5"), TAG_END()); s2_sip_free_message(invite); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); if (i == 3) break; fail_unless_event(nua_r_invite, 100); s2_nua_fast_forward(5, s2base->root); } fail_unless_event(nua_r_invite, 500); /* Graceful termination */ fail_unless(s2_check_callstate(nua_callstate_terminating)); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_sip_respond_to(bye, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(bye); fail_unless_event(nua_r_bye, 200); fail_unless(s2_check_callstate(nua_callstate_terminated)); nua_handle_destroy(nh); } END_TEST START_TEST(call_3_2_3) { nua_handle_t *nh; struct message *invite; S2_CASE("3.2.3", "Re-INVITE failure", "Re-INVITE fails with 491 response"); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite_by_nua(nh, TAG_END()); nua_invite(nh, TAG_END()); fail_unless(s2_check_callstate(nua_callstate_calling)); invite = s2_sip_wait_for_request(SIP_METHOD_INVITE); fail_if(!invite); s2_sip_respond_to(invite, NULL, SIP_491_REQUEST_PENDING, TAG_END()); s2_sip_free_message(invite); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); fail_unless_event(nua_r_invite, 491); /* Return to previous state */ fail_unless(s2_check_callstate(nua_callstate_ready)); bye_by_nua(nh, TAG_END()); } END_TEST TCase *invite_error_tcase(int threading) { TCase *tc = tcase_create("3 - Call Errors"); add_call_fixtures(tc, threading); { tcase_add_test(tc, call_3_1_1); tcase_add_test(tc, call_3_1_2); tcase_add_test(tc, call_3_2_1); tcase_add_test(tc, call_3_2_2); tcase_add_test(tc, call_3_2_3); tcase_set_timeout(tc, 5); } return tc; } /* ====================================================================== */ /* Weird call termination cases */ START_TEST(bye_4_1_1) { nua_handle_t *nh; struct message *bye, *r481; S2_CASE("4.1.1", "Re-INVITE while terminating", "NUA sends BYE, " "BYE is challenged, " "and NUA is re-INVITEd at the same time."); nh = invite_to_nua(TAG_END()); s2_flush_events(); nua_bye(nh, TAG_END()); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_sip_respond_to(bye, dialog, SIP_407_PROXY_AUTH_REQUIRED, SIPTAG_PROXY_AUTHENTICATE_STR(s2_auth_digest_str), TAG_END()); s2_sip_free_message(bye); fail_unless_event(nua_r_bye, 407); soa_generate_offer(soa, 1, NULL); request_with_sdp(dialog, SIP_METHOD_INVITE, NULL, TAG_END()); do { r481 = s2_sip_wait_for_response(0, SIP_METHOD_INVITE); } while (r481->sip->sip_status->st_status < 200); s2_sip_update_dialog(dialog, r481); /* send ACK */ fail_unless(s2_check_callstate(nua_callstate_terminated)); nua_handle_destroy(nh); } END_TEST START_TEST(bye_4_1_2) { nua_handle_t *nh; struct message *bye, *r481; S2_CASE("4.1.2", "Re-INVITE while terminating", "NUA sends BYE, and gets re-INVITEd at same time"); nh = invite_to_nua(TAG_END()); s2_flush_events(); nua_bye(nh, TAG_END()); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); request_with_sdp(dialog, SIP_METHOD_INVITE, NULL, TAG_END()); do { r481 = s2_sip_wait_for_response(0, SIP_METHOD_INVITE); } while (r481->sip->sip_status->st_status < 200); s2_sip_update_dialog(dialog, r481); /* send ACK */ fail_unless(s2_check_callstate(nua_callstate_terminated)); s2_sip_respond_to(bye, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(bye); fail_unless_event(nua_r_bye, 200); nua_handle_destroy(nh); } END_TEST START_TEST(bye_4_1_3) { nua_handle_t *nh; struct message *bye; struct event *i_bye; S2_CASE("4.1.3", "BYE while terminating", "NUA sends BYE and receives BYE"); nh = invite_to_nua(TAG_END()); mark_point(); nua_set_hparams(nh, NUTAG_APPL_METHOD("BYE"), TAG_END()); fail_unless_event(nua_r_set_params, 200); s2_flush_events(); nua_bye(nh, TAG_END()); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_sip_request_to(dialog, SIP_METHOD_BYE, NULL, TAG_END()); i_bye = s2_wait_for_event(nua_i_bye, 100); fail_if(!i_bye); nua_respond(nh, 200, "OKOK", NUTAG_WITH(i_bye->data->e_msg), TAG_END()); s2_sip_respond_to(bye, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(bye); fail_unless_event(nua_r_bye, 200); fail_unless(s2_check_callstate(nua_callstate_terminated)); fail_unless(s2_sip_check_response(200, SIP_METHOD_BYE)); nua_handle_destroy(nh); } END_TEST START_TEST(bye_4_1_4) { nua_handle_t *nh; struct message *bye; struct event *i_bye; S2_CASE("4.1.4", "Send BYE after BYE has been received", "NUA receives BYE, tries to send BYE at same time"); nh = invite_to_nua(TAG_END()); mark_point(); nua_set_hparams(nh, NUTAG_APPL_METHOD("BYE"), TAG_END()); fail_unless_event(nua_r_set_params, 200); s2_flush_events(); s2_sip_request_to(dialog, SIP_METHOD_BYE, NULL, TAG_END()); i_bye = s2_wait_for_event(nua_i_bye, 100); fail_if(!i_bye); nua_bye(nh, TAG_END()); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_sip_respond_to(bye, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(bye); fail_unless_event(nua_r_bye, 200); fail_unless(s2_check_callstate(nua_callstate_terminated)); nua_respond(nh, 200, "OKOK", NUTAG_WITH(i_bye->data->e_msg), TAG_END()); fail_unless(s2_sip_check_response(200, SIP_METHOD_BYE)); nua_handle_destroy(nh); } END_TEST START_TEST(bye_4_1_5) { nua_handle_t *nh; struct message *bye; struct event *i_bye; S2_CASE("4.1.5", "Send BYE after BYE has been received", "NUA receives BYE, tries to send BYE at same time"); nh = invite_to_nua(TAG_END()); mark_point(); nua_set_hparams(nh, NUTAG_APPL_METHOD("BYE"), TAG_END()); fail_unless_event(nua_r_set_params, 200); s2_flush_events(); s2_sip_request_to(dialog, SIP_METHOD_BYE, NULL, TAG_END()); i_bye = s2_wait_for_event(nua_i_bye, 100); fail_if(!i_bye); nua_bye(nh, TAG_END()); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_sip_respond_to(bye, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(bye); fail_unless_event(nua_r_bye, 200); fail_unless(s2_check_callstate(nua_callstate_terminated)); nua_handle_destroy(nh); fail_unless(s2_sip_check_response(200, SIP_METHOD_BYE)); } END_TEST START_TEST(bye_4_1_6) { nua_handle_t *nh; struct message *bye, *r486; S2_CASE("4.1.6", "Send BYE after INVITE has been received", "NUA receives INVITE, sends BYE at same time"); nh = invite_to_nua(TAG_END()); nua_set_hparams(nh, NUTAG_AUTOANSWER(0), TAG_END()); fail_unless_event(nua_r_set_params, 200); s2_flush_events(); request_with_sdp(dialog, SIP_METHOD_INVITE, NULL, TAG_END()); fail_unless(s2_sip_check_response(100, SIP_METHOD_INVITE)); nua_bye(nh, TAG_END()); fail_unless_event(nua_i_invite, 100); fail_unless(s2_check_callstate(nua_callstate_received)); do { r486 = s2_sip_wait_for_response(0, SIP_METHOD_INVITE); } while (r486->sip->sip_status->st_status < 200); s2_sip_update_dialog(dialog, r486); /* send ACK */ fail_unless(r486->sip->sip_status->st_status == 486); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_sip_respond_to(bye, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(bye); nua_handle_destroy(nh); } END_TEST START_TEST(bye_4_1_7) { nua_handle_t *nh; struct message *bye, *r486; S2_CASE("4.1.7", "Send BYE after INVITE has been received", "NUA receives INVITE, sends BYE at same time"); nh = invite_to_nua(TAG_END()); nua_set_hparams(nh, NUTAG_AUTOANSWER(0), TAG_END()); fail_unless_event(nua_r_set_params, 200); s2_flush_events(); request_with_sdp(dialog, SIP_METHOD_INVITE, NULL, TAG_END()); fail_unless(s2_sip_check_response(100, SIP_METHOD_INVITE)); nua_bye(nh, TAG_END()); fail_unless_event(nua_i_invite, 100); fail_unless(s2_check_callstate(nua_callstate_received)); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_sip_respond_to(bye, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(bye); do { r486 = s2_sip_wait_for_response(0, SIP_METHOD_INVITE); } while (r486->sip->sip_status->st_status < 200); s2_sip_update_dialog(dialog, r486); /* send ACK */ fail_unless(r486->sip->sip_status->st_status == 486); nua_handle_destroy(nh); } END_TEST START_TEST(bye_4_1_8) { nua_handle_t *nh; struct message *bye, *r486; S2_CASE("4.1.8", "BYE followed by response to INVITE", "NUA receives INVITE, sends BYE at same time"); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite_by_nua(nh, NUTAG_AUTOANSWER(0), TAG_END()); s2_flush_events(); request_with_sdp(dialog, SIP_METHOD_INVITE, NULL, TAG_END()); fail_unless(s2_sip_check_response(100, SIP_METHOD_INVITE)); nua_bye(nh, TAG_END()); fail_unless_event(nua_i_invite, 100); fail_unless(s2_check_callstate(nua_callstate_received)); nua_respond(nh, SIP_486_BUSY_HERE, TAG_END()); do { r486 = s2_sip_wait_for_response(0, SIP_METHOD_INVITE); } while (r486->sip->sip_status->st_status < 200); s2_sip_update_dialog(dialog, r486); /* send ACK */ fail_unless(r486->sip->sip_status->st_status == 486); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_sip_respond_to(bye, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(bye); nua_handle_destroy(nh); } END_TEST START_TEST(bye_4_1_9) { nua_handle_t *nh; struct message *bye; struct event *i_bye; S2_CASE("4.1.6", "Send BYE, receive BYE, destroy", "NUA sends BYE, receives BYE and handle gets destroyed"); nh = invite_to_nua(TAG_END()); mark_point(); s2_flush_events(); nua_bye(nh, TAG_END()); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_sip_request_to(dialog, SIP_METHOD_BYE, NULL, TAG_END()); i_bye = s2_wait_for_event(nua_i_bye, 200); fail_if(!i_bye); s2_free_event(i_bye), i_bye = NULL; fail_unless(s2_check_callstate(nua_callstate_terminated)); fail_unless(s2_sip_check_response(200, SIP_METHOD_BYE)); nua_handle_destroy(nh); mark_point(); su_root_step(s2base->root, 10); su_root_step(s2base->root, 10); su_root_step(s2base->root, 10); mark_point(); s2_sip_respond_to(bye, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(bye); mark_point(); while (su_home_check_alloc((su_home_t *)nua, (void *)nh)) { su_root_step(s2base->root, 10); } } END_TEST START_TEST(bye_4_1_10) { nua_handle_t *nh; struct message *invite, *bye; struct event *i_bye; S2_CASE("4.1.6", "Send auto-BYE upon receiving 501, receive BYE, destroy", "NUA sends BYE, receives BYE and handle gets destroyed"); nh = invite_to_nua(TAG_END()); mark_point(); s2_flush_events(); nua_invite(nh, TAG_END()); invite = s2_sip_wait_for_request(SIP_METHOD_INVITE); fail_if(!invite); s2_sip_respond_to(invite, dialog, SIP_501_NOT_IMPLEMENTED, TAG_END()); s2_sip_free_message(invite); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); fail_unless(s2_check_callstate(nua_callstate_calling)); fail_unless_event(nua_r_invite, 501); fail_unless(s2_check_callstate(nua_callstate_terminating)); s2_sip_request_to(dialog, SIP_METHOD_BYE, NULL, TAG_END()); i_bye = s2_wait_for_event(nua_i_bye, 200); fail_if(!i_bye); s2_free_event(i_bye), i_bye = NULL; fail_unless(s2_check_callstate(nua_callstate_terminated)); fail_unless(s2_sip_check_response(200, SIP_METHOD_BYE)); nua_handle_destroy(nh); su_root_step(s2base->root, 10); su_root_step(s2base->root, 10); su_root_step(s2base->root, 10); s2_sip_respond_to(bye, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(bye); while (su_home_check_alloc((su_home_t *)nua, (void *)nh)) { su_root_step(s2base->root, 10); } } END_TEST START_TEST(bye_4_1_11) { nua_handle_t *nh; struct message *invite, *ack; struct event *i_bye; S2_CASE("4.1.11", "Receive BYE in completing state", "NUA sends INVITE, receives 200, receives BYE."); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite = invite_sent_by_nua(nh, NUTAG_AUTOACK(0), TAG_END()); process_offer(invite); s2_sip_respond_to(invite, dialog, SIP_180_RINGING, TAG_END()); fail_unless_event(nua_r_invite, 180); fail_unless(s2_check_callstate(nua_callstate_proceeding)); respond_with_sdp(invite, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(invite); fail_unless_event(nua_r_invite, 200); fail_unless(s2_check_callstate(nua_callstate_completing)); s2_sip_request_to(dialog, SIP_METHOD_BYE, NULL, TAG_END()); i_bye = s2_wait_for_event(nua_i_bye, 200); fail_if(!i_bye); s2_free_event(i_bye), i_bye = NULL; fail_unless(s2_check_callstate(nua_callstate_terminated)); fail_unless(s2_sip_check_response(200, SIP_METHOD_BYE)); ack = s2_sip_wait_for_request(SIP_METHOD_ACK); fail_if(!ack); s2_sip_free_message(ack); nua_handle_destroy(nh); } END_TEST START_TEST(bye_4_2_1) { nua_handle_t *nh; struct message *bye; S2_CASE("4.2.1", "BYE in progress while call timer expires", "NUA receives INVITE, " "activates call timers, " "sends BYE, BYE challenged, " "waits until session expires."); nh = invite_to_nua( SIPTAG_SESSION_EXPIRES_STR("300;refresher=uas"), SIPTAG_REQUIRE_STR("timer"), TAG_END()); s2_nua_fast_forward(300, s2base->root); invite_timer_round(nh, "300", NULL); nua_bye(nh, TAG_END()); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_sip_respond_to(bye, dialog, SIP_407_PROXY_AUTH_REQUIRED, SIPTAG_PROXY_AUTHENTICATE_STR(s2_auth_digest_str), TAG_END()); s2_sip_free_message(bye); fail_unless_event(nua_r_bye, 407); s2_nua_fast_forward(300, s2base->root); nua_authenticate(nh, NUTAG_AUTH("Digest:\"s2test\":abc:abc"), TAG_END()); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_sip_respond_to(bye, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(bye); fail_unless_event(nua_r_bye, 200); fail_unless(s2_check_callstate(nua_callstate_terminated)); fail_if(s2->events); nua_handle_destroy(nh); } END_TEST START_TEST(bye_4_2_2) { nua_handle_t *nh; struct message *bye; S2_CASE("4.2.2", "BYE in progress while call timer expires", "NUA receives INVITE, " "activates call timers, " "sends BYE, BYE challenged, " "waits until session expires."); nh = invite_to_nua( SIPTAG_SESSION_EXPIRES_STR("300;refresher=uas"), SIPTAG_REQUIRE_STR("timer"), TAG_END()); s2_nua_fast_forward(300, s2base->root); invite_timer_round(nh, "300", NULL); s2_nua_fast_forward(140, s2base->root); nua_bye(nh, TAG_END()); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_sip_respond_to(bye, dialog, SIP_407_PROXY_AUTH_REQUIRED, SIPTAG_PROXY_AUTHENTICATE_STR(s2_auth_digest_str), TAG_END()); s2_sip_free_message(bye); fail_unless_event(nua_r_bye, 407); s2_nua_fast_forward(160, s2base->root); nua_authenticate(nh, NUTAG_AUTH(s2_auth_credentials), TAG_END()); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_sip_respond_to(bye, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(bye); fail_unless_event(nua_r_bye, 200); fail_unless(s2_check_callstate(nua_callstate_terminated)); fail_if(s2->events); nua_handle_destroy(nh); } END_TEST TCase *termination_tcase(int threading) { TCase *tc = tcase_create("4 - Call Termination"); add_call_fixtures(tc, threading); { tcase_add_test(tc, bye_4_1_1); tcase_add_test(tc, bye_4_1_2); tcase_add_test(tc, bye_4_1_3); tcase_add_test(tc, bye_4_1_4); tcase_add_test(tc, bye_4_1_5); tcase_add_test(tc, bye_4_1_6); tcase_add_test(tc, bye_4_1_7); tcase_add_test(tc, bye_4_1_8); tcase_add_test(tc, bye_4_1_9); tcase_add_test(tc, bye_4_1_10); tcase_add_test(tc, bye_4_1_11); tcase_add_test(tc, bye_4_2_1); tcase_add_test(tc, bye_4_2_2); tcase_set_timeout(tc, 5); } return tc; } /* ====================================================================== */ START_TEST(destroy_4_3_1) { nua_handle_t *nh; struct message *invite, *cancel; S2_CASE("4.3.1", "Destroy handle after INVITE sent", "NUA sends INVITE, handle gets destroyed."); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite = invite_sent_by_nua(nh, TAG_END()); process_offer(invite); nua_handle_destroy(nh); s2_sip_respond_to(invite, dialog, SIP_100_TRYING, TAG_END()); cancel = s2_sip_wait_for_request(SIP_METHOD_CANCEL); fail_if(!cancel); s2_sip_respond_to(invite, dialog, SIP_487_REQUEST_CANCELLED, TAG_END()); s2_sip_free_message(invite); s2_sip_respond_to(cancel, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(cancel); } END_TEST START_TEST(destroy_4_3_2) { nua_handle_t *nh; struct message *invite, *cancel; S2_CASE("4.3.2", "Destroy handle in calling state", "NUA sends INVITE, receives 180, handle gets destroyed."); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite = invite_sent_by_nua(nh, TAG_END()); process_offer(invite); s2_sip_respond_to(invite, dialog, SIP_180_RINGING, TAG_END()); fail_unless_event(nua_r_invite, 180); fail_unless(s2_check_callstate(nua_callstate_proceeding)); nua_handle_destroy(nh); cancel = s2_sip_wait_for_request(SIP_METHOD_CANCEL); fail_if(!cancel); s2_sip_respond_to(invite, dialog, SIP_487_REQUEST_CANCELLED, TAG_END()); s2_sip_free_message(invite); s2_sip_respond_to(cancel, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(cancel); } END_TEST START_TEST(destroy_4_3_3) { nua_handle_t *nh; struct message *invite, *ack, *bye; S2_CASE("4.3.3", "Destroy handle in completing state", "NUA sends INVITE, receives 200, handle gets destroyed."); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite = invite_sent_by_nua(nh, NUTAG_AUTOACK(0), TAG_END()); process_offer(invite); s2_sip_respond_to(invite, dialog, SIP_180_RINGING, TAG_END()); fail_unless_event(nua_r_invite, 180); fail_unless(s2_check_callstate(nua_callstate_proceeding)); respond_with_sdp(invite, dialog, SIP_200_OK, TAG_END()); fail_unless_event(nua_r_invite, 200); fail_unless(s2_check_callstate(nua_callstate_completing)); nua_handle_destroy(nh); ack = s2_sip_wait_for_request(SIP_METHOD_ACK); fail_if(!ack); s2_sip_free_message(ack); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_sip_respond_to(bye, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(bye); s2_sip_free_message(invite); } END_TEST START_TEST(destroy_4_3_4) { nua_handle_t *nh; struct message *invite, *ack, *bye; S2_CASE("4.3.3", "Destroy handle in ready state ", "NUA sends INVITE, receives 200, handle gets destroyed."); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite = invite_sent_by_nua(nh, NUTAG_AUTOACK(0), TAG_END()); process_offer(invite); s2_sip_respond_to(invite, dialog, SIP_180_RINGING, TAG_END()); fail_unless_event(nua_r_invite, 180); fail_unless(s2_check_callstate(nua_callstate_proceeding)); respond_with_sdp(invite, dialog, SIP_200_OK, TAG_END()); fail_unless_event(nua_r_invite, 200); fail_unless(s2_check_callstate(nua_callstate_completing)); nua_ack(nh, TAG_END()); ack = s2_sip_wait_for_request(SIP_METHOD_ACK); fail_if(!ack); s2_sip_free_message(ack); fail_unless(s2_check_callstate(nua_callstate_ready)); nua_handle_destroy(nh); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_sip_respond_to(bye, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(bye); s2_sip_free_message(invite); } END_TEST START_TEST(destroy_4_3_5) { nua_handle_t *nh; struct message *invite, *cancel; S2_CASE("4.3.5", "Destroy handle in re-INVITE calling state", "NUA sends re-INVITE, handle gets destroyed."); nh = invite_to_nua(TAG_END()); invite = invite_sent_by_nua(nh, TAG_END()); process_offer(invite); nua_handle_destroy(nh); s2_sip_respond_to(invite, dialog, SIP_100_TRYING, TAG_END()); cancel = s2_sip_wait_for_request(SIP_METHOD_CANCEL); fail_if(!cancel); s2_sip_respond_to(invite, dialog, SIP_487_REQUEST_CANCELLED, TAG_END()); s2_sip_free_message(invite); s2_sip_respond_to(cancel, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(cancel); } END_TEST START_TEST(destroy_4_3_6) { nua_handle_t *nh; struct message *invite, *cancel; S2_CASE("4.3.6", "Destroy handle in calling state of re-INVITE", "NUA sends re-INVITE, receives 180, handle gets destroyed."); nh = invite_to_nua(TAG_END()); invite = invite_sent_by_nua(nh, TAG_END()); process_offer(invite); s2_sip_respond_to(invite, dialog, SIP_180_RINGING, TAG_END()); fail_unless_event(nua_r_invite, 180); fail_unless(s2_check_callstate(nua_callstate_proceeding)); nua_handle_destroy(nh); cancel = s2_sip_wait_for_request(SIP_METHOD_CANCEL); fail_if(!cancel); s2_sip_respond_to(invite, dialog, SIP_487_REQUEST_CANCELLED, TAG_END()); s2_sip_free_message(invite); s2_sip_respond_to(cancel, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(cancel); } END_TEST START_TEST(destroy_4_3_7) { nua_handle_t *nh; struct message *invite, *ack, *bye; S2_CASE("4.3.7", "Destroy handle in completing state of re-INVITE", "NUA sends INVITE, receives 200, handle gets destroyed."); nh = invite_to_nua(TAG_END()); invite = invite_sent_by_nua(nh, NUTAG_AUTOACK(0), TAG_END()); process_offer(invite); s2_sip_respond_to(invite, dialog, SIP_180_RINGING, TAG_END()); fail_unless_event(nua_r_invite, 180); fail_unless(s2_check_callstate(nua_callstate_proceeding)); respond_with_sdp(invite, dialog, SIP_200_OK, TAG_END()); fail_unless_event(nua_r_invite, 200); fail_unless(s2_check_callstate(nua_callstate_completing)); nua_handle_destroy(nh); ack = s2_sip_wait_for_request(SIP_METHOD_ACK); fail_if(!ack); s2_sip_free_message(ack); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_sip_respond_to(bye, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(bye); s2_sip_free_message(invite); } END_TEST START_TEST(destroy_4_3_8) { nua_handle_t *nh; struct message *invite, *ack, *bye; S2_CASE("4.3.8", "Destroy handle after INVITE sent", "NUA sends INVITE, handle gets destroyed, " "but remote end returns 200 OK. " "Make sure nua tries to release call properly."); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite = invite_sent_by_nua(nh, TAG_END()); process_offer(invite); nua_handle_destroy(nh); respond_with_sdp(invite, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(invite); ack = s2_sip_wait_for_request(SIP_METHOD_ACK); fail_if(!ack); s2_sip_free_message(ack); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_sip_respond_to(bye, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(bye); } END_TEST START_TEST(destroy_4_3_9) { nua_handle_t *nh; struct message *invite, *cancel, *ack, *bye; S2_CASE("4.3.9", "Destroy handle in calling state", "NUA sends INVITE, receives 180, handle gets destroyed, " "but remote end returns 200 OK. " "Make sure nua tries to release call properly."); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite = invite_sent_by_nua(nh, TAG_END()); process_offer(invite); s2_sip_respond_to(invite, dialog, SIP_180_RINGING, TAG_END()); fail_unless_event(nua_r_invite, 180); fail_unless(s2_check_callstate(nua_callstate_proceeding)); nua_handle_destroy(nh); cancel = s2_sip_wait_for_request(SIP_METHOD_CANCEL); fail_if(!cancel); s2_sip_respond_to(cancel, dialog, SIP_481_NO_TRANSACTION, TAG_END()); s2_sip_free_message(cancel); respond_with_sdp(invite, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(invite); ack = s2_sip_wait_for_request(SIP_METHOD_ACK); fail_if(!ack); s2_sip_free_message(ack); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_sip_respond_to(bye, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(bye); } END_TEST START_TEST(destroy_4_4_1) { nua_handle_t *nh; struct event *invite; struct message *response; S2_CASE("4.4.1", "Destroy handle while call is on-going", "NUA is callee, sends 100, destroys handle"); soa_generate_offer(soa, 1, NULL); request_with_sdp(dialog, SIP_METHOD_INVITE, NULL, TAG_END()); invite = s2_wait_for_event(nua_i_invite, 100); fail_unless(invite != NULL); fail_unless(s2_check_callstate(nua_callstate_received)); nh = invite->nh; fail_if(!nh); s2_free_event(invite); response = s2_sip_wait_for_response(100, SIP_METHOD_INVITE); fail_if(!response); s2_sip_free_message(response); nua_handle_destroy(nh); response = s2_sip_wait_for_response(480, SIP_METHOD_INVITE); fail_if(!response); fail_if(s2_sip_request_to(dialog, SIP_METHOD_ACK, NULL, SIPTAG_VIA(sip_object(dialog->invite)->sip_via), TAG_END())); s2_sip_free_message(response); } END_TEST START_TEST(destroy_4_4_2) { nua_handle_t *nh; struct event *invite; struct message *response; S2_CASE("4.4.1", "Destroy handle while call is on-going", "NUA is callee, sends 180, destroys handle"); soa_generate_offer(soa, 1, NULL); request_with_sdp(dialog, SIP_METHOD_INVITE, NULL, TAG_END()); invite = s2_wait_for_event(nua_i_invite, 100); fail_unless(invite != NULL); fail_unless(s2_check_callstate(nua_callstate_received)); nh = invite->nh; fail_if(!nh); s2_free_event(invite); response = s2_sip_wait_for_response(100, SIP_METHOD_INVITE); fail_if(!response); s2_sip_free_message(response); nua_respond(nh, SIP_180_RINGING, TAG_END()); response = s2_sip_wait_for_response(180, SIP_METHOD_INVITE); fail_if(!response); s2_sip_free_message(response); nua_handle_destroy(nh); response = s2_sip_wait_for_response(480, SIP_METHOD_INVITE); fail_if(!response); fail_if(s2_sip_request_to(dialog, SIP_METHOD_ACK, NULL, SIPTAG_VIA(sip_object(dialog->invite)->sip_via), TAG_END())); s2_sip_free_message(response); } END_TEST START_TEST(destroy_4_4_3_1) { nua_handle_t *nh; struct event *invite; struct message *response, *bye; S2_CASE("4.4.3.1", "Destroy handle while call is on-going", "NUA is callee, sends 200, destroys handle"); soa_generate_offer(soa, 1, NULL); request_with_sdp(dialog, SIP_METHOD_INVITE, NULL, TAG_END()); invite = s2_wait_for_event(nua_i_invite, 100); fail_unless(invite != NULL); fail_unless(s2_check_callstate(nua_callstate_received)); nh = invite->nh; fail_if(!nh); s2_free_event(invite); response = s2_sip_wait_for_response(100, SIP_METHOD_INVITE); fail_if(!response); s2_sip_free_message(response); nua_respond(nh, SIP_180_RINGING, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), TAG_END()); response = s2_sip_wait_for_response(180, SIP_METHOD_INVITE); fail_if(!response); s2_sip_free_message(response); fail_unless(s2_check_callstate(nua_callstate_early)); nua_respond(nh, SIP_200_OK, TAG_END()); fail_unless(s2_check_callstate(nua_callstate_completed)); response = s2_sip_wait_for_response(200, SIP_METHOD_INVITE); fail_if(!response); nua_handle_destroy(nh); fail_if(s2_sip_request_to(dialog, SIP_METHOD_ACK, NULL, SIPTAG_VIA(sip_object(dialog->invite)->sip_via), TAG_END())); s2_sip_free_message(response); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_sip_respond_to(bye, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(bye); } END_TEST START_TEST(destroy_4_4_3_2) { nua_handle_t *nh; struct event *invite; struct message *response, *bye; S2_CASE("4.4.3.1", "Destroy handle while call is on-going", "NUA is callee, sends 200, destroys handle"); soa_generate_offer(soa, 1, NULL); request_with_sdp(dialog, SIP_METHOD_INVITE, NULL, TAG_END()); invite = s2_wait_for_event(nua_i_invite, 100); fail_unless(invite != NULL); fail_unless(s2_check_callstate(nua_callstate_received)); nh = invite->nh; fail_if(!nh); s2_free_event(invite); response = s2_sip_wait_for_response(100, SIP_METHOD_INVITE); fail_if(!response); s2_sip_free_message(response); nua_respond(nh, SIP_180_RINGING, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), TAG_END()); response = s2_sip_wait_for_response(180, SIP_METHOD_INVITE); fail_if(!response); s2_sip_free_message(response); fail_unless(s2_check_callstate(nua_callstate_early)); nua_respond(nh, SIP_200_OK, TAG_END()); fail_unless(s2_check_callstate(nua_callstate_completed)); response = s2_sip_wait_for_response(200, SIP_METHOD_INVITE); fail_if(!response); nua_handle_destroy(nh); bye = s2_sip_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_sip_respond_to(bye, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(bye); fail_if(s2_sip_request_to(dialog, SIP_METHOD_ACK, NULL, SIPTAG_VIA(sip_object(dialog->invite)->sip_via), TAG_END())); s2_sip_free_message(response); } END_TEST static TCase *destroy_tcase(int threading) { TCase *tc = tcase_create("4.3 - Destroying Handle"); add_call_fixtures(tc, threading); { tcase_add_test(tc, destroy_4_3_1); tcase_add_test(tc, destroy_4_3_2); tcase_add_test(tc, destroy_4_3_3); tcase_add_test(tc, destroy_4_3_4); tcase_add_test(tc, destroy_4_3_5); tcase_add_test(tc, destroy_4_3_6); tcase_add_test(tc, destroy_4_3_7); if (XXX) { tcase_add_test(tc, destroy_4_3_8); tcase_add_test(tc, destroy_4_3_9); } tcase_add_test(tc, destroy_4_4_1); tcase_add_test(tc, destroy_4_4_2); tcase_add_test(tc, destroy_4_4_3_1); tcase_add_test(tc, destroy_4_4_3_2); tcase_set_timeout(tc, 5); } return tc; } /* ====================================================================== */ static void options_setup(void), options_teardown(void); START_TEST(options_5_1_1) { struct event *options; nua_handle_t *nh; struct message *response; S2_CASE("5.1.1", "Test nua_respond() API", "Test nua_respond() API with OPTIONS."); s2_sip_request_to(dialog, SIP_METHOD_OPTIONS, NULL, TAG_END()); options = s2_wait_for_event(nua_i_options, 200); fail_unless(options != NULL); nh = options->nh; fail_if(!nh); response = s2_sip_wait_for_response(200, SIP_METHOD_OPTIONS); fail_if(!response); s2_sip_free_message(response); nua_handle_destroy(nh); nua_set_params(nua, NUTAG_APPL_METHOD("OPTIONS"), TAG_END()); fail_unless_event(nua_r_set_params, 200); s2_sip_request_to(dialog, SIP_METHOD_OPTIONS, NULL, TAG_END()); options = s2_wait_for_event(nua_i_options, 100); fail_unless(options != NULL); nh = options->nh; fail_if(!nh); nua_respond(nh, 202, "okok", NUTAG_WITH_SAVED(options->event), TAG_END()); response = s2_sip_wait_for_response(202, SIP_METHOD_OPTIONS); fail_if(!response); s2_sip_free_message(response); nua_handle_destroy(nh); } END_TEST #if HAVE_LIBPTHREAD #include void *respond_to_options(void *arg) { struct event *options = (struct event *)arg; nua_respond(options->nh, 202, "ok ok", NUTAG_WITH_SAVED(options->event), TAG_END()); pthread_exit(arg); return NULL; } START_TEST(options_5_1_2) { struct event *options; nua_handle_t *nh; struct message *response; pthread_t tid; void *thread_return = NULL; S2_CASE("5.1.2", "Test nua_respond() API with another thread", "Test multithreading nua_respond() API with OPTIONS."); nua_set_params(nua, NUTAG_APPL_METHOD("OPTIONS"), TAG_END()); fail_unless_event(nua_r_set_params, 200); s2_sip_request_to(dialog, SIP_METHOD_OPTIONS, NULL, TAG_END()); options = s2_wait_for_event(nua_i_options, 100); fail_unless(options != NULL); nh = options->nh; fail_if(!nh); fail_if(pthread_create(&tid, NULL, respond_to_options, (void *)options)); pthread_join(tid, &thread_return); fail_unless(thread_return == (void *)options); response = s2_sip_wait_for_response(202, SIP_METHOD_OPTIONS); fail_if(!response); s2_sip_free_message(response); nua_handle_destroy(nh); } END_TEST #else START_TEST(options_5_1_2) { } END_TEST #endif TCase *options_tcase(int threading) { TCase *tc = tcase_create("5 - OPTIONS, etc"); tcase_add_checked_fixture(tc, options_setup, options_teardown); tcase_add_test(tc, options_5_1_1); tcase_add_test(tc, options_5_1_2); return tc; } static void options_setup(void) { s2_nua_thread = 1; call_setup(); } static void options_teardown(void) { s2_teardown_started("options"); call_teardown(); } /* ====================================================================== */ /* Test cases for REFER */ START_TEST(refer_5_2_1) { nua_handle_t *nh; sip_refer_to_t r[1]; struct event *refer; struct message *notify; S2_CASE("5.2.1", "Receive REFER", "Make a call, receive REFER."); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite_by_nua(nh, TAG_END()); *sip_refer_to_init(r)->r_url = *s2sip->aor->a_url; r->r_url->url_user = "bob2"; s2_sip_request_to(dialog, SIP_METHOD_REFER, NULL, SIPTAG_REFER_TO(r), TAG_END()); refer = s2_wait_for_event(nua_i_refer, 202); bye_by_nua(nh, TAG_END()); nua_handle_destroy(nh); notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY); s2_sip_respond_to(notify, dialog, SIP_200_OK, TAG_END()); } END_TEST START_TEST(refer_5_2_2) { nua_handle_t *nh, *nh2; sip_refer_to_t r[1]; sip_referred_by_t by[1]; struct event *refer, *notified; sip_t const *sip; sip_event_t const *refer_event = NULL; sip_subscription_state_t const *ss; struct message *invite; struct message *notify0, *notify1, *notify2; struct dialog *dialog1, *dialog2; S2_CASE("5.2.2", "Receive REFER", "Make a call, receive REFER, " "make another call with automatic NOTIFYs"); dialog2 = su_home_new(sizeof *dialog2); fail_unless(dialog2 != NULL); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); invite_by_nua(nh, TAG_END()); *sip_refer_to_init(r)->r_url = *s2sip->aor->a_url; r->r_url->url_user = "bob2"; s2_sip_request_to(dialog, SIP_METHOD_REFER, NULL, SIPTAG_REFER_TO(r), TAG_END()); refer = s2_wait_for_event(nua_i_refer, 202); sip = sip_object(refer->data->e_msg); fail_unless(sip && sip->sip_refer_to); bye_by_nua(nh, TAG_END()); dialog1 = dialog, dialog = dialog2; *sip_referred_by_init(by)->b_url = *sip->sip_from->a_url; fail_unless(tl_gets(refer->data->e_tags, NUTAG_REFER_EVENT_REF(refer_event), TAG_END()) == 1); nua_notify(nh, SIPTAG_EVENT(refer_event), SIPTAG_CONTENT_TYPE_STR("message/sipfrag"), SIPTAG_PAYLOAD_STR("SIP/2.0 100 Trying\r\n"), NUTAG_SUBSTATE(nua_substate_active), TAG_END()); notify0 = s2_sip_wait_for_request(SIP_METHOD_NOTIFY); fail_unless((ss = notify0->sip->sip_subscription_state) != NULL); fail_unless(su_casematch("active", ss->ss_substate)); s2_sip_respond_to(notify0, dialog1, SIP_200_OK, TAG_END()); notified = s2_wait_for_event(nua_r_notify, 200); nh2 = nua_handle(nua, NULL, NUTAG_URL(r->r_url), TAG_END()); invite = invite_sent_by_nua(nh2, NUTAG_REFER_EVENT(refer_event), NUTAG_NOTIFY_REFER(nh), SIPTAG_REFERRED_BY(by), TAG_END()); process_offer(invite); respond_with_sdp( invite, dialog, SIP_180_RINGING, SIPTAG_CONTENT_DISPOSITION_STR("session;handling=optional"), TAG_END()); fail_unless_event(nua_r_invite, 180); fail_unless(s2_check_callstate(nua_callstate_proceeding)); notify1 = s2_sip_wait_for_request(SIP_METHOD_NOTIFY); s2_sip_respond_to(notify1, dialog1, SIP_200_OK, TAG_END()); respond_with_sdp(invite, dialog, SIP_200_OK, TAG_END()); s2_sip_free_message(invite); fail_unless_event(nua_r_invite, 200); fail_unless(s2_check_callstate(nua_callstate_ready)); fail_unless(s2_sip_check_request(SIP_METHOD_ACK)); notify2 = s2_sip_wait_for_request(SIP_METHOD_NOTIFY); s2_sip_respond_to(notify2, dialog1, SIP_200_OK, TAG_END()); fail_unless((ss = notify2->sip->sip_subscription_state) != NULL); fail_unless(su_casematch("terminated", ss->ss_substate)); nua_handle_destroy(nh); bye_by_nua(nh2, TAG_END()); nua_handle_destroy(nh2); } END_TEST TCase *refer_tcase(int threading) { TCase *tc = tcase_create("5.2 - Call Transfer"); add_call_fixtures(tc, threading); tcase_add_test(tc, refer_5_2_1); tcase_add_test(tc, refer_5_2_2); return tc; } /* ====================================================================== */ /* Test case template */ START_TEST(empty) { S2_CASE("0.0.0", "Empty test case", "Detailed explanation for empty test case."); tport_set_params(s2sip->master, TPTAG_LOG(1), TAG_END()); s2_setup_logs(7); s2_setup_logs(0); tport_set_params(s2sip->master, TPTAG_LOG(0), TAG_END()); } END_TEST TCase *empty_tcase(int threading) { TCase *tc = tcase_create("0 - Empty"); add_call_fixtures(tc, threading); tcase_add_test(tc, empty); return tc; } /* ====================================================================== */ void check_session_cases(Suite *suite, int threading) { suite_add_tcase(suite, invite_tcase(threading)); suite_add_tcase(suite, cancel_tcase(threading)); suite_add_tcase(suite, session_timer_tcase(threading)); suite_add_tcase(suite, invite_100rel_tcase(threading)); suite_add_tcase(suite, invite_precondition_tcase(threading)); suite_add_tcase(suite, reinvite_tcase(threading)); suite_add_tcase(suite, invite_error_tcase(threading)); suite_add_tcase(suite, termination_tcase(threading)); suite_add_tcase(suite, destroy_tcase(threading)); suite_add_tcase(suite, options_tcase(threading)); suite_add_tcase(suite, refer_tcase(threading)); if (0) /* Template */ suite_add_tcase(suite, empty_tcase(threading)); } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/check_simple.c000066400000000000000000001060571223300710500231400ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2008 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE check_events.c * * @brief NUA module tests for SIP events * * @author Pekka Pessi * * @copyright (C) 2008 Nokia Corporation. */ #include "config.h" #undef NDEBUG #include "check_nua.h" #include #include #include #include #include #include #include #include #include /* define XXX as 1 in order to see all failing test cases */ #ifndef XXX #define XXX (0) #endif /* ====================================================================== */ static nua_t *nua; static struct dialog *dialog = NULL; #define CRLF "\r\n" void s2_dialog_setup(void) { nua = s2_nua_setup("simple", SIPTAG_ORGANIZATION_STR("Pussy Galore's Flying Circus"), NUTAG_OUTBOUND("no-options-keepalive, no-validate"), TAG_END()); dialog = su_home_new(sizeof *dialog); fail_if(!dialog); s2_register_setup(); } void s2_dialog_teardown(void) { s2_teardown_started("simple"); s2_register_teardown(); nua_shutdown(nua); fail_unless_event(nua_r_shutdown, 200); s2_nua_teardown(); } static void simple_thread_setup(void) { s2_nua_thread = 1; s2_dialog_setup(); } static void simple_threadless_setup(void) { s2_nua_thread = 0; s2_dialog_setup(); } static void simple_teardown(void) { s2_dialog_teardown(); } static char const presence_open[] = "\n" "\n" " \n" " open\n" " sip:bob@example.org\n" " \n" "\n"; static char const presence_closed[] = "\n" "\n" " \n" " closed\n" " \n" "\n"; static char const *event_type = "presence"; static char const *event_mime_type = "application/pidf+xml"; static char const *event_state = presence_open; static char const *subscription_state = "active;expires=600"; static struct event * respond_to_subscribe(struct message *subscribe, nua_event_t expect_event, enum nua_substate expect_substate, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...) { struct event *event; ta_list ta; ta_start(ta, tag, value); s2_sip_respond_to(subscribe, dialog, status, phrase, ta_tags(ta)); ta_end(ta); event = s2_wait_for_event(expect_event, status); fail_if(!event); fail_unless(s2_check_substate(event, expect_substate)); return event; } static struct event * notify_to_nua(enum nua_substate expect_substate, tag_type_t tag, tag_value_t value, ...) { struct event *event; struct message *response; ta_list ta; int status; ta_start(ta, tag, value); fail_if(s2_sip_request_to(dialog, SIP_METHOD_NOTIFY, NULL, SIPTAG_CONTENT_TYPE_STR(event_mime_type), SIPTAG_PAYLOAD_STR(event_state), ta_tags(ta))); ta_end(ta); response = s2_sip_wait_for_response(0, SIP_METHOD_NOTIFY); fail_if(!response); status = response->sip->sip_status->st_status; fail_unless(status == 200); s2_sip_free_message(response); event = s2_wait_for_event(nua_i_notify, 200); fail_if(!event); fail_unless(s2_check_substate(event, expect_substate)); return event; } static int send_notify_before_response = 0; static struct event * subscription_by_nua(nua_handle_t *nh, enum nua_substate current, tag_type_t tag, tag_value_t value, ...) { struct message *subscribe; struct event *notify, *event; ta_list ta; enum nua_substate substate = nua_substate_active; char const *substate_str = subscription_state; char const *expires = "600"; subscribe = s2_sip_wait_for_request(SIP_METHOD_SUBSCRIBE); if (event_type) fail_if(!subscribe->sip->sip_event || strcmp(event_type, subscribe->sip->sip_event->o_type)); if (subscribe->sip->sip_expires && subscribe->sip->sip_expires->ex_delta == 0) { substate = nua_substate_terminated; substate_str = "terminated;reason=timeout"; expires = "0"; } ta_start(ta, tag, value); if (send_notify_before_response) { s2_sip_save_uas_dialog(dialog, subscribe->sip); notify = notify_to_nua(substate, SIPTAG_EVENT(subscribe->sip->sip_event), SIPTAG_SUBSCRIPTION_STATE_STR(substate_str), ta_tags(ta)); event = respond_to_subscribe(subscribe, nua_r_subscribe, substate, SIP_200_OK, SIPTAG_EXPIRES_STR(expires), TAG_END()); s2_free_event(event); } else { event = respond_to_subscribe(subscribe, nua_r_subscribe, current, SIP_202_ACCEPTED, SIPTAG_EXPIRES_STR(expires), TAG_END()); s2_free_event(event); notify = notify_to_nua(substate, SIPTAG_EVENT(subscribe->sip->sip_event), SIPTAG_SUBSCRIPTION_STATE_STR(substate_str), ta_tags(ta)); } s2_sip_free_message(subscribe); return notify; } static void unsubscribe_by_nua(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { struct message *subscribe, *response; struct event *event; nua_unsubscribe(nh, TAG_END()); subscribe = s2_sip_wait_for_request(SIP_METHOD_SUBSCRIBE); s2_sip_respond_to(subscribe, dialog, SIP_200_OK, SIPTAG_EXPIRES_STR("0"), TAG_END()); event = s2_wait_for_event(nua_r_unsubscribe, 200); fail_if(!event); fail_unless(s2_check_substate(event, nua_substate_active)); s2_free_event(event); fail_if(s2_sip_request_to(dialog, SIP_METHOD_NOTIFY, NULL, SIPTAG_EVENT(subscribe->sip->sip_event), SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=timeout"), SIPTAG_CONTENT_TYPE_STR(event_mime_type), SIPTAG_PAYLOAD_STR(event_state), TAG_END())); event = s2_wait_for_event(nua_i_notify, 200); fail_if(!event); fail_unless(s2_check_substate(event, nua_substate_terminated)); s2_free_event(event); response = s2_sip_wait_for_response(200, SIP_METHOD_NOTIFY); fail_if(!response); s2_sip_free_message(response); s2_sip_free_message(subscribe); } /* ====================================================================== */ /* 6 - Subscribe/notify */ START_TEST(subscribe_6_1_1) { nua_handle_t *nh; struct event *notify; S2_CASE("6.1.1", "Basic subscription", "NUA sends SUBSCRIBE, waits for NOTIFY, sends un-SUBSCRIBE"); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); nua_subscribe(nh, SIPTAG_EVENT_STR(event_type), TAG_END()); notify = subscription_by_nua(nh, nua_substate_embryonic, TAG_END()); s2_free_event(notify); unsubscribe_by_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST START_TEST(subscribe_6_1_2) { nua_handle_t *nh; struct message *subscribe, *response; struct event *notify, *event; S2_CASE("6.1.2", "Basic subscription with refresh", "NUA sends SUBSCRIBE, waits for NOTIFY, " "sends re-SUBSCRIBE, waits for NOTIFY, " "sends un-SUBSCRIBE"); send_notify_before_response = 1; nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); nua_subscribe(nh, SIPTAG_EVENT_STR(event_type), TAG_END()); notify = subscription_by_nua(nh, nua_substate_embryonic, TAG_END()); s2_free_event(notify); /* Wait for refresh */ s2_nua_fast_forward(600, s2base->root); subscribe = s2_sip_wait_for_request(SIP_METHOD_SUBSCRIBE); s2_sip_respond_to(subscribe, dialog, SIP_200_OK, SIPTAG_EXPIRES_STR("600"), TAG_END()); event = s2_wait_for_event(nua_r_subscribe, 200); fail_if(!event); fail_unless(s2_check_substate(event, nua_substate_active)); s2_free_event(event); fail_if(s2_sip_request_to(dialog, SIP_METHOD_NOTIFY, NULL, SIPTAG_EVENT(subscribe->sip->sip_event), SIPTAG_SUBSCRIPTION_STATE_STR("active;expires=600"), SIPTAG_CONTENT_TYPE_STR(event_mime_type), SIPTAG_PAYLOAD_STR(event_state), TAG_END())); event = s2_wait_for_event(nua_i_notify, 200); fail_if(!event); fail_unless(s2_check_substate(event, nua_substate_active)); s2_free_event(event); response = s2_sip_wait_for_response(200, SIP_METHOD_NOTIFY); fail_if(!response); s2_sip_free_message(response); unsubscribe_by_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST START_TEST(subscribe_6_1_3) { nua_handle_t *nh; struct message *response; struct event *notify, *event; S2_CASE("6.1.3", "Subscription terminated by notifier", "NUA sends SUBSCRIBE, waits for NOTIFY, " "gets NOTIFY terminating the subscription,"); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); nua_subscribe(nh, SIPTAG_EVENT_STR(event_type), TAG_END()); notify = subscription_by_nua(nh, nua_substate_embryonic, TAG_END()); s2_free_event(notify); fail_if(s2_sip_request_to(dialog, SIP_METHOD_NOTIFY, NULL, SIPTAG_EVENT_STR(event_type), SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource"), TAG_END())); event = s2_wait_for_event(nua_i_notify, 200); fail_if(!event); fail_unless(s2_check_substate(event, nua_substate_terminated)); s2_free_event(event); response = s2_sip_wait_for_response(200, SIP_METHOD_NOTIFY); fail_if(!response); s2_sip_free_message(response); nua_handle_destroy(nh); } END_TEST START_TEST(subscribe_6_1_4) { nua_handle_t *nh; struct message *response; struct event *notify, *event; S2_CASE("6.1.4", "Subscription terminated by notifier, re-established", "NUA sends SUBSCRIBE, waits for NOTIFY, " "gets NOTIFY terminating the subscription,"); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); nua_subscribe(nh, SIPTAG_EVENT_STR(event_type), TAG_END()); notify = subscription_by_nua(nh, nua_substate_embryonic, TAG_END()); s2_free_event(notify); fail_if(s2_sip_request_to(dialog, SIP_METHOD_NOTIFY, NULL, SIPTAG_EVENT_STR(event_type), SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=deactivated"), TAG_END())); event = s2_wait_for_event(nua_i_notify, 200); fail_if(!event); fail_unless(s2_check_substate(event, nua_substate_embryonic)); s2_free_event(event); response = s2_sip_wait_for_response(200, SIP_METHOD_NOTIFY); fail_if(!response); s2_sip_free_message(response); su_home_unref((void *)dialog), dialog = su_home_new(sizeof *dialog); fail_if(!dialog); s2_nua_fast_forward(5, s2base->root); /* nua re-establishes the subscription */ notify = subscription_by_nua(nh, nua_substate_embryonic, TAG_END()); s2_free_event(notify); /* Unsubscribe with nua_subscribe() Expires: 0 */ nua_subscribe(nh, SIPTAG_EVENT_STR(event_type), SIPTAG_EXPIRES_STR("0"), TAG_END()); notify = subscription_by_nua(nh, nua_substate_active, TAG_END()); s2_free_event(notify); nua_handle_destroy(nh); } END_TEST START_TEST(subscribe_6_1_5) { nua_handle_t *nh; struct event *notify; sip_via_t *vorig = s2_sip_tport_via(s2sip->udp.tport); sip_via_t via[2]; char *v0_params[8] = {}, *v1_params[8] = {}; char branch0[32], branch1[32]; S2_CASE("6.1.5", "Via handling in response to NOTIFY", "NUA sends SUBSCRIBE, waits for NOTIFY, sends un-SUBSCRIBE"); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); nua_subscribe(nh, SIPTAG_EVENT_STR(event_type), TAG_END()); s2_sip_msg_flags = MSG_FLG_COMMA_LISTS|MSG_FLG_COMPACT; fail_if(vorig == NULL); via[0] = *vorig; via[0].v_host = "example.org"; via[0].v_params = (void *)v0_params; snprintf(v0_params[0] = branch0, sizeof branch0, "branch=z9hG4bK%lx", ++s2sip->tid); fail_if(vorig == NULL); via[1] = *vorig; via[1].v_params = (void *)v1_params; snprintf(v1_params[0] = branch1, sizeof branch1, "branch=z9hG4bK%lx", ++s2sip->tid); notify = subscription_by_nua(nh, nua_substate_embryonic, SIPTAG_VIA(via + 1), SIPTAG_VIA(via + 0), TAG_END()); s2_sip_msg_flags = 0; s2_free_event(notify); unsubscribe_by_nua(nh, TAG_END()); nua_handle_destroy(nh); } END_TEST TCase *subscribe_tcase(int threading) { TCase *tc = tcase_create("6.1 - Basic SUBSCRIBE_"); void (*simple_setup)(void); simple_setup = threading ? simple_thread_setup : simple_threadless_setup; tcase_add_checked_fixture(tc, simple_setup, simple_teardown); { tcase_add_test(tc, subscribe_6_1_1); tcase_add_test(tc, subscribe_6_1_2); tcase_add_test(tc, subscribe_6_1_3); tcase_add_test(tc, subscribe_6_1_4); tcase_add_test(tc, subscribe_6_1_5); } return tc; } START_TEST(fetch_6_2_1) { nua_handle_t *nh; struct event *notify; S2_CASE("6.2.1", "Event fetch - NOTIFY after 202", "NUA sends SUBSCRIBE with Expires 0, waits for NOTIFY"); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); nua_subscribe(nh, SIPTAG_EVENT_STR(event_type), SIPTAG_EXPIRES_STR("0"), TAG_END()); notify = subscription_by_nua(nh, nua_substate_embryonic, TAG_END()); s2_check_substate(notify, nua_substate_terminated); s2_free_event(notify); nua_handle_destroy(nh); } END_TEST START_TEST(fetch_6_2_2) { nua_handle_t *nh; struct event *notify; S2_CASE("6.2.2", "Event fetch - NOTIFY before 200", "NUA sends SUBSCRIBE with Expires 0, waits for NOTIFY"); send_notify_before_response = 1; nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); nua_subscribe(nh, SIPTAG_EVENT_STR(event_type), SIPTAG_EXPIRES_STR("0"), TAG_END()); notify = subscription_by_nua(nh, nua_substate_embryonic, TAG_END()); s2_check_substate(notify, nua_substate_terminated); s2_free_event(notify); nua_handle_destroy(nh); } END_TEST START_TEST(fetch_6_2_3) { nua_handle_t *nh; struct message *subscribe; struct event *event; S2_CASE("6.2.3", "Event fetch - no NOTIFY", "NUA sends SUBSCRIBE with Expires 0, waits for NOTIFY, times out"); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); nua_subscribe(nh, SIPTAG_EVENT_STR(event_type), SIPTAG_EXPIRES_STR("0"), TAG_END()); subscribe = s2_sip_wait_for_request(SIP_METHOD_SUBSCRIBE); s2_sip_respond_to(subscribe, dialog, SIP_202_ACCEPTED, SIPTAG_EXPIRES_STR("0"), TAG_END()); s2_sip_free_message(subscribe); event = s2_wait_for_event(nua_r_subscribe, 202); fail_if(!event); fail_unless(s2_check_substate(event, nua_substate_embryonic)); s2_free_event(event); s2_nua_fast_forward(600, s2base->root); event = s2_wait_for_event(nua_i_notify, 408); fail_if(!event); fail_unless(s2_check_substate(event, nua_substate_terminated)); s2_free_event(event); nua_handle_destroy(nh); } END_TEST TCase *fetch_tcase(int threading) { TCase *tc = tcase_create("6.2 - Event fetch"); void (*simple_setup)(void); simple_setup = threading ? simple_thread_setup : simple_threadless_setup; tcase_add_checked_fixture(tc, simple_setup, simple_teardown); { tcase_add_test(tc, fetch_6_2_1); tcase_add_test(tc, fetch_6_2_2); tcase_add_test(tc, fetch_6_2_3); } return tc; } nua_handle_t * subscribe_to_nua(char const *event, tag_type_t tag, tag_value_t value, ...) { ta_list ta; struct event *subscribe; struct message *response; nua_handle_t *nh; nua_set_params(nua, NUTAG_APPL_METHOD("SUBSCRIBE"), SIPTAG_ALLOW_EVENTS_STR(event), TAG_END()); fail_unless_event(nua_r_set_params, 200); ta_start(ta, tag, value); s2_sip_request_to(dialog, SIP_METHOD_SUBSCRIBE, NULL, SIPTAG_EVENT_STR(event), ta_tags(ta)); ta_end(ta); subscribe = s2_wait_for_event(nua_i_subscribe, 100); nh = subscribe->nh; nua_respond(nh, SIP_202_ACCEPTED, NUTAG_WITH_SAVED(subscribe->event), TAG_END()); s2_free_event(subscribe); response = s2_sip_wait_for_response(202, SIP_METHOD_SUBSCRIBE); s2_sip_update_dialog(dialog, response); fail_unless(response->sip->sip_expires != NULL); s2_sip_free_message(response); return nh; } START_TEST(notify_6_3_1) { nua_handle_t *nh; struct event *subscribe; struct message *notify, *response; sip_t *sip; S2_CASE("6.3.1", "Basic NOTIFY server", "NUA receives SUBSCRIBE, sends 202 and NOTIFY. " "First NOTIFY terminates subscription. "); s2_sip_request_to(dialog, SIP_METHOD_SUBSCRIBE, NULL, SIPTAG_EVENT_STR("presence"), TAG_END()); /* 489 Bad Event by default */ s2_sip_check_response(489, SIP_METHOD_SUBSCRIBE); nua_set_params(nua, NUTAG_APPL_METHOD("SUBSCRIBE"), TAG_END()); fail_unless_event(nua_r_set_params, 200); s2_sip_request_to(dialog, SIP_METHOD_SUBSCRIBE, NULL, SIPTAG_EVENT_STR("presence"), TAG_END()); s2_sip_check_response(489, SIP_METHOD_SUBSCRIBE); nua_set_params(nua, SIPTAG_ALLOW_EVENTS_STR("presence"), TAG_END()); fail_unless_event(nua_r_set_params, 200); s2_sip_request_to(dialog, SIP_METHOD_SUBSCRIBE, NULL, SIPTAG_EVENT_STR("presence"), TAG_END()); subscribe = s2_wait_for_event(nua_i_subscribe, 100); nh = subscribe->nh; nua_respond(nh, SIP_403_FORBIDDEN, NUTAG_WITH_SAVED(subscribe->event), TAG_END()); s2_free_event(subscribe); s2_sip_check_response(403, SIP_METHOD_SUBSCRIBE); nua_handle_destroy(nh); s2_sip_request_to(dialog, SIP_METHOD_SUBSCRIBE, NULL, SIPTAG_EVENT_STR("presence"), TAG_END()); subscribe = s2_wait_for_event(nua_i_subscribe, 100); nh = subscribe->nh; nua_respond(nh, SIP_202_ACCEPTED, NUTAG_WITH_SAVED(subscribe->event), TAG_END()); s2_free_event(subscribe); response = s2_sip_wait_for_response(202, SIP_METHOD_SUBSCRIBE); s2_sip_update_dialog(dialog, response); fail_unless(response->sip->sip_expires != NULL); s2_sip_free_message(response); nua_notify(nh, NUTAG_SUBSTATE(nua_substate_terminated), SIPTAG_PAYLOAD_STR(presence_closed), TAG_END()); notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY); fail_unless(notify != NULL); sip = notify->sip; fail_unless(sip->sip_subscription_state != NULL); fail_unless(su_strmatch(sip->sip_subscription_state->ss_substate, "terminated")); s2_sip_respond_to(notify, dialog, SIP_200_OK, TAG_END()); fail_unless_event(nua_r_notify, 200); nua_handle_destroy(nh); } END_TEST START_TEST(notify_6_3_2) { nua_handle_t *nh; struct message *notify; sip_t *sip; S2_CASE("6.3.2", "NOTIFY server - automatic subscription termination", "NUA receives SUBSCRIBE, sends 202 and NOTIFY. " "The subscription terminates with timeout. "); nh = subscribe_to_nua("presence", SIPTAG_EXPIRES_STR("300"), TAG_END()); nua_notify(nh, NUTAG_SUBSTATE(nua_substate_active), SIPTAG_PAYLOAD_STR(presence_closed), TAG_END()); notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY); fail_unless(notify != NULL); sip = notify->sip; fail_unless(sip->sip_subscription_state != NULL); fail_unless(su_strmatch(sip->sip_subscription_state->ss_substate, "active")); s2_sip_respond_to(notify, dialog, SIP_200_OK, TAG_END()); fail_unless_event(nua_r_notify, 200); s2_nua_fast_forward(300, s2base->root); notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY); fail_unless(notify != NULL); sip = notify->sip; fail_unless(sip->sip_subscription_state != NULL); fail_unless(su_strmatch(sip->sip_subscription_state->ss_substate, "terminated")); s2_sip_respond_to(notify, dialog, SIP_200_OK, TAG_END()); fail_unless_event(nua_r_notify, 200); nua_handle_destroy(nh); } END_TEST static int s2_event_substate(struct event *event) { if (event) { tagi_t const *t = tl_find(event->data->e_tags, nutag_substate); if (t) return t->t_value; } return -1; } START_TEST(notify_6_3_3) { nua_handle_t *nh; struct message *notify; struct event *response; sip_t *sip; S2_CASE("6.3.3", "NOTIFY server - terminate with error response to NOTIFY", "NUA receives SUBSCRIBE, sends 202 and NOTIFY. " "The subscription terminates when watcher " "returns 481 to second NOTIFY."); nh = subscribe_to_nua("presence", SIPTAG_EXPIRES_STR("300"), TAG_END()); nua_notify(nh, NUTAG_SUBSTATE(nua_substate_active), SIPTAG_PAYLOAD_STR(presence_closed), TAG_END()); notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY); fail_unless(notify != NULL); sip = notify->sip; fail_unless(sip->sip_subscription_state != NULL); fail_unless(su_strmatch(sip->sip_subscription_state->ss_substate, "active")); s2_sip_respond_to(notify, dialog, SIP_200_OK, TAG_END()); fail_unless_event(nua_r_notify, 200); nua_notify(nh, NUTAG_SUBSTATE(nua_substate_active), SIPTAG_PAYLOAD_STR(presence_closed), TAG_END()); notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY); fail_unless(notify != NULL); sip = notify->sip; fail_unless(sip->sip_subscription_state != NULL); fail_unless(su_strmatch(sip->sip_subscription_state->ss_substate, "active")); s2_sip_respond_to(notify, dialog, SIP_481_NO_TRANSACTION, TAG_END()); response = s2_wait_for_event(nua_r_notify, 481); fail_unless(s2_event_substate(response) == nua_substate_terminated); nua_handle_destroy(nh); } END_TEST START_TEST(notify_6_3_4) { nua_handle_t *nh; struct message *notify; struct event *response; sip_t *sip; S2_CASE("6.3.4", "NOTIFY server - terminate with error response to NOTIFY", "NUA receives SUBSCRIBE, sends 202 and NOTIFY. " "The subscription terminates when watcher " "returns 481 to second NOTIFY. The queued 3rd NOTIFY gets " "responded by stack."); nh = subscribe_to_nua("presence", SIPTAG_EXPIRES_STR("300"), TAG_END()); nua_notify(nh, NUTAG_SUBSTATE(nua_substate_active), SIPTAG_PAYLOAD_STR(presence_closed), TAG_END()); notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY); fail_unless(notify != NULL); sip = notify->sip; fail_unless(sip->sip_subscription_state != NULL); fail_unless(su_strmatch(sip->sip_subscription_state->ss_substate, "active")); s2_sip_respond_to(notify, dialog, SIP_200_OK, TAG_END()); fail_unless_event(nua_r_notify, 200); nua_notify(nh, NUTAG_SUBSTATE(nua_substate_active), SIPTAG_PAYLOAD_STR(presence_open), TAG_END()); nua_notify(nh, NUTAG_SUBSTATE(nua_substate_active), SIPTAG_PAYLOAD_STR(presence_closed), TAG_END()); notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY); fail_unless(notify != NULL); sip = notify->sip; fail_unless(sip->sip_subscription_state != NULL); fail_unless(su_strmatch(sip->sip_subscription_state->ss_substate, "active")); s2_sip_respond_to(notify, dialog, SIP_481_NO_TRANSACTION, TAG_END()); response = s2_wait_for_event(nua_r_notify, 481); fail_unless(s2_event_substate(response) == nua_substate_terminated); response = s2_wait_for_event(nua_r_notify, 481); fail_unless(s2_event_substate(response) == nua_substate_terminated); nua_handle_destroy(nh); } END_TEST START_TEST(notify_6_3_5) { nua_handle_t *nh; struct message *notify; struct event *response; sip_t *sip; S2_CASE("6.3.4", "NOTIFY server - terminate with error response to NOTIFY", "NUA receives SUBSCRIBE, sends 202 and NOTIFY. " "The subscription terminates when watcher " "returns 481 to NOTIFY."); nh = subscribe_to_nua("presence", SIPTAG_EXPIRES_STR("300"), TAG_END()); nua_notify(nh, SIPTAG_SUBSCRIPTION_STATE_STR("active"), SIPTAG_PAYLOAD_STR(presence_closed), TAG_END()); notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY); fail_unless(notify != NULL); sip = notify->sip; fail_unless(sip->sip_subscription_state != NULL); fail_unless(su_strmatch(sip->sip_subscription_state->ss_substate, "active")); s2_sip_respond_to(notify, dialog, SIP_200_OK, TAG_END()); fail_unless_event(nua_r_notify, 200); nua_notify(nh, SIPTAG_SUBSCRIPTION_STATE_STR("active"), SIPTAG_PAYLOAD_STR(presence_open), TAG_END()); notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY); fail_unless(notify != NULL); sip = notify->sip; fail_unless(sip->sip_subscription_state != NULL); fail_unless(su_strmatch(sip->sip_subscription_state->ss_substate, "active")); nua_notify(nh, NUTAG_NEWSUB(1), SIPTAG_SUBSCRIPTION_STATE_STR("active"), SIPTAG_PAYLOAD_STR(presence_open), TAG_END()); s2_sip_respond_to(notify, dialog, SIP_481_NO_TRANSACTION, TAG_END()); response = s2_wait_for_event(nua_r_notify, 481); fail_unless(s2_event_substate(response) == nua_substate_terminated); notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY); s2_sip_respond_to(notify, dialog, SIP_481_NO_TRANSACTION, TAG_END()); response = s2_wait_for_event(nua_r_notify, 481); fail_unless(s2_event_substate(response) == nua_substate_terminated); nua_handle_destroy(nh); } END_TEST START_TEST(notify_6_3_6) { nua_handle_t *nh; struct event *subscribe; struct message *notify, *response; sip_t *sip; S2_CASE("6.3.6", "Explicit refresh with NUTAG_APPL_EVENT()", "Process subscription refresh by application"); nua_set_params(nua, NUTAG_APPL_METHOD("SUBSCRIBE"), NUTAG_APPL_EVENT("presence"), SIPTAG_ALLOW_EVENTS_STR("presence"), TAG_END()); fail_unless_event(nua_r_set_params, 200); s2_sip_request_to(dialog, SIP_METHOD_SUBSCRIBE, NULL, SIPTAG_EVENT_STR("presence"), TAG_END()); subscribe = s2_wait_for_event(nua_i_subscribe, 100); nh = subscribe->nh; nua_respond(nh, SIP_202_ACCEPTED, NUTAG_WITH_SAVED(subscribe->event), TAG_END()); s2_free_event(subscribe); response = s2_sip_wait_for_response(202, SIP_METHOD_SUBSCRIBE); s2_sip_update_dialog(dialog, response); fail_unless(response->sip->sip_expires != NULL); s2_sip_free_message(response); nua_notify(nh, NUTAG_SUBSTATE(nua_substate_active), SIPTAG_PAYLOAD_STR(presence_closed), TAG_END()); notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY); fail_unless(notify != NULL); sip = notify->sip; fail_unless(sip->sip_subscription_state != NULL); fail_unless(su_strmatch(sip->sip_subscription_state->ss_substate, "active")); s2_sip_respond_to(notify, dialog, SIP_200_OK, TAG_END()); fail_unless_event(nua_r_notify, 200); s2_sip_request_to(dialog, SIP_METHOD_SUBSCRIBE, NULL, SIPTAG_EVENT_STR("presence"), TAG_END()); subscribe = s2_wait_for_event(nua_i_subscribe, 100); nh = subscribe->nh; nua_respond(nh, SIP_202_ACCEPTED, NUTAG_WITH_SAVED(subscribe->event), TAG_END()); s2_free_event(subscribe); response = s2_sip_wait_for_response(202, SIP_METHOD_SUBSCRIBE); s2_sip_update_dialog(dialog, response); fail_unless(response->sip->sip_expires != NULL); s2_sip_free_message(response); notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY); fail_unless(notify != NULL); sip = notify->sip; fail_unless(sip->sip_subscription_state != NULL); fail_unless(su_strmatch(sip->sip_subscription_state->ss_substate, "active")); s2_sip_respond_to(notify, dialog, SIP_200_OK, TAG_END()); fail_unless_event(nua_r_notify, 200); /* Now clear list of application events */ nua_set_params(nua, NUTAG_APPL_EVENT(NULL), NUTAG_SUB_EXPIRES(360), TAG_END()); fail_unless_event(nua_r_set_params, 200); s2_sip_request_to(dialog, SIP_METHOD_SUBSCRIBE, NULL, SIPTAG_EVENT_STR("presence"), TAG_END()); /* Automatically responded && refreshed */ subscribe = s2_wait_for_event(nua_i_subscribe, 200); s2_free_event(subscribe); response = s2_sip_wait_for_response(200, SIP_METHOD_SUBSCRIBE); s2_sip_update_dialog(dialog, response); fail_unless(response->sip->sip_expires != NULL); fail_unless(response->sip->sip_expires->ex_delta == 360); s2_sip_free_message(response); notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY); fail_unless(notify != NULL); sip = notify->sip; fail_unless(sip->sip_subscription_state != NULL); fail_unless(su_strmatch(sip->sip_subscription_state->ss_substate, "active")); s2_sip_respond_to(notify, dialog, SIP_200_OK, TAG_END()); fail_unless_event(nua_r_notify, 200); nua_handle_destroy(nh); notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY); sip = notify->sip; fail_unless(sip->sip_subscription_state != NULL); fail_unless(su_strmatch(sip->sip_subscription_state->ss_substate, "terminated")); s2_sip_respond_to(notify, dialog, SIP_481_NO_TRANSACTION, TAG_END()); } END_TEST TCase *notifier_tcase(int threading) { TCase *tc = tcase_create("6.3 - Basic event server with NOTIFY "); void (*simple_setup)(void); simple_setup = threading ? simple_thread_setup : simple_threadless_setup; tcase_add_checked_fixture(tc, simple_setup, simple_teardown); { tcase_add_test(tc, notify_6_3_1); tcase_add_test(tc, notify_6_3_2); tcase_add_test(tc, notify_6_3_3); tcase_add_test(tc, notify_6_3_4); tcase_add_test(tc, notify_6_3_5); tcase_add_test(tc, notify_6_3_6); } return tc; } /* ====================================================================== */ START_TEST(message_6_4_1) { nua_handle_t *nh; struct message *message; struct event *response; S2_CASE("6.4.1", "SIMPLE MESSAGE", "Send MESSAGE"); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); nua_message(nh, SIPTAG_CONTENT_TYPE_STR("text/plain"), SIPTAG_PAYLOAD_STR("hello"), TAG_END()); message = s2_sip_wait_for_request(SIP_METHOD_MESSAGE); s2_sip_respond_to(message, NULL, SIP_202_ACCEPTED, TAG_END()); s2_sip_free_message(message); response = s2_wait_for_event(nua_r_message, 202); s2_free_event(response); nua_handle_destroy(nh); } END_TEST START_TEST(message_6_4_2) { nua_handle_t *nh; struct message *message; struct event *response; S2_CASE("6.4.2", "MESSAGE with 302/305", "Send MESSAGE"); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); nua_message(nh, SIPTAG_CONTENT_TYPE_STR("text/plain"), SIPTAG_PAYLOAD_STR("hello"), TAG_END()); message = s2_sip_wait_for_request(SIP_METHOD_MESSAGE); s2_sip_respond_to(message, NULL, SIP_302_MOVED_TEMPORARILY, SIPTAG_CONTACT_STR(""), TAG_END()); s2_sip_free_message(message); response = s2_wait_for_event(nua_r_message, 100); s2_free_event(response); message = s2_sip_wait_for_request(SIP_METHOD_MESSAGE); fail_unless(message->sip->sip_request->rq_url->url_user != NULL); fail_if(strcmp(message->sip->sip_request->rq_url->url_user, "302ed")); s2_sip_respond_to(message, NULL, SIP_305_USE_PROXY, SIPTAG_CONTACT_STR(""), TAG_END()); s2_sip_free_message(message); response = s2_wait_for_event(nua_r_message, 100); s2_free_event(response); message = s2_sip_wait_for_request(SIP_METHOD_MESSAGE); fail_unless(message->sip->sip_route != NULL); fail_unless(message->sip->sip_route->r_url->url_user != NULL); fail_if(strcmp(message->sip->sip_route->r_url->url_user, "routed")); s2_sip_respond_to(message, NULL, SIP_200_OK, TAG_END()); s2_sip_free_message(message); response = s2_wait_for_event(nua_r_message, 200); s2_free_event(response); /* ---------------------------------------------------------------------- */ nua_message(nh, NUTAG_AUTO302(0), SIPTAG_CONTENT_TYPE_STR("text/plain"), SIPTAG_PAYLOAD_STR("hello 2"), TAG_END()); message = s2_sip_wait_for_request(SIP_METHOD_MESSAGE); s2_sip_respond_to(message, NULL, SIP_302_MOVED_TEMPORARILY, SIPTAG_CONTACT_STR(""), TAG_END()); s2_sip_free_message(message); response = s2_wait_for_event(nua_r_message, 302); fail_unless(response->sip && response->sip->sip_contact); nua_message(nh, NUTAG_URL(response->sip->sip_contact->m_url), NUTAG_AUTO305(0), SIPTAG_CONTENT_TYPE_STR("text/plain"), SIPTAG_PAYLOAD_STR("hello 2"), TAG_END()); s2_free_event(response); message = s2_sip_wait_for_request(SIP_METHOD_MESSAGE); fail_unless(message->sip->sip_request->rq_url->url_user != NULL); fail_if(strcmp(message->sip->sip_request->rq_url->url_user, "not302ed")); s2_sip_respond_to(message, NULL, SIP_305_USE_PROXY, SIPTAG_CONTACT_STR(""), TAG_END()); s2_sip_free_message(message); response = s2_wait_for_event(nua_r_message, 305); s2_free_event(response); nua_handle_destroy(nh); } END_TEST START_TEST(message_6_4_3) { nua_handle_t *nh; struct message *message; struct event *response; sip_call_id_t *i; S2_CASE("6.4.1", "SIMPLE MESSAGE", "Send MESSAGE"); nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END()); nua_message(nh, SIPTAG_CONTENT_TYPE_STR("text/plain"), SIPTAG_PAYLOAD_STR("hello"), TAG_END()); message = s2_sip_wait_for_request(SIP_METHOD_MESSAGE); s2_sip_respond_to(message, NULL, SIP_407_PROXY_AUTH_REQUIRED, SIPTAG_PROXY_AUTHENTICATE_STR(s2_auth_digest_str), TAG_END()); i = sip_call_id_dup(NULL, message->sip->sip_call_id); fail_unless(i != NULL); s2_sip_free_message(message); fail_unless_event(nua_r_message, 407); nua_authenticate(nh, NUTAG_AUTH(s2_auth_credentials), TAG_END()); message = s2_sip_wait_for_request(SIP_METHOD_MESSAGE); s2_sip_respond_to(message, NULL, SIP_202_ACCEPTED, TAG_END()); fail_unless(su_strmatch(i->i_id, message->sip->sip_call_id->i_id)); s2_sip_free_message(message); response = s2_wait_for_event(nua_r_message, 202); s2_free_event(response); nua_handle_destroy(nh); } END_TEST static TCase *message_tcase(int threading) { TCase *tc = tcase_create(threading ? "6.4 - MESSAGE (MT)" : "6.4 - MESSAGE"); void (*simple_setup)(void); simple_setup = threading ? simple_thread_setup : simple_threadless_setup; tcase_add_checked_fixture(tc, simple_setup, simple_teardown); tcase_add_test(tc, message_6_4_1); tcase_add_test(tc, message_6_4_2); tcase_add_test(tc, message_6_4_3); return tc; } /* ====================================================================== */ /* Test case template */ START_TEST(empty) { S2_CASE("0.0.0", "Empty test case", "Detailed explanation for empty test case."); tport_set_params(s2sip->master, TPTAG_LOG(1), TAG_END()); s2_setup_logs(7); s2_setup_logs(0); tport_set_params(s2sip->master, TPTAG_LOG(0), TAG_END()); } END_TEST static TCase *empty_tcase(int threading) { TCase *tc = tcase_create("0 - Empty"); void (*simple_setup)(void); simple_setup = threading ? simple_thread_setup : simple_threadless_setup; tcase_add_checked_fixture(tc, simple_setup, simple_teardown); tcase_add_test(tc, empty); return tc; } /* ====================================================================== */ void check_simple_cases(Suite *suite, int threading) { suite_add_tcase(suite, subscribe_tcase(threading)); suite_add_tcase(suite, fetch_tcase(threading)); suite_add_tcase(suite, notifier_tcase(threading)); suite_add_tcase(suite, message_tcase(threading)); if (0) /* Template */ suite_add_tcase(suite, empty_tcase(threading)); } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/nua.c000066400000000000000000000676611223300710500213040ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2006 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@internal @file nua.c High-Level User Agent Library - "nua" Implementation. * * @author Pekka Pessi * @author Kai Vehmanen * @author Pasi Rinne-Rahkola * * @date Created: Wed Feb 14 18:32:58 2001 ppessi */ #include "config.h" #include #include #include #include #define SU_LOG (nua_log) #include #define SU_ROOT_MAGIC_T struct nua_s #include #include #include #include "sofia-sip/nua.h" #include "sofia-sip/nua_tag.h" #include "nua_stack.h" #include #include #include #include #include /* From AM_INIT/AC_INIT in our "config.h" */ char const nua_version[] = VERSION; /**Environment variable determining the debug log level for @nua module. * * The NUA_DEBUG environment variable is used to determine the debug logging * level for @nua module. The default level is 3. * * @sa , nua_log, SOFIA_DEBUG */ extern char const NUA_DEBUG[]; #ifndef SU_DEBUG #define SU_DEBUG 3 #endif /**Debug log for @nua module. * * The nua_log is the log object used by @nua module. The level of * #nua_log is set using #NUA_DEBUG environment variable. */ su_log_t nua_log[] = { SU_LOG_INIT("nua", "NUA_DEBUG", SU_DEBUG) }; /**Create a @nua agent. * * This function creates a Sofia-SIP User Agent stack object (@nua) and * initializes its parameters by given tagged values. * * @param root Pointer to a root object * @param callback Pointer to event callback function * @param magic Pointer to callback context * @param tag,value,... List of tagged parameters * * @retval !=NULL a pointer to a @nua stack object * @retval NULL upon an error * * @par Related tags: * - NUTAG_PROXY(), giving the URI of the outbound proxy * (but see also NUTAG_INITIAL_ROUTE()). * - NUTAG_URL() (and NUTAG_SIPS_URL(), listing URIs describing * transports) * - NUTAG_CERTIFICATE_DIR(), specifying the location of the * root and client/server certificate files * - NUTAG_SIP_PARSER(), providing customized parser used to * parse received SIP messages * - All parameter tags, listed with nua_set_params() * - All NTATAG_* are passed to NTA documented in : * see NTATAG_EXTRA_100(), * - All tport tags are passed to tport. * They are documented in * - All SOATAG_* are passed to the default SOA (media session) object which * is created by nua_create() unless NUTAG_MEDIA_ENABLE(0) is included in * the tag list * - STUN tags STUNTAG_DOMAIN(), STUNTAG_SERVER(). * STUN is deprecated, however. * * @note * From the @VERSION_1_12_2 all the nua_set_params() tags are processed. * Previously all nutags except NUTAG_SOA_NAME() and NUTAG_MEDIA_ENABLE() * were ignored. * * @note * Both the NUTAG_URL() and NUTAG_SIPS_URL() are used to pass arguments to * nta_agent_add_tport(). * * @par Events: * none * * @sa nua_shutdown(), nua_destroy(), nua_handle(), nta_agent_create(). */ nua_t *nua_create(su_root_t *root, nua_callback_f callback, nua_magic_t *magic, tag_type_t tag, tag_value_t value, ...) { nua_t *nua = NULL; enter; if (callback == NULL) return (void)(errno = EFAULT), NULL; if (root == NULL) return (void)(errno = EFAULT), NULL; if ((nua = su_home_new(sizeof(*nua)))) { ta_list ta; su_home_threadsafe(nua->nua_home); nua->nua_api_root = root; ta_start(ta, tag, value); nua->nua_args = tl_adup(nua->nua_home, ta_args(ta)); su_task_copy(nua->nua_client, su_root_task(root)); /* XXX: where to put this in the nua_server case? */ #if HAVE_SMIME /* Start NRC Boston */ nua->sm = sm_create(); #endif /* End NRC Boston */ #ifndef NUA_SERVER if (su_clone_start(root, nua->nua_clone, nua, nua_stack_init, nua_stack_deinit) == SU_SUCCESS) { su_task_copy(nua->nua_server, su_clone_task(nua->nua_clone)); nua->nua_callback = callback; nua->nua_magic = magic; } else { su_home_unref(nua->nua_home); nua = NULL; } #endif ta_end(ta); } return nua; } /* nua_shutdown() is documented with nua_stack_shutdown() */ void nua_shutdown(nua_t *nua) { enter; if (nua) nua->nua_shutdown_started = 1; nua_signal(nua, NULL, NULL, nua_r_shutdown, 0, NULL, TAG_END()); } /** Destroy the @nua stack. * * Before calling nua_destroy() the application * should call nua_shutdown and wait for successful #nua_r_shutdown event. * Shuts down and destroys the @nua stack. Ongoing calls, registrations, * and subscriptions are left as they are. * * @param nua Pointer to @nua stack object * * @return * nothing * * @par Related tags: * none * * @par Events: * none * * @sa nua_shutdown(), nua_create(), nua_handle_destroy(), nua_handle_unref() */ void nua_destroy(nua_t *nua) { enter; if (nua) { if (!nua->nua_shutdown_final) { SU_DEBUG_0(("nua_destroy(%p): FATAL: nua_shutdown not completed\n", (void *)nua)); assert(nua->nua_shutdown); return; } nua->nua_callback = NULL; su_task_deinit(nua->nua_server); su_task_deinit(nua->nua_client); su_clone_wait(nua->nua_api_root, nua->nua_clone); #if HAVE_SMIME /* Start NRC Boston */ sm_destroy(nua->sm); #endif /* End NRC Boston */ su_home_unref(nua->nua_home); } } /** Fetch callback context from nua. * * @param nua Pointer to @nua stack object * * @return Callback context pointer. * * @NEW_1_12_4. */ nua_magic_t *nua_magic(nua_t *nua) { return nua ? nua->nua_magic : NULL; } /** Obtain default operation handle of the @nua stack object. * * A default operation can be used for operations where the * ultimate result is not important or can be discarded. * * @param nua Pointer to @nua stack object * * @retval !=NULL Pointer to @nua operation handle * @retval NULL No default operation exists * * @par Related tags: * none * * @par Events: * none * */ nua_handle_t *nua_default(nua_t *nua) { return nua ? nua->nua_handles : NULL; } /** Create an operation handle * * Allocates a new operation handle and associated storage. * * @param nua Pointer to @nua stack object * @param hmagic Pointer to callback context * @param tag, value, ... List of tagged parameters * * @retval !=NULL Pointer to operation handle * @retval NULL Creation failed * * @par Related tags: * Duplicates the provided tags for use with every operation. Note that * NUTAG_URL() is converted to SIPTAG_TO() if there is no SIPTAG_TO(). * And also vice versa, request-URI is taken from SIPTAG_TO() if there * is no NUTAG_URL(). Note that certain SIP headers cannot be saved with * the handle. They include @ContentLength, @CSeq, @RSeq, @RAck, and * @Timestamp. * * @par * nua_handle() accepts all the tags accepted by nua_set_hparams(), too. * * * @par Events: * none * * @sa nua_handle_bind(), nua_handle_destroy(), nua_handle_ref(), * nua_handle_unref(). */ nua_handle_t *nua_handle(nua_t *nua, nua_hmagic_t *hmagic, tag_type_t tag, tag_value_t value, ...) { nua_handle_t *nh = NULL; if (nua) { ta_list ta; ta_start(ta, tag, value); nh = nh_create_handle(nua, hmagic, ta_args(ta)); if (nh) nh->nh_ref_by_user = 1; ta_end(ta); } return nh; } /** Bind a callback context to an operation handle. * * @param nh Pointer to operation handle * @param hmagic Pointer to callback context * * @return * nothing * * @par Related tags: * none * * @par Events: * none */ void nua_handle_bind(nua_handle_t *nh, nua_hmagic_t *hmagic) { enter; if (NH_IS_VALID(nh)) nh->nh_magic = hmagic; } /** Fetch a callback context from an operation handle. * * @param nh Pointer to operation handle * * @return * Pointer to callback context * * @par Related tags: * none * * @par Events: * none * * @NEW_1_12_4. */ nua_hmagic_t *nua_handle_magic(nua_handle_t *nh) { nua_hmagic_t *magic = NULL; enter; if (NH_IS_VALID(nh)) magic = nh->nh_magic; return magic; } /* ---------------------------------------------------------------------- */ /** Check if operation handle is used for INVITE * * Check if operation handle has been used with either outgoing or incoming * INVITE request. * * @param nh Pointer to operation handle * * @retval 0 no invite in operation or operation handle is invalid * @retval 1 operation has invite * * @par Related tags: * none * * @par Events: * none */ int nua_handle_has_invite(nua_handle_t const *nh) { return nh ? nh->nh_has_invite : 0; } /**Check if operation handle has active event subscriptions. * * Active subscription can be established either by nua_subscribe() or * nua_refer() calls. * * @param nh Pointer to operation handle * * @retval 0 no event subscriptions in operation or * operation handle is invalid * @retval !=0 operation has event subscriptions * * @par Related tags: * none * * @par Events: * none */ int nua_handle_has_events(nua_handle_t const *nh) { return nh ? nh->nh_ds->ds_has_events : 0; } /** Check if operation handle has active registrations * * A registration is active when either when a REGISTER operation is going * on or when it has successfully completed so that @nua stack is expected to * refresh the registration in the future. Normally, a handle has active * registration after nua_register() until nua_unregister() completes, * unless the initial nua_register() had either expiration time of 0 or it * had SIPTAG_CONTACT(NULL) as an argument. * * @param nh Pointer to operation handle * * @retval 0 no active registration in operation or * operation handle is invalid * @retval 1 operation has registration * * @par Related tags: * none * * @par Events: * none * * @sa nua_register(), nua_unregister(), #nua_r_register, #nua_r_unregister */ int nua_handle_has_registrations(nua_handle_t const *nh) { return nh && nh->nh_ds->ds_has_register; } /** Check if operation handle has been used with outgoing SUBSCRIBE of REFER request. * * @param nh Pointer to operation handle * * @retval 0 no active subscription in operation or * operation handle is invalid * @retval 1 operation has subscription. * * @par Related tags: * none * * @par Events: * none */ int nua_handle_has_subscribe(nua_handle_t const *nh) { return nh ? nh->nh_has_subscribe : 0; } /** Check if operation handle has been used with nua_register() or nua_unregister(). * * @param nh Pointer to operation handle * * @retval 0 no active register in operation or operation handle is invalid * @retval 1 operation has been used with nua_register() or nua-unregister() * * @par Related tags: * none * * @par Events: * none */ int nua_handle_has_register(nua_handle_t const *nh) { return nh ? nh->nh_has_register : 0; } /** Check if operation handle has an active call * * @param nh Pointer to operation handle * * @retval 0 no active call in operation or operation handle is invalid * @retval 1 operation has established call or pending call request. * * @par Related tags: * none * * @par Events: * none */ int nua_handle_has_active_call(nua_handle_t const *nh) { return nh ? nh->nh_active_call : 0; } /** Check if operation handle has a call on hold * * Please note that this status is not affected by remote end putting * this end on hold. Remote end can put each media separately on hold * and status is reflected on SOATAG_ACTIVE_AUDIO(), SOATAG_ACTIVE_VIDEO() * and SOATAG_ACTIVE_CHAT() tag values in #nua_i_state event. * * @param nh Pointer to operation handle * * @retval 0 if no call on hold in operation or operation handle is invalid * @retval 1 if operation has call on hold, for example nua_invite() or * nua_update() has been called with SOATAG_HOLD() with non-NULL * argument. * * @par Related tags: * none * * @par Events: * none */ int nua_handle_has_call_on_hold(nua_handle_t const *nh) { return nh ? nh->nh_hold_remote : 0; } /** Get the remote address (From/To header) of operation handle * * Remote address is used as To header in outgoing operations and * derived from From: header in incoming operations. * * @param nh Pointer to operation handle * * @retval NULL no remote address for operation or operation handle invalid * @retval !=NULL pointer to remote address for operation * * @par Related tags: * none * * @par Events: * none */ sip_to_t const *nua_handle_remote(nua_handle_t const *nh) { return nh ? nh->nh_ds->ds_remote : NULL; } /** Get the local address (From/To header) of operation handle * * Local address is used as From header in outgoing operations and * derived from To: header in incoming operations. * * @param nh Pointer to operation handle * * @retval NULL no local address for operation or operation handle invalid * @retval !=NULL pointer to local address for operation * * @par Related tags: * none * * @par Events: * none */ sip_to_t const *nua_handle_local(nua_handle_t const *nh) { return nh ? nh->nh_ds->ds_local : NULL; } /* Documented with nua_stack_set_params() */ void nua_set_params(nua_t *nua, tag_type_t tag, tag_value_t value, ...) { ta_list ta; ta_start(ta, tag, value); enter; nua_signal(nua, NULL, NULL, nua_r_set_params, 0, NULL, ta_tags(ta)); ta_end(ta); } /* Documented with nua_stack_get_params() */ void nua_get_params(nua_t *nua, tag_type_t tag, tag_value_t value, ...) { ta_list ta; ta_start(ta, tag, value); enter; nua_signal(nua, NULL, NULL, nua_r_get_params, 0, NULL, ta_tags(ta)); ta_end(ta); } #define NUA_SIGNAL(nh, event, tag, value) \ enter; \ if (NH_IS_VALID((nh))) { \ ta_list ta; \ ta_start(ta, tag, value); \ nua_signal((nh)->nh_nua, nh, NULL, event, 0, NULL, ta_tags(ta)); \ ta_end(ta); \ } \ else { \ SU_DEBUG_1(("nua: " #event " with invalid handle %p\n", (void *)nh)); \ } /* Documented with nua_stack_set_params() */ void nua_set_hparams(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { NUA_SIGNAL(nh, nua_r_set_params, tag, value); } /* Documented with nua_stack_get_params() */ void nua_get_hparams(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { NUA_SIGNAL(nh, nua_r_get_params, tag, value); } /* Documented with nua_stack_register() */ void nua_register(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { NUA_SIGNAL(nh, nua_r_register, tag, value); } void nua_unregister(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { NUA_SIGNAL(nh, nua_r_unregister, tag, value); } /* Documented with nua_stack_invite() */ void nua_invite(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { NUA_SIGNAL(nh, nua_r_invite, tag, value); } /* Documented with nua_stack_ack() */ void nua_ack(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { NUA_SIGNAL(nh, nua_r_ack, tag, value); } /* Documented with nua_stack_bye() */ void nua_bye(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { NUA_SIGNAL(nh, nua_r_bye, tag, value); } /* Documented with nua_stack_cancel() */ void nua_cancel(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { NUA_SIGNAL(nh, nua_r_cancel, tag, value); } /* Documented with nua_stack_options() */ void nua_options(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { NUA_SIGNAL(nh, nua_r_options, tag, value); } /* Documented with nua_stack_message() */ void nua_message(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { NUA_SIGNAL(nh, nua_r_message, tag, value); } /* Documented with nua_stack_method() */ void nua_method(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { NUA_SIGNAL(nh, nua_r_method, tag, value); } /** Send a chat message. * * A chat channel can be established during call setup using "message" media. * An active chat channel is indicated using #nua_i_state event containing * SOATAG_ACTIVE_CHAT() tag. Chat messages can be sent using this channel with * nua_chat() function. Currently this is implemented using SIP MESSAGE * requests but in future MSRP (message session protocol) will replace it. * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Related Tags: * SIPTAG_CONTENT_TYPE() \n * SIPTAG_PAYLOAD() \n * SIPTAG_FROM() \n * SIPTAG_TO() \n * Use of other SIP tags is deprecated * * @par Events: * #nua_r_chat */ void nua_chat(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { NUA_SIGNAL(nh, nua_r_chat, tag, value); } /* Documented with nua_stack_subscribe() */ void nua_subscribe(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { NUA_SIGNAL(nh, nua_r_subscribe, tag, value); } /* Documented with nua_stack_subscribe() */ void nua_unsubscribe(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { NUA_SIGNAL(nh, nua_r_unsubscribe, tag, value); } /* Documented with nua_stack_notify() */ void nua_notify(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { NUA_SIGNAL(nh, nua_r_notify, tag, value); } /* nua_r_notify is documented with process_response_to_notify() */ /** Create an event server. * * This function create an event server taking care of sending NOTIFY * requests and responding to further SUBSCRIBE requests. The event * server can accept multiple subscriptions from several sources and * takes care for distributing the notifications. Unlike other functions * this call only accepts the SIP tags listed below. * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Related Tags: * NUTAG_URL() \n * SIPTAG_EVENT() or SIPTAG_EVENT_STR() \n * SIPTAG_CONTENT_TYPE() or SIPTAG_CONTENT_TYPE_STR() \n * SIPTAG_PAYLOAD() or SIPTAG_PAYLOAD_STR() \n * SIPTAG_ACCEPT() or SIPTAG_ACCEPT_STR() \n * * @par Events: * #nua_r_notify */ void nua_notifier(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { NUA_SIGNAL(nh, nua_r_notifier, tag, value); } /** Terminate an event server. * * Terminate an event server with matching event and content type. The event * server was created earlier with nua_notifier() function. * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Related Tags: * SIPTAG_EVENT() \n * SIPTAG_CONTENT_TYPE() \n * SIPTAG_PAYLOAD() \n * NEATAG_REASON() * * @par Events: * #nua_r_terminate * * @sa nua_notifier(), nua_authorize(). */ void nua_terminate(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { NUA_SIGNAL(nh, nua_r_terminate, tag, value); } /* Documented with nua_stack_refer() */ void nua_refer(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { NUA_SIGNAL(nh, nua_r_refer, tag, value); } /* Documented with nua_stack_publish() */ void nua_publish(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { NUA_SIGNAL(nh, nua_r_publish, tag, value); } /* Documented with nua_stack_publish() */ void nua_unpublish(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { NUA_SIGNAL(nh, nua_r_unpublish, tag, value); } /* Documented with nua_stack_info() */ void nua_info(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { NUA_SIGNAL(nh, nua_r_info, tag, value); } /* Documented with nua_stack_prack() */ void nua_prack(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { NUA_SIGNAL(nh, nua_r_prack, tag, value); } /* Documented with nua_stack_update() */ void nua_update(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { NUA_SIGNAL(nh, nua_r_update, tag, value); } /** Authenticate an operation. * * - 401 / 407 response with www-authenticate header/ proxy-authenticate header * - application should provide stack with username&password for each realm * with NUTAG_AUTH() tag * - restarts operation * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Related Tags: * NUTAG_AUTH() * * @par Events: * (any operation events) */ void nua_authenticate(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { NUA_SIGNAL(nh, nua_r_authenticate, tag, value); } /** Authorize a subscriber. * * After creating a local presence server by nua_notifier(), an incoming * SUBSCRIBE request causes #nua_i_subscription event. Each subscriber is * identified with NEATAG_SUB() tag in the #nua_i_subscription event. * Application can either authorize the subscriber with * NUTAG_SUBSTATE(#nua_substate_active) or terminate the subscription with * NUTAG_SUBSTATE(#nua_substate_terminated). * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Related Tags: * NEATAG_SUB() \n * NUTAG_SUBSTATE() * * @par Events: * #nua_i_subscription * * @sa nua_notifier(), nua_terminate() */ void nua_authorize(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { NUA_SIGNAL(nh, nua_r_authorize, tag, value); } /*# Redirect an operation. */ void nua_redirect(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { NUA_SIGNAL(nh, nua_r_redirect, tag, value); } /* Documented with nua_stack_respond() */ void nua_respond(nua_handle_t *nh, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...) { enter; if (NH_IS_VALID(nh)) { ta_list ta; ta_start(ta, tag, value); nua_signal(nh->nh_nua, nh, NULL, nua_r_respond, status, phrase, ta_tags(ta)); ta_end(ta); } else { SU_DEBUG_1(("nua: respond with invalid handle %p\n", (void *)nh)); } } /** Destroy a handle * * Terminate the protocol state associated with an operation handle. The * stack discards resources and terminates the ongoing dialog usage, * sessions and transactions associated with this handle. For example, calls * are terminated with BYE request. Also, the reference count for the handle * is also decremented. * * The handles use reference counting for memory management. In order to * make it more convenient for programmer, nua_handle_destroy() decreases * the reference count, too. * * @param nh Pointer to operation handle * * @return * nothing * * @par Related Tags: * none * * @par Events: * none * * @sa nua_handle(), nua_handle_bind(), nua_handle_ref(), nua_handle_unref(), * nua_unregister(), nua_unpublish(), nua_unsubscribe(), nua_bye(). */ void nua_handle_destroy(nua_handle_t *nh) { enter; if (NH_IS_VALID(nh) && !NH_IS_DEFAULT(nh)) { nh->nh_valid = NULL; /* Events are no more delivered to appl. */ nua_signal(nh->nh_nua, nh, NULL, nua_r_destroy, 0, NULL, TAG_END()); } } /* ---------------------------------------------------------------------- */ struct nua_stack_handle_make_replaces_args { sip_replaces_t *retval; nua_handle_t *nh; su_home_t *home; int early_only; }; static int nua_stack_handle_make_replaces_call(void *arg) { struct nua_stack_handle_make_replaces_args *a = arg; a->retval = nua_stack_handle_make_replaces(a->nh, a->home, a->early_only); return 0; } /**Generate a @Replaces header for handle. * * A @Replaces header contains the @CallID value, @From and @To tags * corresponding to SIP dialog associated with handle @a nh. Note that the * @Replaces matches with dialog of the remote peer, * nua_handle_by_replaces() does not return same handle (unless you swap * rp_from_tag and rp_to_tag in @Replaces header). * * A @Replaces header is used in attended transfer, among other things. * * @param nh pointer to operation handle * @param home memory home used to allocate the header * @param early_only if true, include "early-only" parameter in @Replaces, too * * @return A newly created @Replaces header. * * @since New in @VERSION_1_12_4. * * @sa nua_handle_by_replaces(), @Replaces, @RFC3891, @RFC3515, nua_refer(), * #nua_i_refer(), @ReferTo, nta_leg_make_replaces(), * sip_headers_as_url_query() */ sip_replaces_t *nua_handle_make_replaces(nua_handle_t *nh, su_home_t *home, int early_only) { if (nh && nh->nh_valid && nh->nh_nua) { #if HAVE_OPEN_C struct nua_stack_handle_make_replaces_args a = { NULL, NULL, NULL, 0 }; a.nh = nh; a.home = home; a.early_only = early_only; #else struct nua_stack_handle_make_replaces_args a = { NULL, nh, home, early_only }; #endif if (su_task_execute(nh->nh_nua->nua_server, nua_stack_handle_make_replaces_call, (void *)&a, NULL) == 0) { return a.retval; } } return NULL; } struct nua_stack_handle_by_replaces_args { nua_handle_t *retval; nua_t *nua; sip_replaces_t const *r; }; static int nua_stack_handle_by_replaces_call(void *arg) { struct nua_stack_handle_by_replaces_args *a = arg; a->retval = nua_stack_handle_by_replaces(a->nua, a->r); return 0; } struct nua_stack_handle_by_call_id_args { nua_handle_t *retval; nua_t *nua; const char *call_id; }; static int nua_stack_handle_by_call_id_call(void *arg) { struct nua_stack_handle_by_call_id_args *a = arg; a->retval = nua_stack_handle_by_call_id(a->nua, a->call_id); return 0; } /** Obtain a new reference to an existing handle based on @Replaces header. * * @since New in @VERSION_1_12_4. * * @note * You should release the reference with nua_handle_unref() when you are * done with the handle. * * @sa nua_handle_make_replaces(), @Replaces, @RFC3891, nua_refer(), * #nua_i_refer, @ReferTo, nta_leg_by_replaces() */ nua_handle_t *nua_handle_by_replaces(nua_t *nua, sip_replaces_t const *r) { if (nua) { #if HAVE_OPEN_C struct nua_stack_handle_by_replaces_args a; a.retval = NULL; a.nua = nua; a.r = r; #else struct nua_stack_handle_by_replaces_args a = { NULL, nua, r }; #endif if (su_task_execute(nua->nua_server, nua_stack_handle_by_replaces_call, (void *)&a, NULL) == 0) { nua_handle_t *nh = a.retval; if (nh && !NH_IS_DEFAULT(nh) && nh->nh_valid) return nua_handle_ref(nh); } } return NULL; } /** Obtain a new reference to an existing handle based on @CallID. * * @since New in @VERSION_1_12_9. * * @note * You should release the reference with nua_handle_unref() when you are * done with the handle. * * @sa nua_handle_make_replaces(), @Replaces, @RFC3891, nua_refer(), * #nua_i_refer, @ReferTo, nta_leg_by_replaces() */ nua_handle_t *nua_handle_by_call_id(nua_t *nua, const char *call_id) { if (nua) { #if HAVE_OPEN_C struct nua_stack_handle_by_call_id_args a; a.retval = NULL; a.nua = nua; a.call_id = call_id; #else struct nua_stack_handle_by_call_id_args a = { NULL, nua, call_id }; #endif if (su_task_execute(nua->nua_server, nua_stack_handle_by_call_id_call, (void *)&a, NULL) == 0) { nua_handle_t *nh = a.retval; if (nh && !NH_IS_DEFAULT(nh) && nh->nh_valid) return nua_handle_ref(nh); } } return NULL; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/nua.docs000066400000000000000000002517131223300710500220030ustar00rootroot00000000000000/* -*- text -*- */ /**@MODULEPAGE "nua" - High-Level User Agent Module @section nua_meta Module Meta Information The @b nua module contains the user-agent library taking care of basic SIP User Agent functions. Its functionality includes call management, messaging and event retrieval. @CONTACT Pekka Pessi @STATUS @SofiaSIP Core library @LICENSE LGPL @par Contributor(s): - Pekka Pessi - Pasi Rinne-Rahkola - Kai Vehmanen - Martti Mela @section nua_overview Overview The NUA API gives the high-level application programmer transparent and full control to the SIP protocol enginebelow it. NUA provides the call semantics on top of existing transaction semantics found in nta module. With NUA it is possible to create different kind of SIP User Agents, like terminals, gateways or MCUs. The @b nua engine hides many low-level signaling and media management aspects from the application programmer. It is possible to use different kind of media interfaces - even remote ones - in a fully transparent way. The application and the protocol engine within User Agent library can be run in separate threads. The protocol engine communicates with the application using @ref nua_event_e "events", delivered to the application with a a callback function. The callback function is called within the thread context of the application, represented with a #su_root_t object. @section nua_concepts_user Sofia Concepts for NUA User @subsection nua_intro Introduction The Sofia software suite is based on certain basic ideas and concepts that are used in all levels of Sofia software. Many of those are implemented in Sofia utility library (su) providing unified interface to the most important OS services and utilities . The following sections contain descriptions of the concepts that a user of NUA library must understand to create a working application. The other utilities (in the SU library and other libraries of Sofia software suite) might also be useful for an application developer but one must be careful when using them because they might change the behavior of the Sofia software suite in a way that causes NUA library to work incorrectly. See [su] for more detailed description of the SU services. @subsection nua_root Event loop - root object The NUA uses the reactor pattern (also known as dispatcher pattern and notifier pattern) for event driven systems (see [Using Design Patterns to Develop Reusable Object-oriented Communication Software, D.C. Schmidt, CACM October '95, 38(10): 65-74]). Sofia uses a task as basic execution unit for the programming model. According to the model, the program can ask that the event loop invokes a callback function when a certain event occurs. Such events include I/O activity, timers or a asynchronously delivered messages from other task. The root object is a handle representing the task in the application. Another way of seeing the same thing is that the root object represents the main event loop of the task. Through the root object the task code can access its context information (magic) and thread-synchronization features like wait objects, timers, and messages. An application using NUA services must create a root object and the callback routine to handle @ref nua_event_e "NUA events". The root object is created with su_root_create() function and the callback routine is registered with nua_create() function. Root object has type #su_root_t. See documentation of and for more information of root object. See section #nua_event_e for more information of the callback function. @subsection nua_magic Magic The magic is a term used for the context pointer that can be bound to various objects in Sofia stack (for example root object and operation handle) by the application code. This context pointer is passed back to the application code when a registered callback function is called by the main event loop. The Sofia stack retains the context information between calls to the callback function. An application can use the context information to store any information it needs for processing the events. @subsection nua_memmgmt Memory Handling The home-based memory management is useful when a lot of memory blocks are allocated for given task. The allocations are done via the memory home, which keeps a reference to each allocated memory block. When the memory home is then freed, it will free all memory blocks to which it has reference. This simplifies application logic because application code does not need to keep track of the allocated memory and free every allocated block separately. An application using NUA services can use the memory management services provided by the SU library but it is not mandatory. See documentation of for more information of memory management services. @subsection nua_tags Tags Tagging is the mechanism used in Sofia software for packing parameters to functions. It enables passing a variable number of parameters having non-fixed types. For an application programmer the tagging is visible as macros that are used to encapsulate the passed parameters. When evaluated a tagging macro creates a structure that contains a tag (telling what is the type of a parameter) and a value (pointer to opaque data). By checking the tag the layers of Sofia software check whether they can handle the parameter or should it just be passed to lower layers for processing. There are some tags with special meaning: - TAG_NULL() (synonymous to TAG_END()) end of tag list - TAG_SKIP() empty tag item - TAG_NEXT() tag item pointing to another tag list, ends the current tag list - TAG_ANY() filter tag accepting any tag - TAG_IF() conditional inclusion of tag item The NUA functions can be called with a list of tagged values if they have following parameters at the end of parameter list: @code tag_type_t tag, tag_value_t value, ...); @endcode The last tagged value on the parameter list must be TAG_NULL() (or TAG_END(), synonym for TAG_NULL()). Every tag has two versions: \n NUTAG_ \n which takes a value parameter and \n NUTAG__REF \n which takes a reference parameter. The latter is used with tl_gets() function to retrieve tag values from tag list. For SIP headers there exists also additional version of tags: \n SIPTAG__STR \n This tag version takes a C-language character string as parameter. The corresponding tag without _STR suffix takes a parsed value structure as parameter. The following is an example of call to NUA function containing tagged values: @code nua_unregister(op->op_handle, TAG_IF(use_registrar, NUTAG_REGISTRAR(registrar)), SIPTAG_CONTACT_STR("*"), SIPTAG_EXPIRES_STR("0"), TAG_NULL()); @endcode An application using NUA services must use tagged arguments for passing the parameters to functions. See nua_invite() for discussion on how a SIP message is constructed from the tags. See documentation of for more information of tags and the module-specific documentation of each Sofia module for information of tags specific for that module. @subsection nua_debugandlogging Debugging and Logging The modules of Sofia stack contain configurable debugging and logging functionality based on the services defined in . The debugging and logging details (for example level of details on output and output file name) can be configured by environment variables, directives in configuration files and compilation directives in the source files. Examples of useful directives/ environment variables are: - #SOFIA_DEBUG Default debug level (0..9) - #NUA_DEBUG NUA debug level (0..9) - #NTA_DEBUG Transaction engine debug level (0..9) - #TPORT_DEBUG Transport event debug level (0..9) - #TPORT_LOG If set, print out all parsed SIP messages on transport layer - #TPORT_DUMP Filename for dumping unparsed messages from transport The defined debug output levels are: - 0 fatal errors, panic - 1 critical errors, minimal progress at subsystem level - 2 non-critical errors - 3 warnings, progress messages - 5 signaling protocol actions (incoming packets, ...) - 7 media protocol actions (incoming packets, ...) - 9 entering/exiting functions, very verbatim progress An application using NUA services can also use the debugging and logging services provided by the Sofia stack but it is not mandatory. See documentation of for more information of debugging and logging services. @section nua_concepts NUA Concepts @subsection nua_stackobject NUA Stack Object Stack object represents an instance of SIP stack and media engine. It contains reference to root object of that stack, user-agent-specific settings, and reference to the SIP transaction engine, for example. A NUA stack object is created by nua_create() function and deleted by nua_destroy() function. The nua_shutdown() function is used to gracefully release active the sessions by @b nua engine. NUA stack object has type nua_t. @subsection nua_operationhandle NUA Operation Handle Operation handle represents an abstract SIP call/session. It contains information of SIP dialog and media session, and state machine that takes care of the call, high-level SDP offer-answer protocol, registration, subscriptions, publications and simple SIP transactions. An operation handle may contain list of tags used when SIP messages are created by NUA (e.g. From and To headers). An operation handle is created explicitly by the application using NUA for sending messages (function nua_handle()) and by stack for incoming calls/sessions (starting with INVITE or MESSAGE). The handle is destroyed by the application using NUA (function nua_handle_destroy()). Indication and response events are associated with an operation handle. NUA operation handle has type nua_handle_t. @subsection nua_stacktread Stack Thread and Message Passing Concepts The stack thread is a separate thread from application that provides the real-time protocol stack operations so that application thread can for example block or redraw UI as it likes. The communication between stack thread and application thread is asynchronous. Most of the NUA API functions cause a send of a message to the stack thread for processing and similarly when something happens in the stack thread it sends a message to the application thread. The messages to the application thread are delivered as invokes of the application callback function when the application calls su_root_run() or su_root_step() function. @subsection nua_sip_message SIP Message and Header Manipulation SIP messages are manipulated with typesafe SIPTAG_ tags. There are three versions of each SIP tag: - SIPTAG_() takes a parsed value as parameter. - SIPTAG__STR() takes an unparsed string as parameter. - SIPTAG__REF() takes a reference as parameter, is used with tl_gets() function to retrieve tag values from tag list. - SIPTAG___STR_REF() takes a reference as parameter, is used with tl_gets() function to retrieve string tag values from tag list. For example a header named "Example" would have tags names SIPTAG_EXAMPLE(), SIPTAG_EXAMPLE_STR(), and SIPTAG_EXAMPLE_REF(). When tags are used in NUA calls the corresponding headers are added to the message. In case the header can be present only once in a message and there already exists a value for the header the value given by tag replaces the existing header value. Passing tag value NULL has no effect on headers. Passing tag value (void *)-1 removes corresponding headers from the message. For example: - sending a SUBSCRIBE with @b Event: header and two @b Accept: headers: @code nua_subscribe(nh, SIPTAG_EVENT_STR("presence"), SIPTAG_ACCEPT(accept1), SIPTAG_ACCEPT(accept2), TAG_END()); @endcode - fetching tag values when processing nua_r_subscribe event: @code sip_accept_t *ac = NULL; sip_event_t *o = NULL; tl_gets(tl, SIPTAG_EVENT_REF(o), /* _REF takes a reference! */ SIPTAG_ACCEPT_REF(ac), TAG_END()); @endcode @section nua_tutorial SIP/NUA tutorial This section describes basic usage scenarios of NUA/Sofia stack using message sequence charts. @subsection nua_outgoingcall Outgoing Call @image latex SIP_outgoing_call.eps @image html SIP_outgoing_call.gif @subsection nua_incomingcall Incoming Call @image latex SIP_incoming_call.eps @image html SIP_incoming_call.gif @subsection nua_basicoutgoingoperation Basic Outgoing Operation @image latex SIP_basic_outgoing_operation.eps @image html SIP_basic_outgoing_operation.gif @subsection nua_basicincomingoperation Basic Incoming Operation @image latex SIP_basic_incoming_operation.eps @image html SIP_basic_incoming_operation.gif @subsection nua_outgoingoperationwithauth Outgoing Operation with Authentication @image latex SIP_outgoing_operation_with_auth.eps @image html SIP_outgoing_operation_with_auth.gif @section nua_simpleapplication Simple Application The following sections will present code examples from a simple application that uses services of NUA. The example is not complete but should present all relevant details of the basic use of NUA. On sourceforge.net there is available an example application sofisip_cli.c that can be studied for more complete example. @subsection nua_datastructures Data Structures & Defines An application using services of NUA normally defines data areas that are used to store context information (i.e., "magic"). The types of pointers to these context information areas are passed to NUA by defines. @code /* type for application context data */ typedef struct application application; #define NUA_MAGIC_T application /* type for operation context data */ typedef union oper_ctx_u oper_ctx_t; #define NUA_HMAGIC_T oper_ctx_t @endcode The information area contents themselves can be defined as C structures or unions: @code /* example of application context information structure */ typedef struct application { su_home_t home[1]; /* memory home */ su_root_t *root; /* root object */ nua_t *nua; /* NUA stack object */ /* other data as needed ... */ } application; /* Example of operation handle context information structure */ typedef union operation { nua_handle_t *handle; /* operation handle / struct { nua_handle_t *handle; /* operation handle / ... /* call-related information */ } call; struct { nua_handle_t *handle; /* operation handle / ... /* subscription-related information */ } subscription; /* other data as needed ... */ } operation; @endcode NUA stack object and handle are opaque to the application programmer. Likewise, the application context is completely opaque to the NUA stack module. NUA functions are passed a pointer, and that pointer is then given back to the application within the callback parameters. In this case the application context information structure is also used to store a root object and memory home for memory handling. The application context information also contains the NUA stack object information. @subsection nua_initanddeinit Initialization and deinitialization The following code is an example of application function that initializes the system, enters the main loop for processing the messages, and, after message processing is ended, deinitalizes the system. If the application is not just responding to incoming SIP messages there must also be means to send messages to NUA. This can be handled for example by having a separate thread that calls NUA functions to send messages or by having a socket connection to the application for sending commands to the application (see documentation of su_wait_create() and su_root_register()). @code /* Application context structure */ application appl[1] = {{{{(sizeof appl)}}}}; /* initialize system utilities */ su_init(); /* initialize memory handling */ su_home_init(appl->home); /* initialize root object */ appl->root = su_root_create(appl); if (appl->root != NULL) { /* create NUA stack */ appl->nua = nua_create(appl->root, app_callback, appl, /* tags as necessary ...*/ TAG_NULL()); if (appl->nua != NULL) { /* set necessary parameters */ nua_set_params(appl->nua, /* tags as necessary ... */ TAG_NULL()); /* enter main loop for processing of messages */ su_root_run(appl->root); /* destroy NUA stack */ nua_destroy(appl->nua); } /* deinit root object */ su_root_destroy(appl->root); appl->root = NULL; } /* deinitialize memory handling */ su_home_deinit(appl->home); /* deinitialize system utilities */ su_deinit(); @endcode @subsection nua_handlingevents Handling events Handling of the events coming from NUA stack is done in the callback function that is registered for NUA stack with the nua_create() function when the application is initialized. The content of callback function is in its simplest form just a switch/case statement that dispatches the incoming events for processing to separate functions. @code void app_callback(nua_event_t event, int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]) { switch (event) { case nua_i_invite: app_i_invite(status, phrase, nua, magic, nh, hmagic, sip, tags); break; case nua_r_invite: app_r_invite(status, phrase, nua, magic, nh, hmagic, sip, tags); break; /* and so on ... */ default: /* unknown event -> print out error message */ if (status > 100) { printf("unknown event %d: %03d %s\n", event, status, phrase); } else { printf("unknown event %d\n", event); } tl_print(stdout, "", tags); break; } } /* app_callback */ @endcode @subsection nua_placeacall Place a call The following three functions show an example of how a basic SIP call is created. The place_a_call() function creates an operation handle and invokes the SIP INVITE method. @code operation *place_a_call(char const *name, url_t const *url) { operation *op; sip_to_t *to; /* create operation context information */ op = su_zalloc(appl->home, (sizeof *op)); if (!op) return NULL; /* Destination address */ to = sip_to_create(NULL, url); if (!to) return NULL; to->a_display = name; /* create operation handle */ op->handle = nua_handle(appl->nua, op, SIPTAG_TO(to), TAG_END()); if (op->handle == NULL) { printf("cannot create operation handle\n"); return NULL; } nua_invite(op->handle, /* other tags as needed ... */ TAG_END()); } /* place_a_call */ @endcode The app_r_invite() function is called by callback function when response to INVITE message is received. Here it is assumed that automatic acknowledge is not enabled so ACK response must be sent explicitly. @code void app_r_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]) { if (status == 200) { nua_ack(nh, TAG_END()); } else { printf("response to INVITE: %03d %s\n", status, phrase); } } /* app_r_invite */ @endcode The nua_i_state event is sent (and app_i_state() function called by callback function) when the call state changes (see @ref nua_uac_call_model "client-side call model"). @code void app_i_state(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]) { nua_callstate_t state = nua_callstate_init; tl_gets(tags, NUTAG_CALLSTATE_REF(state), NUTAG__REF(state), state = (nua_callstate_t)t->t_value; printf("call %s\n", nua_callstate_name(state)); } /* app_i_state */ @endcode @subsection nua_receiveacall Receive a call The app_i_invite() function is called by callback function when incoming INVITE message is received. This example assumes that autoanswer is not enabled so the response must be sent explicitly. @code void app_i_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]) { printf("incoming call\n"); nua_respond(nh, 200, "OK", SOA_USER_SDP(magic->sdp), TAG_END()); } /* app_i_invite */ @endcode The app_i_state() function is called by the callback function when call has been successfully set up and the media has been activated. @code void app_i_active(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]) { printf("call active\n"); } /* app_i_active */ @endcode @subsection nua_terminatingcall Terminating a call The following three functions show an example of how a basic SIP call is terminated. The terminate_call() function sends the SIP BYE message. @code void terminate_call(void) { nua_bye(op->handle, TAG_END()); } /* terminate call */ @endcode The app_r_bye() function is called by the callback function when answer to the BYE message is received. The function destroys the call handle and releases the memory allocated to operation context information. @code void app_r_bye(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]) { if (status < 200) return; printf("call released\n"); /* release operation handle */ nua_handle_destroy(hmagic->handle); op->handle = NULL; /* release operation context information */ su_free(appl->home, hmagic); } /* app_r_bye */ @endcode The app_i_bye() function is called by the callback function when an incoming BYE message is received. The function destroys the call handle and releases the memory allocated to operation context information. @code void app_i_bye(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]) { printf("call released\n"); /* release operation handle */ nua_handle_destroy(hmagic->handle); op->handle = NULL; /* release operation context information */ su_free(appl->home, hmagic); } /* app_i_bye */ @endcode @subsection nua_sendamessage Sending a message The following functions show an example of how a SIP MESSAGE is sent. The send_message() function sends the SIP MESSAGE. @code void send_message(void) { op_t *op; /* create operation context information */ op = su_zalloc(appl->home, sizeof(op_t)); if (op = NULL) { printf("cannot create operation context information\n"); return; } /* how we create destination_address? */ /* create operation handle */ op->handle = nua_handle(appl->nua, op, NUTAG_URL(destination_address), TAG_END()); if (op->handle == NULL) { printf("cannot create operation handle\n"); return; } /* send MESSAGE */ nua_message(op->handle, SIPTAG_CONTENT_TYPE_STR("text/plain"), SIPTAG_PAYLOAD_STR("Hello, world!"), /* other tags as needed ... */ TAG_END()); } /* send_message */ @endcode The app_r_message() function is called by the callback function when answer to the MESSAGE is received. @code void app_r_message(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]) { printf("response to MESSAGE: %03d %s\n", status, phrase); } /* app_r_message */ @endcode @subsection nua_receivemessage Receiving a message The following function shows an example of how a SIP MESSAGE is received. The app_i_message() function is called by the callback function when a SIP MESSAGE is received. @code void app_i_message(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]) { printf("received MESSAGE: %03d %s\n", status, phrase); printf("From: %s%s" URL_PRINT_FORMAT "\n", sip->sip_from->a_display ? sip->sip_from->a_display : "", sip->sip_from->a_display ? " " : "", URL_PRINT_ARGS(sip->sip_from->a_url)); if (sip->sip_subject) { printf("Subject: %s\n", sip->sip_subject->g_value); } if (sip->sip_payload) { fwrite(sip->sip_payload->pl_data, sip->sip_payload->pl_len, 1, stdout); fputs("\n", stdout); } } /* app_i_message */ @endcode @subsection nua_notifier Creating a Presence Server @code ... application_t *app; operation_t *oper; ... oper->app = app; app->nua = nua_create(ssip->s_root, app_callback, app, TAG_NULL()); ... oper->handle = nua_handle(app->nua, app, NUTAG_URL(to->a_url), SIPTAG_TO(to), ta_tags(ta)); ... nua_notifier(oper->handle, SIPTAG_EXPIRES_STR("3600"), SIPTAG_EVENT_STR("presence"), SIPTAG_CONTENT_TYPE_STR("application/pidf-partial+xml"), NUTAG_SUBSTATE(nua_substate_pending), TAG_END()); @endcode After the nua_notifier object -- the presence server -- is created, an event nua_r_notifier is returned. Status and phrase values of the app_callback function indicate the success of the creation. Authorization of an incoming subscription (to the local presence server) can be handled in the callback function. @code void app_callback(nua_event_t event, int status, char const *phrase, nua_t *nua, application_t *app, nua_handle_t *nh, oper_t *op, sip_t const *sip, tagi_t tags[]) { nea_sub_t *subscriber = NULL; switch (event) { case nua_i_subscription: tl_gets(tags, NEATAG_SUB_REF(subscriber), TAG_END()); nua_authorize(nua_substate_active); default: break; } @endcode @subsection nua_shutting_down Shutdown The following functions show an example of how application terminates the NUA stack. The shutdown() function starts the termination. @code void shutdown(void) { nua_shutdown(appl->nua); } /* shutdown */ @endcode The app_r_shutdown() function is called by the callback function when NUA stack termination is either finished or failed. @code void app_r_shutdown(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]) { printf("shutdown: %d %s\n", status, phrase); if (status < 200) { /* shutdown in progress -> return */ return; } /* end the event loop. su_root_run() will return */ su_root_break(magic->root); } /* app_r_shutdown */ @endcode */ /** @page nua_call_model NUA Call Model The NUA call follows a relatively simple state model presented below. The call model is used to present changes in call: when media starts to flow, when call is considered established, when call is terminated. In the figure below, a simplified state diagram for a SIP call is presented. After the call state has changes the application will receive an #nua_i_state event indicating the change. The states in NUA call model are represented by @e enum #nua_callstate, and the current value of state is included as the tag NUTAG_CALLSTATE() with the #nua_i_state event. The @RFC3264 SDP Offer/Answer negotiation status is also included in the #nua_i_state event. The negotiation status includes the local SDP (in SOATAG_LOCAL_SDP()) sent and flags indicating whether the local SDP was an offer or answer (NUTAG_OFFER_SENT(), NUTAG_ANSWER_SENT()). Likewise, the received remote SDP is included in tag SOATAG_REMOTE_SDP() and flags indicating whether the remote SDP was an offer or an answer in tags NUTAG_OFFER_RECV() or NUTAG_ANSWER_RECV(). SOATAG_ACTIVE_AUDIO() and SOATAG_ACTIVE_VIDEO() are informational tags used to indicate what is the status of these media. The #nua_i_state event is not sent, however, if the change is invoked by application calling API functions like nua_bye() and there is no change in SDP offer/answer status. @code +---------------+ +------| INIT |-----+ INVITE/- | +---------------+ | INVITE/100 V | +------------+ +------------+ +----| CALLING |--+ +---| RECEIVED |--+ | +------------+ | | +------------+ | | | | | | | | | 18X/- | | | -/18X | | V | | V | | +------------+ | | +------------+ | |<---| PROCEEDING | | | | EARLY |->| | +------------+ | | +------------+ | -/[3456]XX | | | | | | | | 2XX/- | 2XX/- | -/2XX | -/2XX | or | V | | V | | + - - - - - -+ | | +------------+ | CANCEL/200,487 | : COMPLETING :<-+ +-->| COMPLETE | | | + - - - - - -+ +------------+ | | | | | | | -/ACK ACK/- | | | | | | | | | | | | +---------------+ | | | +----->| READY |<----+ | | +---------------+ | | | | | | BYE/200 | | -/BYE | | | | | | | V | | | +--------------+ | | [3456]XX/ACK | | TERMINATING | | | | +--------------+ | | | | | | | | [23456]XX/- | | V V | | +---------------+ | +---------------->| TERMINATED |<--------------+ +---------------+ @endcode The labels "input/output" along each transition indicates SIP messages received from and sent to network, for instance, state transition "INVITE/100" occurs when a SIP @b INVITE request is received, and it is immediately returned a 100 (Trying) response. Label "2XX" means any 200-series response, e.g., 200 OK or 202 Accepted). Notation "[3456]XX" means any final error response in 300, 400, 500, or 600 series. Label "18X" means any provisional response from 101 to 199, most typically 180 (Ringing) or 183 (Session Progress). @section nua_uac_call_model Detailed Client Call Model The detailed call model at client side is presented below. This model does not include the extensions like @b 100rel or @b UPDATE. @code +------------+ | INIT | +------------+ | (1) nua_invite/INVITE | V +------------+ | |-----------------------------(6a)-----+ | |----+ nua_cancel | +------| CALLING | (7a) /CANCEL | | | |<---+ | | | |----------------------+ | | +------------+ | | | | (8a) nua_bye | | (2) 18X/- | /CANCEL | | | | | | V | | | +------------+ | | | | |-----------------------------(6b)---->| | | |----+ nua_cancel | | | | PROCEEDING | (7b) /CANCEL | | | | |<---+ | | | | |----------------------+ | | +------------+ | | | | | | (3a) 2XX/- (3b) 2XX/- | (6) [3456]XX/ACK | | | | | V | | | + - - - - - -+ | | +----->: : | | : COMPLETING :-------+ | | + - - -: : | | | : + - - - - - -+ | | | : | | | | : | | | | :or nua_ack | | | | :and media | or nua_ack | nua_bye | | (5) error (4) /ACK (9) /ACK+BYE (8b) nua_bye/BYE | : /ACK+BYE | | | | : V | V | : +------------+ | +-------------+ | : | | | | | | : | READY | | | TERMINATING*| | : | | | | | | : +------------+ | +-------------+ | : | | | | : | (10) 2XX (11) 3XX 4XX | : +-------------+ | | /BYE | 5XX 6XX | : | | V | | /- | + - - >| TERMINATING |<--------------+ | | | | | | +-------------+ | | | | | (12) [23456]XX to BYE/- | | | | | V | | +------------+ | | | TERMINATED |<--------------------------+----------+ +------------+ @endcode The detailed description of state transitions on the client side is as follows:
# Previous state Input Output Next state Offer/ Answer Description
C1 init nua_invite() INVITE calling Generate offer Client application starts call be invoking nua_invite(). By default, stack runs the initial offer/answer step and sends @b INVITE request with the SDP offer.
C2 calling18X-proceeding (Save answer) Stack receives a 18X response (a provisional response between 101 and 199). It establishes an early dialog with server. If the provisional response contains an SDP answer, a session with early media is established. The caller can be listen to, for instance, ring tone or announcements about call progress using the early media session.
C3a calling2XX -completing Save answer Client receives a 2XX response (usually 200 OK) indicating that call has been accepted by the server. If there is an SDP session description included with response, it is stored. Unless the @ref NUTAG_AUTOACK() "auto-ack" mode is explicitly turned off by application the client does not stay in @b completing state, but proceeds immediately to next state transition.
C3b proceeding
C4 completing nua_ack() or
@ref NUTAG_AUTOACK() "auto-ack"
ACKready Process answer Client sends an ACK request in this state transition. If the initial offer was sent with INVITE, the answer must have been received by this time, usually in the 2XX response. Client now completes the SDP offer-answer exchange and activates the media.
C5 completing nua_ack() or
@ref NUTAG_AUTOACK() "auto-ack" and
media error
ACK
BYE
terminating Process answer If there was a failure in SDP negotiation or other failure with media, the stack will automatically terminate the call. The BYE follows immediately after the ACK.
C6a calling 3XX 4XX
5XX 6XX
ACK* terminated - Call is terminated when client receives a final error response (from 300 to 699) to its INVITE request. In this case, the underlying transaction engine takes care of sending ACK even when application-driven-ack mode is requested by application.
C6b proceeding
C7a calling nua_cancel() CANCEL calling - Client can ask server to cancel the call attempt while in @b calling or @b proceeding state. There is no direct call state transition caused by nua_cancel(). The call state changes when the server returns a response. After receiving a CANCEL request the server will usually return a 487 Request Terminated response and call is terminated as in previous item. However, there is a race condition and the server can respond with a succesful 2XX response before receiving CANCEL. In that case, the call is established as usual. It is up to application to terminate the call with nua_bye().
C7b proceeding proceeding
C8a calling nua_bye() CANCEL terminating* - The call cannot be terminated with BYE before the dialog is established with a non-100 preliminary response. So, instead of a @b BYE, stack sends a @b CANCEL request, and enters terminating state. However, there is a race condition and the server can respond with a succesful 2XX response before receiving CANCEL. If the server responds with a 2XX response, the nua will automatically send a BYE request asking server to terminate the call.
C8b proceeding nua_bye() BYE Even an early session can be terminated after entering @b proceeding state with nua_bye(). Stack sends a @b BYE request, and enters terminating state. Unlike @b CANCEL, @b BYE affects only one fork. However, there is a race condition and the server can respond with a succesful 2XX response before receiving BYE. If the server responds with a 2XX response, the nua will automatically send a BYE request asking server to terminate the call.
C9 completingnua_bye()ACK
BYE
terminating - If the stack is in @b completing state (it has already received 2XX response), it will have to @b ACK the final response, too.
C10 terminating* 2XX
to INVITE
BYE terminating - There is a race condition between @b BYE and @b INVITE. The call may have been re-established with @b INVITE after @b BYE was processed. @b BYE is re-sent and call state transitions to normal terminating state.
C11 terminating* 3XX 4XX
5XX 6XX
to INVITE
- terminated - The @b INVITE transaction is completed without a call being created. The call state transitions to terminated state.
C12 terminating 3XX 4XX
5XX 6XX
to BYE
- terminated - Call is terminated when the final response to the BYE is received.
@section nua_uas_call_model Detailed Server-Side Call Model The detailed call model at server side (UAS) is presented below. This model does not include the extensions like @b 100rel or @b UPDATE. @code +----------------------------------+ | INIT | +----------------------------------+ | : : | : : (1) INVITE/100 (2b) INVITE/18X (3c) INVITE/2XX | : : | : : V : : +------------+ : : +--------------------| | : : | | RECEIVED |--------------+ : | +---------------| | : | : | | +------------+ : | : | | | : | : | | nua_respond/18X (2a) : | : | | | : | : | | V V | : | | +------------+ | : |<------------------------------| | | : | |<-------------------------| EARLY | | : | | +----------| | | : | | | +------------+ | : | nua_respond/ | | | : (6) /[3456]XX | nua_respond/2XX (3b) (3a) : | | | | | : | | | V V V | | | +-------------+ | | | | | | | | +-----| COMPLETED |- - + | | | | | | : | | | | +-------------+ : | | | | | : | | | | (4) ACK/- : | | | | | : | | | | V : | | | | +-------------+ : | | | | | | : | | | | | READY | : | | | | | | : | | | | +-------------+ : | | | | : | (7) CANCEL/487 (8) BYE/487 (9) BYE/200 (5) timeout | | | | : /BYE | | | | +-------------+ : | | | | | TERMINATING |<- -+ | | | | +-------------+ | | | | | | | | | | [23456]XX/- | | | | | | | | | V | V V V +-------------+ +---------------------------------------->| TERMINATED | +-------------+ @endcode The detailed description of state transitions on the server side is as follows:
# Previous state Input Output Next state Offer/ Answer Description
S1 init INVITE 100 Trying received Save offer When a @b INVITE request for a new call is received, the server creates a fresh call handle for it, responds to the client with 100 Trying and enters in the @b received state by default. It saves the possible SDP offer included in @b INVITE and passes it to the application.
S2a received nua_respond() 18X early (Generate early answer) When server returns a preliminary response for the initial @b INVITE request, a early dialog is created. The server can also send an SDP answer with the preliminary answer and establish an early session, too. It can use the early session to send early media, e.g., ringing tone and announcements towards the client.
S2b init INVITE and @ref NUTAG_AUTOALERT() "auto-alert" 180 Ringing Save offer (and generate early answer) When @ref NUTAG_AUTOALERT() "auto-alert" option is enabled, stack sends 180 Ringing immediately after receiving INVITE and enters @b early state.
S3a received nua_respond() 2XX completed Generate answer When the server sends a 2XX response towards the client, it accepts the call. The @b INVITE transaction is now considered complete but unconfirmed at the server side. If the offer was sent in @b INVITE request, the answer should be included in the 2XX response.
S3b early
S3c init INVITE and @ref NUTAG_AUTOANSWER() "auto-answer" 200 OK Save offer and
generate answer
When @ref NUTAG_AUTOANSWER() "auto-answer" option is enabled, stack send 200 OK immediately after receiving INVITE and enters @b completed state.
S4 completed ACK - ready - The ready state is entered at server side after receiving @b ACK request from client, indicating that the client have received server's 2XX response. The call is ready, the @b INVITE transaction is confirmed.
S5td> completed timeout BYE terminating - If the server does not receive an @b ACK request in timely fashion, it will terminate the call by sending a @b BYE request to client.
S6a received nua_respond() 3XX 4XX
5XX 6XX
terminated - The server can reject the call by sending a 3XX, 4XX, 5XX, or 6XX response towards the client. The underlying transaction engine takes care of retransmitting the response when needed. It consumes the ACK response sent by the client, too.
S6b early
S7a received CANCEL 487 Request terminated terminated - The client can cancel the call attempt before it is completed with a @b CANCEL request. Server returns a 200 OK response to @b CANCEL and a 487 Request Terminated response to the @b INVITE transaction and the call is terminated.
S7b early
S8 early BYE 487 to INVITE
200 to BYE
terminated - The client can terminate an early session with a @b BYE request, too. Like in the @b CANCEL case above, the server will terminate call immediately, return a 200 OK response to @b BYE and a 487 Request Terminated response to the @b INVITE transaction.
S9 completed BYE 200 to BYE terminated - The client can terminate a completed dialog with a @b BYE request. Server terminates call immediately, returns a 200 OK response to @b BYE and lets the underlying transaction engine to take care of consuming @b ACK.
@section nua_3pcc_call_model Third Party Call Control There is an alternative offer-answer model for third party call control (3pcc). The call setup involves a 3rd party, client C, which sends initial INVITE to server A without SDP. The call setup looks perfectly ordinary to server B, however. @code A C B | | | |<-------INVITE---------| | | | | | | | |------200 (offer)----->| | | |----INVITE (offer)---->| | | | | | | | |<-----200 (answer)-----| |<-----ACK (answer)-----| | | | | | |----------ACK--------->| | | | @endcode The modifications to the call model affect mainly offer-answer model. The detailed description of state transitions for 3pcc on the server side is as follows:
# Previous state Input Output Next state Offer/ Answer Description
S1' init INVITE 100 Trying received - There is no SDP to save.
S2b' init INVITE and @ref NUTAG_AUTOALERT() "auto-alert" 180 Ringing early - There is no SDP to save.
S3a' early nua_respond() 2XX completed Generate offer The offer is sent in 200 OK.
S3b' received
S3c' init INVITE and @ref NUTAG_AUTOANSWER() "auto-answer" 200 OK
S4' completed ACK - ready Save and process answer The answer is processed and media activated after receiving @b ACK.
S9b' completed ACK and O/A error BYE terminating Save and process answer If the offer/answer negotiation ends in error after the server receives answer in @b ACK request, the server will have to terminate call by sending a @b BYE request.
@section nua_terminate_call_model Model for Modifying and Terminating Call After the SIP session has been established, it can be further modified by @b INVITE transactions, initiated by either the original client or the original server. These so-called re-INVITE transactions can be used to upgrade session (add new media to it), put the session on hold or resume a held call. A session can be terminated with a @b BYE request at any time. If any in-dialog request (including re-INVITE) fails with certain response code, the session can be considered terminated, too. These response codes are documented with sip_response_terminates_dialog(). In some cases, the session should be terminated gracefully by sending a @b BYE request after the failed requests. @code +-------------------------------------------------------------+ | READY | +-------------------------------------------------------------+ | | | | | | | | (1) BYE/200 (2) nua_bye/BYE (4) graceful/BYE (5) fatal/- | | | | | V V | | +-----------------------------+ | | | TERMINATING | | | +-----------------------------+ | | | | | (3) [23456]XX/- | | | | V V V +-------------------------------------------------------------+ | TERMINATED | +-------------------------------------------------------------+ @endcode The detailed description of state transitions while call is terminated is as follows:
# Previous state Input Output Next state Description
T1 ready BYE 200 OK terminated When the @b BYE request is received, the recipient terminates the currently ongoing @b INVITE transaction, the session and its dialog usage (if there is another dialog usage active, e.g., a subscription creted by @b REFER.)
T2 ready nua_bye BYE terminating The application terminates the session by calling nua_bye(). All the call-related requests on the dialog are rejected while in terminating state with 487 No Such Call response.
T3 terminating 2XX 3XX 4XX 5XX 6XX - terminated The session is finally terminated when a final response to @b BYE is received. Note that nua stack does retry @b BYE requests.
T4 ready "graceful" response BYE terminating A call-related request (@b re-INVITE, @b UPDATE, @b INFO, @b PRACK, @b REFER) fails with a response code indicating that the client should gracefully terminate the call.
T5 ready "fatal" response - terminated A call-related request (@b re-INVITE, @b UPDATE, @b INFO, @b PRACK, @b REFER) fails with a response code indicating that the call has been terminated.
@sa http://www.ietf.org/internet-drafts/draft-sparks-sipping-dialogusage-01.txt @sa sip_response_terminates_dialog() */ /* For reference: +---------------+ +-(1)--| INIT |-----+ INVITE/- | +---------------+ (A) INVITE/100 V | +------------+ +------------+ +----| CALLING | +---| RECEIVED |--+ | +------------+ | +------------+ | | | | | | | (2) 18X/- | (B) -/18X | | V | V | | +------------+ | +------------+ | |<---| PROCEEDING |--+ | | EARLY |->| | +------------+ | | +------------+ (F) -/[3456]XX | : | | | | | (4) 2XX/- | (E) -/2XX (C) -/2XX | or | V | | V | | + - - - - - -+ | | +------------+ (G) CANCEL/200,487 | : COMPLETING : | +-->| COMPLETE | | | + - - - - - -+ | +------------+ | | : | | : | | (5)-/ACK (3) 2XX/ACK ACK/-(D) : | | : | | : | | : V | : | | : +---------------+ | : | | + - - >| READY |<----+ : | | +---------------+ : | | | | : | | BYE/200 (i) (ii) -/BYE timeout/ : | | | | BYE (H) | | | V : | | | +--------------+ : | (6) [3456]XX/ACK | | TERMINATING |<- - + | | | +--------------+ | | | | | | | (iii) [23456]XX/- | | V V | | +---------------+ | +---------------->| TERMINATED |<--------------+ +---------------+ | V INIT */ /**@page nua_event_diagrams NUA Event Diagrams The example diagrams below try to present how to use NUA API with different SIP use cases. @section nua_event_diagram_call Basic Call The SIP following event diagram shows a pretty simple, succesful call case. The nua events and nua function calls are show in the diagram below as well as the SIP messages. The call setup above assumes parameters NUTAG_AUTOALERT(0), NUTAG_AUTOANSWER(0) on B side, NUTAG_AUTOACK(0) on A side. @code Alice Proxy Bob 0 | | | 1 nua_handle() | | | 2 nua_invite() -> |-----INVITE---->| | 3 nua_i_state <- | | | 4 | |-----INVITE---->| -> nua_i_invite 5 |<--100 Trying---| | -> nua_i_state 6 | | | 7 | | | 8 | | | 9 | |<--180 Ringing--| <- nua_respond(180) 10 nua_i_invite <- |<--180 Ringing--| | -> nua_i_state 11 nua_i_state <- | | | 12 | |<--200 OK-------| <- nua_respond(200) 13 nua_i_invite <- |<---200 OK------| | -> nua_i_state 14 nua_i_state <- | | | 15 nua_ack() -> |-----ACK------->| | 16 nua_i_state <- | |-----ACK------->| -> nua_i_ack 17 | | | -> nua_i_state 18 | | | 19 <<====== SIP Session Established =======>> 20 | | | 21 | | | 22 nua_bye() -> |-----BYE------->| | 23 | |-----BYE------->| -> nua_i_bye 24 | |<----200 OK-----| -> nua_i_state 25 nua_r_bye <- |<---200 OK------| | 26 nua_i_state <- | | | | | | @endcode @section nua_event_diagram_call_hold Holding Call The media (audio, video) can be put on hold. In SIP system this means that application can indicate to the remote end that it is engaged in other activity (another call, for instance) and does not wish to receive media from the remove end. The call hold is usully implemented using re-INVITE. Re-INVITE is an INVITE request sent on existing SIP session. Both original caller and callee can send re-INVITEs. The main use of re-INVITE is modifying sessions: adding media lines to the session, changing codecs on existing media, and, as you might expect, putting existing media on hold as well as resuming media from hold. A re-INVITE is sent by calling nua_invite() on handle with existing call. When putting call on hold, the application can include SOATAG_HOLD("audio") or SOATAG_HOLD("video") or SOATAG_HOLD("audio, video") or SOATAG_HOLD("*") as parameters to re-INVITE nua_invite(). (Note that last SOATAG_HOLD() in the tag list will override the SOATAG_HOLD() tags before it.) Another feature where nua tries to be helpful is autoanswer and auto-ACK on existing sessions: the re-INVITE is automatically responded with 200 OK and ACK is automatically sent. (If the application wants to respond and ACK by itself, it should explicitly set NUTAG_AUTOANSWER(0) and/or NUTAG_AUTOACK(0) in the handle; either include them in nua_invite() or nua_respond() parameters or call nua_set_hparams() explicitly. @code Alice Proxy Bob 0 nua_handle() | | | 1 | | | 2 nua_invite() -> |-----INVITE---->| | 3 nua_i_state <- | | | 4 | |-----INVITE---->| -> nua_i_invite 5 |<--100 Trying---| | -> nua_i_state 6 | | | 7 | | | 8 | | | 9 | |<--180 Ringing--| <- nua_respond(180) 10 nua_i_invite <- |<--180 Ringing--| | -> nua_i_state 11 nua_i_state <- | | | 12 | |<--200 OK-------| <- nua_respond(200) 13 nua_i_invite <- |<---200 OK------| | -> nua_i_state 14 nua_i_state <- | | | 15 nua_ack() -> |-----ACK------->| | 16 nua_i_state <- | |-----ACK------->| -> nua_i_ack 17 | | | -> nua_i_state 18 | | | 19 <<== Bi-Directional RTP Established ==>> 20 | | | 21 | | | 22 | |<--INVITE(hold)-| <- nua_invite(.. 21 | | | NUTAG_HOLD("*")..) 23 nua_i_invite <- |<-INVITE(hold)--| | -> nua_i_state 25 nua_i_state <- |----200 OK----->| | 26 | |----200 OK----->| -> nua_i_invite 28 | |<-----ACK-------| -> nua_i_state 29 nua_i_ack <- |<----ACK--------| | 24 | | | 30 <<== Uni-Directional RTP Established ==>> 24 | | | 31 | | | 32 | |<--INVITE-------| <- nua_invite(.. 21 | | | NUTAG_HOLD(NULL)..) 33 nua_i_invite <- |<--INVITE-------| | -> nua_i_state 35 nua_i_state <- |---200 OK------>| | 36 | |---200 OK------>| -> nua_i_invite 38 | |<----ACK--------| -> nua_i_state 39 nua_i_ack <- |<----ACK--------| | 40 nua_i_state <- | | | 19 <<== Bi-Directional RTP Established ==>> 42 | | | 43 nua_bye() -> |-----BYE------->| | 44 nua_i_state <- | |-----BYE------->| -> nua_i_bye 46 | |<----200 OK-----| -> nua_i_state 47 |<---200 OK------| | | | | @endcode @section nua_event_diagram_call_transfer Call Transfer This is the unattended call transfer case. 1st MSC showing Alice's end: @code Alice Bob Carol 0 | | | 1 nua_i_invite <- |<-----INVITE--------| | 2 nua_i_state <- | | | 2 | | | 3 nua_respond(180) -> |----180 Ringing---->| | 2 nua_i_state <- | | | 4 | | | 5 nua_respond(200) -> |------200 OK------->| | 6 nua_i_state <- | | | 8 | | | 7 nua_i_ack <- |<-------ACK---------| | 8 nua_i_state <- | | | 9 |<========RTP=======>| | 10 | | | 11 << Alice performs unattended transfer >> | 12 | | | 13 | | | 14 nua_refer() -> |---REFER("r: C")--->| | 15 | | | 16 nua_r_refer <- |<---202 Accepted----| | 17 | | | 18 nua_i_notify <- |<-----NOTIFY--------| | 19 | | | 20 |------200 OK------->| | 21 | |---INVITE("b: A")-->| 23 | | | 22 nua_bye() -> |-------BYE--------->| | 23 | | | 24 nua_r_bye <- |<----200 OK---------| | 25 nua_i_state <- | No RTP Session | | 28 | |<----180 Ringing----| 26 nua_i_notify <- |<- - -NOTIFY - - - -| | 27 | | | 20 |- - - 200 OK- - - ->| | 29 | | | 30 | |<------200 OK-------| 31 | | | 32 | |---------ACK------->| 33 | | RTP | 34 | |<==================>| 35 | | | 36 |<-----NOTIFY--------| | 37 | | | 38 |------200 OK------->| | | | | @endcode 2nd MSC showing Bobs's end: @code Alice Bob (nh1) Bob (nh2) Carol 0 | | | | 1 |<-----INVITE--------| | | 2 | | | | 3 |---180 Ringing----->| | | 4 | | | | 5 |------200 OK------->| | | 6 | | | | 7 |<-------ACK---------| | | 8 | RTP | | | 9 |<==================>| | | 10 | | | | 11<< Alice performs unattended transfer >> | | 12 | | | | 13 | Refer-To:C F5| | | 14 |-REFER------------->| -> nua_i_refer | | 15 | | | | 16 |<-202 Accepted------| | | 17 | | | | 18 |<-----NOTIFY--------| | | 19 | | | | 20 |------200 OK------->| -> nua_r_notify | | 21 | | | | 22 |-------BYE--------->| -> nua_i_bye | | 23 | | -> nua_i_state | | 24 |<----200 OK---------| nua_handle() -> | | 25 | No RTP Session | nua_invite() -> | | 26 | | |--INVITE("b: A")--->| 27 | | | | 28 | | nua_i_invite <- |<--180 Ringing------| 29 | | nua_i_state <- | | 30 | | nua_i_invite <- |<----200 OK---------| 31 | | nua_i_state <- | | 32 | | nua_ack -> |-------ACK--------->| 33 | | | | 34 | | |<=======RTP========>| 35 | | | | 36 |<-----NOTIFY--------| | | 37 | | 38 |------200 OK------->| -> nua_r_notify 39 | | <- nua_handle_destroy | | @endcode Bob includes nh1 in nua_invite()/25 as NUTAG_NOTIFY_REFER() parameter. Open Issue 1: - how Bob know when to destroy nh1? @section nua_event_diagram_3gpp_call 3GPP Call Model The 3GPP call model is defined in 3GPP TS 24.229. In order to select only a single codec and ensure that the QoS reservationa are made before the call is alerting, the 3GPP call model employs multiple offer/answer exchanges. It uses 100rel and PRACK (@RFC3262), UPDATE (@RFC3311) and preconditions (@RFC3312) extensions specified by IETF. The call setup below assumes parameters NUTAG_AUTOALERT(0), NUTAG_AUTOANSWER(0) on B side, NUTAG_AUTOACK(0) on A side. @code A B 0 nua_handle() | | 1 nua_invite() -> | | 2 nua_i_state <- |----INVITE (offer)---->| 3 | | -> nua_i_invite 4 | | -> nua_i_state 5 | | 6 | | <- nua_respond(183) 7 nua_i_invite <- |<----183 (answer)------| -> nua_i_state 8 nua_i_state <- | | 9 << single codec is selected now >> 10 |-----PRACK(offer2)---->| -> nua_i_prack 11 | | -> nua_i_state 12 nua_r_prack <- |<--200/PRACK(answer2)--| 13 | | 14 | | 15 << resource reservations are done now >> 16 | | 17 nua_update() -> |----UPDATE (offer3)--->| 18 nua_i_state <- | | 19 nua_i_state <- |<-200/UPDATE (answer3)-| -> nua_i_update 20 | | -> nua_i_state 21 | | 22 | | << B rings >> 23 | | 24 | | <- nua_respond(180) 25 nua_i_invite <- |<---------180----------| 26 nua_i_state <- | | 27 |--------PRACK--------->| -> nua_i_prack 28 nua_r_prack <- |<-----200/PRACK------->| -> nua_i_state 29 | | 30 | | <- nua_respond(200) 31 nua_i_invite <- |<---------200----------| -> nua_i_state 32 nua_i_state <- | | 33 nua_ack() -> | | 34 nua_i_state <- |----------ACK--------->| -> nua_i_ack 35 | | -> nua_i_state | | @endcode */ /**@var nua_event_e * * @brief Events * * The NUA event loop calls an event callback function when an application * needs to act on something that happened in the Sofia stack. The callback * function is registered when nua_create() function call is used to create * the NUA stack object. * * The prototype of the event callback function is: * @code * void nua_callback_f(nua_event_t event, * int status, * char const *phrase, * nua_t *nua, * nua_magic_t *magic, * nua_handle_t *nh, * nua_hmagic_t *hmagic, * sip_t const *sip, * tagi_t tags[]); * @endcode * * @param event Callback event identification. \n * Always present * @param status Protocol status code. \n * Always present * @param phrase Text corresponding to status code. \n * Always present * @param nua Pointer to NUA stack object. \n * Always present * @param magic Pointer to callback context from nua_create(). \n * Always present * @param nh Pointer to operation handle. * @param hmagic Pointer to callback context from nua_handle(). * @param sip Headers in parsed incoming message. May be NULL. * See also nua_current_request(). * @param tags Tag list containing more information about the state of NUA. * May be empty. * * Note that the contents of the last four parameters vary depending on * the event. The descriptions can be found from the description of the * individual event. * * The events can be divided into the following categories: \n * @par Status or Error Indications: * #nua_i_active \n * #nua_i_error \n * #nua_i_fork \n * #nua_i_media_error \n * #nua_i_subscription \n * #nua_i_state \n * #nua_i_terminated * * @par SIP requests: * #nua_i_ack \n * #nua_i_bye \n * #nua_i_cancel \n * #nua_i_chat \n * #nua_i_info \n * #nua_i_invite \n * #nua_i_message \n * #nua_i_method \n * #nua_i_notify \n * #nua_i_options \n * #nua_i_prack \n * #nua_i_publish \n * #nua_i_refer \n * #nua_i_register \n * #nua_i_subscribe \n * #nua_i_update * * @par Responses: * #nua_r_get_params \n * #nua_r_notifier \n * #nua_r_shutdown \n * #nua_r_terminate * * @par SIP responses: * #nua_r_bye \n * #nua_r_cancel \n * #nua_r_info \n * #nua_r_invite \n * #nua_r_message \n * #nua_r_notify \n * #nua_r_options \n * #nua_r_prack \n * #nua_r_publish \n * #nua_r_refer \n * #nua_r_register \n * #nua_r_subscribe \n * #nua_r_unpublish \n * #nua_r_unregister \n * #nua_r_unsubscribe \n * #nua_r_update * * @sa nua_event_is_incoming_request(), nua_event_name() */ /** @NUA_EVENT nua_i_chat * * Incoming chat message. * * @param nh operation handle associated with the message * @param hmagic operation magic associated with the handle * @param sip incoming chat message * @param tags empty * * @END_NUA_EVENT */ /** @NUA_EVENT nua_i_error * * Error indication. * * Will be sent when an internal error happened or * an error occurred while responding a request. * * @param status SIP status code or NUA status code (>= 900) * describing the problem * @param phrase a short textual description of @a status code * @param nh NULL or operation handle associated with the call * @param hmagic NULL or operation magic associated with the call * @param sip NULL * @param tags empty or error specific information * * @END_NUA_EVENT */ /** @NUA_EVENT nua_i_fork * * Outgoing call has been forked. * * This is sent when an INVITE request is answered with multiple 2XX series * responses. * * @param status response status code * @param phrase a short textual description of @a status code * @param nh operation handle associated with the original call * @param hmagic operation magic associated with the original call * @param sip preliminary or 2XX response to INVITE * @param tags NUTAG_HANDLE() of the new forked call * * @sa #nua_r_invite, #nua_i_state, @ref nua_call_model * * @END_NUA_EVENT */ /** @NUA_EVENT nua_i_media_error * * Media error indication. * * This may be sent after an SOA operation has failed while processing * incoming or outgoing call. * * @param status SIP status code or NUA status code (>= 900) * describing the problem * @param phrase a short textual description of @a status code * @param nh operation handle associated with the call * @param hmagic operation magic associated with this handle * (maybe NULL if call handle was created for this call) * @param sip NULL * @param tags empty * * @END_NUA_EVENT */ /* nua_i_message is documented with nua_stack_process_message() */ /* nua_i_method is documented with nua_stack_process_method() */ /** @NUA_EVENT nua_i_network_changed * * Local IP(v6) address has changed. * * @param nh default operation handle * @param hmagic operation magic associated with the default operation handle * @param sip NULL * @param tags empty * * @since Experimental in @VERSION_1_12_2. * * @END_NUA_EVENT */ /* nua_i_notify is documented with nua_stack_process_notify() */ /* nua_i_options is documented with nua_stack_process_options() */ /* nua_i_publish is documented with nua_stack_process_publish() */ /* nua_i_refer is documented with nua_stack_process_refer() */ /* nua_i_subscribe is documented with nua_stack_process_subscribe() */ /** @NUA_EVENT nua_i_subscription * * Incoming subscription to be authorized. * * This event is launched by nua_notifier() to inform application of the * current state of the subscriber. The subscriber state is included in the * NUTAG_SUBSTATE() tag. If the state is #nua_substate_pending or * #nua_substate_embryonic, application should to authorize the subscriber * with nua_authorize(). * * @param nh operation handle associated with the notifier * @param hmagic operation magic * @param status statuscode of response sent automatically by stack * @param sip incoming SUBSCRIBE request * @param tags NEATAG_SUB(), * NUTAG_SUBSTATE() * * @sa nua_notifier(), #nua_i_subscribe, nua_authorize(), nua_terminate() * @RFC3265 * * @END_NUA_EVENT */ /* nua_i_update is documented with nua_stack_process_update() */ /* nua_r_bye is documented with process_response_to_bye() */ /* nua_r_cancel is documented with process_response_to_cancel() */ /** @NUA_EVENT nua_r_chat * * Answer to outgoing chat message. * * @param nh operation handle associated with the notifier * @param hmagic operation magic associated with the notifier * @param sip response to MESSAGE request or NULL upon an error * (error code and message are in status and phrase parameters) * @param tags empty * * @sa nua_chat(), #nua_r_message * * @END_NUA_EVENT */ /* nua_r_info is documented with process_response_to_info() */ /* nua_r_invite is documented with process_response_to_invite() */ /* nua_r_message is documented with process_response_to_message() */ /** @NUA_EVENT nua_r_notifier * * Answer to nua_notitier() * * @param nh operation handle associated with the call * @param hmagic operation magic associated with the call * @param sip NULL * @param tags SIPTAG_EVENT() \n * SIPTAG_CONTENT_TYPE() * * @sa nua_notitier(), #nua_i_subscription, @RFC3265 * * @END_NUA_EVENT */ /* nua_r_notify is documented with process_response_to_notify() */ /* nua_r_options is documented with process_response_to_options() */ /* nua_r_prack is documented with process_response_to_prack() */ /* nua_r_publish is documented with process_response_to_publish() */ /* nua_r_refer is documented with process_response_to_refer() */ /* nua_r_shutdown is documented with nua_stack_shutdown() */ /* nua_r_subscribe is documented with process_response_to_subscribe() */ /** @NUA_EVENT nua_r_terminate * * Answer to nua_terminate(). * * @param nh operation handle associated with the notifier * @param hmagic operation magic associated with the notifier * @param sip NULL * @param tags empty * * @sa nua_terminate(), nua_handle_destroy() * * @END_NUA_EVENT */ /* nua_r_unsubscribe is documented with process_response_to_subscribe() */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/nua_client.c000066400000000000000000001305261223300710500226310ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2006 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE nua_client.c * @brief Client transaction handling * * @author Pekka Pessi * * @date Created: Tue Feb 3 16:10:45 EET 2009 */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #define SU_MSG_ARG_T struct nua_ee_data #define SU_TIMER_ARG_T struct nua_client_request #define NUA_SAVED_EVENT_T su_msg_t * #define NUA_SAVED_SIGNAL_T su_msg_t * #define NTA_AGENT_MAGIC_T struct nua_s #define NTA_LEG_MAGIC_T struct nua_handle_s #define NTA_OUTGOING_MAGIC_T struct nua_client_request #include "nua_stack.h" #include "nua_dialog.h" #include "nua_client.h" #include su_inline int can_redirect(sip_contact_t const *m, sip_method_t method); /**@internal * * @class nua_client_request * * Each handle has a queue of client-side requests; if a request is pending, * a new request from API is added to the queue. After the request is * complete, it is removed from the queue and destroyed by the default. The * exception is the client requests bound to a dialog usage: they are saved * and re-used when the dialog usage is refreshed (and sometimes when the * usage is terminated). * * The client request is subclassed and its behaviour modified using virtual * function table in #nua_client_methods_t. * * The first three methods (crm_template(), crm_init(), crm_send()) are * called when the request is sent first time. * * The crm_template() is called if a template request message is needed (for * example, in case of unregister, unsubscribe and unpublish, the template * message is taken from the request establishing the usage). * * The crm_init() is called when the template message and dialog leg has * been created and populated by the tags procided by the application. Its * parameters msg and sip are pointer to the template request message that * is saved in the nua_client_request::cr_msg field. * * The crm_send() is called with a copy of the template message that has * been populated with all the fields included in the request, including * @CSeq and @MaxForwards. The crm_send() function, such as * nua_publish_client_request(), usually calls nua_base_client_trequest() that * then creates the nta-level transaction. * * The response to the request is processed by crm_check_restart(), which * modifies and restarts the request when needed (e.g., when negotiating * expiration time). After the request has been suitably modified, e.g., the * expiration time has been increased, the restart function calls * nua_client_restart(), which restarts the request and relays the * intermediate response to the application with nua_client_restart() and * crm_report(). * * The final responses are processed by crm_recv() and and preliminary ones * by crm_preliminary(). All virtual functions should call * nua_base_client_response() beside method-specific processing. * * The nua_base_client_response() relays the response to the application with * nua_client_restart() and crm_report(). * * @par Terminating Dialog Usages and Dialogs * * The response is marked as terminating with nua_client_set_terminating(). * When a terminating request completes the dialog usage is removed and the * dialog is destroyed (unless there is an another active usage). */ static void nua_client_request_destroy(nua_client_request_t *cr); static int nua_client_init_request0(nua_client_request_t *cr); static int nua_client_request_try(nua_client_request_t *cr); static int nua_client_request_sendmsg(nua_client_request_t *cr); static void nua_client_restart_after(su_root_magic_t *magic, su_timer_t *timer, nua_client_request_t *cr); /**Create a client request. * * @retval 0 if request is pending * @retval > 0 if error event has been sent * @retval < 0 upon an error */ int nua_client_create(nua_handle_t *nh, int event, nua_client_methods_t const *methods, tagi_t const * const tags) { su_home_t *home = nh->nh_home; nua_client_request_t *cr; sip_method_t method; char const *name; method = methods->crm_method, name = methods->crm_method_name; if (!name) { tagi_t const *t = tl_find_last(tags, nutag_method); if (t) name = (char const *)t->t_value; } cr = su_zalloc(home, sizeof *cr + methods->crm_extra); if (!cr) { return nua_stack_event(nh->nh_nua, nh, NULL, (enum nua_event_e)event, NUA_ERROR_AT(__FILE__, __LINE__), NULL); } cr->cr_methods = methods; cr->cr_event = event; cr->cr_method = method; cr->cr_method_name = name; cr->cr_contactize = methods->crm_flags.target_refresh; cr->cr_dialog = methods->crm_flags.create_dialog; cr->cr_auto = 1; if (su_msg_is_non_null(nh->nh_nua->nua_signal)) { nua_event_data_t *e = su_msg_data(nh->nh_nua->nua_signal)->ee_data; if (tags == e->e_tags && event == e->e_event) { cr->cr_auto = 0; if (tags) { nua_move_signal(cr->cr_signal, nh->nh_nua->nua_signal); if (cr->cr_signal[0]) { /* Steal reference from signal */ cr->cr_owner = e->e_nh, e->e_nh = NULL; cr->cr_tags = tags; } } } } if (cr->cr_owner == NULL) cr->cr_owner = nua_handle_ref(nh); if (tags && cr->cr_tags == NULL) cr->cr_tags = tl_tlist(nh->nh_home, TAG_NEXT(tags)); #if HAVE_MEMLEAK_LOG SU_DEBUG_0(("%p %s() for %s\n", cr, __func__, cr->cr_methods->crm_method_name)); #endif if (nua_client_request_queue(cr)) return 0; return nua_client_init_request(cr); } int nua_client_tcreate(nua_handle_t *nh, int event, nua_client_methods_t const *methods, tag_type_t tag, tag_value_t value, ...) { int retval; ta_list ta; ta_start(ta, tag, value); retval = nua_client_create(nh, event, methods, ta_args(ta)); ta_end(ta); return retval; } #if HAVE_MEMLEAK_LOG nua_client_request_t * nua_client_request_ref_by(nua_client_request_t *cr, char const *where, unsigned line, char const *who) { SU_DEBUG_0(("%p ref %s to %u by %s:%u: %s()\n", cr, cr->cr_methods->crm_method_name, ++(cr->cr_refs), where, line, who)); return cr; } int nua_client_request_unref_by(nua_client_request_t *cr, char const *where, unsigned line, char const *who) { SU_DEBUG_0(("%p unref %s to %u by %s:%u: %s()\n", cr, cr->cr_methods->crm_method_name, cr->cr_refs - 1, where, line, who)); if (cr->cr_refs > 1) { cr->cr_refs--; return 0; } else { cr->cr_refs = 0; nua_client_request_destroy(cr); return 1; } } #else nua_client_request_t *nua_client_request_ref(nua_client_request_t *cr) { cr->cr_refs++; return cr; } int nua_client_request_unref(nua_client_request_t *cr) { if (cr->cr_refs > 1) { cr->cr_refs--; return 0; } else { cr->cr_refs = 0; nua_client_request_destroy(cr); return 1; } } #endif int nua_client_request_queue(nua_client_request_t *cr) { int queued = 0; nua_client_request_t **queue = &cr->cr_owner->nh_ds->ds_cr; assert(cr->cr_prev == NULL && cr->cr_next == NULL); cr->cr_status = 0; nua_client_request_ref(cr); if (cr->cr_method != sip_method_invite && cr->cr_method != sip_method_cancel) { while (*queue) { if ((*queue)->cr_method == sip_method_invite || (*queue)->cr_method == sip_method_cancel) break; queue = &(*queue)->cr_next; queued = 1; } } else { while (*queue) { queue = &(*queue)->cr_next; if (cr->cr_method == sip_method_invite) queued = 1; } } if ((cr->cr_next = *queue)) cr->cr_next->cr_prev = &cr->cr_next; cr->cr_prev = queue, *queue = cr; return queued; } int nua_client_request_remove(nua_client_request_t *cr) { int retval = 0; int in_queue = cr->cr_prev != NULL; if (in_queue) { if ((*cr->cr_prev = cr->cr_next)) cr->cr_next->cr_prev = cr->cr_prev; } cr->cr_prev = NULL, cr->cr_next = NULL; if (cr->cr_timer) { su_timer_destroy(cr->cr_timer), cr->cr_timer = NULL; retval = nua_client_request_unref(cr); } if (!in_queue) return retval; return nua_client_request_unref(cr); } int nua_client_request_clean(nua_client_request_t *cr) { if (cr->cr_orq) { nta_outgoing_destroy(cr->cr_orq), cr->cr_orq = NULL, cr->cr_acked = 0; return nua_client_request_unref(cr); } return 0; } int nua_client_request_complete(nua_client_request_t *cr) { if (cr->cr_orq) { nua_client_request_ref(cr); if (cr->cr_methods->crm_complete) /* Calls nua_invite_client_complete() */ cr->cr_methods->crm_complete(cr); nua_client_request_clean(cr); if (nua_client_request_unref(cr)) return 1; } return nua_client_request_remove(cr); } static void nua_client_request_destroy(nua_client_request_t *cr) { nua_handle_t *nh; if (cr == NULL) return; /* Possible references: */ assert(cr->cr_prev == NULL); /* queue */ assert(cr->cr_orq == NULL); /* transaction callback */ assert(cr->cr_timer == NULL); /* timer callback */ nh = cr->cr_owner; nua_destroy_signal(cr->cr_signal); nua_client_bind(cr, NULL); #if HAVE_MEMLEAK_LOG SU_DEBUG_0(("%p %s for %s\n", cr, __func__, cr->cr_methods->crm_method_name)); #endif if (cr->cr_msg) msg_destroy(cr->cr_msg); cr->cr_msg = NULL, cr->cr_sip = NULL; if (cr->cr_orq) nta_outgoing_destroy(cr->cr_orq), cr->cr_orq = NULL; if (cr->cr_target) su_free(nh->nh_home, cr->cr_target); su_free(nh->nh_home, cr); nua_handle_unref(nh); } /** Bind client request to a dialog usage */ int nua_client_bind(nua_client_request_t *cr, nua_dialog_usage_t *du) { assert(cr); if (cr == NULL) return -1; if (du == NULL) { du = cr->cr_usage; cr->cr_usage = NULL; if (du && du->du_cr == cr) { du->du_cr = NULL; nua_client_request_unref(cr); } return 0; } if (du->du_cr && cr == du->du_cr) return 0; if (du->du_cr) { nua_client_bind(du->du_cr, NULL); } du->du_cr = nua_client_request_ref(cr), cr->cr_usage = du; return 0; } /** Check if client request is in progress. * * A client request is in progress, if * 1) it has actual transaction going on * 2) it is waiting credentials from application * 3) it is waiting for Retry-After timer */ int nua_client_request_in_progress(nua_client_request_t const *cr) { return cr && (cr->cr_orq || cr->cr_wait_for_cred || cr->cr_timer); } /**Initialize client request for sending. * * This function is called when the request is taken from queue and sent. * * @retval 0 if request is pending * @retval >=1 if error event has been sent */ int nua_client_init_request(nua_client_request_t *cr) { int retval; nua_client_request_ref(cr); retval = nua_client_init_request0(cr); nua_client_request_unref(cr); return retval; } /**Initialize client request for sending. * * This function is called when the request is taken from queue and sent. * * @retval 0 if request is pending * @retval >=1 if error event has been sent */ static int nua_client_init_request0(nua_client_request_t *cr) { nua_handle_t *nh = cr->cr_owner; nua_t *nua = nh->nh_nua; nua_dialog_state_t *ds = nh->nh_ds; msg_t *msg = NULL; sip_t *sip; url_string_t const *url = NULL; tagi_t const *t; int has_contact = 0; int error = 0; if (!cr->cr_method_name) return nua_client_return(cr, NUA_ERROR_AT(__FILE__, __LINE__), NULL); if (cr->cr_msg) return nua_client_request_try(cr); cr->cr_answer_recv = 0, cr->cr_offer_sent = 0; cr->cr_offer_recv = 0, cr->cr_answer_sent = 0; cr->cr_terminated = 0, cr->cr_graceful = 0; nua_stack_init_handle(nua, nh, cr->cr_tags); if (cr->cr_method == sip_method_cancel) { if (cr->cr_methods->crm_init) { error = cr->cr_methods->crm_init(cr, NULL, NULL, cr->cr_tags); if (error) return error; } if (cr->cr_methods->crm_send) return cr->cr_methods->crm_send(cr, NULL, NULL, cr->cr_tags); else return nua_base_client_request(cr, NULL, NULL, cr->cr_tags); } if (!cr->cr_methods->crm_template || cr->cr_methods->crm_template(cr, &msg, cr->cr_tags) == 0) msg = nua_client_request_template(cr); sip = sip_object(msg); if (!sip) return nua_client_return(cr, NUA_ERROR_AT(__FILE__, __LINE__), msg); if (nh->nh_tags) { for (t = nh->nh_tags; t; t = t_next(t)) { if (t->t_tag == siptag_contact || t->t_tag == siptag_contact_str) has_contact = 1; else if (t->t_tag == nutag_url) url = (url_string_t const *)t->t_value; } } /**@par Populating SIP Request Message with Tagged Arguments * * The tagged arguments can be used to pass values for any SIP headers * to the stack. When the INVITE message (or any other SIP message) is * created, the tagged values saved with nua_handle() are used first, * next the tagged values given with the operation (nua_invite()) are * added. * * When multiple tags for the same header are specified, the behaviour * depends on the header type. If only a single header field can be * included in a SIP message, the latest non-NULL value is used, e.g., * @Subject. However, if the SIP header can consist of multiple lines or * header fields separated by comma, e.g., @Accept, all the tagged * values are concatenated. * * However, if a tag value is #SIP_NONE (-1 casted as a void pointer), * the values from previous tags are ignored. */ for (t = cr->cr_tags; t; t = t_next(t)) { if (t->t_tag == siptag_contact || t->t_tag == siptag_contact_str) has_contact = 1; else if (t->t_tag == nutag_url) url = (url_string_t const *)t->t_value; else if (t->t_tag == nutag_dialog) { cr->cr_dialog = t->t_value > 1; cr->cr_contactize = t->t_value >= 1; } else if (t->t_tag == nutag_auth && t->t_value) { /* XXX ignoring errors */ if (nh->nh_auth) auc_credentials(&nh->nh_auth, nh->nh_home, (char *)t->t_value); } } if (cr->cr_method == sip_method_register && url == NULL) url = (url_string_t const *)NH_PGET(nh, registrar); if ((t = cr->cr_tags)) { if (sip_add_tagis(msg, sip, &t) < 0) return nua_client_return(cr, NUA_ERROR_AT(__FILE__, __LINE__), msg); } /** * Now, the target URI for the request needs to be determined. * * For initial requests, values from tags are used. If NUTAG_URL() is * given, it is used as target URI. Otherwise, if SIPTAG_TO() is given, * it is used as target URI. If neither is given, the complete request * line already specified using SIPTAG_REQUEST() or SIPTAG_REQUEST_STR() * is used. At this point, the target URI is stored in the request line, * together with method name and protocol version ("SIP/2.0"). The * initial dialog information is also created: @CallID, @CSeq headers * are generated, if they do not exist, and a tag is added to the @From * header. */ if (!ds->ds_leg) { if (ds->ds_remote_tag && ds->ds_remote_tag[0] && sip_to_tag(msg_home(msg), sip->sip_to, ds->ds_remote_tag) < 0) return nua_client_return(cr, NUA_ERROR_AT(__FILE__, __LINE__), msg); if (sip->sip_from == NULL && sip_add_dup(msg, sip, (sip_header_t *)nua->nua_from) < 0) return nua_client_return(cr, NUA_ERROR_AT(__FILE__, __LINE__), msg); if (sip->sip_to == NULL && cr->cr_method == sip_method_register && sip_add_dup_as(msg, sip, sip_to_class, (sip_header_t *)sip->sip_from) < 0) { return nua_client_return(cr, NUA_ERROR_AT(__FILE__, __LINE__), msg); } if (sip->sip_call_id == NULL) sip->sip_call_id = sip_call_id_create(msg_home(msg), NULL); } else { if (ds->ds_route) url = NULL; } if (url && nua_client_set_target(cr, (url_t *)url) < 0) return nua_client_return(cr, NUA_ERROR_AT(__FILE__, __LINE__), msg); cr->cr_has_contact = has_contact; if (cr->cr_methods->crm_init) { error = cr->cr_methods->crm_init(cr, msg, sip, cr->cr_tags); if (error < -1) msg = NULL; if (error < 0) return nua_client_return(cr, NUA_ERROR_AT(__FILE__, __LINE__), msg); if (error != 0) return error; } cr->cr_msg = msg; cr->cr_sip = sip; return nua_client_request_try(cr); } msg_t *nua_client_request_template(nua_client_request_t *cr) { nua_handle_t *nh = cr->cr_owner; nua_t *nua = nh->nh_nua; nua_dialog_state_t *ds = nh->nh_ds; msg_t *msg = nta_msg_create(nua->nua_nta, 0); sip_t *sip = sip_object(msg); if (!sip) return NULL; if (nh->nh_tags) { tagi_t const *t = nh->nh_tags; /* Use the From header from the dialog. If From is set, it is always first tag in the handle */ if (ds->ds_leg && t->t_tag == siptag_from) t++; /* When the INVITE message (or any other SIP message) is * created, the tagged values saved with nua_handle() are used first. */ sip_add_tagis(msg, sip, &t); } return msg; } /** Restart the request message. * * A restarted request has not been completed successfully. * * @retval 0 if request is pending * @retval >=1 if error event has been sent */ int nua_client_restart_request(nua_client_request_t *cr, int terminating, tagi_t const *tags) { if (cr) { assert(nua_client_is_queued(cr)); if (tags && cr->cr_msg) if (sip_add_tagis(cr->cr_msg, NULL, &tags) < 0) /* XXX */; nua_client_set_terminating(cr, terminating); return nua_client_request_try(cr); } return 0; } /** Resend the request message. * * A resent request has completed once successfully - restarted has not. * * @retval 0 if request is pending * @retval >=1 if error event has been sent */ int nua_client_resend_request(nua_client_request_t *cr, int terminating) { if (cr) { cr->cr_retry_count = 0; cr->cr_challenged = 0; if (nua_client_is_queued(cr)) { if (terminating) cr->cr_graceful = 1; return 0; } if (terminating) nua_client_set_terminating(cr, terminating); if (nua_client_request_queue(cr)) return 0; if (nua_dialog_is_reporting(cr->cr_owner->nh_ds)) return 0; return nua_client_request_try(cr); } return 0; } /** Send a request message. * * If an error occurs, send error event to the application. * * @retval 0 if request is pending * @retval >=1 if error event has been sent */ static int nua_client_request_try(nua_client_request_t *cr) { int error = nua_client_request_sendmsg(cr); if (error < 0) error = nua_client_response(cr, NUA_ERROR_AT(__FILE__, __LINE__), NULL); return error; } /**Send a request message. * * @retval 0 if request is pending * @retval >=1 if error event has been sent * @retval < 0 if no error event has been sent */ static int nua_client_request_sendmsg(nua_client_request_t *cr) { nua_handle_t *nh = cr->cr_owner; nua_dialog_state_t *ds = nh->nh_ds; sip_method_t method = cr->cr_method; char const *name = cr->cr_method_name; url_string_t const *url = (url_string_t *)cr->cr_target; nta_leg_t *leg; msg_t *msg; sip_t *sip; int error; assert(cr->cr_orq == NULL); cr->cr_offer_sent = cr->cr_answer_recv = 0; cr->cr_offer_recv = cr->cr_answer_sent = 0; if (!ds->ds_leg && cr->cr_dialog) { ds->ds_leg = nta_leg_tcreate(nh->nh_nua->nua_nta, nua_stack_process_request, nh, SIPTAG_CALL_ID(cr->cr_sip->sip_call_id), SIPTAG_FROM(cr->cr_sip->sip_from), SIPTAG_TO(cr->cr_sip->sip_to), SIPTAG_CSEQ(cr->cr_sip->sip_cseq), TAG_END()); if (!ds->ds_leg) return -1; } if (cr->cr_sip->sip_from && ds->ds_leg) { if (cr->cr_sip->sip_from->a_tag == NULL) { if (sip_from_tag(msg_home(cr->cr_msg), cr->cr_sip->sip_from, nta_leg_tag(ds->ds_leg, NULL)) < 0) { return -1; } } } cr->cr_retry_count++; if (ds->ds_leg) leg = ds->ds_leg; else leg = nh->nh_nua->nua_dhandle->nh_ds->ds_leg; /* Default leg */ msg = msg_copy(cr->cr_msg), sip = sip_object(msg); if (msg == NULL) return -1; if (nua_dialog_is_established(ds)) { while (sip->sip_route) sip_route_remove(msg, sip); } else if (!ds->ds_route) { sip_route_t *initial_route = NH_PGET(nh, initial_route); if (initial_route) { initial_route = sip_route_dup(msg_home(msg), initial_route); if (!initial_route) return -1; msg_header_prepend(msg, (msg_pub_t*)sip, /* This should be (msg_header_t **)&sip->sip_route * but directly casting pointer &sip->sip_route gives * spurious type-punning warning */ (msg_header_t **)((char *)sip + offsetof(sip_t, sip_route)), (msg_header_t *)initial_route); } } /** * For in-dialog requests, the request URI is taken from the @Contact * header received from the remote party during dialog establishment, * and the NUTAG_URL() is ignored. * * Also, the @CallID and @CSeq headers and @From and @To tags are * generated based on the dialog information and added to the request. * If the dialog has a route, it is added to the request, too. */ if (nta_msg_request_complete(msg, leg, method, name, url) < 0) { msg_destroy(msg); return -1; } /**@MaxForwards header (with default value set by NTATAG_MAX_FORWARDS()) is * also added now, if it does not exist. */ if (!ds->ds_remote) ds->ds_remote = sip_to_dup(nh->nh_home, sip->sip_to); if (!ds->ds_local) ds->ds_local = sip_from_dup(nh->nh_home, sip->sip_from); /** * Next, values previously set with nua_set_params() or nua_set_hparams() * are used: @Allow, @Supported, @Organization, @UserAgent and * @AllowEvents headers are added to the request if they are not already * set. */ if (!sip->sip_allow) sip_add_dup(msg, sip, (sip_header_t*)NH_PGET(nh, allow)); if (!sip->sip_supported && NH_PGET(nh, supported)) sip_add_dup(msg, sip, (sip_header_t *)NH_PGET(nh, supported)); if (method == sip_method_register && NH_PGET(nh, path_enable) && !sip_has_feature(sip->sip_supported, "path") && !sip_has_feature(sip->sip_require, "path")) sip_add_make(msg, sip, sip_supported_class, "path"); if (!sip->sip_organization && NH_PGET(nh, organization)) sip_add_make(msg, sip, sip_organization_class, NH_PGET(nh, organization)); if (!sip->sip_user_agent && NH_PGET(nh, user_agent)) sip_add_make(msg, sip, sip_user_agent_class, NH_PGET(nh, user_agent)); /** Any node implementing one or more event packages SHOULD include an * appropriate @AllowEvents header indicating all supported events in * all methods which initiate dialogs and their responses (such as * INVITE) and OPTIONS responses. */ if (!sip->sip_allow_events && NH_PGET(nh, allow_events) && (method == sip_method_notify || /* Always in NOTIFY */ (!ds->ds_remote_tag && /* And in initial requests */ (method == sip_method_subscribe || method == sip_method_refer || method == sip_method_options || method == sip_method_invite)))) sip_add_dup(msg, sip, (void *)NH_PGET(nh, allow_events)); /** * Next, the stack generates a @Contact header for the request (unless * the application already gave a @Contact header or it does not want to * use @Contact and indicates that by including SIPTAG_CONTACT(NULL) or * SIPTAG_CONTACT(SIP_NONE) in the tagged parameters.) If the * application has registered the URI in @From header, the @Contact * header used with registration is used. Otherwise, the @Contact header * is generated from the local IP address and port number. */ /**For the initial requests, @ServiceRoute set that was received from the * registrar is also added to the request message. */ if (cr->cr_method != sip_method_register) { if (cr->cr_contactize && cr->cr_has_contact) { sip_contact_t *ltarget = sip_contact_dup(nh->nh_home, sip->sip_contact); if (ds->ds_ltarget) msg_header_free(nh->nh_home, (msg_header_t *)ds->ds_ltarget); ds->ds_ltarget = ltarget; } if (ds->ds_ltarget && !cr->cr_has_contact) sip_add_dup(msg, sip, (sip_header_t *)ds->ds_ltarget); if (nua_registration_add_contact_to_request(nh, msg, sip, cr->cr_contactize && !cr->cr_has_contact && !ds->ds_ltarget, !ds->ds_route) < 0) { msg_destroy(msg); return -1; } } cr->cr_wait_for_cred = 0; if (cr->cr_methods->crm_send) error = cr->cr_methods->crm_send(cr, msg, sip, NULL); else error = nua_base_client_request(cr, msg, sip, NULL); if (error == -1) msg_destroy(msg); return error; } /**Add tags to request message and send it, * * @retval 0 success * @retval -1 if error occurred, but event has not been sent * @retval -2 if error occurred, event has not been sent, * and @a msg has been destroyed * @retval >=1 if error event has been sent */ int nua_base_client_trequest(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tag_type_t tag, tag_value_t value, ...) { int retval; ta_list ta; ta_start(ta, tag, value); retval = nua_base_client_request(cr, msg, sip, ta_args(ta)); ta_end(ta); return retval; } /** Send request. * * @retval 0 success * @retval -1 if error occurred, but event has not been sent, * and caller has to destroy request message @ msg * @retval -2 if error occurred, event has not been sent * @retval >=1 if error event has been sent */ int nua_base_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags) { nua_handle_t *nh = cr->cr_owner; int proxy_is_set = NH_PISSET(nh, proxy); url_string_t * proxy = NH_PGET(nh, proxy); if (nh->nh_auth) { if (cr->cr_challenged || NH_PGET(nh, auth_cache) == nua_auth_cache_dialog) { if (auc_authorize(&nh->nh_auth, msg, sip) < 0) return nua_client_return(cr, 900, "Cannot add credentials", msg); } } cr->cr_seq = sip->sip_cseq->cs_seq; /* Save last sequence number */ assert(cr->cr_orq == NULL); cr->cr_orq = nta_outgoing_mcreate(nh->nh_nua->nua_nta, nua_client_orq_response, nua_client_request_ref(cr), NULL, msg, TAG_IF(proxy_is_set, NTATAG_DEFAULT_PROXY(proxy)), TAG_NEXT(tags)); if (cr->cr_orq == NULL) { nua_client_request_unref(cr); return -1; } return 0; } /** Callback for nta client transaction */ int nua_client_orq_response(nua_client_request_t *cr, nta_outgoing_t *orq, sip_t const *sip) { int status; char const *phrase; if (sip && sip->sip_status) { status = sip->sip_status->st_status; phrase = sip->sip_status->st_phrase; if (sip->sip_payload != NULL && NH_PGET(cr->cr_owner, accept_multipart) && sip->sip_multipart == NULL) { sip_content_type_t *c = sip->sip_content_type; if (c != NULL && su_casenmatch(c->c_type, "multipart/", 10)) { msg_t *msg = nta_outgoing_getresponse(orq); su_home_t *home = msg_home(msg); sip_t *request = (sip_t *)sip; sip_payload_t *pl = (sip_payload_t *)sip->sip_payload; msg_multipart_t *mp = msg_multipart_parse(home, c, pl); request->sip_multipart = mp; msg_unref(msg); } } } else { status = nta_outgoing_status(orq); phrase = ""; } nua_client_response(cr, status, phrase, sip); return 0; } /**Return response to the client request. * * Return a response generated by the stack. This function is used to return * a error response within @a nua_client_methods_t#crm_init or @a * nua_client_methods_t#crm_send functions. It takes care of disposing the @a * to_be_destroyed that cannot be sent. * * @retval 0 if response event was preliminary * @retval 1 if response event was final * @retval 2 if response event destroyed the handle, too. */ int nua_client_return(nua_client_request_t *cr, int status, char const *phrase, msg_t *to_be_destroyed) { if (to_be_destroyed) msg_destroy(to_be_destroyed); nua_client_response(cr, status, phrase, NULL); return 1; } /** Process response to the client request. * * The response can be generated by the stack (@a sip is NULL) or * returned by the remote server. * * @retval 0 if response event was preliminary * @retval 1 if response event was final * @retval 2 if response event destroyed the handle, too. */ int nua_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = cr->cr_usage; int retval = 0; if (cr->cr_restarting) return 0; nua_client_request_ref(cr); cr->cr_status = status; cr->cr_phrase = phrase; if (status < 200) { /* Xyzzy */ } else if (sip && nua_client_check_restart(cr, status, phrase, sip)) { nua_client_request_unref(cr); return 0; } else if (status < 300) { if (cr->cr_terminating) { cr->cr_terminated = 1; } else { if (sip) { if (cr->cr_contactize) nua_dialog_uac_route(nh, nh->nh_ds, sip, 1, cr->cr_initial); nua_dialog_store_peer_info(nh, nh->nh_ds, sip); } if (du && du->du_cr == cr) du->du_ready = 1; } } else { sip_method_t method = cr->cr_method; int terminated, graceful = 1; if (status < 700) terminated = sip_response_terminates_dialog(status, method, &graceful); else /* XXX - terminate usage by all internal error responses */ terminated = 0, graceful = 1; if (terminated < 0) cr->cr_terminated = terminated; else if (cr->cr_terminating || terminated) cr->cr_terminated = 1; else if (graceful) cr->cr_graceful = 1; } if (status < 200) { if (cr->cr_methods->crm_preliminary) cr->cr_methods->crm_preliminary(cr, status, phrase, sip); else nua_base_client_response(cr, status, phrase, sip, NULL); cr->cr_phrase = NULL; } else { if (cr->cr_methods->crm_recv) retval = cr->cr_methods->crm_recv(cr, status, phrase, sip); else retval = nua_base_client_response(cr, status, phrase, sip, NULL); } nua_client_request_unref(cr); return retval; } /** Check if request should be restarted. * * @retval 1 if restarted or waiting for restart * @retval 0 otherwise */ int nua_client_check_restart(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip) { nua_handle_t *nh; assert(cr && status >= 200 && phrase && sip); nh = cr->cr_owner; if (cr->cr_retry_count > NH_PGET(nh, retry_count)) return 0; if (cr->cr_methods->crm_check_restart) return cr->cr_methods->crm_check_restart(cr, status, phrase, sip); else return nua_base_client_check_restart(cr, status, phrase, sip); } int nua_base_client_check_restart(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip) { nua_handle_t *nh = cr->cr_owner; nta_outgoing_t *orq; if (status == 302 || status == 305) { sip_route_t r[1]; if (status == 302 && !NH_PGET(nh, auto302)) return 0; if (status == 305 && !NH_PGET(nh, auto305)) return 0; if (!can_redirect(sip->sip_contact, cr->cr_method)) return 0; switch (status) { case 302: if (nua_dialog_zap(nh, nh->nh_ds) == 0 && nua_client_set_target(cr, sip->sip_contact->m_url) >= 0) return nua_client_restart(cr, 100, "Redirected"); break; case 305: sip_route_init(r); *r->r_url = *sip->sip_contact->m_url; if (nua_dialog_zap(nh, nh->nh_ds) == 0 && sip_add_dup(cr->cr_msg, cr->cr_sip, (sip_header_t *)r) >= 0) return nua_client_restart(cr, 100, "Redirected via a proxy"); break; } } if (status == 423) { unsigned my_expires = 0; if (cr->cr_sip->sip_expires) my_expires = cr->cr_sip->sip_expires->ex_delta; if (sip->sip_min_expires && sip->sip_min_expires->me_delta > my_expires) { sip_expires_t ex[1]; sip_expires_init(ex); ex->ex_delta = sip->sip_min_expires->me_delta; if (sip_add_dup(cr->cr_msg, NULL, (sip_header_t *)ex) < 0) return 0; return nua_client_restart(cr, 100, "Re-Negotiating Expiration"); } } if ((status == 401 && sip->sip_www_authenticate) || (status == 407 && sip->sip_proxy_authenticate)) { int server = 0, proxy = 0; if (sip->sip_www_authenticate) server = auc_challenge(&nh->nh_auth, nh->nh_home, sip->sip_www_authenticate, sip_authorization_class); if (sip->sip_proxy_authenticate) proxy = auc_challenge(&nh->nh_auth, nh->nh_home, sip->sip_proxy_authenticate, sip_proxy_authorization_class); if (server >= 0 && proxy >= 0) { int invalid = cr->cr_challenged && server + proxy == 0; cr->cr_challenged = 1; if (invalid) { /* Bad username/password */ SU_DEBUG_7(("nua(%p): bad credentials, clearing them\n", (void *)nh)); auc_clear_credentials(&nh->nh_auth, NULL, NULL); } else if (auc_has_authorization(&nh->nh_auth)) return nua_client_restart(cr, 100, "Request Authorized by Cache"); orq = cr->cr_orq, cr->cr_orq = NULL; cr->cr_waiting = cr->cr_wait_for_cred = 1; nua_client_report(cr, status, phrase, NULL, orq, NULL); nta_outgoing_destroy(orq); cr->cr_status = 0, cr->cr_phrase = NULL; nua_client_request_unref(cr); return 1; } } if (500 <= status && status < 600 && sip->sip_retry_after && sip->sip_retry_after->af_delta < NH_PGET(nh, max_retry_after)) { su_timer_t *timer; char phrase[18]; /* Retry After XXXX\0 */ timer = su_timer_create(su_root_task(nh->nh_nua->nua_root), 0); if (su_timer_set_interval(timer, nua_client_restart_after, cr, sip->sip_retry_after->af_delta * 1000) < 0) { su_timer_destroy(timer); return 0; /* Too bad */ } cr->cr_timer = timer; /* This takes over cr reference from orq */ snprintf(phrase, sizeof phrase, "Retry After %u", (unsigned)sip->sip_retry_after->af_delta); orq = cr->cr_orq, cr->cr_orq = NULL; cr->cr_waiting = 1; nua_client_report(cr, 100, phrase, NULL, orq, NULL); nta_outgoing_destroy(orq); cr->cr_status = 0, cr->cr_phrase = NULL; return 1; } return 0; /* This was a final response that cannot be restarted. */ } su_inline int can_redirect(sip_contact_t const *m, sip_method_t method) { if (m && m->m_url->url_host) { enum url_type_e type = (enum url_type_e)m->m_url->url_type; return type == url_sip || type == url_sips || (type == url_tel && (method == sip_method_invite || method == sip_method_message)) || (type == url_im && method == sip_method_message) || (type == url_pres && method == sip_method_subscribe); } return 0; } /** @internal Add authorization data */ static int nh_authorize(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { int retval = 0; tagi_t const *ti; ta_list ta; ta_start(ta, tag, value); for (ti = ta_args(ta); ti; ti = tl_next(ti)) { if (ti->t_tag == nutag_auth && ti->t_value) { char *data = (char *)ti->t_value; int rv = auc_credentials(&nh->nh_auth, nh->nh_home, data); if (rv > 0) { retval = 1; } else if (rv < 0) { retval = -1; break; } } } ta_end(ta); return retval; } /** @NUA_EVENT nua_r_authenticate * * Response to nua_authenticate(). Under normal operation, this event is * never sent but rather the unauthenticated operation is completed. * However, if there is no operation to authentication or if there is an * authentication error the #nua_r_authenticate event is sent to the * application with the status code as follows: * - 202 No operation to restart:\n * The authenticator associated with the handle was updated, but there was * no operation to retry with the new credentials. * - 900 Cannot add credentials:\n * There was internal problem updating authenticator. * - 904 No matching challenge:\n * There was no challenge matching with the credentials provided by * nua_authenticate(), e.g., their realm did not match with the one * received with the challenge. * * @param status status code from authentication * @param phrase a short textual description of @a status code * @param nh operation handle authenticated * @param hmagic application context associated with the handle * @param sip NULL * @param tags empty * * @sa nua_terminate(), nua_handle_destroy() * * @END_NUA_EVENT */ void nua_stack_authenticate(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { nua_client_request_t *cr = nh->nh_ds->ds_cr; int status = nh_authorize(nh, TAG_NEXT(tags)); if (status > 0) { if (cr && cr->cr_wait_for_cred) { cr->cr_waiting = cr->cr_wait_for_cred = 0; nua_client_restart_request(cr, cr->cr_terminating, tags); } else { nua_stack_event(nua, nh, NULL, e, 202, "No operation to restart", NULL); } } else if (cr && cr->cr_wait_for_cred) { cr->cr_waiting = cr->cr_wait_for_cred = 0; if (status < 0) nua_client_response(cr, 900, "Operation cannot add credentials", NULL); else nua_client_response(cr, 904, "Operation has no matching challenge ", NULL); } else if (status < 0) { nua_stack_event(nua, nh, NULL, e, 900, "Cannot add credentials", NULL); } else { nua_stack_event(nua, nh, NULL, e, 904, "No matching challenge", NULL); } } /** Request restarted by timer */ static void nua_client_restart_after(su_root_magic_t *magic, su_timer_t *timer, nua_client_request_t *cr) { cr->cr_waiting = 0; su_timer_destroy(cr->cr_timer), cr->cr_timer = NULL; nua_client_restart_request(cr, cr->cr_terminating, NULL); nua_client_request_unref(cr); } /** Restart request. * * @retval 1 if restarted * @retval 0 otherwise */ int nua_client_restart(nua_client_request_t *cr, int status, char const *phrase) { nua_handle_t *nh = cr->cr_owner; nta_outgoing_t *orq; int error = -1, terminated, graceful; if (cr->cr_retry_count > NH_PGET(nh, retry_count)) return 0; orq = cr->cr_orq, cr->cr_orq = NULL; assert(orq); terminated = cr->cr_terminated, cr->cr_terminated = 0; graceful = cr->cr_graceful, cr->cr_graceful = 0; cr->cr_restarting = 1; error = nua_client_request_sendmsg(cr); cr->cr_restarting = 0; if (error) { cr->cr_graceful = graceful; cr->cr_terminated = terminated; assert(cr->cr_orq == NULL); cr->cr_orq = orq; return 0; } nua_client_report(cr, status, phrase, NULL, orq, NULL); nta_outgoing_destroy(orq); nua_client_request_unref(cr); /* ... reference used by old orq */ return 1; } int nua_client_set_target(nua_client_request_t *cr, url_t const *target) { url_t *new_target, *old_target = cr->cr_target; if (!target || target == old_target) return 0; new_target = url_hdup(cr->cr_owner->nh_home, (url_t *)target); if (!new_target) return -1; cr->cr_target = new_target; if (old_target) su_free(cr->cr_owner->nh_home, old_target); return 0; } /**@internal * Relay response event to the application. * * @todo * If handle has already been marked as destroyed by nua_handle_destroy(), * release the handle with nh_destroy(). * * @retval 0 if event was preliminary * @retval 1 if event was final * @retval 2 if event destroyed the handle, too. */ int nua_base_client_tresponse(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip, tag_type_t tag, tag_value_t value, ...) { ta_list ta; int retval; if (cr->cr_event == nua_r_destroy) return nua_base_client_response(cr, status, phrase, sip, NULL); ta_start(ta, tag, value); retval = nua_base_client_response(cr, status, phrase, sip, ta_args(ta)); ta_end(ta); return retval; } /**@internal * Relay response event to the application. * * @todo * If handle has already been marked as destroyed by nua_handle_destroy(), * release the handle with nh_destroy(). * * @retval 0 if event was preliminary * @retval 1 if event was final * @retval 2 if event destroyed the handle, too. */ int nua_base_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip, tagi_t const *tags) { nua_handle_t *nh = cr->cr_owner; sip_method_t method = cr->cr_method; nua_dialog_usage_t *du; cr->cr_reporting = 1, nh->nh_ds->ds_reporting = 1; if (nh->nh_auth && sip && (sip->sip_authentication_info || sip->sip_proxy_authentication_info)) { /* Collect nextnonce */ if (sip->sip_authentication_info) auc_info(&nh->nh_auth, sip->sip_authentication_info, sip_authorization_class); if (sip->sip_proxy_authentication_info) auc_info(&nh->nh_auth, sip->sip_proxy_authentication_info, sip_proxy_authorization_class); } if ((method != sip_method_invite && status >= 200) || status >= 300) nua_client_request_remove(cr); nua_client_report(cr, status, phrase, sip, cr->cr_orq, tags); if (status < 200 || /* Un-ACKed 2XX response to INVITE */ (method == sip_method_invite && status < 300 && !cr->cr_acked)) { cr->cr_reporting = 0, nh->nh_ds->ds_reporting = 0; return 1; } nua_client_request_clean(cr); du = cr->cr_usage; if (cr->cr_terminated < 0) { /* XXX - dialog has been terminated */; nua_dialog_deinit(nh, nh->nh_ds), cr->cr_usage = NULL; } else if (du) { if (cr->cr_terminated || (!du->du_ready && status >= 300 && nua_client_is_bound(cr))) { /* Usage has been destroyed */ nua_dialog_usage_remove(nh, nh->nh_ds, du, cr, NULL), cr->cr_usage = NULL; } else if (cr->cr_graceful) { /* Terminate usage gracefully */ if (nua_dialog_usage_shutdown(nh, nh->nh_ds, du) > 0) cr->cr_usage = NULL; } } else if (cr->cr_terminated) { if (nh->nh_ds->ds_usage == NULL) nua_dialog_remove(nh, nh->nh_ds, NULL), cr->cr_usage = NULL; } cr->cr_phrase = NULL; cr->cr_reporting = 0, nh->nh_ds->ds_reporting = 0; if (method == sip_method_cancel) return 1; return nua_client_next_request(nh->nh_ds->ds_cr, method == sip_method_invite); } /** Send event, zap transaction but leave cr in list */ int nua_client_report(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip, nta_outgoing_t *orq, tagi_t const *tags) { nua_handle_t *nh; if (cr->cr_event == nua_r_destroy) return 1; if (cr->cr_methods->crm_report) return cr->cr_methods->crm_report(cr, status, phrase, sip, orq, tags); nh = cr->cr_owner; nua_stack_event(nh->nh_nua, nh, nta_outgoing_getresponse(orq), (enum nua_event_e)cr->cr_event, status, phrase, tags); return 1; } int nua_client_treport(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip, nta_outgoing_t *orq, tag_type_t tag, tag_value_t value, ...) { int retval; ta_list ta; ta_start(ta, tag, value); retval = nua_client_report(cr, status, phrase, sip, orq, ta_args(ta)); ta_end(ta); return retval; } int nua_client_next_request(nua_client_request_t *cr, int invite) { for (; cr; cr = cr->cr_next) { if (cr->cr_method == sip_method_cancel) continue; if (invite ? cr->cr_method == sip_method_invite : cr->cr_method != sip_method_invite) break; } if (cr && !nua_client_request_in_progress(cr)) { nua_client_init_request(cr); } return 1; } nua_client_request_t * nua_client_request_pending(nua_client_request_t const *cr) { for (;cr;cr = cr->cr_next) if (cr->cr_orq) return (nua_client_request_t *)cr; return NULL; } /**@internal * Save handle parameters and initial authentication info. * * @retval -1 upon an error * @retval 0 when successful */ int nua_stack_init_handle(nua_t *nua, nua_handle_t *nh, tagi_t const *tags) { int retval = 0; if (nh == NULL) return -1; assert(nh != nua->nua_dhandle); if (nua_stack_set_params(nua, nh, nua_i_error, tags) < 0) retval = -1; if (retval || nh->nh_init) /* Already initialized? */ return retval; if (nh->nh_tags) nh_authorize(nh, TAG_NEXT(nh->nh_tags)); nh->nh_init = 1; return 0; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/nua_client.h000066400000000000000000000253341223300710500226360ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2006, 2009 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef NUA_CLIENT_H /** Defined when has been included. */ #define NUA_CLIENT_H /**@IFILE nua_client.h * @brief Client requests * * @author Pekka Pessi * @author Kai Vehmanen * * @date Created: Tue Feb 3 15:50:35 EET 2009 ppessi */ #include /* Methods for client request. @internal */ typedef struct { sip_method_t crm_method; char const *crm_method_name; size_t crm_extra; /**< Size of private data */ struct { unsigned create_dialog:1, in_dialog:1, target_refresh:1; unsigned:0; } crm_flags; /** Generate a request message. * * @retval 1 when request message has been created * @retval 0 when request message should be created in normal fashion * @retval -1 upon an error */ int (*crm_template)(nua_client_request_t *cr, msg_t **return_msg, tagi_t const *tags); /**@a crm_init is called when a client request is sent first time. * * @retval 1 when request has been responded * @retval 0 when request should be sent in normal fashion * @retval -1 upon an error */ int (*crm_init)(nua_client_request_t *, msg_t *msg, sip_t *sip, tagi_t const *tags); /** @a crm_send is called each time when a client request is sent. * * @retval 1 when request has been responded * @retval 0 when request has been sent * @retval -1 upon an error (but request message has not been destroyed) * @retval -2 upon an error */ int (*crm_send)(nua_client_request_t *, msg_t *msg, sip_t *sip, tagi_t const *tags); /** @a crm_check_restart is called each time when a response is received. * * It is used to restart request after responses with method-specific * status code or method-specific way of restarting the request. * * @retval 1 when request has been restarted * @retval 0 when response should be processed normally */ int (*crm_check_restart)(nua_client_request_t *, int status, char const *phrase, sip_t const *sip); /** @a crm_recv is called each time a final response is received. * * A final response is in range 200 .. 699 (or internal response) and it * cannot be restarted. * * crm_recv() should call nua_base_client_response() or * nua_base_client_tresponse(). The return values below are documented with * nua_base_client_response(), too. * * @retval 0 if response was preliminary * @retval 1 if response was final * @retval 2 if response destroyed the handle, too. */ int (*crm_recv)(nua_client_request_t *, int status, char const *phrase, sip_t const *sip); /** @a crm_preliminary is called each time a preliminary response is received. * * A preliminary response is in range 101 .. 199. * * crm_preliminary() should call nua_base_client_response() or * nua_base_client_tresponse(). * * @retval 0 if response was preliminary * @retval 1 if response was final * @retval 2 if response destroyed the handle, too. */ int (*crm_preliminary)(nua_client_request_t *, int status, char const *phrase, sip_t const *sip); /** @a crm_report is called each time a response is received and it is * reported to the application. * * The status and phrase may be different from the status and phrase * received from the network, e.g., when the request is restarted. * * @return The return value should be 0. It is currently ignored. */ int (*crm_report)(nua_client_request_t *, int status, char const *phrase, sip_t const *sip, nta_outgoing_t *orq, tagi_t const *tags); /** @a crm_complete is called when a client-side request is destroyed. * * @return The return value should be 0. It is currently ignored. */ int (*crm_complete)(nua_client_request_t *); } nua_client_methods_t; /* Client-side request. Documented by nua_client_create() */ struct nua_client_request { nua_client_request_t *cr_next, **cr_prev; /**< Linked list of requests */ nua_owner_t *cr_owner; nua_dialog_usage_t *cr_usage; nua_saved_signal_t cr_signal[1]; tagi_t const *cr_tags; nua_client_methods_t const *cr_methods; msg_t *cr_msg; sip_t *cr_sip; nta_outgoing_t *cr_orq; su_timer_t *cr_timer; /**< Expires or retry timer */ /*nua_event_t*/ int cr_event; /**< Request event */ sip_method_t cr_method; char const *cr_method_name; url_t *cr_target; char const *cr_phrase; /**< Latest status phrase */ unsigned short cr_status; /**< Latest status */ unsigned short cr_retry_count; /**< Retry count for this request */ uint32_t cr_seq; unsigned cr_refs; /**< References to client request */ /* Flags used with offer-answer */ unsigned short cr_answer_recv; /**< Recv answer in response * with this status. */ unsigned cr_offer_sent:1; /**< Sent offer in this request */ unsigned cr_offer_recv:1; /**< Recv offer in a response */ unsigned cr_answer_sent:1; /**< Sent answer in (PR)ACK */ /* Flags with usage */ unsigned cr_neutral:1; /**< No effect on session or other usage */ /* Lifelong flags? */ unsigned cr_auto:1; /**< Request was generated by stack */ unsigned cr_has_contact:1; /**< Request has user Contact */ unsigned cr_contactize:1; /**< Request needs Contact */ unsigned cr_dialog:1; /**< Request can initiate dialog */ /* Current state */ unsigned cr_initial:1; /**< Initial request of a dialog */ unsigned cr_acked:1; /**< Final response to the request has been ACKed */ unsigned cr_waiting:1; /**< Request is waiting */ unsigned cr_challenged:1; /**< Request was challenged */ unsigned cr_wait_for_cred:1; /**< Request is pending authentication */ unsigned cr_restarting:1; /**< Request is being restarted */ unsigned cr_reporting:1; /**< Reporting in progress */ unsigned cr_terminating:1; /**< Request terminates the usage */ signed int cr_terminated:2; /**< Response terminated usage (1) or whole dialog (-1) */ unsigned cr_graceful:1; /**< Graceful termination required */ }; int nua_client_create(nua_owner_t *owner, int event, nua_client_methods_t const *methods, tagi_t const *tags); int nua_client_tcreate(nua_owner_t *nh, int event, nua_client_methods_t const *methods, tag_type_t tag, tag_value_t value, ...); su_inline void *nua_private_client_request(nua_client_request_t const *cr) { return (void *)(cr + 1); } nua_client_request_t *nua_client_request_ref(nua_client_request_t *); int nua_client_request_unref(nua_client_request_t *); #if HAVE_MEMLEAK_LOG #define nua_client_request_ref(cr) \ nua_client_request_ref_by((cr), __FILE__, __LINE__, __func__) #define nua_client_request_unref(cr) \ nua_client_request_unref_by((cr), __FILE__, __LINE__, __func__) nua_client_request_t *nua_client_request_ref_by(nua_client_request_t *, char const *file, unsigned line, char const *who); int nua_client_request_unref_by(nua_client_request_t *, char const *file, unsigned line, char const *who); #endif int nua_client_request_queue(nua_client_request_t *cr); su_inline int nua_client_is_queued(nua_client_request_t const *cr) { return cr && cr->cr_prev; } int nua_client_request_in_progress(nua_client_request_t const *cr); int nua_client_request_complete(nua_client_request_t *cr); int nua_client_request_remove(nua_client_request_t *cr); int nua_client_request_clean(nua_client_request_t *cr); int nua_client_bind(nua_client_request_t *cr, nua_dialog_usage_t *du); su_inline int nua_client_is_bound(nua_client_request_t const *cr) { return cr && cr->cr_usage && cr->cr_usage->du_cr == cr; } su_inline int nua_client_is_reporting(nua_client_request_t const *cr) { return cr && cr->cr_reporting; } /** Mark client request as a terminating one */ su_inline void nua_client_set_terminating(nua_client_request_t *cr, int value) { cr->cr_terminating = value != 0; } int nua_client_init_request(nua_client_request_t *cr); msg_t *nua_client_request_template(nua_client_request_t *cr); int nua_client_restart_request(nua_client_request_t *cr, int terminating, tagi_t const *tags); int nua_client_resend_request(nua_client_request_t *cr, int terminating); int nua_base_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags); int nua_base_client_trequest(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tag_type_t tag, tag_value_t value, ...); extern nta_response_f nua_client_orq_response; int nua_client_return(nua_client_request_t *cr, int status, char const *phrase, msg_t *to_be_destroyed); int nua_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip); int nua_client_check_restart(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip); int nua_base_client_check_restart(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip); int nua_client_restart(nua_client_request_t *cr, int status, char const *phrase); int nua_base_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip, tagi_t const *tags); int nua_base_client_tresponse(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip, tag_type_t tag, tag_value_t value, ...); int nua_client_set_target(nua_client_request_t *cr, url_t const *target); int nua_client_report(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip, nta_outgoing_t *orq, tagi_t const *tags); nua_client_request_t *nua_client_request_pending(nua_client_request_t const *); int nua_client_next_request(nua_client_request_t *cr, int invite); #endif /* NUA_CLIENT_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/nua_common.c000066400000000000000000000304451223300710500226420ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE nua_common.c * @brief Function common to both stack and application side. * * @author Pekka.Pessi@nokia.com * * @date Created: Tue Apr 26 13:23:17 2005 ppessi * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #define SU_LOG (nua_log) #include #define SU_ROOT_MAGIC_T struct nua_s #include #include #include #include "sofia-sip/nua.h" #include "sofia-sip/nua_tag.h" #include #include #include #include #if HAVE_SMIME /* Start NRC Boston */ #include "smimec.h" #endif /* End NRC Boston */ #include #include "nua_stack.h" static void nh_destructor(void *arg); /**@internal * Create an operation handle * * Allocates a new operation handle and associated storage. * * @param nua Pointer to NUA stack object * @param hmagic Pointer to callback context * @param tags List of tagged parameters * * @retval non-NULL Pointer to operation handle * @retval NULL Creation failed * * @par Related tags: * Creates a copy of the provided tags which will * be used with every operation. * * @par Events: * none * * @note * This function is called by both stack and application sides. */ nua_handle_t *nh_create_handle(nua_t *nua, nua_hmagic_t *hmagic, tagi_t *tags) { nua_handle_t *nh; static int8_t _handle_lifetime = 1; enter; assert(nua->nua_home); if ((nh = su_home_clone(nua->nua_home, sizeof(*nh)))) { nh->nh_valid = nua_valid_handle_cookie; nh->nh_nua = nua; nh->nh_magic = hmagic; nh->nh_prefs = nua->nua_dhandle->nh_prefs; nh->nh_ds->ds_owner = nh; if (nua_handle_save_tags(nh, tags) < 0) { SU_DEBUG_5(("nua(%p): creating handle %p failed\n", (void *)nua, (void *)nh)); su_home_unref(nh->nh_home), nh = NULL; } if (nh && su_home_is_threadsafe(nua->nua_home)) { if (su_home_threadsafe(nh->nh_home) < 0) { su_home_unref(nh->nh_home); nh = NULL; } } if (nh && _handle_lifetime) { /* This far, we have nothing real to destruct but * when _NUA_HANDLE_DEBUG is set, we add destructor * and get more entertaining debugging output */ if (_handle_lifetime == 1 && !getenv("_NUA_HANDLE_DEBUG")) { _handle_lifetime = 0; } else { _handle_lifetime = 2; SU_DEBUG_0(("nh_handle_create(%p)\n", (void *)nh)); su_home_destructor(nh->nh_home, nh_destructor); } } } return nh; } /**@var _NUA_HANDLE_DEBUG * * If this environment variable is set, nua stack logs a message whenever a * handle is created and when it is destroyed. This is mainly useful when * debugging #nua_handle_t leaks. * * @sa nua_handle(), nua_handle_destroy() */ extern char const _NUA_HANDLE_DEBUG[]; /* nua handle destructor. It does nothing. */ static void nh_destructor(void *arg) { nua_handle_t *nh = arg; SU_DEBUG_0(("nh_destructor(%p)\n", (void *)nh)); } #if HAVE_MEMLEAK_LOG nua_handle_t * _nua_handle_ref_by(nua_handle_t *nh, char const *file, unsigned line, char const *function) { if (nh) SU_DEBUG_0(("%p - nua_handle_ref() => "MOD_ZU" by %s:%u: %s()\n", nh, su_home_refcount((su_home_t *)nh) + 1, file, line, by)); return (nua_handle_t *)su_home_ref((su_home_t *)nh); } int _nua_handle_unref_by(nua_handle_t *nh, char const *file, unsigned line, char const *function) { if (nh) { size_t refcount = su_home_refcount((su_home_t *)nh) - 1; int freed = su_home_unref((su_home_t *)nh); if (freed) refcount = 0; SU_DEBUG_0(("%p - nua_handle_unref() => "MOD_ZU" by %s:%u: %s()\n", nh, refcount, file, line, by)); return freed; } return 0; } nua_handle_t *nua_handle_ref(nua_handle_t *nh) { return _nua_handle_ref_by(nh, "", 0, "") } int nua_handle_unref(nua_handle_t *nh) { return _nua_handle_unref_by(nh, "", 0, "") } #else /** Make a new reference to handle. * * The handles use reference counting for memory management. In addition to * the memory management, there is protocol state associated with the * handles. The protocol state is terminated with nua_handle_destroy(). In * order to make it more convenient for programmer, nua_handle_destroy() * decreases the reference count, too. * * @note All handle references are destroyed when the nua object is destroyed. * * @sa nua_handle_unref(), nua_handle(), nua_handle_destroy(). */ nua_handle_t *nua_handle_ref(nua_handle_t *nh) { return (nua_handle_t *)su_home_ref(nh->nh_home); } /** Destroy reference to handle. * * The handles use reference counting for memory management. In addition to * the memory management, there is protocol state associated with the * handles. The protocol state is terminated with nua_handle_destroy(). In * order to make it more convenient for programmer, nua_handle_destroy() * decreases the reference count, too. * * @sa nua_handle_ref(), nua_handle(), nua_handle_destroy(). */ int nua_handle_unref(nua_handle_t *nh) { return su_home_unref(nh->nh_home); } #endif /** Generate an instance identifier. */ char const *nua_generate_instance_identifier(su_home_t *home) { char str[su_guid_strlen + 1]; su_guid_t guid[1]; su_guid_generate(guid); /* * Guid looks like "NNNNNNNN-NNNN-NNNN-NNNN-XXXXXXXXXXXX" * where NNNNNNNN-NNNN-NNNN-NNNN is timestamp and XX is MAC address * (but we use usually random ID for MAC because we do not have * guid generator available for all processes within node) */ su_guid_sprintf(str, su_guid_strlen + 1, guid); return su_strdup(home, str); } /** Check if event is a request that can be responded with nua_respond(). * * Note that if event status is 200 or greater, it already has been * responded. This function is provided for compatibility with future * versions of nua. An unknown event can always be handled in the event * callback like this: * @code * switch (event) { * ... * default: * if (status < 200 && nua_event_is_incoming_request(event)) * nua_respond(nh, SIP_501_NOT_IMPLEMENTED, * NUTAG_WITH_THIS(nua), TAG_END()); * if (hmagic == NULL) * nua_handle_destroy(nh); * return; * ... * @endcode * * @sa nua_respond(), #nua_event_e, #nua_event_t, nua_event_name() * * @NEW_1_12_6. */ int nua_event_is_incoming_request(nua_event_t event) { switch (event) { case nua_i_invite: return 1; case nua_i_cancel: return 1; case nua_i_register: return 1; case nua_i_bye: return 1; case nua_i_options: return 1; case nua_i_refer: return 1; case nua_i_publish: return 1; case nua_i_prack: return 1; case nua_i_info: return 1; case nua_i_update: return 1; case nua_i_message: return 1; case nua_i_subscribe: return 1; case nua_i_notify: return 1; case nua_i_method: return 1; default: return 0; } } /** Get name for a NUA event. * * @sa #nua_event_e, #nua_event_t, nua_callstate_name(), nua_substate_name() */ char const *nua_event_name(nua_event_t event) { switch (event) { case nua_i_none: return "nua_i_none"; case nua_i_error: return "nua_i_error"; case nua_i_invite: return "nua_i_invite"; case nua_i_cancel: return "nua_i_cancel"; case nua_i_ack: return "nua_i_ack"; case nua_i_register: return "nua_i_register"; case nua_i_fork: return "nua_i_fork"; case nua_i_active: return "nua_i_active"; case nua_i_terminated: return "nua_i_terminated"; case nua_i_state: return "nua_i_state"; case nua_i_outbound: return "nua_i_outbound"; case nua_i_bye: return "nua_i_bye"; case nua_i_options: return "nua_i_options"; case nua_i_refer: return "nua_i_refer"; case nua_i_publish: return "nua_i_publish"; case nua_i_prack: return "nua_i_prack"; case nua_i_info: return "nua_i_info"; case nua_i_update: return "nua_i_update"; case nua_i_message: return "nua_i_message"; case nua_i_chat: return "nua_i_chat"; case nua_i_subscribe: return "nua_i_subscribe"; case nua_i_subscription: return "nua_i_subscription"; case nua_i_notify: return "nua_i_notify"; case nua_i_method: return "nua_i_method"; case nua_i_media_error: return "nua_i_media_error"; /* Responses */ case nua_r_get_params: return "nua_r_get_params"; case nua_r_shutdown: return "nua_r_shutdown"; case nua_r_notifier: return "nua_r_notifier"; case nua_r_terminate: return "nua_r_terminate"; case nua_r_register: return "nua_r_register"; case nua_r_unregister: return "nua_r_unregister"; case nua_r_invite: return "nua_r_invite"; case nua_r_bye: return "nua_r_bye"; case nua_r_options: return "nua_r_options"; case nua_r_refer: return "nua_r_refer"; case nua_r_publish: return "nua_r_publish"; case nua_r_unpublish: return "nua_r_unpublish"; case nua_r_info: return "nua_r_info"; case nua_r_prack: return "nua_r_prack"; case nua_r_update: return "nua_r_update"; case nua_r_message: return "nua_r_message"; case nua_r_chat: return "nua_r_chat"; case nua_r_subscribe: return "nua_r_subscribe"; case nua_r_unsubscribe: return "nua_r_unsubscribe"; case nua_r_notify: return "nua_r_notify"; case nua_r_method: return "nua_r_method"; case nua_r_cancel: return "nua_r_cancel"; case nua_r_authenticate: return "nua_r_authenticate"; case nua_r_authorize: return "nua_r_authorize"; case nua_r_redirect: return "nua_r_redirect"; case nua_r_destroy: return "nua_r_destroy"; case nua_r_respond: return "nua_r_respond"; case nua_r_nit_respond: return "nua_r_nit_respond"; case nua_r_set_params: return "nua_r_set_params"; case nua_r_ack: return "nua_r_ack"; default: return "NUA_UNKNOWN"; } } /** Return name of call state. * * @sa enum #nua_callstate, nua_event_name(), nua_substate_name() */ char const *nua_callstate_name(enum nua_callstate state) { switch (state) { case nua_callstate_init: return "init"; case nua_callstate_authenticating: return "authenticating"; case nua_callstate_calling: return "calling"; case nua_callstate_proceeding: return "proceeding"; case nua_callstate_completing: return "completing"; case nua_callstate_received: return "received"; case nua_callstate_early: return "early"; case nua_callstate_completed: return "completed"; case nua_callstate_ready: return "ready"; case nua_callstate_terminating: return "terminating"; case nua_callstate_terminated: return "terminated"; default: return "UNKNOWN"; } } /** Return name of subscription state. @NEW_1_12_5. * * @sa enum #nua_substate, nua_event_name(), nua_callstate_name() */ char const *nua_substate_name(enum nua_substate substate) { switch (substate) { case nua_substate_embryonic: /*FALLTHROUGH*/ case nua_substate_pending: return "pending"; case nua_substate_terminated: return "terminated"; case nua_substate_active: /*FALLTHROUGH*/ default: return "active"; } } /** Convert string to enum nua_substate. @NEW_1_12_5. */ enum nua_substate nua_substate_make(char const *sip_substate) { if (sip_substate == NULL) return nua_substate_active; else if (su_casematch(sip_substate, "terminated")) return nua_substate_terminated; else if (su_casematch(sip_substate, "pending")) return nua_substate_pending; else /* if (su_casematch(sip_substate, "active")) */ return nua_substate_active; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/nua_dialog.c000066400000000000000000000401621223300710500226060ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2006 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE nua_dialog.c * @brief Dialog and dialog usage handling * * @author Pekka Pessi * * @date Created: Wed Mar 8 11:48:49 EET 2006 ppessi */ #include "config.h" #include #include #include #include #include #include #include #include #include #define NUA_OWNER_T su_home_t #include "nua_dialog.h" #define SU_LOG (nua_log) #include #ifndef NONE #define NONE ((void *)(intptr_t)-1) #endif /* ======================================================================== */ /* Dialog handling */ static void nua_dialog_usage_remove_at(nua_owner_t*, nua_dialog_state_t*, nua_dialog_usage_t**, nua_client_request_t *cr, nua_server_request_t *sr); static void nua_dialog_log_usage(nua_owner_t *, nua_dialog_state_t *); /**@internal * UAS tag and route. * * Update dialog tags and route on the UAS side. * * @param own dialog owner * @param ds dialog state * @param sip SIP message containing response used to update dialog * @param rtag if true, set remote tag within the leg */ void nua_dialog_uas_route(nua_owner_t *own, nua_dialog_state_t *ds, sip_t const *sip, int rtag) { int established = nua_dialog_is_established(ds); if (!established && sip->sip_from->a_tag) ds->ds_remote_tag = su_strdup(own, sip->sip_from->a_tag); if (ds->ds_leg == NULL) return; nta_leg_server_route(ds->ds_leg, sip->sip_record_route, sip->sip_contact); ds->ds_route = ds->ds_route || sip->sip_record_route || sip->sip_contact; if (rtag && !established && sip->sip_from->a_tag) nta_leg_rtag(ds->ds_leg, sip->sip_from->a_tag); } /**@internal * UAC tag and route. * * Update dialog tags and route on the UAC side. * * @param own dialog owner * @param ds dialog state * @param sip SIP message containing response used to update dialog * @param rtag if true, set remote tag within the leg * @param initial if true, @a sip is response to initial transaction */ void nua_dialog_uac_route(nua_owner_t *own, nua_dialog_state_t *ds, sip_t const *sip, int rtag, int initial) { int established = nua_dialog_is_established(ds); int status = sip->sip_status->st_status; if (!established && sip->sip_to->a_tag) ds->ds_remote_tag = su_strdup(own, sip->sip_to->a_tag); if (ds->ds_leg == NULL) return; if (initial && status >= 200) nta_leg_client_reroute(ds->ds_leg, sip->sip_record_route, sip->sip_contact, 1); else nta_leg_client_reroute(ds->ds_leg, sip->sip_record_route, sip->sip_contact, 0); ds->ds_route = ds->ds_route || sip->sip_record_route || sip->sip_contact; if (rtag && !established && sip->sip_to->a_tag) nta_leg_rtag(ds->ds_leg, sip->sip_to->a_tag); } /**@internal Store information from remote endpoint. */ void nua_dialog_store_peer_info(nua_owner_t *own, nua_dialog_state_t *ds, sip_t const *sip) { nua_dialog_peer_info_t *nr = ds->ds_remote_ua; nua_dialog_usage_t *du; nua_dialog_peer_info_t old[1]; *old = *nr; if (sip && sip->sip_status && sip->sip_status->st_status >= 300 && sip->sip_status->st_status <= 399) sip = NULL; /* Redirected */ if (sip == NULL) { nr->nr_allow = NULL, su_free(own, old->nr_allow); nr->nr_accept = NULL, su_free(own, old->nr_accept); nr->nr_require = NULL, su_free(own, old->nr_require); nr->nr_supported = NULL, su_free(own, old->nr_supported); nr->nr_user_agent = NULL, su_free(own, old->nr_user_agent); return; } if (sip->sip_allow) { nr->nr_allow = sip_allow_dup(own, sip->sip_allow); su_free(own, old->nr_allow); } if (sip->sip_accept) { nr->nr_accept = sip_accept_dup(own, sip->sip_accept); su_free(own, old->nr_accept); } if (sip->sip_require) { nr->nr_require = sip_require_dup(own, sip->sip_require); su_free(own, old->nr_require); } if (sip->sip_supported) { nr->nr_supported = sip_supported_dup(own, sip->sip_supported); su_free(own, old->nr_supported); } if (sip->sip_user_agent) { nr->nr_user_agent = sip_user_agent_dup(own, sip->sip_user_agent); su_free(own, old->nr_user_agent); } else if (sip->sip_server) { nr->nr_user_agent = sip_user_agent_dup(own, sip->sip_server); su_free(own, old->nr_user_agent); } for (du = ds->ds_usage; du; du = du->du_next) { if (du->du_class->usage_peer_info) du->du_class->usage_peer_info(du, ds, sip); } } /** Remove dialog information. */ int nua_dialog_zap(nua_owner_t *own, nua_dialog_state_t *ds) { /* zap peer info */ nua_dialog_store_peer_info(own, ds, NULL); /* Local Contact */ msg_header_free(own, (msg_header_t *)ds->ds_ltarget), ds->ds_ltarget = NULL; /* Leg */ nta_leg_destroy(ds->ds_leg), ds->ds_leg = NULL; /* Remote tag */ su_free(own, (void *)ds->ds_remote_tag), ds->ds_remote_tag = NULL; /* Ready to set route/remote target */ ds->ds_route = 0; return 0; } /** Remove dialog (if there is no other usages). */ int nua_dialog_remove(nua_owner_t *own, nua_dialog_state_t *ds, nua_dialog_usage_t *usage) { if (ds->ds_usage == usage && (usage == NULL || usage->du_next == NULL)) { return nua_dialog_zap(own, ds); } return 0; } /** @internal Get dialog usage slot. */ nua_dialog_usage_t ** nua_dialog_usage_at(nua_dialog_state_t const *ds, nua_usage_class const *kind, sip_event_t const *event) { static nua_dialog_usage_t *none = NULL; if (ds) { nua_dialog_usage_t *du, * const * prev; sip_event_t const *o; for (prev = &ds->ds_usage; (du = *prev); prev = &du->du_next) { if (du->du_class != kind) continue; if (event == NONE) return (nua_dialog_usage_t **)prev; o = du->du_event; if (!event && !o) return (nua_dialog_usage_t **)prev; if (event != o) { if (event == NULL || o == NULL) continue; if (!su_strmatch(event->o_type, o->o_type)) continue; if (!su_casematch(event->o_id, o->o_id)) { if (event->o_id || !su_strmatch(event->o_type, "refer")) continue; } } return (nua_dialog_usage_t **)prev; } } return &none; } /** @internal Get a dialog usage */ nua_dialog_usage_t *nua_dialog_usage_get(nua_dialog_state_t const *ds, nua_usage_class const *kind, sip_event_t const *event) { return *nua_dialog_usage_at(ds, kind, event); } /** @internal Get dialog usage name */ char const *nua_dialog_usage_name(nua_dialog_usage_t const *du) { if (du == NULL) return ""; return du->du_class->usage_name(du); } /** @internal Add dialog usage */ nua_dialog_usage_t *nua_dialog_usage_add(nua_owner_t *own, struct nua_dialog_state *ds, nua_usage_class const *uclass, sip_event_t const *event) { if (ds) { sip_event_t *o; nua_dialog_usage_t *du, **prev_du; prev_du = nua_dialog_usage_at(ds, uclass, event); du = *prev_du; if (du) { /* Already exists */ SU_DEBUG_5(("nua(%p): adding already existing %s usage%s%s\n", (void *)own, nua_dialog_usage_name(du), event ? " with event " : "", event ? event->o_type : "")); if (prev_du != &ds->ds_usage) { /* Move as a first usage in the list */ *prev_du = du->du_next; du->du_next = ds->ds_usage; ds->ds_usage = du; } return du; } o = event ? sip_event_dup(own, event) : NULL; if (o != NULL || event == NULL) du = su_zalloc(own, sizeof *du + uclass->usage_size); if (du) { su_home_ref(own); du->du_dialog = ds; du->du_class = uclass; du->du_event = o; if (uclass->usage_add(own, ds, du) < 0) { su_free(own, o); su_free(own, du); return NULL; } SU_DEBUG_5(("nua(%p): adding %s usage%s%s\n", (void *)own, nua_dialog_usage_name(du), o ? " with event " : "", o ? o->o_type :"")); du->du_next = ds->ds_usage, ds->ds_usage = du; return du; } su_free(own, o); } return NULL; } /** @internal Remove dialog usage. */ void nua_dialog_usage_remove(nua_owner_t *own, nua_dialog_state_t *ds, nua_dialog_usage_t *du, nua_client_request_t *cr, nua_server_request_t *sr) { nua_dialog_usage_t **at; assert(own); assert(ds); assert(du); for (at = &ds->ds_usage; *at; at = &(*at)->du_next) if (du == *at) break; assert(*at); nua_dialog_usage_remove_at(own, ds, at, cr, sr); } /** @internal Remove dialog usage. * * Zap dialog state (leg, tag and route) if no usages remain. */ static void nua_dialog_usage_remove_at(nua_owner_t *own, nua_dialog_state_t *ds, nua_dialog_usage_t **at, nua_client_request_t *cr0, nua_server_request_t *sr0) { if (*at) { nua_dialog_usage_t *du = *at; sip_event_t const *o = NULL; nua_client_request_t *cr, *cr_next; nua_server_request_t *sr, *sr_next; *at = du->du_next; o = du->du_event; SU_DEBUG_5(("nua(%p): removing %s usage%s%s\n", (void *)own, nua_dialog_usage_name(du), o ? " with event " : "", o ? o->o_type :"")); du->du_class->usage_remove(own, ds, du, cr0, sr0); /* Clean reference to saved client request */ if (du->du_cr) nua_client_bind(du->du_cr, NULL); /* Clean references from queued client requests */ for (cr = ds->ds_cr; cr; cr = cr_next) { cr_next = cr->cr_next; if (cr->cr_usage == du) cr->cr_usage = NULL; } /* Clean references from queued server requests */ for (sr = ds->ds_sr; sr; sr = sr_next) { sr_next = sr->sr_next; if (sr->sr_usage == du) { sr->sr_usage = NULL; if (sr != sr0) nua_server_request_destroy(sr); } } su_home_unref(own); su_free(own, du); } /* Zap dialog if there are no more usages */ if (ds->ds_terminating) ; else if (ds->ds_usage == NULL) { nua_dialog_remove(own, ds, NULL); ds->ds_has_events = 0; return; } else { nua_dialog_log_usage(own, ds); } } static void nua_dialog_log_usage(nua_owner_t *own, nua_dialog_state_t *ds) { nua_dialog_usage_t *du; if (SU_LOG->log_level >= 3) { char buffer[160]; size_t l = 0, N = sizeof buffer; ssize_t n; buffer[0] = '\0'; for (du = ds->ds_usage; du; du = du->du_next) { msg_header_t const *h = (void *)du->du_event; if (!h) continue; n = sip_event_e(buffer + l, N - l, h, 0); if (n == -1) break; l += (size_t)n; if (du->du_next && l + 2 < sizeof(buffer)) { strcpy(buffer + l, ", "); l += 2; } } SU_DEBUG_3(("nua(%p): handle with %s%s%s\n", (void *)own, ds->ds_has_session ? "session and " : "", ds->ds_has_events ? "events " : "", buffer)); } } /** Deinitialize dialog and its usage. @internal */ void nua_dialog_deinit(nua_owner_t *own, nua_dialog_state_t *ds) { ds->ds_terminating = 1; while (ds->ds_usage) { nua_dialog_usage_remove_at(own, ds, &ds->ds_usage, NULL, NULL); } nua_dialog_remove(own, ds, NULL); ds->ds_has_events = 0; ds->ds_terminating = 0; } void nua_dialog_update_params(nua_dialog_state_t *ds, nua_handle_preferences_t const *changed, nua_handle_preferences_t const *params, nua_handle_preferences_t const *defaults) { nua_dialog_usage_t *usage; for (usage = ds->ds_usage; usage; usage = usage->du_next) { usage->du_class->usage_update_params(usage, changed, params, defaults); } } void nua_base_usage_update_params(nua_dialog_usage_t const *du, nua_handle_preferences_t const *changed, nua_handle_preferences_t const *params, nua_handle_preferences_t const *defaults) { (void)du, (void)changed, (void)params, (void)defaults; } /**@internal * Set refresh value suitably. * * The refresh time is set either around half of the @a delta interval or, * if @a delta is less than 5 minutes but longer than 90 seconds, 30..60 * seconds before end of interval. * * If @a delta is 0, the dialog usage is never refreshed. */ void nua_dialog_usage_set_refresh(nua_dialog_usage_t *du, unsigned delta) { if (delta == 0) nua_dialog_usage_reset_refresh(du); else if (delta > 90 && delta < 5 * 60) /* refresh 30..60 seconds before deadline */ nua_dialog_usage_set_refresh_range(du, delta - 60, delta - 30); else { /* By default, refresh around half time before deadline */ unsigned min = (delta + 2) / 4; unsigned max = (delta + 2) / 4 + (delta + 1) / 2; if (min == 0) min = 1; nua_dialog_usage_set_refresh_range(du, min, max); } } /**@internal Set refresh in range min..max seconds in the future. */ void nua_dialog_usage_set_refresh_range(nua_dialog_usage_t *du, unsigned min, unsigned max) { sip_time_t now = sip_now(), target; unsigned delta; if (max < min) max = min; if (min != max) delta = su_randint(min, max); else delta = min; if (now + delta >= now) target = now + delta; else target = SIP_TIME_MAX; SU_DEBUG_7(("nua(): refresh %s after %lu seconds (in [%u..%u])\n", nua_dialog_usage_name(du), target - now, min, max)); du->du_refquested = now; du->du_refresh = target; } /** Set absolute refresh time */ void nua_dialog_usage_set_refresh_at(nua_dialog_usage_t *du, sip_time_t target) { SU_DEBUG_7(("nua(): refresh %s after %lu seconds\n", nua_dialog_usage_name(du), target - sip_now())); du->du_refresh = target; } /**@internal Do not refresh. */ void nua_dialog_usage_reset_refresh(nua_dialog_usage_t *du) { if (du) { du->du_refquested = sip_now(); du->du_refresh = 0; } } /** @internal Refresh usage. */ void nua_dialog_usage_refresh(nua_owner_t *owner, nua_dialog_state_t *ds, nua_dialog_usage_t *du, sip_time_t now) { assert(du && du->du_class->usage_refresh); du->du_class->usage_refresh(owner, ds, du, now); } /** Terminate all dialog usages gracefully. */ int nua_dialog_shutdown(nua_owner_t *owner, nua_dialog_state_t *ds) { nua_dialog_usage_t *du; ds->ds_terminating = 1; do { for (du = ds->ds_usage; du; du = du->du_next) { if (!du->du_shutdown) { nua_dialog_usage_shutdown(owner, ds, du); break; } } } while (du); return 1; } /** Shutdown (gracefully terminate) usage. * * @retval >0 shutdown done * @retval 0 shutdown in progress * @retval <0 try again later */ int nua_dialog_usage_shutdown(nua_owner_t *owner, nua_dialog_state_t *ds, nua_dialog_usage_t *du) { if (du) { nua_dialog_usage_reset_refresh(du); du->du_shutdown = 1; assert(du->du_class->usage_shutdown); return du->du_class->usage_shutdown(owner, ds, du); } else return 200; } /** Repeat shutdown of all usages. * * @note Caller must have a reference to nh */ int nua_dialog_repeat_shutdown(nua_owner_t *owner, nua_dialog_state_t *ds) { nua_dialog_usage_t *du; nua_server_request_t *sr, *sr_next; for (sr = ds->ds_sr; sr; sr = sr_next) { sr_next = sr->sr_next; if (nua_server_request_is_pending(sr)) { SR_STATUS1(sr, SIP_410_GONE); /* 410 terminates dialog */ nua_server_respond(sr, NULL); nua_server_report(sr); } } for (du = ds->ds_usage; du ;) { nua_dialog_usage_t *du_next = du->du_next; nua_dialog_usage_shutdown(owner, ds, du); if (du_next == NULL) break; for (du = ds->ds_usage; du; du = du->du_next) { if (du == du_next) break; else if (!du->du_shutdown) break; } } return ds->ds_usage != NULL; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/nua_dialog.h000066400000000000000000000166001223300710500226130ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2006 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef NUA_DIALOG_H /** Defined when has been included. */ #define NUA_DIALOG_H /**@IFILE nua_dialog.h * @brief Dialog and dialog usage handling * * @author Pekka Pessi * @author Kai Vehmanen * * @date Created: Wed Mar 8 11:38:18 EET 2006 ppessi */ #include #ifndef NTA_H #include #endif struct nua_dialog_state { /** Dialog owner */ nua_owner_t *ds_owner; /** Dialog usages. */ nua_dialog_usage_t *ds_usage; /** Client requests */ nua_client_request_t *ds_cr; /** Server requests */ nua_server_request_t *ds_sr; /* Dialog and subscription state */ unsigned ds_reporting:1; /**< We are reporting */ unsigned ds_route:1; /**< We have route */ unsigned ds_terminating:1; /**< Being terminated */ unsigned ds_has_session:1; /**< We have session */ unsigned ds_has_register:1; /**< We have registration */ unsigned ds_has_publish:1; /**< We have publish */ unsigned ds_got_session:1; /**< We have (or have had) session */ unsigned ds_got_referrals:1; /**< We have (or have had) referrals */ unsigned :0; unsigned ds_has_events; /**< We have events */ unsigned ds_has_subscribes; /**< We have subscriptions */ unsigned ds_has_notifys; /**< We have notifiers */ sip_from_t const *ds_local; /**< Local address */ sip_to_t const *ds_remote; /**< Remote address */ nta_leg_t *ds_leg; sip_contact_t *ds_ltarget; /**< Local target */ char const *ds_remote_tag; /**< Remote tag (if any). * Should be non-NULL * if dialog is established. */ struct nua_dialog_peer_info { sip_allow_t *nr_allow; sip_accept_t *nr_accept; sip_require_t *nr_require; sip_supported_t *nr_supported; sip_user_agent_t *nr_user_agent; } ds_remote_ua[1]; }; /* Virtual function pointer table for dialog usage. */ typedef struct { unsigned usage_size, usage_class_size; int (*usage_add)(nua_owner_t *, nua_dialog_state_t *ds, nua_dialog_usage_t *du); void (*usage_remove)(nua_owner_t *, nua_dialog_state_t *ds, nua_dialog_usage_t *du, nua_client_request_t *cr, nua_server_request_t *sr); char const *(*usage_name)(nua_dialog_usage_t const *du); void (*usage_update_params)(nua_dialog_usage_t const *du, nua_handle_preferences_t const *changed, nua_handle_preferences_t const *params, nua_handle_preferences_t const *defaults); void (*usage_peer_info)(nua_dialog_usage_t *du, nua_dialog_state_t const *ds, sip_t const *sip); void (*usage_refresh)(nua_owner_t *, nua_dialog_state_t *ds, nua_dialog_usage_t *, sip_time_t now); int (*usage_shutdown)(nua_owner_t *, nua_dialog_state_t *ds, nua_dialog_usage_t *); } nua_usage_class; /* Base structure for dialog usage. */ struct nua_dialog_usage { nua_dialog_usage_t *du_next; nua_usage_class const *du_class; nua_dialog_state_t *du_dialog; nua_client_request_t *du_cr; /**< Client request bound with usage */ sip_time_t du_refquested; /**< When refreshed was requested */ sip_time_t du_refresh; /**< When to refresh */ unsigned du_ready:1; /**< Established usage */ unsigned du_shutdown:1; /**< Shutdown in progress */ unsigned:0; /** When usage expires. * Non-zero if the usage is established, SIP_TIME_MAX if there no * expiration time. */ sip_event_t const *du_event; /**< Event of usage */ }; void nua_dialog_uac_route(nua_owner_t *, nua_dialog_state_t *ds, sip_t const *sip, int rtag, int initial); void nua_dialog_uas_route(nua_owner_t *, nua_dialog_state_t *ds, sip_t const *sip, int rtag); void nua_dialog_store_peer_info(nua_owner_t *, nua_dialog_state_t *ds, sip_t const *sip); int nua_dialog_zap(nua_owner_t *own, nua_dialog_state_t *ds); int nua_dialog_remove(nua_owner_t *own, nua_dialog_state_t *ds, nua_dialog_usage_t *usage); su_inline int nua_dialog_is_reporting(nua_dialog_state_t const *ds) { return ds && ds->ds_reporting; } char const *nua_dialog_usage_name(nua_dialog_usage_t const *du); nua_dialog_usage_t *nua_dialog_usage_add(nua_owner_t *, struct nua_dialog_state *ds, nua_usage_class const *uclass, sip_event_t const *event); nua_dialog_usage_t *nua_dialog_usage_get(nua_dialog_state_t const *ds, nua_usage_class const *uclass, sip_event_t const *event); void nua_dialog_usage_remove(nua_owner_t *, nua_dialog_state_t *ds, nua_dialog_usage_t *du, nua_client_request_t *cr, nua_server_request_t *sr); void nua_dialog_update_params(nua_dialog_state_t *ds, nua_handle_preferences_t const *changed, nua_handle_preferences_t const *params, nua_handle_preferences_t const *defaults); void nua_base_usage_update_params(nua_dialog_usage_t const *du, nua_handle_preferences_t const *changed, nua_handle_preferences_t const *params, nua_handle_preferences_t const *defaults); void nua_dialog_deinit(nua_owner_t *own, nua_dialog_state_t *ds); int nua_dialog_shutdown(nua_owner_t *owner, nua_dialog_state_t *ds); int nua_dialog_repeat_shutdown(nua_owner_t *owner, nua_dialog_state_t *ds); void nua_dialog_usage_set_refresh(nua_dialog_usage_t *du, unsigned delta); void nua_dialog_usage_set_refresh_range(nua_dialog_usage_t *du, unsigned min, unsigned max); void nua_dialog_usage_set_refresh_at(nua_dialog_usage_t *du, sip_time_t target); void nua_dialog_usage_reset_refresh(nua_dialog_usage_t *du); void nua_dialog_usage_refresh(nua_owner_t *owner, nua_dialog_state_t *ds, nua_dialog_usage_t *du, sip_time_t now); int nua_dialog_usage_shutdown(nua_owner_t *owner, nua_dialog_state_t *ds, nua_dialog_usage_t *du); su_inline int nua_dialog_is_established(nua_dialog_state_t const *ds) { return ds->ds_remote_tag != NULL; } #if 0 su_inline void *nua_dialog_usage_private(nua_dialog_usage_t const *du) { return du ? (void *)(du + 1) : NULL; } su_inline nua_dialog_usage_t *nua_dialog_usage_public(void const *p) { return p ? (nua_dialog_usage_t *)p - 1 : NULL; } #else #define nua_dialog_usage_private(du) ((du) ? (void*)((du) + 1) : NULL) #define nua_dialog_usage_public(p) ((p) ? (nua_dialog_usage_t*)(p) - 1 : NULL) #endif #define NUA_DIALOG_USAGE_PRIVATE(du) ((void *)((du) + 1)) #define NUA_DIALOG_USAGE_PUBLIC(pu) ((void *)((nua_dialog_usage_t *)(pu) - 1)) #include "nua_client.h" #include "nua_server.h" #endif /* NUA_DIALOG_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/nua_event_server.c000066400000000000000000000220111223300710500240470ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2006 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE nua_event_server.c * @brief Easy event server * * @author Pekka Pessi * * @date Created: Wed Mar 8 11:48:49 EET 2006 ppessi */ #include "config.h" #include #include #include #include #include #include #include #include #include #define NEA_SMAGIC_T struct nua_handle_s #define NEA_EMAGIC_T struct nua_handle_s #include "nua_stack.h" /* ======================================================================== */ /* Event server */ static nea_event_t *nh_notifier_event(nua_handle_t *nh, su_home_t *home, sip_event_t const *event, tagi_t const *tags); static void authorize_watcher(nea_server_t *nes, nua_handle_t *nh, nea_event_t *ev, nea_subnode_t *sn, sip_t const *sip); void nua_stack_notifier(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { su_home_t home[1] = { SU_HOME_INIT(home) }; sip_event_t const *event = NULL; sip_content_type_t const *ct = NULL; sip_payload_t const *pl = NULL; url_string_t const *url = NULL; char const *event_s = NULL, *ct_s = NULL, *pl_s = NULL; nea_event_t *ev; int status = 900; char const *phrase = nua_internal_error; nua_stack_init_handle(nua, nh, tags); tl_gets(tags, NUTAG_URL_REF(url), SIPTAG_EVENT_REF(event), SIPTAG_EVENT_STR_REF(event_s), SIPTAG_CONTENT_TYPE_STR_REF(ct_s), SIPTAG_PAYLOAD_REF(pl), SIPTAG_PAYLOAD_STR_REF(pl_s), TAG_END()); if (!event && !event_s) status = 400, phrase = "Missing Event"; else if (!ct && !ct_s) status = 400, phrase = "Missing Content-Type"; else if (!nh->nh_notifier && !(nh->nh_notifier = nea_server_create(nua->nua_nta, nua->nua_root, url->us_url, NH_PGET(nh, max_subscriptions), NULL, nh, TAG_NEXT(tags)))) status = 900, phrase = nua_internal_error; else if (!event && !(event = sip_event_make(home, event_s))) status = 900, phrase = "Could not create an event header"; else if (!(ev = nh_notifier_event(nh, home, event, tags))) status = 900, phrase = "Could not create an event view"; else if (nea_server_update(nh->nh_notifier, ev, TAG_NEXT(tags)) < 0) status = 900, phrase = "No content for event"; else if (nea_server_notify(nh->nh_notifier, ev) < 0) status = 900, phrase = "Error when notifying watchers"; else nua_stack_tevent(nua, nh, NULL, e, status = SIP_200_OK, SIPTAG_EVENT(event), SIPTAG_CONTENT_TYPE(ct), TAG_END()); if (status != 200) nua_stack_event(nua, nh, NULL, e, status, phrase, NULL); su_home_deinit(home); } /* Create a event view for notifier */ static nea_event_t *nh_notifier_event(nua_handle_t *nh, su_home_t *home, sip_event_t const *event, tagi_t const *tags) { nea_event_t *ev = nea_event_get(nh->nh_notifier, event->o_type); sip_accept_t const *accept = NULL; char const *accept_s = NULL; sip_content_type_t const *ct = NULL; char const *ct_s = NULL; if (ev == NULL) { char *o_type, *o_subtype; char *temp = NULL; o_type = su_strdup(home, event->o_type); if (o_type == NULL) return NULL; o_subtype = strchr(o_type, '.'); if (o_subtype) *o_subtype++ = '\0'; tl_gets(tags, SIPTAG_ACCEPT_REF(accept), SIPTAG_ACCEPT_STR_REF(accept_s), SIPTAG_CONTENT_TYPE_REF(ct), SIPTAG_CONTENT_TYPE_STR_REF(ct_s), TAG_END()); /* * XXX - We really should build accept header when we add new content * types */ if (accept_s == NULL && accept) accept_s = temp = sip_header_as_string(home, (sip_header_t *)accept); if (accept_s == NULL && ct) accept_s = ct->c_type; if (accept_s == NULL && ct_s) accept_s = ct_s; ev = nea_event_create(nh->nh_notifier, authorize_watcher, nh, o_type, o_subtype, ct ? ct->c_type : ct_s, accept_s); su_free(home, temp); su_free(home, o_type); } return ev; } /* Callback from nea_server asking nua to authorize subscription */ static void authorize_watcher(nea_server_t *nes, nua_handle_t *nh, nea_event_t *ev, nea_subnode_t *sn, sip_t const *sip) { nua_t *nua = nh->nh_nua; msg_t *msg = NULL; nta_incoming_t *irq = NULL; int substate = sn->sn_state; int status; char const *phrase; SET_STATUS1(SIP_200_OK); /* OK. In nhp (nua_handle_preferences_t) structure we have the current default action (or state) for incoming subscriptions. Action can now be modified by the application with NUTAG_SUBSTATE(). */ irq = nea_sub_get_request(sn->sn_subscriber); msg = nta_incoming_getrequest(irq); if (sn->sn_state == nea_embryonic) { char const *what; substate = NH_PGET(nh, substate); if (substate == nua_substate_embryonic) substate = nua_substate_pending; if (substate == nua_substate_terminated) { what = "rejected"; SET_STATUS1(SIP_403_FORBIDDEN); } else if (substate == nua_substate_pending) { what = "pending"; SET_STATUS1(SIP_202_ACCEPTED); } else { what = "active"; } SU_DEBUG_7(("nua(%p): authorize_watcher: %s\n", (void *)nh, what)); nea_sub_auth(sn->sn_subscriber, (nea_state_t)substate, TAG_IF(substate == nua_substate_pending, NEATAG_FAKE(1)), TAG_IF(substate == nua_substate_terminated, NEATAG_REASON("rejected")), TAG_END()); } else if (sn->sn_state == nea_terminated || sn->sn_expires == 0) { substate = nua_substate_terminated; nea_server_flush(nes, NULL); SU_DEBUG_7(("nua(%p): authorize_watcher: %s\n", (void *)nh, "watcher is removed")); } nua_stack_tevent(nua, nh, msg, nua_i_subscription, status, phrase, NUTAG_SUBSTATE(substate), NEATAG_SUB(sn->sn_subscriber), TAG_END()); } /* ---------------------------------------------------------------------- */ /* Authorization of watchers by application */ void nua_stack_authorize(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { nea_sub_t *sub = NULL; int state = nea_extended; tl_gets(tags, NEATAG_SUB_REF(sub), NUTAG_SUBSTATE_REF(state), TAG_END()); if (sub && state > 0) { nea_sub_auth(sub, (nea_state_t)state, TAG_NEXT(tags)); nua_stack_event(nua, nh, NULL, e, SIP_200_OK, NULL); } else { nua_stack_event(nua, nh, NULL, e, NUA_ERROR_AT(__FILE__, __LINE__), NULL); } } /** @internal Shutdown notifier object */ int nh_notifier_shutdown(nua_handle_t *nh, nea_event_t *ev, tag_type_t t, tag_value_t v, ...) { nea_server_t *nes = nh->nh_notifier; nea_subnode_t const **subs; int busy = 0; if (nes == NULL) return 0; subs = nea_server_get_subscribers(nes, ev); if (subs) { int i; ta_list ta; ta_start(ta, t, v); for (i = 0; subs[i]; i++) nea_sub_auth(subs[i]->sn_subscriber, nea_terminated, ta_tags(ta)); ta_end(ta); busy++; } nea_server_free_subscribers(nes, subs); nea_server_flush(nh->nh_notifier, NULL); if (ev == NULL) nea_server_destroy(nh->nh_notifier), nh->nh_notifier = NULL; return busy; } /** @internal Terminate notifier. */ void nua_stack_terminate(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { sip_event_t const *event = NULL; sip_content_type_t const *ct = NULL; sip_payload_t const *pl = NULL; char const *event_s = NULL, *ct_s = NULL, *pl_s = NULL; nea_event_t *nev = NULL; if (nh->nh_notifier == NULL) { UA_EVENT2(e, 900, "No event server to terminate"); return; } tl_gets(tags, SIPTAG_EVENT_REF(event), SIPTAG_EVENT_STR_REF(event_s), SIPTAG_CONTENT_TYPE_REF(ct), SIPTAG_CONTENT_TYPE_STR_REF(ct_s), SIPTAG_PAYLOAD_REF(pl), SIPTAG_PAYLOAD_STR_REF(pl_s), TAG_END()); nev = nea_event_get(nh->nh_notifier, event ? event->o_type : event_s); if (nev && (pl || pl_s) && (ct || ct_s)) { nea_server_update(nh->nh_notifier, nev, TAG_NEXT(tags)); } nh_notifier_shutdown(nh, NULL, NEATAG_REASON("noresource"), TAG_NEXT(tags)); nua_stack_event(nua, nh, NULL, e, SIP_200_OK, NULL); } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/nua_extension.c000066400000000000000000000120021223300710500233530ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2006 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE nua_extension.c * @brief Extension method * * @author Pekka Pessi * * @date Created: Mon Nov 13 15:18:54 EET 2006 */ #include "config.h" #include #include #include #include #include #include #include #include #include "nua_stack.h" /**Send a request message with an extension method. * * Send a request message with the request method specified with * NUTAG_METHOD(). * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return * nothing * * Note that it is possible to send a request with any method (except * perhaps @b INVITE, @b ACK or @b CANCEL) using this function. * * @par Related Tags: * NUTAG_METHOD() \n * NUTAG_URL() \n * Tags of nua_set_hparams() \n * Header tags defined in * * @par Events: * #nua_r_method * * @sa SIP_METHOD_UNKNOWN(), #nua_r_method, #nua_i_method * * @since New in @VERSION_1_12_4. */ static nua_client_methods_t const nua_method_client_methods = { SIP_METHOD_UNKNOWN, /* crm_method, crm_method_name */ 0, /* crm_extra */ { /* crm_flags */ /* create_dialog */ 0, /* in_dialog */ 0, /* target_refresh */ 1, }, NULL, /* crm_template */ NULL, /* crm_init */ NULL, /* crm_send */ NULL, /* crm_check_restart */ NULL, /* crm_recv */ NULL, /* crm_preliminary */ NULL, /* crm_report */ NULL, /* crm_complete */ }; int nua_stack_method(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { return nua_client_create(nh, e, &nua_method_client_methods, tags); } /** @NUA_EVENT nua_r_method * * Response to an outgoing extension request. * * @param status response status code * (if the request is retried, @a status is 100, the @a * sip->sip_status->st_status contain the real status code * from the response method, e.g., 302, 401, or 407) * @param phrase a short textual description of @a status code * @param nh operation handle associated with the method * @param hmagic application context associated with the handle * @param sip response to the extension request or NULL upon an error * (status code is in @a status and * descriptive method in @a phrase parameters) * @param tags empty * * @sa nua_method(), #nua_i_method, @RFC3428 * * @END_NUA_EVENT */ /** @NUA_EVENT nua_i_method * * @brief Incoming extension request. * * The extension request does not create a dialog. If the incoming request * was not assiciated with an existing dialog the stack creates a new handle * for it. If the handle @a nh is not bound, you should probably destroy it * after responding to the request. * * @param status status code of response sent automatically by stack * @param phrase a short textual description of @a status code * @param nh operation handle associated with the method * @param hmagic application context associated with the handle * (maybe NULL if outside session) * @param sip headers in incoming request (see also nua_current_request()) * @param tags NUTAG_METHOD() * * The extension method name is in sip->sip_request->rq_method_name, too. * * @note If the @a status is < 200, it is up to application to respond to * the request with nua_respond(). If the handle is destroyed, the stack * returns a 500 Internal Server Error response to any unresponded * request. * * @sa nua_method(), #nua_r_method, NUTAG_ALLOW(), NUTAG_APPL_METHOD(), * nua_respond(), NUTAG_WITH(), NUTAG_WITH_THIS(), NUTAG_ * * @END_NUA_EVENT */ nua_server_methods_t const nua_extension_server_methods = { SIP_METHOD_UNKNOWN, nua_i_method, /* Event */ { 1, /* Do create dialog */ 0, /* Can be an initial request */ 1, /* Perhaps a target refresh request? */ 1, /* Add a contact? */ }, nua_base_server_init, nua_base_server_preprocess, nua_base_server_params, nua_base_server_respond, nua_base_server_report, }; sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/nua_message.c000066400000000000000000000125551223300710500230000ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2006 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE nua_message.c * @brief MESSAGE method * * @author Pekka Pessi * * @date Created: Wed Mar 8 17:01:22 EET 2006 ppessi */ #include "config.h" #include #include #include #include #include #include #include #include #include "nua_stack.h" /* ======================================================================== */ /* MESSAGE */ /**@fn void nua_message( \ * nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * * Send an instant message. * * Send an instant message using SIP MESSAGE method. * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Related Tags: * NUTAG_URL() \n * Tags of nua_set_hparams() \n * Header tags defined in * * @par Events: * #nua_r_message * * @sa #nua_i_message, @RFC3428 */ static int nua_message_client_init(nua_client_request_t *cr, msg_t *, sip_t *, tagi_t const *tags); static nua_client_methods_t const nua_message_client_methods = { SIP_METHOD_MESSAGE, /* crm_method, crm_method_name */ 0, /* crm_extra */ { /* crm_flags */ /* create_dialog */ 0, /* in_dialog */ 0, /* target refresh */ 0 }, NULL, /* crm_template */ nua_message_client_init, /* crm_init */ NULL, /* crm_send */ NULL, /* crm_check_restart */ NULL, /* crm_recv */ NULL, /* crm_preliminary */ NULL, /* crm_report */ NULL, /* crm_complete */ }; int nua_stack_message(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { return nua_client_create(nh, e, &nua_message_client_methods, tags); } static int nua_message_client_init(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags) { if (NH_PGET(cr->cr_owner, win_messenger_enable)) cr->cr_contactize = 1; return 0; } /** @NUA_EVENT nua_r_message * * Response to an outgoing @b MESSAGE request. * * @param status response status code * (if the request is retried, @a status is 100, the @a * sip->sip_status->st_status contain the real status code * from the response message, e.g., 302, 401, or 407) * @param phrase a short textual description of @a status code * @param nh operation handle associated with the message * @param hmagic application context associated with the handle * @param sip response to MESSAGE request or NULL upon an error * (status code is in @a status and * descriptive message in @a phrase parameters) * @param tags empty * * @sa nua_message(), #nua_i_message, @RFC3428 * * @END_NUA_EVENT */ /** @NUA_EVENT nua_i_message * * @brief Incoming @b MESSAGE request. * * The @b MESSAGE request does not create a dialog. If the incoming @b * MESSAGE request is not assiciated with an existing dialog the stack * creates a new handle for it. If the handle @a nh is not bound, you should * probably destroy it after responding to the MESSAGE request. * * @param status status code of response sent automatically by stack * @param phrase a short textual description of @a status code * @param nh operation handle associated with the message * @param hmagic application context associated with the handle * (maybe NULL if outside session) * @param sip incoming MESSAGE request * @param tags empty * * @sa nua_message(), #nua_r_message, @RFC3428, @RFC3862 * * @END_NUA_EVENT */ int nua_message_server_init(nua_server_request_t *sr); int nua_message_server_params(nua_server_request_t *, tagi_t const *); nua_server_methods_t const nua_message_server_methods = { SIP_METHOD_MESSAGE, nua_i_message, /* Event */ { 0, /* Do not create dialog */ 0, /* Can be initial request */ 0, /* Perhaps a target refresh request? */ 0, /* Do not add contact by default */ }, nua_message_server_init, nua_base_server_preprocess, nua_message_server_params, nua_base_server_respond, nua_base_server_report, }; int nua_message_server_init(nua_server_request_t *sr) { if (!NH_PGET(sr->sr_owner, message_enable)) return SR_STATUS1(sr, SIP_403_FORBIDDEN); return 0; } int nua_message_server_params(nua_server_request_t *sr, tagi_t const *tags) { if (NH_PGET(sr->sr_owner, win_messenger_enable)) sr->sr_add_contact = 1; return 0; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/nua_notifier.c000066400000000000000000000763351223300710500232010ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2006 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE nua_notifier.c * @brief SUBSCRIBE server, NOTIFY client and REFER server * * Simpler event server. See nua_event_server.c for more complex event * server. * * @author Pekka Pessi * * @date Created: Wed Mar 8 15:10:08 EET 2006 ppessi */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "nua_stack.h" /* ---------------------------------------------------------------------- */ /* Notifier event usage */ struct notifier_usage { enum nua_substate nu_substate; /**< Subscription state */ sip_time_t nu_expires; /**< Expiration time */ sip_time_t nu_requested; /**< Requested expiration time */ #if SU_HAVE_EXPERIMENTAL char *nu_tag; /**< @ETag in last NOTIFY */ unsigned nu_etags:1; /**< Subscriber supports etags */ unsigned nu_appl_etags:1; /**< Application generates etags */ unsigned nu_no_body:1; /**< Suppress body */ #endif }; static char const *nua_notify_usage_name(nua_dialog_usage_t const *du); static int nua_notify_usage_add(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du); static void nua_notify_usage_remove(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du, nua_client_request_t *cr, nua_server_request_t *sr); static void nua_notify_usage_refresh(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du, sip_time_t now); static int nua_notify_usage_shutdown(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du); static nua_usage_class const nua_notify_usage[1] = { { sizeof (struct notifier_usage), (sizeof nua_notify_usage), nua_notify_usage_add, nua_notify_usage_remove, nua_notify_usage_name, nua_base_usage_update_params, NULL, nua_notify_usage_refresh, nua_notify_usage_shutdown, }}; static char const *nua_notify_usage_name(nua_dialog_usage_t const *du) { return "notify"; } static int nua_notify_usage_add(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du) { ds->ds_has_events++; ds->ds_has_notifys++; return 0; } static void nua_notify_usage_remove(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du, nua_client_request_t *cr, nua_server_request_t *sr) { ds->ds_has_events--; ds->ds_has_notifys--; } /* ====================================================================== */ /* SUBSCRIBE server */ /** @NUA_EVENT nua_i_subscribe * * Incoming @b SUBSCRIBE request. * * @b SUBSCRIBE request is used to query SIP event state or establish a SIP * event subscription. * * @param status status code of response sent automatically by stack * @param phrase response phrase sent automatically by stack * @param nh operation handle associated with the incoming request * @param hmagic application context associated with the handle * (NULL when handle is created by the stack) * @param sip SUBSCRIBE request headers * @param tags NUTAG_SUBSTATE() * * Initial SUBSCRIBE requests are dropped with 489 Bad Event * response, unless the application has explicitly included the @Event in * the list of allowed events with nua_set_params() tag NUTAG_ALLOW_EVENTS() * (or SIPTAG_ALLOW_EVENTS() or SIPTAG_ALLOW_EVENTS_STR()). * * If the event has been allowed the application * can decide whether to accept the SUBSCRIBE request or reject it. The * nua_response() call responding to a SUBSCRIBE request must have * NUTAG_WITH() (or NUTAG_WITH_THIS()/NUTAG_WITH_SAVED()) tag. * * If the application accepts the SUBSCRIBE request, it must immediately * send an initial NOTIFY establishing the dialog. This is because the * response to the SUBSCRIBE request may be lost by an intermediate proxy * because it had forked the SUBSCRIBE request. * * SUBSCRIBE requests modifying (usually refreshing or terminating) an * existing event subscription are accepted by default and a 200 OK * response along with a copy of previously sent NOTIFY is sent * automatically to the subscriber. * * By default, only event subscriptions accepted are those created * implicitly by REFER request. See #nua_i_refer how the application must * handle the REFER requests. * * @par Subscription Lifetime and Terminating Subscriptions * * Accepting the SUBSCRIBE request creates a dialog with a notifier * dialog usage on the handle. The dialog usage is active, until the * subscriber terminates the subscription, it times out or the application * terminates the usage with nua_notify() call containing the tag * NUTAG_SUBSTATE(nua_substate_terminated) or @SubscriptionState header with * state "terminated" and/or expiration time 0. * * When the subscriber terminates the subscription, the application is * notified of an termination by a #nua_i_subscribe event with * NUTAG_SUBSTATE(nua_substate_terminated) tag. When the subscription times * out, nua automatically initiates a NOTIFY transaction. When it is * terminated, the application is sent a #nua_r_notify event with * NUTAG_SUBSTATE(nua_substate_terminated) tag. * * @sa @RFC3265, nua_notify(), NUTAG_SUBSTATE(), @SubscriptionState, * @Event, nua_subscribe(), #nua_r_subscribe, #nua_i_refer, nua_refer() * * @END_NUA_EVENT */ static int nua_subscribe_server_init(nua_server_request_t *sr); static int nua_subscribe_server_preprocess(nua_server_request_t *sr); static int nua_subscribe_server_respond(nua_server_request_t*, tagi_t const *); static int nua_subscribe_server_report(nua_server_request_t*, tagi_t const *); nua_server_methods_t const nua_subscribe_server_methods = { SIP_METHOD_SUBSCRIBE, nua_i_subscribe, /* Event */ { 1, /* Create dialog */ 0, /* Initial request */ 1, /* Target refresh request */ 1, /* Add Contact */ }, nua_subscribe_server_init, nua_subscribe_server_preprocess, nua_base_server_params, nua_subscribe_server_respond, nua_subscribe_server_report, }; int nua_subscribe_server_init(nua_server_request_t *sr) { nua_handle_t *nh = sr->sr_owner; nua_dialog_state_t *ds = nh->nh_ds; sip_allow_events_t const *allow_events = NH_PGET(nh, allow_events); sip_t const *sip = sr->sr_request.sip; sip_event_t *o = sip->sip_event; char const *event = o ? o->o_type : NULL; if (sr->sr_initial || !nua_dialog_usage_get(ds, nua_notify_usage, o)) { if (su_strmatch(event, "refer")) /* refer event subscription should be initiated with REFER */ return SR_STATUS1(sr, SIP_403_FORBIDDEN); /* XXX - event is case-sensitive, should use msg_header_find_item() */ if (!event || !msg_header_find_param(allow_events->k_common, event)) return SR_STATUS1(sr, SIP_489_BAD_EVENT); } return 0; } int nua_subscribe_server_preprocess(nua_server_request_t *sr) { nua_handle_t *nh = sr->sr_owner; nua_dialog_state_t *ds = nh->nh_ds; nua_dialog_usage_t *du; struct notifier_usage *nu; sip_t const *sip = sr->sr_request.sip; sip_event_t *o = sip->sip_event; char const *event = o ? o->o_type : NULL; /* Maximum expiration time */ unsigned long expires = sip->sip_expires ? sip->sip_expires->ex_delta : 3600; sip_time_t now = sip_now(); sip_allow_events_t *appl_event = NH_PGET(nh, appl_event); assert(nh && nh->nh_nua->nua_dhandle != nh); du = nua_dialog_usage_get(ds, nua_notify_usage, o); if (du == NULL) { /* Create a new subscription */ du = nua_dialog_usage_add(nh, ds, nua_notify_usage, o); if (du == NULL) return SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); } else if (!msg_header_find_param((void *)appl_event, event)) { unsigned max_expires; /* Refresh existing subscription */ if (su_strmatch(event, "refer")) max_expires = NH_PGET(nh, refer_expires); else max_expires = NH_PGET(nh, sub_expires); if (expires >= max_expires) expires = max_expires; SR_STATUS1(sr, SIP_200_OK); } nu = nua_dialog_usage_private(du); if (now + expires >= now) nu->nu_requested = now + expires; else nu->nu_requested = SIP_TIME_MAX - 1; #if SU_HAVE_EXPERIMENTAL nu->nu_etags = sip_suppress_body_if_match(sip) || sip_suppress_notify_if_match(sip) || sip_has_feature(sr->sr_request.sip->sip_supported, "etags"); #endif sr->sr_usage = du; return sr->sr_status <= 100 ? 0 : sr->sr_status; } /** @internal Respond to a SUBSCRIBE request. * */ static int nua_subscribe_server_respond(nua_server_request_t *sr, tagi_t const *tags) { struct notifier_usage *nu = nua_dialog_usage_private(sr->sr_usage); msg_t *msg = sr->sr_response.msg; sip_t *sip = sr->sr_response.sip; if (200 <= sr->sr_status && sr->sr_status < 300) { sip_expires_t ex[1]; sip_expires_init(ex); if (nu) { sip_time_t now = sip_now(); if (nu->nu_requested) { if (sip->sip_expires) { /* Expires in response can only shorten the expiration time */ if (nu->nu_requested > now + sip->sip_expires->ex_delta) nu->nu_requested = now + sip->sip_expires->ex_delta; } else { unsigned sub_expires = NH_PGET(sr->sr_owner, sub_expires); if (nu->nu_requested > now + sub_expires) nu->nu_requested = now + sub_expires; } if (nu->nu_requested >= now) nu->nu_expires = nu->nu_requested; else nu->nu_expires = now; if (nu->nu_expires <= now) nu->nu_substate = nua_substate_terminated; } if (nu->nu_expires > now) ex->ex_delta = nu->nu_expires - now; } else { /* Always add header Expires: 0 */ } if (!sip->sip_expires || sip->sip_expires->ex_delta > ex->ex_delta) sip_add_dup(msg, sip, (sip_header_t *)ex); } return nua_base_server_respond(sr, tags); } static int nua_subscribe_server_report(nua_server_request_t *sr, tagi_t const *tags) { nua_handle_t *nh = sr->sr_owner; nua_dialog_state_t *ds = nh->nh_ds; nua_dialog_usage_t *du = sr->sr_usage; struct notifier_usage *nu = nua_dialog_usage_private(du); enum nua_substate substate = nua_substate_terminated; int notify = 0; int retval; if (nu && !sr->sr_terminating) { substate = nu->nu_substate; } /* nu_requested is set by SUBSCRIBE and cleared when NOTIFY is sent */ if (nu && nu->nu_requested && substate != nua_substate_embryonic) { #if SU_HAVE_EXPERIMENTAL sip_t const *sip = sr->sr_request.sip; sip_suppress_notify_if_match_t *snim = sip_suppress_notify_if_match(sip); sip_suppress_body_if_match_t *sbim = sip_suppress_body_if_match(sip); if (!nu->nu_tag) notify = 1; else if (snim && su_casematch(snim->snim_tag, nu->nu_tag)) notify = 0; else if (sbim && su_casematch(snim->snim_tag, nu->nu_tag)) notify = 1, nu->nu_no_body = 1; else #endif notify = 1; notify = notify && du->du_cr != NULL; } retval = nua_base_server_treport(sr, NUTAG_SUBSTATE(substate), TAG_END()); if (retval >= 2 || du == NULL) return retval; if (notify) { /* Send NOTIFY (and terminate subscription, when needed) */ nua_dialog_usage_refresh(nh, ds, du, sip_now()); } return retval; } /* ======================================================================== */ /* NOTIFY client */ /**@fn void nua_notify(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * * Send a SIP NOTIFY request message. * * This function is used when the application implements itself the * notifier. The application must provide valid @SubscriptionState and * @Event headers using SIP tags. The subscription state can be modified * with NUTAG_SUBSTATE(), however, its effect is overriden by * @SubscriptionState header included in the nua_notify() tags. * * @bug If the @Event is not given by application, stack uses the @Event * header from the first subscription usage on handle. * * If there is no active notifier dialog usage or no notifier dialog * usage matches the @Event header given by the application the nua_notify() * request is rejected locally by the stack with status code 481. The local * rejection can be bypassed if NUTAG_NEWSUB(1) is included in tags. * * Please note that including NUTAG_NEWSUB(1) in nua_notify() tags if there * is a valid subscription may lead to an extra NOTIFY sent to subscriber if * the subscription had been terminated by the subscriber or by a timeout * before the nua_notify() is processed. * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Related Tags: * NUTAG_SUBSTATE() \n * NUTAG_NEWSUB() \n * Tags of nua_set_hparams() \n * Header tags defined in * * @par Events: * #nua_r_notify * * @sa @RFC3265, #nua_i_subscribe, #nua_i_refer, NUTAG_ALLOW_EVENTS() */ static int nua_notify_client_init(nua_client_request_t *cr, msg_t *, sip_t *, tagi_t const *tags); static int nua_notify_client_init_etag(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags); static int nua_notify_client_request(nua_client_request_t *cr, msg_t *, sip_t *, tagi_t const *tags); static int nua_notify_client_report(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip, nta_outgoing_t *orq, tagi_t const *tags); static nua_client_methods_t const nua_notify_client_methods = { SIP_METHOD_NOTIFY, /* crm_method, crm_method_name */ 0, /* crm_extra */ { /* crm_flags */ /* create_dialog */ 1, /* in_dialog */ 1, /* target refresh */ 1 }, NULL, /* crm_template */ nua_notify_client_init, /* crm_init */ nua_notify_client_request, /* crm_send */ NULL, /* crm_check_restart */ NULL, /* crm_recv */ NULL, /* crm_preliminary */ nua_notify_client_report, /* crm_report */ NULL, /* crm_complete */ }; /**@internal Send NOTIFY. */ int nua_stack_notify(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { return nua_client_create(nh, e, &nua_notify_client_methods, tags); } static int nua_notify_client_init(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du; struct notifier_usage *nu; sip_event_t const *o = sip->sip_event; sip_subscription_state_t *ss = sip->sip_subscription_state; sip_time_t now = sip_now(); if (o == NULL && nh->nh_ds->ds_has_notifys == 1) o = NONE; du = nua_dialog_usage_get(nh->nh_ds, nua_notify_usage, o); if (!du) { tagi_t const *newsub = tl_find_last(tags, nutag_newsub); if (!newsub || !newsub->t_value) return 0; /* Rejected eventually by nua_notify_client_request() */ /* Create new notifier */ du = nua_dialog_usage_add(nh, nh->nh_ds, nua_notify_usage, o); if (du == NULL) return -1; nu = nua_dialog_usage_private(du); nu->nu_expires = now; } else nu = nua_dialog_usage_private(du); if (nu->nu_substate == nua_substate_terminated) { /*Xyzzy*/; } else if (ss != NULL) { /* SIPTAG_SUBSCRIPTION_STATE() overrides NUTAG_SUBSTATE() */ nu->nu_substate = nua_substate_make(ss->ss_substate); if (ss->ss_expires) { unsigned long expires = strtoul(ss->ss_expires, NULL, 10); if (now + expires < now) expires = SIP_TIME_MAX - now - 1; /* We can change the lifetime of unsolicited subscription at will */ if (nu->nu_requested == 0) nu->nu_expires = nu->nu_requested = now + expires; /* Notifier can only shorten the subscribed time */ else if (nu->nu_requested >= now + expires) nu->nu_expires = nu->nu_requested = now + expires; } else { if (nu->nu_requested >= nu->nu_expires) nu->nu_expires = nu->nu_requested; } } else { enum nua_substate substate = nu->nu_substate; if (nu->nu_requested >= nu->nu_expires) nu->nu_expires = nu->nu_requested; if (nu->nu_expires > now) { tagi_t const *t = tl_find_last(tags, nutag_substate); if (t) substate = (enum nua_substate)t->t_value; } else substate = nua_substate_terminated; switch (substate) { case nua_substate_embryonic: /*FALLTHROUGH*/ case nua_substate_pending: nu->nu_substate = nua_substate_pending; break; case nua_substate_active: default: nu->nu_substate = nua_substate_active; break; case nua_substate_terminated: nu->nu_substate = nua_substate_terminated; break; } } cr->cr_usage = du; return nua_notify_client_init_etag(cr, msg, sip, tags); } static int nua_notify_client_init_etag(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags) { #if SU_HAVE_EXPERIMENTAL nua_handle_t *nh = cr->cr_owner; struct notifier_usage *nu = nua_dialog_usage_private(cr->cr_usage); nua_server_request_t *sr; if (nu->nu_tag) su_free(nh->nh_home, nu->nu_tag), nu->nu_tag = NULL; nu->nu_no_body = 0; if (sip->sip_etag) { nu->nu_appl_etags = 1; nu->nu_tag = su_strdup(nh->nh_home, sip->sip_etag->g_string); } else if (!nu->nu_appl_etags && nu->nu_etags) { su_md5_t md5[1]; unsigned char digest[SU_MD5_DIGEST_SIZE]; sip_payload_t pl[1] = { SIP_PAYLOAD_INIT() }; char token[2 * 16]; su_md5_init(md5); if (sip->sip_payload) *pl = *sip->sip_payload; if (pl->pl_len) su_md5_update(md5, pl->pl_data, pl->pl_len); su_md5_update(md5, &pl->pl_len, sizeof(pl->pl_len)); if (sip->sip_content_type) su_md5_striupdate(md5, sip->sip_content_type->c_type); su_md5_digest(md5, digest); token64_e(token, sizeof token, digest, sizeof digest); token[(sizeof token) - 1] = '\0'; nu->nu_tag = su_strdup(nh->nh_home, token); } if (!nu->nu_requested || !nu->nu_tag) return 0; /* Check if SUBSCRIBE had matching suppression */ for (sr = nh->nh_ds->ds_sr; sr; sr = sr->sr_next) if (sr->sr_usage == cr->cr_usage && sr->sr_method == sip_method_subscribe) break; if (sr) { sip_t const *sip = sr->sr_request.sip; sip_suppress_body_if_match_t *sbim; sip_suppress_notify_if_match_t *snim; if (cr->cr_usage->du_ready) { snim = sip_suppress_notify_if_match(sip); if (snim && su_casematch(snim->snim_tag, nu->nu_tag)) { if (nu->nu_requested > nu->nu_expires) nu->nu_expires = nu->nu_requested; nu->nu_requested = 0; return nua_client_return(cr, 202, "NOTIFY Suppressed", msg); } } sbim = sip_suppress_body_if_match(sip); if (sbim && su_casematch(sbim->sbim_tag, nu->nu_tag)) nu->nu_no_body = 1; } #endif return 0; } static int nua_notify_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags) { nua_dialog_usage_t *du = cr->cr_usage; struct notifier_usage *nu = nua_dialog_usage_private(du); su_home_t *home = msg_home(msg); sip_time_t now = sip_now(); sip_subscription_state_t *ss = sip->sip_subscription_state; char const *expires; if (du == NULL) /* Subscription has been terminated */ return nua_client_return(cr, SIP_481_NO_TRANSACTION, msg); assert(du && nu); if (du && nua_client_bind(cr, du) < 0) return -1; if (nu->nu_requested) nu->nu_expires = nu->nu_requested; nu->nu_requested = 0; if (nu->nu_expires <= now || du->du_shutdown) { nu->nu_substate = nua_substate_terminated; expires = "expires=0"; } else { expires = su_sprintf(home, "expires=%lu", nu->nu_expires - now); } if (ss == NULL || nua_substate_make(ss->ss_substate) != nu->nu_substate) { if (nu->nu_substate == nua_substate_terminated) expires = nu->nu_expires > now ? "reason=noresource" : "reason=timeout"; ss = sip_subscription_state_format(home, "%s;%s", nua_substate_name(nu->nu_substate), expires); msg_header_insert(msg, (void *)sip, (void *)ss); } else if (nu->nu_substate != nua_substate_terminated) { msg_header_replace_param(home, ss->ss_common, expires); } #if SU_HAVE_EXPERIMENTAL if (nu->nu_tag && !sip->sip_etag) msg_header_add_make(msg, (void *)sip, sip_etag_class, nu->nu_tag); if (nu->nu_no_body) { nu->nu_no_body = 0; msg_header_remove(msg, (void *)sip, (void *)sip->sip_payload); msg_header_remove(msg, (void *)sip, (void *)sip->sip_content_length); } #endif if (nu->nu_substate == nua_substate_terminated) nua_client_set_terminating(cr, 1); if (cr->cr_terminating) { nua_server_request_t *sr; for (sr = du->du_dialog->ds_sr; sr; sr = sr->sr_next) { if (sr->sr_usage == du) { /* If subscribe has not been responded, don't terminate usage by NOTIFY */ sr->sr_terminating = 1; nua_client_set_terminating(cr, 0); break; } } } if (du->du_event && !sip->sip_event) sip_add_dup(cr->cr_msg, sip, (sip_header_t *)du->du_event); return nua_base_client_request(cr, msg, sip, tags); } /** @NUA_EVENT nua_r_notify * * Response to an outgoing @b NOTIFY request. * * The @b NOTIFY may be sent explicitly by nua_notify() or implicitly by NUA * state machine. Implicit @b NOTIFY is sent when an established dialog is * refreshed by client or it is terminated (either by client or because of a * timeout). * * The current subscription state is included in NUTAG_SUBSTATE() tag. The * nua_substate_terminated indicates that the subscription is terminated, * the notifier usage has been removed and when there was no other usages of * the dialog the dialog state is also removed. * * @param status response status code * (if the request is retried, @a status is 100, the @a * sip->sip_status->st_status contain the real status code * from the response message, e.g., 302, 401, or 407) * @param phrase a short textual description of @a status code * @param nh operation handle associated with the subscription * @param hmagic application context associated with the handle * @param sip response to @b NOTIFY request or NULL upon an error * (status code is in @a status and * descriptive message in @a phrase parameters) * @param tags NUTAG_SUBSTATE() indicating subscription state * SIPTAG_EVENT() indicating subscription event * * @sa nua_notify(), @RFC3265, #nua_i_subscribe, #nua_i_refer, NUTAG_SUBSTATE() * * @END_NUA_EVENT */ static int nua_notify_client_report(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip, nta_outgoing_t *orq, tagi_t const *tags) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = cr->cr_usage; struct notifier_usage *nu = nua_dialog_usage_private(du); enum nua_substate substate = nua_substate_terminated; if (nu && !cr->cr_terminated) substate = nu->nu_substate; nua_stack_tevent(nh->nh_nua, nh, nta_outgoing_getresponse(orq), (enum nua_event_e)cr->cr_event, status, phrase, NUTAG_SUBSTATE(substate), SIPTAG_EVENT(du ? du->du_event : NULL), TAG_NEXT(tags)); if (du && du->du_cr == cr && !cr->cr_terminated) { if (nu->nu_requested) { /* Re-SUBSCRIBEd while NOTIFY was in progress, resend NOTIFY */ nua_client_resend_request(cr, 0); } else if (nu->nu_expires) { nua_dialog_usage_set_refresh_at(du, nu->nu_expires); } } return 0; } static void nua_notify_usage_refresh(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du, sip_time_t now) { struct notifier_usage *nu = nua_dialog_usage_private(du); nua_client_request_t *cr = du->du_cr; nua_event_t e = nua_r_notify; if (cr) { int terminating = 0; SU_DEBUG_7(("%s(%p, %p, %p): using existing cr=%p\n", "nua_notify_usage_refresh", (void *)nh, (void *)ds, (void *)du, (void *)cr)); if (nu->nu_expires && nu->nu_expires <= now) terminating = 1; else if (nu->nu_requested && nu->nu_requested <= now) terminating = 1; if (nua_client_resend_request(cr, terminating) >= 0) return; } else { SU_DEBUG_7(("%s(%p, %p, %p): new NOTIFY cr for %s\n", "nua_notify_usage_refresh", (void *)nh, (void *)ds, (void *)du, du->du_event ? du->du_event->o_type : "")); if (nua_client_create(nh, e, &nua_notify_client_methods, NULL) >= 0) return; } nua_stack_tevent(nh->nh_nua, nh, NULL, e, NUA_ERROR_AT(__FILE__, __LINE__), NUTAG_SUBSTATE(nua_substate_terminated), TAG_END()); nua_dialog_usage_remove(nh, ds, du, NULL, NULL); } /** @interal Shut down NOTIFY usage. * * @retval >0 shutdown done * @retval 0 shutdown in progress * @retval <0 try again later */ static int nua_notify_usage_shutdown(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du) { struct notifier_usage *nu = nua_dialog_usage_private(du); nua_client_request_t *cr = du->du_cr; nu->nu_substate = nua_substate_terminated; if (cr) { SU_DEBUG_5(("%s(%p, %p, %p): using existing cr=%p\n", "nua_notify_usage_shutdown", (void *)nh, (void *)ds, (void *)du, (void *)cr)); if (nua_client_resend_request(cr, 1) >= 0) return 0; } else { SU_DEBUG_5(("%s(%p, %p, %p): new NOTIFY cr for %s\n", "nua_notify_usage_shutdown", (void *)nh, (void *)ds, (void *)du, du->du_event ? du->du_event->o_type : "")); if (nua_client_tcreate(nh, nua_r_notify, &nua_notify_client_methods, SIPTAG_EVENT(du->du_event), NUTAG_SUBSTATE(nua_substate_terminated), TAG_END()) >= 0) return 0; } nua_dialog_usage_remove(nh, ds, du, NULL, NULL); return 200; } /* ======================================================================== */ /* REFER */ /* RFC 3515 */ static int nua_refer_server_init(nua_server_request_t *sr); static int nua_refer_server_preprocess(nua_server_request_t *sr); static int nua_refer_server_respond(nua_server_request_t*, tagi_t const *); static int nua_refer_server_report(nua_server_request_t*, tagi_t const *); nua_server_methods_t const nua_refer_server_methods = { SIP_METHOD_REFER, nua_i_refer, /* Event */ { 1, /* Create dialog */ 0, /* Initial request */ 1, /* Target refresh request */ 1, /* Add Contact */ }, nua_refer_server_init, nua_refer_server_preprocess, nua_base_server_params, nua_refer_server_respond, nua_refer_server_report, }; static int nua_refer_server_init(nua_server_request_t *sr) { return 0; } static int nua_refer_server_preprocess(nua_server_request_t *sr) { nua_handle_t *nh = sr->sr_owner; sip_t const *sip = sr->sr_request.sip; struct notifier_usage *nu; sip_event_t *o; if (nh->nh_ds->ds_got_referrals || NH_PGET(nh, refer_with_id)) o = sip_event_format(nh->nh_home, "refer;id=%u", sip->sip_cseq->cs_seq); else o = sip_event_make(nh->nh_home, "refer"); if (o) { sr->sr_usage = nua_dialog_usage_add(nh, nh->nh_ds, nua_notify_usage, o); msg_header_free(nh->nh_home, (msg_header_t *)o); } if (!sr->sr_usage) return SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); nu = nua_dialog_usage_private(sr->sr_usage); nu->nu_requested = sip_now() + NH_PGET(nh, refer_expires); return 0; } static int nua_refer_server_respond(nua_server_request_t *sr, tagi_t const *tags) { nua_handle_t *nh = sr->sr_owner; struct notifier_usage *nu = nua_dialog_usage_private(sr->sr_usage); sip_refer_sub_t const *rs = sip_refer_sub(sr->sr_response.sip); if (sr->sr_status < 200 || nu == NULL) { } else if (sr->sr_status < 300 && /* No subscription if Refer-Sub: false in response */ (rs == NULL || !su_casematch(rs->rs_value, "false"))) { sr->sr_usage->du_ready = 1; nu->nu_expires = sip_now() + NH_PGET(nh, refer_expires); if (sr->sr_application) /* Application responded to REFER */ nu->nu_substate = nua_substate_active; } else { /* Destroy the implicit subscription usage */ sr->sr_terminating = 1; } return nua_base_server_respond(sr, tags); } /** @NUA_EVENT nua_i_refer * * Incoming @b REFER request used to transfer calls. The tag list will * contain tag NUTAG_REFER_EVENT() with the @Event header constructed from * the REFER request. It will also contain the SIPTAG_REFERRED_BY() tag with * the @ReferredBy header containing the identity of the party sending the * REFER. The @ReferredBy structure contained in the tag is constructed from * the @From header if the @ReferredBy header was not present in the REFER * request. * * The application can let the nua to send NOTIFYs from the call it * initiates with nua_invite() if it includes in the nua_invite() arguments * both the NUTAG_NOTIFY_REFER() with the handle with which nua_i_refer was * received and the NUTAG_REFER_EVENT() from #nua_i_refer event tags. * * @param status status code of response sent automatically by stack * @param phrase a short textual description of @a status code * @param nh operation handle associated with the incoming request * @param hmagic application context associated with the handle * (NULL if outside of an already established session) * @param sip incoming REFER request * @param tags NUTAG_REFER_EVENT() \n * SIPTAG_REFERRED_BY() * * @sa nua_refer(), #nua_r_refer, @ReferTo, NUTAG_REFER_EVENT(), * SIPTAG_REFERRED_BY(), @ReferredBy, NUTAG_NOTIFY_REFER(), * NUTAG_REFER_WITH_ID(), @RFC3515. * * @END_NUA_EVENT */ static int nua_refer_server_report(nua_server_request_t *sr, tagi_t const *tags) { nua_handle_t *nh = sr->sr_owner; struct notifier_usage *nu = nua_dialog_usage_private(sr->sr_usage); sip_t const *sip = sr->sr_request.sip; sip_referred_by_t *by = sip->sip_referred_by, default_by[1]; sip_event_t const *o = sr->sr_usage->du_event; enum nua_substate substate = nua_substate_terminated; int initial = sr->sr_initial, retval; if (nu) { if (!sr->sr_terminating) substate = nu->nu_substate; } if (by == NULL) { by = sip_referred_by_init(default_by); by->b_display = sip->sip_from->a_display; *by->b_url = *sip->sip_from->a_url; } retval = nua_base_server_treport(sr, NUTAG_SUBSTATE(substate), NUTAG_REFER_EVENT(o), TAG_IF(by, SIPTAG_REFERRED_BY(by)), TAG_END()); if (retval >= 2 || nu == NULL) return retval; if (initial) nua_stack_post_signal(nh, nua_r_notify, SIPTAG_EVENT(o), SIPTAG_CONTENT_TYPE_STR("message/sipfrag"), SIPTAG_PAYLOAD_STR("SIP/2.0 100 Trying\r\n"), TAG_END()); return retval; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/nua_options.c000066400000000000000000000063441223300710500230460ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2006 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE nua_options.c * @brief Implementation of OPTIONS client. * * OPTIONS server is in nua_session.c. * * @author Pekka Pessi * * @date Created: Wed Mar 8 17:02:19 EET 2006 ppessi */ #include "config.h" #include #include #include #include #include #include #include #include #include "nua_stack.h" /**@fn void nua_options(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * * Query capabilities from server with OPTIONS request. * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Related Tags: * Header tags defined in * * @par Events: * #nua_r_options * * @sa #nua_i_options, @RFC3261 section 10 */ /** @NUA_EVENT nua_r_options * * Answer to outgoing OPTIONS. * * @param status response status code * (if the request is retried the @a status is 100 and the @a * sip->sip_status->st_status contain the real status code * from the response message, e.g., 302, 401, or 407) * @param phrase a short textual description of @a status code * @param nh operation handle associated with the incoming OPTIONS request * @param hmagic application context associated with the handle * @param sip response to OPTIONS request or NULL upon an error * (status code is in @a status and * descriptive message in @a phrase parameters) * @param tags empty * * @sa nua_options(), @RFC3261 section 11, #nua_i_options * * @END_NUA_EVENT */ static nua_client_methods_t const nua_options_client_methods = { SIP_METHOD_OPTIONS, /* crm_method, crm_method_name */ 0, /* crm_extra */ { /* crm_flags */ /* create_dialog */ 0, /* in_dialog */ 0, /* target refresh */ 0 }, NULL, /* crm_template */ NULL, /* crm_init */ NULL, /* crm_send */ NULL, /* crm_check_restart */ NULL, /* crm_recv */ NULL, /* crm_preliminary */ NULL, /* crm_report */ NULL, /* crm_complete */ }; int nua_stack_options(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { return nua_client_create(nh, e, &nua_options_client_methods, tags); } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/nua_params.c000066400000000000000000001552771223300710500226500ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2006 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE nua_register.c * @brief REGISTER and registrations * * @author Pekka Pessi * * @date Created: Wed Mar 8 11:48:49 EET 2006 ppessi */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include "nua_stack.h" #include #include #include #include #include /* ====================================================================== */ /* Helper macros and functions for handling #nua_handle_preferences_t. */ #define NHP_IS_ANY_SET(nhp) nhp_is_any_set((nhp)) /** Check if any preference is set in @a nhp. */ su_inline int nhp_is_any_set(nua_handle_preferences_t const *nhp) { char nhp_zero[sizeof nhp->nhp_set] = { 0 }; return memcmp(&nhp->nhp_set, nhp_zero, sizeof nhp->nhp_set) != 0; } /** Copy set parameters from @a b to @a a. * * If preference is set in @a b, mark it set also in @a a. */ su_inline void nhp_or_set(nua_handle_preferences_t *a, nua_handle_preferences_t const *b) { memcpy(a, b, offsetof(nua_handle_preferences_t, nhp_set)); /* Bitwise or of bitfields, casted to unsigned */ a->nhp_set_.set_unsigned[0] |= b->nhp_set_.set_unsigned[0]; a->nhp_set_.set_unsigned[1] |= b->nhp_set_.set_unsigned[1]; } static int nhp_set_tags(su_home_t *home, nua_handle_preferences_t *nhp, nua_global_preferences_t *ngp, tagi_t const *tags); static int nhp_merge_lists(su_home_t *home, msg_hclass_t *hc, msg_list_t **return_new_list, msg_list_t const *old_list, int already_set, int already_parsed, int always_merge, tag_value_t value); static int nhp_save_params(nua_handle_t *nh, su_home_t *tmphome, nua_global_preferences_t *gsrc, nua_handle_preferences_t *src); /* ====================================================================== */ /* Magical NUTAG_USER_AGENT() - add NHP_USER_AGENT there if it is not there */ #define NHP_USER_AGENT PACKAGE_NAME "/" PACKAGE_VERSION static int already_contains_package_name(char const *s) { char const pn[] = " " PACKAGE_NAME "/"; size_t pnlen = strlen(pn + 1); return su_casenmatch(s, pn + 1, pnlen) || su_strcasestr(s, pn); } /* ====================================================================== */ /* Stack and handle parameters */ static int nua_stack_set_smime_params(nua_t *nua, tagi_t const *tags); /** @internal Methods allowed by default. */ static char const nua_allow_str[] = "INVITE, ACK, BYE, CANCEL, OPTIONS, PRACK, " "MESSAGE, SUBSCRIBE, NOTIFY, REFER, UPDATE"; /** @internal Set default parameters */ int nua_stack_set_defaults(nua_handle_t *nh, nua_handle_preferences_t *nhp) { su_home_t *home = (su_home_t *)nh; /* Set some defaults */ NHP_SET(nhp, retry_count, 3); NHP_SET(nhp, max_subscriptions, 20); NHP_SET(nhp, media_enable, 1); NHP_SET(nhp, accept_multipart, 0); NHP_SET(nhp, invite_enable, 1); NHP_SET(nhp, auto_alert, 0); NHP_SET(nhp, early_media, 0); NHP_SET(nhp, only183_100rel, 0); NHP_SET(nhp, auto_answer, 0); NHP_SET(nhp, auto_ack, 1); NHP_SET(nhp, invite_timeout, 120); nhp->nhp_session_timer = 1800; nhp->nhp_refresher = nua_no_refresher; NHP_SET(nhp, min_se, 120); NHP_SET(nhp, update_refresh, 0); NHP_SET(nhp, message_enable, 1); NHP_SET(nhp, win_messenger_enable, 0); if (getenv("PIMIW_HACK") != 0) NHP_SET(nhp, message_auto_respond, 1); NHP_SET(nhp, media_features, 0); NHP_SET(nhp, callee_caps, 0); NHP_SET(nhp, service_route_enable, 1); NHP_SET(nhp, path_enable, 1); NHP_SET(nhp, refer_expires, 300); NHP_SET(nhp, refer_with_id, 1); NHP_SET(nhp, auto302, 1); NHP_SET(nhp, auto305, 1); NHP_SET(nhp, auto100, 1); NHP_SET(nhp, max_retry_after, 32); NHP_SET(nhp, substate, nua_substate_active); NHP_SET(nhp, sub_expires, 3600); NHP_SET(nhp, allow, sip_allow_make(home, nua_allow_str)); NHP_SET(nhp, supported, sip_supported_make(home, "timer, 100rel")); NHP_SET(nhp, user_agent, su_strdup(home, NHP_USER_AGENT)); NHP_SET(nhp, outbound, su_strdup(home, "natify")); NHP_SET(nhp, keepalive, 120000); NHP_SET(nhp, appl_method, sip_allow_make(home, "INVITE, REGISTER, PUBLISH, SUBSCRIBE")); if (!nhp->nhp_allow || !nhp->nhp_supported || !nhp->nhp_user_agent || !nhp->nhp_outbound) return -1; return 0; } /** @internal Set the default from field */ int nua_stack_set_from(nua_t *nua, int initial, tagi_t const *tags) { sip_from_t const *from = NONE; char const *str = NONE; sip_from_t *f = NULL, f0[1]; int set; tl_gets(tags, /* By nua_stack_set_from() */ SIPTAG_FROM_REF(from), SIPTAG_FROM_STR_REF(str), TAG_END()); if (!initial && from == NONE && str == NONE) return 0; sip_from_init(f0); if (from && from != NONE) { f0->a_display = from->a_display; *f0->a_url = *from->a_url; f = sip_from_dup(nua->nua_home, f0); set = 1; } else if (str && str != NONE) { f = sip_from_make(nua->nua_home, str); if (f) *f0 = *f, f = f0, f->a_params = NULL; set = 1; } else { sip_contact_t const *m; m = nua_stack_get_contact(nua->nua_registrations); if (m) { f0->a_display = m->m_display; *f0->a_url = *m->m_url; f = sip_from_dup(nua->nua_home, f0); } set = 0; } if (!f) return -1; nua->nua_from_is_set = set; *nua->nua_from = *f; return 0; } /** @internal Initialize instance ID. */ int nua_stack_init_instance(nua_handle_t *nh, tagi_t const *tags) { nua_handle_preferences_t *nhp = nh->nh_prefs; char const *instance = NONE; tl_gets(tags, NUTAG_INSTANCE_REF(instance), TAG_END()); if (instance != NONE) { NHP_SET(nhp, instance, su_strdup(nh->nh_home, instance)); if (instance && !nhp->nhp_instance) return -1; } return 0; } /**@fn void nua_set_params(nua_t *nua, tag_type_t tag, tag_value_t value, ...) * * Set @nua parameters, shared by all handles. * * @param nua Pointer to NUA stack object * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Related tags: * NUTAG_ACCEPT_MULTIPART() \n * NUTAG_ALLOW(), SIPTAG_ALLOW(), and SIPTAG_ALLOW_STR() \n * NUTAG_ALLOW_EVENTS(), SIPTAG_ALLOW_EVENTS(), and * SIPTAG_ALLOW_EVENTS_STR() \n * NUTAG_APPL_EVENT() \n * NUTAG_APPL_METHOD() \n * NUTAG_AUTO100() \n * NUTAG_AUTO302() \n * NUTAG_AUTO305() \n * NUTAG_AUTOACK() \n * NUTAG_AUTOALERT() \n * NUTAG_AUTOANSWER() \n * NUTAG_CALLEE_CAPS() \n * NUTAG_DETECT_NETWORK_UPDATES() \n * NUTAG_EARLY_ANSWER() \n * NUTAG_EARLY_MEDIA() \n * NUTAG_ENABLEINVITE() \n * NUTAG_ENABLEMESSAGE() \n * NUTAG_ENABLEMESSENGER() \n * NUTAG_INITIAL_ROUTE() \n * NUTAG_INITIAL_ROUTE_STR() \n * NUTAG_INSTANCE() \n * NUTAG_INVITE_TIMER() \n * NUTAG_KEEPALIVE() \n * NUTAG_KEEPALIVE_STREAM() \n * NUTAG_MAX_RETRY_AFTER() \n * NUTAG_MAX_SUBSCRIPTIONS() \n * NUTAG_MEDIA_ENABLE() \n * NUTAG_MEDIA_FEATURES() \n * NUTAG_MIN_SE() \n * NUTAG_M_DISPLAY() \n * NUTAG_M_FEATURES() \n * NUTAG_M_PARAMS() \n * NUTAG_M_USERNAME() \n * NUTAG_ONLY183_100REL() \n * NUTAG_OUTBOUND() \n * NUTAG_PATH_ENABLE() \n * NUTAG_PROXY() (aka NTATAG_DEFAULT_PROXY()) \n * NUTAG_REFER_EXPIRES() \n * NUTAG_REFER_WITH_ID() \n * NUTAG_REFRESH_WITHOUT_SDP() \n * NUTAG_REGISTRAR() \n * NUTAG_RETRY_COUNT() \n * NUTAG_SERVICE_ROUTE_ENABLE() \n * NUTAG_SESSION_REFRESHER() \n * NUTAG_SESSION_TIMER() \n * NUTAG_SMIME_ENABLE() \n * NUTAG_SMIME_KEY_ENCRYPTION() \n * NUTAG_SMIME_MESSAGE_DIGEST() \n * NUTAG_SMIME_MESSAGE_ENCRYPTION() \n * NUTAG_SMIME_OPT() \n * NUTAG_SMIME_PROTECTION_MODE() \n * NUTAG_SMIME_SIGNATURE() \n * NUTAG_SOA_NAME() \n * NUTAG_SUBSTATE() \n * NUTAG_SUB_EXPIRES() \n * NUTAG_SUPPORTED(), SIPTAG_SUPPORTED(), and SIPTAG_SUPPORTED_STR() \n * NUTAG_UPDATE_REFRESH() \n * NUTAG_USER_AGENT(), SIPTAG_USER_AGENT() and SIPTAG_USER_AGENT_STR() \n * SIPTAG_ORGANIZATION() and SIPTAG_ORGANIZATION_STR() \n * * nua_set_params() also accepts any soa tags, defined in * , and nta tags, defined in . * * @par Events: * #nua_r_set_params * * @par SIP Header as NUA Parameters * The @nua parameters include SIP headers @Allow, @Supported, @Organization, * @UserAgent and @From. They are included in most of the SIP messages sent * by @nua. They are set in the same way as the tagged arguments are * used to populate a SIP message. * @par * When multiple tags for the same header are specified, the behaviour * depends on the header type. If only a single header field can be included * in a SIP message, the latest non-NULL value is used, e.g., @Organization. * However, if the SIP header can consist of multiple lines or header fields * separated by comma, in this case, @Allow and @Supported, all the tagged * values are concatenated. * @par * However, if the tag value is #SIP_NONE (-1 casted as a void pointer), the * values from previous tags are ignored. * * For example, the nua_set_params() call like this: * @code * nua_set_params(nua, * SIPTAG_USER_AGENT_STR("tester/1.0"), * SIPTAG_ALLOW_STR("INVITE,CANCEL,BYE,ACK"), * SIPTAG_ORGANIZATION(NULL), * SIPTAG_USER_AGENT(NULL), * SIPTAG_ALLOW(SIP_NONE), * TAG_END()); * @endcode * will leave @Allow and @Organization headers empty. The @UserAgent header * will contain value "tester/1.0". * @code * nua_set_params(nua, * SIPTAG_ORGANIZATION_STR("Malevolent Microwavers"), * SIPTAG_ALLOW_STR("OPTIONS"), * SIPTAG_ALLOW(SIP_NONE), * SIPTAG_ORGANIZATION_STR("The Phone Company"), * SIPTAG_ALLOW_STR("SUBSCRIBE"), * SIPTAG_ALLOW(NULL), * SIPTAG_ORGANIZATION_STR(NULL), * TAG_END()); * @endcode * sets the header @Allow with value SUBSCRIBE and the * header @Organization will have value The Phone Company. * */ /**@fn void nua_set_hparams(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * * Set the handle-specific parameters. * * The handle-specific parameters override default or global parameters set * by nua_set_params(). The handle-specific parameters are set by several * other operations: nua_invite(), nua_respond(), nua_ack(), * nua_prack(), nua_update(), nua_info(), nua_bye(), nua_options(), * nua_message(), nua_register(), nua_publish(), nua_refer(), * nua_subscribe(), nua_notify(), nua_refer(), and nua_notifier(). * * @param nh Pointer to a NUA handle * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Tags Used to Set Handle-Specific Parameters: * NUTAG_ACCEPT_MULTIPART() \n * NUTAG_ALLOW(), SIPTAG_ALLOW(), and SIPTAG_ALLOW_STR() \n * NUTAG_ALLOW_EVENTS(), SIPTAG_ALLOW_EVENTS(), and * SIPTAG_ALLOW_EVENTS_STR() \n * NUTAG_APPL_EVENT() \n * NUTAG_APPL_METHOD() \n * NUTAG_AUTH_CACHE() \n * NUTAG_AUTO100() \n * NUTAG_AUTO302() \n * NUTAG_AUTO305() \n * NUTAG_AUTOACK() \n * NUTAG_AUTOALERT() \n * NUTAG_AUTOANSWER() \n * NUTAG_CALLEE_CAPS() \n * NUTAG_EARLY_ANSWER() \n * NUTAG_EARLY_MEDIA() \n * NUTAG_ENABLEINVITE() \n * NUTAG_ENABLEMESSAGE() \n * NUTAG_ENABLEMESSENGER() \n * NUTAG_INITIAL_ROUTE() \n * NUTAG_INITIAL_ROUTE_STR() \n * NUTAG_INSTANCE() \n * NUTAG_INVITE_TIMER() \n * NUTAG_KEEPALIVE() \n * NUTAG_KEEPALIVE_STREAM() \n * NUTAG_MAX_RETRY_AFTER() \n * NUTAG_MAX_SUBSCRIPTIONS() \n * NUTAG_MEDIA_ENABLE() \n * NUTAG_MEDIA_FEATURES() \n * NUTAG_MIN_SE() \n * NUTAG_M_DISPLAY() \n * NUTAG_M_FEATURES() \n * NUTAG_M_PARAMS() \n * NUTAG_M_USERNAME() \n * NUTAG_ONLY183_100REL() \n * NUTAG_OUTBOUND() \n * NUTAG_PATH_ENABLE() \n * NUTAG_PROXY() (aka NTATAG_DEFAULT_PROXY()) \n * NUTAG_REFER_EXPIRES() \n * NUTAG_REFER_WITH_ID() \n * NUTAG_REFRESH_WITHOUT_SDP() \n * NUTAG_REGISTRAR() \n * NUTAG_RETRY_COUNT() \n * NUTAG_SERVICE_ROUTE_ENABLE() \n * NUTAG_SESSION_REFRESHER() \n * NUTAG_SESSION_TIMER() \n * NUTAG_SOA_NAME() \n * NUTAG_SUBSTATE() \n * NUTAG_SUB_EXPIRES() \n * NUTAG_SUPPORTED(), SIPTAG_SUPPORTED(), and SIPTAG_SUPPORTED_STR() \n * NUTAG_UPDATE_REFRESH() \n * NUTAG_USER_AGENT(), SIPTAG_USER_AGENT() and SIPTAG_USER_AGENT_STR() \n * SIPTAG_ORGANIZATION() and SIPTAG_ORGANIZATION_STR() \n * Any soa tags are also considered as handle-specific parameters. They are * defined in . * * The global parameters that can not be set by nua_set_hparams() include * NUTAG_DETECT_NETWORK_UPDATES(), NUTAG_SMIME_* tags, and all NTA tags. * * @par Events: * #nua_r_set_params */ /** @NUA_EVENT nua_r_set_params * * Response to nua_set_params() or nua_set_hparams(). * * @param status 200 when successful, error code otherwise * @param phrase a short textual description of @a status code * @param nh NULL when responding to nua_set_params(), * operation handle when responding to nua_set_hparams() * @param hmagic NULL when responding to nua_set_params(), * application contact associated with the operation handle * when responding to nua_set_hparams() * @param sip NULL * @param tags None * * @sa nua_set_params(), nua_set_hparams(), * #nua_r_get_params, nua_get_params(), nua_get_hparams() * * @END_NUA_EVENT */ int nua_stack_set_params(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { nua_handle_t *dnh = nua->nua_dhandle; int status; char const *phrase; nua_handle_preferences_t tmp[1]; int any_changes = 0; enter; { su_home_t tmphome[1] = { SU_HOME_INIT(tmphome) }; nua_handle_preferences_t *nhp = nh->nh_prefs; nua_handle_preferences_t const *dnhp = dnh->nh_prefs; nua_global_preferences_t gtmp[1], *ngp = NULL; *tmp = *nhp; NHP_UNSET_ALL(tmp); /* * Supported features, allowed methods and events are merged * with previous or default settings. * * Here we just copy pointers from default settings. However when saving * settings we have to be extra careful so that we * 1) zero the pointers if the setting has not been modified * 2) do not free pointer if the setting has been modified * See NHP_ZAP_OVERRIDEN() below for gorier details. */ if (!NHP_ISSET(nhp, supported)) tmp->nhp_supported = dnhp->nhp_supported; if (!NHP_ISSET(nhp, allow)) tmp->nhp_allow = dnhp->nhp_allow; if (!NHP_ISSET(nhp, allow_events)) tmp->nhp_allow_events = dnhp->nhp_allow_events; if (!NHP_ISSET(nhp, appl_method)) tmp->nhp_appl_method = dnhp->nhp_appl_method; if (nh == dnh) /* nua_set_params() call, save stack-wide params, too */ ngp = gtmp, *gtmp = *nua->nua_prefs; /* Set and save parameters to tmp */ if (!nh->nh_used_ptags && nhp_set_tags(tmphome, tmp, NULL, nh->nh_ptags) < 0) status = 900, phrase = "Error storing default handle parameters"; else if (nhp_set_tags(tmphome, tmp, ngp, tags) < 0) status = 900, phrase = "Error storing parameters"; else if ((any_changes = nhp_save_params(nh, tmphome, ngp, tmp)) < 0) status = 900, phrase = su_strerror(ENOMEM); else status = 200, phrase = "OK", nh->nh_used_ptags = 1; su_home_deinit(tmphome); } if (status == 200) { nua_handle_preferences_t const *nhp = nh->nh_prefs; nua_handle_preferences_t const *dnhp = dnh->nh_prefs; if (!nh->nh_soa && NHP_GET(nhp, dnhp, media_enable)) { /* Create soa when needed */ char const *soa_name = NHP_GET(nhp, dnhp, soa_name); if (dnh->nh_soa) nh->nh_soa = soa_clone(dnh->nh_soa, nua->nua_root, nh); else nh->nh_soa = soa_create(soa_name, nua->nua_root, nh); if (!nh->nh_soa) status = 900, phrase = "Error Creating SOA Object"; else if (soa_set_params(nh->nh_soa, TAG_NEXT(nh->nh_ptags)) < 0) status = 900, phrase = "Error Setting SOA Parameters"; } else if (nh->nh_soa && !NHP_GET(nhp, dnhp, media_enable)) { /* ... destroy soa when not needed */ soa_destroy(nh->nh_soa), nh->nh_soa = NULL; } if (status == 200 && tags && nh->nh_soa && soa_set_params(nh->nh_soa, TAG_NEXT(tags)) < 0) status = 900, phrase = "Error Setting SOA Parameters"; } if (status == 200 && nh == dnh) { /* Set stack-specific things below */ if (nua_stack_set_smime_params(nua, tags) < 0) { status = 900, phrase = "Error setting S/MIME parameters"; } else if (nua->nua_nta && nta_agent_set_params(nua->nua_nta, TAG_NEXT(tags)) < 0) { status = 900, phrase = "Error setting NTA parameters"; } else { nua_stack_set_from(nua, 0, tags); if (nua->nua_prefs->ngp_detect_network_updates) nua_stack_launch_network_change_detector(nua); } } if (status != 200) { if (e == nua_i_none) SU_DEBUG_1(("nua_set_params(): failed: %s\n", phrase)); return UA_EVENT2(e, status, phrase), -1; } else { if (e == nua_r_set_params) UA_EVENT2(e, status, phrase); if (any_changes) { nua_handle_preferences_t changed[1]; *changed = *nh->nh_prefs; memcpy(&changed->nhp_set_, &tmp->nhp_set_, sizeof changed->nhp_set_); nua_dialog_update_params(nh->nh_ds, changed, nh->nh_prefs, dnh->nh_prefs); } return 0; } } /** Parse parameters from tags to @a nhp or @a ngp. * * @param home allocate new values from @a home * @param nhp structure to store handle preferences * @param ngp structure to store global preferences * @param tags list of tags to parse */ static int nhp_set_tags(su_home_t *home, nua_handle_preferences_t *nhp, nua_global_preferences_t *ngp, tagi_t const *tags) { /* Set copy of string to handle pref structure */ #define NHP_SET_STR(nhp, name, v) \ if ((v) != (tag_value_t)0) { \ char const *_value = (char const *)v; \ char *_new = _value ? su_strdup(home, _value) : NULL; \ if (NHP_ISSET(nhp, name)) \ su_free(home, (void *)nhp->nhp_##name); \ NHP_SET(nhp, name, _new); \ if (_new == NULL && _value != NULL) \ return -1; \ } /* Set copy of string from url to handle pref structure */ #define NHP_SET_STR_BY_URL(nhp, type, name, v) \ if ((v) != (tag_value_t)-1) { \ url_t const *_value = (url_t const *)(v); \ type *_new = (type *)url_as_string(home, (void *)_value); \ if (NHP_ISSET(nhp, name)) \ su_free(home, (void *)nhp->nhp_##name); \ NHP_SET(nhp, name, _new); \ if (_new == NULL && _value != NULL) \ return -1; \ } /* Set copy of header to handle pref structure */ #define NHP_SET_HEADER(nhp, name, hdr, v) \ if ((v) != 0) { \ sip_##hdr##_t const *_value = (sip_##hdr##_t const *)(v); \ sip_##hdr##_t *_new = NULL; \ if (_value != SIP_NONE) \ _new = sip_##name##_dup(home, _value); \ if (NHP_ISSET(nhp, name)) \ msg_header_free_all(home, (void *)nhp->nhp_##name); \ NHP_SET(nhp, name, _new); \ if (_new == NULL && _value != SIP_NONE) \ return -1; \ } /* Set header made of string to handle pref structure */ #define NHP_SET_HEADER_STR(nhp, name, hdr, v) \ if ((v) != 0) { \ char const *_value = (char const *)(v); \ sip_##hdr##_t *_new = NULL; \ if (_value != SIP_NONE) \ _new = sip_##name##_make(home, _value); \ if (NHP_ISSET(nhp, name)) \ msg_header_free_all(home, (void *)nhp->nhp_##name); \ NHP_SET(nhp, name, _new); \ if (_new == NULL && _value != SIP_NONE) \ return -1; \ } /* Append copy of header to handle pref structure */ #define NHP_APPEND_HEADER(nhp, name, hdr, is_str, next, v) \ { \ sip_##hdr##_t const *_value = (sip_##hdr##_t const *)(v); \ char const *_str = (char const *)(v); \ sip_##hdr##_t *_new = NULL; \ sip_##hdr##_t **_end = &nhp->nhp_##name; \ if (_value != SIP_NONE && _value != NULL) { \ _new = (is_str) \ ? sip_##hdr##_make(home, _str) \ : sip_##hdr##_dup(home, _value); \ if (_new == NULL) return -1; \ } \ if (NHP_ISSET(nhp, name)) \ while(*_end) \ _end = next(*_end); \ nhp->nhp_set.nhb_##name = 1; \ *_end = _new; \ } /* Set copy of string from header to handle pref structure */ #define NHP_SET_STR_BY_HEADER(nhp, name, v) \ if ((v) != 0) { \ sip_##name##_t const *_value = (sip_##name##_t const *)(v); \ char *_new = NULL; \ if (_value != SIP_NONE) \ _new = sip_header_as_string(home, (void *)_value); \ if (NHP_ISSET(nhp, name)) \ su_free(home, (void *)nhp->nhp_##name); \ NHP_SET(nhp, name, _new); \ if (_new == NULL && _value != SIP_NONE) \ return -1; \ } tagi_t const *t; for (t = tags; t; t = tl_next(t)) { tag_type_t tag = t->t_tag; tag_value_t value = t->t_value; if (tag == NULL) break; /* NUTAG_RETRY_COUNT(retry_count) */ else if (tag == nutag_retry_count) { NHP_SET(nhp, retry_count, (unsigned)value); } /* NUTAG_MAX_SUBSCRIPTIONS(max_subscriptions) */ else if (tag == nutag_max_subscriptions) { NHP_SET(nhp, max_subscriptions, (unsigned)value); } /* NUTAG_SOA_NAME(soa_name) */ else if (tag == nutag_soa_name) { NHP_SET_STR(nhp, soa_name, value); } /* NUTAG_MEDIA_ENABLE(media_enable) */ else if (tag == nutag_media_enable) { NHP_SET(nhp, media_enable, value != 0); } /* NUTAG_ACCEPT_MULTIPART(accept_multipart) */ else if (tag == nutag_accept_multipart) { NHP_SET(nhp, accept_multipart, value != 0); } /* NUTAG_ENABLEINVITE(invite_enable) */ else if (tag == nutag_enableinvite) { NHP_SET(nhp, invite_enable, value != 0); } /* NUTAG_AUTOALERT(auto_alert) */ else if (tag == nutag_autoalert) { NHP_SET(nhp, auto_alert, value != 0); } /* NUTAG_EARLY_ANSWER(early_answer) */ else if (tag == nutag_early_answer) { NHP_SET(nhp, early_answer, value != 0); } /* NUTAG_EARLY_MEDIA(early_media) */ else if (tag == nutag_early_media) { NHP_SET(nhp, early_media, value != 0); } /* NUTAG_ONLY183_100REL(only183_100rel) */ else if (tag == nutag_only183_100rel) { NHP_SET(nhp, only183_100rel, value != 0); } /* NUTAG_AUTOANSWER(auto_answer) */ else if (tag == nutag_autoanswer) { NHP_SET(nhp, auto_answer, value != 0); } /* NUTAG_AUTOACK(auto_ack) */ else if (tag == nutag_autoack) { NHP_SET(nhp, auto_ack, value != 0); } /* NUTAG_AUTO302(auto302) */ else if (tag == nutag_auto302) { NHP_SET(nhp, auto302, value != 0); } /* NUTAG_AUTO305(auto305) */ else if (tag == nutag_auto305) { NHP_SET(nhp, auto305, value != 0); } /* NUTAG_AUTO100(auto100) */ else if (tag == nutag_auto100) { NHP_SET(nhp, auto100, value != 0); } /* NUTAG_MAX_RETRY_AFTER(retry_after) */ else if (tag == nutag_max_retry_after) { NHP_SET(nhp, max_retry_after, (unsigned)value); } /* NUTAG_INVITE_TIMER(invite_timeout) */ else if (tag == nutag_invite_timer) { NHP_SET(nhp, invite_timeout, (unsigned)value); } /* NUTAG_SESSION_TIMER(session_timer) */ else if (tag == nutag_session_timer) { NHP_SET(nhp, session_timer, (unsigned)value); } /* NUTAG_MIN_SE(min_se) */ else if (tag == nutag_min_se) { NHP_SET(nhp, min_se, (unsigned)value); } /* NUTAG_SESSION_REFRESHER(refresher) */ else if (tag == nutag_session_refresher) { int refresher = value; if (refresher >= nua_remote_refresher) refresher = nua_remote_refresher; else if (refresher <= nua_no_refresher) refresher = nua_no_refresher; NHP_SET(nhp, refresher, (enum nua_session_refresher)refresher); } /* NUTAG_UPDATE_REFRESH(update_refresh) */ else if (tag == nutag_update_refresh) { NHP_SET(nhp, update_refresh, value != 0); } /* NUTAG_REFRESH_WITHOUT_SDP(refresh_without_sdp) */ else if (tag == nutag_refresh_without_sdp) { NHP_SET(nhp, refresh_without_sdp, value != 0); } /* NUTAG_ENABLEMESSAGE(message_enable) */ else if (tag == nutag_enablemessage) { NHP_SET(nhp, message_enable, value != 0); } /* NUTAG_ENABLEMESSENGER(win_messenger_enable) */ else if (tag == nutag_enablemessenger) { NHP_SET(nhp, win_messenger_enable, value != 0); } /* NUTAG_CALLEE_CAPS(callee_caps) */ else if (tag == nutag_callee_caps) { NHP_SET(nhp, callee_caps, value != 0); } /* NUTAG_MEDIA_FEATURES(media_features) */ else if (tag == nutag_media_features) { NHP_SET(nhp, media_features, value != 0); } /* NUTAG_SERVICE_ROUTE_ENABLE(service_route_enable) */ else if (tag == nutag_service_route_enable) { NHP_SET(nhp, service_route_enable, value != 0); } /* NUTAG_PATH_ENABLE(path_enable) */ else if (tag == nutag_path_enable) { NHP_SET(nhp, path_enable, value != 0); } /* NUTAG_AUTH_CACHE(auth_cache) */ else if (tag == nutag_auth_cache) { if (value >= 0 && value < (tag_value_t)_nua_auth_cache_invalid) NHP_SET(nhp, auth_cache, (int)value); } /* NUTAG_REFER_EXPIRES(refer_expires) */ else if (tag == nutag_refer_expires) { NHP_SET(nhp, refer_expires, value); } /* NUTAG_REFER_WITH_ID(refer_with_id) */ else if (tag == nutag_refer_with_id) { NHP_SET(nhp, refer_with_id, value != 0); } /* NUTAG_SUBSTATE(substate) */ else if (tag == nutag_substate) { NHP_SET(nhp, substate, (int)value); } /* NUTAG_SUB_EXPIRES(sub_expires) */ else if (tag == nutag_sub_expires) { NHP_SET(nhp, sub_expires, value); } /* NUTAG_KEEPALIVE(keepalive) */ else if (tag == nutag_keepalive) { NHP_SET(nhp, keepalive, (unsigned)value); } /* NUTAG_KEEPALIVE_STREAM(keepalive_stream) */ else if (tag == nutag_keepalive_stream) { NHP_SET(nhp, keepalive_stream, (unsigned)value); } /* NUTAG_SUPPORTED(feature) */ /* SIPTAG_SUPPORTED_STR(supported_str) */ /* SIPTAG_SUPPORTED(supported) */ else if (tag == nutag_supported || tag == siptag_supported || tag == siptag_supported_str) { int ok; sip_supported_t *supported = NULL; ok = nhp_merge_lists(home, sip_supported_class, &supported, nhp->nhp_supported, NHP_ISSET(nhp, supported), /* already set by tags */ tag == siptag_supported, /* dup it, don't make */ tag == nutag_supported, /* merge with old value */ t->t_value); if (ok < 0) return -1; else if (ok) NHP_SET(nhp, supported, supported); } /* NUTAG_ALLOW(allowing) */ /* SIPTAG_ALLOW_STR(allow_str) */ /* SIPTAG_ALLOW(allow) */ else if (tag == nutag_allow || tag == siptag_allow_str || tag == siptag_allow) { int ok; msg_list_t *allow = NULL; ok = nhp_merge_lists(home, sip_allow_class, &allow, (msg_list_t const *)nhp->nhp_allow, NHP_ISSET(nhp, allow), /* already set by tags */ tag == siptag_allow, /* dup it, don't make */ tag == nutag_allow, /* merge with old value */ t->t_value); if (ok < 0) return -1; else if (ok) NHP_SET(nhp, allow, (sip_allow_t *)allow); } /* NUTAG_ALLOW_EVENTS(allow_events) */ /* SIPTAG_ALLOW_EVENTS_STR(allow_events) */ /* SIPTAG_ALLOW_EVENTS(allow_events) */ else if (tag == nutag_allow_events || tag == siptag_allow_events_str || tag == siptag_allow_events) { int ok; sip_allow_events_t *allow_events = NULL; ok = nhp_merge_lists(home, sip_allow_events_class, &allow_events, nhp->nhp_allow_events, NHP_ISSET(nhp, allow_events), /* already set */ tag == siptag_allow_events, /* dup it, don't make */ tag == nutag_allow_events, /* merge with old value */ t->t_value); if (ok < 0) return -1; else if (ok) NHP_SET(nhp, allow_events, allow_events); } else if (tag == nutag_appl_event) { int ok; sip_allow_events_t *appl_event = NULL; tag_value_t value = t->t_value; if (value == 0) value = (tag_value_t)NUA_NONE; ok = nhp_merge_lists(home, sip_allow_events_class, &appl_event, nhp->nhp_appl_event, NHP_ISSET(nhp, appl_event), /* already set */ 0, /* dup it, don't make */ 1, /* merge with old value */ value); if (ok < 0) return -1; else if (ok) NHP_SET(nhp, appl_event, appl_event); } /* NUTAG_APPL_METHOD(appl_method) */ else if (tag == nutag_appl_method) { if (t->t_value == 0) { NHP_SET(nhp, appl_method, NULL); } else { int ok; msg_list_t *appl_method = NULL; ok = nhp_merge_lists(home, sip_allow_class, &appl_method, (msg_list_t const *)nhp->nhp_appl_method, /* already set by tags? */ NHP_ISSET(nhp, appl_method), 0, /* dup it, don't make */ 1, /* merge with old value */ t->t_value); if (ok < 0) return -1; else if (ok) NHP_SET(nhp, appl_method, (sip_allow_t *)appl_method); } } else if (tag == nutag_initial_route || tag == nutag_initial_route_str) { #define next_route(r) (&(r)->r_next) NHP_APPEND_HEADER(nhp, initial_route, route, (tag == nutag_initial_route_str), next_route, t->t_value); sip_route_fix(nhp->nhp_initial_route); } /* SIPTAG_USER_AGENT(user_agent) */ else if (tag == siptag_user_agent) { NHP_SET_STR_BY_HEADER(nhp, user_agent, value); } /* SIPTAG_USER_AGENT_STR(user_agent_str) */ else if (tag == siptag_user_agent_str && value != 0) { if (value == -1) value = 0; NHP_SET_STR(nhp, user_agent, value); } /* NUTAG_USER_AGENT(ua_name) */ else if (tag == nutag_user_agent) { /* Add contents of NUTAG_USER_AGENT() to our distribution name */ char const *str = (void *)value, *ua; if (str && !already_contains_package_name(str)) ua = su_sprintf(home, "%s %s", str, NHP_USER_AGENT); else if (str) ua = su_strdup(home, str); else ua = su_strdup(home, NHP_USER_AGENT); NHP_SET(nhp, user_agent, ua); } /* SIPTAG_ORGANIZATION(organization) */ else if (tag == siptag_organization) { NHP_SET_STR_BY_HEADER(nhp, organization, value); } /* SIPTAG_ORGANIZATION_STR(organization_str) */ else if (tag == siptag_organization_str) { if (value == -1) value = 0; NHP_SET_STR(nhp, organization, value); } /* NUTAG_REGISTRAR(registrar) */ else if (tag == nutag_registrar) { NHP_SET_STR_BY_URL(nhp, char, registrar, value); if (NHP_ISSET(nhp, registrar) && su_strmatch(nhp->nhp_registrar, "*")) NHP_SET_STR(nhp, registrar, 0); } /* NUTAG_INSTANCE(instance) */ else if (tag == nutag_instance) { NHP_SET_STR(nhp, instance, value); } /* NUTAG_M_DISPLAY(m_display) */ else if (tag == nutag_m_display) { NHP_SET_STR(nhp, m_display, value); } /* NUTAG_M_USERNAME(m_username) */ else if (tag == nutag_m_username) { NHP_SET_STR(nhp, m_username, value); } /* NUTAG_M_PARAMS(m_params) */ else if (tag == nutag_m_params) { NHP_SET_STR(nhp, m_params, value); } /* NUTAG_M_FEATURES(m_features) */ else if (tag == nutag_m_features) { NHP_SET_STR(nhp, m_features, value); } /* NUTAG_OUTBOUND(outbound) */ else if (tag == nutag_outbound) { NHP_SET_STR(nhp, outbound, value); } /* NUTAG_PROXY() (aka NTATAG_DEFAULT_PROXY()) */ else if (tag == ntatag_default_proxy) { NHP_SET_STR_BY_URL(nhp, url_string_t, proxy, value); } /* NUTAG_DETECT_NETWORK_UPDATES(detect_network_updates) */ else if (ngp && tag == nutag_detect_network_updates) { int detector = (int)value; if (detector < NUA_NW_DETECT_NOTHING) detector = NUA_NW_DETECT_NOTHING; else if (detector > NUA_NW_DETECT_TRY_FULL) detector = NUA_NW_DETECT_TRY_FULL; ngp->ngp_detect_network_updates = detector; ngp->ngp_set.ngp_detect_network_updates = 1; } /* NUTAG_SHUTDOWN_EVENTS() */ else if (ngp && tag == nutag_shutdown_events) { ngp->ngp_shutdown_events = value != 0; ngp->ngp_set.ngp_shutdown_events = 1; } /* NUTAG_DEFERRABLE_TIMERS() */ else if (ngp && tag == nutag_deferrable_timers) { ngp->ngp_deferrable_timers = value != 0; ngp->ngp_set.ngp_deferrable_timers = 1; } } return 0; } /** Merge (when needed) new values with old values. */ static int nhp_merge_lists(su_home_t *home, msg_hclass_t *hc, msg_list_t **return_new_list, msg_list_t const *old_list, int already_set, int already_parsed, int always_merge, tag_value_t value) { msg_list_t *list, *elems; if (value == -1) { *return_new_list = NULL; return 1; } if (value == 0) { if (!already_set && !always_merge) { *return_new_list = NULL; return 1; } return 0; } if (already_parsed) elems = (void *)msg_header_dup_as(home, hc, (msg_header_t *)value); else elems = (void *)msg_header_make(home, hc, (char const *)value); if (!elems) return -1; list = (msg_list_t *)old_list; if (!already_set) { if (always_merge && list) { list = (void *)msg_header_dup_as(home, hc, (void *)old_list); if (!list) return -1; } else list = NULL; } if (!list) { *return_new_list = elems; return 1; } /* Add contents to the new list to the old list */ if (msg_params_join(home, (msg_param_t **)&list->k_items, elems->k_items, 2 /* prune */, 0 /* don't dup */) < 0) return -1; *return_new_list = (msg_list_t *)msg_header_dup_as(home, hc, (msg_header_t *)list); if (!*return_new_list) return -1; msg_header_free(home, (msg_header_t *)list); msg_header_free(home, (msg_header_t *)elems); return 1; } /** Save parameters in @a gtmp and @a tmp. * * @retval 1 - parameters were changed * @retval 0 - no changes in parameters * @retval -1 - an error */ static int nhp_save_params(nua_handle_t *nh, su_home_t *tmphome, nua_global_preferences_t *gsrc, nua_handle_preferences_t *src) { su_home_t *home = nh->nh_home; nua_t *nua = nh->nh_nua; nua_handle_t *dnh = nua->nua_dhandle; nua_handle_preferences_t *dst = nh->nh_prefs, old[1]; if (gsrc) { *nua->nua_prefs = *gsrc; /* No pointers this far */ } if (!NHP_IS_ANY_SET(src)) return 0; if (nh == dnh || nh->nh_prefs != dnh->nh_prefs) { dst = nh->nh_prefs, *old = *dst; } else { dst = su_zalloc(home, sizeof *dst), memset(old, 0, sizeof *old); if (!dst) return -1; } /* Move allocations from tmphome to home */ su_home_move(nh->nh_home, tmphome); /* Copy parameters that are set from src to dst */ nhp_or_set(dst, src); /* Handle pointer items. Free changed ones and zap unset ones. */ /* Note that pointer items where !NHP_ISSET(old, pref) are not freed (because they were just on loan from the default preference set) */ #define NHP_ZAP_OVERRIDEN(old, dst, free, pref) \ (((NHP_ISSET(old, pref) && \ (old)->nhp_##pref && (old)->nhp_##pref != (dst)->nhp_##pref) \ ? (free)(home, (void *)(old)->nhp_##pref) : (void)0), \ (void)(!(dst)->nhp_set.nhb_##pref ? (dst)->nhp_##pref = NULL : NULL)) NHP_ZAP_OVERRIDEN(old, dst, su_free, soa_name); NHP_ZAP_OVERRIDEN(old, dst, su_free, registrar); NHP_ZAP_OVERRIDEN(old, dst, msg_header_free, allow); NHP_ZAP_OVERRIDEN(old, dst, msg_header_free, supported); NHP_ZAP_OVERRIDEN(old, dst, msg_header_free, allow_events); NHP_ZAP_OVERRIDEN(old, dst, msg_header_free, appl_event); NHP_ZAP_OVERRIDEN(old, dst, su_free, user_agent); NHP_ZAP_OVERRIDEN(old, dst, su_free, organization); NHP_ZAP_OVERRIDEN(old, dst, su_free, m_display); NHP_ZAP_OVERRIDEN(old, dst, su_free, m_username); NHP_ZAP_OVERRIDEN(old, dst, su_free, m_params); NHP_ZAP_OVERRIDEN(old, dst, su_free, m_features); NHP_ZAP_OVERRIDEN(old, dst, su_free, instance); NHP_ZAP_OVERRIDEN(old, dst, su_free, outbound); NHP_ZAP_OVERRIDEN(old, dst, msg_header_free, appl_method); NHP_ZAP_OVERRIDEN(old, dst, msg_header_free, initial_route); nh->nh_prefs = dst; return memcmp(dst, old, sizeof *dst) != 0; } static int nua_handle_tags_filter(tagi_t const *f, tagi_t const *t); static int nua_handle_param_filter(tagi_t const *f, tagi_t const *t); /** Save taglist to a handle */ int nua_handle_save_tags(nua_handle_t *nh, tagi_t *tags) { /* Initialization parameters */ url_string_t const *url = NULL; sip_to_t const *p_to = NULL; char const *to_str = NULL; sip_from_t const *p_from = NULL; char const *from_str = NULL; nua_handle_t *identity = NULL; tagi_t const *t; su_home_t tmphome[SU_HOME_AUTO_SIZE(1024)]; int error; #if HAVE_OPEN_C /* Nice. An old symbian compiler */ tagi_t tagfilter[2]; tagi_t paramfilter[2]; tagfilter[0].t_tag = tag_filter; tagfilter[0].t_value = tag_filter_v(nua_handle_tags_filter); tagfilter[1].t_tag = (tag_type_t)0; tagfilter[1].t_value = (tag_value_t)0; paramfilter[0].t_tag = tag_filter; paramfilter[0].t_value = tag_filter_v(nua_handle_param_filter); paramfilter[1].t_tag = (tag_type_t)0; paramfilter[1].t_value = (tag_value_t)0; #else tagi_t const tagfilter[] = { { TAG_FILTER(nua_handle_tags_filter) }, { TAG_NULL() } }; tagi_t const paramfilter[] = { { TAG_FILTER(nua_handle_param_filter) }, { TAG_NULL() } }; #endif for (t = tags; t; t = tl_next(t)) { if (t->t_tag == NULL) break; /* SIPTAG_FROM_REF(p_from) */ else if (t->t_tag == siptag_from) { p_from = (sip_from_t *)t->t_value, from_str = NULL; } /* SIPTAG_FROM_STR_REF(from_str) */ else if (t->t_tag == siptag_from_str) { from_str = (char const *)t->t_value, p_from = NULL; } /* SIPTAG_TO_REF(p_to) */ else if (t->t_tag == siptag_to) { p_to = (sip_to_t *)t->t_value, to_str = NULL; } /* SIPTAG_TO_STR_REF(to_str) */ else if (t->t_tag == siptag_to_str) { to_str = (char const *)t->t_value, p_to = NULL; } /* NUTAG_IDENTITY_REF(identity) */ else if (t->t_tag == nutag_identity) { identity = (nua_handle_t *)t->t_value; } /* NUTAG_URL_REF(url) */ else if (t->t_tag == nutag_url) { url = (url_string_t *)t->t_value; } /* NUTAG_SIPS_URL_REF(url) */ else if (t->t_tag == nutag_sips_url) { url = (url_string_t *)t->t_value; } } su_home_auto(tmphome, sizeof tmphome); if (p_from) ; else if (from_str) p_from = sip_from_make(tmphome, from_str); else p_from = SIP_NONE; if (p_to) ; else if (to_str) p_to = sip_to_make(tmphome, to_str); else if (url) p_to = sip_to_create(tmphome, url), p_to ? sip_aor_strip((url_t*)p_to->a_url) : 0; else p_to = SIP_NONE; if (p_to == NULL || p_from == NULL) { su_home_deinit(tmphome); return -1; } nh->nh_tags = tl_filtered_tlist(nh->nh_home, tagfilter, TAG_IF(p_from != SIP_NONE, SIPTAG_FROM(p_from)), TAG_IF(p_from != SIP_NONE, TAG_FILTER(nua_handle_tags_filter)), TAG_IF(p_to != SIP_NONE, SIPTAG_TO(p_to)), TAG_IF(p_to != SIP_NONE, TAG_FILTER(nua_handle_tags_filter)), TAG_NEXT(tags)); nh->nh_ptags = tl_filtered_tlist(nh->nh_home, paramfilter, TAG_NEXT(tags)); error = nh->nh_tags == NULL || nh->nh_ptags == NULL; if (!error) tl_gets(nh->nh_tags, /* These does not change while nh lives */ SIPTAG_FROM_REF(nh->nh_ds->ds_local), SIPTAG_TO_REF(nh->nh_ds->ds_remote), TAG_END()); if (nh->nh_ptags && nh->nh_ptags->t_tag == NULL) su_free(nh->nh_home, nh->nh_ptags), nh->nh_ptags = NULL; if (identity) nh->nh_identity = nua_handle_ref(identity); su_home_deinit(tmphome); return -error; } /** Filter tags used for settings. */ static int nua_handle_param_filter(tagi_t const *f, tagi_t const *t) { char const *ns; if (!t || !t->t_tag) return 0; if (t->t_tag == nutag_url || t->t_tag == nutag_sips_url || t->t_tag == nutag_identity) return 0; ns = t->t_tag->tt_ns; if (!ns) return 0; return strcmp(ns, "nua") == 0 || strcmp(ns, "soa") == 0; } /** Filter tags stored permanently as taglist. */ static int nua_handle_tags_filter(tagi_t const *f, tagi_t const *t) { tag_type_t tag; if (!t || !t->t_tag) return 0; tag = t->t_tag; if (tag == tag_filter) return 0; /* Accept @From or @To only when they are followed by TAG_FILTER(nua_handle_tags_filter) */ if (tag == siptag_from || tag == siptag_to) { t = tl_next(t); return t && t->t_tag == tag_filter && t->t_value == (tag_value_t)nua_handle_tags_filter; } if (tag == nutag_identity) return 0; if (tag == siptag_from_str) return 0; if (tag == siptag_to_str) return 0; /** Ignore @CSeq, @RSeq, @RAck, @Timestamp, and @ContentLength */ if (tag == siptag_cseq || tag == siptag_cseq_str) return 0; if (tag == siptag_rseq || tag == siptag_rseq_str) return 0; if (tag == siptag_rack || tag == siptag_rack_str) return 0; if (tag == siptag_timestamp || tag == siptag_timestamp_str) return 0; if (tag == siptag_content_length || tag == siptag_content_length_str) return 0; return ! nua_handle_param_filter(f, t); } static int nua_stack_set_smime_params(nua_t *nua, tagi_t const *tags) { #if HAVE_SOFIA_SMIME int smime_enable = nua->sm->sm_enable; int smime_opt = nua->sm->sm_opt; int smime_protection_mode = nua->sm->sm_protection_mode; char const *smime_message_digest = NONE; char const *smime_signature = NONE; char const *smime_key_encryption = NONE; char const *smime_message_encryption = NONE; char const *smime_path = NONE; int n; n = tl_gets(tags, NUTAG_SMIME_ENABLE_REF(smime_enable), NUTAG_SMIME_OPT_REF(smime_opt), NUTAG_SMIME_PROTECTION_MODE_REF(smime_protection_mode), NUTAG_SMIME_MESSAGE_DIGEST_REF(smime_message_digest), NUTAG_SMIME_SIGNATURE_REF(smime_signature), NUTAG_SMIME_KEY_ENCRYPTION_REF(smime_key_encryption), NUTAG_SMIME_MESSAGE_ENCRYPTION_REF(smime_message_encryption), NUTAG_CERTIFICATE_DIR_REF(smime_path), TAG_NULL()); if (n <= 0) return n; /* XXX - all other S/MIME parameters? */ return sm_set_params(nua->sm, smime_enable, smime_opt, smime_protection_mode, smime_path); #endif return 0; } /**@fn void nua_get_params(nua_t *nua, tag_type_t tag, tag_value_t value, ...) * * Get NUA parameters matching with the given filter. * The values of NUA parameters is returned in #nua_r_get_params event. * * @param nua Pointer to NUA stack object * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Related tags: * TAG_ANY() \n * otherwise same tags as nua_set_params() * * @par Events: * #nua_r_get_params * * @par Examples * Find out default values of all parameters: * @code * nua_get_params(nua, TAG_ANY(), TAG_END()); * @endcode */ /**@fn void nua_get_hparams(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) * * Get values of handle-specific parameters in #nua_r_get_params event. * * Application will specify either expilicit list of tags it is interested * in, or a filter (at the moment, TAG_ANY()). The values are returned as a * list of tags in the #nua_r_get_params event. * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * * The handle-specific parameters will contain only the parameters actually * modified by application, either by nua_set_hparams() or some other * handle-specific call. Currently, no NTA parameters are returned. They are * returned only when application asks for user-agent-level parameters using * either nua_get_params() or using default handle, eg. * @code * nua_get_hparams(nua_default(nua), TAG_ANY()) * @endcode * * @return * nothing * * @par Related tags: * #TAG_ANY \n * othervise same tags as nua_set_hparams() * * @par Events: * #nua_r_get_params */ /** @NUA_EVENT nua_r_get_params * * Answer to nua_get_params() or nua_get_hparams(). * * @param status 200 when succesful, error code otherwise * @param phrase a short textual description of @a status code * @param nh NULL when responding to nua_get_params(), * operation handle when responding to nua_get_hparams() * @param hmagic NULL when responding to nua_get_params(), * application contact associated with the operation handle * when responding to nua_get_hparams() * @param sip NULL * @param tags * NUTAG_ACCEPT_MULTIPART() \n * NUTAG_APPL_EVENT() \n * NUTAG_APPL_METHOD() \n * NUTAG_AUTH_CACHE() \n * NUTAG_AUTOACK() \n * NUTAG_AUTOALERT() \n * NUTAG_AUTOANSWER() \n * NUTAG_CALLEE_CAPS() \n * NUTAG_DETECT_NETWORK_UPDATES() \n * NUTAG_EARLY_ANSWER() \n * NUTAG_EARLY_MEDIA() \n * NUTAG_ENABLEINVITE() \n * NUTAG_ENABLEMESSAGE() \n * NUTAG_ENABLEMESSENGER() \n * NUTAG_INITIAL_ROUTE() \n * NUTAG_INITIAL_ROUTE_STR() \n * NUTAG_INSTANCE() \n * NUTAG_INVITE_TIMER() \n * NUTAG_KEEPALIVE() \n * NUTAG_KEEPALIVE_STREAM() \n * NUTAG_MAX_SUBSCRIPTIONS() \n * NUTAG_MEDIA_ENABLE() \n * NUTAG_MEDIA_FEATURES() \n * NUTAG_MIN_SE() \n * NUTAG_M_DISPLAY() \n * NUTAG_M_FEATURES() \n * NUTAG_M_PARAMS() \n * NUTAG_M_USERNAME() \n * NUTAG_ONLY183_100REL() \n * NUTAG_OUTBOUND() \n * NUTAG_PATH_ENABLE() \n * NUTAG_REFER_EXPIRES() \n * NUTAG_REFER_WITH_ID() \n * NUTAG_REFRESH_WITHOUT_SDP() \n * NUTAG_REGISTRAR() \n * NUTAG_RETRY_COUNT() \n * NUTAG_SERVICE_ROUTE_ENABLE() \n * NUTAG_SESSION_REFRESHER() \n * NUTAG_SESSION_TIMER() \n * NUTAG_SMIME_ENABLE() \n * NUTAG_SMIME_KEY_ENCRYPTION() \n * NUTAG_SMIME_MESSAGE_DIGEST() \n * NUTAG_SMIME_MESSAGE_ENCRYPTION() \n * NUTAG_SMIME_OPT() \n * NUTAG_SMIME_PROTECTION_MODE() \n * NUTAG_SMIME_SIGNATURE() \n * NUTAG_SOA_NAME() \n * NUTAG_SUBSTATE() \n * NUTAG_SUB_EXPIRES() \n * NUTAG_UPDATE_REFRESH() \n * NUTAG_USER_AGENT() \n * SIPTAG_ALLOW() \n * SIPTAG_ALLOW_STR() \n * SIPTAG_ALLOW_EVENTS() \n * SIPTAG_ALLOW_EVENTS_STR() \n * SIPTAG_FROM() \n * SIPTAG_FROM_STR() \n * SIPTAG_ORGANIZATION() \n * SIPTAG_ORGANIZATION_STR() \n * SIPTAG_SUPPORTED() \n * SIPTAG_SUPPORTED_STR() \n * SIPTAG_USER_AGENT() \n * SIPTAG_USER_AGENT_STR() \n * * @sa nua_get_params(), nua_get_hparams(), * nua_set_params(), nua_set_hparams(), #nua_r_set_params * * @END_NUA_EVENT */ /**@internal * Send a list of NUA parameters to the application. * * This function gets invoked when application calls either nua_get_params() * or nua_get_hparams(). * * The parameter tag list will initially contain all the relevant parameter * tags, and it will be filtered down to parameters asked by application. * * The handle-specific parameters will contain only the parameters actually * modified by application, either by nua_set_hparams() or some other * handle-specific call. NTA parameters are returned only when application * asks for user-agent-level parameters using nua_get_params(). * */ int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { nua_handle_t *dnh = nua->nua_dhandle; nua_global_preferences_t const *ngp = nua->nua_prefs; nua_handle_preferences_t const *nhp = nh->nh_prefs; nua_handle_preferences_t const nhp_zero[1] = {{ 0 }}; tagi_t *lst; int has_from; sip_from_t from[1]; sip_contact_t const *m; /* nta */ unsigned udp_mtu = 0; usize_t max_proceeding = 0; unsigned sip_t1 = 0, sip_t2 = 0, sip_t4 = 0, sip_t1x64 = 0; unsigned debug_drop_prob = 0; url_string_t const *proxy = NULL; sip_contact_t const *aliases = NULL; unsigned flags = 0; /* soa */ tagi_t *media_params = NULL; su_home_t tmphome[SU_HOME_AUTO_SIZE(16536)]; enter; if (nh == dnh) nta_agent_get_params(nua->nua_nta, NTATAG_UDP_MTU_REF(udp_mtu), NTATAG_MAX_PROCEEDING_REF(max_proceeding), NTATAG_SIP_T1_REF(sip_t1), NTATAG_SIP_T2_REF(sip_t2), NTATAG_SIP_T4_REF(sip_t4), NTATAG_SIP_T1X64_REF(sip_t1x64), NTATAG_DEBUG_DROP_PROB_REF(debug_drop_prob), NTATAG_DEFAULT_PROXY_REF(proxy), NTATAG_ALIASES_REF(aliases), NTATAG_SIPFLAGS_REF(flags), TAG_END()); if (nh->nh_ds->ds_local) has_from = 1, *from = *nh->nh_ds->ds_local, from->a_params = NULL; else /* if (nua->nua_from_is_set) */ has_from = 1, *from = *nua->nua_from; media_params = soa_get_paramlist(nh->nh_soa, TAG_END()); m = nua_stack_get_contact(nua->nua_registrations); /* Include tag in the list returned to user * if it has been earlier set (by user) */ #define TIF(TAG, pref) \ TAG_IF(nhp->nhp_set.nhb_##pref, TAG(nhp->nhp_##pref)) /* Include tag in the list returned to user * if it has been earlier set (by user) * but always include in the default parameters */ #define TIFD(TAG, pref) \ TAG_IF(nh == dnh || nhp->nhp_set.nhb_##pref, TAG(nhp->nhp_##pref)) /* Include string tag made out of SIP header * if it has been earlier set (by user) */ #define TIF_STR(TAG, pref) \ TAG_IF(nhp->nhp_set.nhb_##pref, \ TAG(nhp->nhp_set.nhb_##pref && nhp->nhp_##pref \ ? sip_header_as_string(tmphome, (void *)nhp->nhp_##pref) : NULL)) /* Include header tag made out of string * if it has been earlier set (by user) */ #define TIF_SIP(TAG, pref) \ TAG_IF(nhp->nhp_set.nhb_##pref, \ TAG(nhp->nhp_set.nhb_##pref && nhp->nhp_##pref \ ? sip_##pref##_make(tmphome, (char *)nhp->nhp_##pref) \ : NULL)) if (nh != dnh && nhp == dnh->nh_prefs) nhp = nhp_zero; su_home_auto(tmphome, sizeof(tmphome)); lst = tl_filtered_tlist (tmphome, tags, TAG_IF(has_from, SIPTAG_FROM(from)), TAG_IF(has_from, SIPTAG_FROM_STR(has_from ? sip_header_as_string(tmphome, (void *)from) : NULL)), TIF(NUTAG_RETRY_COUNT, retry_count), TIF(NUTAG_MAX_SUBSCRIPTIONS, max_subscriptions), TIF(NUTAG_SOA_NAME, soa_name), TIF(NUTAG_MEDIA_ENABLE, media_enable), TIF(NUTAG_ACCEPT_MULTIPART, accept_multipart), TIF(NUTAG_ENABLEINVITE, invite_enable), TIF(NUTAG_AUTOALERT, auto_alert), TIF(NUTAG_EARLY_ANSWER, early_answer), TIF(NUTAG_EARLY_MEDIA, early_media), TIF(NUTAG_ONLY183_100REL, only183_100rel), TIF(NUTAG_AUTOANSWER, auto_answer), TIF(NUTAG_AUTOACK, auto_ack), TIF(NUTAG_INVITE_TIMER, invite_timeout), TIFD(NUTAG_SESSION_TIMER, session_timer), TIF(NUTAG_MIN_SE, min_se), TIFD(NUTAG_SESSION_REFRESHER, refresher), TIF(NUTAG_UPDATE_REFRESH, update_refresh), TIF(NUTAG_REFRESH_WITHOUT_SDP, refresh_without_sdp), TIF(NUTAG_ENABLEMESSAGE, message_enable), TIF(NUTAG_ENABLEMESSENGER, win_messenger_enable), /* TIF(NUTAG_AUTORESPOND, autorespond), */ TIF(NUTAG_CALLEE_CAPS, callee_caps), TIF(NUTAG_MEDIA_FEATURES, media_features), TIF(NUTAG_SERVICE_ROUTE_ENABLE, service_route_enable), TIF(NUTAG_PATH_ENABLE, path_enable), TIF(NUTAG_AUTH_CACHE, auth_cache), TIF(NUTAG_REFER_EXPIRES, refer_expires), TIF(NUTAG_REFER_WITH_ID, refer_with_id), TIF(NUTAG_AUTO302, auto302), TIF(NUTAG_AUTO305, auto305), TIF(NUTAG_AUTO100, auto100), TIF(NUTAG_MAX_RETRY_AFTER, max_retry_after), TIF(NUTAG_SUBSTATE, substate), TIF(NUTAG_SUB_EXPIRES, sub_expires), TIF(SIPTAG_SUPPORTED, supported), TIF_STR(SIPTAG_SUPPORTED_STR, supported), TIF(SIPTAG_ALLOW, allow), TIF_STR(SIPTAG_ALLOW_STR, allow), TIF_STR(NUTAG_APPL_METHOD, appl_method), TIF(SIPTAG_ALLOW_EVENTS, allow_events), TIF_STR(SIPTAG_ALLOW_EVENTS_STR, allow_events), TIF_STR(NUTAG_APPL_EVENT, appl_event), TIF_SIP(SIPTAG_USER_AGENT, user_agent), TIF(SIPTAG_USER_AGENT_STR, user_agent), TIF(NUTAG_USER_AGENT, user_agent), TIF_SIP(SIPTAG_ORGANIZATION, organization), TIF(SIPTAG_ORGANIZATION_STR, organization), TIF(NUTAG_INITIAL_ROUTE, initial_route), TIF_STR(NUTAG_INITIAL_ROUTE_STR, initial_route), TIF(NUTAG_REGISTRAR, registrar), TIF(NUTAG_KEEPALIVE, keepalive), TIF(NUTAG_KEEPALIVE_STREAM, keepalive_stream), TIF(NUTAG_INSTANCE, instance), TIF(NUTAG_M_DISPLAY, m_display), TIF(NUTAG_M_USERNAME, m_username), TIF(NUTAG_M_PARAMS, m_params), TIF(NUTAG_M_FEATURES, m_features), TIF(NUTAG_OUTBOUND, outbound), /* Handle-specific proxy */ TAG_IF(nh != dnh && nhp->nhp_set.nhb_proxy, NUTAG_PROXY(nhp->nhp_proxy)), /* Skip user-agent-level parameters if parameters are for handle only */ TAG_IF(nh != dnh, TAG_NEXT(media_params)), /* Include tag in the list returned to user * if it has been earlier set (by user) */ #define GIF(TAG, pref) \ TAG_IF(ngp->ngp_set.ngp_##pref, TAG(ngp->ngp_##pref)) GIF(NUTAG_DETECT_NETWORK_UPDATES, detect_network_updates), GIF(NUTAG_SHUTDOWN_EVENTS, shutdown_events), NTATAG_CONTACT(m), #if HAVE_SOFIA_SMIME NUTAG_SMIME_ENABLE(nua->sm->sm_enable), NUTAG_SMIME_OPT(nua->sm->sm_opt), NUTAG_SMIME_PROTECTION_MODE(nua->sm->sm_protection_mode), NUTAG_SMIME_MESSAGE_DIGEST(nua->sm->sm_message_digest), NUTAG_SMIME_SIGNATURE(nua->sm->sm_signature), NUTAG_SMIME_KEY_ENCRYPTION(nua->sm->sm_key_encryption), NUTAG_SMIME_MESSAGE_ENCRYPTION(nua->sm->sm_message_encryption), #endif NTATAG_UDP_MTU(udp_mtu), NTATAG_MAX_PROCEEDING(max_proceeding), NTATAG_SIP_T1(sip_t1), NTATAG_SIP_T2(sip_t2), NTATAG_SIP_T4(sip_t4), NTATAG_SIP_T1X64(sip_t1x64), NTATAG_DEBUG_DROP_PROB(debug_drop_prob), /* Stack-wide proxy */ NTATAG_DEFAULT_PROXY(proxy), NTATAG_ALIASES(aliases), NTATAG_SIPFLAGS(flags), TAG_NEXT(media_params)); nua_stack_event(nua, nh, NULL, nua_r_get_params, SIP_200_OK, lst); su_home_deinit(tmphome); tl_vfree(media_params); return 0; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/nua_params.h000066400000000000000000000226761223300710500226510ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2006 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef NUA_PARAMS_H /** Defined when has been included. */ #define NUA_PARAMS_H /**@internal @file nua_params.h * @brief Parameters and their handling * * @author Pekka Pessi * @author Kai Vehmanen * * @date Created: Wed Mar 8 11:38:18 EET 2006 ppessi */ #include #ifndef NUA_TAG_H #include #endif /**@internal @brief NUA preferences. * * This structure contains values for various preferences and a separate * bitmap (nhp_set) for each preference. Preferences are set using * nua_set_params() or nua_set_hparams() or a handle-specific operation * setting the preferences, including nua_invite(), nua_respond(), * nua_ack(), nua_prack(), nua_update(), nua_info(), nua_bye(), * nua_options(), nua_message(), nua_register(), nua_publish(), nua_refer(), * nua_subscribe(), nua_notify(), nua_refer(), and nua_notifier(). * * The stack uses preference value if corresponding bit in bitmap is set, * otherwise it uses preference value from default handle. * * @see NHP_GET(), NH_PGET(), NHP_ISSET(), NH_PISSET() */ struct nua_handle_preferences { unsigned nhp_retry_count; /**< times to retry a request */ unsigned nhp_max_subscriptions; /* Session-related preferences */ char const *nhp_soa_name; unsigned nhp_media_enable:1; unsigned nhp_accept_multipart:1; unsigned nhp_invite_enable:1; unsigned nhp_auto_alert:1; unsigned nhp_early_answer:1; /**< Include answer in 1XX */ unsigned nhp_early_media:1; /**< Establish early media with 100rel */ unsigned nhp_only183_100rel:1;/**< Only 100rel 183. */ unsigned nhp_auto_answer:1; unsigned nhp_auto_ack:1; /**< Automatically ACK a final response */ unsigned :0; /** INVITE timeout. * * If no response is received in nhp_invite_timeout seconds, * INVITE client transaction times out */ unsigned nhp_invite_timeout; /** Default session timer (in seconds, 0 disables) */ unsigned nhp_session_timer; /** Default Min-SE Delta value */ unsigned nhp_min_se; /** no (preference), local or remote */ enum nua_session_refresher nhp_refresher; unsigned nhp_update_refresh:1; /**< Use UPDATE to refresh */ /**< Accept refreshes without SDP */ unsigned nhp_refresh_without_sdp:1; /* Messaging preferences */ unsigned nhp_message_enable : 1; /** Be bug-compatible with Windows Messenger */ unsigned nhp_win_messenger_enable : 1; /** PIM-IW hack */ unsigned nhp_message_auto_respond : 1; /* Preferences for registration (and dialog establishment) */ unsigned nhp_callee_caps:1; /**< Add callee caps to contact */ unsigned nhp_media_features:1;/**< Add media features to caps*/ /** Enable Service-Route */ unsigned nhp_service_route_enable:1; /** Enable Path */ unsigned nhp_path_enable:1; /** Authentication cache policy */ unsigned nhp_auth_cache:1; /** Always include id with Event: refer */ unsigned nhp_refer_with_id:1; /** Redirect automatically when receiving 302 responses */ unsigned nhp_auto302:1; /** Redirect automatically when receiving 305 responses */ unsigned nhp_auto305:1; /** Automatically generate 100 Trying responses. */ unsigned nhp_auto100:1; unsigned:0; unsigned nhp_max_retry_after; /* Default lifetime for implicit subscriptions created by REFER */ unsigned nhp_refer_expires; /* Subscriber state, i.e. nua_substate_pending */ unsigned nhp_substate; unsigned nhp_sub_expires; /* REGISTER keepalive intervals */ unsigned nhp_keepalive, nhp_keepalive_stream; char const *nhp_registrar; sip_allow_t *nhp_allow; sip_supported_t *nhp_supported; sip_allow_events_t *nhp_allow_events; sip_allow_events_t *nhp_appl_event; char const *nhp_user_agent; char const *nhp_organization; char const *nhp_m_display; char const *nhp_m_username; char const *nhp_m_params; char const *nhp_m_features; char const *nhp_instance; /** Outbound OPTIONS */ char const *nhp_outbound; sip_allow_t *nhp_appl_method; /** Initial route set */ sip_route_t *nhp_initial_route; /** Next hop URI (used instead of route). */ url_string_t *nhp_proxy; union { struct { /* A bit for each feature set by application */ /* NOTE: Some compilers behave weird if there are bitfields together with width > 32 So there should be a padding field (unsigned:0;) every 32 bits. */ unsigned nhb_retry_count:1; unsigned nhb_max_subscriptions:1; unsigned nhb_soa_name:1; unsigned nhb_media_enable:1; unsigned nhb_accept_multipart:1; unsigned nhb_invite_enable:1; unsigned nhb_auto_alert:1; unsigned nhb_early_answer:1; unsigned nhb_early_media:1; unsigned nhb_only183_100rel:1; unsigned nhb_auto_answer:1; unsigned nhb_auto_ack:1; unsigned nhb_invite_timeout:1; unsigned nhb_session_timer:1; unsigned nhb_min_se:1; unsigned nhb_refresher:1; unsigned nhb_update_refresh:1; unsigned nhb_refresh_without_sdp:1; unsigned nhb_message_enable:1; unsigned nhb_win_messenger_enable:1; unsigned nhb_message_auto_respond:1; unsigned nhb_callee_caps:1; unsigned nhb_media_features:1; unsigned nhb_service_route_enable:1; unsigned nhb_path_enable:1; unsigned nhb_auth_cache:1; unsigned nhb_refer_with_id:1; unsigned nhb_auto302:1; unsigned nhb_auto305:1; unsigned nhb_auto100:1; unsigned nhb_max_retry_after:1; unsigned nhb_refer_expires:1; unsigned :0; /* at most 32 bits before this point */ unsigned nhb_substate:1; unsigned nhb_sub_expires:1; unsigned nhb_keepalive:1; unsigned nhb_keepalive_stream:1; unsigned nhb_registrar:1; unsigned nhb_allow:1; unsigned nhb_supported:1; unsigned nhb_allow_events:1; unsigned nhb_appl_event:1; unsigned nhb_user_agent:1; unsigned nhb_organization:1; unsigned nhb_m_display:1; unsigned nhb_m_username:1; unsigned nhb_m_params:1; unsigned nhb_m_features:1; unsigned nhb_instance:1; unsigned nhb_outbound:1; unsigned nhb_appl_method:1; unsigned nhb_initial_route:1; unsigned nhb_proxy:1; unsigned :0; } set_bits; unsigned set_unsigned[2]; } nhp_set_; }; #define nhp_set nhp_set_.set_bits /** @internal Global preferences for nua. */ struct nua_global_preferences { /** Network detection: NONE, INFORMAL, TRY_FULL */ signed int ngp_detect_network_updates:3; /** Pass events during shutdown, too */ int ngp_shutdown_events:1; /** Use deferrable timers */ int ngp_deferrable_timers:1; unsigned :0; /* pad */ union { struct { /* A bit for each feature set by application */ unsigned ngp_detect_network_updates:1; unsigned ngp_shutdown_events:1; unsigned ngp_deferrable_timers:1; unsigned :0; } set_bits; unsigned set_unsigned[2]; } ngp_set_; }; #define ngp_set ngp_set_.set_bits #define DNHP_GET(dnhp, pref) ((dnhp)->nhp_##pref) #define NHP_GET(nhp, dnhp, pref) \ ((nhp)->nhp_set.nhb_##pref \ ? (nhp)->nhp_##pref : (dnhp)->nhp_##pref) #define NHP_SET(nhp, pref, value) \ ((nhp)->nhp_##pref = (value), \ (nhp)->nhp_set.nhb_##pref = 1) /* Check if preference is set */ #define NHP_ISSET(nhp, pref) \ ((nhp)->nhp_set.nhb_##pref) #define NHP_UNSET_ALL(nhp) (memset(&(nhp)->nhp_set, 0, sizeof (nhp)->nhp_set)) #define NHP_SET_ALL(nhp) (memset(&(nhp)->nhp_set, 255, sizeof (nhp)->nhp_set)) /* Get preference from handle, if set, otherwise from default handle */ #define NH_PGET(nh, pref) \ NHP_GET((nh)->nh_prefs, (nh)->nh_dprefs, pref) /* Get preference from handle, if exists and set, otherwise from default handle */ #define NUA_PGET(nua, nh, pref) \ NHP_GET((nh) ? (nh)->nh_prefs : (nua)->nua_dhandle->nh_prefs, \ (nua)->nua_dhandle->nh_prefs, \ pref) /* Get preference from default handle */ #define DNH_PGET(dnh, pref) \ DNHP_GET((dnh)->nh_prefs, pref) /* Check if preference is set in the handle */ #define NH_PISSET(nh, pref) \ (NHP_ISSET((nh)->nh_prefs, pref) && \ (nh)->nh_nua->nua_dhandle->nh_prefs != (nh)->nh_prefs) /* Check if preference has been set by application */ #define NUA_PISSET(nua, nh, pref) \ (NHP_ISSET((nua)->nua_dhandle->nh_prefs, pref) || \ ((nh) && NHP_ISSET((nh)->nh_prefs, pref))) #endif /* NUA_PARAMS_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/nua_publish.c000066400000000000000000000370331223300710500230200ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2006 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE nua_publish.c * @brief PUBLISH and publications * * @sa @RFC3903 * * @author Pekka Pessi * * @date Created: Wed Mar 8 17:01:32 EET 2006 ppessi */ #include "config.h" #include #include #include #include #include #include #include #include #include "nua_stack.h" /* ====================================================================== */ /* Publish usage */ struct publish_usage { sip_etag_t *pu_etag; int pu_published; }; static char const *nua_publish_usage_name(nua_dialog_usage_t const *du); static int nua_publish_usage_add(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du); static void nua_publish_usage_remove(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du, nua_client_request_t *cr, nua_server_request_t *sr); static void nua_publish_usage_refresh(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du, sip_time_t now); static int nua_publish_usage_shutdown(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du); static nua_usage_class const nua_publish_usage[1] = { { sizeof (struct publish_usage), sizeof nua_publish_usage, nua_publish_usage_add, nua_publish_usage_remove, nua_publish_usage_name, nua_base_usage_update_params, NULL, nua_publish_usage_refresh, nua_publish_usage_shutdown, }}; static char const *nua_publish_usage_name(nua_dialog_usage_t const *du) { return "publish"; } static int nua_publish_usage_add(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du) { if (ds->ds_has_publish) return -1; /* There can be only one */ ds->ds_has_publish = 1; return 0; } static void nua_publish_usage_remove(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du, nua_client_request_t *cr, nua_server_request_t *sr ) { struct publish_usage *pu = NUA_DIALOG_USAGE_PRIVATE(du); su_free(nh->nh_home, pu->pu_etag); ds->ds_has_publish = 0; /* There can be only one */ } /* ======================================================================== */ /* PUBLISH */ /**@fn \ * void nua_publish(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * * Send PUBLISH request to publication server. * * Request status will be delivered to the application using #nua_r_publish * event. When successful the publication will be updated periodically until * nua_unpublish() is called or handle is destroyed. Note that the periodic * updates and unpublish do not include the original message body nor the @b * Content-Type header. Instead, the periodic update will include the * @SIPIfMatch header, which was generated from the latest @SIPETag * header received in response to @b PUBLISH request. * * The handle used for publication cannot be used for any other purposes. * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Related Tags: * NUTAG_URL() \n * Tags of nua_set_hparams() \n * Header tags defined in * * @par Events: * #nua_r_publish * * @sa #nua_r_publish, @RFC3903, @SIPIfMatch, * nua_unpublish(), #nua_r_unpublish, #nua_i_publish */ /** @NUA_EVENT nua_r_publish * * Response to an outgoing PUBLISH. * * The PUBLISH request may be sent explicitly by nua_publish() or implicitly * by NUA state machine. * * @param status status code of PUBLISH request * (if the request is retried, @a status is 100, the @a * sip->sip_status->st_status contain the real status code * from the response message, e.g., 302, 401, or 407) * @param phrase a short textual description of @a status code * @param nh operation handle associated with the publication * @param hmagic application context associated with the handle * @param sip response to PUBLISH request or NULL upon an error * (status code is in @a status and * descriptive message in @a phrase parameters) * @param tags empty * * @sa nua_publish(), @RFC3903, @SIPETag, @Expires, * nua_unpublish(), #nua_r_unpublish, #nua_i_publish * * @END_NUA_EVENT */ /**@fn \ void nua_unpublish(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * * Send un-PUBLISH request to publication server. Un-PUBLISH request is just * a PUBLISH request with @Expires set to 0. It is possible to un-publish a * publication not associated with the handle by providing correct ETag in * SIPTAG_IF_MATCH() or SIPTAG_IF_MATCH_STR() tags. * * Response to the un-PUBLISH request will be delivered to the application * using #nua_r_unpublish event. * * The handle used for publication cannot be used for any other purposes. * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Related Tags: * NUTAG_URL() \n * SIPTAG_IF_MATCH(), SIPTAG_IF_MATCH_STR() \n * SIPTAG_EVENT(), SIPTAG_EVENT_STR() \n * Tags of nua_set_hparams() \n * Other header tags defined in except SIPTAG_EXPIRES() or SIPTAG_EXPIRES_STR() * * @par Events: * #nua_r_unpublish * * @sa #nua_r_unpublish, @RFC3903, @SIPIfMatch, * #nua_i_publish, nua_publish(), #nua_r_publish */ /** @NUA_EVENT nua_r_unpublish * * Response to an outgoing un-PUBLISH. * * @param status response status code * (if the request is retried, @a status is 100, the @a * sip->sip_status->st_status contain the real status code * from the response message, e.g., 302, 401, or 407) * @param phrase a short textual description of @a status code * @param nh operation handle associated with the publication * @param hmagic application context associated with the handle * @param sip response to PUBLISH request or NULL upon an error * (status code is in @a status and * descriptive message in @a phrase parameters) * @param tags empty * * @sa nua_unpublish(), @RFC3903, @SIPETag, @Expires, * nua_publish(), #nua_r_publish, #nua_i_publish * * @END_NUA_EVENT */ static int nua_publish_client_template(nua_client_request_t *cr, msg_t **return_msg, tagi_t const *tags); static int nua_publish_client_init(nua_client_request_t *cr, msg_t *, sip_t *, tagi_t const *tags); static int nua_publish_client_request(nua_client_request_t *cr, msg_t *, sip_t *, tagi_t const *tags); static int nua_publish_client_check_restart(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip); static int nua_publish_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip); static nua_client_methods_t const nua_publish_client_methods = { SIP_METHOD_PUBLISH, /* crm_method, crm_method_name */ 0, /* crm_extra */ { /* crm_flags */ /* create_dialog */ 0, /* in_dialog */ 0, /* target refresh */ 0 }, nua_publish_client_template, /* crm_template */ nua_publish_client_init, /* crm_init */ nua_publish_client_request, /* crm_send */ nua_publish_client_check_restart, /* crm_check_restart */ nua_publish_client_response, /* crm_recv */ NULL, /* crm_preliminary */ NULL, /* crm_report */ NULL, /* crm_complete */ }; /**@internal Send PUBLISH. */ int nua_stack_publish(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { return nua_client_create(nh, e, &nua_publish_client_methods, tags); } static int nua_publish_client_template(nua_client_request_t *cr, msg_t **return_msg, tagi_t const *tags) { nua_dialog_usage_t *du; if (cr->cr_event == nua_r_publish) return 0; du = nua_dialog_usage_get(cr->cr_owner->nh_ds, nua_publish_usage, NULL); if (du && du->du_cr) { if (nua_client_set_target(cr, du->du_cr->cr_target) < 0) return -1; *return_msg = msg_copy(du->du_cr->cr_msg); return 1; } return 0; } static int nua_publish_client_init(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du; struct publish_usage *pu; if (cr->cr_event == nua_r_publish) { du = nua_dialog_usage_add(nh, nh->nh_ds, nua_publish_usage, NULL); if (!du) return -1; pu = nua_dialog_usage_private(du); pu->pu_published = 0; if (sip->sip_if_match) { pu->pu_etag = sip_etag_dup(nh->nh_home, sip->sip_if_match); if (!pu->pu_etag) return -1; sip_header_remove(msg, sip, (sip_header_t *)sip->sip_if_match); } } else du = nua_dialog_usage_get(nh->nh_ds, nua_publish_usage, NULL); cr->cr_usage = du; return 0; } static int nua_publish_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags) { nua_dialog_usage_t *du = cr->cr_usage; int un, done; sip_etag_t const *etag = NULL; un = cr->cr_terminating || cr->cr_event != nua_r_publish || (du && du->du_shutdown) || (sip->sip_expires && sip->sip_expires->ex_delta == 0); nua_client_set_terminating(cr, un); done = un; if (du) { struct publish_usage *pu = nua_dialog_usage_private(du); if (nua_client_bind(cr, du) < 0) return -1; if (pu->pu_published) done = 1; etag = pu->pu_etag; } return nua_base_client_trequest(cr, msg, sip, SIPTAG_IF_MATCH(etag), TAG_IF(done, SIPTAG_PAYLOAD(NONE)), TAG_IF(done, SIPTAG_CONTENT_TYPE(NONE)), TAG_IF(un, SIPTAG_EXPIRES_STR("0")), TAG_NEXT(tags)); } static int nua_publish_client_check_restart(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip) { char const *restarting = NULL; if (cr->cr_terminating || !cr->cr_usage) ; else if (status == 412) restarting = phrase; else if (200 <= status && status < 300 && sip->sip_expires && sip->sip_expires->ex_delta == 0) restarting = "Immediate re-PUBLISH"; if (restarting) { struct publish_usage *pu = nua_dialog_usage_private(cr->cr_usage); if (pu) { pu->pu_published = 0; su_free(cr->cr_owner->nh_home, pu->pu_etag), pu->pu_etag = NULL; if (nua_client_restart(cr, 100, restarting)) return 0; } } return nua_base_client_check_restart(cr, status, phrase, sip); } static int nua_publish_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = cr->cr_usage; if (!cr->cr_terminated && du && sip) { struct publish_usage *pu = nua_dialog_usage_private(du); sip_expires_t const *ex = sip->sip_expires; /* Reset state */ pu->pu_published = 0; if (pu->pu_etag) su_free(nh->nh_home, pu->pu_etag), pu->pu_etag = NULL; if (status < 300) { pu->pu_published = 1; pu->pu_etag = sip_etag_dup(nh->nh_home, sip->sip_etag); if (!ex || ex->ex_delta == 0 || !pu->pu_etag) { cr->cr_terminated = 1; if (!ex || ex->ex_delta == 0) SET_STATUS(900, "Received Invalid Expiration Time"); else SET_STATUS1(NUA_ERROR_AT(__FILE__, __LINE__)); } else nua_dialog_usage_set_refresh(du, ex->ex_delta); } } return nua_base_client_response(cr, status, phrase, sip, NULL); } static void nua_publish_usage_refresh(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du, sip_time_t now) { nua_client_request_t *cr = du->du_cr; if (cr) { if (nua_client_resend_request(cr, 0) >= 0) return; } nua_stack_event(nh->nh_nua, nh, NULL, nua_r_publish, NUA_ERROR_AT(__FILE__, __LINE__), NULL); nua_dialog_usage_remove(nh, ds, du, NULL, NULL); } /** @interal Shut down PUBLISH usage. * * @retval >0 shutdown done * @retval 0 shutdown in progress * @retval <0 try again later */ static int nua_publish_usage_shutdown(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du) { nua_client_request_t *cr = du->du_cr; if (cr) { if (nua_client_resend_request(cr, 1) >= 0) return 0; } /* XXX - report to user */ nua_dialog_usage_remove(nh, ds, du, NULL, NULL); return 200; } /* ---------------------------------------------------------------------- */ /* Server side */ /** @NUA_EVENT nua_i_publish * * Incoming PUBLISH request. * * In order to receive #nua_i_publish events, the application must enable * both the PUBLISH method with NUTAG_ALLOW() tag and the acceptable SIP * events with nua_set_params() tag NUTAG_ALLOW_EVENTS(). * * The nua_response() call responding to a PUBLISH request must have * NUTAG_WITH() (or NUTAG_WITH_THIS()/NUTAG_WITH_SAVED()) tag. Note that * a successful response to PUBLISH @b MUST include @Expires and @SIPETag * headers. * * The PUBLISH request does not create a dialog. Currently the processing * of incoming PUBLISH creates a new handle for each incoming request which * is not assiciated with an existing dialog. If the handle @a nh is not * bound, you should probably destroy it after responding to the PUBLISH * request. * * @param status status code of response sent automatically by stack * @param phrase a short textual description of @a status code * @param nh operation handle associated with the incoming request * @param hmagic application context associated with the call * (usually NULL) * @param sip incoming PUBLISH request * @param tags empty * * @sa @RFC3903, nua_respond(), * @Expires, @SIPETag, @SIPIfMatch, @Event, * nua_subscribe(), #nua_i_subscribe, * nua_notifier(), #nua_i_subscription, * * @since First used in @VERSION_1_12_4 * * @END_NUA_EVENT */ int nua_publish_server_init(nua_server_request_t *sr); nua_server_methods_t const nua_publish_server_methods = { SIP_METHOD_PUBLISH, nua_i_publish, /* Event */ { 0, /* Do not create dialog */ 0, /* Initial request */ 0, /* Not a target refresh request */ 1, /* Add Contact */ }, nua_publish_server_init, nua_base_server_preprocess, nua_base_server_params, nua_base_server_respond, nua_base_server_report, }; int nua_publish_server_init(nua_server_request_t *sr) { sip_allow_events_t *allow_events = NH_PGET(sr->sr_owner, allow_events); sip_event_t *o = sr->sr_request.sip->sip_event; char const *event = o ? o->o_type : NULL; if (!allow_events) return SR_STATUS1(sr, SIP_501_NOT_IMPLEMENTED); else if (!event || !msg_header_find_param(allow_events->k_common, event)) return SR_STATUS1(sr, SIP_489_BAD_EVENT); return 0; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/nua_register.c000066400000000000000000001702241223300710500231760ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2006 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE nua_register.c * @brief REGISTER and registrations * * @author Pekka Pessi * @author Martti Mela * @author Kai Vehmanen * * @date Created: Wed Mar 8 11:48:49 EET 2006 ppessi */ #include "config.h" /** @internal SU network changed detector argument pointer type */ #define SU_NETWORK_CHANGED_MAGIC_T struct nua_s #define TP_CLIENT_T struct register_usage #include #include #include #include #include #include #include #define NTA_UPDATE_MAGIC_T struct nua_s #include "nua_stack.h" #include #include #include #include #define OUTBOUND_OWNER_T struct nua_handle_s #include "outbound.h" #if HAVE_SIGCOMP #include #endif #include #include #include #include #include /* ======================================================================== */ /* Registrations and contacts */ int nua_registration_from_via(nua_registration_t **list, nua_handle_t *nh, sip_via_t const *via, int public); int nua_registration_add(nua_registration_t **list, nua_registration_t *nr); void nua_registration_remove(nua_registration_t *nr); int nua_registration_set_aor(su_home_t *, nua_registration_t *nr, sip_from_t const *aor); int nua_registration_set_contact(nua_handle_t *, nua_registration_t *nr, sip_contact_t const *m, int terminating); void nua_registration_set_ready(nua_registration_t *nr, int ready); /* ====================================================================== */ /* REGISTER usage */ static char const *nua_register_usage_name(nua_dialog_usage_t const *du); static int nua_register_usage_add(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du); static void nua_register_usage_remove(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du, nua_client_request_t *cr, nua_server_request_t *sr); static void nua_register_usage_update_params(nua_dialog_usage_t const *du, nua_handle_preferences_t const *, nua_handle_preferences_t const *, nua_handle_preferences_t const *); static void nua_register_usage_peer_info(nua_dialog_usage_t *du, nua_dialog_state_t const *ds, sip_t const *sip); static void nua_register_usage_refresh(nua_handle_t *, nua_dialog_state_t *, nua_dialog_usage_t *, sip_time_t); static int nua_register_usage_shutdown(nua_handle_t *, nua_dialog_state_t *, nua_dialog_usage_t *); /** @internal @brief REGISTER usage, aka nua_registration_t. */ struct register_usage { nua_registration_t *nr_next, **nr_prev, **nr_list; /* Doubly linked list and its head */ sip_from_t *nr_aor; /**< AoR for this registration, NULL if none */ sip_contact_t *nr_contact; /**< Our Contact */ sip_contact_t nr_dcontact[1]; /**< Contact in dialog */ sip_via_t *nr_via; /**< Corresponding Via headers */ unsigned long nr_min_expires; /**< Value from 423 negotiation */ /** Status of registration */ unsigned nr_ready:1; /** Kind of registration. * * If nr_default is true, this is not a real registration but placeholder * for Contact header derived from a transport address. * * If nr_secure is true, this registration supports SIPS/TLS. * * If nr_public is true, transport should have public address. */ unsigned nr_default:1, nr_secure:1, nr_public:1, nr_ip4:1, nr_ip6:1; /** Stack-generated contact */ unsigned nr_by_stack:1; unsigned:0; int nr_error_report_id; /**< ID used to ask for error reports from tport */ sip_route_t *nr_route; /**< Outgoing Service-Route */ sip_path_t *nr_path; /**< Incoming Path */ tport_t *nr_tport; /**< Transport to be used when registered */ nua_dialog_state_t *nr_dialogs; /**< List of our dialogs */ #if HAVE_SIGCOMP struct sigcomp_compartment *nr_compartment; #endif outbound_t *nr_ob; /**< Outbound connection */ }; nua_usage_class const nua_register_usage[1] = { { sizeof (struct register_usage), (sizeof nua_register_usage), nua_register_usage_add, nua_register_usage_remove, nua_register_usage_name, nua_register_usage_update_params, nua_register_usage_peer_info, nua_register_usage_refresh, nua_register_usage_shutdown }}; static char const *nua_register_usage_name(nua_dialog_usage_t const *du) { return "register"; } static int nua_register_usage_add(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du) { nua_registration_t *nr = NUA_DIALOG_USAGE_PRIVATE(du); if (ds->ds_has_register) return -1; /* There can be only one usage */ ds->ds_has_register = 1; nr->nr_public = 1; /* */ return 0; } static void nua_register_usage_remove(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du, nua_client_request_t *cr, nua_server_request_t *sr) { nua_registration_t *nr = NUA_DIALOG_USAGE_PRIVATE(du); if (nr->nr_list) nua_registration_remove(nr); /* Remove from list of registrations */ if (nr->nr_ob) outbound_unref(nr->nr_ob); #if HAVE_SIGCOMP if (nr->nr_compartment) sigcomp_compartment_unref(nr->nr_compartment); nr->nr_compartment = NULL; #endif if (nr->nr_error_report_id) tport_release(nr->nr_tport, nr->nr_error_report_id, NULL, NULL, nr, 0); if (nr->nr_tport) tport_unref(nr->nr_tport), nr->nr_tport = NULL; ds->ds_has_register = 0; /* There can be only one */ } /** @internal Store information about registrar. */ static void nua_register_usage_peer_info(nua_dialog_usage_t *du, nua_dialog_state_t const *ds, sip_t const *sip) { nua_registration_t *nr = NUA_DIALOG_USAGE_PRIVATE(du); if (nr->nr_ob) outbound_peer_info(nr->nr_ob, sip); } /* ======================================================================== */ /* REGISTER */ static void nua_register_connection_closed(tp_stack_t *sip_stack, nua_registration_t *nr, tport_t *tport, msg_t *msg, int error); /* Interface towards outbound_t */ sip_contact_t *nua_handle_contact_by_via(nua_handle_t *nh, su_home_t *home, int in_dialog, sip_via_t const *v, char const *transport, char const *m_param, ...); static int nua_stack_outbound_refresh(nua_handle_t *, outbound_t *ob); static int nua_stack_outbound_status(nua_handle_t *, outbound_t *ob, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...); static int nua_stack_outbound_failed(nua_handle_t *, outbound_t *ob, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...); static int nua_stack_outbound_credentials(nua_handle_t *, auth_client_t **auc); outbound_owner_vtable nua_stack_outbound_callbacks = { sizeof nua_stack_outbound_callbacks, /* oo_contact */ nua_handle_contact_by_via, /* oo_refresh */ nua_stack_outbound_refresh, /* oo_status */ nua_stack_outbound_status, /* oo_probe_error */ nua_stack_outbound_failed, /* oo_keepalive_error */ nua_stack_outbound_failed, /* oo_credentials */ nua_stack_outbound_credentials }; /**@fn void nua_register(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * * Send SIP REGISTER request to the registrar. * * Request status will be delivered to the application using #nua_r_register * event. When successful the registration will be updated periodically. * * The handle used for registration cannot be used for any other purposes. * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Related tags: * NUTAG_REGISTRAR(), NUTAG_INSTANCE(), NUTAG_OUTBOUND(), * NUTAG_KEEPALIVE(), NUTAG_KEEPALIVE_STREAM(), NUTAG_M_USERNAME(), * NUTAG_M_DISPLAY(), NUTAG_M_PARAMS(), NUTAG_M_FEATURES() * * @par Events: * #nua_r_register, #nua_i_outbound * * @par Generating Contact Header * * If the application did not specify the Contact header in the tags, * nua_register() will generate one. It will obtain the schema, IP address * for the host and port number for the Contact URI from the transport * socket. The diplay name is taken from NUTAG_M_DISPLAY(), URL username * part is taken from NUTAG_M_USERNAME(), URI parameters from * NUTAG_M_PARAMS(), and Contact header parameters from NUTAG_M_FEATURES(). * If NUTAG_CALLEE_CAPS(1) is specified, additional Contact header * parameters are generated based on SDP capabilities and SIP @Allow header. * * Note that @b nua may append a identifier of its own to the @Contact URI * username. Such nua-generated identifier trailer always starts with "=" * (equal sign), rest of the nua-generated identifier may contain any * url-unreserved characters except "=". * * Likewise, nua may add transport parameters (such as "transport=tcp" or * "maddr") to the @Contact URI. It can add addtional header parameters, like * "+sip.instance" or "reg-id", too. * * For instance, if application uses tags like * @code * nua_register(nh, * NUTAG_M_DISPLAY("1"), * NUTAG_M_USERNAME("line-1"), * NUTAG_M_PARAMS("user=phone"), * NUTAG_M_FEATURES("audio"), * NUTAG_CALLEE_CAPS(0), * TAG_END()) * @endcode * @b nua can generate a Contact header like * @code * Contact: 1 * ;audio;reg-id=1 * ;+sip.instance=urn:uuid:97701ad9-39df-1229-1083-dbc0a85f029c * @endcode * * The incoming request from the proxy should contain the registered contact * URI as the request URI. The application can use the username prefix set * by NUTAG_M_USERNAME() and the non-transport parameters of the request URI * set by NUTAG_M_PARAMS() when determining to which registration the * incoming request belongs. * * For example, a request line correspoding to the @Contact in above example * may look like: * @code * INVITE sip:line-1=SSQAIbjv@192.168.1.200;user=phone SIP/2.0 * @endcode * * @sa NUTAG_M_DISPLAY(), NUTAG_M_USERNAME(), NUTAG_M_PARAMS(), * NUTAG_M_FEATURES(), NUTAG_CALLEE_CAPS(). * * @par NAT, Firewall and Outbound Support * * Normally, @b nua will start start a protocol engine for outbound * connections used for NAT and firewall traversal and connectivity checks * when registering. * * @note If the application provides @b nua with a * @Contact header of its own (or includes a SIPTAG_CONTACT(NULL) tag in * nua_register() tags), the outbound protocol engine is not started. It is * assumed that the application knows better what it is doing when it sets * the @Contact, or it is using experimental CPL upload as specified in * * draft-lennox-sip-reg-payload-01.txt. * * First, outbound engine will probe for NATs in between UA and registrar. * It will send a REGISTER request as usual. Upon receiving the response it * checks for the presence of "received" and "rport" parameters in the Via * header returned by registrar. The presence of NAT is determined from the * "received" parameter in a Via header. When a REGISTER request was sent, * the stack inserted the actual source IP address in the Via header: if * that is different from the source IP address seen by the registrar, the * registrar inserts the source IP address it sees into the "received" * parameter. * * Please note that an ALG (application-level gateway) modifying the Via * headers in outbound requests and again in incoming responses will make * the above-described NAT check to fail. * * The response to the initial REGISTER should also include option tags * indicating whether registrar supports various SIP extension options: @e * outbound, @e pref, @e path, @e gruu. * * Basically, @e outbound means that instead of registering its contact URI * with a particular address-of-record URI, the user-agent registers a * transport-level connection. Such a connection is identified on the * Contact header field with an instance identifier, application-provided * @ref NUTAG_INSTANCE() "unique string" identifying the user-agent instance * and a stack-generated numeric index identifying the transport-level * connection. * * If the @e outbound extension is supported, NUTAG_OUTBOUND() contains * option string "outbound" and the application has provided an instance * identifer to the stack with NUTAG_INSTANCE(), the nua_register() will try * to use outbound. * * If @e outbound is not supported, nua_register() has to generate a URI * that can be used to reach it from outside. It will check for public * transport addresses detected by underlying stack with, e.g., STUN, UPnP * or SOCKS. If there are public addresses, nua_register() will use them. If * there is no public address, it will try to generate a Contact URI from * the "received" and "rport" parameters found in the Via header of the * response message. * * @todo Actually generate public addresses. * * You can disable this kind of NAT traversal by setting "no-natify" into * NUTAG_OUTBOUND() options string. * * @par GRUU and Service-Route * * After a successful response to the REGISTER request has been received, * nua_register() will update the information about the registration based * on it. If there is a "gruu" parameter included in the response, * nua_register() will save it and use the gruu URI in the Contact header * fields of dialog-establishing messages, such as INVITE or SUBSCRIBE. * Also, if the registrar has included a Service-Route header in the * response, and the service route feature has not been disabled using * NUTAG_SERVICE_ROUTE_ENABLE(), the route URIs from the Service-Route * header will be used for initial non-REGISTER requests. * * The #nua_r_register message will include the contact header and route * used in with the registration. * * @par Registration Keep-Alive * * After the registration has successfully completed the nua_register() will * validate the registration and initiate the keepalive mechanism, too. The * user-agent validates the registration by sending a OPTIONS requests to * itself. If there is an error, nua_register() will indicate that to the * application using #nua_i_outbound event, and start unregistration * procedure (unless that has been explicitly disabled). * * You can disable validation by inserting "no-validate" into * NUTAG_OUTBOUND() string. * * The keepalive mechanism depends on the network features detected earlier. * If @a outbound extension is used, the STUN keepalives will be used. * Otherwise, NUA stack will repeatedly send OPTIONS requests to itself. In * order to save bandwidth, it will include Max-Forwards: 0 in the * keep-alive requests, however. The keepalive interval is determined by * NUTAG_KEEPALIVE() parameter. If the interval is 0, no keepalive messages * is sent. * * You can disable keepalive OPTIONS by inserting "no-options-keepalive" * into NUTAG_OUTBOUND() string. Currently there are no other keepalive * mechanisms available. * * The value of NUTAG_KEEPALIVE_STREAM(), if specified, is used to indicate * the desired transport-layer keepalive interval for stream-based * transports like TLS and TCP. * * As alternative to OPTIONS/STUN keepalives, the client can propose * a more frequent registration refresh interval with * NUTAG_M_FEATURES() (e.g. NUTAG_M_FEATURES("expires=120") given as * parameter to nua_register()). * * @sa #nua_r_register, nua_unregister(), #nua_r_unregister, * #nua_i_register, * @RFC3261 section 10, * @Expires, @Contact, @CallID, @CSeq, * @Path, @RFC3327, @ServiceRoute, @RFC3608, @RFC3680, * NUTAG_REGISTRAR(), NUTAG_INSTANCE(), NUTAG_OUTBOUND(), * NUTAG_KEEPALIVE(), NUTAG_KEEPALIVE_STREAM(), * SIPTAG_CONTACT(), SIPTAG_CONTACT_STR(), NUTAG_M_USERNAME(), * NUTAG_M_DISPLAY(), NUTAG_M_PARAMS(), NUTAG_M_FEATURES(), */ /** @NUA_EVENT nua_r_register * * Response to an outgoing REGISTER. * * The REGISTER may be sent explicitly by nua_register() or implicitly by * NUA state machines. * * When REGISTER request has been restarted the @a status may be 100 even * while the real response status returned is different. * * @param status response status code * (if the request is retried, @a status is 100, the @a * sip->sip_status->st_status contain the real status code * from the response message, e.g., 302, 401, or 407) * @param phrase a short textual description of @a status code * @param nh operation handle associated with the registration * @param hmagic application context associated with the registration * @param sip response message to REGISTER request or NULL upon an error * (status code is in @a status and * descriptive message in @a phrase parameters) * @param tags empty * * @sa nua_register(), nua_unregister(), #nua_r_unregister, * @Contact, @CallID, @CSeq, @RFC3261 section 10, * @Path, @RFC3327, @ServiceRoute, @RFC3608, @RFC3680 * * @END_NUA_EVENT */ /**@fn void nua_unregister(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * Unregister. * * Send a REGISTER request with expiration time 0. This removes the * registration from the registrar. If the handle was earlier used * with nua_register() the periodic updates will be terminated. * * If a SIPTAG_CONTACT_STR() with argument "*" is used, all the * registrations will be removed from the registrar otherwise only the * contact address belonging to the NUA stack is removed. * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Related tags: * NUTAG_REGISTRAR() \n * Header tags defined in except SIPTAG_EXPIRES() or SIPTAG_EXPIRES_STR() * * @par Events: * #nua_r_unregister * * @sa nua_register(), #nua_r_register, nua_handle_destroy(), nua_shutdown(), * #nua_i_register, * @Expires, @Contact, @CallID, @CSeq, @RFC3261 section 10, * @Path, @RFC3327, @ServiceRoute, @RFC3608, @RFC3680, * NUTAG_REGISTRAR(), NUTAG_INSTANCE(), NUTAG_OUTBOUND(), * NUTAG_KEEPALIVE(), NUTAG_KEEPALIVE_STREAM(), * SIPTAG_CONTACT(), SIPTAG_CONTACT_STR(), NUTAG_M_USERNAME(), * NUTAG_M_DISPLAY(), NUTAG_M_PARAMS(), NUTAG_M_FEATURES(), */ /** @NUA_EVENT nua_r_unregister * * Answer to outgoing un-REGISTER. * * @param status response status code * (if the request is retried, @a status is 100, the @a * sip->sip_status->st_status contain the real status code * from the response message, e.g., 302, 401, or 407) * @param phrase a short textual description of @a status code * @param nh operation handle associated with the registration * @param hmagic application context associated with the registration * @param sip response message to REGISTER request or NULL upon an error * (status code is in @a status and * descriptive message in @a phrase parameters) * @param tags empty * * @sa nua_unregister(), nua_register(), #nua_r_register, * @Contact, @CallID, @CSeq, @RFC3261 section 10, * @Path, @RFC3327, @ServiceRoute, @RFC3608, @RFC3680 * * @END_NUA_EVENT */ static int nua_register_client_template(nua_client_request_t *cr, msg_t **return_msg, tagi_t const *tags); static int nua_register_client_init(nua_client_request_t *cr, msg_t *, sip_t *, tagi_t const *tags); static int nua_register_client_request(nua_client_request_t *cr, msg_t *, sip_t *, tagi_t const *tags); static int nua_register_client_check_restart(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip); static int nua_register_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip); static nua_client_methods_t const nua_register_client_methods = { SIP_METHOD_REGISTER, /* crm_method, crm_method_name */ 0, /* crm_extra */ { /* crm_flags */ /* create_dialog */ 1, /* in_dialog */ 0, /* target refresh */ 0 }, nua_register_client_template, /* crm_template */ nua_register_client_init, /* crm_init */ nua_register_client_request, /* crm_send */ nua_register_client_check_restart, /* crm_check_restart */ nua_register_client_response, /* crm_recv */ NULL, /* crm_preliminary */ NULL, /* crm_report */ NULL, /* crm_complete */ }; /**@internal Send REGISTER. */ int nua_stack_register(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { return nua_client_create(nh, e, &nua_register_client_methods, tags); } static int nua_register_client_template(nua_client_request_t *cr, msg_t **return_msg, tagi_t const *tags) { nua_dialog_usage_t *du; if (cr->cr_event == nua_r_register) return 0; /* Use a copy of REGISTER message as the template for un-REGISTER */ du = nua_dialog_usage_get(cr->cr_owner->nh_ds, nua_register_usage, NULL); if (du && du->du_cr) { if (nua_client_set_target(cr, du->du_cr->cr_target) < 0) return -1; *return_msg = msg_copy(du->du_cr->cr_msg); return 1; } return 0; } static int nua_register_client_init(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du; nua_registration_t *nr; sip_to_t const *aor = sip->sip_to; int unreg; /* Explicit empty (NULL) contact - used for CPL store/remove? */ if (!sip->sip_contact && cr->cr_has_contact) /* Do not create any usage */ return 0; unreg = cr->cr_event != nua_r_register || (sip->sip_expires && sip->sip_expires->ex_delta == 0); if (unreg) nua_client_set_terminating(cr, 1); du = nua_dialog_usage_add(nh, nh->nh_ds, nua_register_usage, NULL); if (du == NULL) return -1; nr = nua_dialog_usage_private(du); if (nua_client_bind(cr, du) < 0) return -1; if (!nr->nr_list) { nua_registration_add(&nh->nh_nua->nua_registrations, nr); if (aor == NULL) aor = sip->sip_from; if (aor == NULL) aor = nh->nh_nua->nua_from; if (nua_registration_set_aor(nh->nh_home, nr, aor) < 0) return -1; } if (nua_registration_set_contact(nh, nr, sip->sip_contact, unreg) < 0) return -1; if (!nr->nr_ob && (NH_PGET(nh, outbound) || NH_PGET(nh, instance))) { nr->nr_ob = outbound_new(nh, &nua_stack_outbound_callbacks, nh->nh_nua->nua_root, nh->nh_nua->nua_nta, NH_PGET(nh, instance)); if (!nr->nr_ob) return nua_client_return(cr, 900, "Cannot create outbound", msg); nua_register_usage_update_params(du, NULL, nh->nh_prefs, nh->nh_dprefs); } if (nr->nr_ob) { outbound_t *ob = nr->nr_ob; sip_contact_t *m; if (!unreg && sip->sip_contact) { for (m = sip->sip_contact; m; m = m->m_next) if (!m->m_expires || strtoul(m->m_expires, NULL, 10) != 0) break; if (m == NULL) unreg = 1; /* All contacts have expires=0 */ } if (outbound_set_contact(ob, sip->sip_contact, nr->nr_via, unreg) < 0) return nua_client_return(cr, 900, "Cannot set outbound contact", msg); } return 0; } static int nua_register_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = cr->cr_usage; nua_registration_t *nr; sip_contact_t *m, *contacts = sip->sip_contact; char const *min_expires = NULL; int unreg; tport_t *tport = NULL; (void)nh; /* Explicit empty (NULL) contact - used for CPL store/remove? */ if (!contacts && cr->cr_has_contact) return nua_base_client_request(cr, msg, sip, tags); if ((du && du->du_shutdown) || (sip->sip_expires && sip->sip_expires->ex_delta == 0)) nua_client_set_terminating(cr, 1); if (contacts) { if (!cr->cr_terminating) { for (m = contacts; m; m = m->m_next) if (!m->m_expires || strtoul(m->m_expires, NULL, 10) != 0) break; /* All contacts have expires=0 */ if (m == NULL) nua_client_set_terminating(cr, 1); } } unreg = cr->cr_terminating; nr = nua_dialog_usage_private(du); if (nr) { if (nr->nr_ob) { outbound_stop_keepalive(nr->nr_ob); outbound_start_registering(nr->nr_ob); } if (nr->nr_by_stack) { sip_contact_t *m = nr->nr_contact, *previous = NULL; outbound_get_contacts(nr->nr_ob, &m, &previous); sip_add_dup(msg, sip, (sip_header_t *)m); /* previous is an outdated contact generated by stack * and it is now unregistered */ if (previous) sip_add_dup(msg, sip, (sip_header_t *)previous); } tport = nr->nr_tport; } for (m = sip->sip_contact; m; m = m->m_next) { if (m->m_url->url_type == url_any) { /* If there is a '*' in contact list, remove everything else */ while (m != sip->sip_contact) sip_header_remove(msg, sip, (sip_header_t *)sip->sip_contact); while (m->m_next) sip_header_remove(msg, sip, (sip_header_t *)m->m_next); contacts = m; break; } if (!m->m_expires) continue; if (unreg) { /* Remove the expire parameters from contacts */ msg_header_remove_param(m->m_common, "expires"); } else if (nr && nr->nr_min_expires) { unsigned long exp = strtoul(m->m_expires, 0, 10); if (exp != 0 && exp < nr->nr_min_expires) { if (min_expires == NULL) min_expires = su_sprintf(msg_home(msg), "expires=%lu", nr->nr_min_expires); msg_header_replace_param(msg_home(msg), m->m_common, min_expires); } } } return nua_base_client_trequest(cr, msg, sip, TAG_IF(unreg, SIPTAG_EXPIRES_STR("0")), #if 0 TAG_IF(unreg, NTATAG_SIGCOMP_CLOSE(1)), TAG_IF(!unreg, NTATAG_COMP("sigcomp")), #endif NTATAG_TPORT(tport), TAG_NEXT(tags)); } static int nua_register_client_check_restart(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip) { nua_registration_t *nr = nua_dialog_usage_private(cr->cr_usage); unsigned short retry_count = cr->cr_retry_count; int restart = 0, retry; if (nr && nr->nr_ob) { msg_t *_reqmsg = nta_outgoing_getrequest(cr->cr_orq); sip_t *req = sip_object(_reqmsg); msg_destroy(_reqmsg); retry = outbound_register_response(nr->nr_ob, cr->cr_terminating, req, sip); restart = retry >= ob_reregister_now; if (retry == ob_reregister) /* outbound restarts REGISTER later */; if (retry < 0) /* XXX - report an error? */; } if (nr && status == 423) { if (sip->sip_min_expires) nr->nr_min_expires = sip->sip_min_expires->me_delta; } /* Check for status-specific reasons to retry */ if (nua_base_client_check_restart(cr, status, phrase, sip)) return 1; /* Restart only if nua_base_client_check_restart() did not try to restart */ if (restart && retry_count == cr->cr_retry_count) return nua_client_restart(cr, 100, "Outbound NAT Detected"); return 0; } static int nua_register_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = cr->cr_usage; nua_registration_t *nr = nua_dialog_usage_private(du); int ready; ready = du && !cr->cr_terminated && status < 300; if (ready) { sip_time_t mindelta = 0; sip_time_t now = sip_now(), delta, reqdelta, mdelta; sip_contact_t const *m, *sent; msg_t *_reqmsg = nta_outgoing_getrequest(cr->cr_orq); sip_t *req = sip_object(_reqmsg); tport_t *tport; msg_destroy(_reqmsg); assert(nr); assert(sip); assert(req); #if HAVE_SIGCOMP { struct sigcomp_compartment *cc; cc = nta_outgoing_compartment(cr->cr_orq); sigcomp_compartment_unref(nr->nr_compartment); nr->nr_compartment = cc; } #endif /* XXX - if store/remove, remove Content-Disposition Content-Type body */ /** Search for lowest delta of SIP contacts we tried to register */ mindelta = SIP_TIME_MAX; reqdelta = req->sip_expires ? req->sip_expires->ex_delta : 0; for (m = sip->sip_contact; m; m = m->m_next) { if (m->m_url->url_type != url_sip && m->m_url->url_type != url_sips) continue; for (sent = req->sip_contact; sent; sent = sent->m_next) { if (url_cmp(m->m_url, sent->m_url)) continue; if (sent->m_expires) mdelta = strtoul(sent->m_expires, NULL, 10); else mdelta = reqdelta; if (mdelta == 0) mdelta = 3600; delta = sip_contact_expires(m, sip->sip_expires, sip->sip_date, mdelta, now); if (delta > 0 && delta < mindelta) mindelta = delta; if (url_cmp_all(m->m_url, sent->m_url) == 0) break; } } if (mindelta == SIP_TIME_MAX) mindelta = 3600; nua_dialog_usage_set_refresh(du, mindelta); /* RFC 3608 Section 6.1 Procedures at the UA The UA performs a registration as usual. The REGISTER response may contain a Service-Route header field. If so, the UA MAY store the value of the Service-Route header field in an association with the address-of-record for which the REGISTER transaction had registered a contact. If the UA supports multiple addresses-of-record, it may be able to store multiple service routes, one per address-of-record. If the UA refreshes the registration, the stored value of the Service- Route is updated according to the Service-Route header field of the latest 200 class response. If there is no Service-Route header field in the response, the UA clears any service route for that address- of-record previously stored by the UA. If the re-registration request is refused or if an existing registration expires and the UA chooses not to re-register, the UA SHOULD discard any stored service route for that address-of-record. */ su_free(nh->nh_home, nr->nr_route); nr->nr_route = sip_route_dup(nh->nh_home, sip->sip_service_route); { /* RFC 3327 */ /* Store last URI in Path header */ sip_path_t *path = sip->sip_path; while (path && path->r_next) path = path->r_next; if (!nr->nr_path || !path || url_cmp_all(nr->nr_path->r_url, path->r_url)) { su_free(nh->nh_home, nr->nr_path); nr->nr_path = sip_path_dup(nh->nh_home, path); } } if (sip->sip_to->a_url->url_type == url_sips) nr->nr_secure = 1; if (nr->nr_ob) { outbound_gruuize(nr->nr_ob, sip); outbound_start_keepalive(nr->nr_ob, cr->cr_orq); } tport = nta_outgoing_transport (cr->cr_orq); /* cache persistant connection for registration */ if (tport && tport != nr->nr_tport) { if (nr->nr_error_report_id) { if (tport_release(nr->nr_tport, nr->nr_error_report_id, NULL, NULL, nr, 0) < 0) SU_DEBUG_1(("nua_register: tport_release() failed\n")); nr->nr_error_report_id = 0; } tport_unref(nr->nr_tport); nr->nr_tport = tport; if (tport_is_secondary(tport)) { tport_set_params(tport, TPTAG_SDWN_ERROR(1), TAG_END()); nr->nr_error_report_id = tport_pend(tport, NULL, nua_register_connection_closed, nr); } } else tport_unref(tport); /* note: nta_outgoing_transport() makes a ref */ nua_registration_set_ready(nr, 1); } else if (du) { nua_dialog_usage_reset_refresh(du); su_free(nh->nh_home, nr->nr_route); nr->nr_route = NULL; outbound_stop_keepalive(nr->nr_ob); /* release the persistant transport for registration */ if (nr->nr_tport) { if (nr->nr_error_report_id) { if (tport_release(nr->nr_tport, nr->nr_error_report_id, NULL, NULL, nr, 0) < 0) SU_DEBUG_1(("nua_register: tport_release() failed\n")); nr->nr_error_report_id = 0; } tport_unref(nr->nr_tport), nr->nr_tport = NULL; } nua_registration_set_ready(nr, 0); } return nua_base_client_response(cr, status, phrase, sip, NULL); } static void nua_register_connection_closed(tp_stack_t *sip_stack, nua_registration_t *nr, tport_t *tport, msg_t *msg, int error) { nua_dialog_usage_t *du; tp_name_t const *tpn; int pending; assert(nr && tport == nr->nr_tport); if (nr == NULL || tport != nr->nr_tport) return; du = NUA_DIALOG_USAGE_PUBLIC(nr); pending = nr->nr_error_report_id; if (tport_release(tport, pending, NULL, NULL, nr, 0) < 0) SU_DEBUG_1(("nua_register: tport_release() failed\n")); nr->nr_error_report_id = 0; tpn = tport_name(nr->nr_tport); SU_DEBUG_5(("nua_register(%p): tport to %s/%s:%s%s%s closed %s\n", (void *)du->du_dialog->ds_owner, tpn->tpn_proto, tpn->tpn_host, tpn->tpn_port, tpn->tpn_comp ? ";comp=" : "", tpn->tpn_comp ? tpn->tpn_comp : "", error != 0 ? su_strerror(error) : "")); tport_unref(nr->nr_tport), nr->nr_tport = NULL; /* Schedule re-REGISTER immediately */ nua_dialog_usage_set_refresh_range(du, 0, 0); } static void nua_register_usage_update_params(nua_dialog_usage_t const *du, nua_handle_preferences_t const *changed, nua_handle_preferences_t const *nhp, nua_handle_preferences_t const *dnhp) { nua_registration_t *nr = nua_dialog_usage_private(du); outbound_t *ob = nr->nr_ob; if (!ob) return; if (!changed || NHP_ISSET(changed, outbound) || NHP_ISSET(changed, keepalive) || NHP_ISSET(changed, keepalive_stream)) { char const *outbound = NHP_ISSET(nhp, outbound) ? nhp->nhp_outbound : dnhp->nhp_outbound; unsigned keepalive = NHP_ISSET(nhp, keepalive) ? nhp->nhp_keepalive : dnhp->nhp_keepalive; unsigned keepalive_stream = NHP_ISSET(nhp, keepalive_stream) ? nhp->nhp_keepalive_stream : NHP_ISSET(dnhp, keepalive_stream) ? nhp->nhp_keepalive_stream : keepalive; outbound_set_options(ob, outbound, keepalive, keepalive_stream); } if (!changed || NHP_ISSET(changed, proxy)) { if (NHP_ISSET(nhp, proxy)) outbound_set_proxy(ob, nhp->nhp_proxy); } } static void nua_register_usage_refresh(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du, sip_time_t now) { nua_t *nua = nh->nh_nua; nua_client_request_t *cr = du->du_cr; if (cr) { if (nua_client_resend_request(cr, 0) >= 0) return; } /* Report that we have de-registered */ nua_stack_event(nua, nh, NULL, nua_r_register, NUA_ERROR_AT(__FILE__, __LINE__), NULL); nua_dialog_usage_remove(nh, ds, du, NULL, NULL); } /** @interal Shut down REGISTER usage. * * @retval >0 shutdown done * @retval 0 shutdown in progress * @retval <0 try again later */ static int nua_register_usage_shutdown(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du) { nua_client_request_t *cr = du->du_cr; nua_registration_t *nr = NUA_DIALOG_USAGE_PRIVATE(du); if (cr) { if (nua_client_is_queued(cr)) /* Already registering. */ return -1; cr->cr_event = nua_r_unregister; if (nua_client_resend_request(cr, 1) >= 0) return 0; } /* release the persistant transport for registration */ if (nr->nr_tport) tport_decref(&nr->nr_tport), nr->nr_tport = NULL; nua_dialog_usage_remove(nh, ds, du, NULL, NULL); return 200; } /* ---------------------------------------------------------------------- */ /* nua_registration_t interface */ #if HAVE_SOFIA_STUN #include #endif static void nua_stack_tport_update(nua_t *nua, nta_agent_t *nta); static int nua_registration_add_contact_and_route(nua_handle_t *nh, nua_registration_t *nr, msg_t *msg, sip_t *sip, int add_contact, int add_service_route); int nua_stack_init_transport(nua_t *nua, tagi_t const *tags) { url_string_t const *contact1 = NULL, *contact2 = NULL; char const *name1 = "sip", *name2 = "sip"; char const *certificate_dir = NULL; tl_gets(tags, NUTAG_URL_REF(contact1), NUTAG_SIPS_URL_REF(contact2), NUTAG_CERTIFICATE_DIR_REF(certificate_dir), TAG_END()); if (!contact1 && contact2) contact1 = contact2, contact2 = NULL; if (contact1 && (url_is_string(contact1) ? su_casenmatch(contact1->us_str, "sips:", 5) : contact1->us_url->url_type == url_sips)) name1 = "sips"; if (contact2 && (url_is_string(contact2) ? su_casenmatch(contact2->us_str, "sips:", 5) : contact2->us_url->url_type == url_sips)) name2 = "sips"; if (!contact1 /* && !contact2 */) { if (nta_agent_add_tport(nua->nua_nta, NULL, TPTAG_IDENT("sip"), TPTAG_CERTIFICATE(certificate_dir), TAG_NEXT(nua->nua_args)) < 0 && nta_agent_add_tport(nua->nua_nta, URL_STRING_MAKE("sip:*:*"), TPTAG_IDENT("sip"), TPTAG_CERTIFICATE(certificate_dir), TAG_NEXT(nua->nua_args)) < 0) return -1; #if HAVE_SOFIA_STUN if (stun_is_requested(TAG_NEXT(nua->nua_args)) && nta_agent_add_tport(nua->nua_nta, URL_STRING_MAKE("sip:0.0.0.0:*"), TPTAG_IDENT("stun"), TPTAG_PUBLIC(tport_type_stun), /* use stun */ TPTAG_CERTIFICATE(certificate_dir), TAG_NEXT(nua->nua_args)) < 0) { SU_DEBUG_0(("nua: error initializing STUN transport\n")); } #endif } else { if (nta_agent_add_tport(nua->nua_nta, contact1, TPTAG_IDENT(name1), TPTAG_CERTIFICATE(certificate_dir), TAG_NEXT(nua->nua_args)) < 0) return -1; if (contact2 && nta_agent_add_tport(nua->nua_nta, contact2, TPTAG_IDENT(name2), TPTAG_CERTIFICATE(certificate_dir), TAG_NEXT(nua->nua_args)) < 0) return -1; } if (nua_stack_init_registrations(nua) < 0) return -1; return 0; } #if 0 /* Store network detector param value */ if (agent->sa_nw_updates == 0) agent->sa_nw_updates = nw_updates; NTATAG_DETECT_NETWORK_UPDATES_REF(nw_updates), unsigned nw_updates = 0; unsigned nw_updates = 0; su_network_changed_t *sa_nw_changed; #endif static void nua_network_changed_cb(nua_t *nua, su_root_t *root) { uint32_t nw_updates; nw_updates = nua->nua_prefs->ngp_detect_network_updates; switch (nw_updates) { case NUA_NW_DETECT_ONLY_INFO: nua_stack_event(nua, NULL, NULL, nua_i_network_changed, SIP_200_OK, NULL); break; case NUA_NW_DETECT_TRY_FULL: /* 1) Shutdown all tports */ nta_agent_close_tports(nua->nua_nta); /* 2) Create new tports */ if (nua_stack_init_transport(nua, nua->nua_args) < 0) /* We are hosed */ nua_stack_event(nua, NULL, NULL, nua_i_network_changed, 900, "Internal Error", NULL); else nua_stack_event(nua, NULL, NULL, nua_i_network_changed, SIP_200_OK, NULL); break; default: break; } return; } int nua_stack_launch_network_change_detector(nua_t *nua) { su_network_changed_t *snc = NULL; snc = su_root_add_network_changed(nua->nua_home, nua->nua_root, nua_network_changed_cb, nua); if (!snc) return -1; nua->nua_nw_changed = snc; return 0; } int nua_stack_init_registrations(nua_t *nua) { /* Create initial identities: peer-to-peer, public, sips */ nua_registration_t **nr_list = &nua->nua_registrations, **nr_next; nua_handle_t **nh_list; nua_handle_t *dnh = nua->nua_dhandle; sip_via_t const *v; /* Remove existing, local address based registrations and count the rest */ while (nr_list && *nr_list) { nr_next = &(*nr_list)->nr_next; if ((*nr_list)->nr_default == 1) { nua_registration_remove(*nr_list); /* memset(*nr_list, 170, sizeof(**nr_list)); */ /* XXX - free, too */ } nr_list = nr_next; } nr_list = &nua->nua_registrations; v = nta_agent_public_via(nua->nua_nta); if (v) { nua_registration_from_via(nr_list, dnh, v, 1); } v = nta_agent_via(nua->nua_nta); if (v) { nua_registration_from_via(nr_list, dnh, v, 0); } else { sip_via_t v[2]; sip_via_init(v)->v_next = v + 1; v[0].v_protocol = sip_transport_udp; v[0].v_host = "addr.is.invalid."; sip_via_init(v + 1); v[1].v_protocol = sip_transport_tcp; v[1].v_host = "addr.is.invalid."; nua_registration_from_via(nr_list, dnh, v, 0); } /* Go through all the registrations and set to refresh almost immediately */ nh_list = &nua->nua_handles; for (; *nh_list; nh_list = &(*nh_list)->nh_next) { nua_dialog_state_t *ds; nua_dialog_usage_t *du; ds = (*nh_list)->nh_ds; du = ds->ds_usage; if (ds->ds_has_register == 1 && du->du_class->usage_refresh) { nua_dialog_usage_refresh(*nh_list, ds, du, 1); } } nta_agent_bind_tport_update(nua->nua_nta, (nta_update_magic_t *)nua, nua_stack_tport_update); return 0; } int nua_registration_from_via(nua_registration_t **list, nua_handle_t *nh, sip_via_t const *via, int public) { su_home_t *home = nh->nh_home; sip_via_t *v, *pair, /* v2[2], */ *vias, **vv, **prev; nua_registration_t *nr = NULL, **next; su_home_t autohome[SU_HOME_AUTO_SIZE(1024)]; int nr_items = 0; vias = sip_via_copy(su_home_auto(autohome, sizeof autohome), via); for (; *list; list = &(*list)->nr_next) ++nr_items; next = list; for (vv = &vias; (v = *vv);) { char const *protocol; sip_contact_t *contact; sip_via_t v2[2]; *vv = v->v_next, v->v_next = NULL, pair = NULL; if (v->v_protocol == sip_transport_tcp) protocol = sip_transport_udp; else if (v->v_protocol == sip_transport_udp) protocol = sip_transport_tcp; else protocol = NULL; if (protocol) { /* Try to pair vias if we have both udp and tcp */ for (prev = vv; *prev; prev = &(*prev)->v_next) { if (!su_casematch(protocol, (*prev)->v_protocol)) continue; if (!su_casematch(v->v_host, (*prev)->v_host)) continue; if (!su_strmatch(v->v_port, (*prev)->v_port)) continue; break; } if (*prev) { pair = *prev; *prev = pair->v_next; pair->v_next = NULL; } } /* if more than one candidate, ignore local entries */ if (v && (*vv || nr_items > 0) && host_is_local(v->v_host)) { SU_DEBUG_9(("nua_register: ignoring contact candidate %s:%s.\n", v->v_host, v->v_port ? v->v_port : "")); continue; } nr = su_zalloc(home, sizeof *nr); if (!nr) break; v2[0] = *v; if (pair) /* Don't use protocol if we have both udp and tcp */ protocol = NULL, v2[0].v_next = &v2[1], v2[1] = *pair; else protocol = via->v_protocol, v2[0].v_next = NULL; v2[1].v_next = NULL; contact = nua_handle_contact_by_via(nh, home, 0, v2, protocol, NULL); v = sip_via_dup(home, v2); if (!contact || !v) { su_free(home, nr); break; } nr->nr_ready = 1, nr->nr_default = 1, nr->nr_public = public; nr->nr_secure = contact->m_url->url_type == url_sips; nr->nr_contact = contact; *nr->nr_dcontact = *contact, nr->nr_dcontact->m_params = NULL; nr->nr_via = v; nr->nr_ip4 = host_is_ip4_address(contact->m_url->url_host); nr->nr_ip6 = !nr->nr_ip4 && host_is_ip6_reference(contact->m_url->url_host); SU_DEBUG_9(("nua_register: Adding contact URL '%s' to list.\n", contact->m_url->url_host)); ++nr_items; nr->nr_next = *next, nr->nr_prev = next; *next = nr, next = &nr->nr_next; nr->nr_list = list; } su_home_deinit(autohome); return 0; } static void nua_stack_tport_update(nua_t *nua, nta_agent_t *nta) { #if 0 nua_registration_t *default_oc; nua_registration_t const *defaults = nua->nua_registrations; sip_via_t *via = nta_agent_via(nta); default_oc = outbound_by_aor(defaults, NULL, 1); if (default_oc) { assert(default_oc->nr_via); outbound_contacts_from_via(default_oc, via, via->v_next); /* refresh_register(nua_handle_t *nh, nua_dialog_usage_t *du, sip_time_t now); */ } #endif return; } nua_registration_t *nua_registration_by_aor(nua_registration_t const *list, sip_from_t const *aor, url_t const *remote_uri, int only_default) { sip_from_t *alt_aor = NULL, _alt_aor[1]; int sips_aor = aor && aor->a_url->url_type == url_sips; int sips_uri = remote_uri && remote_uri->url_type == url_sips; nua_registration_t const *nr, *public = NULL, *any = NULL; nua_registration_t const *registered = NULL; nua_registration_t const *namewise = NULL, *sipswise = NULL; int ip4 = remote_uri && host_is_ip4_address(remote_uri->url_host); int ip6 = remote_uri && host_is_ip6_reference(remote_uri->url_host); if (only_default || aor == NULL) { /* Ignore AoR, select only by remote_uri */ for (nr = list; nr; nr = nr->nr_next) { if (!nr->nr_ready) continue; if (only_default && !nr->nr_default) continue; if (nr->nr_ip4 && ip6) continue; if (nr->nr_ip6 && ip4) continue; if (sips_uri ? nr->nr_secure : !nr->nr_secure) return (nua_registration_t *)nr; if (!registered && nr->nr_aor) registered = nr; if (!public && nr->nr_public) public = nr; if (!any) any = nr; } if (registered) return (nua_registration_t *)registered; if (public) return (nua_registration_t *)public; if (any) return (nua_registration_t *)any; return NULL; } if (!sips_aor && aor) { alt_aor = memcpy(_alt_aor, aor, sizeof _alt_aor); alt_aor->a_url->url_type = url_sips; alt_aor->a_url->url_scheme = "sips"; } for (nr = list; nr; nr = nr->nr_next) { if (!nr->nr_ready || !nr->nr_contact) continue; if (nr->nr_aor) { if (aor && url_cmp(nr->nr_aor->a_url, aor->a_url) == 0) return (nua_registration_t *)nr; if (!namewise && alt_aor && url_cmp(nr->nr_aor->a_url, aor->a_url) == 0) namewise = nr; } if (!sipswise && ((sips_aor || sips_uri) ? nr->nr_secure : !nr->nr_secure)) sipswise = nr; if (!registered) registered = nr; if (!public && nr->nr_public) public = nr; if (!any) any = nr; } if (namewise) return (nua_registration_t *)namewise; if (sipswise) return (nua_registration_t *)sipswise; if (registered) return (nua_registration_t *)registered; /* XXX - should we do some policing whether sips_aor or sips_uri can be used with sip contact? */ if (public) return (nua_registration_t *)public; if (any) return (nua_registration_t *)any; return NULL; } nua_registration_t * nua_registration_for_request(nua_registration_t const *list, sip_t const *sip) { sip_from_t const *aor; url_t *uri; aor = sip->sip_from; uri = sip->sip_request->rq_url; return nua_registration_by_aor(list, aor, uri, 0); } nua_registration_t * nua_registration_for_response(nua_registration_t const *list, sip_t const *sip, sip_record_route_t const *record_route, sip_contact_t const *remote_contact) { nua_registration_t *nr; sip_to_t const *aor = NULL; url_t const *uri = NULL; if (sip) aor = sip->sip_to; if (record_route) uri = record_route->r_url; else if (sip && sip->sip_record_route) uri = sip->sip_record_route->r_url; else if (remote_contact) uri = remote_contact->m_url; else if (sip && sip->sip_from) uri = sip->sip_from->a_url; nr = nua_registration_by_aor(list, aor, uri, 0); return nr; } /** Return Contact usable in dialogs */ sip_contact_t const *nua_registration_contact(nua_registration_t const *nr) { if (nr->nr_by_stack && nr->nr_ob) { sip_contact_t const *m = outbound_dialog_contact(nr->nr_ob); if (m) return m; } if (nr->nr_contact) return nr->nr_dcontact; else return NULL; } /** Return initial route. */ sip_route_t const *nua_registration_route(nua_registration_t const *nr) { return nr ? nr->nr_route : NULL; } sip_contact_t const *nua_stack_get_contact(nua_registration_t const *nr) { nr = nua_registration_by_aor(nr, NULL, NULL, 1); return nr && nr->nr_contact ? nr->nr_dcontact : NULL; } /** Add a Contact (and Route) header to request */ int nua_registration_add_contact_to_request(nua_handle_t *nh, msg_t *msg, sip_t *sip, int add_contact, int add_service_route) { nua_registration_t *nr = NULL; if (!add_contact && !add_service_route) return 0; if (nh == NULL || msg == NULL) return -1; if (sip == NULL) sip = sip_object(msg); if (nr == NULL) nr = nua_registration_for_request(nh->nh_nua->nua_registrations, sip); return nua_registration_add_contact_and_route(nh, nr, msg, sip, add_contact, add_service_route); } /** Add a Contact header to response. * * @param nh * @param msg response message * @param sip headers in response message * @param record_route record-route from request * @param remote_contact Contact from request */ int nua_registration_add_contact_to_response(nua_handle_t *nh, msg_t *msg, sip_t *sip, sip_record_route_t const *record_route, sip_contact_t const *remote_contact) { nua_registration_t *nr = NULL; if (sip == NULL) sip = sip_object(msg); if (nh == NULL || msg == NULL || sip == NULL) return -1; if (nr == NULL) nr = nua_registration_for_response(nh->nh_nua->nua_registrations, sip, record_route, remote_contact); return nua_registration_add_contact_and_route(nh, nr, msg, sip, 1, 0); } /** Add a Contact (and Route) header to request */ static int nua_registration_add_contact_and_route(nua_handle_t *nh, nua_registration_t *nr, msg_t *msg, sip_t *sip, int add_contact, int add_service_route) { if (nr == NULL) return -1; if (add_contact) { sip_contact_t const *m = NULL; char const *m_display; char const *m_username; char const *m_params; url_t const *u; if (nr->nr_by_stack && nr->nr_ob) { m = outbound_dialog_gruu(nr->nr_ob); if (m) return msg_header_add_dup(msg, (msg_pub_t *)sip, (void const *)m); m = outbound_dialog_contact(nr->nr_ob); } if (m == NULL) m = nr->nr_contact; if (!m) return -1; u = m->m_url; if (NH_PISSET(nh, m_display)) m_display = NH_PGET(nh, m_display); else m_display = m->m_display; if (NH_PISSET(nh, m_username)) m_username = NH_PGET(nh, m_username); else m_username = m->m_url->url_user; if (NH_PISSET(nh, m_params)) { m_params = NH_PGET(nh, m_params); if (u->url_params && m_params && strstr(u->url_params, m_params) == 0) m_params = NULL; } else m_params = NULL; m = sip_contact_format(msg_home(msg), "%s<%s:%s%s%s%s%s%s%s%s%s>", m_display ? m_display : "", u->url_scheme, m_username ? m_username : "", m_username ? "@" : "", u->url_host, u->url_port ? ":" : "", u->url_port ? u->url_port : "", u->url_params ? ";" : "", u->url_params ? u->url_params : "", m_params ? ";" : "", m_params ? m_params : ""); if (msg_header_insert(msg, (msg_pub_t *)sip, (void *)m) < 0) return -1; } if (add_service_route && !sip->sip_status) { sip_route_t const *sr = nua_registration_route(nr); if (msg_header_add_dup(msg, (msg_pub_t *)sip, (void const *)sr) < 0) return -1; } return 0; } /** Add a registration to list of contacts */ int nua_registration_add(nua_registration_t **list, nua_registration_t *nr) { assert(list && nr); if (nr->nr_list == NULL) { nua_registration_t *next = *list; if (next) next->nr_prev = &nr->nr_next; nr->nr_next = next, nr->nr_prev = list, nr->nr_list = list; *list = nr; } return 0; } /** Remove from list of registrations */ void nua_registration_remove(nua_registration_t *nr) { if ((*nr->nr_prev = nr->nr_next)) nr->nr_next->nr_prev = nr->nr_prev; nr->nr_next = NULL, nr->nr_prev = NULL, nr->nr_list = NULL; } /** Set address-of-record. */ int nua_registration_set_aor(su_home_t *home, nua_registration_t *nr, sip_from_t const *aor) { sip_from_t *new_aor, *old_aor; if (!home || !nr || !aor) return -1; new_aor = sip_from_dup(home, aor); if (!new_aor) return -1; old_aor = nr->nr_aor; nr->nr_aor = new_aor; msg_header_free(home, (void *)old_aor); return 0; } /** Set contact. */ int nua_registration_set_contact(nua_handle_t *nh, nua_registration_t *nr, sip_contact_t const *application_contact, int terminating) { sip_contact_t *m = NULL, *previous; url_t *uri; if (!nh || !nr) return -1; uri = nr->nr_aor ? nr->nr_aor->a_url : NULL; previous = nr->nr_contact; if (application_contact) { m = sip_contact_dup(nh->nh_home, application_contact); } else if (terminating && nr->nr_contact) { return 0; } else { nua_registration_t *nr0; nr0 = nua_registration_by_aor(*nr->nr_list, NULL, uri, 1); if (nr0 && nr0->nr_via) { char const *tport = nr0->nr_via->v_next ? NULL : nr0->nr_via->v_protocol; m = nua_handle_contact_by_via(nh, nh->nh_home, 0, nr0->nr_via, tport, NULL); } } if (!m) return -1; nr->nr_contact = m; *nr->nr_dcontact = *m, nr->nr_dcontact->m_params = NULL; nr->nr_ip4 = host_is_ip4_address(m->m_url->url_host); nr->nr_ip6 = !nr->nr_ip4 && host_is_ip6_reference(m->m_url->url_host); nr->nr_by_stack = !application_contact; msg_header_free(nh->nh_home, (void *)previous); return 0; } /** Mark registration as ready */ void nua_registration_set_ready(nua_registration_t *nr, int ready) { if (nr) { assert(!ready || nr->nr_contact); nr->nr_ready = ready; } } /** @internal Hook for processing incoming request by registration. * * This is used for keepalive/validate OPTIONS. */ int nua_registration_process_request(nua_registration_t *list, nta_incoming_t *irq, sip_t const *sip) { sip_call_id_t *i; nua_registration_t *nr; if (!outbound_targeted_request(sip)) return 0; /* Process by outbound... */ i = sip->sip_call_id; for (nr = list; nr; nr = nr->nr_next) { outbound_t *ob = nr->nr_ob; if (ob) if (outbound_process_request(ob, irq, sip)) return 501; /* Just in case */ } return 481; /* Call/Transaction does not exist */ } /** Outbound requests us to refresh registration */ static int nua_stack_outbound_refresh(nua_handle_t *nh, outbound_t *ob) { nua_dialog_state_t *ds = nh->nh_ds; nua_dialog_usage_t *du; du = nua_dialog_usage_get(ds, nua_register_usage, NULL); if (du) nua_dialog_usage_refresh(nh, ds, du, 1); return 0; } /** @NUA_EVENT nua_i_outbound * * Status from outbound engine. * * @param status SIP status code or NUA status code (>= 900) * describing the outbound state * @param phrase a short textual description of @a status code * @param nh operation handle associated with the outbound engine * @param hmagic application context associated with the handle * @param sip NULL or response message to an keepalive message or * registration probe * (error code and message are in status an phrase parameters) * @param tags empty * * @sa NUTAG_OUTBOUND(), NUTAG_KEEPALIVE(), NUTAG_KEEPALIVE_STREAM(), * nua_register(), #nua_r_register, nua_unregister(), #nua_r_unregister * * @END_NUA_EVENT */ /** @internal Callback from outbound_t */ static int nua_stack_outbound_status(nua_handle_t *nh, outbound_t *ob, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...) { ta_list ta; ta_start(ta, tag, value); nua_stack_event(nh->nh_nua, nh, NULL, nua_i_outbound, status, phrase, ta_args(ta)); ta_end(ta); return 0; } /** @internal Callback from outbound_t */ static int nua_stack_outbound_failed(nua_handle_t *nh, outbound_t *ob, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...) { ta_list ta; ta_start(ta, tag, value); nua_stack_event(nh->nh_nua, nh, NULL, nua_i_outbound, status, phrase, ta_args(ta)); ta_end(ta); return 0; } /** @internal Callback for obtaining credentials for keepalive */ static int nua_stack_outbound_credentials(nua_handle_t *nh, auth_client_t **auc) { return auc_copy_credentials(auc, nh->nh_auth); } #include #include /** @internal Generate a @Contact header. */ sip_contact_t *nua_handle_contact_by_via(nua_handle_t *nh, su_home_t *home, int in_dialog, sip_via_t const *v, char const *transport, char const *m_param, ...) { su_strlst_t *l; char const *s; char const *host, *port, *maddr, *comp; int one = 1; char _transport[16]; va_list va; sip_contact_t *m; url_t url; url_init(&url, url_sip); if (!v) return NULL; host = v->v_host; if (v->v_received) host = v->v_received; port = sip_via_port(v, &one); maddr = v->v_maddr; comp = v->v_comp; if (host == NULL) return NULL; if (sip_transport_has_tls(v->v_protocol) || sip_transport_has_tls(transport)) { url.url_type = url_sips; url.url_scheme = url_scheme(url_sips); if (port && strcmp(port, SIPS_DEFAULT_SERV) == 0) port = NULL; if (port || host_is_ip_address(host)) transport = NULL; } else if (port && host_is_ip_address(host) && strcmp(port, SIP_DEFAULT_SERV) == 0) { port = NULL; } if (transport) { if (su_casenmatch(transport, "SIP/2.0/", 8)) transport += 8; /* Make transport parameter lowercase */ if (strlen(transport) < (sizeof _transport)) { char *s = strcpy(_transport, transport); short c; for (; (c = *s) && c != ';'; s++) if (isupper(c)) *s = tolower(c); transport = _transport; } } s = NH_PGET(nh, m_username); if (s) url.url_user = s; url.url_host = host; url.url_port = port; url.url_params = su_strdup(home, NH_PGET(nh, m_params)); if (transport) { url.url_params = url_strip_param_string((char*)url.url_params, "transport"); url_param_add(home, &url, su_sprintf(home, "transport=%s", transport)); } if (maddr) { url.url_params = url_strip_param_string((char*)url.url_params, "maddr"); url_param_add(home, &url, su_sprintf(home, "maddr=%s", maddr)); } if (comp) { url.url_params = url_strip_param_string((char*)url.url_params, "comp"); url_param_add(home, &url, su_sprintf(home, "comp=%s", comp)); } l = su_strlst_create(NULL); s = NH_PGET(nh, m_display); if (s) { int quote = s[span_token_lws(s)] != '\0'; su_strlst_append(l, quote ? "\"" : ""); su_strlst_append(l, s); su_strlst_append(l, quote ? "\" " : " "); } su_strlst_append(l, "<"); su_strlst_append(l, url_as_string(home, &url)); su_strlst_append(l, ">"); va_start(va, m_param); for (s = m_param; s; s = va_arg(va, char *)) { if (strlen(s) == 0) continue; su_strlst_append(l, s[0] == ';' ? "" : ";"); su_strlst_append(l, s); } va_end(va); if (!in_dialog) { s = NH_PGET(nh, m_features); if (s) s[0] == ';' ? "" : su_strlst_append(l, ";"), su_strlst_append(l, s); if (NH_PGET(nh, callee_caps)) { sip_allow_t const *allow = NH_PGET(nh, allow); if (allow) { su_strlst_append(l, ";methods=\""); if (allow->k_items) { size_t i; for (i = 0; allow->k_items[i]; i++) { su_strlst_append(l, allow->k_items[i]); if (allow->k_items[i + 1]) su_strlst_append(l, ","); } } su_strlst_append(l, "\""); } if (nh->nh_soa) { char **media = soa_media_features(nh->nh_soa, 0, home); while (*media) { if (su_strlst_len(l)) su_strlst_append(l, ";"); su_strlst_append(l, *media++); } } } } m = sip_contact_make(home, su_strlst_join(l, su_strlst_home(l), "")); su_strlst_destroy(l); return m; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/nua_registrar.c000066400000000000000000000066371223300710500233620ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2006 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE nua_registrar.c * @brief REGISTER UAS * * @author Michael Jerris * * @date Created: Tue Oct 3 10:14:54 EEST 2006 ppessi */ #include "config.h" #include #include #include #include #include #include #include #include #include #define NTA_INCOMING_MAGIC_T struct nua_handle_s #define NTA_RELIABLE_MAGIC_T struct nua_handle_s #include "nua_stack.h" /* ======================================================================== */ /* REGISTER */ /** @NUA_EVENT nua_i_register * * Incoming REGISTER request. * * In order to receive #nua_i_register events, the application must enable * the REGISTER method with NUTAG_ALLOW() tag, e.g., * @verbatim * nua_set_params(nua; * NUTAG_APPL_METHOD("REGISTER"), * NUTAG_ALLOW("REGISTER"), * TAG_END()); * @endverbatim * * The nua_response() call responding to a REGISTER request must include * NUTAG_WITH() (or NUTAG_WITH_THIS()/NUTAG_WITH_SAVED()) tag. Note that * a successful response to REGISTER @b MUST include the @Contact header * bound to the the AoR URI (in @To header). * * The REGISTER request does not create a dialog. Currently the processing * of incoming REGISTER creates a new handle for each incoming request which * is not assiciated with an existing dialog. If the handle @a nh is not * bound, you should probably destroy it after responding to the REGISTER * request. * * @param status status code of response sent automatically by stack * @param phrase a short textual description of @a status code * @param nh operation handle associated with the request * @param hmagic application context associated with the handle * (usually NULL) * @param sip incoming REGISTER request * @param tags empty * * @sa nua_respond(), @RFC3261 section 10.3, * @Expires, @Contact, @CallID, @CSeq, * @Path, @RFC3327, @ServiceRoute, @RFC3608, @RFC3680, * nua_register(), #nua_i_register, nua_unregister(), #nua_i_unregister * * @since New in @VERSION_1_12_4 * @END_NUA_EVENT */ nua_server_methods_t const nua_register_server_methods = { SIP_METHOD_REGISTER, nua_i_register, /* Event */ { 0, /* Do not create dialog */ 0, /* Initial request */ 0, /* Not a target refresh request */ 0, /* Do not add Contact */ }, nua_base_server_init, nua_base_server_preprocess, nua_base_server_params, nua_base_server_respond, nua_base_server_report, }; sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/nua_server.c000066400000000000000000000543141223300710500226610ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2006 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE nua_server.c * @brief Server transaction handling * * @author Pekka Pessi * * @date Created: Tue Feb 3 16:10:45 EET 2009 */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #define NUA_SAVED_EVENT_T su_msg_t * #define NUA_SAVED_SIGNAL_T su_msg_t * #include #include "nua_stack.h" #include "nua_dialog.h" #include "nua_server.h" #include "nua_params.h" static int nua_server_init_response(nua_server_request_t *sr, int status, char const *phrase); /* ======================================================================== */ /* * Process incoming requests */ nua_server_methods_t const *nua_server_methods[] = { /* These must be in same order as in sip_method_t */ &nua_extension_server_methods, &nua_invite_server_methods, /**< INVITE */ NULL, /**< ACK */ NULL, /**< CANCEL */ &nua_bye_server_methods, /**< BYE */ &nua_options_server_methods, /**< OPTIONS */ &nua_register_server_methods, /**< REGISTER */ &nua_info_server_methods, /**< INFO */ &nua_prack_server_methods, /**< PRACK */ &nua_update_server_methods, /**< UPDATE */ &nua_message_server_methods, /**< MESSAGE */ &nua_subscribe_server_methods,/**< SUBSCRIBE */ &nua_notify_server_methods, /**< NOTIFY */ &nua_refer_server_methods, /**< REFER */ &nua_publish_server_methods, /**< PUBLISH */ NULL }; int nua_stack_process_request(nua_handle_t *nh, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip) { nua_t *nua = nh->nh_nua; sip_method_t method = sip->sip_request->rq_method; char const *name = sip->sip_request->rq_method_name; nua_server_methods_t const *sm; nua_server_request_t *sr, sr0[1]; int status, initial = 1; int create_dialog; char const *user_agent = NH_PGET(nh, user_agent); sip_supported_t const *supported = NH_PGET(nh, supported); sip_allow_t const *allow = NH_PGET(nh, allow); enter; nta_incoming_tag(irq, NULL); if (method == sip_method_cancel) return 481; /* Hook to outbound */ if (method == sip_method_options) { status = nua_registration_process_request(nua->nua_registrations, irq, sip); if (status) return status; } if (nta_check_method(irq, sip, allow, SIPTAG_SUPPORTED(supported), SIPTAG_USER_AGENT_STR(user_agent), TAG_END())) return 405; switch (sip->sip_request->rq_url->url_type) { case url_sip: case url_sips: case url_im: case url_pres: case url_tel: break; default: nta_incoming_treply(irq, status = SIP_416_UNSUPPORTED_URI, SIPTAG_ALLOW(allow), SIPTAG_SUPPORTED(supported), SIPTAG_USER_AGENT_STR(user_agent), TAG_END()); return status; } if (nta_check_required(irq, sip, supported, SIPTAG_ALLOW(allow), SIPTAG_USER_AGENT_STR(user_agent), TAG_END())) return 420; if (method > sip_method_unknown && method <= sip_method_publish) sm = nua_server_methods[method]; else sm = nua_server_methods[0]; initial = nh == nua->nua_dhandle; if (sm == NULL) { SU_DEBUG_1(("nua(%p): strange %s from <" URL_PRINT_FORMAT ">\n", (void *)nh, sip->sip_request->rq_method_name, URL_PRINT_ARGS(sip->sip_from->a_url))); } else if (initial && sm->sm_flags.in_dialog) { /* These must be in-dialog */ sm = NULL; } else if (initial && sip->sip_to->a_tag) { /* RFC 3261 section 12.2.2: If the UAS wishes to reject the request because it does not wish to recreate the dialog, it MUST respond to the request with a 481 (Call/Transaction Does Not Exist) status code and pass that to the server transaction. */ switch (method) { case sip_method_info: /* accept out-of-dialog info */; break; case sip_method_message: if (!NH_PGET(nh, win_messenger_enable)) sm = NULL; break; default: sm = NULL; } } if (!sm) { nta_incoming_treply(irq, status = 481, "Call Does Not Exist", SIPTAG_ALLOW(allow), SIPTAG_SUPPORTED(supported), SIPTAG_USER_AGENT_STR(user_agent), TAG_END()); return 481; } create_dialog = sm->sm_flags.create_dialog; if (method == sip_method_message && NH_PGET(nh, win_messenger_enable)) create_dialog = 1; sr = memset(sr0, 0, (sizeof sr0)); sr->sr_methods = sm; sr->sr_method = method = sip->sip_request->rq_method; sr->sr_add_contact = sm->sm_flags.add_contact; sr->sr_target_refresh = sm->sm_flags.target_refresh; sr->sr_owner = nh; sr->sr_initial = initial; sr->sr_irq = irq; SR_STATUS1(sr, SIP_100_TRYING); sr->sr_request.msg = nta_incoming_getrequest(irq); sr->sr_request.sip = sip; assert(sr->sr_request.msg); sr->sr_response.msg = nta_incoming_create_response(irq, 0, NULL); sr->sr_response.sip = sip_object(sr->sr_response.msg); if (sr->sr_response.msg == NULL) return nua_server_init_response(sr, SIP_500_INTERNAL_SERVER_ERROR); if (sip->sip_payload != NULL && NH_PGET(nh, accept_multipart) && sip->sip_multipart == NULL) { sip_content_type_t *c = sip->sip_content_type; if (c != NULL && su_casenmatch(c->c_type, "multipart/", 10)) { su_home_t *home = msg_home(sr->sr_request.msg); sip_t *request = (sip_t *)sip; sip_payload_t *pl = (sip_payload_t *)sip->sip_payload; msg_multipart_t *mp = msg_multipart_parse(home, c, pl); if (mp == NULL) return nua_server_init_response(sr, 400, "Bad multipart body"); request->sip_multipart = mp; } } if (sm->sm_init && sm->sm_init(sr)) { if (sr->sr_status >= 200) /* Init have set response status */ return nua_server_init_response(sr, sr->sr_status, sr->sr_phrase); else return nua_server_init_response(sr, SIP_500_INTERNAL_SERVER_ERROR); } /* Create handle if request does not fail */ if (initial && sr->sr_status < 300) { if ((nh = nua_stack_incoming_handle(nua, irq, sip, create_dialog))) sr->sr_owner = nh; else return nua_server_init_response(sr, SIP_500_INTERNAL_SERVER_ERROR); } if (sr->sr_status < 300 && sm->sm_preprocess && sm->sm_preprocess(sr)) { if (sr->sr_status >= 200) return nua_server_init_response(sr, sr->sr_status, sr->sr_phrase); else /* Set response status if preprocess did not */ return nua_server_init_response(sr, SIP_500_INTERNAL_SERVER_ERROR); } if (sr->sr_status < 300) { if (sr->sr_target_refresh) nua_dialog_uas_route(nh, nh->nh_ds, sip, 1); /* Set route and tags */ nua_dialog_store_peer_info(nh, nh->nh_ds, sip); } if (sr->sr_status == 100 && method != sip_method_unknown && !sip_is_allowed(NH_PGET(sr->sr_owner, appl_method), method, name)) { if (method == sip_method_refer || method == sip_method_subscribe) SR_STATUS1(sr, SIP_202_ACCEPTED); else SR_STATUS1(sr, SIP_200_OK); } /* INVITE server request is not finalized after 2XX response */ if (sr->sr_status < (method == sip_method_invite ? 300 : 200)) { sr = su_alloc(nh->nh_home, (sizeof *sr)); if (sr) { *sr = *sr0; if ((sr->sr_next = nh->nh_ds->ds_sr)) *(sr->sr_prev = sr->sr_next->sr_prev) = sr, sr->sr_next->sr_prev = &sr->sr_next; else *(sr->sr_prev = &nh->nh_ds->ds_sr) = sr; } else { sr = sr0; SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); } } if (sr->sr_status > 100) return nua_server_init_response(sr, sr->sr_status, sr->sr_phrase); SR_STATUS1(sr, SIP_100_TRYING); if (method == sip_method_invite || sip->sip_timestamp) { if (NH_PGET(nh, auto100)) nta_incoming_treply(irq, SIP_100_TRYING, SIPTAG_USER_AGENT_STR(user_agent), TAG_END()); } if (nua_server_report(sr) == 0) return 0; return 501; } static int nua_server_init_response(nua_server_request_t *sr, int status, char const *phrase) { sr->sr_status = status; sr->sr_phrase = phrase; /* Note that this may change the sr->sr_status */ nua_server_respond(sr, NULL); if (nua_server_report(sr) != 0) return 501; return 0; } #undef nua_base_server_init #undef nua_base_server_preprocess int nua_base_server_init(nua_server_request_t *sr) { return 0; } int nua_base_server_preprocess(nua_server_request_t *sr) { return 0; } void nua_server_request_destroy(nua_server_request_t *sr) { if (sr == NULL) return; if (SR_HAS_SAVED_SIGNAL(sr)) nua_destroy_signal(sr->sr_signal); if (sr->sr_irq) { if (sr->sr_method == sip_method_bye && sr->sr_status < 200) { nta_incoming_treply(sr->sr_irq, SIP_200_OK, TAG_END()); } nta_incoming_destroy(sr->sr_irq), sr->sr_irq = NULL; } if (sr->sr_request.msg) msg_destroy(sr->sr_request.msg), sr->sr_request.msg = NULL; if (sr->sr_response.msg) msg_destroy(sr->sr_response.msg), sr->sr_response.msg = NULL; if (sr->sr_prev) { /* Allocated from heap */ if ((*sr->sr_prev = sr->sr_next)) sr->sr_next->sr_prev = sr->sr_prev; su_free(sr->sr_owner->nh_home, sr); } } /**@fn void nua_respond(nua_handle_t *nh, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...); * * Respond to a request with given status code and phrase. * * The stack returns a SIP response message with given status code and * phrase to the client. The tagged parameter list can specify extra headers * to include with the response message and other stack parameters. The SIP * session or other protocol state associated with the handle is updated * accordingly (for instance, if an initial INVITE is responded with 200, a * SIP session is established.) * * When responding to an incoming INVITE request, the nua_respond() can be * called without NUTAG_WITH() (or NUTAG_WITH_CURRENT() or * NUTAG_WITH_SAVED()). Otherwise, NUTAG_WITH() will contain an indication * of the request being responded. * * @param nh Pointer to operation handle * @param status SIP response status code (see RFCs of SIP) * @param phrase free text (default response phrase is used if NULL) * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Responses by Protocol Engine * * When nua protocol engine receives an incoming SIP request, it can either * respond to the request automatically or let application to respond to the * request. The automatic response is returned to the client if the request * fails syntax check, or the method, SIP extension or content negotiation * fails. * * When the @ref nua_handlingevents "request event" is delivered to the * application, the application should examine the @a status parameter. The * @a status parameter is 200 or greater if the request has been already * responded automatically by the stack. * * The application can add methods that it likes to handle by itself with * NUTAG_APPL_METHOD(). The default set of NUTAG_APPL_METHOD() includes * INVITE, PUBLISH, REGISTER and SUBSCRIBE. Note that unless the method is * also included in the set of allowed methods with NUTAG_ALLOW(), the stack * will respond to the incoming methods with 405 Not Allowed. * * In order to simplify the simple applications, most requests are responded * automatically. The BYE and CANCEL requests are always responded by the * stack. Likewise, the NOTIFY requests associated with an event * subscription are responded by the stack. * * Note that certain methods are rejected outside a SIP session (created * with INVITE transaction). They include BYE, UPDATE, PRACK and INFO. Also * the auxiliary methods ACK and CANCEL are rejected by the stack if there * is no ongoing INVITE transaction corresponding to them. * * @par Related Tags: * NUTAG_WITH(), NUTAG_WITH_THIS(), NUTAG_WITH_SAVED() \n * NUTAG_EARLY_ANSWER() \n * SOATAG_ADDRESS() \n * SOATAG_AF() \n * SOATAG_HOLD() \n * Tags used with nua_set_hparams() \n * Header tags defined in . * * @par Events: * #nua_i_state \n * #nua_i_media_error \n * #nua_i_error \n * #nua_i_active \n * #nua_i_terminated \n * * @sa #nua_i_invite, #nua_i_register, #nua_i_subscribe, #nua_i_publish */ void nua_stack_respond(nua_t *nua, nua_handle_t *nh, int status, char const *phrase, tagi_t const *tags) { nua_server_request_t *sr; tagi_t const *t; msg_t const *request = NULL; t = tl_find_last(tags, nutag_with); if (t) request = (msg_t const *)t->t_value; for (sr = nh->nh_ds->ds_sr; sr; sr = sr->sr_next) { if (request && sr->sr_request.msg == request) break; /* nua_respond() to INVITE can be used without NUTAG_WITH() */ if (!t && sr->sr_method == sip_method_invite) break; } if (sr == NULL) { nua_stack_event(nua, nh, NULL, nua_i_error, 500, "Responding to a Non-Existing Request", NULL); return; } else if (!nua_server_request_is_pending(sr)) { nua_stack_event(nua, nh, NULL, nua_i_error, 500, "Already Sent Final Response", NULL); return; } else if (sr->sr_100rel && !sr->sr_pracked && 200 <= status && status < 300) { /* Save signal until we have received PRACK */ if (tags && nua_stack_set_params(nua, nh, nua_i_none, tags) < 0) { sr->sr_application = status; SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); } else { su_msg_save(sr->sr_signal, nh->nh_nua->nua_signal); return; } } else { sr->sr_application = status; if (tags && nua_stack_set_params(nua, nh, nua_i_none, tags) < 0) SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); else { sr->sr_status = status, sr->sr_phrase = phrase; } } nua_server_params(sr, tags); nua_server_respond(sr, tags); nua_server_report(sr); } int nua_server_params(nua_server_request_t *sr, tagi_t const *tags) { if (sr->sr_methods->sm_params) return sr->sr_methods->sm_params(sr, tags); return 0; } #undef nua_base_server_params int nua_base_server_params(nua_server_request_t *sr, tagi_t const *tags) { return 0; } /** Return the response to the client. * * @retval 0 when successfully sent * @retval -1 upon an error */ int nua_server_trespond(nua_server_request_t *sr, tag_type_t tag, tag_value_t value, ...) { int retval; ta_list ta; ta_start(ta, tag, value); retval = nua_server_respond(sr, ta_args(ta)); ta_end(ta); return retval; } /** Return the response to the client. * * @retval 0 when successfully sent * @retval -1 upon an error */ int nua_server_respond(nua_server_request_t *sr, tagi_t const *tags) { nua_handle_t *nh = sr->sr_owner; nua_dialog_state_t *ds = nh->nh_ds; sip_method_t method = sr->sr_method; struct { msg_t *msg; sip_t *sip; } next = { NULL, NULL }; int retval, user_contact = 1; #if HAVE_OPEN_C /* Nice. And old arm symbian compiler; see below. */ tagi_t next_tags[2]; #else tagi_t next_tags[2] = {{ SIPTAG_END() }, { TAG_NEXT(tags) }}; #endif msg_t *msg = sr->sr_response.msg; sip_t *sip = sr->sr_response.sip; sip_contact_t *m = sr->sr_request.sip->sip_contact; #if HAVE_OPEN_C next_tags[0].t_tag = siptag_end; next_tags[0].t_value = (tag_value_t)0; next_tags[1].t_tag = tag_next; next_tags[1].t_value = (tag_value_t)(tags); #endif if (sr->sr_response.msg == NULL) { /* assert(sr->sr_status == 500); */ SU_DEBUG_0(("sr without msg, sr_status=%u", sr->sr_status)); if (sr->sr_status < 300 || sr->sr_status >= 700) SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); goto internal_error; } if (sr->sr_status < 200) { next.msg = nta_incoming_create_response(sr->sr_irq, 0, NULL); next.sip = sip_object(next.msg); if (next.sip == NULL) SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); } if (nta_incoming_complete_response(sr->sr_irq, msg, sr->sr_status, sr->sr_phrase, TAG_NEXT(tags)) < 0) ; else if (!sip->sip_supported && NH_PGET(nh, supported) && sip_add_dup(msg, sip, (sip_header_t *)NH_PGET(nh, supported)) < 0) ; else if (!sip->sip_user_agent && NH_PGET(nh, user_agent) && sip_add_make(msg, sip, sip_user_agent_class, NH_PGET(nh, user_agent)) < 0) ; else if (!sip->sip_organization && NH_PGET(nh, organization) && sip_add_make(msg, sip, sip_organization_class, NH_PGET(nh, organization)) < 0) ; else if (!sip->sip_allow && NH_PGET(nh, allow) && sip_add_dup(msg, sip, (void *)NH_PGET(nh, allow)) < 0) ; else if (!sip->sip_allow_events && NH_PGET(nh, allow_events) && (method == sip_method_publish || method == sip_method_subscribe || method == sip_method_options || method == sip_method_refer || (sr->sr_initial && (method == sip_method_invite || method == sip_method_notify))) && sip_add_dup(msg, sip, (void *)NH_PGET(nh, allow_events)) < 0) ; else if (!sip->sip_contact && sr->sr_status < 300 && sr->sr_add_contact && (user_contact = 0, ds->ds_ltarget ? sip_add_dup(msg, sip, (sip_header_t *)ds->ds_ltarget) : nua_registration_add_contact_to_response(nh, msg, sip, NULL, m)) < 0) ; else { int term; sip_contact_t *ltarget = NULL; term = sip_response_terminates_dialog(sr->sr_status, sr->sr_method, NULL); sr->sr_terminating = (term < 0) ? -1 : (term > 0 || sr->sr_terminating); if (sr->sr_target_refresh && sr->sr_status < 300 && !sr->sr_terminating && user_contact && sip->sip_contact) { /* Save Contact given by application */ ltarget = sip_contact_dup(nh->nh_home, sip->sip_contact); } retval = sr->sr_methods->sm_respond(sr, next_tags); if (sr->sr_status < 200) sr->sr_response.msg = next.msg, sr->sr_response.sip = next.sip; else if (next.msg) msg_destroy(next.msg); assert(sr->sr_status >= 200 || sr->sr_response.msg); if (ltarget) { if (sr->sr_status < 300) { nua_dialog_state_t *ds = nh->nh_ds; msg_header_free(nh->nh_home, (msg_header_t *)ds->ds_ltarget); ds->ds_ltarget = ltarget; } else msg_header_free(nh->nh_home, (msg_header_t *)ltarget); } return retval; } if (next.msg) msg_destroy(next.msg); SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); msg_destroy(msg); internal_error: sr->sr_response.msg = NULL, sr->sr_response.sip = NULL; nta_incoming_treply(sr->sr_irq, sr->sr_status, sr->sr_phrase, TAG_END()); return 0; } /** Return the response to the client. * * @retval 0 when successfully sent * @retval -1 upon an error */ int nua_base_server_respond(nua_server_request_t *sr, tagi_t const *tags) { msg_t *response = sr->sr_response.msg; sip_t *sip = sr->sr_response.sip; sr->sr_response.msg = NULL, sr->sr_response.sip = NULL; if (sr->sr_status != sip->sip_status->st_status) { msg_header_remove(response, (msg_pub_t *)sip, (msg_header_t *)sip->sip_status); nta_incoming_complete_response(sr->sr_irq, response, sr->sr_status, sr->sr_phrase, TAG_END()); } if (sr->sr_status != sip->sip_status->st_status) { msg_destroy(response); SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); nta_incoming_treply(sr->sr_irq, sr->sr_status, sr->sr_phrase, TAG_END()); return 0; } return nta_incoming_mreply(sr->sr_irq, response); } int nua_server_report(nua_server_request_t *sr) { if (sr) return sr->sr_methods->sm_report(sr, NULL); else return 1; } int nua_base_server_treport(nua_server_request_t *sr, tag_type_t tag, tag_value_t value, ...) { int retval; ta_list ta; ta_start(ta, tag, value); retval = nua_base_server_report(sr, ta_args(ta)); ta_end(ta); return retval; } /**Report request event to the application. * * @retval 0 request lives * @retval 1 request was destroyed * @retval 2 request and its usage was destroyed * @retval 3 request, all usages and dialog was destroyed * @retval 4 request, all usages, dialog, and handle was destroyed */ int nua_base_server_report(nua_server_request_t *sr, tagi_t const *tags) { nua_handle_t *nh = sr->sr_owner; nua_t *nua = nh->nh_nua; nua_dialog_usage_t *usage = sr->sr_usage; int initial = sr->sr_initial; int status = sr->sr_status; char const *phrase = sr->sr_phrase; int terminated; int handle_can_be_terminated = initial && !sr->sr_event; if (sr->sr_application) { /* There was an error sending response */ if (sr->sr_application != sr->sr_status) nua_stack_event(nua, nh, NULL, nua_i_error, status, phrase, tags); sr->sr_application = 0; } else if (status < 300 && !sr->sr_event) { msg_t *msg = msg_ref(sr->sr_request.msg); nua_event_t e = (enum nua_event_e)sr->sr_methods->sm_event; sr->sr_event = 1; nua_stack_event(nua, nh, msg, e, status, phrase, tags); } if (status < 200) return 0; /* sr lives on until final response is sent */ if (sr->sr_method == sip_method_invite && status < 300) return 0; /* INVITE lives on until ACK is received */ if (initial && 300 <= status) terminated = 1; else terminated = sip_response_terminates_dialog(status, sr->sr_method, NULL); if (sr->sr_terminating & !terminated) terminated = 1; if (usage && terminated) nua_dialog_usage_remove(nh, nh->nh_ds, usage, NULL, sr); nua_server_request_destroy(sr); if (!terminated) return 1; if (!initial) { if (terminated > 0) return 2; /* Remove all usages of the dialog */ nua_dialog_deinit(nh, nh->nh_ds); return 3; } else if (!handle_can_be_terminated) { return 3; } else { if (nh != nh->nh_nua->nua_dhandle) nh_destroy(nh->nh_nua, nh); return 4; } } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/nua_server.h000066400000000000000000000141531223300710500226630ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2006 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef NUA_SERVER_H /** Defined when has been included. */ #define NUA_SERVER_H /**@IFILE nua_server.h * @brief Dialog and dialog usage handling * * @author Pekka Pessi * @author Kai Vehmanen * * @date Created: Wed Mar 8 11:38:18 EET 2006 ppessi */ #include #ifndef NTA_H #include #endif typedef struct { sip_method_t sm_method; char const *sm_method_name; int sm_event; struct { unsigned create_dialog:1, in_dialog:1, target_refresh:1, add_contact:1; unsigned :0; } sm_flags; /** Initialize server-side request. */ int (*sm_init)(nua_server_request_t *sr); /** Preprocess server-side request (after handle has been created). */ int (*sm_preprocess)(nua_server_request_t *sr); /** Update server-side request parameters */ int (*sm_params)(nua_server_request_t *sr, tagi_t const *tags); /** Respond to server-side request. */ int (*sm_respond)(nua_server_request_t *sr, tagi_t const *tags); /** Report server-side request to application. */ int (*sm_report)(nua_server_request_t *sr, tagi_t const *tags); } nua_server_methods_t; /* Server side transaction */ struct nua_server_request { struct nua_server_request *sr_next, **sr_prev; nua_server_methods_t const *sr_methods; nua_owner_t *sr_owner; /**< Backpointer to handle */ nua_dialog_usage_t *sr_usage; /**< Backpointer to usage */ nta_incoming_t *sr_irq; /**< Server transaction object */ struct { msg_t *msg; /**< Request message */ sip_t const *sip; /**< Headers in request message */ } sr_request; struct { msg_t *msg; /**< Response message */ sip_t *sip; /**< Headers in response message */ } sr_response; sip_method_t sr_method; /**< Request method */ int sr_application; /**< Status by application */ int sr_status; /**< Status code */ char const *sr_phrase; /**< Status phrase */ unsigned sr_event:1; /**< Reported to application */ unsigned sr_initial:1; /**< Handle was created by this request */ unsigned sr_add_contact:1; /**< Add Contact header to the response */ unsigned sr_target_refresh:1; /**< Refresh target */ unsigned sr_terminating:1; /**< Terminate usage after final response */ unsigned sr_gracefully:1; /**< Terminate usage gracefully */ unsigned sr_neutral:1; /**< No effect on session or other usage */ /* Flags used with 100rel */ unsigned sr_100rel:1, sr_pracked:1; /* Flags used with offer-answer */ unsigned sr_offer_recv:1; /**< We have received an offer */ unsigned sr_answer_sent:2; /**< We have answered (reliably, if >1) */ unsigned sr_offer_sent:2; /**< We have offered SDP (reliably, if >1) */ unsigned sr_answer_recv:1; /**< We have received SDP answer */ unsigned :0; char const *sr_sdp; /**< SDP received from client */ size_t sr_sdp_len; /**< SDP length */ /**< Save 200 OK nua_respond() signal until PRACK has been received */ nua_saved_signal_t sr_signal[1]; }; #define SR_STATUS(sr, status, phrase) \ ((sr)->sr_phrase = (phrase), (sr)->sr_status = (status)) #define SR_STATUS1(sr, statusphrase) \ sr_status(sr, statusphrase) #define SR_HAS_SAVED_SIGNAL(sr) ((sr)->sr_signal[0] != NULL) su_inline int sr_status(nua_server_request_t *sr, int status, char const *phrase) { return (void)(sr->sr_phrase = phrase), (sr->sr_status = status); } extern nua_server_methods_t const nua_extension_server_methods, nua_invite_server_methods, /**< INVITE */ nua_bye_server_methods, /**< BYE */ nua_options_server_methods, /**< OPTIONS */ nua_register_server_methods, /**< REGISTER */ nua_info_server_methods, /**< INFO */ nua_prack_server_methods, /**< PRACK */ nua_update_server_methods, /**< UPDATE */ nua_message_server_methods, /**< MESSAGE */ nua_subscribe_server_methods, /**< SUBSCRIBE */ nua_notify_server_methods, /**< NOTIFY */ nua_refer_server_methods, /**< REFER */ nua_publish_server_methods; /**< PUBLISH */ /** Return true if we have not sent final response to request */ su_inline int nua_server_request_is_pending(nua_server_request_t const *sr) { return sr && sr->sr_response.msg; } su_inline int nua_server_request_status(nua_server_request_t const *sr) { return sr ? nta_incoming_status(sr->sr_irq) : 500; } void nua_server_request_destroy(nua_server_request_t *sr); int nua_base_server_init(nua_server_request_t *sr); #define nua_base_server_init NULL int nua_base_server_preprocess(nua_server_request_t *sr); #define nua_base_server_preprocess NULL int nua_server_params(nua_server_request_t *sr, tagi_t const *tags); int nua_base_server_params(nua_server_request_t *sr, tagi_t const *tags); #define nua_base_server_params NULL int nua_server_trespond(nua_server_request_t *sr, tag_type_t tag, tag_value_t value, ...); int nua_server_respond(nua_server_request_t *sr, tagi_t const *tags); int nua_base_server_trespond(nua_server_request_t *sr, tag_type_t tag, tag_value_t value, ...); int nua_base_server_respond(nua_server_request_t *sr, tagi_t const *tags); int nua_server_report(nua_server_request_t *sr); int nua_base_server_treport(nua_server_request_t *sr, tag_type_t tag, tag_value_t value, ...); int nua_base_server_report(nua_server_request_t *sr, tagi_t const *tags); #endif /* NUA_SERVER_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/nua_session.c000066400000000000000000004351701223300710500230410ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2006 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE nua_session.c * @brief SIP session handling * * @author Pekka Pessi * * @date Created: Wed Mar 8 16:17:27 EET 2006 ppessi */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #define NTA_INCOMING_MAGIC_T struct nua_server_request #define NTA_OUTGOING_MAGIC_T struct nua_client_request #define NTA_RELIABLE_MAGIC_T struct nua_server_request #include "nua_stack.h" #include #ifndef SDP_H typedef struct sdp_session_s sdp_session_t; #endif /* ---------------------------------------------------------------------- */ /** @enum nua_callstate The states for SIP session established with INVITE. Initially the call states follow the state of the INVITE transaction. If the initial INVITE transaction fails, the call is terminated. The status codes 401 and 407 are an exception: if the client (on the left side in the diagram below) receives them, it enters in #nua_callstate_authenticating state. If a re-INVITE transaction fails, the result depends on the status code in failure. The call can return to the ready state, be terminated immediately, or be terminated gracefully. The proper action to take is determined with sip_response_terminates_dialog(). @sa @ref nua_call_model, #nua_i_state, nua_invite(), #nua_i_invite @par Session State Diagram @code +----------+ | |---------------------+ | Init | | | |----------+ | +----------+ | | | | | | --/INVITE| |INVITE/100 | | V V | | +----------+ +----------+ | | +--------| | | | | | | 18X +-| Calling | | Received | |INVITE/ | | /- | | | | | | /18X | | V +----------+ +----------+ V | | +----------+ | | | +----------+ | |---| | |2XX -/ | -/ | | | | | | Proceed- | | /- 2XX| 18X| | Early | |INVITE/ | | ing | | | +->| | | /200 | +----------+ V V +----------+ | | | +----------+ +----------+ | -/ | | 2XX| | | | |<--+ 2XX | | /-| | Complet- | | Complete |<-----------+ | +->| ing | | |------+ | +----------+ +----------+ | | | | | | |401,407/ -/ACK| |ACK/- |timeout/ | | /ACK V V | /BYE | | +----------+ | | | | | | | | +--| Ready | | | | | | | | | | | +----------+ | | | | | | | | BYE/ | |-/BYE | |BYE/ V /200 | V | |/200 +----------+ | +----------+ | | | | | | | | | |Authentic-| | | Terminat-|<----+ | | ating | | | ing | | +----------+ | +----------+ | | | | | |[23456]XX/- | | V | | +----------+ | | | | | +->|Terminated|<--------------+ | | +----------+ | V +----------+ | | | Init | | | +----------+ @endcode */ /* ---------------------------------------------------------------------- */ /* Session event usage */ /** @internal @brief Session-related state. */ typedef struct nua_session_usage { enum nua_callstate ss_state; /**< Session status (enum nua_callstate) */ unsigned ss_100rel:1; /**< Use 100rel, send 183 */ unsigned ss_alerting:1; /**< 180 is sent/received */ unsigned ss_update_needed:2; /**< Send an UPDATE (do O/A if > 1) */ unsigned ss_precondition:1; /**< Precondition required */ unsigned ss_reporting:1; /**< True if reporting state */ unsigned : 0; struct session_timer { unsigned interval; /**< Negotiated expiration time */ enum nua_session_refresher refresher; /**< Our Negotiated role */ struct { unsigned expires, defaults; /**< Value of Session-Expires (delta) */ unsigned min_se; /**< Minimum session expires */ /** none, local or remote */ enum nua_session_refresher refresher; unsigned supported:1, require:1, :0; } local, remote; unsigned timer_set:1; /**< We have active session timer. */ } ss_timer[1]; char const *ss_reason; /**< Reason for termination. */ /* Offer-Answer status */ char const *ss_oa_recv, *ss_oa_sent; /**< Version of user SDP from latest successful O/A */ int ss_sdp_version; } nua_session_usage_t; static char const Offer[] = "offer", Answer[] = "answer"; static char const *nua_session_usage_name(nua_dialog_usage_t const *du); static int nua_session_usage_add(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du); static void nua_session_usage_remove(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du, nua_client_request_t *cr, nua_server_request_t *sr); static void nua_session_usage_refresh(nua_owner_t *, nua_dialog_state_t *, nua_dialog_usage_t *, sip_time_t now); static int nua_session_usage_shutdown(nua_owner_t *, nua_dialog_state_t *, nua_dialog_usage_t *); static void signal_call_state_change(nua_handle_t *nh, nua_session_usage_t *ss, int status, char const *phrase, enum nua_callstate next_state); static int nua_invite_client_should_ack(nua_client_request_t const *cr); static int nua_invite_client_ack(nua_client_request_t *cr, tagi_t const *tags); static int nua_invite_client_complete(nua_client_request_t *cr); static nua_usage_class const nua_session_usage[1] = { { sizeof (nua_session_usage_t), sizeof nua_session_usage, nua_session_usage_add, nua_session_usage_remove, nua_session_usage_name, nua_base_usage_update_params, NULL, nua_session_usage_refresh, nua_session_usage_shutdown }}; static char const *nua_session_usage_name(nua_dialog_usage_t const *du) { return "session"; } static int nua_session_usage_add(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du) { nua_session_usage_t *ss = NUA_DIALOG_USAGE_PRIVATE(du); if (ds->ds_has_session) return -1; ds->ds_has_session = 1; ds->ds_got_session = 1; ss->ss_timer->local.refresher = nua_any_refresher; ss->ss_timer->remote.refresher = nua_any_refresher; return 0; } static void nua_session_usage_remove(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du, nua_client_request_t *cr0, nua_server_request_t *sr0) { nua_session_usage_t *ss = NUA_DIALOG_USAGE_PRIVATE(du); nua_client_request_t *cr, *cr_next; nua_server_request_t *sr; /* Destroy queued INVITE transactions */ for (cr = ds->ds_cr; cr; cr = cr_next) { cr_next = cr->cr_next; if (cr->cr_method != sip_method_invite) continue; if (cr == cr0) continue; nua_client_request_ref(cr); if (nua_invite_client_should_ack(cr)) { ss->ss_reporting = 1; nua_invite_client_ack(cr, NULL); ss->ss_reporting = 0; } if (cr == du->du_cr && cr->cr_orq) continue; if (cr->cr_status < 200) { nua_stack_event(nh->nh_nua, nh, NULL, (enum nua_event_e)cr->cr_event, SIP_481_NO_TRANSACTION, NULL); } nua_client_request_remove(cr); nua_client_request_unref(cr); cr_next = ds->ds_cr; } if (ss->ss_state != nua_callstate_terminated && ss->ss_state != nua_callstate_init && !ss->ss_reporting) { int status = 0; char const *phrase = "Terminated"; if (cr0) status = cr0->cr_status, phrase = cr0->cr_phrase ? cr0->cr_phrase : phrase; else if (sr0) status = sr0->sr_status, phrase = sr0->sr_phrase; signal_call_state_change(nh, ss, status, phrase, nua_callstate_terminated); } /* Application can respond to BYE after the session usage has terminated */ for (sr = ds->ds_sr; sr; sr = sr->sr_next) { if (sr->sr_usage == du && sr->sr_method == sip_method_bye) sr->sr_usage = NULL; } ds->ds_has_session = 0; nh->nh_has_invite = 0; nh->nh_active_call = 0; nh->nh_hold_remote = 0; if (nh->nh_soa) soa_destroy(nh->nh_soa), nh->nh_soa = NULL; } static nua_dialog_usage_t *nua_dialog_usage_for_session(nua_dialog_state_t const *ds) { if (ds == ((nua_handle_t *)NULL)->nh_ds) return NULL; return nua_dialog_usage_get(ds, nua_session_usage, NULL); } static nua_session_usage_t *nua_session_usage_for_dialog(nua_dialog_state_t const *ds) { nua_dialog_usage_t *du; if (ds == ((nua_handle_t *)NULL)->nh_ds) return NULL; du = nua_dialog_usage_get(ds, nua_session_usage, NULL); return (nua_session_usage_t *)nua_dialog_usage_private(du); } /** Zap the session associated with the handle */ static void nua_session_usage_destroy(nua_handle_t *nh, nua_session_usage_t *ss) { /* Remove usage */ nua_dialog_usage_remove(nh, nh->nh_ds, nua_dialog_usage_public(ss), NULL, NULL); SU_DEBUG_5(("nua: terminated session %p\n", (void *)nh)); } /* ======================================================================== */ /* INVITE and call (session) processing */ static int session_timer_is_supported(struct session_timer const *t); static void session_timer_preferences(struct session_timer *t, sip_t const *sip, sip_supported_t const *supported, unsigned expires, int isset, enum nua_session_refresher refresher, unsigned min_se); static void session_timer_store(struct session_timer *t, sip_t const *sip); static int session_timer_check_min_se(msg_t *msg, sip_t *sip, sip_t const *request, unsigned long min_se); static int session_timer_add_headers(struct session_timer *t, int initial, msg_t *msg, sip_t *sip); static void session_timer_negotiate(struct session_timer *t, int uas); static void session_timer_set(nua_session_usage_t *ss, int uas); static int session_timer_check_restart(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip); static int nh_referral_check(nua_handle_t *nh, tagi_t const *tags); static void nh_referral_respond(nua_handle_t *, int status, char const *phrase); static int session_get_description(sip_t const *sip, char const **return_sdp, size_t *return_len); static int session_include_description(soa_session_t *soa, int session, msg_t *msg, sip_t *sip); static int session_make_description(su_home_t *home, soa_session_t *soa, int session, sip_content_disposition_t **return_cd, sip_content_type_t **return_ct, sip_payload_t **return_pl); static int nua_server_retry_after(nua_server_request_t *sr, int status, char const *phrase, int min, int max); /**@fn void nua_invite(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * * Place a call using SIP @b INVITE method. * * The INVITE method is used to initiate a call between two parties. The * call is also known as SIP session. * * At SIP level the session is represented as @e Dialog, which is a * peer-to-peer association between two SIP User-Agents. The dialog is * established by a successful 2XX response to the INVITE. The dialog is * terminated by BYE transaction, which application can initiate with * nua_bye() call. * * An @e early @e dialog is established by an preliminary response * (101..199), such as 180 Ringing. An early dialog is terminated * with an error response with response code in range 300...699. * * The media session belonging to the SIP session is usually represented by * SDP, Session Description Protocol. The media session it is usually * established during the call set-up with procedure known as SDP * Offer/Answer exchange, defined by @RFC3264. See Media Session * Handling below for details. * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Events: * #nua_r_invite \n * #nua_i_state (#nua_i_active, #nua_i_terminated) \n * #nua_i_media_error \n * #nua_i_fork \n * * @par Tags: * NUTAG_AUTH_CACHE() \n * NUTAG_AUTOACK() \n * NUTAG_AUTOANSWER() \n * NUTAG_EARLY_MEDIA() \n * NUTAG_ENABLEINVITE() \n * NUTAG_INITIAL_ROUTE(), NUTAG_INITIAL_ROUTE_STR() \n * NUTAG_INVITE_TIMER() \n * NUTAG_MEDIA_ENABLE() \n * NUTAG_MEDIA_FEATURES() \n * NUTAG_MIN_SE() \n * NUTAG_RETRY_COUNT() \n * NUTAG_SERVICE_ROUTE_ENABLE() \n * NUTAG_SESSION_REFRESHER() \n * NUTAG_SESSION_TIMER() \n * NUTAG_SOA_NAME() \n * NUTAG_UPDATE_REFRESH() \n * * @par Populating SIP Request Message with Tagged Arguments * The tagged arguments can be used to pass values for any SIP headers to * the stack. When the INVITE message (or any other SIP message) is created, * the tagged values saved with nua_handle() are used first, next the tagged * values given with the operation (nua_invite()) are added. * * @par * When multiple tags for the same header are specified, the behaviour * depends on the header type. If only a single header field can be included * in a SIP message, the latest non-NULL value is used, e.g., @Subject. * However, if the SIP header can consist of multiple lines or header fields * separated by comma, e.g., @Accept, all the tagged * values are concatenated. * * @par * However, if a tag value is #SIP_NONE (-1 casted as a void pointer), the * values from previous tags are ignored. * * @par * Next, values previously set with nua_set_params() or nua_set_hparams() * are used: @Allow, @Supported, @Organization, and @UserAgent headers are * added to the request if they are not already set. * * @par * Now, the target URI for the request needs to be determined. * * @par * For initial INVITE requests, values from tags are used. If NUTAG_URL() is * given, it is used as target URI. Otherwise, if SIPTAG_TO() is given, it * is used as target URI. If neither is given, the complete request line * already specified using SIPTAG_REQUEST() or SIPTAG_REQUEST_STR() is used. * If none of the tags above are given, an internal error is returned to the * application. At this point, the target URI is stored in the request line, * together with method name ("INVITE") and protocol version ("SIP/2.0"). * The initial dialog information is also created: @CallID, @CSeq headers * are generated, if they do not exist, and an unique tag is added to @From * header. * * @par * For the initial INVITE requests, the @Route headers specified by * SIPTAG_ROUTE()/SIPTAG_ROUTER_STR() tags in nua_handle() and nua_invite() * calls are inserted to the request. Next the initial route set specified * by NUTAG_INITIAL_ROUTE()/NUTAG_INITIAL_ROUTE_STR() tags is prepended to * the route. Finally (unless NUTAG_SERVICE_ROUTE_ENABLE(0) is used) the * @ServiceRoute set received from the registrar is also appended to the * route set of the initial request message. * * @par * Next, the stack generates a @Contact header for the request (Unless the * application already gave a @Contact header or it does not want to use * @Contact and indicates that by including SIPTAG_CONTACT(NULL) or * SIPTAG_CONTACT(SIP_NONE) in the tagged parameters.) If the application * has a registration active, the @Contact header used with registration is * used. Otherwise, the @Contact header is generated from the local IP * address and port number, taking also the values from NUTAG_M_DISPLAY(), * NUTAG_M_FEATURES(), NUTAG_M_PARAMS(), and NUTAG_M_USERNAME(). * * @par * For in-dialog INVITE (re-INVITE), the request URI is taken from the * @Contact header received from the remote party during the dialog * establishment. Also, the @CallID and @CSeq headers and @From and @To tags * are generated based on the dialog information and added to the request. * If the dialog has a route (set by @RecordRoute headers), it is added to * the request, too. * * @par * @MaxForwards header (with default value set by NTATAG_MAX_FORWARDS()) is * also added now, if it does not exist. * * @par * The INVITE request message created by nua_invite() operation is saved as * a template for automatic re-INVITE requests sent by the session timer * ("timer") feature (see NUTAG_SESSION_TIMER() for more details). Please * note that the template message is not used when ACK, PRACK, UPDATE or * INFO requests are created (however, these requests will include * dialog-specific headers like @To, @From, and @CallID as well as * preference headers @Allow, @Supported, @UserAgent, @Organization). * * @par Tags Related to SIP Headers and Request-URI * NUTAG_URL(), SIPTAG_REQUEST(), SIPTAG_REQUEST_STR() \n * NUTAG_INITIAL_ROUTE(), NUTAG_INITIAL_ROUTE_STR(), * SIPTAG_ROUTE(), SIPTAG_ROUTE_STR(), * NUTAG_SERVICE_ROUTE_ENABLE() \n * SIPTAG_MAX_FORWARDS(), SIPTAG_MAX_FORWARDS_STR() \n * SIPTAG_PROXY_REQUIRE(), SIPTAG_PROXY_REQUIRE_STR() \n * SIPTAG_FROM(), SIPTAG_FROM_STR() \n * SIPTAG_TO(), SIPTAG_TO_STR() \n * SIPTAG_CALL_ID(), SIPTAG_CALL_ID_STR() \n * SIPTAG_CSEQ(), SIPTAG_CSEQ_STR() * (note that @CSeq value is incremented if request gets retried)\n * SIPTAG_CONTACT(), SIPTAG_CONTACT_STR() \n * SIPTAG_REQUEST_DISPOSITION(), SIPTAG_REQUEST_DISPOSITION_STR() \n * SIPTAG_ACCEPT_CONTACT(), SIPTAG_ACCEPT_CONTACT_STR() \n * SIPTAG_REJECT_CONTACT(), SIPTAG_REJECT_CONTACT_STR() \n * SIPTAG_EXPIRES(), SIPTAG_EXPIRES_STR() \n * SIPTAG_DATE(), SIPTAG_DATE_STR() \n * SIPTAG_TIMESTAMP(), SIPTAG_TIMESTAMP_STR() \n * SIPTAG_SUBJECT(), SIPTAG_SUBJECT_STR() \n * SIPTAG_PRIORITY(), SIPTAG_PRIORITY_STR() \n * SIPTAG_CALL_INFO(), SIPTAG_CALL_INFO_STR() \n * SIPTAG_ORGANIZATION(), SIPTAG_ORGANIZATION_STR() \n * NUTAG_USER_AGENT(), SIPTAG_USER_AGENT() and SIPTAG_USER_AGENT_STR() \n * SIPTAG_IN_REPLY_TO(), SIPTAG_IN_REPLY_TO_STR() \n * SIPTAG_ACCEPT(), SIPTAG_ACCEPT_STR() \n * SIPTAG_ACCEPT_ENCODING(), SIPTAG_ACCEPT_ENCODING_STR() \n * SIPTAG_ACCEPT_LANGUAGE(), SIPTAG_ACCEPT_LANGUAGE_STR() \n * NUTAG_ALLOW(), SIPTAG_ALLOW(), and SIPTAG_ALLOW_STR() \n * NUTAG_EARLY_MEDIA(), SIPTAG_REQUIRE(), and SIPTAG_REQUIRE_STR() \n * NUTAG_SUPPORTED(), SIPTAG_SUPPORTED(), and SIPTAG_SUPPORTED_STR() \n * SIPTAG_ALLOW_EVENTS(), SIPTAG_ALLOW_EVENTS_STR() \n * SIPTAG_PROXY_AUTHORIZATION(), SIPTAG_PROXY_AUTHORIZATION_STR() \n * SIPTAG_AUTHORIZATION(), SIPTAG_AUTHORIZATION_STR() \n * SIPTAG_REFERRED_BY(), SIPTAG_REFERRED_BY_STR() \n * SIPTAG_REPLACES(), SIPTAG_REPLACES_STR() \n * NUTAG_SESSION_TIMER(), NUTAG_SESSION_REFRESHER(), * SIPTAG_SESSION_EXPIRES(), SIPTAG_SESSION_EXPIRES_STR() \n * NUTAG_MIN_SE(), SIPTAG_MIN_SE(), SIPTAG_MIN_SE_STR() \n * SIPTAG_SECURITY_CLIENT(), SIPTAG_SECURITY_CLIENT_STR() \n * SIPTAG_SECURITY_VERIFY(), SIPTAG_SECURITY_VERIFY_STR() \n * SIPTAG_PRIVACY(), SIPTAG_PRIVACY_STR() \n * SIPTAG_MIME_VERSION(), SIPTAG_MIME_VERSION_STR() \n * SIPTAG_CONTENT_TYPE(), SIPTAG_CONTENT_TYPE_STR() \n * SIPTAG_CONTENT_ENCODING(), SIPTAG_CONTENT_ENCODING_STR() \n * SIPTAG_CONTENT_LANGUAGE(), SIPTAG_CONTENT_LANGUAGE_STR() \n * SIPTAG_CONTENT_DISPOSITION(), SIPTAG_CONTENT_DISPOSITION_STR() \n * SIPTAG_HEADER(), SIPTAG_HEADER_STR() \n * SIPTAG_PAYLOAD(), SIPTAG_PAYLOAD_STR() \n * * @par SDP Handling * By default the nua_invite() uses an @ref soa_session_t "SOA media * session" object to take care of the Offer/Answer exchange. The SOA can * be disabled with tag NUTAG_MEDIA_ENABLE(0). * * @par * The SDP description of the * @ref soa_session_t "soa media session" is included in the INVITE request * as a message body. * The SDP in the message body of the 1XX or 2XX response message is * interpreted as an answer, given to the @ref soa_session_t "soa media * session" object for processing. * * @bug If the INVITE request already contains a message body, SDP is not * added. Also, if the response contains a multipart body, it is not parsed. * * @par Tags Related to SDP Management and Offer/Answer Model: * NUTAG_MEDIA_ENABLE(), \n * NUTAG_INCLUDE_EXTRA_SDP(), \n * SOATAG_HOLD(), SOATAG_AF(), SOATAG_ADDRESS(), * SOATAG_ORDERED_USER(), SOATAG_REUSE_REJECTED(), * SOATAG_RTP_SELECT(), SOATAG_RTP_SORT(), SOATAG_RTP_MISMATCH(), * SOATAG_AUDIO_AUX(), \n * SOATAG_USER_SDP() or SOATAG_USER_SDP_STR() \n * * @par Alternative Call Models * In addition to the basic SIP call model described in @RFC3261 and * @RFC3264, the early media model described in @RFC3262 is available. The * use of 100rel and early media can be use can be forced with * NUTAG_EARLY_MEDIA(1). * * Also, the "precondition" call model described in @RFC3312 is supported at * SIP level, that is, the SIP PRACK and UPDATE requests are sent if * "precondition" is added to the @Require header in the INVITE request. * * Optionally * - uses early media if NUTAG_EARLY_MEDIA() tag is used with non zero-value * - media parameters can be set by SOA tags * - nua_invite() can be used to change status of an existing call: * - #SOATAG_HOLD tag can be used to list the media that will be put on hold, * the value "*" sets all the media beloginging to the session on hold * * @par Authentication * The INVITE request may need authentication. Each proxy or server * requiring authentication can respond with 401 or 407 response. The * nua_authenticate() operation stores authentication information (username * and password) to the handle, and stack tries to authenticate all the rest * of the requests (e.g., PRACK, ACK, UPDATE, re-INVITE, BYE) using the * stored username and password. * * @sa @ref nua_call_model, #nua_r_invite, #nua_i_state, \n * nua_handle_has_active_call() \n * nua_handle_has_call_on_hold()\n * nua_handle_has_invite() \n * nua_authenticate() \n * nua_prack() \n * nua_update() \n * nua_info() \n * nua_cancel() \n * nua_bye() \n * #nua_i_invite, nua_respond() */ /* Tags not implemented * NUTAG_REFER_PAUSE() \n */ static int nua_invite_client_init(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags); static int nua_invite_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags); static int nua_invite_client_preliminary(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip); static int nua_invite_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip); static int nua_session_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip); static int nua_invite_client_report(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip, nta_outgoing_t *orq, tagi_t const *tags); nua_client_methods_t const nua_invite_client_methods = { SIP_METHOD_INVITE, /* crm_method, crm_method_name */ 0, /* crm_extra */ { /* crm_flags */ /* create_dialog */ 1, /* in_dialog */ 1, /* target refresh */ 1 }, NULL, /* crm_template */ nua_invite_client_init, /* crm_init */ nua_invite_client_request, /* crm_send */ session_timer_check_restart, /* crm_check_restart */ nua_invite_client_response, /* crm_recv */ nua_invite_client_preliminary, /* crm_preliminary */ nua_invite_client_report, /* crm_report */ nua_invite_client_complete, /* crm_complete */ }; extern nua_client_methods_t const nua_bye_client_methods; extern nua_client_methods_t const nua_cancel_client_methods; extern nua_client_methods_t const nua_update_client_methods; extern nua_client_methods_t const nua_prack_client_methods; int nua_stack_invite(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { return nua_client_create(nh, e, &nua_invite_client_methods, tags); } static int nua_invite_client_init(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du; nua_session_usage_t *ss; cr->cr_usage = du = nua_dialog_usage_for_session(nh->nh_ds); /* Errors returned by nua_invite_client_init() do not change the session state */ cr->cr_neutral = 1; if (nh_is_special(nh) || nua_stack_set_handle_special(nh, nh_has_invite, nua_i_error)) return nua_client_return(cr, 900, "Invalid handle for INVITE", msg); else if (nh_referral_check(nh, tags) < 0) return nua_client_return(cr, 900, "Invalid referral", msg); if (du) { nua_server_request_t *sr; for (sr = nh->nh_ds->ds_sr; sr; sr = sr->sr_next) /* INVITE in progress? */ if (sr->sr_usage == du && sr->sr_method == sip_method_invite && nua_server_request_is_pending(sr)) return nua_client_return(cr, SIP_491_REQUEST_PENDING, msg); cr->cr_initial = 0; } else { du = nua_dialog_usage_add(nh, nh->nh_ds, nua_session_usage, NULL); cr->cr_initial = 1; } if (!du) return -1; ss = nua_dialog_usage_private(du); if (ss->ss_state >= nua_callstate_terminating) return nua_client_return(cr, 900, "Session is terminating", msg); if (nua_client_bind(cr, du) < 0) return nua_client_return(cr, 900, "INVITE already in progress", msg); cr->cr_neutral = 0; session_timer_preferences(ss->ss_timer, sip, NH_PGET(nh, supported), NH_PGET(nh, session_timer), NUA_PISSET(nh->nh_nua, nh, session_timer), NH_PGET(nh, refresher), NH_PGET(nh, min_se)); return 0; } static int nua_invite_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = cr->cr_usage; nua_session_usage_t *ss; int offer_sent = 0, retval; sip_time_t invite_timeout; if (du == NULL) /* Call terminated */ return nua_client_return(cr, SIP_481_NO_TRANSACTION, msg); ss = NUA_DIALOG_USAGE_PRIVATE(du); if (ss->ss_state >= nua_callstate_terminating) return nua_client_return(cr, 900, "Session is terminating", msg); invite_timeout = NH_PGET(nh, invite_timeout); if (invite_timeout == 0) invite_timeout = UINT_MAX; /* Send CANCEL if we don't get response within timeout*/ /* nua_dialog_usage_set_expires(du, invite_timeout); Xyzzy */ nua_dialog_usage_reset_refresh(du); /* Add session timer headers */ if (session_timer_is_supported(ss->ss_timer)) session_timer_add_headers(ss->ss_timer, ss->ss_state == nua_callstate_init, msg, sip); ss->ss_100rel = NH_PGET(nh, early_media); ss->ss_precondition = sip_has_feature(sip->sip_require, "precondition"); if (ss->ss_precondition) ss->ss_update_needed = ss->ss_100rel = 1; if (nh->nh_soa) { soa_init_offer_answer(nh->nh_soa); if (soa_is_delayed_offer(nh->nh_soa)) offer_sent = 0; else if (sip->sip_payload) /* Kludge, we should probably use multipart */ offer_sent = 0; else if (soa_generate_offer(nh->nh_soa, 0, NULL) < 0) return -1; else offer_sent = 1; if (offer_sent > 0 && session_include_description(nh->nh_soa, 1, msg, sip) < 0) return nua_client_return(cr, 900, "Internal media error", msg); if (NH_PGET(nh, media_features) && !nua_dialog_is_established(nh->nh_ds) && !sip->sip_accept_contact && !sip->sip_reject_contact) { sip_accept_contact_t ac[1]; sip_accept_contact_init(ac); ac->cp_params = (msg_param_t *) soa_media_features(nh->nh_soa, 1, msg_home(msg)); if (ac->cp_params) { msg_header_replace_param(msg_home(msg), ac->cp_common, "explicit"); sip_add_dup(msg, sip, (sip_header_t *)ac); } } } else { offer_sent = session_get_description(sip, NULL, NULL); } retval = nua_base_client_trequest(cr, msg, sip, NTATAG_REL100(ss->ss_100rel), TAG_NEXT(tags)); if (retval == 0) { if ((cr->cr_offer_sent = offer_sent)) ss->ss_oa_sent = Offer; if (!cr->cr_restarting) /* Restart logic calls nua_invite_client_report */ signal_call_state_change(nh, ss, 0, "INVITE sent", nua_callstate_calling); } return retval; } static int nua_invite_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip) { nua_dialog_usage_t *du = cr->cr_usage; nua_session_usage_t *ss = nua_dialog_usage_private(du); int uas; if (ss == NULL || sip == NULL) { /* Xyzzy */ } else if (status < 300) { du->du_ready = 1; if (session_timer_is_supported(ss->ss_timer)) session_timer_store(ss->ss_timer, sip); session_timer_set(ss, uas = 0); } return nua_session_client_response(cr, status, phrase, sip); } static int nua_invite_client_preliminary(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = cr->cr_usage; nua_session_usage_t *ss = nua_dialog_usage_private(du); assert(sip); if (ss && sip && sip->sip_rseq) { /* Handle 100rel responses */ sip_rseq_t *rseq = sip->sip_rseq; /* Establish early dialog - we should fork here */ if (!nua_dialog_is_established(nh->nh_ds)) { nta_outgoing_t *tagged; nua_dialog_uac_route(nh, nh->nh_ds, sip, 1, 1); nua_dialog_store_peer_info(nh, nh->nh_ds, sip); /* Tag the INVITE request */ tagged = nta_outgoing_tagged(cr->cr_orq, nua_client_orq_response, cr, sip->sip_to->a_tag, sip->sip_rseq); if (tagged) { nta_outgoing_destroy(cr->cr_orq), cr->cr_orq = tagged; } else { cr->cr_graceful = 1; ss->ss_reason = "SIP;cause=500;text=\"Cannot Create Early Dialog\""; } } if (!rseq) { SU_DEBUG_5(("nua(%p): 100rel missing RSeq\n", (void *)nh)); } else if (nta_outgoing_rseq(cr->cr_orq) > rseq->rs_response) { SU_DEBUG_5(("nua(%p): 100rel bad RSeq %u (got %u)\n", (void *)nh, (unsigned)rseq->rs_response, nta_outgoing_rseq(cr->cr_orq))); return 1; /* Do not send event */ } else if (nta_outgoing_setrseq(cr->cr_orq, rseq->rs_response) < 0) { SU_DEBUG_1(("nua(%p): cannot set RSeq %u\n", (void *)nh, (unsigned)rseq->rs_response)); cr->cr_graceful = 1; ss->ss_reason = "SIP;cause=400;text=\"Bad RSeq\""; } } return nua_session_client_response(cr, status, phrase, sip); } /** Process response to a session request (INVITE, PRACK, UPDATE) */ static int nua_session_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = cr->cr_usage; nua_session_usage_t *ss = nua_dialog_usage_private(du); char const *sdp = NULL; size_t len; char const *received = NULL; #define LOG3(m) \ SU_DEBUG_3(("nua(%p): %s: %s %s in %u %s\n", \ (void *)nh, cr->cr_method_name, (m), \ received ? received : "SDP", status, phrase)) #define LOG5(m) \ SU_DEBUG_5(("nua(%p): %s: %s %s in %u %s\n", \ (void *)nh, cr->cr_method_name, (m), received, status, phrase)) if (!ss || 300 <= status || !session_get_description(sip, &sdp, &len)) return nua_base_client_response(cr, status, phrase, sip, NULL); if (cr->cr_offer_sent) { /* case 1: answer to our offer? */ int new_answer, previous_answer = cr->cr_answer_recv; cr->cr_answer_recv = status; received = Answer; if (nh->nh_soa == NULL) { LOG5("got SDP"); goto response; } if (previous_answer && status < 200) { /* Ignore extra answers in unreliable provisional responses */ LOG5("ignoring extra"); sdp = NULL; received = NULL; goto response; } new_answer = soa_set_remote_sdp(nh->nh_soa, NULL, sdp, len); if (new_answer < 0) { LOG3("error parsing SDP"); sdp = NULL; cr->cr_graceful = 1; ss->ss_reason = "SIP;cause=400;text=\"Malformed Session Description\""; goto response; } if (previous_answer) { if (!new_answer) { /* Ignore duplicate answers */ LOG5("ignoring duplicate"); sdp = NULL; received = NULL; goto response; } else { if (soa_init_offer_answer(nh->nh_soa) < 0 || soa_generate_offer(nh->nh_soa, 1, NULL) < 0 || soa_set_remote_sdp(nh->nh_soa, NULL, sdp, len) < 0) { LOG5("error reinitializing session"); sdp = NULL; goto response; } } } if (soa_process_answer(nh->nh_soa, NULL) < 0) { LOG5("error processing SDP"); /* XXX */ sdp = NULL; } else if (soa_activate(nh->nh_soa, NULL) < 0) { /* XXX - what about errors? */ LOG3("error activating media after"); } else { ss->ss_sdp_version = soa_get_user_version(nh->nh_soa); LOG5("processed SDP"); } } else if (cr->cr_method != sip_method_invite) { /* If non-invite request did not have offer, ignore SDP in response */ LOG3("ignoring extra"); sdp = NULL; } else { /* case 2: new offer */ cr->cr_offer_recv = 1, cr->cr_answer_sent = 0; received = Offer; if (nh->nh_soa && soa_set_remote_sdp(nh->nh_soa, NULL, sdp, len) < 0) { LOG3("error parsing SDP"); sdp = NULL; cr->cr_graceful = 1; ss->ss_reason = "SIP;cause=400;text=\"Malformed Session Description\""; } else LOG5("got SDP"); } response: if (received) ss->ss_oa_recv = received; if (sdp && nh->nh_soa) return nua_base_client_tresponse(cr, status, phrase, sip, NH_REMOTE_MEDIA_TAGS(1, nh->nh_soa), TAG_END()); else return nua_base_client_response(cr, status, phrase, sip, NULL); } static int nua_invite_client_report(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip, nta_outgoing_t *orq, tagi_t const *tags) { nua_handle_t *nh = cr->cr_owner; nua_dialog_state_t *ds = nh->nh_ds; nua_dialog_usage_t *du = cr->cr_usage; nua_session_usage_t *ss = nua_dialog_usage_private(du); msg_t *response = nta_outgoing_getresponse(orq); unsigned next_state; int error; nh_referral_respond(nh, status, phrase); /* XXX - restarting after 401/407 */ nua_stack_event(nh->nh_nua, nh, response, (enum nua_event_e)cr->cr_event, status, phrase, tags); if (cr->cr_waiting) /* Do not report call state change if waiting for restart */ return 1; if (ss == NULL) { signal_call_state_change(nh, ss, status, phrase, nua_callstate_terminated); return 1; } ss->ss_reporting = 1; if (cr->cr_neutral) { signal_call_state_change(nh, ss, status, phrase, ss->ss_state); ss->ss_reporting = 0; return 1; } response = msg_ref(response); /* Keep reference to contents of sip */ if (orq != cr->cr_orq && cr->cr_orq) { /* Being restarted */ next_state = nua_callstate_calling; } else if (status == 100) { next_state = nua_callstate_calling; } else if (status < 300 && cr->cr_graceful) { next_state = nua_callstate_terminating; if (200 <= status) { nua_invite_client_ack(cr, NULL); } } else if (status < 200) { next_state = nua_callstate_proceeding; if (sip && sip->sip_rseq && !SIP_IS_ALLOWED(NH_PGET(nh, appl_method), sip_method_prack)) { sip_rack_t rack[1]; sip_rack_init(rack); rack->ra_response = sip->sip_rseq->rs_response; rack->ra_cseq = sip->sip_cseq->cs_seq; rack->ra_method = sip->sip_cseq->cs_method; rack->ra_method_name = sip->sip_cseq->cs_method_name; error = nua_client_tcreate(nh, nua_r_prack, &nua_prack_client_methods, SIPTAG_RACK(rack), TAG_END()); if (error < 0) { cr->cr_graceful = 1; next_state = nua_callstate_terminating; } } } else if (status < 300) { next_state = nua_callstate_completing; } else if (cr->cr_terminated) { next_state = nua_callstate_terminated; } else if (cr->cr_graceful && ss->ss_state >= nua_callstate_completing) { next_state = nua_callstate_terminating; } else { next_state = nua_callstate_init; } if (next_state == nua_callstate_calling) { if (sip && sip->sip_status && sip->sip_status->st_status == 100) { ss->ss_reporting = 0; return 1; } } if (next_state == nua_callstate_completing) { if (NH_PGET(nh, auto_ack) || /* Auto-ACK response to re-INVITE when media is enabled and auto_ack is not set to 0 on handle */ (ss->ss_state == nua_callstate_ready && nh->nh_soa && !NH_PISSET(nh, auto_ack))) { nua_client_request_t *cru; for (cru = ds->ds_cr; cru; cru = cru->cr_next) { if (cr != cru && cru->cr_offer_sent && !cru->cr_answer_recv) break; } if (cru) /* A final response to UPDATE or PRACK with answer on its way? */; else if (nua_invite_client_ack(cr, NULL) > 0) next_state = nua_callstate_ready; else next_state = nua_callstate_terminating; } } if (next_state == nua_callstate_terminating) { /* Send BYE or CANCEL */ /* XXX - Forking - send BYE to early dialog?? */ if (ss->ss_state > nua_callstate_proceeding || status >= 200) error = nua_client_create(nh, nua_r_bye, &nua_bye_client_methods, NULL); else error = nua_client_create(nh, nua_r_cancel, &nua_cancel_client_methods, tags); if (error) { next_state = nua_callstate_terminated; cr->cr_terminated = 1; } cr->cr_graceful = 0; } ss->ss_reporting = 0; signal_call_state_change(nh, ss, status, phrase, (enum nua_callstate)next_state); msg_destroy(response); return 1; } /**@fn void nua_ack(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * * Acknowledge a succesful response to INVITE request. * * Acknowledge a successful response (200..299) to INVITE request with the * SIP ACK request message. This function is needed only if NUTAG_AUTOACK() * parameter has been cleared. * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Related Tags: * Header tags defined in * * @par Events: * #nua_i_media_error \n * #nua_i_state (#nua_i_active, #nua_i_terminated) * * @sa NUTAG_AUTOACK(), @ref nua_call_model, #nua_i_state */ int nua_stack_ack(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { nua_dialog_usage_t *du = nua_dialog_usage_for_session(nh->nh_ds); nua_session_usage_t *ss = nua_dialog_usage_private(du); nua_client_request_t *cr = du ? du->du_cr : NULL; int error; if (!cr || cr->cr_orq == NULL || cr->cr_status < 200) { UA_EVENT2(nua_i_error, 900, "No response to ACK"); return 1; } if (tags) nua_stack_set_params(nua, nh, nua_i_error, tags); nua_client_request_ref(cr); error = nua_invite_client_ack(cr, tags); if (error < 0) { if (ss->ss_reason == NULL) ss->ss_reason = "SIP;cause=500;text=\"Internal Error\""; ss->ss_reporting = 1; /* We report terminated state here if BYE fails */ error = nua_client_create(nh, nua_r_bye, &nua_bye_client_methods, NULL); ss->ss_reporting = 0; signal_call_state_change(nh, ss, 500, "Internal Error", error ? nua_callstate_terminated : nua_callstate_terminating); } else if (ss) signal_call_state_change(nh, ss, 200, "ACK sent", nua_callstate_ready); nua_client_request_unref(cr); return 0; } /** Send ACK, destroy INVITE transaction. * * @retval 1 if successful * @retval < 0 if an error occurred */ static int nua_invite_client_ack(nua_client_request_t *cr, tagi_t const *tags) { nua_handle_t *nh = cr->cr_owner; nua_dialog_state_t *ds = nh->nh_ds; nua_session_usage_t *ss = nua_dialog_usage_private(cr->cr_usage); msg_t *msg; sip_t *sip; int error = -1; sip_authorization_t *wa; sip_proxy_authorization_t *pa; sip_cseq_t *cseq; int proxy_is_set; url_string_t *proxy; nta_outgoing_t *ack; int status = 200; char const *phrase = "OK", *reason = NULL; char const *invite_branch; assert(cr->cr_orq); assert(cr->cr_method == sip_method_invite); cr->cr_initial = 0; if (!ds->ds_leg) { /* XXX - fix nua_dialog_usage_remove_at() instead! */ goto error; } assert(ds->ds_leg); msg = nta_outgoing_getrequest(cr->cr_orq); sip = sip_object(msg); if (!msg) goto error; invite_branch = nta_outgoing_branch(cr->cr_orq); wa = sip_authorization(sip); pa = sip_proxy_authorization(sip); msg_destroy(msg); msg = nta_msg_create(nh->nh_nua->nua_nta, 0); sip = sip_object(msg); if (!msg) goto error; cseq = sip_cseq_create(msg_home(msg), cr->cr_seq, SIP_METHOD_ACK); if (!cseq) ; else if (nh->nh_tags && sip_add_tl(msg, sip, TAG_NEXT(nh->nh_tags)) < 0) ; else if (tags && sip_add_tl(msg, sip, TAG_NEXT(tags)) < 0) ; else if (wa && sip_add_dup(msg, sip, (sip_header_t *)wa) < 0) ; else if (pa && sip_add_dup(msg, sip, (sip_header_t *)pa) < 0) ; else if (sip_header_insert(msg, sip, (sip_header_t *)cseq) < 0) ; else if (nta_msg_request_complete(msg, ds->ds_leg, SIP_METHOD_ACK, NULL) < 0) ; else { /* Remove extra headers */ while (sip->sip_allow) sip_header_remove(msg, sip, (sip_header_t*)sip->sip_allow); while (sip->sip_priority) sip_header_remove(msg, sip, (sip_header_t*)sip->sip_priority); while (sip->sip_proxy_require) sip_header_remove(msg, sip, (sip_header_t*)sip->sip_proxy_require); while (sip->sip_require) sip_header_remove(msg, sip, (sip_header_t*)sip->sip_require); while (sip->sip_subject) sip_header_remove(msg, sip, (sip_header_t*)sip->sip_subject); while (sip->sip_supported) sip_header_remove(msg, sip, (sip_header_t*)sip->sip_supported); if (ss == NULL || ss->ss_state > nua_callstate_ready) ; else if (cr->cr_offer_recv && !cr->cr_answer_sent) { if (nh->nh_soa == NULL) { if (session_get_description(sip, NULL, NULL)) cr->cr_answer_sent = 1, ss->ss_oa_sent = Answer; } else if (soa_generate_answer(nh->nh_soa, NULL) < 0 || session_include_description(nh->nh_soa, 1, msg, sip) < 0) { status = 900, phrase = "Internal media error"; reason = "SIP;cause=500;text=\"Internal media error\""; /* reason = soa_error_as_sip_reason(nh->nh_soa); */ } else { cr->cr_answer_sent = 1, ss->ss_oa_sent = Answer; } } if (ss == NULL || ss->ss_state > nua_callstate_ready || reason) ; else if (nh->nh_soa && soa_is_complete(nh->nh_soa)) { /* signal SOA that O/A round(s) is (are) complete */ if (soa_activate(nh->nh_soa, NULL) >= 0) { ss->ss_sdp_version = soa_get_user_version(nh->nh_soa); } } else if (nh->nh_soa == NULL /* NUA does not necessarily know dirty details */ /* && !(cr->cr_offer_sent && !cr->cr_answer_recv) */) { ; } else { nua_client_request_t *cru; /* Final response to UPDATE or PRACK may be on its way ... */ for (cru = ds->ds_cr; cru; cru = cru->cr_next) { if (cr != cru && cru->cr_offer_sent && !cru->cr_answer_recv) break; } if (cru == NULL) { /* No SDP answer -> terminate call */ status = 988, phrase = "Incomplete offer/answer"; reason = "SIP;cause=488;text=\"Incomplete offer/answer\""; } } proxy_is_set = NH_PISSET(nh, proxy); proxy = NH_PGET(nh, proxy); if ((ack = nta_outgoing_mcreate(nh->nh_nua->nua_nta, NULL, NULL, NULL, msg, NTATAG_ACK_BRANCH(invite_branch), TAG_IF(proxy_is_set, NTATAG_DEFAULT_PROXY(proxy)), SIPTAG_END(), TAG_NEXT(tags)))) { /* TR engine keeps this around for T2 so it catches all 2XX retransmissions */ nta_outgoing_destroy(ack); if (nh->nh_soa && reason && ss && ss->ss_state <= nua_callstate_ready) nua_stack_event(nh->nh_nua, nh, NULL, nua_i_media_error, status, phrase, NULL); } else if (!reason) { status = 900, phrase = "Cannot send ACK"; reason = "SIP;cause=500;text=\"Internal Error\""; } if (ss && reason) ss->ss_reason = reason; if (status < 300) error = 1; else error = -2; } if (error == -1) msg_destroy(msg); error: cr->cr_acked = 1; /* ... or we have at least tried */ nua_client_request_remove(cr); nua_client_request_clean(cr); return error; } static int nua_invite_client_should_ack(nua_client_request_t const *cr) { return cr && cr->cr_orq && !cr->cr_acked && 200 <= cr->cr_status && cr->cr_status < 300; } /** Complete client request */ static int nua_invite_client_complete(nua_client_request_t *cr) { if (cr->cr_orq == NULL) /* Xyzzy */; else if (cr->cr_status < 200) nta_outgoing_cancel(cr->cr_orq); else if (cr->cr_status < 300 && !cr->cr_acked) nua_invite_client_ack(cr, NULL); return 0; } /**@fn void nua_cancel(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * * Cancel an INVITE operation * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Related Tags: * Header tags defined in * * @par Events: * #nua_r_cancel, #nua_i_state (#nua_i_active, #nua_i_terminated) * * @sa @ref nua_call_model, nua_invite(), #nua_i_cancel */ static int nua_cancel_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags); static int nua_cancel_client_check_restart(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip); nua_client_methods_t const nua_cancel_client_methods = { SIP_METHOD_CANCEL, /* crm_method, crm_method_name */ 0, /* crm_extra */ { /* crm_flags */ /* create_dialog */ 0, /* in_dialog */ 1, /* target refresh */ 0 }, NULL, /* crm_template */ NULL, /* crm_init */ nua_cancel_client_request, /* .. not really crm_send */ nua_cancel_client_check_restart, /* crm_check_restart */ NULL, /* crm_recv */ NULL, /* crm_preliminary */ NULL, /* crm_report */ NULL, /* crm_complete */ }; int nua_stack_cancel(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { return nua_client_create(nh, e, &nua_cancel_client_methods, tags); } static int nua_cancel_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = nua_dialog_usage_for_session(nh->nh_ds); if (!du || !du->du_cr || !du->du_cr->cr_orq || nta_outgoing_status(du->du_cr->cr_orq) >= 200) { return nua_client_return(cr, 481, "No transaction to CANCEL", msg); } assert(cr->cr_orq == NULL); cr->cr_orq = nta_outgoing_tcancel(du->du_cr->cr_orq, nua_client_orq_response, nua_client_request_ref(cr), TAG_NEXT(tags)); if (cr->cr_orq == NULL) { nua_client_request_unref(cr); return -1; } return 0; } static int nua_cancel_client_check_restart(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip) { /* We cannot really restart CANCEL */ return 0; } /** @NUA_EVENT nua_r_cancel * * Answer to outgoing CANCEL. * * The CANCEL may be sent explicitly by nua_cancel() or implicitly by NUA * state machine. * * @param status response status code * @param phrase a short textual description of @a status code * @param nh operation handle associated with the call * @param hmagic application context associated with the call * @param sip response to CANCEL request or NULL upon an error * (status code is in @a status and * descriptive message in @a phrase parameters) * @param tags empty * * @sa nua_cancel(), @ref nua_uac_call_model, #nua_r_invite, nua_invite(), * #nua_i_state * * @END_NUA_EVENT */ static void nua_session_usage_refresh(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du, sip_time_t now) { nua_session_usage_t *ss = NUA_DIALOG_USAGE_PRIVATE(du); nua_client_request_t const *cr = du->du_cr; nua_server_request_t const *sr; if (ss->ss_state >= nua_callstate_terminating || /* INVITE is in progress or being authenticated */ nua_client_request_in_progress(cr)) return; /* UPDATE has been queued */ for (cr = ds->ds_cr; cr; cr = cr->cr_next) if (cr->cr_method == sip_method_update) return; /* INVITE or UPDATE in progress on server side */ for (sr = ds->ds_sr; sr; sr = sr->sr_next) if (sr->sr_usage == du && (sr->sr_method == sip_method_invite || sr->sr_method == sip_method_update)) return; /* XXX - should check if we actually start something */ if (ss->ss_timer->refresher == nua_remote_refresher) { SU_DEBUG_3(("nua(%p): session almost expired, " "sending BYE before timeout.\n", (void *)nh)); ss->ss_reason = "SIP;cause=408;text=\"Session timeout\""; nua_stack_bye(nh->nh_nua, nh, nua_r_bye, NULL); } else if (NH_PGET(nh, update_refresh)) { nua_stack_update(nh->nh_nua, nh, nua_r_update, NULL); } else if (du->du_cr) { nua_client_resend_request(du->du_cr, 0); } else { nua_stack_invite(nh->nh_nua, nh, nua_r_invite, NULL); } } /** @interal Shut down session usage. * * @retval >0 shutdown done * @retval 0 shutdown in progress * @retval <0 try again later */ static int nua_session_usage_shutdown(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du) { nua_session_usage_t *ss = NUA_DIALOG_USAGE_PRIVATE(du); nua_server_request_t *sr, *sr_next; nua_client_request_t *cri; assert(ss == nua_session_usage_for_dialog(nh->nh_ds)); /* Zap server-side transactions */ for (sr = ds->ds_sr; sr; sr = sr_next) { sr_next = sr->sr_next; if (sr->sr_usage == du) { assert(sr->sr_usage == du); sr->sr_usage = NULL; if (nua_server_request_is_pending(sr)) { SR_STATUS1(sr, SIP_480_TEMPORARILY_UNAVAILABLE); nua_server_respond(sr, NULL); if (nua_server_report(sr) >= 2) return 480; } else nua_server_request_destroy(sr); } } cri = du->du_cr; switch (ss->ss_state) { case nua_callstate_calling: case nua_callstate_proceeding: return nua_client_create(nh, nua_r_cancel, &nua_cancel_client_methods, NULL); case nua_callstate_completing: case nua_callstate_completed: case nua_callstate_ready: if (cri && cri->cr_orq) { if (cri->cr_status < 200) { nua_client_create(nh, nua_r_cancel, &nua_cancel_client_methods, NULL); } else if (cri->cr_status < 300 && !cri->cr_acked) { nua_invite_client_ack(cri, NULL); } } if (nua_client_create(nh, nua_r_bye, &nua_bye_client_methods, NULL) != 0) break; signal_call_state_change(nh, ss, 487, "BYE sent", nua_callstate_terminating); return 0; case nua_callstate_terminating: case nua_callstate_terminated: /* XXX */ return 0; default: break; } nua_dialog_usage_remove(nh, ds, du, NULL, NULL); return 200; } /**@fn void nua_prack(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * Send a PRACK request. * * PRACK is used to acknowledge receipt of 100rel responses. See @RFC3262. * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Related Tags: * Tags in , . * * @par Events: * #nua_r_prack */ /** @NUA_EVENT nua_r_prack * * Response to an outgoing @b PRACK request. PRACK request is used to * acknowledge reliable preliminary responses and it is usually sent * automatically by the nua stack. * * @param status response status code * (if the request is retried, @a status is 100, the @a * sip->sip_status->st_status contain the real status code * from the response message, e.g., 302, 401, or 407) * @param phrase a short textual description of @a status code * @param nh operation handle associated with the call * @param hmagic application context associated with the call * @param sip response to @b PRACK or NULL upon an error * (status code is in @a status and * descriptive message in @a phrase parameters) * @param tags empty * * @sa nua_prack(), #nua_i_prack, @RFC3262 * * @END_NUA_EVENT */ static int nua_prack_client_init(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags); static int nua_prack_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags); static int nua_prack_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip); static int nua_prack_client_report(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip, nta_outgoing_t *orq, tagi_t const *tags); nua_client_methods_t const nua_prack_client_methods = { SIP_METHOD_PRACK, /* crm_method, crm_method_name */ 0, /* crm_extra */ { /* crm_flags */ /* create_dialog */ 0, /* in_dialog */ 1, /* target refresh */ 0 }, NULL, /* crm_template */ nua_prack_client_init, /* crm_init */ nua_prack_client_request, /* crm_send */ NULL, /* crm_check_restart */ nua_prack_client_response, /* crm_recv */ NULL, /* crm_preliminary */ nua_prack_client_report, /* crm_report */ NULL, /* crm_complete */ }; int nua_stack_prack(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { return nua_client_create(nh, e, &nua_prack_client_methods, tags); } static int nua_prack_client_init(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = nua_dialog_usage_for_session(nh->nh_ds); cr->cr_usage = du; return 0; } static int nua_prack_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = cr->cr_usage; nua_session_usage_t *ss; nua_client_request_t *cri; int offer_sent = 0, answer_sent = 0, retval; int status = 0; char const *phrase = "PRACK Sent"; uint32_t rseq = 0; if (du == NULL) /* Call terminated */ return nua_client_return(cr, SIP_481_NO_TRANSACTION, msg); ss = NUA_DIALOG_USAGE_PRIVATE(du); if (ss->ss_state >= nua_callstate_terminating) return nua_client_return(cr, 900, "Session is terminating", msg); cri = du->du_cr; if (sip->sip_rack) rseq = sip->sip_rack->ra_response; if (cri->cr_offer_recv && !cri->cr_answer_sent) { if (nh->nh_soa == NULL) /* It is up to application to handle SDP */ answer_sent = session_get_description(sip, NULL, NULL); else if (sip->sip_payload) /* XXX - we should just do MIME in session_include_description() */; else if (soa_generate_answer(nh->nh_soa, NULL) < 0 || session_include_description(nh->nh_soa, 1, msg, sip) < 0) { status = soa_error_as_sip_response(nh->nh_soa, &phrase); SU_DEBUG_3(("nua(%p): local response to PRACK: %d %s\n", (void *)nh, status, phrase)); nua_stack_event(nh->nh_nua, nh, NULL, nua_i_media_error, status, phrase, NULL); return nua_client_return(cr, status, phrase, msg); } else { answer_sent = 1; if (soa_activate(nh->nh_soa, NULL) >= 0) { ss->ss_sdp_version = soa_get_user_version(nh->nh_soa); } } } else if (nh->nh_soa == NULL) { offer_sent = session_get_description(sip, NULL, NULL); } else { /* When 100rel response status was 183 do support for preconditions */ int send_offer = ss->ss_precondition && cri->cr_status == 183 && cri->cr_offer_sent && cri->cr_answer_recv; if (!send_offer) { tagi_t const *t = tl_find_last(tags, nutag_include_extra_sdp); send_offer = t && t->t_value; } if (!send_offer) { } else if (soa_generate_offer(nh->nh_soa, 0, NULL) >= 0 && session_include_description(nh->nh_soa, 1, msg, sip) >= 0) { offer_sent = 1; } else { status = soa_error_as_sip_response(nh->nh_soa, &phrase); SU_DEBUG_3(("nua(%p): PRACK offer: %d %s\n", (void *)nh, status, phrase)); nua_stack_event(nh->nh_nua, nh, NULL, nua_i_media_error, status, phrase, NULL); return nua_client_return(cr, status, phrase, msg); } } retval = nua_base_client_request(cr, msg, sip, NULL); if (retval == 0) { cr->cr_offer_sent = offer_sent; cr->cr_answer_sent = answer_sent; if (cri->cr_offer_recv && answer_sent) { cr->cr_answer_sent = 0; cri->cr_offer_recv = 0; cri->cr_answer_sent = 0; } if (offer_sent) ss->ss_oa_sent = Offer; else if (answer_sent) ss->ss_oa_sent = Answer; if (cr->cr_restarting) /* Restart logic calls nua_prack_client_report */; else if (!cr->cr_auto && (!offer_sent || !answer_sent)) /* Suppose application know it called nua_prack() */; else signal_call_state_change(nh, ss, status, phrase, ss->ss_state); } return retval; } static int nua_prack_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip) { /* XXX - fatal error cases? */ return nua_session_client_response(cr, status, phrase, sip); } static int nua_prack_client_report(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip, nta_outgoing_t *orq, tagi_t const *tags) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = cr->cr_usage; nua_session_usage_t *ss = nua_dialog_usage_private(du); int acked = 0; nua_stack_event(nh->nh_nua, nh, nta_outgoing_getresponse(orq), (enum nua_event_e)cr->cr_event, status, phrase, tags); if (!ss || cr->cr_terminated || cr->cr_graceful || cr->cr_waiting) return 1; if (cr->cr_offer_sent || cr->cr_answer_sent) { unsigned next_state = ss->ss_state; if (status < 200) ; else if (nua_invite_client_should_ack(du->du_cr)) { /* There is an un-ACK-ed INVITE there */ assert(du->du_cr->cr_method == sip_method_invite); if (NH_PGET(nh, auto_ack) || /* Auto-ACK response to re-INVITE when media is enabled and auto_ack is not set to 0 on handle */ (ss->ss_state == nua_callstate_ready && nh->nh_soa && !NH_PISSET(nh, auto_ack))) { /* There should be no UPDATE with offer/answer if PRACK with offer/answer was ongoing! */ if (nua_invite_client_ack(du->du_cr, NULL) > 0) next_state = nua_callstate_ready; else next_state = nua_callstate_terminating; acked = 1; } } signal_call_state_change(nh, ss, status, phrase, (enum nua_callstate)next_state); } if (acked && nua_client_is_queued(du->du_cr) && du->du_cr->cr_method == sip_method_invite) { /* New INVITE was queued - do not send UPDATE */ } else if (ss->ss_update_needed && 200 <= status && status < 300 && !SIP_IS_ALLOWED(NH_PGET(nh, appl_method), sip_method_update)) nua_client_create(nh, nua_r_update, &nua_update_client_methods, NULL); return 1; } /* ---------------------------------------------------------------------- */ /* UAS side of INVITE */ /** @NUA_EVENT nua_i_invite * * Indication of incoming call or re-INVITE request. * * @param status statuscode of response sent automatically by stack * @param phrase a short textual description of @a status code * @param nh operation handle associated with this call * (maybe created for this call) * @param hmagic application context associated with this call * (maybe NULL if call handle was created for this call) * @param sip incoming INVITE request * @param tags SOATAG_ACTIVE_AUDIO(), SOATAG_ACTIVE_VIDEO() * * @par * @par Responding to INVITE with nua_respond() * * If @a status in #nua_i_invite event is below 200, the application should * accept or reject the call with nua_respond(). See the @ref nua_call_model * for the detailed explanation of various options in call processing at * server end. * * The @b INVITE request takes care of session setup using SDP Offer-Answer * negotiation as specified in @RFC3264 (updated in @RFC3262 section 5, * @RFC3311, and @RFC3312). The Offer-Answer can be taken care by * application (if NUTAG_MEDIA_ENABLE(0) parameter has been set) or by the * built-in SDP Offer/Answer engine @soa (by default and when * NUTAG_MEDIA_ENABLE(1) parameter has been set). When @soa is enabled, it * will take care of parsing the SDP, negotiating the media and codecs, and * including the SDP in the SIP message bodies as required by the * Offer-Answer model. * * When @soa is enabled, the SDP in the incoming INVITE is parsed and feed * to a #soa_session_t object. The #nua_i_state event sent to the * application immediately after #nua_i_invite will contain the parsing * results in SOATAG_REMOTE_SDP() and SOATAG_REMOTE_SDP_STR() tags. * * Note that currently the parser within @nua does not handle MIME * multipart. The SDP Offer/Answer engine can get confused if the SDP offer * is included in a MIME multipart, therefore such an @b INVITE is rejected * with 415 Unsupported Media Type error response: the client is * expected to retry the INVITE without MIME multipart content. * * If the call is to be accepted, the application should include the SDP in * the 2XX response. If @soa is not disabled with NUTAG_MEDIA_ENABLE(0), the * SDP should be included in the SOATAG_USER_SDP() or SOATAG_USER_SDP_STR() * parameter given to nua_respond(). If it is disabled, the SDP should be * included in the response message using SIPTAG_PAYLOAD() or * SIPTAG_PAYLOAD_STR(). Also, the @ContentType should be set using * SIPTAG_CONTENT_TYPE() or SIPTAG_CONTENT_TYPE_STR(). * * @par Preliminary Responses and 100rel * * Call progress can be signaled with preliminary responses (with status * code in the range 101..199). It is possible to conclude the SDP * Offer-Answer negotiation using preliminary responses, too. If * NUTAG_EARLY_ANSWER(1), SOATAG_USER_SDP() or SOATAG_USER_SDP_STR() * parameter is included with in a preliminary nua_response(), the SDP * answer is generated and sent with the preliminary responses, too. * * The preliminary responses are sent reliably if feature tag "100rel" is * included in the @Require header of the response or if * NUTAG_EARLY_MEDIA(1) parameter has been given. The reliably delivery of * preliminary responses mean that a sequence number is included in the * @RSeq header in the response message and the response message is resent * until the client responds with a @b PRACK request with matching sequence * number in @RAck header. * * Note that only the "183" response is sent reliably if the * NUTAG_ONLY183_100REL(1) parameter has been given. The reliable * preliminary responses are acknowledged with @b PRACK request sent by the * client. * * Note if the SDP offer-answer is completed with the reliable preliminary * responses, the is no need to include SDP in 200 OK response (or other 2XX * response). However, it the tag NUTAG_INCLUDE_EXTRA_SDP(1) is included * with nua_respond(), a copy of the SDP answer generated earlier by @soa is * included as the message body. * * @sa nua_respond(), @ref nua_uas_call_model, #nua_i_state, * NUTAG_MEDIA_ENABLE(), SOATAG_USER_SDP(), SOATAG_USER_SDP_STR(), * @RFC3262, NUTAG_EARLY_ANSWER(), NUTAG_EARLY_MEDIA(), * NUTAG_ONLY183_100REL(), * NUTAG_INCLUDE_EXTRA_SDP(), * #nua_i_prack, #nua_i_update, nua_update(), * nua_invite(), #nua_r_invite * * @par * @par Third Party Call Control * * When so called 2rd party call control is used, the initial @b INVITE may * not contain SDP offer. In that case, the offer is sent by the recipient * of the @b INVITE request (User-Agent Server, UAS). The SDP sent in 2XX * response (or in a preliminary reliable response) is considered as an * offer, and the answer will be included in the @b ACK request sent by the * UAC (or @b PRACK in case of preliminary reliable response). * * @sa @ref nua_3pcc_call_model * * @END_NUA_EVENT */ static int nua_invite_server_init(nua_server_request_t *sr); static int nua_session_server_init(nua_server_request_t *sr); static int nua_invite_server_preprocess(nua_server_request_t *sr); static int nua_invite_server_respond(nua_server_request_t *sr, tagi_t const *); static int nua_invite_server_is_100rel(nua_server_request_t *, tagi_t const *); static int nua_invite_server_report(nua_server_request_t *sr, tagi_t const *); static int process_ack_or_cancel(nua_server_request_t *, nta_incoming_t *, sip_t const *), process_ack(nua_server_request_t *, nta_incoming_t *, sip_t const *), process_ack_error(nua_server_request_t *sr, msg_t *ackmsg, int status, char const *phrase, char const *reason), process_cancel(nua_server_request_t *, nta_incoming_t *, sip_t const *), process_timeout(nua_server_request_t *, nta_incoming_t *), process_prack(nua_server_request_t *, nta_reliable_t *rel, nta_incoming_t *irq, sip_t const *sip); nua_server_methods_t const nua_invite_server_methods = { SIP_METHOD_INVITE, nua_i_invite, /* Event */ { 1, /* Create dialog */ 0, /* Initial request */ 1, /* Target refresh request */ 1, /* Add Contact */ }, nua_invite_server_init, nua_invite_server_preprocess, nua_base_server_params, nua_invite_server_respond, nua_invite_server_report, }; /** @internal Preprocess incoming invite - sure we have a valid request. * * @return 0 if request is valid, or error statuscode otherwise */ static int nua_invite_server_init(nua_server_request_t *sr) { nua_handle_t *nh = sr->sr_owner; nua_t *nua = nh->nh_nua; nua_session_usage_t *ss; sr->sr_neutral = 1; if (!NUA_PGET(nua, nh, invite_enable)) return SR_STATUS1(sr, SIP_403_FORBIDDEN); if (nua_session_server_init(sr)) return sr->sr_status; if (sr->sr_usage) { /* Existing session - check for overlap and glare */ nua_server_request_t const *sr0; nua_client_request_t const *cr; for (sr0 = nh->nh_ds->ds_sr; sr0; sr0 = sr0->sr_next) { /* Previous INVITE has not been ACKed */ if (sr0->sr_method == sip_method_invite) break; /* Or we have sent offer but have not received an answer */ if (sr->sr_sdp && sr0->sr_offer_sent && !sr0->sr_answer_recv) break; /* Or we have received request with offer but not sent an answer */ if (sr->sr_sdp && sr0->sr_offer_recv && !sr0->sr_answer_sent) break; } if (sr0) { /* Overlapping invites - RFC 3261 14.2 */ return nua_server_retry_after(sr, 500, "Overlapping Requests", 0, 10); } for (cr = nh->nh_ds->ds_cr; cr; cr = cr->cr_next) { if (cr->cr_usage == sr->sr_usage && cr->cr_orq && cr->cr_offer_sent) /* Glare - RFC 3261 14.2 and RFC 3311 section 5.2 */ return SR_STATUS1(sr, SIP_491_REQUEST_PENDING); } ss = nua_dialog_usage_private(sr->sr_usage); if (ss->ss_state < nua_callstate_ready && ss->ss_state != nua_callstate_init) { return nua_server_retry_after(sr, 500, "Overlapping Requests 2", 0, 10); } } sr->sr_neutral = 0; return 0; } /** Initialize session server request. * * Ensure that the request is valid. */ static int nua_session_server_init(nua_server_request_t *sr) { nua_handle_t *nh = sr->sr_owner; nua_t *nua = nh->nh_nua; msg_t *msg = sr->sr_response.msg; sip_t *sip = sr->sr_response.sip; sip_t const *request = sr->sr_request.sip; if (!sr->sr_initial) sr->sr_usage = nua_dialog_usage_get(nh->nh_ds, nua_session_usage, NULL); if (sr->sr_method != sip_method_invite && sr->sr_usage == NULL) { /* UPDATE/PRACK sent within an existing dialog? */ return SR_STATUS(sr, 481, "Call Does Not Exist"); } else if (sr->sr_usage) { nua_session_usage_t *ss = nua_dialog_usage_private(sr->sr_usage); if (ss->ss_state >= nua_callstate_terminating) return SR_STATUS(sr, 481, "Call is being terminated"); } if (nh->nh_soa) { sip_accept_t *a, *sdp_only = nua->nua_invite_accept; if (NH_PGET(nh, accept_multipart)) a = nua->nua_accept_multipart; else a = nua->nua_invite_accept; sip_add_dup(msg, sip, (sip_header_t *)a); /* Make sure caller uses application/sdp without compression */ if (nta_check_session_content(NULL, request, a, TAG_END())) { sip_add_make(msg, sip, sip_accept_encoding_class, ""); return SR_STATUS1(sr, SIP_415_UNSUPPORTED_MEDIA); } /* Make sure caller accepts application/sdp */ if (nta_check_accept(NULL, request, sdp_only, NULL, TAG_END())) { sip_add_make(msg, sip, sip_accept_encoding_class, ""); return SR_STATUS1(sr, SIP_406_NOT_ACCEPTABLE); } } if (request->sip_session_expires && sip_has_feature(NH_PGET(nh, supported), "timer") && session_timer_check_min_se(msg, sip, request, NH_PGET(nh, min_se))) { if (sip->sip_min_se) return SR_STATUS1(sr, SIP_422_SESSION_TIMER_TOO_SMALL); else return SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); } session_get_description(request, &sr->sr_sdp, &sr->sr_sdp_len); return 0; } /** Preprocess INVITE. * * This is called after a handle has been created for an incoming INVITE. */ int nua_invite_server_preprocess(nua_server_request_t *sr) { nua_handle_t *nh = sr->sr_owner; nua_dialog_state_t *ds = nh->nh_ds; nua_session_usage_t *ss; sip_t const *request = sr->sr_request.sip; assert(sr->sr_status == 100); assert(nh != nh->nh_nua->nua_dhandle); if (sr->sr_status > 100) return sr->sr_status; if (nh->nh_soa) soa_init_offer_answer(nh->nh_soa); if (sr->sr_sdp) { if (nh->nh_soa && soa_set_remote_sdp(nh->nh_soa, NULL, sr->sr_sdp, sr->sr_sdp_len) < 0) { SU_DEBUG_5(("nua(%p): %s server: error parsing SDP\n", (void *)nh, "INVITE")); return SR_STATUS(sr, 400, "Bad Session Description"); } else sr->sr_offer_recv = 1; } /* Add the session usage */ if (sr->sr_usage == NULL) { sr->sr_usage = nua_dialog_usage_add(nh, ds, nua_session_usage, NULL); if (sr->sr_usage == NULL) return SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); } ss = nua_dialog_usage_private(sr->sr_usage); if (sr->sr_offer_recv) ss->ss_oa_recv = Offer; ss->ss_100rel = NH_PGET(nh, early_media); ss->ss_precondition = sip_has_feature(request->sip_require, "precondition"); if (ss->ss_precondition) ss->ss_100rel = 1; session_timer_store(ss->ss_timer, request); #if 0 /* The glare and overlap tests should take care of this. */ assert(ss->ss_state >= nua_callstate_completed || ss->ss_state == nua_callstate_init); #endif if (NH_PGET(nh, auto_answer) || /* Auto-answer to re-INVITE unless auto_answer is set to 0 on handle */ (ss->ss_state == nua_callstate_ready && /* Auto-answer requires enabled media (soa). * XXX - if the re-INVITE modifies the media we should not auto-answer. */ nh->nh_soa && !NH_PISSET(nh, auto_answer))) { SR_STATUS1(sr, SIP_200_OK); } else if (NH_PGET(nh, auto_alert)) { if (ss->ss_100rel && (sip_has_feature(request->sip_supported, "100rel") || sip_has_feature(request->sip_require, "100rel"))) { SR_STATUS1(sr, SIP_183_SESSION_PROGRESS); } else { SR_STATUS1(sr, SIP_180_RINGING); } } return 0; } /** @internal Respond to an INVITE request. * */ static int nua_invite_server_respond(nua_server_request_t *sr, tagi_t const *tags) { nua_handle_t *nh = sr->sr_owner; nua_dialog_usage_t *du = sr->sr_usage; nua_session_usage_t *ss = nua_dialog_usage_private(du); msg_t *msg = sr->sr_response.msg; sip_t *sip = sr->sr_response.sip; int reliable = 0, maybe_answer = 0, offer = 0, answer = 0, extra = 0; enter; if (du == NULL) { if (sr->sr_status < 300) sr_status(sr, SIP_500_INTERNAL_SERVER_ERROR); return nua_base_server_respond(sr, tags); } if (200 <= sr->sr_status && sr->sr_status < 300) { reliable = 1, maybe_answer = 1; } else if (nua_invite_server_is_100rel(sr, tags)) { reliable = 1, maybe_answer = 1; } else if (!nh->nh_soa || sr->sr_status >= 300) { if (sr->sr_neutral) return nua_base_server_respond(sr, tags); } else if (tags && 100 < sr->sr_status && sr->sr_status < 200 && !NHP_ISSET(nh->nh_prefs, early_answer)) { sdp_session_t const *user_sdp = NULL; char const *user_sdp_str = NULL; tl_gets(tags, SOATAG_USER_SDP_REF(user_sdp), SOATAG_USER_SDP_STR_REF(user_sdp_str), TAG_END()); maybe_answer = user_sdp || user_sdp_str; } else { maybe_answer = NH_PGET(nh, early_answer); } if (!nh->nh_soa) { if (session_get_description(sip, NULL, NULL)) { if (sr->sr_offer_recv) answer = 1; else if (sr->sr_offer_sent < 2) offer = 1; } } else if (sr->sr_status >= 300) { soa_clear_remote_sdp(nh->nh_soa); } else if (sr->sr_offer_sent && !sr->sr_answer_recv) /* Wait for answer */; else if (sr->sr_offer_recv && sr->sr_answer_sent > 1) { /* We have sent answer */ /* ... but we may want to send it again */ tagi_t const *t = tl_find_last(tags, nutag_include_extra_sdp); extra = t && t->t_value; } else if (sr->sr_offer_recv && !sr->sr_answer_sent && maybe_answer) { /* Generate answer */ if (soa_generate_answer(nh->nh_soa, NULL) >= 0 && soa_activate(nh->nh_soa, NULL) >= 0) { answer = 1; /* signal that O/A answer sent (answer to invite) */ /* ss_sdp_version is updated only after answer is sent reliably */ } /* We have an error! */ else if (sr->sr_status >= 200) { sip_warning_t *warning = NULL; int wcode; char const *text; char const *host = "invalid."; sr->sr_status = soa_error_as_sip_response(nh->nh_soa, &sr->sr_phrase); wcode = soa_get_warning(nh->nh_soa, &text); if (wcode) { if (sip->sip_contact) host = sip->sip_contact->m_url->url_host; warning = sip_warning_format(msg_home(msg), "%u %s \"%s\"", wcode, host, text); sip_header_insert(msg, sip, (sip_header_t *)warning); } } else { /* 1xx - we don't have to send answer */ } } else if (sr->sr_offer_recv && sr->sr_answer_sent == 1 && maybe_answer) { /* The answer was sent unreliably, keep sending it */ answer = 1; } else if (!sr->sr_offer_recv && !sr->sr_offer_sent && reliable) { if (200 <= sr->sr_status && nua_callstate_ready <= ss->ss_state && NH_PGET(nh, refresh_without_sdp)) /* This is a re-INVITE without SDP - do not try to send offer in 200 */; else /* Generate offer */ if (soa_generate_offer(nh->nh_soa, 0, NULL) < 0) sr->sr_status = soa_error_as_sip_response(nh->nh_soa, &sr->sr_phrase); else offer = 1; } if (sr->sr_status < 300 && (offer || answer || extra)) { if (nh->nh_soa && session_include_description(nh->nh_soa, 1, msg, sip) < 0) SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); else if (offer) sr->sr_offer_sent = 1 + reliable, ss->ss_oa_sent = Offer; else if (answer) sr->sr_answer_sent = 1 + reliable, ss->ss_oa_sent = Answer; if (answer && reliable && nh->nh_soa) { ss->ss_sdp_version = soa_get_user_version(nh->nh_soa); } } if (reliable && sr->sr_status < 200) { sr->sr_response.msg = NULL, sr->sr_response.sip = NULL; if (nta_reliable_mreply(sr->sr_irq, process_prack, sr, msg) == NULL) return -1; sr->sr_100rel = 1; return 0; } if (200 <= sr->sr_status && sr->sr_status < 300) { session_timer_preferences(ss->ss_timer, sip, NH_PGET(nh, supported), NH_PGET(nh, session_timer), NUA_PISSET(nh->nh_nua, nh, session_timer), NH_PGET(nh, refresher), NH_PGET(nh, min_se)); if (session_timer_is_supported(ss->ss_timer)) session_timer_add_headers(ss->ss_timer, 0, msg, sip); } return nua_base_server_respond(sr, tags); } /** Check if the response should be sent reliably. * XXX - use tags to indicate when to use reliable responses ??? */ static int nua_invite_server_is_100rel(nua_server_request_t *sr, tagi_t const *tags) { nua_handle_t *nh = sr->sr_owner; sip_require_t *require = sr->sr_request.sip->sip_require; sip_supported_t *supported = sr->sr_request.sip->sip_supported; if (sr->sr_status >= 200) return 0; else if (sr->sr_status == 100) return 0; if (sip_has_feature(sr->sr_response.sip->sip_require, "100rel")) return 1; if (require == NULL && supported == NULL) return 0; if (!sip_has_feature(NH_PGET(nh, supported), "100rel")) return 0; if (sip_has_feature(require, "100rel")) return 1; if (!sip_has_feature(supported, "100rel")) return 0; if (sr->sr_status == 183) return 1; if (NH_PGET(nh, early_media) && !NH_PGET(nh, only183_100rel)) return 1; if (sip_has_feature(require, "precondition")) { if (!NH_PGET(nh, only183_100rel)) return 1; if (sr->sr_offer_recv && !sr->sr_answer_sent) return 1; } return 0; } int nua_invite_server_report(nua_server_request_t *sr, tagi_t const *tags) { nua_handle_t *nh = sr->sr_owner; nua_dialog_usage_t *du = sr->sr_usage; nua_session_usage_t *ss = nua_dialog_usage_private(sr->sr_usage); int initial = sr->sr_initial && !sr->sr_event; int neutral = sr->sr_neutral; int application = sr->sr_application; int status = sr->sr_status; char const *phrase = sr->sr_phrase; int retval; if (!sr->sr_event && status < 300) { /* Not reported yet */ nta_incoming_bind(sr->sr_irq, process_ack_or_cancel, sr); } retval = nua_base_server_report(sr, tags), sr = NULL; /* destroys sr */ if (retval >= 2 || ss == NULL) { /* Session has been terminated. */ if (!initial && !neutral) { #if 0 signal_call_state_change(nh, NULL, status, phrase, nua_callstate_terminated); #endif } return retval; } /* Update session state */ if (status < 300 || application != 0) { assert(ss->ss_state != nua_callstate_calling); assert(ss->ss_state != nua_callstate_proceeding); signal_call_state_change(nh, ss, status, phrase, status >= 300 ? nua_callstate_init : status >= 200 ? nua_callstate_completed : status > 100 ? nua_callstate_early : nua_callstate_received); } if (status == 180) ss->ss_alerting = 1; else if (status >= 200) ss->ss_alerting = 0; if (200 <= status && status < 300) { du->du_ready = 1; } else if (300 <= status && !neutral) { if (nh->nh_soa) soa_init_offer_answer(nh->nh_soa); } if (ss->ss_state == nua_callstate_init) { assert(status >= 300); nua_session_usage_destroy(nh, ss); } return retval; } /** @internal Process ACK or CANCEL or timeout (no ACK) for incoming INVITE */ static int process_ack_or_cancel(nua_server_request_t *sr, nta_incoming_t *irq, sip_t const *sip) { enter; assert(sr->sr_usage); assert(sr->sr_usage->du_class == nua_session_usage); if (sip && sip->sip_request->rq_method == sip_method_ack) return process_ack(sr, irq, sip); else if (sip && sip->sip_request->rq_method == sip_method_cancel) return process_cancel(sr, irq, sip); else return process_timeout(sr, irq); } /** @NUA_EVENT nua_i_ack * * Final response to INVITE has been acknowledged by UAC with ACK. * * @note This event is only sent after 2XX response. * * @param nh operation handle associated with the call * @param hmagic application context associated with the call * @param sip incoming ACK request * @param tags empty * * @sa #nua_i_invite, #nua_i_state, @ref nua_uas_call_model, nua_ack() * * @END_NUA_EVENT */ static int process_ack(nua_server_request_t *sr, nta_incoming_t *irq, sip_t const *sip) { nua_handle_t *nh = sr->sr_owner; nua_session_usage_t *ss = nua_dialog_usage_private(sr->sr_usage); msg_t *msg = nta_incoming_getrequest_ackcancel(irq); char const *recv = NULL; int uas; if (ss == NULL) return 0; if (sr->sr_offer_sent && !sr->sr_answer_recv) { char const *sdp; size_t len; if (session_get_description(sip, &sdp, &len)) recv = Answer; if (recv) { assert(ss->ss_oa_recv == NULL); ss->ss_oa_recv = recv; } if (nh->nh_soa == NULL) ; else if (recv == NULL ) { if (ss->ss_state >= nua_callstate_ready && soa_get_user_version(nh->nh_soa) == ss->ss_sdp_version && soa_process_reject(nh->nh_soa, NULL) >= 0) { url_t const *m; /* The re-INVITE was a refresh and re-INVITEr ignored our offer */ ss->ss_oa_sent = NULL; if (sr->sr_request.sip->sip_contact) m = sr->sr_request.sip->sip_contact->m_url; else m = sr->sr_request.sip->sip_from->a_url; SU_DEBUG_3(("nua(%p): re-INVITEr ignored offer in our %u response " "(Contact: <" URL_PRINT_FORMAT ">)\n", (void *)nh, sr->sr_status, URL_PRINT_ARGS(m))); if (sr->sr_request.sip->sip_user_agent) SU_DEBUG_3(("nua(%p): re-INVITE: \"User-Agent: %s\"\n", (void *)nh, sr->sr_request.sip->sip_user_agent->g_string)); } else return process_ack_error(sr, msg, 488, "Offer-Answer error", "SIP;cause=488;text=\"No answer to offer\""); } else if (soa_set_remote_sdp(nh->nh_soa, NULL, sdp, len) >= 0 && soa_process_answer(nh->nh_soa, NULL) >= 0 && soa_activate(nh->nh_soa, NULL) >= 0) { ss->ss_sdp_version = soa_get_user_version(nh->nh_soa); } else { int status; char const *phrase, *reason; status = soa_error_as_sip_response(nh->nh_soa, &phrase); reason = soa_error_as_sip_reason(nh->nh_soa); return process_ack_error(sr, msg, status, phrase, reason); } } if (nh->nh_soa) soa_clear_remote_sdp(nh->nh_soa); nua_stack_event(nh->nh_nua, nh, msg, nua_i_ack, SIP_200_OK, NULL); signal_call_state_change(nh, ss, 200, "OK", nua_callstate_ready); session_timer_set(ss, uas = 1); nua_server_request_destroy(sr); return 0; } static int process_ack_error(nua_server_request_t *sr, msg_t *ackmsg, int status, char const *phrase, char const *reason) { nua_handle_t *nh = sr->sr_owner; nua_session_usage_t *ss = nua_dialog_usage_private(sr->sr_usage); int error; nua_stack_event(nh->nh_nua, nh, ackmsg, nua_i_ack, status, phrase, NULL); nua_stack_event(nh->nh_nua, nh, NULL, nua_i_media_error, status, phrase, NULL); if (reason) ss->ss_reason = reason; ss->ss_reporting = 1; error = nua_client_create(nh, nua_r_bye, &nua_bye_client_methods, NULL); ss->ss_reporting = 0; signal_call_state_change(nh, ss, 488, "Offer-Answer Error", /* We report terminated state if BYE failed */ error ? nua_callstate_terminated : nua_callstate_terminating); return 0; } /** @NUA_EVENT nua_i_cancel * * Incoming INVITE has been cancelled by the client. * * @param status status code of response to CANCEL sent automatically by stack * @param phrase a short textual description of @a status code * @param nh operation handle associated with the call * @param hmagic application context associated with the call * @param sip incoming CANCEL request * @param tags empty * * @sa @ref nua_uas_call_model, nua_cancel(), #nua_i_invite, #nua_i_state * * @END_NUA_EVENT */ /* CANCEL */ static int process_cancel(nua_server_request_t *sr, nta_incoming_t *irq, sip_t const *sip) { nua_handle_t *nh = sr->sr_owner; nua_session_usage_t *ss = nua_dialog_usage_private(sr->sr_usage); msg_t *cancel = nta_incoming_getrequest_ackcancel(irq); assert(ss); assert(ss == nua_session_usage_for_dialog(nh->nh_ds)); (void)ss; assert(nta_incoming_status(irq) < 200); nua_stack_event(nh->nh_nua, nh, cancel, nua_i_cancel, SIP_200_OK, NULL); sr->sr_application = SR_STATUS1(sr, SIP_487_REQUEST_TERMINATED); nua_server_respond(sr, NULL); nua_server_report(sr); return 0; } /* Timeout (no ACK or PRACK received) */ static int process_timeout(nua_server_request_t *sr, nta_incoming_t *irq) { nua_handle_t *nh = sr->sr_owner; nua_session_usage_t *ss = nua_dialog_usage_private(sr->sr_usage); char const *phrase = "ACK Timeout"; char const *reason = "SIP;cause=408;text=\"ACK Timeout\""; int error; assert(ss); assert(ss == nua_session_usage_for_dialog(nh->nh_ds)); if (nua_server_request_is_pending(sr)) { phrase = "PRACK Timeout"; reason = "SIP;cause=504;text=\"PRACK Timeout\""; } nua_stack_event(nh->nh_nua, nh, 0, nua_i_error, 408, phrase, NULL); if (nua_server_request_is_pending(sr)) { /* PRACK timeout */ SR_STATUS1(sr, SIP_504_GATEWAY_TIME_OUT); nua_server_trespond(sr, SIPTAG_REASON_STR(reason), TAG_END()); if (nua_server_report(sr) >= 2) return 0; /* Done */ sr = NULL; } /* send BYE, too, if 200 OK (or 183 to re-INVITE) timeouts */ ss->ss_reason = reason; ss->ss_reporting = 1; /* We report terminated state here if BYE fails */ error = nua_client_create(nh, nua_r_bye, &nua_bye_client_methods, NULL); ss->ss_reporting = 0; signal_call_state_change(nh, ss, 0, phrase, error ? nua_callstate_terminated : nua_callstate_terminating); if (sr) nua_server_request_destroy(sr); return 0; } /** @NUA_EVENT nua_i_prack * * Incoming PRACK request. PRACK request is used to acknowledge reliable * preliminary responses and it is usually sent automatically by the nua * stack. * * @param status status code of response sent automatically by stack * @param phrase a short textual description of @a status code * @param nh operation handle associated with the call * @param hmagic application context associated with the call * @param sip incoming PRACK request * @param tags empty * * @sa nua_prack(), #nua_r_prack, @RFC3262, NUTAG_EARLY_MEDIA() * * @END_NUA_EVENT */ int nua_prack_server_init(nua_server_request_t *sr); int nua_prack_server_respond(nua_server_request_t *sr, tagi_t const *tags); int nua_prack_server_report(nua_server_request_t *sr, tagi_t const *tags); nua_server_methods_t const nua_prack_server_methods = { SIP_METHOD_PRACK, nua_i_prack, /* Event */ { 0, /* Do not create dialog */ 1, /* In-dialog request */ 1, /* Target refresh request */ 1, /* Add Contact */ }, nua_prack_server_init, nua_base_server_preprocess, nua_base_server_params, nua_prack_server_respond, nua_prack_server_report, }; /** @internal Process reliable response PRACK or (timeout from 100rel) */ static int process_prack(nua_server_request_t *sr, nta_reliable_t *rel, nta_incoming_t *irq, sip_t const *sip) { nua_handle_t *nh; nta_reliable_destroy(rel); if (irq == NULL) /* Final response interrupted 100rel, we did not actually receive PRACK */ return 200; sr->sr_pracked = 1; if (!nua_server_request_is_pending(sr)) /* There is no INVITE anymore */ return 481; nh = sr->sr_owner; if (nh->nh_ds->ds_leg == NULL) return 500; if (sip == NULL) { /* 100rel timeout */ SR_STATUS(sr, 504, "Reliable Response Timeout"); nua_stack_event(nh->nh_nua, nh, NULL, nua_i_error, sr->sr_status, sr->sr_phrase, NULL); nua_server_trespond(sr, SIPTAG_REASON_STR("SIP;cause=504;" "text=\"PRACK Timeout\""), TAG_END()); nua_server_report(sr); return 504; } nta_incoming_bind(irq, NULL, (void *)sr); return nua_stack_process_request(nh, nh->nh_ds->ds_leg, irq, sip); } int nua_prack_server_init(nua_server_request_t *sr) { nua_handle_t *nh = sr->sr_owner; nua_server_request_t *sri = nta_incoming_magic(sr->sr_irq, NULL); if (sri == NULL) return SR_STATUS(sr, 481, "No Such Preliminary Response"); if (nua_session_server_init(sr)) return sr->sr_status; if (sr->sr_sdp) { nua_session_usage_t *ss = NUA_DIALOG_USAGE_PRIVATE(sr->sr_usage); char const *offeranswer; /* XXX - check for overlap? */ if (sri->sr_offer_sent && !sri->sr_answer_recv) sr->sr_answer_recv = 1, sri->sr_answer_recv = 1, offeranswer = Answer; else sr->sr_offer_recv = 1, offeranswer = Offer; ss->ss_oa_recv = offeranswer; if (nh->nh_soa && soa_set_remote_sdp(nh->nh_soa, NULL, sr->sr_sdp, sr->sr_sdp_len) < 0) { SU_DEBUG_5(("nua(%p): %s server: error parsing %s\n", (void *)nh, "PRACK", offeranswer)); return sr->sr_status = soa_error_as_sip_response(nh->nh_soa, &sr->sr_phrase); } } return 0; } int nua_prack_server_respond(nua_server_request_t *sr, tagi_t const *tags) { nua_handle_t *nh = sr->sr_owner; if (sr->sr_status < 200 || 300 <= sr->sr_status) return nua_base_server_respond(sr, tags); if (sr->sr_sdp) { nua_session_usage_t *ss = nua_dialog_usage_private(sr->sr_usage); msg_t *msg = sr->sr_response.msg; sip_t *sip = sr->sr_response.sip; if (nh->nh_soa == NULL) { if (sr->sr_offer_recv && session_get_description(sip, NULL, NULL)) sr->sr_answer_sent = 1, ss ? ss->ss_oa_sent = Answer : Answer; } else if ((sr->sr_offer_recv && soa_generate_answer(nh->nh_soa, NULL) < 0) || (sr->sr_answer_recv && soa_process_answer(nh->nh_soa, NULL) < 0)) { SU_DEBUG_5(("nua(%p): %s server: %s %s\n", (void *)nh, "PRACK", "error processing", sr->sr_offer_recv ? Offer : Answer)); sr->sr_status = soa_error_as_sip_response(nh->nh_soa, &sr->sr_phrase); } else if (sr->sr_offer_recv) { if (session_include_description(nh->nh_soa, 1, msg, sip) < 0) sr_status(sr, SIP_500_INTERNAL_SERVER_ERROR); else sr->sr_answer_sent = 1, ss ? ss->ss_oa_sent = Answer : Answer; } } return nua_base_server_respond(sr, tags); } int nua_prack_server_report(nua_server_request_t *sr, tagi_t const *tags) { nua_handle_t *nh = sr->sr_owner; nua_session_usage_t *ss = nua_dialog_usage_private(sr->sr_usage); nua_server_request_t *sri = nta_incoming_magic(sr->sr_irq, NULL); int status = sr->sr_status; char const *phrase = sr->sr_phrase; int offer_recv_or_answer_sent = sr->sr_offer_recv || sr->sr_answer_sent; int retval; retval = nua_base_server_report(sr, tags), sr = NULL; /* destroys sr */ if (retval >= 2 || ss == NULL) { #if 0 signal_call_state_change(nh, NULL, status, phrase, nua_callstate_terminated); #endif return retval; } if (offer_recv_or_answer_sent) { /* signal offer received, answer sent */ signal_call_state_change(nh, ss, status, phrase, ss->ss_state); if (nh->nh_soa) { if (soa_activate(nh->nh_soa, NULL) >= 0) ss->ss_sdp_version = soa_get_user_version(nh->nh_soa); } } if (status < 200 || 300 <= status) return retval; assert(sri); if (sri == NULL) { } else if (SR_HAS_SAVED_SIGNAL(sri)) { nua_signal_data_t const *e; e = nua_signal_data(sri->sr_signal); sri->sr_application = SR_STATUS(sri, e->e_status, e->e_phrase); nua_server_params(sri, e->e_tags); nua_server_respond(sri, e->e_tags); nua_server_report(sri); } else if (ss->ss_state < nua_callstate_ready && !ss->ss_alerting && !ss->ss_precondition && NH_PGET(nh, auto_alert)) { SR_STATUS1(sri, SIP_180_RINGING); nua_server_respond(sri, NULL); nua_server_report(sri); } return retval; } /* ---------------------------------------------------------------------- */ /* Automatic notifications from a referral */ static int nh_referral_check(nua_handle_t *nh, tagi_t const *tags) { sip_event_t const *event = NULL; int pause = 1; struct nua_referral *ref = nh->nh_referral; nua_handle_t *ref_handle = ref->ref_handle; if (!ref_handle && tl_gets(tags, NUTAG_NOTIFY_REFER_REF(ref_handle), NUTAG_REFER_EVENT_REF(event), NUTAG_REFER_PAUSE_REF(pause), TAG_END()) == 0 && tl_gets(nh->nh_tags, NUTAG_NOTIFY_REFER_REF(ref_handle), NUTAG_REFER_EVENT_REF(event), NUTAG_REFER_PAUSE_REF(pause), TAG_END()) == 0) return 0; if (!ref_handle) return 0; /* Remove nh_referral and nh_notevent */ tl_tremove(nh->nh_tags, NUTAG_NOTIFY_REFER(ref_handle), TAG_IF(event, NUTAG_REFER_EVENT(event)), TAG_END()); if (event) ref->ref_event = sip_event_dup(nh->nh_home, event); if (!nh_validate(nh->nh_nua, ref_handle)) { SU_DEBUG_3(("nua: invalid NOTIFY_REFER handle\n")); return -1; } else if (!ref->ref_event) { SU_DEBUG_3(("nua: NOTIFY event missing\n")); return -1; } if (ref_handle != ref->ref_handle) { if (ref->ref_handle) nua_handle_unref(ref->ref_handle); ref->ref_handle = nua_handle_ref(ref_handle); } #if 0 if (pause) { /* Pause media on REFER handle */ nmedia_pause(nua, ref_handle->nh_nm, NULL); } #endif return 0; } static void nh_referral_respond(nua_handle_t *nh, int status, char const *phrase) { char payload[128]; char const *substate; struct nua_referral *ref = nh->nh_referral; if (!nh_validate(nh->nh_nua, ref->ref_handle)) { if (ref) { if (ref->ref_handle) SU_DEBUG_1(("nh_handle_referral: stale referral handle %p\n", (void *)ref->ref_handle)); ref->ref_handle = NULL; } return; } /* XXX - we should have a policy here whether to send 101..199 */ assert(ref->ref_event); if (status >= 300) status = 503, phrase = sip_503_Service_unavailable; snprintf(payload, sizeof(payload), "SIP/2.0 %03u %s\r\n", status, phrase); if (status < 200) substate = "active"; else substate = "terminated ;reason=noresource"; nua_stack_post_signal(ref->ref_handle, nua_r_notify, SIPTAG_EVENT(ref->ref_event), SIPTAG_SUBSCRIPTION_STATE_STR(substate), SIPTAG_CONTENT_TYPE_STR("message/sipfrag"), SIPTAG_PAYLOAD_STR(payload), TAG_END()); if (status < 200) return; su_free(nh->nh_home, ref->ref_event), ref->ref_event = NULL; nua_handle_unref(ref->ref_handle), ref->ref_handle = NULL; } /* ======================================================================== */ /* INFO */ /**@fn void nua_info(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * * Send an INFO request. * * INFO is used to send call related information like DTMF * digit input events. See @RFC2976. * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Related Tags: * Header tags defined in . * * @par Events: * #nua_r_info * * @sa #nua_i_info */ nua_client_methods_t const nua_info_client_methods = { SIP_METHOD_INFO, /* crm_method, crm_method_name */ 0, /* crm_extra */ { /* crm_flags */ /* create_dialog */ 0, /* in_dialog */ 1, /* target refresh */ 0 }, NULL, /* crm_template */ NULL, /* crm_init */ NULL, /* crm_send */ NULL, /* crm_check_restart */ NULL, /* crm_recv */ NULL, /* crm_preliminary */ NULL, /* crm_report */ NULL, /* crm_complete */ }; int nua_stack_info(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { return nua_client_create(nh, e, &nua_info_client_methods, tags); } /** @NUA_EVENT nua_r_info * * Response to an outgoing @b INFO request. * * @param status response status code * (if the request is retried, @a status is 100, the @a * sip->sip_status->st_status contain the real status code * from the response message, e.g., 302, 401, or 407) * @param phrase a short textual description of @a status code * @param nh operation handle associated with the call * @param hmagic application context associated with the call * @param sip response to @b INFO or NULL upon an error * (status code is in @a status and * descriptive message in @a phrase parameters) * @param tags empty * * @sa nua_info(), #nua_i_info, @RFC2976 * * @END_NUA_EVENT */ /** @NUA_EVENT nua_i_info * * Incoming session INFO request. * * @param status statuscode of response sent automatically by stack * @param phrase a short textual description of @a status code * @param nh operation handle associated with the call * @param hmagic application context associated with the call * @param sip incoming INFO request * @param tags empty * * @sa nua_info(), #nua_r_info, @RFC2976 * * @END_NUA_EVENT */ nua_server_methods_t const nua_info_server_methods = { SIP_METHOD_INFO, nua_i_info, /* Event */ { 0, /* Do not create dialog */ 0, /* Allow outside dialog, too */ 0, /* Not a target refresh request */ 0, /* Do not add Contact */ }, nua_base_server_init, nua_base_server_preprocess, nua_base_server_params, nua_base_server_respond, nua_base_server_report, }; /* ======================================================================== */ /* UPDATE */ /**@fn void nua_update(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * * Update a session. * * Update a session using SIP UPDATE method. See @RFC3311. * * Update method can be used when the session has been established with * INVITE. It's mainly used during the session establishment when * preconditions are used (@RFC3312). It can be also used during the call if * no user input is needed for offer/answer negotiation. * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Related Tags: * same as nua_invite() * * @par Events: * #nua_r_update \n * #nua_i_state (#nua_i_active, #nua_i_terminated)\n * #nua_i_media_error \n * * @sa @ref nua_call_model, @RFC3311, nua_update(), #nua_i_update */ static int nua_update_client_init(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags); static int nua_update_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags); static int nua_update_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip); static int nua_update_client_report(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip, nta_outgoing_t *orq, tagi_t const *tags); nua_client_methods_t const nua_update_client_methods = { SIP_METHOD_UPDATE, /* crm_method, crm_method_name */ 0, /* crm_extrasize of private data */ { /* crm_flags */ /* create_dialog */ 0, /* in_dialog */ 1, /* target refresh */ 1 }, NULL, /* crm_template */ nua_update_client_init, /* crm_init */ nua_update_client_request, /* crm_send */ session_timer_check_restart, /* crm_check_restart */ nua_update_client_response, /* crm_recv */ NULL, /* crm_preliminary */ nua_update_client_report, /* crm_report */ NULL, /* crm_complete */ }; int nua_stack_update(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { return nua_client_create(nh, e, &nua_update_client_methods, tags); } static int nua_update_client_init(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = nua_dialog_usage_for_session(nh->nh_ds); cr->cr_usage = du; return 0; } static int nua_update_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = cr->cr_usage; nua_session_usage_t *ss; nua_server_request_t *sr; nua_client_request_t *cri; int offer_sent = 0, retval; if (du == NULL) /* Call terminated */ return nua_client_return(cr, SIP_481_NO_TRANSACTION, msg); ss = NUA_DIALOG_USAGE_PRIVATE(du); if (ss->ss_state >= nua_callstate_terminating) return nua_client_return(cr, 900, "Session is terminating", msg); cri = du->du_cr; for (sr = nh->nh_ds->ds_sr; sr; sr = sr->sr_next) if ((sr->sr_offer_sent && !sr->sr_answer_recv) || (sr->sr_offer_recv && !sr->sr_answer_sent)) break; if (nh->nh_soa == NULL) { offer_sent = session_get_description(sip, NULL, NULL); } else if (sr || (cri && cri->cr_offer_sent && !cri->cr_answer_recv) || (cri && cri->cr_offer_recv && !cri->cr_answer_sent)) { if (session_get_description(sip, NULL, NULL)) return nua_client_return(cr, 500, "Overlapping Offer/Answer", msg); } else if (!sip->sip_payload) { soa_init_offer_answer(nh->nh_soa); if (soa_generate_offer(nh->nh_soa, 0, NULL) < 0 || session_include_description(nh->nh_soa, 1, msg, sip) < 0) { if (ss->ss_state < nua_callstate_ready) { /* XXX - use soa_error_as_sip_reason(nh->nh_soa) */ cr->cr_graceful = 1; ss->ss_reason = "SIP;cause=400;text=\"Local media failure\""; } return nua_client_return(cr, 900, "Local media failed", msg); } offer_sent = 1; } /* Add session timer headers */ session_timer_preferences(ss->ss_timer, sip, NH_PGET(nh, supported), NH_PGET(nh, session_timer), NUA_PISSET(nh->nh_nua, nh, session_timer), NH_PGET(nh, refresher), NH_PGET(nh, min_se)); if (session_timer_is_supported(ss->ss_timer)) session_timer_add_headers(ss->ss_timer, ss->ss_state < nua_callstate_ready, msg, sip); retval = nua_base_client_request(cr, msg, sip, NULL); if (retval == 0) { enum nua_callstate state = ss->ss_state; cr->cr_offer_sent = offer_sent; ss->ss_update_needed = 0; if (state == nua_callstate_ready) state = nua_callstate_calling; /* XXX */ if (offer_sent) ss->ss_oa_sent = Offer; if (!cr->cr_restarting) /* Restart logic calls nua_update_client_report */ signal_call_state_change(nh, ss, 0, "UPDATE sent", state); } return retval; } static int nua_update_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = cr->cr_usage; nua_session_usage_t *ss = nua_dialog_usage_private(du); int uas; assert(200 <= status); if (ss && sip && status < 300) { if (session_timer_is_supported(ss->ss_timer)) { nua_server_request_t *sr; for (sr = nh->nh_ds->ds_sr; sr; sr = sr->sr_next) if (sr->sr_method == sip_method_invite || sr->sr_method == sip_method_update) break; if (!sr && (!du->du_cr || !du->du_cr->cr_orq)) { session_timer_store(ss->ss_timer, sip); session_timer_set(ss, uas = 0); } } } return nua_session_client_response(cr, status, phrase, sip); } /** @NUA_EVENT nua_r_update * * Answer to outgoing UPDATE. * * The UPDATE may be sent explicitly by nua_update() or * implicitly by NUA state machine. * * @param status response status code * (if the request is retried, @a status is 100, the @a * sip->sip_status->st_status contain the real status code * from the response message, e.g., 302, 401, or 407) * @param phrase a short textual description of @a status code * @param nh operation handle associated with the call * @param hmagic application context associated with the call * @param sip response to UPDATE request or NULL upon an error * (status code is in @a status and * descriptive message in @a phrase parameters) * @param tags empty * * @sa @ref nua_call_model, @RFC3311, nua_update(), #nua_i_update * * @END_NUA_EVENT */ static int nua_update_client_report(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip, nta_outgoing_t *orq, tagi_t const *tags) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = cr->cr_usage; nua_session_usage_t *ss = nua_dialog_usage_private(du); nua_stack_event(nh->nh_nua, nh, nta_outgoing_getresponse(orq), (enum nua_event_e)cr->cr_event, status, phrase, tags); if (!ss || cr->cr_terminated || cr->cr_graceful || cr->cr_waiting) return 1; if (cr->cr_offer_sent) { unsigned next_state = ss->ss_state; if (status < 200) ; else if (nua_invite_client_should_ack(du->du_cr)) { /* There is an un-ACK-ed INVITE there */ assert(du->du_cr->cr_method == sip_method_invite); if (NH_PGET(nh, auto_ack) || /* Auto-ACK response to re-INVITE when media is enabled and auto_ack is not set to 0 on handle */ (ss->ss_state == nua_callstate_ready && nh->nh_soa && !NH_PISSET(nh, auto_ack))) { if (nua_invite_client_ack(du->du_cr, NULL) > 0) next_state = nua_callstate_ready; else next_state = nua_callstate_terminating; } } signal_call_state_change(nh, ss, status, phrase, (enum nua_callstate)next_state); } return 1; } /* ---------------------------------------------------------------------- */ /* UPDATE server */ int nua_update_server_init(nua_server_request_t *sr); int nua_update_server_respond(nua_server_request_t *sr, tagi_t const *tags); int nua_update_server_report(nua_server_request_t *, tagi_t const *); nua_server_methods_t const nua_update_server_methods = { SIP_METHOD_UPDATE, nua_i_update, /* Event */ { 0, /* Do not create dialog */ 1, /* In-dialog request */ 1, /* Target refresh request */ 1, /* Add Contact */ }, nua_update_server_init, nua_base_server_preprocess, nua_base_server_params, nua_update_server_respond, nua_update_server_report, }; int nua_update_server_init(nua_server_request_t *sr) { nua_handle_t *nh = sr->sr_owner; nua_session_usage_t *ss; sip_t const *request = sr->sr_request.sip; if (nua_session_server_init(sr)) return sr->sr_status; ss = nua_dialog_usage_private(sr->sr_usage); /* Do session timer negotiation */ if (request->sip_session_expires) session_timer_store(ss->ss_timer, request); if (sr->sr_sdp) { /* Check for overlap */ nua_client_request_t *cr; nua_server_request_t *sr0; int overlap = 0; /* A UAS that receives an UPDATE before it has generated a final response to a previous UPDATE on the same dialog MUST return a 500 response to the new UPDATE, and MUST include a Retry-After header field with a randomly chosen value between 0 and 10 seconds. If an UPDATE is received that contains an offer, and the UAS has generated an offer (in an UPDATE, PRACK or INVITE) to which it has not yet received an answer, the UAS MUST reject the UPDATE with a 491 response. Similarly, if an UPDATE is received that contains an offer, and the UAS has received an offer (in an UPDATE, PRACK, or INVITE) to which it has not yet generated an answer, the UAS MUST reject the UPDATE with a 500 response, and MUST include a Retry-After header field with a randomly chosen value between 0 and 10 seconds. */ for (cr = nh->nh_ds->ds_cr; cr; cr = cr->cr_next) if ((overlap = cr->cr_offer_sent && !cr->cr_answer_recv)) break; if (!overlap) for (sr0 = nh->nh_ds->ds_sr; sr0; sr0 = sr0->sr_next) if ((overlap = sr0->sr_offer_recv && !sr0->sr_answer_sent)) break; if (nh->nh_soa && overlap) return nua_server_retry_after(sr, 500, "Overlapping Offer/Answer", 1, 9); if (nh->nh_soa && soa_set_remote_sdp(nh->nh_soa, NULL, sr->sr_sdp, sr->sr_sdp_len) < 0) { SU_DEBUG_5(("nua(%p): %s server: error parsing %s\n", (void *)nh, "UPDATE", Offer)); return sr->sr_status = soa_error_as_sip_response(nh->nh_soa, &sr->sr_phrase); } sr->sr_offer_recv = 1; ss ? ss->ss_oa_recv = Offer : Offer; } return 0; } /** @internal Respond to an UPDATE request. * */ int nua_update_server_respond(nua_server_request_t *sr, tagi_t const *tags) { nua_handle_t *nh = sr->sr_owner; nua_session_usage_t *ss = nua_dialog_usage_private(sr->sr_usage); msg_t *msg = sr->sr_response.msg; sip_t *sip = sr->sr_response.sip; if (200 <= sr->sr_status && sr->sr_status < 300 && sr->sr_sdp) { if (nh->nh_soa == NULL) { sr->sr_answer_sent = 1, ss ? ss->ss_oa_sent = Answer : Answer; } else if (soa_generate_answer(nh->nh_soa, NULL) < 0) { SU_DEBUG_5(("nua(%p): %s server: %s %s\n", (void *)nh, "UPDATE", "error processing", Offer)); sr->sr_status = soa_error_as_sip_response(nh->nh_soa, &sr->sr_phrase); } else if (soa_activate(nh->nh_soa, NULL) < 0) { SU_DEBUG_5(("nua(%p): %s server: error activating media\n", (void *)nh, "UPDATE")); /* XXX */ } else if (session_include_description(nh->nh_soa, 1, msg, sip) < 0) { sr_status(sr, SIP_500_INTERNAL_SERVER_ERROR); } else { sr->sr_answer_sent = 1, ss->ss_oa_sent = Answer; ss->ss_sdp_version = soa_get_user_version(nh->nh_soa); } } if (ss && 200 <= sr->sr_status && sr->sr_status < 300) { session_timer_preferences(ss->ss_timer, sip, NH_PGET(nh, supported), NH_PGET(nh, session_timer), NUA_PISSET(nh->nh_nua, nh, session_timer), NH_PGET(nh, refresher), NH_PGET(nh, min_se)); if (session_timer_is_supported(ss->ss_timer)) { nua_server_request_t *sr0; int uas; session_timer_add_headers(ss->ss_timer, 0, msg, sip); for (sr0 = nh->nh_ds->ds_sr; sr0; sr0 = sr0->sr_next) if (sr0->sr_method == sip_method_invite) break; if (!sr0 && (!sr->sr_usage->du_cr || !sr->sr_usage->du_cr->cr_orq)) session_timer_set(ss, uas = 1); } } return nua_base_server_respond(sr, tags); } /** @NUA_EVENT nua_i_update * * @brief Incoming session UPDATE request. * * @param status statuscode of response sent automatically by stack * @param phrase a short textual description of @a status code * @param nh operation handle associated with the call * @param hmagic application context associated with the call * @param sip incoming UPDATE request * @param tags empty * * @sa nua_update(), #nua_r_update, #nua_i_state * * @END_NUA_EVENT */ int nua_update_server_report(nua_server_request_t *sr, tagi_t const *tags) { nua_handle_t *nh = sr->sr_owner; nua_dialog_usage_t *du = sr->sr_usage; nua_session_usage_t *ss = nua_dialog_usage_private(du); int status = sr->sr_status; char const *phrase = sr->sr_phrase; int offer_recv_or_answer_sent = sr->sr_offer_recv || sr->sr_answer_sent; int retval; retval = nua_base_server_report(sr, tags), sr = NULL; /* destroys sr */ if (retval >= 2 || ss == NULL) { #if 0 signal_call_state_change(nh, NULL, status, phrase, nua_callstate_terminated); #endif return retval; } if (offer_recv_or_answer_sent) { /* signal offer received, answer sent */ enum nua_callstate state = ss->ss_state; if (state == nua_callstate_ready && status < 200) state = nua_callstate_received; signal_call_state_change(nh, ss, status, phrase, state); } if (200 <= status && status < 300 && ss->ss_state < nua_callstate_ready && ss->ss_precondition && !ss->ss_alerting && NH_PGET(nh, auto_alert)) { nua_server_request_t *sri; for (sri = nh->nh_ds->ds_sr; sri; sri = sri->sr_next) if (sri->sr_method == sip_method_invite && nua_server_request_is_pending(sri)) break; if (sri) { SR_STATUS1(sri, SIP_180_RINGING); nua_server_respond(sri, NULL); nua_server_report(sri); } } return retval; } /* ======================================================================== */ /* BYE */ /**@fn void nua_bye(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * * Hangdown a call. * * Hangdown a call using SIP BYE method. Also the media session * associated with the call is terminated. * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Related Tags: * none * * @par Events: * #nua_r_bye \n * #nua_i_media_error */ static int nua_bye_client_init(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags); static int nua_bye_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags); static int nua_bye_client_report(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip, nta_outgoing_t *orq, tagi_t const *tags); nua_client_methods_t const nua_bye_client_methods = { SIP_METHOD_BYE, /* crm_method, crm_method_name */ 0, /* crm_extrasize */ { /* crm_flags */ /* create_dialog */ 0, /* in_dialog */ 1, /* target refresh */ 0 }, NULL, /* crm_template */ nua_bye_client_init, /* crm_init */ nua_bye_client_request, /* crm_send */ NULL, /* crm_check_restart */ NULL, /* crm_recv */ NULL, /* crm_preliminary */ nua_bye_client_report, /* crm_report */ NULL, /* crm_complete */ }; int nua_stack_bye(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { nua_session_usage_t *ss = nua_session_usage_for_dialog(nh->nh_ds); if (ss && nua_callstate_calling <= ss->ss_state && ss->ss_state <= nua_callstate_proceeding) return nua_client_create(nh, e, &nua_cancel_client_methods, tags); else return nua_client_create(nh, e, &nua_bye_client_methods, tags); } static int nua_bye_client_init(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = nua_dialog_usage_for_session(nh->nh_ds); nua_session_usage_t *ss = nua_dialog_usage_private(du); if (!ss || (ss->ss_state >= nua_callstate_terminating && !cr->cr_auto)) return nua_client_return(cr, 900, "Invalid handle for BYE", msg); if (!cr->cr_auto) /* Implicit state transition by nua_bye() */ ss->ss_state = nua_callstate_terminating; if (nh->nh_soa) soa_terminate(nh->nh_soa, 0); nua_client_bind(cr, du); return 0; } static int nua_bye_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags) { nua_dialog_usage_t *du = cr->cr_usage; nua_session_usage_t *ss; char const *reason = NULL; int error; nua_server_request_t *sr; if (du == NULL) return nua_client_return(cr, SIP_481_NO_TRANSACTION, msg); ss = nua_dialog_usage_private(du); reason = ss->ss_reason; error = nua_base_client_trequest(cr, msg, sip, SIPTAG_REASON_STR(reason), TAG_NEXT(tags)); if (error == 0) { nua_dialog_usage_reset_refresh(du); ss->ss_timer->timer_set = 0; /* Terminate server transactions associated with session, too. */ for (sr = du->du_dialog->ds_sr; sr; sr = sr->sr_next) { if (sr->sr_usage == du && nua_server_request_is_pending(sr) && sr->sr_method != sip_method_bye) { sr_status(sr, SIP_486_BUSY_HERE); nua_server_respond(sr, 0); } } } return error; } /** @NUA_EVENT nua_r_bye * * Answer to outgoing BYE. * * The BYE may be sent explicitly by nua_bye() or implicitly by NUA state * machine. * * @param status response status code * (if the request is retried, @a status is 100, the @a * sip->sip_status->st_status contain the real status code * from the response message, e.g., 302, 401, or 407) * @param phrase a short textual description of @a status code * @param nh operation handle associated with the call * @param hmagic application context associated with the call * @param sip response to BYE request or NULL upon an error * (status code is in @a status and * descriptive message in @a phrase parameters) * @param tags empty * * @sa nua_bye(), @ref nua_call_model, #nua_i_state, #nua_r_invite() * * @END_NUA_EVENT */ static int nua_bye_client_report(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip, nta_outgoing_t *orq, tagi_t const *tags) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = cr->cr_usage; nua_stack_event(nh->nh_nua, nh, nta_outgoing_getresponse(orq), (enum nua_event_e)cr->cr_event, status, phrase, tags); if (du == NULL) { /* No more session */ } else if (status < 200) { /* Preliminary */ } else { nua_session_usage_t *ss = nua_dialog_usage_private(du); nua_client_request_t *cri; if (ss->ss_reporting) { return 1; /* Somebody else's problem */ } else if (cr->cr_waiting) { return 1; /* Application problem */ } nua_client_bind(cr, NULL); signal_call_state_change(nh, ss, status, "to BYE", nua_callstate_terminated); for (cri = du->du_dialog->ds_cr; cri; cri = cri->cr_next) { if (cri->cr_method == sip_method_invite) break; } if (!cri || cri->cr_status >= 200) { /* INVITE is completed, we can zap the session... */; nua_session_usage_destroy(nh, ss); } } return 1; } /** @NUA_EVENT nua_i_bye * * Incoming BYE request, call hangup. * * @param status statuscode of response sent automatically by stack * @param phrase a short textual description of @a status code * @param nh operation handle associated with the call * @param hmagic application context associated with the call * @param sip pointer to BYE request * @param tags empty * * @sa @ref nua_call_model, #nua_i_state, nua_bye(), nua_bye(), #nua_r_cancel * * @END_NUA_EVENT */ int nua_bye_server_init(nua_server_request_t *sr); int nua_bye_server_report(nua_server_request_t *sr, tagi_t const *tags); nua_server_methods_t const nua_bye_server_methods = { SIP_METHOD_BYE, nua_i_bye, /* Event */ { 0, /* Do not create dialog */ 1, /* In-dialog request */ 0, /* Not a target refresh request */ 0, /* Do not add Contact */ }, nua_bye_server_init, nua_base_server_preprocess, nua_base_server_params, nua_base_server_respond, nua_bye_server_report, }; int nua_bye_server_init(nua_server_request_t *sr) { nua_handle_t *nh = sr->sr_owner; nua_dialog_usage_t *du = nua_dialog_usage_for_session(nh->nh_ds); sr->sr_terminating = 1; if (du) sr->sr_usage = du; else return SR_STATUS(sr, 481, "No Such Call"); return 0; } int nua_bye_server_report(nua_server_request_t *sr, tagi_t const *tags) { nua_handle_t *nh = sr->sr_owner; nua_dialog_usage_t *du = sr->sr_usage; nua_session_usage_t *ss = nua_dialog_usage_private(du); int early = 0, retval; if (sr->sr_status < 200) return nua_base_server_report(sr, tags); if (ss) { nua_server_request_t *sr0 = NULL, *sr_next; char const *phrase; early = ss->ss_state < nua_callstate_ready; phrase = early ? "Early Session Terminated" : "Session Terminated"; #if 0 sr->sr_usage = NULL; #endif for (sr0 = nh->nh_ds->ds_sr; sr0; sr0 = sr_next) { sr_next = sr0->sr_next; if (sr == sr0 || sr0->sr_usage != sr->sr_usage) continue; if (nua_server_request_is_pending(sr0)) { SR_STATUS(sr0, 487, phrase); nua_server_respond(sr0, NULL); } nua_server_request_destroy(sr0); } sr->sr_phrase = phrase; } retval = nua_base_server_report(sr, tags); #if 0 if (ss) { signal_call_state_change(nh, ss, 200, early ? "Received early BYE" : "Received BYE", nua_callstate_terminated); nua_dialog_usage_remove(nh, nh->nh_ds, du); } #endif return retval; } /* ---------------------------------------------------------------------- */ /** @NUA_EVENT nua_i_state * * @brief Call state has changed. * * This event will be sent whenever the call state changes. * * In addition to basic changes of session status indicated with enum * ::nua_callstate, the @RFC3264 SDP Offer/Answer negotiation status is also * included. The tags NUTAG_OFFER_RECV() or NUTAG_ANSWER_RECV() indicate * whether the remote SDP that was received was considered as an offer or an * answer. Tags NUTAG_OFFER_SENT() or NUTAG_ANSWER_SENT() indicate whether * the local SDP which was sent was considered as an offer or answer. * * If the @b soa SDP negotiation is enabled (by default or with * NUTAG_MEDIA_ENABLE(1)), the received remote SDP is included in tags * SOATAG_REMOTE_SDP() and SOATAG_REMOTE_SDP_STR(). The SDP negotiation * result from @b soa is included in the tags SOATAG_LOCAL_SDP() and * SOATAG_LOCAL_SDP_STR(). * * SOATAG_ACTIVE_AUDIO() and SOATAG_ACTIVE_VIDEO() are informational tags * used to indicate what is the status of audio or video. * * Note that #nua_i_state also covers the information relayed in call * establisment (#nua_i_active) and termination (#nua_i_terminated) events. * * @param status protocol status code \n * (always present) * @param phrase short description of status code \n * (always present) * @param nh operation handle associated with the call * @param hmagic application context associated with the call * @param sip NULL * @param tags NUTAG_CALLSTATE(), * SOATAG_LOCAL_SDP(), SOATAG_LOCAL_SDP_STR(), * NUTAG_OFFER_SENT(), NUTAG_ANSWER_SENT(), * SOATAG_REMOTE_SDP(), SOATAG_REMOTE_SDP_STR(), * NUTAG_OFFER_RECV(), NUTAG_ANSWER_RECV(), * SOATAG_ACTIVE_AUDIO(), SOATAG_ACTIVE_VIDEO(), * SOATAG_ACTIVE_IMAGE(), SOATAG_ACTIVE_CHAT(). * * @sa @ref nua_call_model, #nua_i_active, #nua_i_terminated, * nua_invite(), #nua_r_invite, #nua_i_invite, nua_respond(), * NUTAG_MEDIA_ENABLE(), * NUTAG_AUTOALERT(), NUTAG_AUTOANSWER(), NUTAG_EARLY_MEDIA(), * NUTAG_EARLY_ANSWER(), NUTAG_INCLUDE_EXTRA_SDP(), * nua_ack(), NUTAG_AUTOACK(), nua_bye(), #nua_r_bye, #nua_i_bye, * nua_cancel(), #nua_r_cancel, #nua_i_cancel, * nua_prack(), #nua_r_prack, #nua_i_prack, * nua_update(), #nua_r_update, #nua_i_update * * @par History * Prior @VERSION_1_12_6 the tags NUTAG_OFFER_RECV(), NUTAG_ANSWER_RECV(), * NUTAG_ANSWER_SENT(), NUTAG_OFFER_SENT() were not included with * nua_i_state eventif media was disabled. * * @END_NUA_EVENT */ /** * Delivers call state changed event to the nua client. @internal * * @param nh call handle * @param status status code * @param tr_event SIP transaction event triggering this change * @param oa_recv Received SDP * @param oa_sent Sent SDP */ static void signal_call_state_change(nua_handle_t *nh, nua_session_usage_t *ss, int status, char const *phrase, enum nua_callstate next_state) { enum nua_callstate ss_state = nua_callstate_init; enum nua_callstate invite_state = next_state; char const *oa_recv = NULL; char const *oa_sent = NULL; int offer_recv = 0, answer_recv = 0, offer_sent = 0, answer_sent = 0; if (ss) { if (ss->ss_reporting) return; ss_state = ss->ss_state; oa_recv = ss->ss_oa_recv, ss->ss_oa_recv = NULL; oa_sent = ss->ss_oa_sent, ss->ss_oa_sent = NULL; assert(oa_sent == Offer || oa_sent == Answer || oa_sent == NULL); assert(oa_recv == Offer || oa_recv == Answer || oa_recv == NULL); if (oa_recv) { offer_recv = oa_recv == Offer; answer_recv = oa_recv == Answer; } if (oa_sent) { offer_sent = oa_sent == Offer; answer_sent = oa_sent == Answer; } } if (ss_state < nua_callstate_ready || next_state > nua_callstate_ready) SU_DEBUG_5(("nua(%p): call state changed: %s -> %s%s%s%s%s\n", (void *)nh, nua_callstate_name(ss_state), nua_callstate_name(next_state), oa_recv ? ", received " : "", oa_recv ? oa_recv : "", oa_sent && oa_recv ? ", and sent " : oa_sent ? ", sent " : "", oa_sent ? oa_sent : "")); else SU_DEBUG_5(("nua(%p): ready call updated: %s%s%s%s%s\n", (void *)nh, nua_callstate_name(next_state), oa_recv ? " received " : "", oa_recv ? oa_recv : "", oa_sent && oa_recv ? ", sent " : oa_sent ? " sent " : "", oa_sent ? oa_sent : "")); if (next_state == nua_callstate_terminating && ss_state >= nua_callstate_terminating) return; if (ss) { /* Update state variables */ if (next_state == nua_callstate_init) { if (ss_state < nua_callstate_ready) ss->ss_state = next_state; else if (ss->ss_state == nua_callstate_ready) next_state = ss->ss_state; else if (ss->ss_state == nua_callstate_terminating) return; else ss->ss_state = next_state = nua_callstate_terminated; } else if (next_state > ss_state) ss->ss_state = next_state; } if (next_state == nua_callstate_init) next_state = nua_callstate_terminated; if (ss && ss->ss_state == nua_callstate_ready) nh->nh_active_call = 1; else if (next_state == nua_callstate_terminated) nh->nh_active_call = 0; /* Send events */ if (phrase == NULL) phrase = "Call state"; { sdp_session_t const *remote_sdp = NULL; char const *remote_sdp_str = NULL; sdp_session_t const *local_sdp = NULL; char const *local_sdp_str = NULL; if (nh->nh_soa) { if (oa_recv) soa_get_remote_sdp(nh->nh_soa, &remote_sdp, &remote_sdp_str, 0); if (oa_sent) soa_get_local_sdp(nh->nh_soa, &local_sdp, &local_sdp_str, 0); if (answer_recv || answer_sent) { /* Update nh_hold_remote */ char const *held = NULL; soa_get_params(nh->nh_soa, SOATAG_HOLD_REF(held), TAG_END()); nh->nh_hold_remote = held && strlen(held) > 0; } } else oa_recv = NULL, oa_sent = NULL; nua_stack_tevent(nh->nh_nua, nh, NULL, nua_i_state, status, phrase, NUTAG_CALLSTATE(next_state), NH_ACTIVE_MEDIA_TAGS(1, nh->nh_soa), /* NUTAG_SOA_SESSION(nh->nh_soa), */ TAG_IF(offer_recv, NUTAG_OFFER_RECV(offer_recv)), TAG_IF(answer_recv, NUTAG_ANSWER_RECV(answer_recv)), TAG_IF(offer_sent, NUTAG_OFFER_SENT(offer_sent)), TAG_IF(answer_sent, NUTAG_ANSWER_SENT(answer_sent)), TAG_IF(oa_recv, SOATAG_REMOTE_SDP(remote_sdp)), TAG_IF(oa_recv, SOATAG_REMOTE_SDP_STR(remote_sdp_str)), TAG_IF(oa_sent, SOATAG_LOCAL_SDP(local_sdp)), TAG_IF(oa_sent, SOATAG_LOCAL_SDP_STR(local_sdp_str)), TAG_END()); } if (next_state == nua_callstate_ready && ss_state <= nua_callstate_ready) { nua_stack_tevent(nh->nh_nua, nh, NULL, nua_i_active, status, "Call active", NH_ACTIVE_MEDIA_TAGS(1, nh->nh_soa), /* NUTAG_SOA_SESSION(nh->nh_soa), */ TAG_END()); } else if (next_state == nua_callstate_terminated) { nua_stack_event(nh->nh_nua, nh, NULL, nua_i_terminated, status, phrase, NULL); } if (invite_state == nua_callstate_ready) { /* Start next INVITE request, if queued */ nua_client_next_request(nh->nh_ds->ds_cr, 1); } } /** @NUA_EVENT nua_i_active * * A call has been activated. * * This event will be sent after a succesful response to the initial * INVITE has been received and the media has been activated. * * @param nh operation handle associated with the call * @param hmagic application context associated with the call * @param sip NULL * @param tags SOATAG_ACTIVE_AUDIO(), SOATAG_ACTIVE_VIDEO(), * SOATAG_ACTIVE_IMAGE(), SOATAG_ACTIVE_CHAT(). * * @deprecated Use #nua_i_state instead. * * @sa @ref nua_call_model, #nua_i_state, #nua_i_terminated, * #nua_i_invite * * @END_NUA_EVENT */ /** @NUA_EVENT nua_i_terminated * * A call has been terminated. * * This event will be sent after a call has been terminated. A call is * terminated, when * 1) an error response (300..599) is sent to an incoming initial INVITE * 2) a reliable response (200..299 or reliable preliminary response) to * an incoming initial INVITE is not acknowledged with ACK or PRACK * 3) BYE is received or sent * * @param nh operation handle associated with the call * @param hmagic application context associated with the call * @param sip NULL * @param tags empty * * @deprecated Use #nua_i_state instead. * * @sa @ref nua_call_model, #nua_i_state, #nua_i_active, #nua_i_bye, * #nua_i_invite * * @END_NUA_EVENT */ /* ======================================================================== */ static int nua_server_retry_after(nua_server_request_t *sr, int status, char const *phrase, int min, int max) { sip_retry_after_t af[1]; sip_retry_after_init(af); af->af_delta = (unsigned)su_randint(min, max); af->af_comment = phrase; sip_add_dup(sr->sr_response.msg, sr->sr_response.sip, (sip_header_t *)af); return sr_status(sr, status, phrase); } /* ======================================================================== */ /* Session timer - RFC 4028 */ static int session_timer_is_supported(struct session_timer const *t) { return t->local.supported; } /** Set session timer preferences */ static void session_timer_preferences(struct session_timer *t, sip_t const *sip, sip_supported_t const *supported, unsigned expires, int isset, enum nua_session_refresher refresher, unsigned min_se) { memset(&t->local, 0, sizeof t->local); t->local.require = sip_has_feature(sip->sip_require, "timer"); t->local.supported = sip_has_feature(supported, "timer") || sip_has_feature(sip->sip_supported, "timer"); if (isset || refresher != nua_no_refresher) t->local.expires = expires; else t->local.defaults = expires; t->local.min_se = min_se; t->local.refresher = refresher; } static int session_timer_check_restart(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip) { if (status == 422) { nua_session_usage_t *ss = nua_dialog_usage_private(cr->cr_usage); if (ss && session_timer_is_supported(ss->ss_timer)) { struct session_timer *t = ss->ss_timer; if (sip->sip_min_se && t->local.min_se < sip->sip_min_se->min_delta) t->local.min_se = sip->sip_min_se->min_delta; if (t->local.expires != 0 && t->local.min_se > t->local.expires) t->local.expires = t->local.min_se; return nua_client_restart(cr, 100, "Re-Negotiating Session Timer"); } } return nua_base_client_check_restart(cr, status, phrase, sip); } /** Check that received Session-Expires is longer than Min-SE */ static int session_timer_check_min_se(msg_t *msg, sip_t *sip, sip_t const *request, unsigned long min) { if (min == 0) min = 1; /* If an incoming request contains a Supported header field with a value 'timer' and a Session Expires header field, the UAS MAY reject the INVITE request with a 422 (Session Interval Too Small) response if the session interval in the Session-Expires header field is smaller than the minimum interval defined by the UAS' local policy. When sending the 422 response, the UAS MUST include a Min-SE header field with the value of its minimum interval. This minimum interval MUST NOT be lower than 90 seconds. */ if (request->sip_session_expires && sip_has_feature(request->sip_supported, "timer") && request->sip_session_expires->x_delta < min) { sip_min_se_t min_se[1]; if (min < 90) min = 90; sip_min_se_init(min_se)->min_delta = min; /* Include extension parameters, if any */ if (request->sip_min_se) min_se->min_params = request->sip_min_se->min_params; sip_add_dup(msg, sip, (sip_header_t *)min_se); return 422; } return 0; } /** Store session timer parameters in request from uac / response from uas */ static void session_timer_store(struct session_timer *t, sip_t const *sip) { sip_require_t const *require = sip->sip_require; sip_supported_t const *supported = sip->sip_supported; sip_session_expires_t const *x = sip->sip_session_expires; t->remote.require = require && sip_has_feature(require, "timer"); t->remote.supported = t->remote.supported || (supported && sip_has_feature(supported, "timer")); t->remote.expires = 0; t->remote.refresher = nua_any_refresher; t->remote.min_se = 0; if (x) { t->remote.expires = x->x_delta; if (x->x_refresher) { int uas = sip->sip_request != NULL; if (su_casenmatch(x->x_refresher, "uac", (sizeof "uac"))) t->remote.refresher = uas ? nua_remote_refresher : nua_local_refresher; else if (su_casenmatch(x->x_refresher, "uas", (sizeof "uas"))) t->remote.refresher = uas ? nua_local_refresher : nua_remote_refresher; } else if (t->remote.require) { /* Require: timer but no refresher parameter in Session-Expires header */ t->remote.refresher = nua_local_refresher; } } if (sip->sip_min_se) t->remote.min_se = sip->sip_min_se->min_delta; } /** Add timer feature and Session-Expires/Min-SE headers to request/response * */ static int session_timer_add_headers(struct session_timer *t, int initial, msg_t *msg, sip_t *sip) { unsigned long expires, min; sip_min_se_t min_se[1]; sip_session_expires_t x[1]; int uas; enum nua_session_refresher refresher = nua_any_refresher; static sip_param_t const x_params_uac[] = {"refresher=uac", NULL}; static sip_param_t const x_params_uas[] = {"refresher=uas", NULL}; if (!t->local.supported) return 0; uas = sip->sip_status != NULL; min = t->local.min_se; if (min < t->remote.min_se) min = t->remote.min_se; if (uas) { session_timer_negotiate(t, uas = 1); refresher = t->refresher; expires = t->interval; } else { /* RFC 4028: * The UAC MAY include the refresher parameter with value 'uac' if it * wants to perform the refreshes. However, it is RECOMMENDED that the * parameter be omitted so that it can be selected by the negotiation * mechanisms described below. */ if (t->local.refresher == nua_local_refresher) refresher = nua_local_refresher; else if (!initial) refresher = t->refresher; expires = t->local.expires; if (expires != 0 && expires < min) expires = min; if (expires == 0 && !initial && t->interval) expires = t->interval; } sip_min_se_init(min_se)->min_delta = min; sip_session_expires_init(x)->x_delta = expires; if (refresher == nua_remote_refresher) x->x_params = uas ? x_params_uac : x_params_uas; else if (refresher == nua_local_refresher) x->x_params = uas ? x_params_uas : x_params_uac; if (expires == 0 && t->remote.min_se == 0) /* Session timer is not used, do not add headers */ return 1; sip_add_tl(msg, sip, TAG_IF(expires != 0, SIPTAG_SESSION_EXPIRES(x)), TAG_IF(min != 0 /* Min-SE: 0 is optional with initial INVITE */ || !initial, SIPTAG_MIN_SE(min_se)), TAG_IF(refresher == nua_remote_refresher && expires != 0, SIPTAG_REQUIRE_STR("timer")), TAG_END()); return 1; } static void session_timer_negotiate(struct session_timer *t, int uas) { if (!t->local.supported) t->refresher = nua_no_refresher; else if (!t->remote.supported) t->refresher = nua_local_refresher; else if (t->remote.refresher == nua_local_refresher) t->refresher = nua_local_refresher; else if (t->remote.refresher == nua_remote_refresher) t->refresher = nua_remote_refresher; else if (uas) /* UAS defaults UAC to refreshing */ t->refresher = nua_remote_refresher; else /* UAC refreshes by itself */ t->refresher = nua_local_refresher; t->interval = t->remote.expires; if (t->interval == 0) t->interval = t->local.expires; if (t->local.expires != 0 && t->interval > t->local.expires) t->interval = t->local.expires; if (t->local.defaults != 0 && t->interval > t->local.defaults) t->interval = t->local.defaults; if (t->interval != 0) { if (t->interval < t->local.min_se) t->interval = t->local.min_se; if (t->interval < t->remote.min_se) t->interval = t->remote.min_se; } if (t->interval == 0) t->refresher = nua_no_refresher; } static void session_timer_set(nua_session_usage_t *ss, int uas) { nua_dialog_usage_t *du = nua_dialog_usage_public(ss); struct session_timer *t; if (ss == NULL) return; t = ss->ss_timer; session_timer_negotiate(t, uas); if (t->refresher == nua_local_refresher) { unsigned low = t->interval / 2, high = t->interval / 2; if (t->interval >= 90) low -=5, high += 5; nua_dialog_usage_set_refresh_range(du, low, high); t->timer_set = 1; } else if (t->refresher == nua_remote_refresher) { /* RFC 4028 section 10: "Similarly, if the side not performing refreshes does not receive a session refresh request before the session expiration, it SHOULD send a BYE to terminate the session, slightly before the session expiration. The minimum of 32 seconds and one third of the session interval is RECOMMENDED." However, we use increased interval from 2/3 to 9/10 of session expiration delay because some endpoints won't UPDATE early enough with very short sessions (e.g. 120). */ unsigned interval; if (t->interval / 10 < 32) interval = t->interval - t->interval / 10; else interval = t->interval - 32; nua_dialog_usage_set_refresh_range(du, interval, interval); t->timer_set = 1; } else { nua_dialog_usage_reset_refresh(du); t->timer_set = 0; } } su_inline int session_timer_has_been_set(struct session_timer const *t) { return t->timer_set; } /* ======================================================================== */ static int session_get_multipart_description(msg_multipart_t *mp, char const **return_sdp, size_t *return_len) { /* Find the SDP from multiparts */ for (; mp; mp = mp->mp_next) { msg_content_type_t *c = mp->mp_content_type; if (!c || !c->c_type || !mp->mp_payload) continue; if (!su_casematch(c->c_type, SDP_MIME_TYPE)) continue; if (return_sdp) *return_sdp = mp->mp_payload->pl_data; if (return_len) *return_len = mp->mp_payload->pl_len; return 1; } return 0; } /** Get SDP from a SIP message. * * @retval 1 if message contains SDP * @retval 0 if message does not contain valid SDP */ static int session_get_description(sip_t const *sip, char const **return_sdp, size_t *return_len) { sip_payload_t const *pl; sip_content_type_t const *ct; int matching_content_type = 0; if (sip == NULL) return 0; pl = sip->sip_payload; if (pl == NULL || pl->pl_len == 0 || pl->pl_data == NULL) return 0; ct = sip->sip_content_type; if (ct == NULL) /* Be bug-compatible with our old gateways */ SU_DEBUG_3(("nua: no %s, assuming %s\n", "Content-Type", SDP_MIME_TYPE)); else if (ct->c_type == NULL) SU_DEBUG_3(("nua: empty %s, assuming %s\n", "Content-Type", SDP_MIME_TYPE)); else if (sip->sip_multipart) { return session_get_multipart_description(sip->sip_multipart, return_sdp, return_len); } else if (!su_casematch(ct->c_type, SDP_MIME_TYPE)) { SU_DEBUG_5(("nua: unknown %s: %s\n", "Content-Type", ct->c_type)); return 0; } else matching_content_type = 1; if (!matching_content_type) { /* Make sure we got SDP */ if (pl->pl_len < 3 || !su_casenmatch(pl->pl_data, "v=0", 3)) return 0; } if (return_sdp && return_len) { *return_sdp = pl->pl_data; *return_len = pl->pl_len; } return 1; } /** Insert SDP into SIP message */ static int session_include_description(soa_session_t *soa, int session, msg_t *msg, sip_t *sip) { su_home_t *home = msg_home(msg); sip_content_disposition_t *cd = NULL; sip_content_type_t *ct = NULL; sip_payload_t *pl = NULL; int retval; if (!soa) return 0; retval = session_make_description(home, soa, session, &cd, &ct, &pl); if (retval <= 0) return retval; if ((cd && sip_header_insert(msg, sip, (sip_header_t *)cd) < 0) || sip_header_insert(msg, sip, (sip_header_t *)ct) < 0 || sip_header_insert(msg, sip, (sip_header_t *)pl) < 0) return -1; return retval; } /** Generate SDP headers */ static int session_make_description(su_home_t *home, soa_session_t *soa, int session, sip_content_disposition_t **return_cd, sip_content_type_t **return_ct, sip_payload_t **return_pl) { char const *sdp; isize_t len; int retval; if (!soa) return 0; if (session) retval = soa_get_local_sdp(soa, 0, &sdp, &len); else retval = soa_get_capability_sdp(soa, 0, &sdp, &len); if (retval > 0) { *return_pl = sip_payload_create(home, sdp, len); *return_ct = sip_content_type_make(home, SDP_MIME_TYPE); if (session) *return_cd = sip_content_disposition_make(home, "session"); else *return_cd = NULL; if (!*return_pl || !*return_ct) return -1; if (session && !*return_cd) return -1; } return retval; } /* ====================================================================== */ /** @NUA_EVENT nua_i_options * * Incoming OPTIONS request. The user-agent should respond to an OPTIONS * request with the same statuscode as it would respond to an INVITE * request. * * Stack responds automatically to OPTIONS request unless OPTIONS is * included in the set of application methods, set by NUTAG_APPL_METHOD(). * * The OPTIONS request does not create a dialog. Currently the processing * of incoming OPTIONS creates a new handle for each incoming request which * is not assiciated with an existing dialog. If the handle @a nh is not * bound, you should probably destroy it after responding to the OPTIONS * request. * * @param status status code of response sent automatically by stack * @param phrase a short textual description of @a status code * @param nh operation handle associated with the OPTIONS request * @param hmagic application context associated with the call * (NULL if outside session) * @param sip incoming OPTIONS request * @param tags empty * * @sa nua_respond(), nua_options(), #nua_r_options, @RFC3261 section 11.2 * * @END_NUA_EVENT */ int nua_options_server_respond(nua_server_request_t *sr, tagi_t const *tags); nua_server_methods_t const nua_options_server_methods = { SIP_METHOD_OPTIONS, nua_i_options, /* Event */ { 0, /* Do not create dialog */ 0, /* Initial request */ 0, /* Not a target refresh request */ 1, /* Add Contact */ }, nua_base_server_init, nua_base_server_preprocess, nua_base_server_params, nua_options_server_respond, nua_base_server_report, }; /** @internal Respond to an OPTIONS request. * */ int nua_options_server_respond(nua_server_request_t *sr, tagi_t const *tags) { nua_handle_t *nh = sr->sr_owner; nua_t *nua = nh->nh_nua; if (200 <= sr->sr_status && sr->sr_status < 300) { msg_t *msg = sr->sr_response.msg; sip_t *sip = sr->sr_response.sip; sip_add_tl(msg, sip, SIPTAG_ACCEPT(nua->nua_invite_accept), TAG_END()); if (!sip->sip_payload) { /* XXX - do MIME multipart? */ soa_session_t *soa = nh->nh_soa; if (soa == NULL) soa = nua->nua_dhandle->nh_soa; session_include_description(soa, 0, msg, sip); } } return nua_base_server_respond(sr, tags); } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/nua_stack.c000066400000000000000000000665411223300710500224650ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE nua_stack.c * @brief Sofia-SIP User Agent Engine implementation * * @author Pekka Pessi * @author Kai Vehmanen * @author Martti Mela * @author Remeres Jacobs * @author Tat Chan * * @date Created: Wed Feb 14 18:32:58 2001 ppessi */ #include "config.h" #include #include #include #include #include #include #define SU_ROOT_MAGIC_T struct nua_s #define SU_MSG_ARG_T struct nua_ee_data #define NUA_SAVED_EVENT_T su_msg_t * #define NUA_SAVED_SIGNAL_T su_msg_t * #define NTA_AGENT_MAGIC_T struct nua_s #define NTA_LEG_MAGIC_T struct nua_handle_s #define NTA_OUTGOING_MAGIC_T struct nua_client_request #include #include #include #include #include #include #include #include #include #include "sofia-sip/nua.h" #include "sofia-sip/nua_tag.h" #include "nua_stack.h" #include #include #include #include #include #include /* ======================================================================== * * Protocol stack side * * ======================================================================== */ /* ---------------------------------------------------------------------- */ /* Internal types */ /** @internal Linked stack frames from nua event callback */ struct nua_event_frame_s { nua_event_frame_t *nf_next; nua_saved_event_t nf_saved[1]; }; static void nua_event_deinit(nua_ee_data_t *ee); static void nua_application_event(nua_t *, su_msg_r, nua_ee_data_t *ee); static void nua_stack_signal(nua_t *nua, su_msg_r, nua_ee_data_t *ee); nua_handle_t *nh_create(nua_t *nua, tag_type_t t, tag_value_t v, ...); static void nh_append(nua_t *nua, nua_handle_t *nh); static void nh_remove(nua_t *nua, nua_handle_t *nh); static void nua_stack_timer(nua_t *nua, su_timer_t *t, su_timer_arg_t *a); /* ---------------------------------------------------------------------- */ /* Constant data */ /**@internal Default internal error. */ char const nua_internal_error[] = "Internal NUA Error"; char const nua_application_sdp[] = "application/sdp"; #define NUA_STACK_TIMER_INTERVAL (1000) /* ---------------------------------------------------------------------- * Initialization & deinitialization */ int nua_stack_init(su_root_t *root, nua_t *nua) { su_home_t *home; nua_handle_t *dnh; static int initialized_logs = 0; enter; if (!initialized_logs) { extern su_log_t tport_log[]; extern su_log_t nta_log[]; extern su_log_t nea_log[]; extern su_log_t iptsec_log[]; su_log_init(tport_log); su_log_init(nta_log); su_log_init(nea_log); su_log_init(iptsec_log); initialized_logs = 1; } nua->nua_root = root; nua->nua_timer = su_timer_create(su_root_task(root), NUA_STACK_TIMER_INTERVAL); if (!nua->nua_timer) return -1; home = nua->nua_home; nua->nua_handles_tail = &nua->nua_handles; sip_from_init(nua->nua_from); dnh = su_home_clone(nua->nua_home, sizeof (*dnh) + sizeof(*dnh->nh_prefs)); if (!dnh) return -1; dnh->nh_prefs = (void *)(dnh + 1); dnh->nh_valid = nua_valid_handle_cookie; dnh->nh_nua = nua; nua_handle_ref(dnh); dnh->nh_ref_by_stack = 1; nua_handle_ref(dnh); dnh->nh_ref_by_user = 1; nh_append(nua, dnh); dnh->nh_identity = dnh; dnh->nh_ds->ds_local = nua->nua_from; dnh->nh_ds->ds_remote = nua->nua_from; if (nua_stack_set_defaults(dnh, dnh->nh_prefs) < 0) return -1; if (nua_stack_set_params(nua, dnh, nua_i_none, nua->nua_args) < 0) return -1; /* XXX - soa should know what it supports */ nua->nua_invite_accept = sip_accept_make(home, SDP_MIME_TYPE); nua->nua_accept_multipart = sip_accept_format(home, "%s, %s", SDP_MIME_TYPE, "multipart/*"); nua->nua_nta = nta_agent_create(root, NONE, NULL, NULL, NTATAG_MERGE_482(1), NTATAG_CLIENT_RPORT(1), NTATAG_UA(1), #if HAVE_SOFIA_SMIME NTATAG_SMIME(nua->sm), #endif TPTAG_STUN_SERVER(1), TAG_NEXT(nua->nua_args)); dnh->nh_ds->ds_leg = nta_leg_tcreate(nua->nua_nta, nua_stack_process_request, dnh, NTATAG_NO_DIALOG(1), TAG_END()); if (nua->nua_nta == NULL || dnh->nh_ds->ds_leg == NULL || nta_agent_set_params(nua->nua_nta, NTATAG_UA(1), TAG_END()) < 0 || nua_stack_init_transport(nua, nua->nua_args) < 0) { SU_DEBUG_1(("nua: initializing SIP stack failed\n")); return -1; } if (nua_stack_set_from(nua, 1, nua->nua_args) < 0) return -1; if (nua->nua_prefs->ngp_detect_network_updates) nua_stack_launch_network_change_detector(nua); su_timer_deferrable(nua->nua_timer, nua->nua_prefs->ngp_deferrable_timers); nua_stack_timer(nua, nua->nua_timer, NULL); return 0; } void nua_stack_deinit(su_root_t *root, nua_t *nua) { enter; su_timer_destroy(nua->nua_timer), nua->nua_timer = NULL; nta_agent_destroy(nua->nua_nta), nua->nua_nta = NULL; } /* ---------------------------------------------------------------------- * Sending events to client application */ static void nua_stack_shutdown(nua_t *); void nua_stack_authenticate(nua_t *, nua_handle_t *, nua_event_t, tagi_t const *), nua_stack_respond(nua_t *, nua_handle_t *, int , char const *, tagi_t const *), nua_stack_destroy_handle(nua_t *, nua_handle_t *, tagi_t const *); /* Notifier */ void nua_stack_authorize(nua_t *, nua_handle_t *, nua_event_t, tagi_t const *), nua_stack_notifier(nua_t *, nua_handle_t *, nua_event_t, tagi_t const *), nua_stack_terminate(nua_t *, nua_handle_t *, nua_event_t, tagi_t const *); int nh_notifier_shutdown(nua_handle_t *nh, nea_event_t *ev, tag_type_t t, tag_value_t v, ...); int nua_stack_tevent(nua_t *nua, nua_handle_t *nh, msg_t *msg, nua_event_t event, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...) { ta_list ta; int retval; ta_start(ta, tag, value); retval = nua_stack_event(nua, nh, msg, event, status, phrase, ta_args(ta)); ta_end(ta); return retval; } /** @internal Send an event to the application. */ int nua_stack_event(nua_t *nua, nua_handle_t *nh, msg_t *msg, nua_event_t event, int status, char const *phrase, tagi_t const *tags) { su_msg_r sumsg = SU_MSG_R_INIT; size_t e_len, len, xtra, p_len; if (event == nua_r_ack || event == nua_i_none) return event; if (nh == nua->nua_dhandle) nh = NULL; if (nua_log->log_level >= 5) { char const *name = nua_event_name(event) + 4; char const *p = phrase ? phrase : ""; if (status == 0) SU_DEBUG_5(("nua(%p): event %s %s\n", (void *)nh, name, p)); else SU_DEBUG_5(("nua(%p): event %s %u %s\n", (void *)nh, name, status, p)); } if (event == nua_r_destroy) { if (msg) msg_destroy(msg); if (status >= 200) { nh_destroy(nua, nh); } return event; } if ((event > nua_r_authenticate && event <= nua_r_ack) || event < nua_i_error || (nh && !nh->nh_valid) || (nua->nua_shutdown && event != nua_r_shutdown && !nua->nua_prefs->ngp_shutdown_events)) { if (msg) msg_destroy(msg); return event; } if (tags) { e_len = offsetof(nua_ee_data_t, ee_data[0].e_tags); len = tl_len(tags); xtra = tl_xtra(tags, len); } else { e_len = sizeof(nua_ee_data_t), len = 0, xtra = 0; } p_len = phrase ? strlen(phrase) + 1 : 1; if (su_msg_new(sumsg, e_len + len + xtra + p_len) == 0) { nua_ee_data_t *ee = su_msg_data(sumsg); nua_event_data_t *e = ee->ee_data; void *p; if (tags) { tagi_t *t = e->e_tags, *t_end = (tagi_t *)((char *)t + len); void *b = t_end, *end = (char *)b + xtra; t = tl_dup(t, tags, &b); p = b; assert(t == t_end); assert(b == end); (void)end; } else p = e + 1; ee->ee_nua = nua_stack_ref(nua); e->e_event = event; e->e_nh = nh ? nua_handle_ref(nh) : NULL; e->e_status = status; e->e_phrase = strcpy(p, phrase ? phrase : ""); if (msg) e->e_msg = msg, su_home_threadsafe(msg_home(msg)); su_msg_deinitializer(sumsg, nua_event_deinit); su_msg_send_to(sumsg, nua->nua_client, nua_application_event); } return event; } static void nua_event_deinit(nua_ee_data_t *ee) { nua_t *nua = ee->ee_nua; nua_event_data_t *e = ee->ee_data; nua_handle_t *nh = e->e_nh; if (e->e_msg) msg_destroy(e->e_msg), e->e_msg = NULL; if (nh) nua_handle_unref(nh), e->e_nh = NULL; if (nua) nua_stack_unref(nua), ee->ee_nua = NULL; } /*# Receive event from protocol machine and hand it over to application */ static void nua_application_event(nua_t *dummy, su_msg_r sumsg, nua_ee_data_t *ee) { nua_t *nua = ee->ee_nua; nua_event_data_t *e = ee->ee_data; nua_handle_t *nh = e->e_nh; enter; ee->ee_nua = NULL; e->e_nh = NULL; if (nh == NULL) { /* Xyzzy */ } else if (nh->nh_valid) { if (!nh->nh_ref_by_user) { /* Application must now call nua_handle_destroy() */ nh->nh_ref_by_user = 1; nua_handle_ref(nh); } } else if (!nh->nh_valid) { /* Handle has been destroyed */ if (nua_log->log_level >= 7) { char const *name = nua_event_name((enum nua_event_e)e->e_event) + 4; SU_DEBUG_7(("nua(%p): event %s dropped\n", (void *)nh, name)); } nua_handle_unref(nh); nua_stack_unref(nua); return; } if (e->e_event == nua_r_shutdown && e->e_status >= 200) nua->nua_shutdown_final = 1; if (nua->nua_callback) { nua_event_frame_t frame[1]; su_msg_save(frame->nf_saved, sumsg); frame->nf_next = nua->nua_current, nua->nua_current = frame; nua->nua_callback((enum nua_event_e)e->e_event, e->e_status, e->e_phrase, nua, nua->nua_magic, nh, nh ? nh->nh_magic : NULL, e->e_msg ? sip_object(e->e_msg) : NULL, e->e_tags); su_msg_destroy(frame->nf_saved); nua->nua_current = frame->nf_next; } nua_handle_unref(nh); nua_stack_unref(nua); } /** Get current request message. @NEW_1_12_4. * * @note A response message is returned when processing response message. * * @sa #nua_event_e, nua_respond(), NUTAG_WITH_CURRENT() */ msg_t *nua_current_request(nua_t const *nua) { if (nua && nua->nua_current && su_msg_is_non_null(nua->nua_current->nf_saved)) return su_msg_data(nua->nua_current->nf_saved)->ee_data->e_msg; return NULL; } /** Get request message from saved nua event. @NEW_1_12_4. * * @sa nua_save_event(), nua_respond(), NUTAG_WITH_SAVED(), */ msg_t *nua_saved_event_request(nua_saved_event_t const *saved) { return saved && saved[0] ? su_msg_data(saved)->ee_data->e_msg : NULL; } /** Save nua event and its arguments. * * @sa #nua_event_e, nua_event_data() nua_saved_event_request(), nua_destroy_event() */ int nua_save_event(nua_t *nua, nua_saved_event_t return_saved[1]) { if (return_saved) { if (nua && nua->nua_current) { su_msg_save(return_saved, nua->nua_current->nf_saved); return su_msg_is_non_null(return_saved); } else *return_saved = NULL; } return 0; } /* ---------------------------------------------------------------------- */ /** @internal * Post signal to stack itself */ void nua_stack_post_signal(nua_handle_t *nh, nua_event_t event, tag_type_t tag, tag_value_t value, ...) { ta_list ta; ta_start(ta, tag, value); nua_signal((nh)->nh_nua, nh, NULL, event, 0, NULL, ta_tags(ta)); ta_end(ta); } /*# Send a request to the protocol thread */ int nua_signal(nua_t *nua, nua_handle_t *nh, msg_t *msg, nua_event_t event, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...) { su_msg_r sumsg = SU_MSG_R_INIT; size_t len, xtra, ee_len, l_len = 0, l_xtra = 0; ta_list ta; int retval = -1; if (nua == NULL) return -1; if (nua->nua_shutdown_started && event != nua_r_shutdown) return -1; ta_start(ta, tag, value); ee_len = offsetof(nua_ee_data_t, ee_data[0].e_tags); len = tl_len(ta_args(ta)); xtra = tl_xtra(ta_args(ta), len); if (su_msg_new(sumsg, ee_len + len + l_len + xtra + l_xtra) == 0) { nua_ee_data_t *ee = su_msg_data(sumsg); nua_event_data_t *e = ee->ee_data; tagi_t *t = e->e_tags; void *b = (char *)t + len + l_len; tagi_t *tend = (tagi_t *)b; char *bend = (char *)b + xtra + l_xtra; t = tl_dup(t, ta_args(ta), &b); assert(tend == t); (void)tend; assert(b == bend); (void)bend; e->e_always = event == nua_r_destroy || event == nua_r_shutdown; e->e_event = event; e->e_nh = nh ? nua_handle_ref(nh) : NULL; e->e_status = status; e->e_phrase = phrase; su_msg_deinitializer(sumsg, nua_event_deinit); retval = su_msg_send_to(sumsg, nua->nua_server, nua_stack_signal); if (retval == 0){ SU_DEBUG_7(("nua(%p): %s signal %s\n", (void *)nh, "sent", nua_event_name(event) + 4)); } else { SU_DEBUG_0(("nua(%p): %s signal %s\n", (void *)nh, "FAILED TO SEND", nua_event_name(event) + 4)); } } ta_end(ta); return retval; } /* ---------------------------------------------------------------------- * Receiving events from client */ static void nua_stack_signal(nua_t *nua, su_msg_r msg, nua_ee_data_t *ee) { nua_event_data_t *e = ee->ee_data; nua_handle_t *nh = e->e_nh; tagi_t *tags = e->e_tags; nua_event_t event; int error = 0; if (nh) { if (!nh->nh_prev) nh_append(nua, nh); if (!nh->nh_ref_by_stack) { /* Mark handle as used by stack */ nh->nh_ref_by_stack = 1; nua_handle_ref(nh); } } if (nua_log->log_level >= 5) { char const *name = nua_event_name((enum nua_event_e)e->e_event); if (e->e_status == 0) SU_DEBUG_5(("nua(%p): %s signal %s\n", (void *)nh, "recv", name + 4)); else SU_DEBUG_5(("nua(%p): recv signal %s %u %s\n", (void *)nh, name + 4, e->e_status, e->e_phrase ? e->e_phrase : "")); } su_msg_save(nua->nua_signal, msg); event = (enum nua_event_e)e->e_event; if (nua->nua_shutdown && !e->e_always) { /* Shutting down */ nua_stack_event(nua, nh, NULL, event, 901, "Stack is going down", NULL); } else switch (event) { case nua_r_get_params: nua_stack_get_params(nua, nh ? nh : nua->nua_dhandle, event, tags); break; case nua_r_set_params: nua_stack_set_params(nua, nh ? nh : nua->nua_dhandle, event, tags); break; case nua_r_shutdown: nua_stack_shutdown(nua); break; case nua_r_register: case nua_r_unregister: nua_stack_register(nua, nh, event, tags); break; case nua_r_invite: error = nua_stack_invite(nua, nh, event, tags); break; case nua_r_cancel: error = nua_stack_cancel(nua, nh, event, tags); break; case nua_r_bye: error = nua_stack_bye(nua, nh, event, tags); break; case nua_r_options: error = nua_stack_options(nua, nh, event, tags); break; case nua_r_refer: error = nua_stack_refer(nua, nh, event, tags); break; case nua_r_publish: case nua_r_unpublish: error = nua_stack_publish(nua, nh, event, tags); break; case nua_r_info: error = nua_stack_info(nua, nh, event, tags); break; case nua_r_prack: error = nua_stack_prack(nua, nh, event, tags); break; case nua_r_update: error = nua_stack_update(nua, nh, event, tags); break; case nua_r_message: error = nua_stack_message(nua, nh, event, tags); break; case nua_r_subscribe: case nua_r_unsubscribe: error = nua_stack_subscribe(nua, nh, event, tags); break; case nua_r_notify: error = nua_stack_notify(nua, nh, event, tags); break; case nua_r_notifier: nua_stack_notifier(nua, nh, event, tags); break; case nua_r_terminate: nua_stack_terminate(nua, nh, event, tags); break; case nua_r_method: error = nua_stack_method(nua, nh, event, tags); break; case nua_r_authenticate: nua_stack_authenticate(nua, nh, event, tags); break; case nua_r_authorize: nua_stack_authorize(nua, nh, event, tags); break; case nua_r_ack: error = nua_stack_ack(nua, nh, event, tags); break; case nua_r_respond: nua_stack_respond(nua, nh, e->e_status, e->e_phrase, tags); break; case nua_r_destroy: nua_stack_destroy_handle(nua, nh, tags); su_msg_destroy(nua->nua_signal); return; default: break; } if (error < 0) { nua_stack_event(nh->nh_nua, nh, NULL, event, NUA_ERROR_AT(__FILE__, __LINE__), NULL); } su_msg_destroy(nua->nua_signal); } /* ====================================================================== */ /* Signal and event handling */ /** Get event data. * * @sa #nua_event_e, nua_event_save(), nua_saved_event_request(), nua_destroy_event(). */ nua_event_data_t const *nua_event_data(nua_saved_event_t const saved[1]) { return saved && saved[0] ? su_msg_data(saved)->ee_data : NULL; } /** Destroy saved event. * * @sa #nua_event_e, nua_event_save(), nua_event_data(), nua_saved_event_request(). */ void nua_destroy_event(nua_saved_event_t saved[1]) { if (saved && saved[0]) su_msg_destroy(saved); } /** @internal Move signal. */ void nua_move_signal(nua_saved_signal_t a[1], nua_saved_signal_t b[1]) { su_msg_save(a, b); } void nua_destroy_signal(nua_saved_signal_t saved[1]) { if (saved) su_msg_destroy(saved); } nua_signal_data_t const *nua_signal_data(nua_saved_signal_t const saved[1]) { return nua_event_data(saved); } /* ====================================================================== */ static int nh_call_pending(nua_handle_t *nh, sip_time_t time); /**@internal * Timer routine. * * Go through all active handles and execute pending tasks */ void nua_stack_timer(nua_t *nua, su_timer_t *t, su_timer_arg_t *a) { nua_handle_t *nh, *nh_next; sip_time_t now = sip_now(); su_root_t *root = su_timer_root(t); su_timer_set(t, nua_stack_timer, a); if (nua->nua_shutdown) { nua_stack_shutdown(nua); return; } for (nh = nua->nua_handles; nh; nh = nh_next) { nh_next = nh->nh_next; nh_call_pending(nh, now); su_root_yield(root); /* Handle received packets */ } } static int nh_call_pending(nua_handle_t *nh, sip_time_t now) { nua_dialog_state_t *ds = nh->nh_ds; nua_dialog_usage_t *du; sip_time_t next = now + NUA_STACK_TIMER_INTERVAL / 1000; for (du = ds->ds_usage; du; du = du->du_next) { if (now == 0) break; if (du->du_refresh && du->du_refresh < next) break; } if (du == NULL) return 0; nua_handle_ref(nh); while (du) { nua_dialog_usage_t *du_next = du->du_next; nua_dialog_usage_refresh(nh, ds, du, now); if (du_next == NULL) break; for (du = nh->nh_ds->ds_usage; du; du = du->du_next) if (du == du_next) break; for (; du; du = du->du_next) { if (now == 0) break; if (du->du_refresh && du->du_refresh < next) break; } } nua_handle_unref(nh); return 1; } /* ====================================================================== */ /**Shutdown a @nua stack. * * When the @nua stack is shutdown, ongoing calls are released, * registrations unregistered, publications un-PUBLISHed and subscriptions * terminated. If the stack cannot terminate everything within 30 seconds, * it sends the #nua_r_shutdown event with status 500. * * @param nua Pointer to @nua stack object * * @return * nothing * * @par Related tags: * none * * @par Events: * #nua_r_shutdown * * @sa #nua_r_shutdown, nua_destroy(), nua_create(), nua_bye(), * nua_unregister(), nua_unpublish(), nua_unsubscribe(), nua_notify(), * nua_handle_destroy(), nua_handle_unref() */ /** @NUA_EVENT nua_r_shutdown * * Answer to nua_shutdown(). * * Status codes * - 100 shutdown started * - 101 shutdown in progress (sent when shutdown has been progressed) * - 200 shutdown was successful * - 500 shutdown timeout after 30 sec * * @param status shutdown status code * @param nh NULL * @param hmagic NULL * @param sip NULL * @param tags empty * * @sa nua_shutdown(), nua_destroy() * * @END_NUA_EVENT */ /** @internal Shut down stack. */ void nua_stack_shutdown(nua_t *nua) { nua_handle_t *nh, *nh_next; int busy = 0; sip_time_t now = sip_now(); int status; char const *phrase; enter; if (!nua->nua_shutdown) nua->nua_shutdown = now; for (nh = nua->nua_handles; nh; nh = nh_next) { nua_dialog_state_t *ds = nh->nh_ds; nh_next = nh->nh_next; busy += nua_dialog_repeat_shutdown(nh, ds); if (nh->nh_soa) { soa_destroy(nh->nh_soa), nh->nh_soa = NULL; } if (nua_client_request_pending(ds->ds_cr)) busy++; if (nh_notifier_shutdown(nh, NULL, NEATAG_REASON("noresource"), TAG_END())) busy++; } if (!busy) SET_STATUS(200, "Shutdown successful"); else if (now == nua->nua_shutdown) SET_STATUS(100, "Shutdown started"); else if (now - nua->nua_shutdown < 30) SET_STATUS(101, "Shutdown in progress"); else SET_STATUS(500, "Shutdown timeout"); if (status >= 200) { for (nh = nua->nua_handles; nh; nh = nh_next) { nh_next = nh->nh_next; while (nh->nh_ds && nh->nh_ds->ds_usage) { nua_dialog_usage_remove(nh, nh->nh_ds, nh->nh_ds->ds_usage, NULL, NULL); } } su_timer_destroy(nua->nua_timer), nua->nua_timer = NULL; nta_agent_destroy(nua->nua_nta), nua->nua_nta = NULL; } nua_stack_event(nua, NULL, NULL, nua_r_shutdown, status, phrase, NULL); } /* ---------------------------------------------------------------------- */ /** @internal Create a handle */ nua_handle_t *nh_create(nua_t *nua, tag_type_t tag, tag_value_t value, ...) { ta_list ta; nua_handle_t *nh; enter; ta_start(ta, tag, value); nh = nh_create_handle(nua, NULL, ta_args(ta)); ta_end(ta); if (nh) { nh->nh_ref_by_stack = 1; nh_append(nua, nh); } return nh; } /** @internal Append a handle to the list of handles */ void nh_append(nua_t *nua, nua_handle_t *nh) { nh->nh_next = NULL; nh->nh_prev = nua->nua_handles_tail; *nua->nua_handles_tail = nh; nua->nua_handles_tail = &nh->nh_next; } nua_handle_t *nh_validate(nua_t *nua, nua_handle_t *maybe) { nua_handle_t *nh; if (maybe) for (nh = nua->nua_handles; nh; nh = nh->nh_next) if (nh == maybe) return nh; return NULL; } void nua_stack_destroy_handle(nua_t *nua, nua_handle_t *nh, tagi_t const *tags) { if (nh->nh_notifier) nua_stack_terminate(nua, nh, (enum nua_event_e)0, NULL); nua_dialog_shutdown(nh, nh->nh_ds); if (nh->nh_ref_by_user) { nh->nh_ref_by_user = 0; nua_handle_unref(nh); } nh_destroy(nua, nh); } #define nh_is_inserted(nh) ((nh)->nh_prev != NULL) /** @internal Remove a handle from list of handles */ static void nh_remove(nua_t *nua, nua_handle_t *nh) { assert(nh_is_inserted(nh)); assert(*nh->nh_prev == nh); if (nh->nh_next) nh->nh_next->nh_prev = nh->nh_prev; else nua->nua_handles_tail = nh->nh_prev; *nh->nh_prev = nh->nh_next; nh->nh_prev = NULL; nh->nh_next = NULL; } void nh_destroy(nua_t *nua, nua_handle_t *nh) { assert(nh); assert(nh != nua->nua_dhandle); if (nh->nh_notifier) nea_server_destroy(nh->nh_notifier), nh->nh_notifier = NULL; while (nh->nh_ds->ds_cr) nua_client_request_complete(nh->nh_ds->ds_cr); while (nh->nh_ds->ds_sr) nua_server_request_destroy(nh->nh_ds->ds_sr); nua_dialog_deinit(nh, nh->nh_ds); if (nh->nh_soa) soa_destroy(nh->nh_soa), nh->nh_soa = NULL; if (nh_is_inserted(nh)) nh_remove(nua, nh); nua_handle_unref(nh); /* Remove stack reference */ } /* ======================================================================== */ /** @internal Create a handle for processing incoming request */ nua_handle_t *nua_stack_incoming_handle(nua_t *nua, nta_incoming_t *irq, sip_t const *sip, int create_dialog) { nua_handle_t *nh; url_t const *url; sip_to_t to[1]; sip_from_t from[1]; assert(sip && sip->sip_from && sip->sip_to); if (sip->sip_contact) url = sip->sip_contact->m_url; else url = sip->sip_from->a_url; /* Strip away parameters */ sip_from_init(from)->a_display = sip->sip_to->a_display; *from->a_url = *sip->sip_to->a_url; sip_to_init(to)->a_display = sip->sip_from->a_display; *to->a_url = *sip->sip_from->a_url; nh = nh_create(nua, NUTAG_URL((url_string_t *)url), /* Remote target */ SIPTAG_TO(to), /* Local AoR */ SIPTAG_FROM(from), /* Remote AoR */ TAG_END()); if (nh && nua_stack_init_handle(nua, nh, NULL) < 0) nh_destroy(nua, nh), nh = NULL; if (nh && create_dialog) { struct nua_dialog_state *ds = nh->nh_ds; nua_dialog_store_peer_info(nh, ds, sip); ds->ds_leg = nta_leg_tcreate(nua->nua_nta, nua_stack_process_request, nh, SIPTAG_CALL_ID(sip->sip_call_id), SIPTAG_FROM(sip->sip_to), SIPTAG_TO(sip->sip_from), NTATAG_REMOTE_CSEQ(sip->sip_cseq->cs_seq), TAG_END()); if (!ds->ds_leg || !nta_leg_tag(ds->ds_leg, nta_incoming_tag(irq, NULL))) nh_destroy(nua, nh), nh = NULL; } if (nh) nua_dialog_uas_route(nh, nh->nh_ds, sip, 1); return nh; } /** Set flags and special event on handle. * * @retval 0 when successful * @retval -1 upon an error */ int nua_stack_set_handle_special(nua_handle_t *nh, enum nh_kind kind, nua_event_t special) { if (nh == NULL) return -1; if (special && nh->nh_special && nh->nh_special != special) return -1; if (!nh_is_special(nh) && !nh->nh_has_invite) { switch (kind) { case nh_has_invite: nh->nh_has_invite = 1; break; case nh_has_subscribe: nh->nh_has_subscribe = 1; break; case nh_has_notify: nh->nh_has_notify = 1; break; case nh_has_register: nh->nh_has_register = 1; break; case nh_has_nothing: default: break; } if (special) nh->nh_special = special; } return 0; } sip_replaces_t *nua_stack_handle_make_replaces(nua_handle_t *nh, su_home_t *home, int early_only) { if (nh && nh->nh_ds && nh->nh_ds->ds_leg) return nta_leg_make_replaces(nh->nh_ds->ds_leg, home, early_only); else return NULL; } nua_handle_t *nua_stack_handle_by_replaces(nua_t *nua, sip_replaces_t const *r) { if (nua) { nta_leg_t *leg = nta_leg_by_replaces(nua->nua_nta, r); if (leg) return nta_leg_magic(leg, nua_stack_process_request); } return NULL; } nua_handle_t *nua_stack_handle_by_call_id(nua_t *nua, const char *call_id) { if (nua) { nta_leg_t *leg = nta_leg_by_call_id(nua->nua_nta, call_id); if (leg) return nta_leg_magic(leg, nua_stack_process_request); } return NULL; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/nua_stack.h000066400000000000000000000321261223300710500224620ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef NUA_STACK_H /** Defined when has been included. */ #define NUA_STACK_H /**@IFILE nua_stack.h * @brief Sofia-SIP User Agent Engine - internal stack interface * * @author Pekka Pessi * @author Kai Vehmanen * * @date Created: Wed Feb 14 17:09:44 2001 ppessi */ #ifndef SU_CONFIG_H #include #endif #ifndef SU_OS_NW_H #include #endif #ifndef SOA_H #include "sofia-sip/soa.h" #endif #ifndef NTA_H #include #endif #ifndef AUTH_CLIENT_H #include #endif #ifndef NEA_H #include #endif #ifndef NUA_H #include #endif #define SU_LOG (nua_log) #include #ifndef NUA_DIALOG_H #define NUA_OWNER_T struct nua_handle_s #include "nua_dialog.h" #endif SOFIA_BEGIN_DECLS #if HAVE_SIGCOMP #include #endif #ifndef NUA_PARAMS_H #include "nua_params.h" #endif typedef struct event_s event_t, nua_signal_data_t; /** @internal Extended event data. */ typedef struct nua_ee_data { nua_t *ee_nua; nua_event_data_t ee_data[1]; } nua_ee_data_t; #define NONE ((void *)(intptr_t)-1) typedef struct register_usage nua_registration_t; #define \ NH_ACTIVE_MEDIA_TAGS(include, soa) \ TAG_IF((include) && (soa) && soa_is_audio_active(soa) >= 0, \ SOATAG_ACTIVE_AUDIO(soa_is_audio_active(soa))), \ TAG_IF((include) && (soa) && soa_is_video_active(soa) >= 0, \ SOATAG_ACTIVE_VIDEO(soa_is_video_active(soa))), \ TAG_IF((include) && (soa) && soa_is_image_active(soa) >= 0, \ SOATAG_ACTIVE_IMAGE(soa_is_image_active(soa))), \ TAG_IF((include) && (soa) && soa_is_chat_active(soa) >= 0, \ SOATAG_ACTIVE_CHAT(soa_is_chat_active(soa))) #define \ NH_REMOTE_MEDIA_TAGS(include, soa) \ TAG_IF((include) && (soa) && soa_is_remote_audio_active(soa) >= 0, \ SOATAG_ACTIVE_AUDIO(soa_is_remote_audio_active(soa))), \ TAG_IF((include) && (soa) && soa_is_remote_video_active(soa) >= 0, \ SOATAG_ACTIVE_VIDEO(soa_is_remote_video_active(soa))), \ TAG_IF((include) && (soa) && soa_is_remote_image_active(soa) >= 0, \ SOATAG_ACTIVE_IMAGE(soa_is_remote_image_active(soa))), \ TAG_IF((include) && (soa) && soa_is_remote_chat_active(soa) >= 0, \ SOATAG_ACTIVE_CHAT(soa_is_remote_chat_active(soa))) /** @internal @brief NUA handle. * */ struct nua_handle_s { su_home_t nh_home[1]; /**< Memory home */ nua_handle_t *nh_next; nua_handle_t **nh_prev; nua_t *nh_nua; /**< Pointer to NUA object */ void *nh_valid; /**< Cookie */ #define nua_valid_handle_cookie ((void *)(intptr_t)nua_handle) nua_hmagic_t *nh_magic; /**< Application context */ tagi_t *nh_tags; /**< Initial tags */ tagi_t *nh_ptags; /**< Initial parameters */ nua_handle_t *nh_identity; /**< Identity */ nua_handle_preferences_t *nh_prefs; /**< Preferences */ #define nh_dprefs nh_nua->nua_dhandle->nh_prefs /* Handle type is determined by special event and flags. */ nua_event_t nh_special; /**< Special event */ unsigned nh_has_invite:1; /**< Has call */ unsigned nh_has_subscribe:1; /**< Has watcher */ unsigned nh_has_notify:1; /**< Has notifier */ unsigned nh_has_register:1; /**< Has registration */ /* Call status */ unsigned nh_active_call:1; unsigned nh_hold_remote:1; unsigned nh_ref_by_stack:1; /**< Has stack used the handle? */ unsigned nh_ref_by_user:1; /**< Has user used the handle? */ unsigned nh_init:1; /**< Handle has been initialized */ unsigned nh_used_ptags:1; /**< Ptags has been used */ unsigned :0; nua_dialog_state_t nh_ds[1]; auth_client_t *nh_auth; /**< Authorization objects */ soa_session_t *nh_soa; /**< Media session */ struct nua_referral { nua_handle_t *ref_handle; /**< Referring handle */ sip_event_t *ref_event; /**< Event used with NOTIFY */ } nh_referral[1]; nea_server_t *nh_notifier; /**< SIP notifier */ }; #define NH_IS_VALID(nh) \ ((nh) && (nh)->nh_valid == nua_valid_handle_cookie) #define NH_STATUS(nh) \ (nh)->nh_status, \ (nh)->nh_phrase, \ SIPTAG_WARNING_STR(nh->nh_warning) #define NH_IS_DEFAULT(nh) ((nh) == (nh)->nh_nua->nua_handles) su_inline int nh_is_special(nua_handle_t *nh) { return nh == NULL || nh->nh_special; } typedef struct nua_event_frame_s nua_event_frame_t; extern char const nua_internal_error[]; #define NUA_INTERNAL_ERROR 900, nua_internal_error #define _NUA_INTERNAL_ERROR_AT(file, line) "Internal error at " file ":" #line #define NUA_ERROR_AT(file, line) 900, _NUA_INTERNAL_ERROR_AT(file, line) struct nua_s { su_home_t nua_home[1]; /* API (client) side */ su_root_t *nua_api_root; su_clone_r nua_clone; su_task_r nua_client; nua_callback_f nua_callback; nua_magic_t *nua_magic; nua_event_frame_t *nua_current; nua_saved_event_t nua_signal[1]; /**< Used by stop-and-wait args calls */ tagi_t const *nua_args; /* Engine state flags */ sip_time_t nua_shutdown; unsigned nua_shutdown_started:1; /**< Shutdown initiated */ unsigned nua_shutdown_final:1; /**< Shutdown is complete */ unsigned nua_from_is_set; unsigned :0; /**< Local SIP address. Contents are kept around for ever. */ sip_from_t nua_from[1]; /* ---------------------------------------------------------------------- */ /* Protocol (server) side */ su_network_changed_t *nua_nw_changed; nua_registration_t *nua_registrations; /**< Active registrations */ /* Constants */ sip_accept_t *nua_accept_multipart; sip_accept_t *nua_invite_accept; /* What we accept for invite */ su_root_t *nua_root; su_task_r nua_server; nta_agent_t *nua_nta; su_timer_t *nua_timer; /* User-agent parameters */ nua_global_preferences_t nua_prefs[1]; nua_handle_t *nua_handles; nua_handle_t **nua_handles_tail; }; #define nua_dhandle nua_handles #if HAVE_FUNC #define enter (void)SU_DEBUG_9(("nua: %s: entering\n", __func__)) #define nh_enter (void)SU_DEBUG_9(("nua %s(%p): entering\n", __func__, nh)) #elif HAVE_FUNCTION #define enter (void)SU_DEBUG_9(("nua: %s: entering\n", __FUNCTION__)) #define nh_enter (void)SU_DEBUG_9(("nua %s(%p): entering\n", __FUNCTION__, nh)) #define __func__ __FUNCTION__ #else #define enter ((void)0) #define nh_enter ((void)0) #define __func__ "nua" #endif #if HAVE_MEMLEAK_LOG #define nua_handle_ref(nh) \ _nua_handle_ref_by((nh), __FILE__, __LINE__, __func__) #define nua_handle_unref(nh) \ _nua_handle_unref_by((nh), __FILE__, __LINE__, __func__) nua_handle_t *_nua_handle_ref_by( nua_handle_t *nh, char const *file, unsigned line, char const *by); int _nua_handle_unref_by( nua_handle_t *nh, char const *file, unsigned line, char const *by); #endif su_inline nua_t *nua_stack_ref(nua_t *nua) { return (nua_t *)su_home_ref(nua->nua_home); } su_inline void nua_stack_unref(nua_t *nua) { su_home_unref(nua->nua_home); } /* Internal prototypes */ int nua_stack_init(su_root_t *root, nua_t *nua); void nua_stack_deinit(su_root_t *root, nua_t *nua); int nua_stack_init_transport(nua_t *nua, tagi_t const *tags); int nua_stack_init_registrations(nua_t *nua); nua_registration_t *nua_registration_by_aor(nua_registration_t const *list, sip_from_t const *aor, url_t const *remote_uri, int only_default); sip_contact_t const *nua_registration_contact(nua_registration_t const *nr); int nua_registration_process_request(nua_registration_t *nr, nta_incoming_t *irq, sip_t const *sip); void nua_stack_post_signal(nua_handle_t *nh, nua_event_t event, tag_type_t tag, tag_value_t value, ...); typedef int nua_stack_signal_handler(nua_t *, nua_handle_t *, nua_event_t, tagi_t const *); void nua_move_signal(nua_saved_signal_t a[1], nua_saved_signal_t b[1]); nua_signal_data_t const *nua_signal_data(nua_saved_signal_t const saved[1]); void nua_destroy_signal(nua_saved_signal_t saved[1]); nua_stack_signal_handler nua_stack_set_params, nua_stack_get_params, nua_stack_register, nua_stack_invite, nua_stack_ack, nua_stack_cancel, nua_stack_bye, nua_stack_info, nua_stack_update, nua_stack_prack, nua_stack_options, nua_stack_publish, nua_stack_message, nua_stack_subscribe, nua_stack_notify, nua_stack_refer, nua_stack_method; #define UA_EVENT1(e, statusphrase) \ nua_stack_event(nua, nh, NULL, e, statusphrase, NULL) #define UA_EVENT2(e, status, phrase) \ nua_stack_event(nua, nh, NULL, e, status, phrase, NULL) #define UA_EVENT3(e, status, phrase, tag) \ nua_stack_event(nua, nh, NULL, e, status, phrase, tag, NULL) int nua_stack_tevent(nua_t *nua, nua_handle_t *nh, msg_t *msg, nua_event_t event, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...); int nua_stack_event(nua_t *nua, nua_handle_t *nh, msg_t *msg, nua_event_t event, int status, char const *phrase, tagi_t const *tags); void nua_move_event(nua_saved_event_t a[1], nua_saved_event_t b[1]); nua_handle_t *nh_create_handle(nua_t *nua, nua_hmagic_t *hmagic, tagi_t *tags); nua_handle_t *nua_stack_incoming_handle(nua_t *nua, nta_incoming_t *irq, sip_t const *sip, int create_dialog); int nua_stack_init_handle(nua_t *nua, nua_handle_t *nh, tagi_t const *tags); enum nh_kind { nh_has_nothing, nh_has_invite, nh_has_subscribe, nh_has_notify, nh_has_register, nh_has_streaming }; int nua_stack_set_handle_special(nua_handle_t *nh, enum nh_kind kind, nua_event_t special); int nua_handle_save_tags(nua_handle_t *h, tagi_t *tags); void nh_destroy(nua_t *nua, nua_handle_t *nh); nua_handle_t *nh_validate(nua_t *nua, nua_handle_t *maybe); sip_replaces_t *nua_stack_handle_make_replaces(nua_handle_t *handle, su_home_t *home, int early_only); nua_handle_t *nua_stack_handle_by_replaces(nua_t *nua, sip_replaces_t const *r); nua_handle_t *nua_stack_handle_by_call_id(nua_t *nua, const char *call_id); /* ---------------------------------------------------------------------- */ int nua_stack_set_defaults(nua_handle_t *nh, nua_handle_preferences_t *nhp); int nua_stack_set_from(nua_t *, int initial, tagi_t const *tags); int nua_stack_init_instance(nua_handle_t *nh, tagi_t const *tags); int nua_stack_process_request(nua_handle_t *nh, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip); int nua_stack_launch_network_change_detector(nua_t *nua); sip_contact_t const *nua_stack_get_contact(nua_registration_t const *nr); int nua_registration_add_contact_to_request(nua_handle_t *nh, msg_t *msg, sip_t *sip, int add_contact, int add_service_route); int nua_registration_add_contact_to_response(nua_handle_t *nh, msg_t *msg, sip_t *sip, sip_record_route_t const *, sip_contact_t const *remote); /* ---------------------------------------------------------------------- */ #ifndef SDP_MIME_TYPE #define SDP_MIME_TYPE nua_application_sdp #endif extern char const nua_application_sdp[]; /* ---------------------------------------------------------------------- */ #define SIP_METHOD_UNKNOWN sip_method_unknown, NULL /* Private tags */ #define NUTAG_ADD_CONTACT(v) _nutag_add_contact, tag_bool_v(v) extern tag_typedef_t _nutag_add_contact; /* ---------------------------------------------------------------------- */ #define SET_STATUS(_status, _phrase) status = _status, phrase = _phrase #define SET_STATUS2(_status, _phrase) status = _status, phrase = _phrase /* This is an "interesting" macro: * x is a define expanding to num, str. * @a num is assigned to variable status, @a str to variable phrase. * Macro SET_STATUS1 expands to two comma-separated expressions that are * also usable as function arguments. */ #define SET_STATUS1(x) ((status = x), status), (phrase = ((void)x)) /* ---------------------------------------------------------------------- */ /* Application side prototypes */ int nua_signal(nua_t *nua, nua_handle_t *nh, msg_t *msg, nua_event_t event, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...); SOFIA_END_DECLS #endif /* NUA_STACK_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/nua_subnotref.c000066400000000000000000000656631223300710500233730ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2006 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE nua_subnotref.c * @brief Subscriber (event watcher) * * This file contains implementation SUBSCRIBE UAC, NOTIFY UAS, REFER UAC. * The implementation of SUBSCRIBE UAS, NOTIFY UAC and REFER UAS is in * nua_notifier.c. * Alternative implementation using nea is in nua_event_server.c. * * @author Pekka Pessi * * @date Created: Wed Mar 8 15:10:08 EET 2006 ppessi */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include "nua_stack.h" /* ---------------------------------------------------------------------- */ /* Subcriber event usage */ struct event_usage { enum nua_substate eu_substate; /**< Subscription state */ unsigned eu_delta; /**< Proposed expiration */ sip_time_t eu_expires; /**< Absolute expiration time */ unsigned eu_notified; /**< Number of NOTIFYs received */ unsigned eu_unsolicited:1; /**< Not SUBSCRIBEd or REFERed */ unsigned eu_refer:1; /**< Implied subscription by refer */ unsigned eu_final_wait:1; /**< Waiting for final NOTIFY */ unsigned eu_no_id:1; /**< Do not use "id" (even if we have one) */ }; static char const *nua_subscribe_usage_name(nua_dialog_usage_t const *du); static int nua_subscribe_usage_add(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du); static void nua_subscribe_usage_remove(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du, nua_client_request_t *cr, nua_server_request_t *sr); static void nua_subscribe_usage_refresh(nua_handle_t *, nua_dialog_state_t *, nua_dialog_usage_t *, sip_time_t); static int nua_subscribe_usage_shutdown(nua_handle_t *, nua_dialog_state_t *, nua_dialog_usage_t *); static nua_usage_class const nua_subscribe_usage[1] = { { sizeof (struct event_usage), (sizeof nua_subscribe_usage), nua_subscribe_usage_add, nua_subscribe_usage_remove, nua_subscribe_usage_name, nua_base_usage_update_params, NULL, nua_subscribe_usage_refresh, nua_subscribe_usage_shutdown }}; static char const *nua_subscribe_usage_name(nua_dialog_usage_t const *du) { return "subscribe"; } static int nua_subscribe_usage_add(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du) { ds->ds_has_events++; ds->ds_has_subscribes++; return 0; } static void nua_subscribe_usage_remove(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du, nua_client_request_t *cr, nua_server_request_t *sr) { ds->ds_has_events--; ds->ds_has_subscribes--; } /* ====================================================================== */ /* SUBSCRIBE */ /**@fn void nua_subscribe(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * * Subscribe to a SIP event. * * Subscribe a SIP event using the SIP SUBSCRIBE request. If the * SUBSCRBE is successful a subscription state is established and * the subscription is refreshed regularly. The refresh requests will * generate #nua_r_subscribe events. * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Related Tags: * NUTAG_URL() * Header tags defined in * * @par Events: * #nua_r_subscribe \n * #nua_i_notify * * @sa NUTAG_SUBSTATE(), @RFC3265 */ /**@fn void nua_unsubscribe(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * * Unsubscribe an event. * * Unsubscribe an active or pending subscription with SUBSCRIBE request * containing Expires: header with value 0. The dialog associated with * subscription will be destroyed if there is no other subscriptions or * call using this dialog. * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Related Tags: * SIPTAG_EVENT() or SIPTAG_EVENT_STR() \n * Header tags defined in except SIPTAG_EXPIRES() or SIPTAG_EXPIRES_STR() * * @par Events: * #nua_r_unsubscribe * * @sa NUTAG_SUBSTATE(), @RFC3265 */ static int nua_subscribe_client_init(nua_client_request_t *cr, msg_t *, sip_t *, tagi_t const *tags); static int nua_subscribe_client_request(nua_client_request_t *cr, msg_t *, sip_t *, tagi_t const *tags); static int nua_subscribe_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip); static nua_client_methods_t const nua_subscribe_client_methods = { SIP_METHOD_SUBSCRIBE, /* crm_method, crm_method_name */ 0, /* crm_extra */ { /* crm_flags */ /* create_dialog */ 1, /* in_dialog */ 1, /* target refresh */ 1 }, NULL, /* crm_template */ nua_subscribe_client_init, /* crm_init */ nua_subscribe_client_request, /* crm_send */ NULL, /* crm_check_restart */ nua_subscribe_client_response, /* crm_recv */ NULL, /* crm_preliminary */ NULL, /* crm_report */ NULL, /* crm_complete */ }; int nua_stack_subscribe(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { return nua_client_create(nh, e, &nua_subscribe_client_methods, tags); } static int nua_subscribe_client_init(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du; sip_event_t *o = sip->sip_event; du = nua_dialog_usage_get(nh->nh_ds, nua_subscribe_usage, o); if (du == NULL && o == NULL) du = nua_dialog_usage_get(nh->nh_ds, nua_subscribe_usage, NONE); if (du) { if (du->du_event && o == NULL) /* Add Event header */ sip_add_dup(msg, sip, (sip_header_t *)du->du_event); } else if (cr->cr_event == nua_r_subscribe) { /* Create dialog usage */ du = nua_dialog_usage_add(nh, nh->nh_ds, nua_subscribe_usage, o); /* Note that we allow SUBSCRIBE without event */ } cr->cr_usage = du; return 0; } static int nua_subscribe_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags) { nua_dialog_usage_t *du = cr->cr_usage; sip_time_t expires = 0; if (cr->cr_event == nua_r_destroy || !du || du->du_shutdown) nua_client_set_terminating(cr, 1); if (du) { struct event_usage *eu = nua_dialog_usage_private(du); sip_event_t *o = sip->sip_event; if (nua_client_bind(cr, du) < 0) return -1; if (eu->eu_no_id && o && o->o_id) { /* Notifier does not handle id properly, remove it */ msg_header_remove_param(o->o_common, "id"); } #if 0 if (cr->cr_terminating) { /* Already terminated subscription? */ if (eu->eu_substate == nua_substate_terminated || eu->eu_substate == nua_substate_embryonic) { return nua_client_return(cr, SIP_200_OK, msg); } } #endif nua_dialog_usage_reset_refresh(du); /* during SUBSCRIBE transaction */ if (cr->cr_terminating || cr->cr_event != nua_r_subscribe) expires = eu->eu_delta = 0; else if (sip->sip_expires) /* Use value specified by application or negotiated with Min-Expires */ expires = eu->eu_delta = sip->sip_expires->ex_delta; else /* We just use common default value, but the default is actually package-specific according to the RFC 3265 section 4.4.4: [Event] packages MUST also define a default "Expires" value to be used if none is specified. */ expires = eu->eu_delta = 3600; eu->eu_final_wait = 0; if (eu->eu_substate == nua_substate_terminated) eu->eu_substate = nua_substate_embryonic; } if (!sip->sip_expires || sip->sip_expires->ex_delta != expires) { sip_expires_t ex[1]; sip_expires_init(ex)->ex_delta = expires; sip_add_dup(msg, sip, (sip_header_t *)ex); } return nua_base_client_request(cr, msg, sip, tags); } /** @NUA_EVENT nua_r_subscribe * * Response to an outgoing SUBSCRIBE request. * * The SUBSCRIBE request may have been sent explicitly by nua_subscribe() or * implicitly by NUA state machine. * * @param status response status code * (if the request is retried, @a status is 100, the @a * sip->sip_status->st_status contain the real status code * from the response message, e.g., 302, 401, or 407) * @param phrase a short textual description of @a status code * @param nh operation handle associated with the subscription * @param hmagic application context associated with the handle * @param sip response to SUBSCRIBE request or NULL upon an error * (status code is in @a status and * descriptive message in @a phrase parameters) * @param tags NUTAG_SUBSTATE() * * @sa nua_subscribe(), @RFC3265 * * @END_NUA_EVENT */ /** @NUA_EVENT nua_r_unsubscribe * * Response to an outgoing un-SUBSCRIBE. * * @param status response status code * (if the request is retried, @a status is 100, the @a * sip->sip_status->st_status contain the real status code * from the response message, e.g., 302, 401, or 407) * @param phrase a short textual description of @a status code * @param nh operation handle associated with the subscription * @param hmagic application context associated with the handle * @param sip response to SUBSCRIBE request or NULL upon an error * (status code is in @a status and * descriptive message in @a phrase parameters) * @param tags NUTAG_SUBSTATE() * * @sa nua_unsubscribe(), @RFC3265 * * @END_NUA_EVENT */ static int nua_subscribe_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = cr->cr_usage; struct event_usage *eu = nua_dialog_usage_private(du); enum nua_substate substate; if (eu == NULL || cr->cr_terminated) substate = nua_substate_terminated; else if (status >= 300) substate = eu->eu_substate; else { int win_messenger_enable = NH_PGET(nh, win_messenger_enable); sip_time_t delta, now = sip_now(); du->du_ready = 1; if (eu->eu_substate != nua_substate_terminated) /* If there is no @Expires header, use default value stored in eu_delta */ delta = sip_contact_expires(NULL, sip->sip_expires, sip->sip_date, eu->eu_delta, now); else delta = 0; if (delta > eu->eu_delta) delta = eu->eu_delta; if (win_messenger_enable && !nua_dialog_is_established(nh->nh_ds)) { /* Notify from messanger does not match with dialog tag */ nh->nh_ds->ds_remote_tag = su_strdup(nh->nh_home, ""); } if (delta > 0) { nua_dialog_usage_set_refresh(du, delta); eu->eu_expires = du->du_refquested + delta; } else { if (eu->eu_substate == nua_substate_terminated) { if (!eu->eu_notified) eu->eu_substate = nua_substate_embryonic; } if (eu->eu_substate != nua_substate_terminated) { /* Wait 32 seconds for NOTIFY. */ delta = 64 * NTA_SIP_T1 / 1000; eu->eu_final_wait = 1; if (!eu->eu_notified && win_messenger_enable) delta = 4 * 60; /* Wait 4 minutes for NOTIFY from Messenger */ nua_dialog_usage_set_refresh_range(du, delta, delta); } else { nua_dialog_usage_reset_refresh(du); } eu->eu_expires = du->du_refquested; } substate = eu->eu_substate; if (substate == nua_substate_terminated) /* let nua_base_client_tresponse to remove usage */ cr->cr_terminated = 1; } return nua_base_client_tresponse(cr, status, phrase, sip, NUTAG_SUBSTATE(substate), SIPTAG_EVENT(du ? du->du_event : NULL), TAG_END()); } /** Refresh subscription */ static void nua_subscribe_usage_refresh(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du, sip_time_t now) { nua_client_request_t *cr = du->du_cr; struct event_usage *eu = nua_dialog_usage_private(du); assert(eu); if (eu->eu_final_wait) { /* Did not receive NOTIFY for fetch */ sip_event_t const *o = du->du_event; char const *id = o ? o->o_id : NULL; SU_DEBUG_3(("nua(%p): event %s%s%s fetch timeouts\n", (void *)nh, o ? o->o_type : "(empty)", id ? "; id=" : "", id ? id : "")); nua_stack_tevent(nh->nh_nua, nh, NULL, nua_i_notify, 408, "Fetch Timeouts without NOTIFY", NUTAG_SUBSTATE(nua_substate_terminated), SIPTAG_EVENT(du->du_event), TAG_END()); nua_dialog_usage_remove(nh, ds, du, NULL, NULL); return; } if (cr) { if (nua_client_resend_request(cr, 0) >= 0) return; } else if (eu->eu_refer) { /* * XXX - If we have received a NOTIFY, we should try to terminate * subscription */ } if (!eu->eu_unsolicited) nua_stack_tevent(nh->nh_nua, nh, NULL, nua_i_notify, NUA_ERROR_AT(__FILE__, __LINE__), NUTAG_SUBSTATE(nua_substate_terminated), SIPTAG_EVENT(du->du_event), TAG_END()); nua_dialog_usage_remove(nh, ds, du, NULL, NULL); } /** Terminate subscription. * * @retval >0 shutdown done * @retval 0 shutdown in progress * @retval <0 try again later */ static int nua_subscribe_usage_shutdown(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du) { struct event_usage *eu = nua_dialog_usage_private(du); nua_client_request_t *cr = du->du_cr; assert(eu); (void)eu; if (cr) { if (nua_client_resend_request(cr, 1) >= 0) return 0; } nua_dialog_usage_remove(nh, ds, du, NULL, NULL); return 200; } /* ======================================================================== */ /* NOTIFY server */ /** @NUA_EVENT nua_i_notify * * Event for incoming NOTIFY request. * * @param status statuscode of response sent automatically by stack * @param phrase a short textual description of @a status code * @param nh operation handle associated with the subscription * @param hmagic application context associated with the handle * @param sip incoming NOTIFY request * @param tags NUTAG_SUBSTATE() indicating the subscription state * * @sa nua_subscribe(), nua_unsubscribe(), @RFC3265, #nua_i_subscribe * * @END_NUA_EVENT */ int nua_notify_server_init(nua_server_request_t *sr); int nua_notify_server_preprocess(nua_server_request_t *sr); int nua_notify_server_report(nua_server_request_t *, tagi_t const *); nua_server_methods_t const nua_notify_server_methods = { SIP_METHOD_NOTIFY, nua_i_notify, /* Event */ { /* create_dialog: */ 1, /* Do create dialog */ /* in_dialog: */ 0, /* Not always in-dialog request */ /* target_refresh: */ 1, /* Target refresh request */ /* add_contact: */ 1, /* Add Contact to response */ }, nua_notify_server_init, nua_notify_server_preprocess, nua_base_server_params, nua_base_server_respond, nua_notify_server_report, }; int nua_notify_server_init(nua_server_request_t *sr) { if (!sr->sr_initial) { nua_dialog_state_t *ds = sr->sr_owner->nh_ds; /* Check for forked subscription. */ if (ds->ds_remote_tag && ds->ds_remote_tag[0] && su_strcasecmp(ds->ds_remote_tag, sr->sr_request.sip->sip_from->a_tag)) { sip_contact_t const *m = NULL; m = nua_stack_get_contact(sr->sr_owner->nh_nua->nua_registrations); if (m) { sip_warning_t w[1]; sip_warning_init(w)->w_code = 399; w->w_host = m->m_url->url_host; w->w_port = m->m_url->url_port; w->w_text = "Forking SUBSCRIBEs are not supported"; sip_add_dup(sr->sr_response.msg, NULL, (sip_header_t*)w); } return SR_STATUS(sr, 481, "Subscription Does Not Exist"); } } return 0; } int nua_notify_server_preprocess(nua_server_request_t *sr) { nua_dialog_state_t *ds = sr->sr_owner->nh_ds; nua_dialog_usage_t *du; struct event_usage *eu; sip_t const *sip = sr->sr_request.sip; sip_event_t *o = sip->sip_event; enum nua_substate substate = nua_substate_terminated; sip_subscription_state_t *subs = sip->sip_subscription_state; char const *what = "", *reason = NULL; int solicited = 1; du = nua_dialog_usage_get(ds, nua_subscribe_usage, o); if (du == NULL) { if (!sip_is_allowed(NH_PGET(sr->sr_owner, appl_method), SIP_METHOD_NOTIFY)) return SR_STATUS(sr, 481, "Subscription Does Not Exist"); solicited = 0; /* Let application to handle unsolicited NOTIFY */ du = nua_dialog_usage_add(sr->sr_owner, ds, nua_subscribe_usage, o); if (!du) return SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); } sr->sr_usage = du; eu = nua_dialog_usage_private(du); assert(eu); eu->eu_notified++; if (!o || !o->o_id) eu->eu_no_id = 1; if (subs == NULL) { /* Compatibility */ unsigned long delta = eu->eu_delta; if (sip->sip_expires) delta = sip->sip_expires->ex_delta; if (delta == 0) substate = nua_substate_terminated, what = "terminated"; else substate = nua_substate_active, what = "active"; } else if (su_casematch(subs->ss_substate, what = "terminated")) { substate = nua_substate_terminated; reason = subs->ss_reason; if (su_casematch(reason, "deactivated") || su_casematch(reason, "probation")) substate = nua_substate_embryonic; } else if (su_casematch(subs->ss_substate, what = "pending")) { substate = nua_substate_pending; } else /* if (su_casematch(subs->ss_substate, what = "active")) */ { /* Any extended state is considered as active */ what = subs->ss_substate; substate = nua_substate_active; } eu->eu_substate = substate; if (!solicited) eu->eu_unsolicited = 1; SU_DEBUG_5(("nua(%p): %s: %s (%s)\n", (void *)sr->sr_owner, "nua_notify_server_preprocess", what, reason ? reason : "")); if (solicited) return SR_STATUS1(sr, SIP_200_OK); return 0; } int nua_notify_server_report(nua_server_request_t *sr, tagi_t const *tags) { nua_handle_t *nh = sr->sr_owner; nua_dialog_usage_t *du = sr->sr_usage; struct event_usage *eu = nua_dialog_usage_private(du); sip_t const *sip = sr->sr_request.sip; enum nua_substate substate = nua_substate_terminated; sip_time_t delta = SIP_TIME_MAX; sip_event_t const *o = sip->sip_event; int retry = -1; int retval; if (eu) { sip_subscription_state_t *subs = sip->sip_subscription_state; substate = eu->eu_substate; if (substate == nua_substate_active || substate == nua_substate_pending) { if (subs && subs->ss_expires) { sip_time_t now = sip_now(); sip_time_t delta0 = strtoul(subs->ss_expires, NULL, 10); if (now + delta0 <= eu->eu_expires) delta = delta0; } } else if (substate == nua_substate_embryonic) { if (subs && subs->ss_reason) { if (su_casematch(subs->ss_reason, "deactivated")) { retry = 0; /* retry immediately */ } else if (su_casematch(subs->ss_reason, "probation")) { retry = 30; if (subs->ss_retry_after) retry = strtoul(subs->ss_retry_after, NULL, 10); if (retry > 3600) retry = 3600; } } } else if (substate == nua_substate_terminated) { sr->sr_terminating = 1; } } retval = nua_base_server_treport(sr, /* can destroy sr */ NUTAG_SUBSTATE(substate), SIPTAG_EVENT(o), TAG_NEXT(tags)); if (retval != 1 || du == NULL) return retval; if (eu->eu_unsolicited) { /* Xyzzy */; } else if (retry >= 0) { /* Try to subscribe again */ /* XXX - this needs through testing */ nua_dialog_remove(nh, nh->nh_ds, du); /* tear down */ nua_dialog_usage_set_refresh_range(du, retry, retry + 5); } else { if (delta < SIP_TIME_MAX) { nua_dialog_usage_set_refresh(du, delta); eu->eu_expires = du->du_refquested + delta; } } return retval; } /* ======================================================================== */ /* REFER */ /**@fn void nua_refer(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * * Transfer a call. * * Send a REFER request asking the recipient to transfer the call. * * The REFER request also establishes an implied subscription to the "refer" * event. The "refer" event can have an "id" parameter, which has the value * of CSeq number in the REFER request. After initiating the REFER request, * the nua engine sends application a #nua_r_refer event with status 100 and * tag NUTAG_REFER_EVENT() containing a matching event header with id * parameter. * * Note that the @Event header in the locally generated #nua_r_refer event * contains the @a id parameter. The @a id parameter contains the @CSeq * number of the REFER request, and it may get incremented if the request is * retried because it got challenged or redirected. In that case, the * application gets a new #nua_r_refer event with status 100 and tag * NUTAG_REFER_EVENT(). Also the recipient of the REFER request may or may * not include the @a id parameter with the @Event header in the NOTIFY * requests messages which it sends to the sender of the REFER request. * * Therefore the application is not able to modify the state of the implied * subscription before receiving the first NOTIFY request. * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Related Tags: * NUTAG_URL() \n * Tags of nua_set_hparams() \n * Header tags defined in * * @par Events: * #nua_r_refer \n * #nua_i_notify * * @sa #nua_r_refer, NUTAG_SUBSTATE(), NUTAG_REFER_EVENT(),#nua_i_refer, * @RFC3515, @ReferTo, SIPTAG_REFER_TO(), SIPTAG_REFER_TO_STR(), * @RFC3892, @ReferredBy, SIPTAG_REFERRED_BY(), SIPTAG_REFERRED_BY_STR(), * @RFC3891, @Replaces, SIPTAG_REPLACES(), SIPTAG_REPLACES_STR(), * @RFC4488, @ReferSub, SIPTAG_REFER_SUB(), SIPTAG_REFER_SUB_STR() */ /**@NUA_EVENT nua_r_refer * * @brief Response to outgoing REFER. * * @param status response status code * (if the request is retried, @a status is 100, the @a * sip->sip_status->st_status contain the real status code * from the response message, e.g., 302, 401, or 407) * @param phrase a short textual description of @a status code * @param nh operation handle associated with the REFER request * @param hmagic application context associated with the handle * @param sip response to REFER request or NULL upon an error * (status code is in @a status and * descriptive message in @a phrase parameters) * @param tags NUTAG_REFER_EVENT() \n * NUTAG_SUBSTATE() * * @sa nua_refer(), NUTAG_SUBSTATE(), #nua_i_refer, * @RFC3515, @RFC4488, @ReferSub * * @END_NUA_EVENT */ static int nua_refer_client_init(nua_client_request_t *cr, msg_t *, sip_t *, tagi_t const *tags); static int nua_refer_client_request(nua_client_request_t *cr, msg_t *, sip_t *, tagi_t const *tags); static int nua_refer_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip); static nua_client_methods_t const nua_refer_client_methods = { SIP_METHOD_REFER, /* crm_method, crm_method_name */ 0, /* crm_extra */ { /* crm_flags */ /* create_dialog */ 1, /* in_dialog */ 1, /* target refresh */ 1 }, NULL, /* crm_template */ nua_refer_client_init, /* crm_init */ nua_refer_client_request, /* crm_send */ NULL, /* crm_check_restart */ nua_refer_client_response, /* crm_recv */ nua_refer_client_response, /* crm_preliminary */ NULL, /* crm_report */ NULL, /* crm_complete */ }; int nua_stack_refer(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { return nua_client_create(nh, e, &nua_refer_client_methods, tags); } static int nua_refer_client_init(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags) { nua_handle_t *nh = cr->cr_owner; if (sip->sip_referred_by == NULL) { sip_from_t *a = sip->sip_from; sip_referred_by_t by[1]; sip_referred_by_init(by); if (a == NULL) a = nh->nh_nua->nua_from; by->b_display = a->a_display; *by->b_url = *a->a_url; sip_add_dup(msg, sip, (sip_header_t *)by); } if (sip->sip_event) sip_header_remove(msg, sip, (sip_header_t *)sip->sip_event); return 0; } static int nua_refer_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du, *du0 = cr->cr_usage; struct event_usage *eu; sip_event_t *event; int error; cr->cr_usage = NULL; event = sip_event_format(nh->nh_home, "refer;id=%u", sip->sip_cseq->cs_seq); if (!event) return -1; if (du0 == NULL || du0->du_event == NULL || du0->du_event->o_id == NULL || strcmp(du0->du_event->o_id, event->o_id)) { du = nua_dialog_usage_add(nh, nh->nh_ds, nua_subscribe_usage, event); if (!du) return -1; } else { du = du0, du0 = NULL; } if (du0) nua_dialog_usage_remove(nh, nh->nh_ds, du0, NULL, NULL); eu = nua_dialog_usage_private(cr->cr_usage = du); eu ->eu_refer = 1; error = nua_base_client_request(cr, msg, sip, tags); if (!error) { /* Give application an Event header for matching NOTIFYs with REFER */ nua_stack_tevent(nh->nh_nua, nh, NULL, (enum nua_event_e)cr->cr_event, SIP_100_TRYING, NUTAG_REFER_EVENT(event), SIPTAG_EVENT(event), TAG_END()); su_free(nh->nh_home, event); } return error; } static int nua_refer_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip) { nua_dialog_usage_t *du = cr->cr_usage; enum nua_substate substate = nua_substate_terminated; if (du) { struct event_usage *eu = nua_dialog_usage_private(du); if (status < 200) { substate = eu->eu_substate; } else if (status < 300) { sip_refer_sub_t const *rs = sip_refer_sub(sip); if (rs && su_casematch("false", rs->rs_value)) cr->cr_terminated = 1; if (!cr->cr_terminated) substate = eu->eu_substate; } } return nua_base_client_tresponse(cr, status, phrase, sip, NUTAG_SUBSTATE(substate), SIPTAG_EVENT(du ? du->du_event : NULL), TAG_END()); } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/nua_tag.c000066400000000000000000002606221223300710500221270ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE nua_tag.c Tags and tag lists for NUA * * @author Pekka Pessi * @author Martti Mela * * @date Created: Wed Feb 21 10:13:29 2001 ppessi */ #include "config.h" #define TAG_NAMESPACE "nua" #include "sofia-sip/nua_tag.h" #include #include #include #include #include /** @page nua_api_overview NUA API Overview * * This page gives a short overview of the NUA API: different functions, * events, tags, and where and how they affect the workings of the NUA * engine. * * The application and the NUA engine can pass various parameters between * them using tagged arguments. Tagged arguments can be used like named * arguments in higher-lever languages. * * @par NUA Agent * * The NUA agent object is created with nua_create(). The nua_create() also * creates the transports and binds the transport sockets used by the SIP * stack. * * The special tags controlling the transports are * - NUTAG_URL(), NUTAG_SIPS_URL(), NUTAG_CERTIFICATE_DIR(), NUTAG_SIP_PARSER() * * See nta_agent_add_tport() for discussion about magic URIs used to * initialize transports. * * The agent-wide parameter can be later modified or obtained with * nua_set_params() and nua_get_params(), respectively. * * The #su_root_t mainloop integration uses: * - su_root_create(), su_root_threading(), * su_root_step(), su_root_run(), su_root_break() * * @par NUA Handles * * - nua_handle(), nua_get_hparams(), nua_set_hparams() * - nua_handle_home(), nua_handle_has_invite(), nua_handle_has_subscribe(), * nua_handle_has_register(), nua_handle_has_active_call(), * nua_handle_has_call_on_hold(), nua_handle_has_events(), * nua_handle_has_registrations(), nua_handle_remote(), and * nua_handle_local() * * Settings: * - See nua_set_hparams() * * There are a few "sticky" headers that are used * on subsequent requests if included with any handle-specific call: * - @Contact, @UserAgent, @Supported, @Allow, @Organization * * @par Client Generating SIP Requests * * - nua_register(), nua_unregister(), nua_invite(), nua_cancel(), * nua_ack(), nua_bye(), nua_options(), nua_refer(), nua_publish(), * nua_unpublish(), nua_prack(), nua_info(), nua_update(), nua_message(), * nua_subscribe(), nua_unsubscribe(), nua_notify(), nua_method() * - NUTAG_URL() * * Settings: * - NUTAG_RETRY_COUNT(), NUTAG_PROXY(), * NUTAG_INITIAL_ROUTE() and NUTAG_INITIAL_ROUTE_STR() * - NUTAG_ALLOW(), SIPTAG_ALLOW() and SIPTAG_ALLOW_STR() * - NUTAG_SUPPORTED(), SIPTAG_SUPPORTED(), and SIPTAG_SUPPORTED_STR() * - NUTAG_USER_AGENT(), SIPTAG_USER_AGENT() and SIPTAG_USER_AGENT_STR() * - SIPTAG_ORGANIZATION() and SIPTAG_ORGANIZATION_STR() * - NUTAG_AUTO302(), NUTAG_AUTO305() * * @par Client Authenticating Requests * * - nua_authenticate(), #nua_r_authenticate * - NUTAG_AUTH(), NUTAG_AUTH_CACHE() * * @par Server Processing Received SIP Requests * * - nua_respond(), NUTAG_WITH_THIS(), NUTAG_WITH_SAVED(), NUTAG_WITH() * - #nua_i_invite, #nua_i_cancel, #nua_i_ack, #nua_i_bye, * #nua_i_options, #nua_i_refer, #nua_i_publish, #nua_i_prack, * #nua_i_info, #nua_i_update, #nua_i_message, #nua_i_subscribe, * #nua_i_notify, #nua_i_method, #nua_i_register * * Settings: * - NUTAG_APPL_METHOD(), NUTAG_PROXY() * - NUTAG_ALLOW(), SIPTAG_ALLOW(), and SIPTAG_ALLOW_STR() * - NUTAG_SUPPORTED(), SIPTAG_SUPPORTED(), and SIPTAG_SUPPORTED_STR() * - NUTAG_ACCEPT_MULTIPART() * * @par Registrations and Contact Header Generation * * - nua_register(), #nua_r_register(), #nua_i_outbound, * nua_unregister(), and #nua_r_unregister * * Settings: * - NUTAG_CALLEE_CAPS() * - NUTAG_DETECT_NETWORK_UPDATES() * - NUTAG_INSTANCE() * - NUTAG_KEEPALIVE() * - NUTAG_KEEPALIVE_STREAM() * - NUTAG_M_DISPLAY() * - NUTAG_M_FEATURES() * - NUTAG_M_PARAMS() * - NUTAG_M_USERNAME() * - NUTAG_OUTBOUND() * - NUTAG_PATH_ENABLE() * - NUTAG_SERVICE_ROUTE_ENABLE() * * Specifications: * - @RFC3261 section 10, @RFC3327, @RFC3608, @RFC3680, @RFC3840, * draft-ietf-sip-outbound, draft-ietf-sip-gruu-14 * * @par INVITE Sessions and Call Model * * - nua_invite(), #nua_r_invite, #nua_i_invite * - nua_handle_has_active_call(), nua_handle_has_call_on_hold(), * nua_handle_has_invite() * - nua_cancel(), #nua_r_cancel, #nua_i_cancel * - nua_ack(), #nua_i_ack * - nua_bye(), #nua_r_bye, #nua_i_bye * - #nua_i_state, NUTAG_CALLSTATE(), * NUTAG_OFFER_SENT(), NUTAG_OFFER_RECV(), NUTAG_ANSWER_RECV(), and * NUTAG_ANSWER_SENT(), SOATAG_REMOTE_SDP(), SOATAG_REMOTE_SDP_STR(), * SOATAG_LOCAL_SDP(), SOATAG_LOCAL_SDP_STR() * * Settings: * - NUTAG_AUTOACK(), NUTAG_AUTOALERT(), NUTAG_AUTOANSWER(), NUTAG_AUTO100(), * NUTAG_ENABLEINVITE(), NUTAG_INVITE_TIMER(), NUTAG_MEDIA_ENABLE(), * SOATAG_USER_SDP(), SOATAG_USER_SDP_STR(), SOATAG_CAPS_SDP(), * SOATAG_CAPS_SDP_STR() * * Specifications: * - @RFC3261, @RFC3264 * * @par In-Session Information requests * * - nua_info() #nua_r_info, #nua_i_info * * Settings: * - @ref NUTAG_ALLOW("INFO"), @ref NUTAG_APPL_METHOD("INFO") * * @par SDP Processing * * - #nua_i_state, SOATAG_ACTIVE_AUDIO(), SOATAG_ACTIVE_VIDEO(), * SOATAG_ACTIVE_IMAGE(), SOATAG_ACTIVE_CHAT(), * SOATAG_REMOTE_SDP(), SOATAG_REMOTE_SDP_STR(), * SOATAG_LOCAL_SDP(), SOATAG_LOCAL_SDP_STR() * * Settings: * - NUTAG_MEDIA_ENABLE(), NUTAG_SOA_NAME(), NUTAG_EARLY_ANSWER(), * SOATAG_USER_SDP(), SOATAG_USER_SDP_STR(), SOATAG_CAPS_SDP(), * SOATAG_CAPS_SDP_STR(), NUTAG_ACCEPT_MULTIPART() * * Specifications: * - @RFC3264 * * @par Call Model Extensions ("100rel" and "precondition") * * Early media: * - nua_prack(), #nua_r_prack, #nua_i_prack * - nua_update() #nua_r_update, #nua_i_update * * Settings: * - NUTAG_EARLY_MEDIA(), NUTAG_ONLY183_100REL() * - "100rel" or "precondition" in NUTAG_SUPPORTED() or SIPTAG_SUPPORTED() * * Specifications: * - @RFC3262, @RFC3311, @RFC3312 * * @par SIP Session Timers ("timer") * * Periodic refresh of SIP Session initiated with INVITE with re-INVITE or * UPDATE requests. * * Settings: * - NUTAG_MIN_SE(), NUTAG_SESSION_REFRESHER(), * NUTAG_SESSION_TIMER(), NUTAG_UPDATE_REFRESH(), * NUTAG_REFRESH_WITHOUT_SDP(), * - "timer" in NUTAG_SUPPORTED() or SIPTAG_SUPPORTED() * * Specifications: * - @RFC4028 * * @par Caller Preferences and Callee Caps * * - Caller preferences in an @AcceptContact header in a INVITE requests * - Callee caps contained in a @Contact header in a REGISTER request * * Settings: * - NUTAG_CALLEE_CAPS(), NUTAG_MEDIA_FEATURES(), * NUTAG_M_FEATURES() * * Specifications: * - @RFC3840, @RFC3841 * * @par Instant Messaging * * - nua_message(), #nua_r_message, #nua_i_message * * Settings: * - @ref NUTAG_APPL_METHOD("MESSAGE"), * NUTAG_ENABLEMESSAGE(), NUTAG_ENABLEMESSENGER() * * Specifications: * - @RFC3428 * * @par Call Transfer * * - nua_refer(), #nua_r_refer, #nua_i_notify, SIPTAG_EVENT(), * @ReferTo, SIPTAG_REFER_TO(), @ReferredBy, SIPTAG_REFERRED_BY(), * nua_handle_make_replaces(), @Replaces, SIPTAG_REPLACES(), * @ReferSub, SIPTAG_REFER_SUB() * - #nua_i_refer, nua_notify(), #nua_r_notify, * nua_handle_by_replaces() * - nua_invite() with NUTAG_NOTIFY_REFER() and NUTAG_REFER_EVENT() * * Settings: * - NUTAG_REFER_EXPIRES(), NUTAG_REFER_WITH_ID() * * Specifications: * - @RFC3515 (@ReferTo), @RFC3892 (@ReferredBy), @RFC3891 (@Replaces), * @RFC4488 (@ReferSub) * * @par Internal SIP Event Server * * - nua_notifier(), #nua_r_notifier, #nua_i_subscription, * nua_authorize(), #nua_r_authorize, nua_terminate(), #nua_r_terminate * - SIPTAG_EVENT(), SIPTAG_CONTENT_TYPE(), SIPTAG_PAYLOAD(), * NUTAG_SUBSTATE() * * @par Settings * * - NUTAG_ALLOW_EVENTS(), SIPTAG_ALLOW_EVENTS(), and * SIPTAG_ALLOW_EVENTS_STR() * - NUTAG_MAX_SUBSCRIPTIONS() * - NUTAG_SUBSTATE(), NUTAG_SUB_EXPIRES() * * Specifications: * - @RFC3265 * * @par SIP Event Subscriber * * - nua_subscribe(), #nua_r_subscribe, #nua_i_notify, NUTAG_SUBSTATE(), * SIPTAG_EVENT(), SIPTAG_EXPIRES() * - nua_unsubscribe(), #nua_r_unsubscribe() * * Specifications: * - @RFC3265 * * @par SIP Event Notifier * * - #nua_i_subscribe(), nua_notify(), #nua_r_notify, * NUTAG_SUBSTATE(), NUTAG_SUB_EXPIRES(), SIPTAG_EVENT() * * Settings: * - NUTAG_SUB_EXPIRES() * - NUTAG_ALLOW_EVENTS(), SIPTAG_ALLOW_EVENTS(), and * SIPTAG_ALLOW_EVENTS_STR() * - NUTAG_APPL_EVENT() * - @ref NUTAG_ALLOW("SUBSCRIBE"), * @ref NUTAG_APPL_METHOD("SUBSCRIBE") * * Specifications * - @RFC3265 * * @par SIP Event Publisher * * - nua_publish(), #nua_r_publish(), nua_unpublish(), nua_r_unpublish() * - @SIPETag, SIPTAG_ETAG(), @SIPIfMatch, SIPTAG_IF_MATCH() * * Specifications: * - @RFC3903 * * @par SIP Event State Compositor (PUBLISH Server) * * - #nua_i_publish, @SIPETag, @SIPIfMatch * * Settings: * - @ref NUTAG_ALLOW("PUBLISH"), @ref NUTAG_APPL_METHOD("PUBLISH") * * Specifications: * - @RFC3903 * * @par Non-Standard Extension Methods * * - nua_method(), NUTAG_METHOD(), #nua_r_method, NUTAG_DIALOG() * - #nua_i_method, nua_respond() * * Settings: * - NUTAG_ALLOW(x), NUTAG_APPL_METHOD(x) * * @par Server Shutdown * * - nua_shutdown(), NUTAG_SHUTDOWN_EVENTS(), nua_destroy(). */ /* @par S/MIME * - NUTAG_SMIME_ENABLE() * - NUTAG_SMIME_KEY_ENCRYPTION() * - NUTAG_SMIME_MESSAGE_DIGEST() * - NUTAG_SMIME_MESSAGE_ENCRYPTION() * - NUTAG_SMIME_OPT() * - NUTAG_SMIME_PROTECTION_MODE() * - NUTAG_SMIME_SIGNATURE() */ tag_typedef_t nutag_any = NSTAG_TYPEDEF(*); /**@def NUTAG_URL() * * URL address from application to NUA * * @par Used with * any function that create SIP request or nua_handle() \n * nua_create() \n * nua_set_params() \n * nua_get_params() \n * * @par Parameter type * char const * or url_t * or url_string_t * * * @par Values * #url_string_t, which is either a pointer to #url_t or NULL terminated * character string representing URL * * For normal nua calls, this tag is used as request target, which is usually * stored as request-URI. * * It is used to set stack's own address with nua_create(), nua_set_params() * and nua_get_params(). It can be specified multiple times when used with * nua_create(). * * @sa SIPTAG_TO() * * Corresponding tag taking reference parameter is NUTAG_URL_REF() */ tag_typedef_t nutag_url = URLTAG_TYPEDEF(url); /**@def NUTAG_METHOD(x) * * Extension method name. * * Specify extension method name with nua_method() function. * * @par Used with * nua_method() \n * * @par Parameter type * char const * * * @par Values * Extension method name (e.g., "SERVICE") * * Corresponding tag taking reference parameter is NUTAG_METHOD_REF() * * @sa nua_method(), SIP_METHOD_UNKNOWN() * * @since New in @VERSION_1_12_4. */ tag_typedef_t nutag_method = STRTAG_TYPEDEF(method); /**@def NUTAG_METHOD_REF(x) * Reference tag for NUTAG_METHOD(). */ /*#@def NUTAG_UICC(x) * * Intentionally undocumented. */ tag_typedef_t nutag_uicc = STRTAG_TYPEDEF(uicc); /*#@def NUTAG_UICC_REF(x) * Reference tag for NUTAG_UICC(). */ /**@def NUTAG_MEDIA_FEATURES() * * Add media tags from our offer to Accept-Contact headers. * * Automatically generate @AcceptContact headers for caller * preference processing according to the media capabilities in @a soa. * * @par Used with * - nua_create(), nua_set_params(), nua_get_params() * - nua_handle(), nua_set_hparams(), nua_get_hparams() * - nua_invite() * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * @par Values * - 0 (false) - Do not add @AcceptContact * - 1 (true) - Add @AcceptContact with media tags * * Corresponding tag taking reference parameter is NUTAG_MEDIA_FEATURES_REF() * * @sa nua_invite(), @AcceptContact, @RFC3841, @RFC3840, SOATAG_USER_SDP(), * SIPTAG_ACCEPT_CONTACT(), NUTAG_CALLEE_CAPS() */ tag_typedef_t nutag_media_features = BOOLTAG_TYPEDEF(media_features); /**@def NUTAG_MEDIA_FEATURES_REF(x) * Reference tag for NUTAG_MEDIA_FEATURES(). */ /**@def NUTAG_CALLEE_CAPS(x) * * Add methods parameter and media feature parameter to the @Contact headers * generated for REGISTER request. * * @par Used with * - nua_create(), nua_set_params(), nua_get_params() * - nua_handle(), nua_set_hparams(), nua_get_hparams() * - nua_register() * * @par Parameter type * int * * @par Values * - 0 (false) - Do not include methods and media feature parameters * - 1 (true) - Include media tags in @Contact * * Corresponding tag taking reference parameter is NUTAG_MEDIA_FEATURES_REF(). * * @sa nua_register(), @Contact, NUTAG_M_FEATURES(), @RFC3840, @RFC3841, * SOATAG_USER_SDP(), NUTAG_MEDIA_FEATURES() */ tag_typedef_t nutag_callee_caps = BOOLTAG_TYPEDEF(callee_caps); /**@def NUTAG_CALLEE_CAPS_REF(x) * Reference tag for NUTAG_CALLEE_CAPS(). */ /**@def NUTAG_EARLY_MEDIA(x) * * Establish early media session using 100rel, 183 responses and PRACK. * * @par Used with * - nua_create(), nua_set_params(), nua_get_params() * - nua_handle(), nua_set_hparams(), nua_get_hparams() * - nua_invite(), nua_respond() * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * @par Values * - 0 (false) - do not try to use early media * - 1 (true) - try to use early media * * @sa NUTAG_EARLY_ANSWER() * * Corresponding tag taking reference parameter is NUTAG_EARLY_MEDIA_REF(). */ tag_typedef_t nutag_early_media = BOOLTAG_TYPEDEF(early_media); /**@def NUTAG_EARLY_MEDIA_REF(x) * Reference tag for NUTAG_EARLY_MEDIA(). */ /**@def NUTAG_ONLY183_100REL(x) * * Require 100rel extension and PRACK only with 183 response. * * When NUTAG_EARLY_MEDIA() is set, and if this parameter is set, stack * includes feature tag "100rel" in the @Require header only with 183: * otherwise, all 1XX responses (except 100 Trying) require 100rel. * * @par Used with * nua_set_params() \n * nua_get_params() \n * nua_handle() \n * nua_set_hparams() \n * nua_get_hparams() \n * nua_invite() \n * nua_respond() * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * @par Values * - 0 (false) - include 100rel in all preliminary responses * - 1 (true) - include 100rel only in 183 responses * * @note * This tag takes only effect when NUTAG_EARLY_MEDIA(1) has been used, too. * * Corresponding tag taking reference parameter is NUTAG_ONLY183_100REL_REF(). * * @sa */ tag_typedef_t nutag_only183_100rel = BOOLTAG_TYPEDEF(only183_100rel); /**@def NUTAG_ONLY183_100REL_REF(x) * Reference tag for NUTAG_ONLY183_100REL(). */ /**@def NUTAG_EARLY_ANSWER(x) * * Establish early media session by including SDP answer in 1XX response. * * @par Used with * nua_respond(), nua_set_params(), nua_set_hparams() * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * @par Values * - 0 (false) - do not include SDP in non-100rel 1XX responses * - 1 (true) - try to include SDP in preliminary responses * * Corresponding tag taking reference parameter is NUTAG_EARLY_ANSWER_REF(). * * @note Requires that @soa is enabled with NUTAG_MEDIA_ENABLE(1). * * @sa NUTAG_EARLY_MEDIA(), NUTAG_AUTOALERT(), NUTAG_MEDIA_ENABLE() * * @since New in @VERSION_1_12_2. */ tag_typedef_t nutag_early_answer = BOOLTAG_TYPEDEF(early_answer); /**@def NUTAG_EARLY_ANSWER_REF(x) * Reference tag for NUTAG_EARLY_ANSWER(). */ /**@def NUTAG_INCLUDE_EXTRA_SDP(x) * * Include an extra copy of SDP answer in the response. * * When NUTAG_INCLUDE_EXTRA_SDP(1) is included in nua_respond() tags, stack * will include in the response a copy of the SDP offer/answer that was last * sent to the client. This tag should be used only when you know that the * remote end requires the extra SDP, for example, some versions of Cisco * SIPGateway need a copy of answer in 200 OK even when they indicate * support for 100rel. * * @par Used with * nua_respond() * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * @par Values * - 0 (false) - do not include extra SDP on 200 OK * - 1 (true) - include SDP in 200 OK even if it has been sent * a 100rel response, too * * Corresponding tag taking reference parameter is * NUTAG_INCLUDE_EXTRA_SDP_REF(). * * @note Requires that @soa is enabled with NUTAG_MEDIA_ENABLE(1). * * @sa NUTAG_EARLY_ANSWER(), NUTAG_EARLY_MEDIA(), NUTAG_AUTOALERT(), * NUTAG_MEDIA_ENABLE(), @RFC3264, @RFC3264 * * @since New in @VERSION_1_12_4. */ tag_typedef_t nutag_include_extra_sdp = BOOLTAG_TYPEDEF(include_extra_sdp); /**@def NUTAG_INCLUDE_EXTRA_SDP_REF(x) * Reference tag for NUTAG_INCLUDE_EXTRA_SDP(). */ /**@def NUTAG_MEDIA_ENABLE() * * Enable built-in media session handling * * The built-in media session object @soa takes care of most details * of offer-answer negotiation. * * @par Used with * nua_create(), nua_handle(), nua_set_hparams(), * nua_get_params(), nua_get_hparams(), * nua_register(), nua_unregister(), * nua_options(), nua_invite(), nua_ack(), nua_cancel(), nua_bye(), * nua_prack(), nua_update(), nua_info(), * nua_message(), nua_publish(), nua_unpublish(), nua_notifier(), * nua_subscribe(), nua_unsubscribe(), nua_notify(), nua_refer(), * nua_method(), nua_respond(), * nua_authenticate(). * * @par Parameter type * int * * @par Values * - 0 (false) - do not use soa * - 1 (true) - use soa with SDP O/A * * Corresponding tag taking reference parameter is NUTAG_MEDIA_ENABLE_REF() */ tag_typedef_t nutag_media_enable = BOOLTAG_TYPEDEF(media_enable); /**@def NUTAG_MEDIA_ENABLE_REF(x) * Reference tag for NUTAG_MEDIA_ENABLE(). */ /**@def NUTAG_ACCEPT_MULTIPART() * * Enable multipart processing for received messages. If an incoming * request or response contains multipart body, it is parsed and can be * accessed from @a sip_multipart field. * * @par Used with * nua_create(), nua_handle(), nua_set_hparams(), * nua_get_params(), nua_get_hparams(), * nua_register(), nua_unregister(), * nua_options(), nua_invite(), nua_ack(), nua_cancel(), nua_bye(), * nua_prack(), nua_update(), nua_info(), * nua_message(), nua_publish(), nua_unpublish(), nua_notifier(), * nua_subscribe(), nua_unsubscribe(), nua_notify(), nua_refer(), * nua_method(), nua_respond(), * nua_authenticate(). * * @par Parameter type * int (boolean) * * @par Values * - 0 (false) - do not interpret multipart bodies * - 1 (true) - try to parse message body in multipart format * * Corresponding tag taking reference parameter is NUTAG_ACCEPT_MULTIPART_REF() * * @NEW_UNRELEASED */ tag_typedef_t nutag_accept_multipart = BOOLTAG_TYPEDEF(accept_multipart); /**@def NUTAG_ACCEPT_MULTIPART_REF(x) * Reference tag for NUTAG_ACCEPT_MULTIPART(). * @NEW_UNRELEASED */ /**@def NUTAG_SOA_NAME(x) * * Name for SDP Offer-Answer session object. * * SDP Offer-Answer session object name. * * @par Used with nua_create(), nua_handle(). * * @par Parameter type * void * (actually soa_session_t *) * * @par Values * Pointer to MSS media session. * * Corresponding tag taking reference parameter is NUTAG_SOA_NAME_REF(). */ tag_typedef_t nutag_soa_name = STRTAG_TYPEDEF(soa_name); /**@def NUTAG_SOA_NAME_REF(x) * Reference tag for NUTAG_SOA_NAME(). */ /**@def NUTAG_RETRY_COUNT(x) * * Set request retry count. * * Retry count determines how many times stack will automatically retry * after an recoverable error response, like 302, 401 or 407. * * Note that the first request does not count as retry. * * @par Used with * nua_create(), nua_set_params(), nua_handle(), nua_set_hparams(), * nua_get_params(), nua_get_hparams(), * nua_register(), nua_unregister(), * nua_options(), nua_invite(), nua_ack(), nua_cancel(), nua_bye(), * nua_prack(), nua_update(), nua_info(), * nua_message(), nua_publish(), nua_unpublish(), nua_notifier(), * nua_subscribe(), nua_unsubscribe(), nua_notify(), nua_refer(), * nua_method(), nua_respond(), * nua_authenticate(). * * @par Parameter type * unsigned * * @par Values * - 0 - Never retry automatically * - Otherwise, number of extra transactions initiated after initial * transaction failed with recoverable error response * * @NEW_1_12_4. * * Corresponding tag taking reference parameter is NUTAG_RETRY_COUNT_REF(). */ tag_typedef_t nutag_retry_count = UINTTAG_TYPEDEF(retry_count); /**@def NUTAG_RETRY_COUNT_REF(x) * * Reference tag for NUTAG_RETRY_COUNT(). */ /**@def NUTAG_MAX_SUBSCRIPTIONS(x) * * Set maximum number of simultaneous subscribers per single event server. * * Determines how many subscribers can simultaneously subscribe to a single * event. * * @par Used with * nua_set_params() \n * nua_get_params() * * @par Parameter type * unsigned int * * @par Values * - 0 (zero) - do not allow any subscriptions * * @sa nua_notifier(), nua_authorize() * * Corresponding tag taking reference parameter is * NUTAG_MAX_SUBSCRIPTIONS_REF(). */ tag_typedef_t nutag_max_subscriptions = UINTTAG_TYPEDEF(max_subscriptions); /**@def NUTAG_MAX_SUBSCRIPTIONS_REF(x) * Reference tag for NUTAG_MAX_SUBSCRIPTIONS(). */ /**@def NUTAG_CALLSTATE() * * Call state * * @par Used with * #nua_i_state * * @par Parameter type * int * * @par Values * - #nua_callstate_init - Initial state * - #nua_callstate_authenticating - 401/407 received * - #nua_callstate_calling - INVITE sent * - #nua_callstate_proceeding - 18X received * - #nua_callstate_completing - 2XX received * - #nua_callstate_received - INVITE received (and 100 Trying sent) * - #nua_callstate_early - 18X sent * - #nua_callstate_completed - 2XX sent * - #nua_callstate_ready - 2XX and ACK received/sent * - #nua_callstate_terminating - BYE sent * - #nua_callstate_terminated - BYE complete * * Corresponding tag taking reference parameter is NUTAG_CALLSTATE_REF(). */ tag_typedef_t nutag_callstate = INTTAG_TYPEDEF(callstate); /**@def NUTAG_CALLSTATE_REF(x) * Reference tag for NUTAG_CALLSTATE(). */ /**@def NUTAG_OFFER_RECV() * * Indicate that SDP offer has been received. * * @par Used with * #nua_i_state * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * Corresponding tag taking reference parameter is NUTAG_OFFER_RECV_REF(). */ tag_typedef_t nutag_offer_recv = BOOLTAG_TYPEDEF(offer_recv); /**@def NUTAG_OFFER_RECV_REF(x) * Reference tag for NUTAG_OFFER_RECV(). */ /**@def NUTAG_ANSWER_RECV() * * Indicate that SDP answer has been received. * * @par Used with * #nua_i_state * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * Corresponding tag taking reference parameter is NUTAG_ANSWER_RECV_REF(). */ tag_typedef_t nutag_answer_recv = BOOLTAG_TYPEDEF(answer_recv); /**@def NUTAG_ANSWER_RECV_REF(x) * Reference tag for NUTAG_ANSWER_RECV(). */ /**@def NUTAG_OFFER_SENT() * * Indicate that SDP offer has been sent. * * @par Used with * #nua_i_state * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * Corresponding tag taking reference parameter is NUTAG_OFFER_SENT_REF(). */ tag_typedef_t nutag_offer_sent = BOOLTAG_TYPEDEF(offer_sent); /**@def NUTAG_OFFER_SENT_REF(x) * Reference tag for NUTAG_OFFER_SENT(). */ /**@def NUTAG_ANSWER_SENT() * * Indicate that SDP answer has been sent. * * @par Used with * #nua_i_state * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * Corresponding tag taking reference parameter is NUTAG_ANSWER_SENT_REF(). */ tag_typedef_t nutag_answer_sent = BOOLTAG_TYPEDEF(answer_sent); /**@def NUTAG_ANSWER_SENT_REF(x) * Reference tag for NUTAG_ANSWER_SENT(). */ /**@def NUTAG_SUBSTATE() * * Subscription state. * * @par Used with * - with nua_create(), nua_set_params(), nua_get_params(), * nua_handle(), nua_set_hparams(), nua_get_hparams(), and * nua_notifier() to change the default subscription state returned by * the internal event server * - with nua_notify() and nua_respond() to SUBSCRIBE to determine the * subscription state (if application include @SubscriptionState * header in the tag list, the NUTAG_SUBSTATE() value is ignored) * - with #nua_r_subscribe, #nua_i_notify, #nua_i_subscribe, and #nua_r_notify * to indicate the current subscription state * * @par Parameter type * int * * @par Values * - #nua_substate_embryonic (0) * - #nua_substate_pending (1) * - #nua_substate_active (2) * - #nua_substate_terminated (3) * * Note that the @SubscriptionState or @Expires headers specified by * application with the nua_notify() or nua_respond() to SUBSCRIBE overrides * the subscription state specified by NUTAG_SUBSTATE(). * Application can terminate subscription by including * NUTAG_SUBSTATE(nua_substate_terminated), @SubscriptionState with value * "terminated" or @Expires header with value 0 in the NOTIFY request sent * by nua_notify(). * * @sa @RFC3265, @SubscriptionState, SIPTAG_SUBSCRIPTION_STATE(), * SIPTAG_SUBSCRIPTION_STATE_STR(), nua_notifier(), #nua_r_subscribe, * #nua_i_subscribe, #nua_i_refer, #nua_r_notify, #nua_i_notify. * * Corresponding tag taking reference parameter is NUTAG_SUBSTATE_REF(). */ tag_typedef_t nutag_substate = INTTAG_TYPEDEF(substate); /**@def NUTAG_SUBSTATE_REF(x) * Reference tag for NUTAG_SUBSTATE(). */ /**@def NUTAG_SUB_EXPIRES() * * Default expiration time of subscriptions. * * @par Used with * - with nua_create(), nua_set_params(), nua_get_params(), nua_handle(), * nua_set_hparams(), nua_get_hparams(), nua_respond(), nua_notify(), and * nua_notifier() to change the default expiration time of subscriptions * * @par Parameter type * unsigned int * * @par Values * - default expiration time in seconds * * Note that the expires parameter in @SubscriptionState or @Expires header * in the nua_response() to the SUBSCRIBE overrides the default subscription * expiration specified by NUTAG_SUB_EXPIRES(). * * @sa @RFC3265, NUTAG_REFER_EXPIRES(), @Expires, SIPTAG_EXPIRES(), * SIPTAG_EXPIRES_STR(), @SubscriptionState, nua_respond(), nua_notifier(), * #nua_r_subscribe, #nua_i_subscribe, #nua_r_refer, #nua_r_notify, * #nua_i_notify. * * Corresponding tag taking reference parameter is NUTAG_SUB_EXPIRES_REF(). * * @NEW_1_12_9. */ tag_typedef_t nutag_sub_expires = UINTTAG_TYPEDEF(substate); /**@def NUTAG_SUB_EXPIRES_REF(x) * Reference tag for NUTAG_SUB_EXPIRES(). */ /**@def NUTAG_NEWSUB() * * Send unsolicited NOTIFY request. * * Some applications may require sending unsolicited NOTIFY requests, that * is, NOTIFY without SUBSCRIBE or REFER request sent by event watcher. * However, sending NOTIFY request requires an existing dialog usage by * default. If the nua_notify() tags include NUTAG_NEWSUB(1), the usage * is created by nua_notify() itself. * * If you want to create a subscription that does not terminate immediately * include SIPTAG_SUBSCRIPTION_STATE()/SIPTAG_SUBSCRIPTION_STATE_STR() with * an "expires" parameter in the argument list, too. * * @par Used with * nua_notify() * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * @par Values * - 0 - false (default) - do not create new subscription * but reject NOTIFY with 481 locally * - 1 - true - create a subscription if it does not exist * * Corresponding tag taking reference parameter is NUTAG_NEWSUB_REF(). * * @NEW_1_12_5. */ tag_typedef_t nutag_newsub = BOOLTAG_TYPEDEF(newsub); /**@def NUTAG_NEWSUB_REF(x) * Reference tag for NUTAG_NEWSUB(). */ /**@def NUTAG_INVITE_TIMER(x) * * Timer for outstanding INVITE in seconds. * * INVITE will be canceled if no answer is received before timer expires. * * @par Used with * nua_invite() \n * nua_set_params(), nua_set_hparams(), * nua_get_params(), nua_get_hparams() * * @par Parameter type * int (enum nua_af) * * @par Values * - 0 no timer * - >0 timer in seconds * * Corresponding tag taking reference parameter is NUTAG_INVITE_TIMER_REF(). */ tag_typedef_t nutag_invite_timer = UINTTAG_TYPEDEF(invite_timer); /**@def NUTAG_INVITE_TIMER_REF(x) * Reference tag for NUTAG_INVITE_TIMER(). */ /**@def NUTAG_SESSION_TIMER(x) * * Default session timer in seconds. * * Set default value for session timer in seconds when the session timer * extension is used. The tag value is the proposed session expiration time * in seconds, the session is refreshed twice during the expiration time. * * @par Sending INVITE and UPDATE Requests * * If NUTAG_SESSION_TIMER() is used with non-zero value, the value is used * in the @SessionExpires header included in the INVITE or UPDATE requests. * The intermediate proxies or the ultimate destination can lower the * interval in @SessionExpires header. If the value is too low, they can * reject the request with the status code 422 Session Timer Too * Small. In that case, @b nua increases the value of @SessionExpires * header and retries the request automatically. * * @par Returning a Response to the INVITE and UPDATE Requests * * The NUTAG_SESSION_TIMER() value is also used when sending the final * response to the INVITE or UPDATE requests. If the NUTAG_SESSION_TIMER() * value is 0 or the value in the @SessionExpires header of the request is * lower than the value in NUTAG_SESSION_TIMER(), the value from the * incoming @SessionExpires header is used. However, if the value in * @SessionExpires is lower than the minimal acceptable session expiration * interval specified with the tag NUTAG_MIN_SE() the request is * automatically rejected with 422 Session Timer Too Small. * * @par Refreshes * * After the initial INVITE request, the SIP session is refreshed at the * intervals indicated by the @SessionExpires header returned in the 2XX * response. The party indicated with the "refresher" parameter of the * @SessionExpires header sends a re-INVITE requests (or an UPDATE * request if NUTAG_UPDATE_REFRESH(1) parameter tag has been set). * * Some SIP user-agents use INVITE without SDP offer to refresh session. * By default, NUA sends an offer in 200 OK to such an INVITE and expects * an answer back in ACK. If NUTAG_REFRESH_WITHOUT_SDP(1) tag is used, * no SDP offer is sent in 200 OK if re-INVITE was received without SDP. * * @par When to Use NUTAG_SESSION_TIMER()? * * The session time extension is enabled ("timer" feature tag is included in * @Supported header) but not activated by default (no @SessionExpires * header is included in the requests or responses by default). Using * non-zero value with NUTAG_SESSION_TIMER() or NUTAG_SESSION_REFRESHER() * activates it. When the extension is activated, @nua refreshes the call * state by sending periodic re-INVITE or UPDATE requests unless the remote * end indicated that it will take care of refreshes. * * The session timer extension is mainly useful for proxies or back-to-back * user agents that keep call state. The call state is "soft" meaning that * if no call-related SIP messages are processed for certain time the state * will be destroyed. An ordinary user-agent can also make use of session * timer if it cannot get any activity feedback from RTP or other media. * * @note The session timer extension is used only if the feature * tag "timer" is listed in the @Supported header, set by NUTAG_SUPPORTED(), * SIPTAG_SUPPORTED(), or SIPTAG_SUPPORTED_STR() tags. * * @par Used with * nua_invite(), nua_update(), nua_respond() \n * nua_set_params() or nua_set_hparams() \n * nua_get_params() or nua_get_hparams() * * See nua_set_hparams() for a complete list of the the nua operations that * accept this tag. * * @par Parameter type * unsigned int * * @par Values * - 0 disable * - >0 interval in seconds * * Corresponding tag taking reference parameter is NUTAG_SESSION_TIMER_REF(). * * @sa NUTAG_SUPPORTED(), NUTAG_MIN_SE(), NUTAG_SESSION_REFRESHER(), * nua_invite(), #nua_r_invite, #nua_i_invite, nua_respond(), * nua_update(), #nua_r_update, #nua_i_update, * NUTAG_UPDATE_REFRESH(), @RFC4028, @SessionExpires, @MinSE */ tag_typedef_t nutag_session_timer = UINTTAG_TYPEDEF(session_timer); /**@def NUTAG_SESSION_TIMER_REF(x) * Reference tag for NUTAG_SESSION_TIMER(). */ /**@def NUTAG_MIN_SE(x) * * Minimum acceptable refresh interval for session. * * Specifies the value of @MinSE header in seconds. The @b Min-SE header is * used to specify minimum acceptable refresh interval for session timer * extension. * * @par Used with * nua_handle(), nua_invite(), nua_update(), nua_respond() \n * nua_set_params() or nua_set_hparams() \n * nua_get_params() or nua_get_hparams() * * See nua_set_hparams() for a complete list of the nua operations that * accept this tag. * * @par Parameter type * unsigned int * * @par Values * interval in seconds. * * Corresponding tag taking reference parameter is NUTAG_MIN_SE_REF(). * * @sa NUTAG_SESSION_TIMER(), NUTAG_SESSION_REFRESHER(), * NUTAG_UPDATE_REFRESH(), @RFC4028, @MinSE, @SessionExpires */ tag_typedef_t nutag_min_se = UINTTAG_TYPEDEF(min_se); /**@def NUTAG_MIN_SE_REF(x) * Reference tag for NUTAG_MIN_SE(). */ /**@def NUTAG_SESSION_REFRESHER(x) * * Specify the preferred refresher. * * Specify for session timer extension which party is the preferred refresher. * * @par Used with * nua_handle(), nua_invite(), nua_update(), nua_respond() \n * nua_set_params() or nua_set_hparams() \n * nua_get_params() or nua_get_hparams() * * See nua_set_hparams() for a complete list of all the nua operations that * accept this tag. * * @par Parameter type * enum { #nua_no_refresher, #nua_local_refresher, #nua_remote_refresher, * #nua_any_refresher } * * @par Values * - nua_no_refresher (session timers are disabled) * - nua_local_refresher * - nua_remote_refresher * - nua_any_refresher (default) * * Corresponding tag taking reference parameter is * NUTAG_SESSION_REFRESHER_REF(). * * @sa NUTAG_SESSION_TIMER(), NUTAG_MIN_SE_REF(), * NUTAG_UPDATE_REFRESH(), @RFC4028, @SessionExpires, @MinSE */ tag_typedef_t nutag_session_refresher = INTTAG_TYPEDEF(session_refresher); /**@def NUTAG_SESSION_REFRESHER_REF(x) * Reference tag for NUTAG_SESSION_REFRESHER(). */ /**@def NUTAG_UPDATE_REFRESH(x) * * Use UPDATE as refresh method. * * If this parameter is true and the remote endpoint has included UPDATE in * Allow header, the nua stack uses UPDATE instead of INVITE to refresh the * session when using the session timer extension. * * Note that the session timer headers @SessionExpires and @MinSE are always * included in the UPDATE request and responses regardless of the value of * this tag. * * @par Used with * nua_handle(), nua_invite(), nua_update(), nua_respond() \n * nua_set_params() or nua_set_hparams() \n * nua_get_params() or nua_get_hparams() * * See nua_set_hparams() for a complete list of all the nua operations that * accept this tag. * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * @par Values * - 1 (true, use UPDATE) * - 0 (false, use INVITE) * * Corresponding tag taking reference parameter is NUTAG_UPDATE_REFRESH_REF(). * * @sa #nua_r_update, NUTAG_SESSION_TIMER(), NUTAG_MIN_SE_REF(), * NUTAG_SESSION_REFRESHER(), @RFC4028, @SessionExpires, @MinSE */ tag_typedef_t nutag_update_refresh = BOOLTAG_TYPEDEF(update_refresh); /**@def NUTAG_UPDATE_REFRESH_REF(x) * Reference tag for NUTAG_UPDATE_REFRESH(). */ /**@def NUTAG_REFRESH_WITHOUT_SDP(x) * * Do not send offer in response if re-INVITE was received without SDP. * * Some SIP user-agents use INVITE without SDP offer to refresh session. * By default, NUA sends an offer in 200 OK to such an INVITE and expects * an answer back in ACK. * * If NUTAG_REFRESH_WITHOUT_SDP(1) tag is used, no SDP offer is sent in 200 * OK if re-INVITE was received without SDP. * * @par Used with * nua_handle(), nua_invite(), nua_update(), nua_respond() \n * nua_set_params() or nua_set_hparams() \n * nua_get_params() or nua_get_hparams() * * See nua_set_hparams() for a complete list of all the nua operations that * accept this tag. * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * @par Values * - 1 (true, do not try to send offer in response to re-INVITE) * - 0 (false, always use SDP offer-answer in re-INVITEs) * * Corresponding tag taking reference parameter is NUTAG_REFRESH_WITHOUT_SDP_REF(). * * @sa #nua_r_update, NUTAG_SESSION_TIMER(), NUTAG_MIN_SE_REF(), * NUTAG_SESSION_REFRESHER(), NUTAG_UPDATE_REFRESH(), @RFC4028, * @SessionExpires, @MinSE * * @NEW_1_12_10 */ tag_typedef_t nutag_refresh_without_sdp = BOOLTAG_TYPEDEF(refresh_without_sdp); /**@def NUTAG_REFRESH_WITHOUT_SDP_REF(x) * Reference tag for NUTAG_REFRESH_WITHOUT_SDP_REF(). */ /**@def NUTAG_REFER_EXPIRES() * * Default lifetime for implicit subscriptions created by REFER. * * Default expiration time in seconds for implicit subscriptions created by * REFER. * * @par Used with * nua_handle(), nua_respond() \n * nua_set_params() or nua_set_hparams() \n * nua_get_params() or nua_get_hparams() * * @par Parameter type * unsigned int * * @par Values * - default interval in seconds * * @sa NUTAG_SUB_EXPIRES() * * Corresponding tag taking reference parameter is NUTAG_REFER_EXPIRES_REF(). */ tag_typedef_t nutag_refer_expires = UINTTAG_TYPEDEF(refer_expires); /**@def NUTAG_REFER_EXPIRES_REF(x) * Reference tag for NUTAG_REFER_EXPIRES(). */ /**@def NUTAG_REFER_WITH_ID() * * Always use id parameter with refer event. * * When an incoming REFER creates an implicit subscription, the event header * in the NOTIFY request may have an id parameter. The id parameter can be * either always included (default behavior), or the parameter can be used * only for the second and subsequent REFER requests received in a given * dialog. * * Note that once the subscription is created, the event header should not * be modified. Therefore this tag has no effect on already established * subscriptions, and its use makes sense largely on nua_set_params() only. * * @par Used with * nua_set_params() (nua_set_hparams(), nua_invite(), nua_respond(), * nua_update()). * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * @par Values * - 0 (false, do not use id with subscription created with first REFER request) * - 1 (true, use id with all subscriptions created with REFER request) * * Corresponding tag taking reference parameter is NUTAG_REFER_WITH_ID_REF(). * * @since New in @VERSION_1_12_2. */ tag_typedef_t nutag_refer_with_id = BOOLTAG_TYPEDEF(refer_with_id); /**@def NUTAG_REFER_WITH_ID_REF(x) * Reference tag for NUTAG_REFER_WITH_ID(). */ /**@def NUTAG_AUTOALERT(x) * * Send alerting (180 Ringing) automatically (instead of 100 Trying). If the * early media has been enabled with NUTAG_EARLY_MEDIA(1), the stack will * send 183, wait for PRACK and then return 180 Ringing. * * @par Used with * nua_set_params() \n * nua_get_params() * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * @par Values * - 0 (false) - no automatic sending of "180 Ringing" * - 1 (true) - "180 Ringing" sent automatically * * Corresponding tag taking reference parameter is NUTAG_AUTOALERT_REF(). */ tag_typedef_t nutag_autoalert = BOOLTAG_TYPEDEF(autoAlert); /**@def NUTAG_AUTOALERT_REF(x) * Reference tag for NUTAG_AUTOALERT(). */ /**@def NUTAG_AUTOANSWER(x) * * Answer (with 200 Ok) automatically to incoming call. * * @par Used with * nua_set_params(), nua_set_hparams() \n * nua_get_params(), nua_get_hparams() \n * nua_invite() \n * nua_respond() * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * @par Values * - 0 (false) - No automatic sending of "200 Ok" * - 1 (true) - "200 Ok" sent automatically * * Corresponding tag taking reference parameter is NUTAG_AUTOANSWER_REF(). * * @note Requires that @soa is enabled with NUTAG_MEDIA_ENABLE(1). * * @par Auto-Answer to Re-INVITE requests * By default, NUA tries to auto answer the re-INVITEs used to refresh the * session when the media is enabled. Set NUTAG_AUTOANSWER(0) on the call * handle (e.g., include the tag with nua_invite(), nua_respond()) in order * to disable the auto answer on re-INVITEs. * * @bug If the re-INVITE modifies the session (e.g., SDP contains offer that * adds video stream to the session), NUA auto-answers it if * NUTAG_AUTOANSWER(0) has not been set on the handle. It accepts or rejects * media based on the existing user SDP (set with SOATAG_USER_SDP(), for * example). It should auto-answer only session refresh request and let * application decide how to handle requests to modify the session. * * @sa NUTAG_MEDIA_ENABLE(), NUTAG_AUTOALERT(), NUTAG_AUTOACK(). */ tag_typedef_t nutag_autoanswer = BOOLTAG_TYPEDEF(autoAnswer); /**@def NUTAG_AUTOANSWER_REF(x) * Reference tag for NUTAG_AUTOANSWER(). */ /**@def NUTAG_AUTOACK(x) * * ACK automatically * * If this parameter is true, ACK is sent automatically after receiving 2XX * series response to INVITE. Note that ACK is always sent automatically by * lower layers of the stack after receiving an error response 3XX, 4XX, 5XX * or 6XX. * * @par Used with * nua_set_params(), nua_set_hparams(), \n * nua_get_params(), nua_get_hparams(), \n * nua_invite(), nua_ack(), nua_respond(), nua_update() \n * nua_respond() * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * @par Values * - 0 (false) - No automatic sending of ACK * - 1 (true) - ACK sent automatically * * Default value is NUTAG_AUTOACK(1). * * @par Auto ACK with Re-INVITE requests * By default, NUA tries to auto-ACK the final response to re-INVITE used to * refresh the session when the media is enabled. Set NUTAG_AUTOACK(0) on * the call handle (e.g., include the tag with nua_invite() or * nua_respond()) in order to disable the auto ACK with re-INVITE. * * Corresponding tag taking reference parameter is NUTAG_AUTOACK_REF(). */ tag_typedef_t nutag_autoack = BOOLTAG_TYPEDEF(autoACK); /**@def NUTAG_AUTOACK_REF(x) * Reference tag for NUTAG_AUTOACK(). */ /**@def NUTAG_ENABLEINVITE(x) * * Enable incoming INVITE. * * * @par Used with * nua_set_params() \n * nua_get_params() * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * @par Values * - 0 (false) - Incoming INVITE not enabled. NUA answers 403 Forbidden * - 1 (true) - Incoming INVITE enabled * * Corresponding tag taking reference parameter is NUTAG_ENABLEINVITE_REF(). */ tag_typedef_t nutag_enableinvite = BOOLTAG_TYPEDEF(enableInvite); /**@def NUTAG_ENABLEINVITE_REF(x) * Reference tag for NUTAG_ENABLEINVITE(). */ /**@def NUTAG_ENABLEMESSAGE(x) * * Enable incoming MESSAGE * * @par Used with * nua_set_params() \n * nua_get_params() * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * @par Values * - 0 (false) - Incoming MESSAGE not enabled. NUA answers 403 Forbidden * - 1 (true) - Incoming MESSAGE enabled * * Corresponding tag taking reference parameter is NUTAG_ENABLEMESSAGE_REF(). */ tag_typedef_t nutag_enablemessage = BOOLTAG_TYPEDEF(enableMessage); /**@def NUTAG_ENABLEMESSAGE_REF(x) * Reference tag for NUTAG_ENABLEMESSAGE(). */ /**@def NUTAG_ENABLEMESSENGER(x) * * Enable incoming MESSAGE with To tag. * * Set this parameter true if you want to chat with Windows Messenger. When * it is set, stack will accept MESSAGE requests with To tag outside * existing dialogs. * * @par Used with * nua_set_params() \n * nua_get_params() * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * @par Values * - 0 (false) - disable Windows-Messenger-specific features * - 1 (true) - enable Windows-Messenger-specific features * * Corresponding tag taking reference parameter is NUTAG_ENABLEMESSENGER_REF(). */ tag_typedef_t nutag_enablemessenger = BOOLTAG_TYPEDEF(enableMessenger); /**@def NUTAG_ENABLEMESSENGER_REF(x) * Reference tag for NUTAG_ENABLEMESSENGER(). */ /**@def NUTAG_AUTO302(x) * * Recurse automatically on 302 response. * * If this parameter is true, a client recurses automatically upon receiving * a 302 response. The request is resent with the request-URI from the * @Contact header in the 302 response. * * @par Used with * nua_create(), nua_set_params(), nua_set_hparams(), \n * nua_get_params(), nua_get_hparams(), \n * nua_invite(), nua_prack(), nua_ack(), nua_update(), nua_respond(), \n * nua_info(), nua_cancel(), nua_bye(), \n * nua_register(), nua_unregister(), nua_publish(), nua_unpublish(), \n * nua_subscribe(), nua_unsubscribe(), nua_refer(), nua_notify(), \n * nua_options(), nua_message(), nua_method() * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * @par Values * - 0 (false) - process 302 as an ordinary final response * - 1 (true) - resend request with URI received in 302 response * * Default value is NUTAG_AUTO302(1). * * Corresponding tag taking reference parameter is NUTAG_AUTO302_REF(). * * @NEW_1_12_11 */ tag_typedef_t nutag_auto302 = BOOLTAG_TYPEDEF(auto302); /**@def NUTAG_AUTO302_REF(x) * Reference tag for NUTAG_AUTO302(). */ /**@def NUTAG_AUTO305(x) * * Recurse automatically on 305 response. * * If this parameter is true, a client recurses automatically upon receiving * a 305 response. The request is resent via the proxy specified by the * @Contact header in the 305 response. The proxy URI is included in the * @Route header of the request. * * Note that the NUTAG_PROXY() takes a precedence over the proxy in 305, and * the NUTAG_PROXY() is responsible of actually routing the request through * the 305 proxy. * * @par Used with * nua_create(), nua_set_params(), nua_set_hparams(), \n * nua_get_params(), nua_get_hparams(), \n * nua_invite(), nua_prack(), nua_ack(), nua_update(), nua_respond(), \n * nua_info(), nua_cancel(), nua_bye(), \n * nua_register(), nua_unregister(), nua_publish(), nua_unpublish(), \n * nua_subscribe(), nua_unsubscribe(), nua_refer(), nua_notify(), \n * nua_options(), nua_message(), nua_method() * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * @par Values * - 0 (false) - process 305 as an ordinary final response * - 1 (true) - resend request via proxy received in 305 response * * Default value is NUTAG_AUTO305(1). * * Corresponding tag taking reference parameter is NUTAG_AUTO305_REF(). * * @NEW_1_12_11 */ tag_typedef_t nutag_auto305 = BOOLTAG_TYPEDEF(auto305); /**@def NUTAG_AUTO305_REF(x) * Reference tag for NUTAG_AUTO305(). */ /**@def NUTAG_AUTO100(x) * * Generate automatically 100 Trying responses. * * If this parameter is true, the server will automatically generate a * "100 Trying" response to the incoming INVITE request (and other * requests containing @Timestamp header). * * @par Used with * nua_create(), nua_set_params(), nua_set_hparams(), \n * nua_get_params(), nua_get_hparams(), \n * nua_invite(), nua_prack(), nua_ack(), nua_update(), nua_respond(), \n * nua_info(), nua_cancel(), nua_bye(), \n * nua_register(), nua_unregister(), nua_publish(), nua_unpublish(), \n * nua_subscribe(), nua_unsubscribe(), nua_refer(), nua_notify(), \n * nua_options(), nua_message(), nua_method() * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * @par Values * - 0 (false) - let application generate 100 Trying * - 1 (true) - automatically generate 100 Trying response * * Default value is NUTAG_AUTO100(1). * * Corresponding tag taking reference parameter is NUTAG_AUTO100_REF(). * * @NEW_UNRELEASED * * @sa NTATAG_EXTRA_100() */ tag_typedef_t nutag_auto100 = BOOLTAG_TYPEDEF(auto100); /**@def NUTAG_AUTO100_REF(x) * Reference tag for NUTAG_AUTO100(). */ /**@def NUTAG_MAX_RETRY_AFTER(x) * * This parameter specifies the maximum delay in seconds that stack * allows for @RetryAfter header when it considers if it should * automatically retry the request. * * If the delay specified by in @RetryAfter header is greater or equal * to this value, stack does no retry but considers the transaction * complete. * * The value 0 disables the automatic retry. * * @par Used with * nua_create(), nua_set_params() or nua_set_hparams() \n * nua_get_params() or nua_get_hparams() * nua_handle(), nua_invite(), nua_update(), nua_respond() \n * * See nua_set_hparams() for a complete list of all the nua operations that * accept this tag. * * @par Parameter type * unsigned int * * @par Value * Maximum @RetryAfter delay obeyed. * * Default value is NUTAG_MAX_RETRY_AFTER(32). * * Corresponding tag taking reference parameter is NUTAG_MAX_RETRY_AFTER_REF(). * * @NEW_UNRELEASED * * @sa @RetryAfter */ tag_typedef_t nutag_max_retry_after = UINTTAG_TYPEDEF(max_retry_after); /**@def NUTAG_MAX_RETRY_AFTER_REF(x) * Reference tag for NUTAG_MAX_RETRY_AFTER(). */ /**@def NUTAG_SMIME_ENABLE(x) * * Enable S/MIME * * @par Used with * nua_create() \n * nua_set_params() \n * nua_get_params() * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * @par Values * - 0 (false) - S/MIME is Disabled * - 1 (true) - S/MIME is Enabled * * Corresponding tag taking reference parameter is NUTAG_SMIME_ENABLE_REF(). */ tag_typedef_t nutag_smime_enable = BOOLTAG_TYPEDEF(smime_enable); /**@def NUTAG_SMIME_ENABLE_REF(x) * Reference tag for NUTAG_SMIME_ENABLE(). */ /**@def NUTAG_SMIME_OPT(x) * * S/MIME Options * * This tag specifies the type of S/MIME security services requested * by the user. * * @par Used with * nua_set_params() \n * nua_get_params() \n * nua_message() * * @par Parameter type * int * * @par Values * - -1 (SM_ID_NULL) No security service needed * - 0 (SM_ID_CLEAR_SIGN) Clear signing * - 1 (SM_ID_SIGN) S/MIME signing * - 2 (SM_ID_ENCRYPT) S/MIME encryption * * Corresponding tag taking reference parameter is NUTAG_SMIME_OPT_REF(). */ tag_typedef_t nutag_smime_opt = INTTAG_TYPEDEF(smime_opt); /**@def NUTAG_SMIME_OPT_REF(x) * Reference tag for NUTAG_SMIME_OPT(). */ /**@def NUTAG_SMIME_PROTECTION_MODE(x) * * S/MIME protection mode * * This tag specifies the protection mode of the SIP message by * S/MIME as requested by the user * * @par Used with * nua_set_params() \n * nua_get_params() * * @par Parameter type * unsigned int * * @par Values * - -1 (SM_MODE_NULL) Unspecified * - 0 (SM_MODE_PAYLOAD_ONLY) SIP payload only * - 1 (SM_MODE_TUNNEL) SIP tunneling mode * - 2 (SM_MODE_SIPFRAG) SIPfrag protection * * Corresponding tag taking reference parameter is NUTAG_SMIME_PROTECTION_MODE_REF(). */ tag_typedef_t nutag_smime_protection_mode = INTTAG_TYPEDEF(smime_protection_mode); /**@def NUTAG_SMIME_PROTECTION_MODE_REF(x) * Reference tag for NUTAG_SMIME_PROTECTION_MODE(). */ /**@def NUTAG_SMIME_MESSAGE_DIGEST(x) * * S/MIME digest algorithm * * This tag specifies the message digest algorithm to be used in S/MIME. * * @par Used with * To be implemented * * @par Parameter type * char const * * * @par Values * * Corresponding tag taking reference parameter is NUTAG_SMIME_MESSAGE_DIGEST_REF(). */ tag_typedef_t nutag_smime_message_digest = STRTAG_TYPEDEF(smime_message_digest); /**@def NUTAG_SMIME_MESSAGE_DIGEST_REF(x) * Reference tag for NUTAG_SMIME_MESSAGE_DIGEST(). */ /**@def NUTAG_SMIME_SIGNATURE(x) * * S/MIME signature algorithm * * This tag specifies the signature algorithm to be used in S/MIME. * * @par Used with * To be implemented. * * @par Parameter type * char const * * * @par Values * * Corresponding tag taking reference parameter is NUTAG_SMIME_SIGNATURE_REF(). */ tag_typedef_t nutag_smime_signature = STRTAG_TYPEDEF(smime_signature); /**@def NUTAG_SMIME_SIGNATURE_REF(x) * Reference tag for NUTAG_SMIME_SIGNATURE(). */ /**@def NUTAG_SMIME_KEY_ENCRYPTION(x) * * S/MIME key encryption algorithm * * This tag specifies the key encryption algorithm to be used by S/MIME. * * @par Used with * To be implemented * * @par Parameter type * char const * * * @par Values * * Corresponding tag taking reference parameter is NUTAG_SMIME_KEY_ENCRYPTION_REF(). */ tag_typedef_t nutag_smime_key_encryption = STRTAG_TYPEDEF(smime_key_encryption); /**@def NUTAG_SMIME_KEY_ENCRYPTION_REF(x) * Reference tag for NUTAG_SMIME_KEY_ENCRYPTION(). */ /**@def NUTAG_SMIME_MESSAGE_ENCRYPTION(x) * * S/MIME message encryption algorithm * * This tag specifies the message encryption algorithm to be used in S/MIME. * * @par Used with * To be implemented. * * @par Parameter type * char const * * * @par Values * * Corresponding tag taking reference parameter is NUTAG_SMIME_MESSAGE_ENCRYPTION_REF(). */ tag_typedef_t nutag_smime_message_encryption = STRTAG_TYPEDEF(smime_message_encryption); /**@def NUTAG_SMIME_MESSAGE_ENCRYPTION_REF(x) * Reference tag for NUTAG_SMIME_MESSAGE_ENCRYPTION(). */ /**@def NUTAG_SIPS_URL(x) * * Local SIPS url. * * The application can specify an alternative local address for * NUA user agent engine. Usually the alternative address is a * secure SIP URI (SIPS) used with TLS transport. * * @par Used with * nua_create() * * @par Parameter type * char const * * * @par Values * * Corresponding tag taking reference parameter is NUTAG_SIPS_URL_REF(). */ tag_typedef_t nutag_sips_url = URLTAG_TYPEDEF(sips_url); /**@def NUTAG_SIPS_URL_REF(x) * Reference tag for NUTAG_SIPS_URL(). */ /**@def NUTAG_CERTIFICATE_DIR(x) * * X.500 certificate directory * * @par Used with * nua_create() * * @par Parameter type * char const * * * @par Values * NULL terminated pathname of directory containing agent.pem and cafile.pem files. * * Corresponding tag taking reference parameter is NUTAG_CERTIFICATE_DIR_REF(). */ tag_typedef_t nutag_certificate_dir = STRTAG_TYPEDEF(certificate_dir); /**@def NUTAG_CERTIFICATE_DIR_REF(x) * Reference tag for NUTAG_CERTIFICATE_DIR(). */ /**@def NUTAG_CERTIFICATE_PHRASE(x) * * Certificate phrase * * @par Used with * Currently not processed by NUA * * @par Parameter type * char const * * * @par Values * * Corresponding tag taking reference parameter is NUTAG_CERTIFICATE_PHRASE_REF(). */ tag_typedef_t nutag_certificate_phrase = STRTAG_TYPEDEF(certificate_phrase); /**@def NUTAG_CERTIFICATE_PHRASE_REF(x) * Reference tag for NUTAG_CERTIFICATE_PHRASE(). */ extern msg_hclass_t sip_route_class[]; /**@def NUTAG_INITIAL_ROUTE(x) * * Specify initial route set. * * The initial route set is used instead or or in addition to the outbound * proxy URL given by NUTAG_PROXY(). The NUTAG_INITIAL_ROUTE() accepts a * list of parsed @Route header structures, NUTAG_INITIAL_ROUTE_STR() an * unparsed string. * * If a tag list contains multiple NUTAG_INITIAL_ROUTE() or * NUTAG_INITIAL_ROUTE_STR() tags, the route set is constructed from them * all. * * The initial route is inserted into request message before the route * entries set with SIPTAG_ROUTE() or SIPTAG_ROUTE_STR(). * * @par Used with * nua_set_params() \n * nua_set_hparams() \n * any handle-specific nua call * * @par Parameter type * sip_route_t const * * * @par Values * Linked list of #sip_route_t structures * * Corresponding tag taking reference parameter is NUTAG_INITIAL_ROUTE_REF(). * * @NEW_1_12_7. */ tag_typedef_t nutag_initial_route = SIPEXTHDRTAG_TYPEDEF(initial_route, route); /**@def NUTAG_INITIAL_ROUTE_REF(x) * Reference tag for NUTAG_INITIAL_ROUTE(). */ /**@def NUTAG_INITIAL_ROUTE_STR(x) * * Specify initial route set. * * The initial route set is used instead or or in addition to the outbound * proxy URL given by NUTAG_PROXY(). The NUTAG_INITIAL_ROUTE() accepts a * list of parsed @Route header structures, NUTAG_INITIAL_ROUTE_STR() a * unparsed string containing route URIs, quoted with <> and separated by * commas. * * Please note that the syntax requires <> around the @Route URIs if they * contain parameters, e.g., "lr". * * If a tag list contains multiple NUTAG_INITIAL_ROUTE() or * NUTAG_INITIAL_ROUTE_STR() tags, the route set is constructed from them * all. * * The initial route set can be reset with NUTAG_INITIAL_ROUTE(NULL). * * If a tag list of a request contains SIPTAG_ROUTE() or * SIPTAG_ROUTE_STR() tags, the resulting route set will contain first the * initial route entries followed by the route URIs given with the * SIPTAG_ROUTE()/SIPTAG_ROUTE_STR() tags. * * @par Used with * nua_set_params() \n * nua_set_hparams() \n * any handle-specific nua call * * @par Parameter type * sip_route_t const * * * @par Values * Linked list of #sip_route_t structures * * Corresponding tag taking reference parameter is NUTAG_INITIAL_ROUTE_STR_REF(). * * @NEW_1_12_7. */ tag_typedef_t nutag_initial_route_str = STRTAG_TYPEDEF(inital_route_str); /**@def NUTAG_INITIAL_ROUTE_STR_REF(x) * Reference tag for NUTAG_INITIAL_ROUTE_STR(). */ /**@def NUTAG_REGISTRAR(x) * * Registrar URL * * @par Used with * nua_register() \n * nua_set_params() \n * nua_get_params() * * @par Parameter type * url_string_t const * (either char const * or url_t *) * * @par Values * * Corresponding tag taking reference parameter is NUTAG_REGISTRAR_REF(). */ tag_typedef_t nutag_registrar = URLTAG_TYPEDEF(registrar); /**@def NUTAG_REGISTRAR_REF(x) * Reference tag for NUTAG_REGISTRAR(). */ /**@def NUTAG_IDENTITY(x) * * Registration handle (used with requests and nua_respond()) (NOT YET IMPLEMENTED) * * When a new request is made or new call is responded, a new identity can * be selected with NUTAG_IDENTITY(). The identity comprises of @b From * header, initial route set, local contact header and media tags associated * with it, soa handle and so on. User can make multiple registrations using * multiple identities. * * @par Used with * nua_invite() * * @par Parameter type * nua_handle_t * * * @par Values * * Corresponding tag taking reference parameter is NUTAG_IDENTITY_REF(). */ tag_typedef_t nutag_identity = PTRTAG_TYPEDEF(identity); /**@def NUTAG_IDENTITY_REF(x) * Reference tag for NUTAG_IDENTITY(). */ /**@def NUTAG_M_DISPLAY(x) * * Display name for @Contact. * * Specify display name for the Contact header URI generated for * registration request and dialog-creating requests/responses. * * Note that the display name is not included the request-URI when proxy * forwards the request towards the user-agent. * * @par Used with * nua_register(), nua_set_hparams(), nua_set_params(). * nua_invite(), nua_respond(), nua_subscribe(), nua_notify() * * @par Parameter type * string (char *) * * @par Values * Valid display name. * * @sa NUTAG_M_USERNAME(), NUTAG_M_PARAMS(), NUTAG_M_FEATURES(), * NUTAG_CALLEE_CAPS(). * * Corresponding tag taking reference parameter is NUTAG_M_DISPLAY_REF(). * * @since New in @VERSION_1_12_2. */ tag_typedef_t nutag_m_display = STRTAG_TYPEDEF(m_display); /**@def NUTAG_M_DISPLAY_REF(x) * Reference tag for NUTAG_M_DISPLAY(). */ /**@def NUTAG_M_USERNAME(x) * * Username prefix for @Contact. * * Specify username part for the Contact header URI generated for * registration request and dialog-creating requests/responses. * * Using username, application can make multiple registrations using * multiple identities, or it can distinguish between different logical * destinations. * * @par Used with * nua_register(), nua_set_hparams(), nua_set_params(). * nua_invite(), nua_respond(), nua_subscribe(), nua_notify() * * @par Parameter type * string (char *) * * @par Values * Valid SIP username. * * @sa NUTAG_M_DISPLAY(), NUTAG_M_PARAMS(), NUTAG_M_FEATURES(), * NUTAG_CALLEE_CAPS(). * * Corresponding tag taking reference parameter is NUTAG_M_USERNAME_REF(). * * @since New in @VERSION_1_12_2. */ tag_typedef_t nutag_m_username = STRTAG_TYPEDEF(m_username); /**@def NUTAG_M_USERNAME_REF(x) * Reference tag for NUTAG_M_USERNAME(). */ /**@def NUTAG_M_PARAMS(x) * * URL parameters for @Contact. * * Specify URL parameters for the @Contact header URI generated for * registration request and dialog-creating requests/responses. * * Please note that some proxies may remove even the non-transport * parameters from the request-URI when they forward the request towards * user-agent. * * @par Used with * nua_register(), nua_set_hparams(), nua_set_params(), * nua_invite(), nua_respond(), nua_subscribe(), nua_notify() * * @par Parameter type * string (char *) * * @par Values * Semicolon-separated URL parameters. * * @sa NUTAG_M_DISPLAY(), NUTAG_M_USERNAME(), NUTAG_M_FEATURES(), * NUTAG_CALLEE_CAPS(). * * Corresponding tag taking reference parameter is NUTAG_M_PARAMS_REF(). * * @since New in @VERSION_1_12_2. */ tag_typedef_t nutag_m_params = STRTAG_TYPEDEF(m_params); /**@def NUTAG_M_PARAMS_REF(x) * Reference tag for NUTAG_M_PARAMS(). */ /**@def NUTAG_M_FEATURES(x) * * Header parameters for @Contact used in registration. * * Specify header parameters for the @Contact header generated for * registration request and dialog-creating requests/responses. Such header * parameters include "q", indicating preference for the @Contact URI, and * "expires", indicating the desired expiration time for the registration. * * Additional header parameters are typically media feature tags, specified in * @RFC3840. If NUTAG_CALLEE_CAPS(1) is specified, additional @Contact header * parameters are generated based on SDP capabilities and SIP @Allow header. * * When using the "outbound" extension option, the stack will also add * "+sip.instance" and "reg-id" header parameters to the @Contact. * * @par Used with * nua_register(), nua_set_hparams(), nua_set_params() * * @par Parameter type * string (char *) * * @par Values * Semicolon-separated SIP header parameters. * * @sa NUTAG_M_DISPLAY(), NUTAG_M_USERNAME(), NUTAG_M_PARAMS(), * NUTAG_CALLEE_CAPS(), NUTAG_IDENTITY(). * * Corresponding tag taking reference parameter is NUTAG_M_FEATURES_REF(). * * @since New in @VERSION_1_12_2. */ tag_typedef_t nutag_m_features = STRTAG_TYPEDEF(m_features); /**@def NUTAG_M_FEATURES_REF(x) * Reference tag for NUTAG_M_FEATURES(). */ /**@def NUTAG_INSTANCE(x) * * Intance identifier. * * @par Used with * nua_create(), nua_set_params(), nua_get_params(), * nua_register() * * @par Parameter type * char const * * * @par Value * urn:uuid string, a globally unique identifier for this user-agent * instance. * * Corresponding tag taking reference parameter is NUTAG_INSTANCE_REF(). */ tag_typedef_t nutag_instance = STRTAG_TYPEDEF(instance); /**@def NUTAG_INSTANCE_REF(x) * Reference tag for NUTAG_INSTANCE(). */ /**@def NUTAG_OUTBOUND(x) * * Outbound option string. * * The outbound option string can specify how the NAT traversal is handled. * The option tokens are as follows: * - "gruuize": try to generate a GRUU contact from REGISTER response * - "outbound": use SIP outbound extension (off by default) * - "validate": validate registration behind a NAT by sending OPTIONS to self * - "natify": try to traverse NAT * - "use-rport": use rport to traverse NAT * - "options-keepalive": send periodic OPTIONS requests as keepalive messages * * An option token with "no-" or "not-" prefix turns the option off. For * example, if you want to try to traverse NATs but not to use OPTIONS * keepalive, use NUTAG_OUTBOUND("natify no-options-keepalive"). * * An empty string can be passed to let the stack choose the * default values for outbound usage (in the 1.12.10 release, the * defaults are: "gruuize no-outbound validate use-rport options-keepalive"). * * @note * Options string is used so that no new tags need to be added when the * outbound functionality changes. * * @par Used with * nua_register() \n * nua_set_params() \n * nua_get_params() \n * nua_set_hparams() \n * nua_get_hparams() * * @par Parameter type * char const * * * @par Values * * Corresponding tag taking reference parameter is NUTAG_OUTBOUND_REF(). */ tag_typedef_t nutag_outbound = STRTAG_TYPEDEF(outbound); /**@def NUTAG_OUTBOUND_REF(x) * Reference tag for NUTAG_OUTBOUND(). */ /*#@def NUTAG_OUTBOUND_SET1(x) * * Outbound proxy set 1. * * @par Used with * nua_register() \n * nua_set_params() \n * nua_get_params() \n * nua_set_hparams() \n * nua_get_hparams() * * @par Parameter type * char const * * * @par Values * * Corresponding tag taking reference parameter is NUTAG_OUTBOUND_SET1_REF(). */ tag_typedef_t nutag_outbound_set1 = STRTAG_TYPEDEF(outbound_set1); /*#@def NUTAG_OUTBOUND_SET1_REF(x) * Reference tag for NUTAG_OUTBOUND_SET1(). */ /*#@def NUTAG_OUTBOUND_SET2(x) * * Outbound proxy set 2. * * @par Used with * nua_register() \n * nua_set_params() \n * nua_get_params() \n * nua_set_hparams() \n * nua_get_hparams() * * @par Parameter type * char const * * * @par Values * * Corresponding tag taking reference parameter is NUTAG_OUTBOUND_SET2_REF(). */ tag_typedef_t nutag_outbound_set2 = STRTAG_TYPEDEF(outbound_set2); /*#@def NUTAG_OUTBOUND_SET2_REF(x) * Reference tag for NUTAG_OUTBOUND_SET2(). */ /*#@def NUTAG_OUTBOUND_SET3(x) * * Outbound proxy set 3. * * @par Used with * nua_register() \n * nua_set_params() \n * nua_get_params() \n * nua_set_hparams() \n * nua_get_hparams() * * @par Parameter type * char const * * * @par Values * * Corresponding tag taking reference parameter is NUTAG_OUTBOUND_SET3_REF(). */ tag_typedef_t nutag_outbound_set3 = STRTAG_TYPEDEF(outbound_set3); /*#@def NUTAG_OUTBOUND_SET3_REF(x) * Reference tag for NUTAG_OUTBOUND_SET3(). */ /*#@def NUTAG_OUTBOUND_SET4(x) * * Outbound proxy set 4. * * @par Used with * nua_register() \n * nua_set_params() \n * nua_get_params() \n * nua_set_hparams() \n * nua_get_hparams() * * @par Parameter type * char const * * * @par Values * * Corresponding tag taking reference parameter is NUTAG_OUTBOUND_SET4_REF(). */ tag_typedef_t nutag_outbound_set4 = STRTAG_TYPEDEF(outbound_set4); /*#@def NUTAG_OUTBOUND_SET4_REF(x) * Reference tag for NUTAG_OUTBOUND_SET4(). */ /**@def NUTAG_KEEPALIVE(x) * * Keepalive interval in milliseconds. * * This setting applies to OPTIONS/STUN keepalives. See documentation * for nua_register() for more detailed information. * * @par Used with * nua_register() \n * nua_set_params() \n * nua_get_params() \n * nua_set_hparams() \n * nua_get_hparams() * * @par Parameter type * unsigned int * * @par Values * - 0 - disable keepalives * - 120000 - default value (120000 milliseconds, 120 seconds) * * Corresponding tag taking reference parameter is * NUTAG_KEEPALIVE_REF(). */ tag_typedef_t nutag_keepalive = UINTTAG_TYPEDEF(keepalive); /**@def NUTAG_KEEPALIVE_REF(x) * Reference tag for NUTAG_KEEPALIVE(). */ /**@def NUTAG_KEEPALIVE_STREAM(x) * * Transport-level keepalive interval for streams. * * See documentation for nua_register() for more detailed information. * * @par Used with * nua_register() \n * nua_set_params() \n * nua_get_params() \n * nua_set_hparams() \n * nua_get_hparams() * * @par Parameter type * unsigned int * * @par Values * * Transport-level keepalive interval for streams in milliseconds. If this * parameter specified, it takes presedence over value given in * NUTAG_KEEPALIVE(). * * Corresponding tag taking reference parameter is * NUTAG_KEEPALIVE_STREAM_REF(). * * @todo Actually pass NUTAG_KEEPALIVE_STREAM() to transport layer. */ tag_typedef_t nutag_keepalive_stream = UINTTAG_TYPEDEF(keepalive_stream); /**@def NUTAG_KEEPALIVE_STREAM_REF(x) * Reference tag for NUTAG_KEEPALIVE_STREAM(). */ /**@def NUTAG_USE_DIALOG(x) * * Ask NUA to create dialog for this handle * * @par Used with nua calls that send a SIP request * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * @par Values * - 0 (false) - do not create a dialog * - 1 (true) - store dialog info * * Corresponding tag taking reference parameter is NUTAG_USE_DIALOG_REF(). */ tag_typedef_t nutag_use_dialog = BOOLTAG_TYPEDEF(use_dialog); /**@def NUTAG_USE_DIALOG_REF(x) * Reference tag for NUTAG_USE_DIALOG(). */ /**@def NUTAG_AUTH(x) * * Authentication data ("scheme" "realm" "user" "password") * * @par Used with * nua_authenticate() * * @par Parameter type * char const * * * @par Values * NULL terminated string of format: \n * basic digest scheme:"realm":user:password \n * @b NOTE the double quotes around realm! * For example: \n * \code Digest:"nokia proxy":xyz:secret \endcode * * Corresponding tag taking reference parameter is NUTAG_AUTH_REF(). */ tag_typedef_t nutag_auth = STRTAG_TYPEDEF(auth); /**@def NUTAG_AUTH_REF(x) * Reference tag for NUTAG_AUTH(). */ /**@def NUTAG_AUTHTIME(x) * * Lifetime of authentication data in seconds. * * @par Used with * Currently not processed by NUA * * @par Parameter type * unsigned int * * @par Values * - 0 (zero) - Use authentication data only for this handle * - nonzero - Lifetime of authentication data in seconds * * Corresponding tag taking reference parameter is NUTAG_AUTHTIME_REF(). */ tag_typedef_t nutag_authtime = INTTAG_TYPEDEF(authtime); /**@def NUTAG_AUTHTIME_REF(x) * Reference tag for NUTAG_AUTHTIME(). */ /**@def NUTAG_EVENT(x) * * NUA event. * * @deprecated * * @par Parameter type * enum nua_event_e * * @par Values * * Corresponding tag taking reference parameter is NUTAG_EVENT_REF(). */ tag_typedef_t nutag_event = INTTAG_TYPEDEF(event); /**@def NUTAG_EVENT_REF(x) * Reference tag for NUTAG_EVENT(). */ /**@def NUTAG_STATUS(x) * * Response status code * * @deprecated * * @par Parameter type * unsigned int * * @par Values * - 100 - preliminary response, request is being processed by next hop * - 1XX - preliminary response, request is being processed by UAS * - 2XX - successful final response * - 3XX - redirection error response * - 4XX - client error response * - 5XX - server error response * - 6XX - global error response * * Corresponding tag taking reference parameter is NUTAG_STATUS_REF(). */ tag_typedef_t nutag_status = INTTAG_TYPEDEF(status); /**@def NUTAG_STATUS_REF(x) * Reference tag for NUTAG_STATUS(). */ /**@def NUTAG_PHRASE(x) * * Response phrase * * @deprecated * * @par Parameter type * char const * * * @par Values. * * Corresponding tag taking reference parameter is NUTAG_PHRASE_REF(). */ tag_typedef_t nutag_phrase = STRTAG_TYPEDEF(phrase); /**@def NUTAG_PHRASE_REF(x) * Reference tag for NUTAG_PHRASE(). */ /**@def NUTAG_HANDLE(x) * * NUA Handle * * @deprecated * * @par Parameter type * nua_handle_t * * * @par Values * * Corresponding tag taking reference parameter is NUTAG_HANDLE_REF(). */ tag_typedef_t nutag_handle = PTRTAG_TYPEDEF(handle); /**@def NUTAG_HANDLE_REF(x) * Reference tag for NUTAG_HANDLE(). */ /**@def NUTAG_NOTIFY_REFER(x) * * Refer reply handle (used with refer) * * When making a call in response to a REFER request [RFC3515] with * nua_invite(), the application can ask NUA to automatically generate * notifications about the call progress to the referrer. In order to * do that the application should pass to the stack the handle, which * it used to receive the REFER request. It should also pass the event * header object along with the handle using NUTAG_REFER_EVENT(). * * @par Used with * nua_invite() * * @par Parameter type * nua_handle_t * * * @par Values * * Corresponding tag taking reference parameter is NUTAG_NOTIFY_REFER_REF(). */ tag_typedef_t nutag_notify_refer = PTRTAG_TYPEDEF(notify_refer); /**@def NUTAG_NOTIFY_REFER_REF(x) * Reference tag for NUTAG_NOTIFY_REFER(). */ /**@def NUTAG_REFER_EVENT(x) * * Event used with automatic refer notifications. * * When creating a call in response to a REFER request [RFC3515] * the application can ask NUA to automatically generate notifications * about the call progress to the referrer. The #nua_i_refer event will * contain a suitable SIP event header for the notifications in the * NUTAG_REFER_EVENT() tag. The application should store the SIP event * header and when it makes the referred call, it should pass it back * to the stack again using the NUTAG_REFER_EVENT() tag. * * @par Used with * * @par Parameter type * sip_event_t * * * @par Values * * Corresponding tag taking reference parameter is NUTAG_REFER_EVENT_REF(). */ tag_typedef_t nutag_refer_event = SIPHDRTAG_NAMED_TYPEDEF(refer_event, event); /**@def NUTAG_REFER_EVENT_REF(x) * Reference tag for NUTAG_REFER_EVENT(). */ /**@def NUTAG_REFER_PAUSE() * * Invite pauses referrer's handle. * * When creating a call in response to a REFER [RFC3515] request, * the application can ask that the original call will be muted * when the new call is connected by specifying NUTAG_REFER_PAUSE() * along with NUTAG_NOTIFY_REFER() as a parameter to nua_invite() call. * * @par Used with * nua_invite() * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * @par Values * - 0 (false) - do not pause referring call * - 1 (true) - pause referring call * * Corresponding tag taking reference parameter is NUTAG_REFER_PAUSE_REF(). * * @deprecated Not implemented. */ tag_typedef_t nutag_refer_pause = BOOLTAG_TYPEDEF(refer_pause); /**@def NUTAG_REFER_PAUSE_REF(x) * Reference tag for NUTAG_REFER_PAUSE(). */ /**@def NUTAG_USER_AGENT() * * User-Agent string. * * Indicate the User-Agent header used by the stack. The value set with this * tag is concatenated with the value indicating the stack name and version, * e.g., "sofia-sip/1.12.1" unless the stack name "sofia-sip" followed by * slash is already included in the string. The concatenated value is * returned in SIPTAG_USER_AGENT_STR() and NUTAG_USER_AGENT() when * nua_get_params() is called. * * If you want to set the complete string, use SIPTAG_USER_AGENT_STR() or * SIPTAG_USER_AGENT(). * * @par Used with * nua_set_params(), nua_set_hparams() \n * nua_get_params(), nua_get_hparams(), #nua_r_get_params \n * any handle-specific nua call * * @par Parameter type * char const * * * @par Values * See @RFC3261 \n * If NULL, stack uses default string which of format "sofia-sip/1.12". * * Corresponding tag taking reference parameter is NUTAG_USER_AGENT_REF(). */ tag_typedef_t nutag_user_agent = STRTAG_TYPEDEF(user_agent); /**@def NUTAG_USER_AGENT_REF(x) * Reference tag for NUTAG_USER_AGENT(). */ /**@def NUTAG_ALLOW() * * Allow a method (or methods). * * This tag is used to add a new method to the already existing set of * allowed methods. If you want to ignore the existing set of allowed * methods, use SIPTAG_ALLOW_STR() or SIPTAG_ALLOW(). * * The set of allowed methods is added to the @Allow header in the response * or request messages. For incoming request, an error response 405 * Method Not Allowed is automatically returned if the incoming method * is not included in the set. * * @par Used with * nua_set_params() \n * nua_set_hparams() \n * any handle-specific nua call * * @par Parameter type * char const * * * @par Values * Valid method name, or comma-separated list of them. * * Corresponding tag taking reference parameter is NUTAG_ALLOW_REF(). */ tag_typedef_t nutag_allow = STRTAG_TYPEDEF(allow); /**@def NUTAG_ALLOW_REF(x) * Reference tag for NUTAG_ALLOW(). */ /**@def NUTAG_ALLOW_EVENTS() * * Allow an event or events. * * This tag is used to add a new event to the already existing set of * allowed events. If you want to ignore the existing set of allowed events, * set the allowed event set with SIPTAG_ALLOW_EVENTS_STR() or * SIPTAG_ALLOW_EVENTS(). * * The set of allowed methods is added to the @AllowEvents header in the * response to the SUBSCRIBE or PUBLISH requests. For incoming SUBSCRIBE or * PUBLISH request, an error response 489 Bad Event is automatically * returned if the incoming method is not included in the set. * * @par Used with * nua_set_params() \n * nua_set_hparams() \n * any handle-specific nua call * * @par Parameter type * char const * * * @par Values * Valid event name, or comma-separated list of them. * * @sa @AllowEvents, @RFC3265, @RFC3903, #nua_i_subscribe, #nua_i_publish, * #nua_i_refer, nua_notify(), nua_refer(), * nua_subscribe(), nua_publish(), SIPTAG_ALLOW_EVENTS(), * SIPTAG_ALLOW_EVENTS_STR(), NUTAG_APPL_EVENT() * * @NEW_1_12_4. * * Corresponding tag taking reference parameter is NUTAG_ALLOW_EVENTS_REF(). */ tag_typedef_t nutag_allow_events = STRTAG_TYPEDEF(allow_events); /**@def NUTAG_ALLOW_EVENTS_REF(x) * Reference tag for NUTAG_ALLOW_EVENTS(). */ /**@def NUTAG_APPL_EVENT() * * List events which the application handles always. * * When nua stack receives a SUBSCRIBE request for an already existing * subscription, it can either automatically refresh the subscription * or, if the event name is listed in NUTAG_APPL_EVENT() list, it * is passed to application, pass the SUBSCRIBE request to application. * * The list of application events is cleared with * NUTAG_APPL_EVENT(NULL). * * @par Used with * nua_set_params() \n * nua_set_hparams() \n * any handle-specific nua call * * @par Parameter type * char const * * * @par Values * Valid event name, or comma-separated list of them. * * @sa @AllowEvents, @RFC3265, @RFC3903, #nua_i_subscribe, * #nua_i_publish, #nua_i_refer, nua_notify(), nua_refer(), * nua_subscribe(), nua_publish(), NUTAG_ALLOW_EVENTS(), * * @NEW_UNRELEASED * * Corresponding tag taking reference parameter is * NUTAG_APPL_EVENT_REF(). */ tag_typedef_t nutag_appl_event = STRTAG_TYPEDEF(appl_event); /**@def NUTAG_APPL_EVENT_REF(x) * Reference tag for NUTAG_APPL_EVENT(). */ /**@def NUTAG_APPL_METHOD() * * Indicate that a method (or methods) are handled by application. * * This tag is used to add a new method to the already existing set of * methods handled by application, or clear the set. If you want to * determine the set explicitly, include NUTAG_APPL_METHOD() twice, * first with NULL and then with your supported set. * * The default set of application methods now include INVITE, REGISTER, * PUBLISH and SUBSCRIBE. * * If the request method is in the set of methods handled by application, * the nua stack does not automatically respond to the incoming request nor * it will automatically send such a request. Note if the application adds * the PRACK and UPDATE requests to the set of application methods it must * also take care for sending the PRACK and UPDATE requests during the call * setup when necessary. * * @par Used with * nua_set_params() \n * nua_set_hparams() \n * any handle-specific nua call * * @par Parameter type * char const * * * @par Values * Valid method name, or comma-separated list of them. * * Corresponding tag taking reference parameter is NUTAG_APPL_METHOD_REF(). * * @since Working since @VERSION_1_12_5. Handling of client-side PRACK and * UPDATE was fixed in @VERSION_1_12_6. */ tag_typedef_t nutag_appl_method = STRTAG_TYPEDEF(appl_method); /**@def NUTAG_APPL_METHOD_REF(x) * Reference tag for NUTAG_APPL_METHOD(). */ /**@def NUTAG_SUPPORTED() * * Support a feature. * * This tag is used to add a new feature to the existing set of supported * SIP features. If you want to ignore the existing set of supported * features, use SIPTAG_SUPPORTED_STR() or SIPTAG_SUPPORTED(). * * The set of supported features is added to the @Supported header in the * response or request messages. For incoming requests, an error response * 420 Bad Extension is automatically returned if the request * requires features that are not included in the supported feature set. * * @par Used with * nua_set_params() \n * nua_set_hparams() \n * any handle-specific nua call * * @par Parameter type * char const * * * @par Values * Feature name, or comma-separated list of them. * * Corresponding tag taking reference parameter is NUTAG_SUPPORTED_REF(). * * @since New in @VERSION_1_12_2. */ tag_typedef_t nutag_supported = STRTAG_TYPEDEF(supported); /**@def NUTAG_SUPPORTED_REF(x) * Reference tag for NUTAG_SUPPORTED(). */ /**@def NUTAG_PATH_ENABLE(x) * * If true, add "path" to @Supported in REGISTER. * * @par Used with * - nua_create(), nua_set_params(), nua_get_params() * - nua_handle(), nua_set_hparams(), nua_get_hparams() * - nua_register() * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * @par Values * - 0 (false) - Do not include "path" to @Supported header * - 1 (true) - Include "path" to @Supported header * * @sa NUTAG_SERVICE_ROUTE_ENABLE(), NUTAG_SUPPORTED(), * NUTAG_INITIAL_ROUTE(), NUTAG_INITIAL_ROUTE_STR(), @RFC3327 * "SIP Extension Header Field for Registering Non-Adjacent Contacts", * D. Willis, B. Hoeneisen, * December 2002. */ tag_typedef_t nutag_path_enable = BOOLTAG_TYPEDEF(path_enable); /**@def NUTAG_PATH_ENABLE_REF(x) * Reference tag for NUTAG_PATH_ENABLE(). */ /**@def NUTAG_SERVICE_ROUTE_ENABLE(x) * * Use route taken from the @ServiceRoute header in the 200 class response * to REGISTER. * * @par Used with * - nua_create(), nua_set_params(), nua_get_params() * - nua_handle(), nua_set_hparams(), nua_get_hparams() * - nua_register() * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * @par Values * - 0 (false) - Do not use @ServiceRoute * - 1 (true) - Use @ServiceRoute * * Corresponding tag taking reference parameter is NUTAG_SERVICE_ROUTE_ENABLE_REF(). * * @sa NUTAG_INITIAL_ROUTE(), NUTAG_INITIAL_ROUTE_STR(), @RFC3608 */ tag_typedef_t nutag_service_route_enable = BOOLTAG_TYPEDEF(service_route_enable); /**@def NUTAG_SERVICE_ROUTE_ENABLE_REF(x) * Reference tag for NUTAG_SERVICE_ROUTE_ENABLE(). */ /**@def NUTAG_AUTH_CACHE(x) * * Authentication caching policy * * @par Used with * nua_set_params(), nua_set_hparams() \n * nua_get_params(), nua_get_hparams() \n * @NUA_HPARAM_CALLS * * @par Parameter type * enum nua_auth_cache * * @par Values * - nua_auth_cache_dialog (0) - include credentials within dialog * - nua_auth_cache_challenged (1) - include credentials only when * challenged * * Corresponding tag taking reference parameter is NUTAG_AUTH_CACHE_REF(). * * @NEW_1_12_6. */ tag_typedef_t nutag_auth_cache = INTTAG_TYPEDEF(auth_cache); /**@def NUTAG_AUTH_CACHE_REF(x) * Reference tag for NUTAG_AUTH_CACHE(). */ /**@def NUTAG_DETECT_NETWORK_UPDATES(x) * * Enable detection of local IP address updates. * * @par Used with * nua_create() \n * nua_set_params() \n * nua_get_params() * * @par Parameter type * int (enum nua_nw_detector_e aka #nua_nw_detector_t) * * @sa #nua_i_network_changed, #nua_nw_detector_t * * Corresponding tag taking reference parameter is * NUTAG_DETECT_NETWORK_UPDATES_REF(). * * @since New in @VERSION_1_12_2. */ tag_typedef_t nutag_detect_network_updates = UINTTAG_TYPEDEF(detect_network_updates); /**@def NUTAG_DETECT_NETWORK_UPDATES_REF(x) * Reference tag for NUTAG_DETECT_NETWORK_UPDATES(). */ /**@def NUTAG_WITH_THIS(nua) * * Specify request to respond to. * * @par Used with * nua_respond() * * @par Parameter type * nua_t * * * @par Values * Pointer to the nua agent instance object. * * @NEW_1_12_4. * * @sa NUTAG_WITH(), NUTAG_WITH_SAVED() */ /**@def NUTAG_WITH(msg) * * Specify request to respond to. * * @par Used with * nua_respond() * * @par Parameter type * msg_t * * * @par Values * Pointer to a request message. * * @NEW_1_12_4. * * @sa nua_save_event(), NUTAG_WITH_THIS(), NUTAG_WITH_SAVED() */ /**@def NUTAG_WITH_SAVED(event) * * Specify request to respond to. * * @par Used with * nua_respond() * * @par Parameter type * nua_saved_event_t * * * @par Values * Pointer to a saved event. * * @NEW_1_12_4. * * @sa nua_save_event(), NUTAG_WITH(), NUTAG_WITH_THIS() */ tag_typedef_t nutag_with = PTRTAG_TYPEDEF(with); /**@def NUTAG_DIALOG(x) * * An (extension) method is used to create dialog or refresh target. * * @par Used with * nua_method() * * @par Parameter type * unsigned int (0, 1, 2) * * @par Values * - 0 if dialog target is not refreshed * - 1 if dialog target is refreshed * - > 1 if dialog is to be created * * @NEW_1_12_6. * * @sa nua_method(), #nua_i_method */ tag_typedef_t nutag_dialog = UINTTAG_TYPEDEF(dialog); /**@def NUTAG_PROXY(x) * * Outbound proxy URL. * * Same tag as NTATAG_DEFAULT_PROXY() * * @par Used with * nua_set_params() \n * nua_get_params() \n * nua_create() * @note * Since @VERSION_1_12_9, NUTAG_PROXY()/NTATAG_DEFAULT_PROXY() can be used * to set handle-specific outbound route. The route is set with \n * nua_set_hparams(), \n * nua_invite(), nua_prack(), nua_ack(), nua_update(), nua_respond(), \n * nua_info(), nua_cancel(), nua_bye(), \n * nua_register(), nua_unregister(), nua_publish(), nua_unpublish(), \n * nua_subscribe(), nua_unsubscribe(), nua_refer(), nua_notify(), \n * nua_options(), nua_message(), nua_method() * * @par Parameter type * url_string_t const * (either char const * or url_t *) * * @par Values * NULL implies routing based on request-URI or Route header. * Non-NULL is used as invisible routing URI, ie., routing URI that is * not included in the request. * * Corresponding tag taking reference parameter is NUTAG_PROXY_REF(). */ /**@def NUTAG_PROXY_REF(x) * Reference tag for NUTAG_PROXY(). */ /**@def NUTAG_SIP_PARSER(x) * * Pointer to a customized SIP parser used with NUA. * * @par Used with * nua_create() * * @par Parameter type * msg_mclass_t const * * * @par Values * Pointer to an extended SIP parser. * * @sa msg_mclass_clone(), msg_mclass_insert_header() * * Corresponding tag taking reference parameter is NUTAG_SIP_PARSER_REF(). */ /**@def NUTAG_SIP_PARSER_REF(x) * Reference tag for NUTAG_SIP_PARSER(). */ /**@def NUTAG_SHUTDOWN_EVENTS(x) * * Allow passing of normal events when stack is being shut down. * * By default, only #nua_r_shutdown events are passed to application after * calling nua_shutdown(). If application is interested in nua events during * shutdown, it should give NUTAG_SHUTDOWN_EVENTS(1) to nua_create() or * nua_set_params() called before nua_shutdown(). * * @par Used with * nua_create(), nua_set_params(). * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * @par Values * - 0 (false) - pass only #nua_r_shutdown events during shutdown * - 1 (true) - pass all events to application during shutdown * * Corresponding tag taking reference parameter is NUTAG_SHUTDOWN_EVENTS_REF(). * * @sa nua_shutdown(), nua_destroy(). * * @NEW_1_12_9. */ tag_typedef_t nutag_shutdown_events = BOOLTAG_TYPEDEF(shutdown_events); /**@def NUTAG_SHUTDOWN_EVENTS_REF(x) * Reference tag for NUTAG_SHUTDOWN_EVENTS(). */ /**@def NUTAG_DEFERRABLE_TIMERS(x) * * Use deferrable timers in NUA. * * @par Used with * nua_create() * * @par Parameter type * int (boolean: nonzero is true, zero is false) * * @par Values * - 0 (false) - do not use deferrable timers (default) * - 1 (true) - use deferrable timers * * Corresponding tag taking reference parameter is * NUTAG_DEFERRABLE_TIMERS_REF(). * * @sa su_timer_deferrable(), su_root_set_max_defer() * * @NEW_UNRELEASED */ tag_typedef_t nutag_deferrable_timers = BOOLTAG_TYPEDEF(deferrable_timers); /**@def NUTAG_DEFERRABLE_TIMERS_REF(x) * Reference tag for NUTAG_DEFERRABLE_TIMERS(). */ /* ---------------------------------------------------------------------- */ tag_typedef_t nutag_soa_session = PTRTAG_TYPEDEF(soa_session); tag_typedef_t nutag_hold = BOOLTAG_TYPEDEF(hold); tag_typedef_t nutag_address = STRTAG_TYPEDEF(address); sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/nua_types.h000066400000000000000000000033331223300710500225170ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2008 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef NUA_TYPES_H /** Defined when has been included. */ #define NUA_TYPES_H /**@internal @file nua_types.h * @brief Internal types for nua. * * @author Pekka Pessi */ typedef struct nua_handle_preferences nua_handle_preferences_t; typedef struct nua_global_preferences nua_global_preferences_t; #ifndef NUA_OWNER_T #define NUA_OWNER_T struct nua_owner_s #endif typedef NUA_OWNER_T nua_owner_t; typedef struct nua_dialog_state nua_dialog_state_t; typedef struct nua_dialog_usage nua_dialog_usage_t; typedef struct nua_server_request nua_server_request_t; typedef struct nua_client_request nua_client_request_t; typedef struct nua_dialog_peer_info nua_dialog_peer_info_t; #ifndef NUA_SAVED_SIGNAL_T #define NUA_SAVED_SIGNAL_T struct nua_saved_signal * #endif typedef NUA_SAVED_SIGNAL_T nua_saved_signal_t; #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/outbound.c000066400000000000000000001066651223300710500223560ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE outbound.c * @brief Implementation of SIP NAT traversal and outbound * * @author Pekka Pessi * @author Kai Vehmanen * @author Martti Mela * * @date Created: Wed May 10 12:11:54 EEST 2006 ppessi */ #include "config.h" #define NTA_OUTGOING_MAGIC_T struct outbound #include "outbound.h" #include #include #include #include #include #include #include #include #include #include #include #define SU_LOG (nua_log) #include #include #include #include #include #include struct outbound { su_home_t ob_home[1]; outbound_owner_vtable const *ob_oo; /**< Callbacks */ outbound_owner_t *ob_owner; /**< Backpointer */ su_root_t *ob_root; /**< Root for timers and stuff */ nta_agent_t *ob_nta; /**< SIP transactions */ char ob_cookie[32]; /**< Our magic cookie */ struct outbound_prefs { unsigned interval; /**< Default keepalive interval for datagram */ unsigned stream_interval; /**< Default keepalive interval for streams */ unsigned gruuize:1; /**< Establish a GRUU */ unsigned outbound:1; /**< Try to use outbound */ unsigned natify:1; /**< Try to detect NAT */ signed okeepalive:2; /**< Connection keepalive with OPTIONS */ unsigned validate:1; /**< Validate registration with OPTIONS */ /* How to detect NAT binding or connect to outbound: */ unsigned use_connect:1; /**< Use HTTP connect */ unsigned use_rport:1; /**< Use received/rport */ unsigned use_socks:1; /**< Detect and use SOCKS V5 */ unsigned use_upnp:1; /**< Detect and use UPnP */ unsigned use_stun:1; /**< Detect and try to use STUN */ unsigned :0; } ob_prefs; struct outbound_info { /* See enum outbound_feature: */ /* 0 do not support, 1 - perhaps supports, 2 - supports, 3 - requires */ unsigned gruu:2, outbound:2, pref:2; } ob_info; /** Source of Contact header */ unsigned ob_by_stack:1; /** Self-generated contacts */ unsigned ob_contacts:1; /* The registration state machine. */ /** Initial REGISTER containing ob_rcontact has been sent */ unsigned ob_registering:1; /** 2XX response to REGISTER containing ob_rcontact has been received */ unsigned ob_registered:1; /** The registration has been validated: * We have successfully sent OPTIONS to ourselves. */ unsigned ob_validated:1; /** The registration has been validated once. * We have successfully sent OPTIONS to ourselves, so do not give * up if OPTIONS probe fails. */ unsigned ob_once_validated:1; unsigned ob_validate_timed_out:1; unsigned ob_proxy_override:1; /**< Override stack default proxy */ unsigned :0; url_string_t *ob_proxy; /**< Outbound-specific proxy */ char const *ob_instance; /**< Our instance ID */ int32_t ob_reg_id; /**< Flow-id */ sip_contact_t *ob_rcontact; /**< Our contact */ sip_contact_t *ob_dcontact; /**< Contact for dialogs */ sip_contact_t *ob_previous; /**< Stale contact */ sip_contact_t *ob_gruu; /**< Contact added to requests */ sip_via_t *ob_via; /**< Via header used to generate contacts */ sip_contact_t *ob_obp; /**< Contacts from outbound proxy */ char *ob_nat_detected; /**< Our public address */ char *ob_nat_port; /**< Our public port number */ void *ob_stun; /**< Stun context */ void *ob_upnp; /**< UPnP context */ /** Keepalive information */ struct { char *sipstun; /**< Stun server usable for keep-alives */ unsigned interval; /**< Interval. */ su_timer_t *timer; /**< Keep-alive timer */ msg_t *msg; /**< Keep-alive OPTIONS message */ nta_outgoing_t *orq; /**< Keep-alive OPTIONS transaction */ auth_client_t *auc[1]; /**< Authenticator for OPTIONS */ /** Progress of registration validation */ unsigned validating:1, validated:1,:0; } ob_keepalive; }; static int outbound_nat_detect(outbound_t *ob, sip_t const *request, sip_t const *response); /** Return values for outbound_nat_detect(). */ enum { ob_nat_error = -1, /* or anything below zero */ ob_no_nat = 0, ob_nat_detected = 1, ob_nat_changed = 2 }; /* ---------------------------------------------------------------------- */ #define SIP_METHOD_UNKNOWN sip_method_unknown, NULL /** Content-Type sent in OPTIONS probing connectivity */ char const * const outbound_content_type = "application/vnd.nokia-register-usage"; static int outbound_check_for_nat(outbound_t *ob, sip_t const *request, sip_t const *response); enum outbound_feature { outbound_feature_unsupported = 0, outbound_feature_unsure = 1, outbound_feature_supported = 2, outbound_feature_required = 3 }; static enum outbound_feature feature_level(sip_t const *sip, char const *tag, int level); static int outbound_contacts_from_via(outbound_t *ob, sip_via_t const *via); /* ---------------------------------------------------------------------- */ /** Create a new outbound object */ outbound_t * outbound_new(outbound_owner_t *owner, outbound_owner_vtable const *owner_methods, su_root_t *root, nta_agent_t *agent, char const *instance) { outbound_t *ob; if (!owner || !owner_methods || !root || !agent) return NULL; ob = su_home_clone((su_home_t *)owner, sizeof *ob); if (ob) { su_md5_t md5[1]; uint8_t digest[SU_MD5_DIGEST_SIZE]; su_guid_t guid[1]; ob->ob_owner = owner; ob->ob_oo = owner_methods; ob->ob_root = root; ob->ob_nta = agent; if (instance) ob->ob_instance = su_sprintf(ob->ob_home, "+sip.instance=\"<%s>\"", instance); ob->ob_reg_id = 0; outbound_peer_info(ob, NULL); /* Generate a random cookie (used as Call-ID) for us */ su_md5_init(md5); su_guid_generate(guid); if (instance) su_md5_update(md5, (void *)instance, strlen(instance)); su_md5_update(md5, (void *)guid, sizeof guid); su_md5_digest(md5, digest); token64_e(ob->ob_cookie, sizeof ob->ob_cookie, digest, sizeof digest); if (instance && !ob->ob_instance) su_home_unref(ob->ob_home), ob = NULL; } return ob; } void outbound_unref(outbound_t *ob) { if (ob->ob_keepalive.timer) su_timer_destroy(ob->ob_keepalive.timer), ob->ob_keepalive.timer = NULL; if (ob->ob_keepalive.orq) nta_outgoing_destroy(ob->ob_keepalive.orq), ob->ob_keepalive.orq = NULL; if (ob->ob_keepalive.msg) msg_destroy(ob->ob_keepalive.msg), ob->ob_keepalive.msg = NULL; su_home_unref(ob->ob_home); } #include /** Set various outbound and nat-traversal related options. */ int outbound_set_options(outbound_t *ob, char const *_options, unsigned interval, unsigned stream_interval) { struct outbound_prefs prefs[1] = {{ 0 }}; char *s, *options = su_strdup(NULL, _options); int invalid; prefs->interval = interval; prefs->stream_interval = stream_interval; #define MATCH(v) (len == sizeof(#v) - 1 && su_casenmatch(#v, s, len)) if (options) { for (s = options; s[0]; s++) if (s[0] == '-') s[0] = '_'; } prefs->gruuize = 1; prefs->outbound = 0; prefs->natify = 1; prefs->okeepalive = -1; prefs->validate = 1; prefs->use_rport = 1; for (s = options; s && s[0]; ) { size_t len = span_token(s); int value = 1; if (len > 3 && su_casenmatch(s, "no_", 3)) value = 0, s += 3, len -= 3; else if (len > 4 && su_casenmatch(s, "not_", 4)) value = 0, s += 4, len -= 4; if (len == 0) break; else if (MATCH(gruuize)) prefs->gruuize = value; else if (MATCH(outbound)) prefs->outbound = value; else if (MATCH(natify)) prefs->natify = value; else if (MATCH(validate)) prefs->validate = value; else if (MATCH(options_keepalive)) prefs->okeepalive = value; else if (MATCH(use_connect)) prefs->use_connect = value; else if (MATCH(use_rport)) prefs->use_rport = value; else if (MATCH(use_socks)) prefs->use_socks = value; else if (MATCH(use_upnp)) prefs->use_upnp = value; else if (MATCH(use_stun)) prefs->use_stun = value; else SU_DEBUG_1(("outbound(%p): unknown option \"%.*s\"\n", (void *)ob->ob_owner, (int)len, s)); s += len; len = strspn(s, " \t\n\r,;"); if (len == 0) break; s += len; } invalid = s && s[0]; if (invalid) SU_DEBUG_1(("outbound(%p): invalid options \"%s\"\n", (void *)ob->ob_owner, options)); su_free(NULL, options); if (invalid) return -1; if (prefs->natify && !(prefs->outbound || prefs->use_connect || prefs->use_rport || prefs->use_socks || prefs->use_upnp || prefs->use_stun)) { SU_DEBUG_1(("outbound(%p): no nat traversal method given\n", (void *)ob->ob_owner)); } ob->ob_prefs = *prefs; ob->ob_reg_id = prefs->outbound ? 1 : 0; return 0; } /** Override stack default proxy for outbound */ int outbound_set_proxy(outbound_t *ob, url_string_t *proxy) { url_string_t *new_proxy = NULL, *old_proxy = ob->ob_proxy; if (proxy) new_proxy = (url_string_t *)url_as_string(ob->ob_home, proxy->us_url); if (proxy == NULL || new_proxy != NULL) { ob->ob_proxy_override = 1; ob->ob_proxy = new_proxy; su_free(ob->ob_home, old_proxy); return 0; } return -1; } /* ---------------------------------------------------------------------- */ /** Obtain contacts for REGISTER */ int outbound_get_contacts(outbound_t *ob, sip_contact_t **return_current_contact, sip_contact_t **return_previous_contact) { if (ob) { if (ob->ob_contacts) *return_current_contact = ob->ob_rcontact; *return_previous_contact = ob->ob_previous; } return 0; } /** REGISTER request has been sent */ int outbound_start_registering(outbound_t *ob) { if (ob) ob->ob_registering = 1; return 0; } /** Process response to REGISTER request */ int outbound_register_response(outbound_t *ob, int terminating, sip_t const *request, sip_t const *response) { int status, reregister; if (!ob) return 0; if (terminating) { ob->ob_registering = ob->ob_registered = 0; return 0; /* Cleanup is done separately */ } if (!response || !request) return 0; assert(request->sip_request); assert(response->sip_status); status = response->sip_status->st_status; if (status < 300) { if (request->sip_contact && response->sip_contact) { sip_contact_t *m; if (ob->ob_rcontact != NULL) { msg_header_free(ob->ob_home, (msg_header_t *)ob->ob_rcontact); ob->ob_rcontact = NULL; } /* Ignore the contacts that were unregistered, if any */ for (m = request->sip_contact; m; m = m->m_next) { if (!m->m_expires || strtoul(m->m_expires, NULL, 10) != 0) break; } assert (!ob->ob_registering || m != NULL); if (m) ob->ob_rcontact = (sip_contact_t *) msg_header_dup_one(ob->ob_home, (const msg_header_t *)m); ob->ob_registered = ob->ob_registering; } else ob->ob_registered = 0; } reregister = outbound_check_for_nat(ob, request, response); if (reregister) return reregister; if (ob->ob_previous && status < 300) { msg_header_free(ob->ob_home, (void *)ob->ob_previous); ob->ob_previous = NULL; } return 0; } /** @internal Check if there is a NAT between us and registrar. * * @retval -1 upon an error * @retval #ob_register_ok (0) if the registration was OK * @retval #ob_reregister (1) if client needs to re-register * @retval #ob_reregister_now (2) if client needs to re-register immediately */ static int outbound_check_for_nat(outbound_t *ob, sip_t const *request, sip_t const *response) { int binding_changed; sip_contact_t *m = ob->ob_rcontact; /* Update NAT information */ binding_changed = outbound_nat_detect(ob, request, response); if (!ob->ob_nat_detected) return ob_no_nat; /* Contact was set by application, do not change it */ if (!ob->ob_by_stack) return ob_no_nat; /* Application does not want us to do any NAT traversal */ if (!ob->ob_prefs.natify) return ob_no_nat; /* We have detected NAT. Now, what to do? * 1) do nothing - register as usual and let proxy take care of it? * 2) try to detect our public nat binding and use it * 2A) use public vias from nta generated by STUN or UPnP * 2B) use SIP Via header */ /* Do we have to ask for reregistration */ if (!m || binding_changed >= ob_nat_changed) { if (ob->ob_stun) { /* Use STUN? */ return ob_reregister; } else if (ob->ob_upnp) { /* Use UPnP */ return ob_reregister; } else { if (outbound_contacts_from_via(ob, response->sip_via) < 0) return -1; } return ob_reregister_now; } return 0; } /**@internal * * Detect NAT. * * Based on "received" and possible "rport" parameters in the top-most Via, * check and update our NAT status. * * @retval ob_nat_changed (2) change in public NAT binding detected * @retval ob_nat_detected (1) NAT binding detected * @retval ob_no_nat (0) no NAT binding detected * @retval -1 an error occurred */ static int outbound_nat_detect(outbound_t *ob, sip_t const *request, sip_t const *response) { sip_via_t const *v; int one = 1; char const *received, *rport; char *nat_detected, *nat_port; char *new_detected, *new_port; assert(request && request->sip_request); assert(response && response->sip_status); if (!ob || !response || !response->sip_via || !request->sip_via) return -1; v = response->sip_via; received = v->v_received; if (!received || !strcmp(received, request->sip_via->v_host)) return 0; if (!host_is_ip_address(received)) { if (received[0]) SU_DEBUG_3(("outbound(%p): Via with invalid received=%s\n", (void *)ob->ob_owner, received)); return 0; } rport = sip_via_port(v, &one); assert(rport); nat_detected = ob->ob_nat_detected; nat_port = ob->ob_nat_port; if (nat_detected && host_cmp(received, nat_detected) == 0) { if (nat_port && su_casematch(rport, nat_port)) return 1; if (!v->v_rport || !v->v_rport[0]) return 1; } if (!nat_detected) { SU_DEBUG_5(("outbound(%p): detected NAT: %s != %s\n", (void *)ob->ob_owner, v->v_host, received)); if (ob->ob_oo && ob->ob_oo->oo_status) ob->ob_oo->oo_status(ob->ob_owner, ob, 101, "NAT detected", TAG_END()); } else { SU_DEBUG_5(("outbound(%p): NAT binding changed: " "[%s]:%s != [%s]:%s\n", (void *)ob->ob_owner, nat_detected, nat_port, received, rport)); if (ob->ob_oo && ob->ob_oo->oo_status) ob->ob_oo->oo_status(ob->ob_owner, ob, 102, "NAT binding changed", TAG_END()); } /* Save our nat binding */ new_detected = su_strdup(ob->ob_home, received); new_port = su_strdup(ob->ob_home, rport); if (!new_detected || !new_port) { su_free(ob->ob_home, new_detected); su_free(ob->ob_home, new_port); return -1; } ob->ob_nat_detected = new_detected; ob->ob_nat_port = new_port; su_free(ob->ob_home, nat_detected); su_free(ob->ob_home, nat_port); return 2; } /* ---------------------------------------------------------------------- */ /** Convert "gruu" parameter returned by registrar to Contact header. */ int outbound_gruuize(outbound_t *ob, sip_t const *sip) { sip_contact_t *m = NULL; char *gruu; if (!ob) return 0; if (ob->ob_rcontact == NULL) return -1; if (!ob->ob_prefs.gruuize && ob->ob_instance) { char const *my_instance, *my_reg_id = NULL; char const *instance, *reg_id; m = ob->ob_rcontact; my_instance = msg_header_find_param(m->m_common, "+sip.instance="); if (my_instance) my_reg_id = msg_header_find_param(m->m_common, "reg-id="); for (m = sip->sip_contact; m; m = m->m_next) { if (my_instance) { instance = msg_header_find_param(m->m_common, "+sip.instance="); if (!instance || strcmp(instance, my_instance)) continue; if (my_reg_id) { reg_id = msg_header_find_param(m->m_common, "reg-id="); if (!reg_id || strcmp(reg_id, my_reg_id)) continue; } } if (url_cmp_all(ob->ob_rcontact->m_url, m->m_url) == 0) break; } } if (m == NULL) { if (ob->ob_gruu) msg_header_free(ob->ob_home, (void *)ob->ob_gruu), ob->ob_gruu = NULL; return 0; } gruu = (char *)msg_header_find_param(m->m_common, "pub-gruu="); if (gruu == NULL || gruu[0] == '\0') gruu = (char *)msg_header_find_param(m->m_common, "gruu="); if (gruu == NULL || gruu[0] == '\0') return 0; gruu = msg_unquote_dup(NULL, gruu); m = gruu ? sip_contact_format(ob->ob_home, "<%s>", gruu) : NULL; su_free(NULL, gruu); if (!m) return -1; if (ob->ob_gruu) msg_header_free(ob->ob_home, (void *)ob->ob_gruu); ob->ob_gruu = m; return 0; } /* ---------------------------------------------------------------------- */ static int create_keepalive_message(outbound_t *ob, sip_t const *register_request); static int keepalive_options(outbound_t *ob); static int keepalive_options_with_registration_probe(outbound_t *ob); static int response_to_keepalive_options(outbound_t *ob, nta_outgoing_t *orq, sip_t const *sip); static int process_response_to_keepalive_options(outbound_t *ob, nta_outgoing_t *orq, sip_t const *sip, int status, char const *phrase); static void keepalive_timer(su_root_magic_t *root_magic, su_timer_t *t, su_timer_arg_t *ob_as_timer_arg); /** Start OPTIONS keepalive or contact validation process */ void outbound_start_keepalive(outbound_t *ob, nta_outgoing_t *register_transaction) { unsigned interval = 0; int need_to_validate, udp; if (!ob) return; udp = ob->ob_via && ob->ob_via->v_protocol == sip_transport_udp; if (/* ob->ob_prefs.natify && */ /* On UDP, use OPTIONS keepalive by default */ (udp ? ob->ob_prefs.okeepalive != 0 /* Otherwise, only if requested */ : ob->ob_prefs.okeepalive > 0)) interval = ob->ob_prefs.interval; need_to_validate = ob->ob_prefs.validate && !ob->ob_validated; if (!register_transaction || !(need_to_validate || interval != 0) || /* * Never validated, but OPTIONS timed out * => retry only if application retries REGISTER */ ob->ob_validate_timed_out) { outbound_stop_keepalive(ob); return; } if (ob->ob_keepalive.timer) su_timer_destroy(ob->ob_keepalive.timer), ob->ob_keepalive.timer = NULL; if (interval) { su_duration_t max_defer; max_defer = su_root_get_max_defer(ob->ob_root); if ((su_duration_t)interval >= max_defer) { interval -= max_defer - 100; } ob->ob_keepalive.timer = su_timer_create(su_root_task(ob->ob_root), interval); su_timer_deferrable(ob->ob_keepalive.timer, 1); } ob->ob_keepalive.interval = interval; if (!ob->ob_validated && ob->ob_keepalive.sipstun && 0 /* Stun is disabled for now */) { nta_tport_keepalive(register_transaction); } else { if (register_transaction) { msg_t *msg = nta_outgoing_getrequest(register_transaction); sip_t const *register_request = sip_object(msg); create_keepalive_message(ob, register_request); msg_destroy(msg); } keepalive_options(ob); } } void outbound_stop_keepalive(outbound_t *ob) { if (!ob) return; ob->ob_keepalive.interval = 0; if (ob->ob_keepalive.timer) su_timer_destroy(ob->ob_keepalive.timer), ob->ob_keepalive.timer = NULL; if (ob->ob_keepalive.orq) nta_outgoing_destroy(ob->ob_keepalive.orq), ob->ob_keepalive.orq = NULL; if (ob->ob_keepalive.msg) msg_destroy(ob->ob_keepalive.msg), ob->ob_keepalive.msg = NULL; } /** @internal Create a message template for keepalive. */ static int create_keepalive_message(outbound_t *ob, sip_t const *regsip) { msg_t *msg = nta_msg_create(ob->ob_nta, MSG_FLG_COMPACT), *previous; sip_t *osip = sip_object(msg); sip_contact_t *m = ob->ob_rcontact; unsigned d = ob->ob_keepalive.interval; if (msg == NULL) return -1; assert(regsip); assert(regsip->sip_request); if (m && m->m_params) { sip_accept_contact_t *ac; size_t i; int features = 0; ac = sip_accept_contact_make(msg_home(msg), "*;require;explicit"); for (i = 0; m->m_params[i]; i++) { char const *s = m->m_params[i]; if (!sip_is_callerpref(s)) continue; features++; s = su_strdup(msg_home(msg), s); msg_header_add_param(msg_home(msg), ac->cp_common, s); } if (features) msg_header_insert(msg, NULL, (void *)ac); else msg_header_free(msg_home(msg), (void *)ac); } if (0 > /* Duplicate essential headers from REGISTER request: */ sip_add_tl(msg, osip, SIPTAG_TO(regsip->sip_to), SIPTAG_FROM(regsip->sip_from), /* XXX - we should only use loose routing here */ /* XXX - if we used strict routing, the route header/request_uri must be restored */ SIPTAG_ROUTE(regsip->sip_route), /* Add Max-Forwards 0 */ TAG_IF(d, SIPTAG_MAX_FORWARDS_STR("0")), TAG_IF(d, SIPTAG_SUBJECT_STR("KEEPALIVE")), SIPTAG_CALL_ID_STR(ob->ob_cookie), SIPTAG_ACCEPT_STR(outbound_content_type), TAG_END()) || /* Create request-line, Call-ID, CSeq */ nta_msg_request_complete(msg, nta_default_leg(ob->ob_nta), SIP_METHOD_OPTIONS, (void *)regsip->sip_to->a_url) < 0 || msg_serialize(msg, (void *)osip) < 0 || msg_prepare(msg) < 0) return msg_destroy(msg), -1; previous = ob->ob_keepalive.msg; ob->ob_keepalive.msg = msg; msg_destroy(previous); return 0; } static int keepalive_options(outbound_t *ob) { msg_t *req; sip_t *sip; if (ob->ob_keepalive.orq) return 0; if (ob->ob_prefs.validate && ob->ob_registered && !ob->ob_validated) return keepalive_options_with_registration_probe(ob); req = msg_copy(ob->ob_keepalive.msg); if (!req) return -1; sip = sip_object(req); assert(sip); assert(sip->sip_request); if (nta_msg_request_complete(req, nta_default_leg(ob->ob_nta), SIP_METHOD_UNKNOWN, NULL) < 0) return msg_destroy(req), -1; if (ob->ob_keepalive.auc[0]) auc_authorization(ob->ob_keepalive.auc, req, (void *)sip, "OPTIONS", sip->sip_request->rq_url, sip->sip_payload); ob->ob_keepalive.orq = nta_outgoing_mcreate(ob->ob_nta, response_to_keepalive_options, ob, NULL, req, TAG_IF(ob->ob_proxy_override, NTATAG_DEFAULT_PROXY(ob->ob_proxy)), TAG_END()); if (!ob->ob_keepalive.orq) return msg_destroy(req), -1; return 0; } static int response_to_keepalive_options(outbound_t *ob, nta_outgoing_t *orq, sip_t const *sip) { int status = 408; char const *phrase = sip_408_Request_timeout; if (sip && sip->sip_status) { status = sip->sip_status->st_status; phrase = sip->sip_status->st_phrase; } if (status == 100) { /* This probably means that we are in trouble. whattodo, whattodo */ } if (status >= 200) { if (orq == ob->ob_keepalive.orq) ob->ob_keepalive.orq = NULL; process_response_to_keepalive_options(ob, orq, sip, status, phrase); nta_outgoing_destroy(orq); } return 0; } static int process_response_to_keepalive_options(outbound_t *ob, nta_outgoing_t *orq, sip_t const *sip, int status, char const *phrase) { int binding_check; int challenged = 0, credentials = 0; msg_t *_reqmsg = nta_outgoing_getrequest(orq); sip_t *request = sip_object(_reqmsg); msg_destroy(_reqmsg); if (sip == NULL) { SU_DEBUG_3(("outbound(%p): keepalive %u %s\n", (void *)ob->ob_owner, status, phrase)); ob->ob_oo->oo_keepalive_error(ob->ob_owner, ob, status, phrase, TAG_END()); return 0; } if (status == 401 || status == 407) { if (sip->sip_www_authenticate) challenged += auc_challenge(ob->ob_keepalive.auc, ob->ob_home, sip->sip_www_authenticate, sip_authorization_class) > 0; if (sip->sip_proxy_authenticate) challenged += auc_challenge(ob->ob_keepalive.auc, ob->ob_home, sip->sip_proxy_authenticate, sip_proxy_authorization_class) > 0; if (ob->ob_oo->oo_credentials) credentials = ob->ob_oo->oo_credentials(ob->ob_owner, ob->ob_keepalive.auc); } binding_check = outbound_nat_detect(ob, request, sip); if (binding_check > 1) { /* Bindings have changed */ if (outbound_contacts_from_via(ob, sip->sip_via) == 0) { /* XXX - Destroy old keepalive template message */ /* re-REGISTER */ ob->ob_oo->oo_refresh(ob->ob_owner, ob); return 0; } } if (binding_check <= 1 && ob->ob_registered && ob->ob_keepalive.validating) { int failed = 0; unsigned loglevel = 3; if (challenged > 0 && credentials > 0) { keepalive_options_with_registration_probe(ob); return 0; } if (status < 300 && ob->ob_keepalive.validated) { loglevel = 5; if (ob->ob_validated) loglevel = 99; /* only once */ ob->ob_validated = ob->ob_once_validated = 1; } else if (status == 408) { loglevel = 3, failed = 1; ob->ob_validate_timed_out = !ob->ob_once_validated; } else if (status == 401 || status == 407 || status == 403) loglevel = 5, failed = 1; else loglevel = 3, failed = 1; if (loglevel >= SU_LOG->log_level) { sip_contact_t const *m = ob->ob_rcontact; if (m) su_llog(SU_LOG, loglevel, "outbound(%p): %s <" URL_PRINT_FORMAT ">\n", (void *)ob->ob_owner, failed ? "FAILED to validate" : "validated", URL_PRINT_ARGS(m->m_url)); else su_llog(SU_LOG, loglevel, "outbound(%p): %s registration\n", (void *)ob->ob_owner, failed ? "FAILED to validate" : "validated"); if (failed) su_llog(SU_LOG, loglevel, "outbound(%p): FAILED with %u %s\n", (void *)ob->ob_owner, status, phrase); } if (failed) ob->ob_oo->oo_probe_error(ob->ob_owner, ob, status, phrase, TAG_END()); } else if (status == 408) { SU_DEBUG_3(("outbound(%p): keepalive timeout\n", (void *)ob->ob_owner)); ob->ob_oo->oo_keepalive_error(ob->ob_owner, ob, status, phrase, TAG_END()); return 0; } ob->ob_keepalive.validating = 0; if (ob->ob_keepalive.timer) su_timer_set(ob->ob_keepalive.timer, keepalive_timer, ob); return 0; } static void keepalive_timer(su_root_magic_t *root_magic, su_timer_t *t, su_timer_arg_t *ob_casted_as_timer_arg) { outbound_t *ob = (outbound_t *)ob_casted_as_timer_arg; (void)root_magic; if (keepalive_options(ob) < 0) su_timer_set(t, keepalive_timer, ob_casted_as_timer_arg); /* XXX */ } /** @internal Send a keepalive OPTIONS that probes the registration */ static int keepalive_options_with_registration_probe(outbound_t *ob) { msg_t *req; sip_t *sip; void *request_uri; if (ob->ob_keepalive.orq) return 0; req = msg_copy(ob->ob_keepalive.msg); if (!req) return -1; sip = sip_object(req); assert(sip); request_uri = sip->sip_to->a_url; if (nta_msg_request_complete(req, nta_default_leg(ob->ob_nta), SIP_METHOD_OPTIONS, request_uri) < 0) return msg_destroy(req), -1; if (ob->ob_keepalive.auc[0]) auc_authorization(ob->ob_keepalive.auc, req, (void *)sip, "OPTIONS", request_uri, sip->sip_payload); ob->ob_keepalive.orq = nta_outgoing_mcreate(ob->ob_nta, response_to_keepalive_options, ob, NULL, req, TAG_IF(ob->ob_proxy_override, NTATAG_DEFAULT_PROXY(ob->ob_proxy)), SIPTAG_SUBJECT_STR("REGISTRATION PROBE"), /* NONE is used to remove Max-Forwards: 0 found in ordinary keepalives */ SIPTAG_MAX_FORWARDS(SIP_NONE), TAG_END()); if (!ob->ob_keepalive.orq) return msg_destroy(req), -1; ob->ob_keepalive.validating = 1; ob->ob_keepalive.validated = 0; return 0; } /** Check if request should be processed by outbound */ int outbound_targeted_request(sip_t const *sip) { return sip && sip->sip_request && sip->sip_request->rq_method == sip_method_options && sip->sip_accept && sip->sip_accept->ac_type && su_casematch(sip->sip_accept->ac_type, outbound_content_type); } /** Answer to the connectivity probe OPTIONS */ int outbound_process_request(outbound_t *ob, nta_incoming_t *irq, sip_t const *sip) { /* XXX - We assume that Call-ID is not modified. */ if (strcmp(sip->sip_call_id->i_id, ob->ob_cookie)) return 0; if (ob->ob_keepalive.validating) { SU_DEBUG_5(("outbound(%p): registration check OPTIONS received\n", (void *)ob->ob_owner)); ob->ob_keepalive.validated = 1; } nta_incoming_treply(irq, SIP_200_OK, SIPTAG_CONTENT_TYPE_STR(outbound_content_type), SIPTAG_PAYLOAD_STR(ob->ob_cookie), TAG_END()); return 200; } /* ---------------------------------------------------------------------- */ /**@internal * Create contacts for outbound. * * There are two contacts: * one suitable for registrations (ob_rcontact) and another that can be used * in dialogs (ob_dcontact). */ int outbound_contacts_from_via(outbound_t *ob, sip_via_t const *via) { su_home_t *home = ob->ob_home; sip_contact_t *rcontact, *dcontact; char reg_id_param[20] = ""; sip_contact_t *previous_previous, *previous_rcontact, *previous_dcontact; sip_via_t *v, v0[1], *previous_via; int contact_uri_changed; if (!via) return -1; v = v0; *v0 = *via; v0->v_next = NULL; dcontact = ob->ob_oo->oo_contact(ob->ob_owner, home, 1, v, v->v_protocol, NULL); if (ob->ob_instance && ob->ob_reg_id != 0) snprintf(reg_id_param, sizeof reg_id_param, ";reg-id=%u", ob->ob_reg_id); rcontact = ob->ob_oo->oo_contact(ob->ob_owner, home, 0, v, v->v_protocol, ob->ob_instance, reg_id_param, NULL); v = sip_via_dup(home, v); if (!rcontact || !dcontact || !v) { msg_header_free(home, (void *)dcontact); if (rcontact != dcontact) msg_header_free(home, (void *)rcontact); msg_header_free(home, (void *)v); return -1; } contact_uri_changed = !ob->ob_rcontact || url_cmp_all(ob->ob_rcontact->m_url, rcontact->m_url); if (contact_uri_changed) { previous_previous = ob->ob_previous; previous_dcontact = ob->ob_dcontact; previous_via = ob->ob_via; if (ob->ob_registered /* && (ob->ob_reg_id == 0 || ob->ob_info.outbound < outbound_feature_supported) * XXX - multiple connections not yet supported */) previous_rcontact = NULL, ob->ob_previous = ob->ob_rcontact; else previous_rcontact = ob->ob_rcontact, ob->ob_previous = NULL; if (ob->ob_previous) msg_header_replace_param(home, (void*)ob->ob_previous, "expires=0"); } else { previous_previous = ob->ob_rcontact; previous_rcontact = NULL; previous_dcontact = ob->ob_dcontact; previous_via = ob->ob_via; } ob->ob_contacts = 1; ob->ob_rcontact = rcontact; ob->ob_dcontact = dcontact; ob->ob_via = v; if (contact_uri_changed) { ob->ob_registering = 0; ob->ob_registered = 0; ob->ob_validated = 0; } msg_header_free(home, (void *)previous_rcontact); msg_header_free(home, (void *)previous_previous); if (previous_dcontact != ob->ob_previous && previous_dcontact != previous_rcontact && previous_dcontact != previous_previous) msg_header_free(home, (void *)previous_dcontact); msg_header_free(home, (void *)previous_via); return 0; } /**Set new contact. * * @retval 0 when successful * @retval -1 error setting contact */ int outbound_set_contact(outbound_t *ob, sip_contact_t const *application_contact, sip_via_t const *v, int terminating) { su_home_t *home = ob->ob_home; sip_contact_t *rcontact = NULL, *dcontact = NULL, *previous = NULL; sip_contact_t *m1, *m2, *m3; int contact_uri_changed = 0; m1 = ob->ob_rcontact; m2 = ob->ob_dcontact; m3 = ob->ob_previous; if (terminating) { if (ob->ob_by_stack && application_contact == NULL) return 0; if (ob->ob_contacts) previous = ob->ob_rcontact; } else if (application_contact) { rcontact = sip_contact_dup(home, application_contact); if (!ob->ob_rcontact || url_cmp_all(ob->ob_rcontact->m_url, application_contact->m_url)) { contact_uri_changed = 1; previous = ob->ob_contacts ? ob->ob_rcontact : NULL; } } else if (ob->ob_by_stack) { return 0; /* Xyzzy - nothing happens */ } else if (v) { char const *tport = !v->v_next ? v->v_protocol : NULL; char reg_id_param[20]; dcontact = ob->ob_oo->oo_contact(ob->ob_owner, home, 1, v, tport, NULL); if (!dcontact) return -1; if (ob->ob_instance && ob->ob_reg_id != 0) snprintf(reg_id_param, sizeof reg_id_param, ";reg-id=%u", ob->ob_reg_id); rcontact = ob->ob_oo->oo_contact(ob->ob_owner, home, 0, v, v->v_protocol, ob->ob_instance, reg_id_param, NULL); if (!rcontact) return -1; if (!ob->ob_rcontact || url_cmp_all(ob->ob_rcontact->m_url, rcontact->m_url)) { contact_uri_changed = 1; previous = ob->ob_contacts ? ob->ob_rcontact : NULL; } } if (previous) msg_header_replace_param(home, (msg_common_t *)previous, "expires=0"); ob->ob_by_stack = application_contact == NULL; ob->ob_contacts = rcontact != NULL; ob->ob_rcontact = rcontact; ob->ob_dcontact = dcontact; ob->ob_previous = previous; if (contact_uri_changed) { ob->ob_registering = 0; ob->ob_registered = 0; ob->ob_validated = 0; ob->ob_once_validated = 0; } if (m1 != previous) msg_header_free(home, (void *)m1); if (m2 != m1 && m2 != m3) msg_header_free(home, (void *)m2); msg_header_free(home, (void *)m3); return 0; } sip_contact_t const *outbound_dialog_contact(outbound_t const *ob) { if (ob == NULL) return NULL; else if (ob->ob_gruu) return ob->ob_gruu; else return ob->ob_dcontact; } sip_contact_t const *outbound_dialog_gruu(outbound_t const *ob) { return ob ? ob->ob_gruu : NULL; } /* ---------------------------------------------------------------------- */ static enum outbound_feature feature_level(sip_t const *sip, char const *tag, int level) { if (sip_has_feature(sip->sip_require, tag)) return outbound_feature_required; else if (sip_has_feature(sip->sip_supported, tag)) return outbound_feature_supported; else if (sip_has_feature(sip->sip_unsupported, tag)) return outbound_feature_unsupported; else return (enum outbound_feature)level; } void outbound_peer_info(outbound_t *ob, sip_t const *sip) { if (sip == NULL) { ob->ob_info.outbound = outbound_feature_unsure; ob->ob_info.gruu = outbound_feature_unsure; ob->ob_info.pref = outbound_feature_unsure; return; } ob->ob_info.outbound = feature_level(sip, "outbound", ob->ob_info.outbound); ob->ob_info.gruu = feature_level(sip, "gruu", ob->ob_info.gruu); ob->ob_info.pref = feature_level(sip, "pref", ob->ob_info.pref); } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/outbound.h000066400000000000000000000102541223300710500223470ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2006 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef OUTBOUND_H /** Defined when has been included. */ #define OUTBOUND_H /**@IFILE outbound.h * * @brief Interface to SIP NAT traversal and outbound * * @author Pekka Pessi * * @date Created: Wed May 10 12:01:38 EEST 2006 ppessi */ #ifndef SU_CONFIG_H #include #endif #ifndef NTA_H #include #endif #ifndef AUTH_CLIENT_H #include #endif SOFIA_BEGIN_DECLS /* ====================================================================== */ /* Outbound connection */ #ifndef OUTBOUND_OWNER_T #define OUTBOUND_OWNER_T struct nua_handle_s /* Just for now */ #endif typedef struct outbound outbound_t; typedef struct outbound_owner_vtable outbound_owner_vtable; typedef OUTBOUND_OWNER_T outbound_owner_t; outbound_t *outbound_new(outbound_owner_t *owner, outbound_owner_vtable const *owner_methods, su_root_t *root, nta_agent_t *agent, char const *instance); void outbound_unref(outbound_t *ob); int outbound_set_options(outbound_t *ob, char const *options, unsigned dgram_interval, unsigned stream_interval); int outbound_set_proxy(outbound_t *ob, url_string_t *proxy); int outbound_get_contacts(outbound_t *ob, sip_contact_t **return_current_contact, sip_contact_t **return_previous_contact); int outbound_start_registering(outbound_t *ob); int outbound_register_response(outbound_t *ob, int terminating, sip_t const *request, sip_t const *response); /** Return values for outbound_register_response(). */ enum { ob_register_error = -1, /* Or anything below zero */ ob_register_ok = 0, /* No need to re-register */ ob_reregister = 1, /* Re-register when oo_refresh() is called */ ob_reregister_now = 2 /* Re-register immediately */ }; int outbound_set_contact(outbound_t *ob, sip_contact_t const *application_contact, sip_via_t const *v, int terminating); sip_contact_t const *outbound_dialog_contact(outbound_t const *ob); sip_contact_t const *outbound_dialog_gruu(outbound_t const *ob); int outbound_gruuize(outbound_t *ob, sip_t const *sip); void outbound_start_keepalive(outbound_t *ob, nta_outgoing_t *register_trans); void outbound_stop_keepalive(outbound_t *ob); int outbound_targeted_request(sip_t const *sip); int outbound_process_request(outbound_t *ob, nta_incoming_t *irq, sip_t const *sip); void outbound_peer_info(outbound_t *ob, sip_t const *sip); struct outbound_owner_vtable { int oo_size; sip_contact_t *(*oo_contact)(outbound_owner_t *, su_home_t *home, int used_in_dialog, sip_via_t const *v, char const *transport, char const *m_param, ...); int (*oo_refresh)(outbound_owner_t *, outbound_t *ob); int (*oo_status)(outbound_owner_t *, outbound_t *ob, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...); int (*oo_probe_error)(outbound_owner_t *, outbound_t *ob, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...); int (*oo_keepalive_error)(outbound_owner_t *, outbound_t *ob, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...); int (*oo_credentials)(outbound_owner_t *, auth_client_t **auc); }; SOFIA_END_DECLS #endif /* OUTBOUND_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/sofia-sip/000077500000000000000000000000001223300710500222275ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/sofia-sip/nua.h000066400000000000000000000322361223300710500231710ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@file sofia-sip/nua.h * @brief Sofia-SIP User Agent Library API * * @author Pekka Pessi * * @date Created: Wed Feb 14 17:09:44 2001 ppessi */ #ifndef NUA_H /** Defined when has been included. */ #define NUA_H #ifndef SU_WAIT_H #include #endif #ifndef URL_H #include #endif #ifndef SIP_H #include #endif #ifndef NUA_TAG_H #include #endif SOFIA_BEGIN_DECLS #ifndef NUA_MAGIC_T #define NUA_MAGIC_T void #endif /** Application context for NUA agent. */ typedef NUA_MAGIC_T nua_magic_t; #ifndef NUA_HMAGIC_T #define NUA_HMAGIC_T void #endif /** Application context for NUA handle. */ typedef NUA_HMAGIC_T nua_hmagic_t; #define NUA_NONE ((void *)(intptr_t)-1) /**Network change event levels given to NUTAG_DETECT_NETWORK_UPDATES(). * * @sa NUTAG_DETECT_NETWORK_UPDATES(), #nua_i_network_changed * * @since New in @VERSION_1_12_2. */ typedef enum nua_nw_detector_e { NUA_NW_DETECT_NOTHING = 0, NUA_NW_DETECT_ONLY_INFO, NUA_NW_DETECT_TRY_FULL } nua_nw_detector_t; /** Events */ typedef enum nua_event_e { /* Event used by stack internally */ nua_i_none = -1, /* Indications */ nua_i_error, /**< Error indication */ nua_i_invite, /**< Incoming call INVITE */ nua_i_cancel, /**< Incoming INVITE has been cancelled */ nua_i_ack, /**< Final response to INVITE has been ACKed */ nua_i_fork, /**< Outgoing call has been forked */ nua_i_active, /**< A call has been activated */ nua_i_terminated, /**< A call has been terminated */ nua_i_state, /**< Call state has changed */ nua_i_outbound, /**< Status from outbound processing */ nua_i_bye, /**< Incoming BYE call hangup */ nua_i_options, /**< Incoming OPTIONS */ nua_i_refer, /**< Incoming REFER call transfer */ nua_i_publish, /**< Incoming PUBLISH */ nua_i_prack, /**< Incoming PRACK */ nua_i_info, /**< Incoming session INFO */ nua_i_update, /**< Incoming session UPDATE */ nua_i_message, /**< Incoming MESSAGE */ nua_i_chat, /**< Incoming chat MESSAGE */ nua_i_subscribe, /**< Incoming SUBSCRIBE */ nua_i_subscription, /**< Incoming subscription to be authorized */ nua_i_notify, /**< Incoming event NOTIFY */ nua_i_method, /**< Incoming, unknown method */ nua_i_media_error, /**< Offer-answer error indication */ /* Responses */ nua_r_set_params, /**< Answer to nua_set_params() or * nua_get_hparams(). */ nua_r_get_params, /**< Answer to nua_get_params() or * nua_get_hparams(). */ nua_r_shutdown, /**< Answer to nua_shutdown() */ nua_r_notifier, /**< Answer to nua_notifier() */ nua_r_terminate, /**< Answer to nua_terminate() */ nua_r_authorize, /**< Answer to nua_authorize() */ /* SIP responses */ nua_r_register, /**< Answer to outgoing REGISTER */ nua_r_unregister, /**< Answer to outgoing un-REGISTER */ nua_r_invite, /**< Answer to outgoing INVITE */ nua_r_cancel, /**< Answer to outgoing CANCEL */ nua_r_bye, /**< Answer to outgoing BYE */ nua_r_options, /**< Answer to outgoing OPTIONS */ nua_r_refer, /**< Answer to outgoing REFER */ nua_r_publish, /**< Answer to outgoing PUBLISH */ nua_r_unpublish, /**< Answer to outgoing un-PUBLISH */ nua_r_info, /**< Answer to outgoing INFO */ nua_r_prack, /**< Answer to outgoing PRACK */ nua_r_update, /**< Answer to outgoing UPDATE */ nua_r_message, /**< Answer to outgoing MESSAGE */ nua_r_chat, /**< Answer to outgoing chat message */ nua_r_subscribe, /**< Answer to outgoing SUBSCRIBE */ nua_r_unsubscribe, /**< Answer to outgoing un-SUBSCRIBE */ nua_r_notify, /**< Answer to outgoing NOTIFY */ nua_r_method, /**< Answer to unknown outgoing method */ nua_r_authenticate, /**< Answer to nua_authenticate() */ /* Internal events: nua hides them from application */ nua_r_redirect, nua_r_destroy, nua_r_respond, nua_r_nit_respond, nua_r_ack, /*#< Answer to ACK */ /* NOTE: Post 1.12 release events come here (below) to keep ABI compatibility! */ nua_i_network_changed, /**< Local IP(v6) address has changed. @NEW_1_12_2 */ nua_i_register /**< Incoming REGISTER. @NEW_1_12_4. */ } nua_event_t; typedef struct event_s { nua_handle_t *e_nh; int e_event; short e_always; short e_status; char const *e_phrase; msg_t *e_msg; tagi_t e_tags[1]; } nua_event_data_t; /** NUA API version */ #define NUA_VERSION "2.0" /** NUA module version */ SOFIAPUBVAR char const nua_version[]; /** Typedef of NUA event callback. */ typedef void (*nua_callback_f)(nua_event_t event, int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]); /** Create a NUA agent. */ SOFIAPUBFUN nua_t *nua_create(su_root_t *root, nua_callback_f callback, nua_magic_t *magic, tag_type_t tag, tag_value_t value, ...); /** Shutdown NUA stack. */ SOFIAPUBFUN void nua_shutdown(nua_t *nua); /** Destroy the NUA stack. */ SOFIAPUBFUN void nua_destroy(nua_t *nua); /** Fetch callback context from nua. */ SOFIAPUBFUN nua_magic_t *nua_magic(nua_t *nua); /** Set NUA parameters. */ SOFIAPUBFUN void nua_set_params(nua_t *, tag_type_t, tag_value_t, ...); /** Get NUA parameters. */ SOFIAPUBFUN void nua_get_params(nua_t *nua, tag_type_t, tag_value_t, ...); /** Obtain default operation handle of the NUA stack object. */ SOFIAPUBFUN nua_handle_t *nua_default(nua_t *nua); /** Create an operation handle */ SOFIAPUBFUN nua_handle_t *nua_handle(nua_t *nua, nua_hmagic_t *hmagic, tag_type_t, tag_value_t, ...); /** Destroy a handle */ SOFIAPUBFUN void nua_handle_destroy(nua_handle_t *h); /** Make a new reference to handle */ SOFIAPUBFUN nua_handle_t *nua_handle_ref(nua_handle_t *); /** Destroy reference to handle */ SOFIAPUBFUN int nua_handle_unref(nua_handle_t *); /** Bind a callback context to an operation handle. */ SOFIAPUBFUN void nua_handle_bind(nua_handle_t *nh, nua_hmagic_t *magic); /** Fetch a callback context from an operation handle. */ SOFIAPUBFUN nua_hmagic_t *nua_handle_magic(nua_handle_t *nh); /** Set handle parameters. */ SOFIAPUBFUN void nua_set_hparams(nua_handle_t *, tag_type_t, tag_value_t, ...); /** Get handle parameters. */ SOFIAPUBFUN void nua_get_hparams(nua_handle_t *, tag_type_t, tag_value_t, ...); /** Check if operation handle is used for INVITE */ SOFIAPUBFUN int nua_handle_has_invite(nua_handle_t const *nh); /** Check if operation handle has been used with outgoing SUBSCRIBE of REFER request. */ SOFIAPUBFUN int nua_handle_has_subscribe(nua_handle_t const *nh); /** Check if operation handle has been used with nua_register() or nua_unregister(). */ SOFIAPUBFUN int nua_handle_has_register(nua_handle_t const *nh); /** Check if operation handle has an active call */ SOFIAPUBFUN int nua_handle_has_active_call(nua_handle_t const *nh); /** Check if operation handle has a call on hold */ SOFIAPUBFUN int nua_handle_has_call_on_hold(nua_handle_t const *nh); /** Check if handle has active event subscriptions (refers sent). */ SOFIAPUBFUN int nua_handle_has_events(nua_handle_t const *nh); /** Check if operation handle has active registrations */ SOFIAPUBFUN int nua_handle_has_registrations(nua_handle_t const *nh); /** Get the remote address (From/To header) of operation handle */ SOFIAPUBFUN sip_to_t const *nua_handle_remote(nua_handle_t const *nh); /** Get the local address (From/To header) of operation handle */ SOFIAPUBFUN sip_to_t const *nua_handle_local(nua_handle_t const *nh); /** Get name for NUA event. */ SOFIAPUBFUN char const *nua_event_name(nua_event_t event); /** Get name for NUA callstate. */ SOFIAPUBFUN char const *nua_callstate_name(enum nua_callstate state); /** Return name of subscription state. @NEW_1_12_5. */ SOFIAPUBFUN char const *nua_substate_name(enum nua_substate substate); /** Convert string to enum nua_substate. @NEW_1_12_5. */ SOFIAPUBFUN enum nua_substate nua_substate_make(char const *sip_substate); /** Send SIP REGISTER request to the registrar. */ SOFIAPUBFUN void nua_register(nua_handle_t *nh, tag_type_t, tag_value_t, ...); /** Unregister. */ SOFIAPUBFUN void nua_unregister(nua_handle_t *nh, tag_type_t, tag_value_t, ...); /** Place a call using SIP INVITE method. */ SOFIAPUBFUN void nua_invite(nua_handle_t *nh, tag_type_t, tag_value_t, ...); /** Acknowledge a succesfull response to INVITE request. */ SOFIAPUBFUN void nua_ack(nua_handle_t *nh, tag_type_t, tag_value_t, ...); /** Acknowledge a reliable preliminary response to INVITE request. */ SOFIAPUBFUN void nua_prack(nua_handle_t *nh, tag_type_t, tag_value_t, ...); /** Query capabilities from server */ SOFIAPUBFUN void nua_options(nua_handle_t *nh, tag_type_t, tag_value_t, ...); /** Send PUBLISH request to publication server. */ SOFIAPUBFUN void nua_publish(nua_handle_t *nh, tag_type_t, tag_value_t, ...); /** Send un-PUBLISH request to publication server. */ SOFIAPUBFUN void nua_unpublish(nua_handle_t *nh, tag_type_t, tag_value_t, ...); /** Send an instant message. */ SOFIAPUBFUN void nua_message(nua_handle_t *nh, tag_type_t, tag_value_t, ...); /** Send a chat message. */ SOFIAPUBFUN void nua_chat(nua_handle_t *nh, tag_type_t, tag_value_t, ...); /** Send an INFO request. */ SOFIAPUBFUN void nua_info(nua_handle_t *nh, tag_type_t, tag_value_t, ...); /** Subscribe a SIP event. */ SOFIAPUBFUN void nua_subscribe(nua_handle_t *nh, tag_type_t, tag_value_t, ...); /** Unsubscribe an event. */ SOFIAPUBFUN void nua_unsubscribe(nua_handle_t *, tag_type_t, tag_value_t, ...); /** Send a NOTIFY message. */ SOFIAPUBFUN void nua_notify(nua_handle_t *, tag_type_t, tag_value_t, ...); /** Create an event server. */ SOFIAPUBFUN void nua_notifier(nua_handle_t *, tag_type_t, tag_value_t, ...); /** Terminate an event server. */ SOFIAPUBFUN void nua_terminate(nua_handle_t *, tag_type_t, tag_value_t, ...); /** Transfer a call. */ SOFIAPUBFUN void nua_refer(nua_handle_t *, tag_type_t, tag_value_t, ...); /** Update a call */ SOFIAPUBFUN void nua_update(nua_handle_t *, tag_type_t, tag_value_t, ...); /** Hangdown a call. */ SOFIAPUBFUN void nua_bye(nua_handle_t *, tag_type_t, tag_value_t, ...); /** Cancel an INVITE operation */ SOFIAPUBFUN void nua_cancel(nua_handle_t *, tag_type_t, tag_value_t, ...); /** Authenticate an operation. */ SOFIAPUBFUN void nua_authenticate(nua_handle_t *, tag_type_t, tag_value_t, ...); /** Authorize a subscriber. */ SOFIAPUBFUN void nua_authorize(nua_handle_t *, tag_type_t, tag_value_t, ...); /*# Redirect an operation. @deprecated */ SOFIAPUBFUN void nua_redirect(nua_handle_t *, tag_type_t, tag_value_t, ...); /** Send a request message with an extension method. */ SOFIAPUBFUN void nua_method(nua_handle_t *, tag_type_t, tag_value_t, ...); /** Respond to a request with given status code and phrase. */ SOFIAPUBFUN void nua_respond(nua_handle_t *nh, int status, char const *phrase, tag_type_t, tag_value_t, ...); /** Check if event can be responded with nua_respond() */ SOFIAPUBFUN int nua_event_is_incoming_request(nua_event_t e); /** Cast a #nua_handle_t pointer to a #su_home_t. */ #define nua_handle_home(nh) ((su_home_t *)(nh)) /** Generate an instance identifier. */ SOFIAPUBFUN char const *nua_generate_instance_identifier(su_home_t *); #ifndef NUA_SAVED_EVENT_T #define NUA_SAVED_EVENT_T struct nua_saved_event * #endif /** Abstract type for saved nua events. */ typedef NUA_SAVED_EVENT_T nua_saved_event_t; /** Save last nua event */ SOFIAPUBFUN int nua_save_event(nua_t *nua, nua_saved_event_t return_saved[1]); /** Get information from saved event */ SOFIAPUBFUN nua_event_data_t const *nua_event_data(nua_saved_event_t const saved[1]); /** Destroy a save nua event */ SOFIAPUBFUN void nua_destroy_event(nua_saved_event_t *saved); /** Get request message from saved nua event. */ SOFIAPUBFUN msg_t *nua_saved_event_request(nua_saved_event_t const *saved); /** Get current request message. */ SOFIAPUBFUN msg_t *nua_current_request(nua_t const *nua); SOFIAPUBFUN sip_replaces_t *nua_handle_make_replaces(nua_handle_t *nh, su_home_t *home, int early_only); SOFIAPUBFUN nua_handle_t *nua_handle_by_replaces(nua_t *nua, sip_replaces_t const *rp); SOFIAPUBFUN nua_handle_t *nua_handle_by_call_id(nua_t *nua, const char *call_id); SOFIA_END_DECLS #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/nua/sofia-sip/nua_tag.h000066400000000000000000000674541223300710500240360ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2006 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef NUA_TAG_H /** Defined when has been included. */ #define NUA_TAG_H /**@file sofia-sip/nua_tag.h * @brief Tags for Sofia-SIP User Agent Library * * @author Pekka Pessi * @author Martti Mela * * @date Created: Mon Feb 19 18:54:26 EET 2001 ppessi */ #ifndef SU_TAG_H #include #endif #ifndef SDP_TAG_H #include #endif #ifndef URL_TAG_H #include #endif #ifndef SIP_TAG_H #include #endif #ifndef NTA_TAG_H #include #endif #ifndef NEA_TAG_H #include #endif #ifndef SOA_TAG_H #include #endif SOFIA_BEGIN_DECLS /** NUA agent. */ typedef struct nua_s nua_t; /** NUA transaction handle. */ typedef struct nua_handle_s nua_handle_t; /** List of all NUA tags. */ SOFIAPUBVAR tag_type_t nua_tag_list[]; /** Filter tag matching any nua tag. */ #define NUTAG_ANY() nutag_any, ((tag_value_t)0) SOFIAPUBVAR tag_typedef_t nutag_any; #define NUTAG_URL(x) nutag_url, urltag_url_v(x) SOFIAPUBVAR tag_typedef_t nutag_url; #define NUTAG_URL_REF(x) nutag_url_ref, urltag_url_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_url_ref; #define NUTAG_ADDRESS(x) nutag_address, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_address; #define NUTAG_ADDRESS_REF(x) nutag_address_ref, tag_str_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_address_ref; #define NUTAG_WITH(x) nutag_with, tag_ptr_v(x) SOFIAPUBVAR tag_typedef_t nutag_with; #define NUTAG_WITH_THIS(nua) nutag_with, tag_ptr_v(nua_current_request((nua))) #define NUTAG_WITH_CURRENT(nua) \ nutag_with, tag_ptr_v(nua_current_request((nua))) #define NUTAG_WITH_SAVED(e) nutag_with, tag_ptr_v(nua_saved_event_request((e))) #define NUTAG_DIALOG(b) nutag_dialog, tag_uint_v((b)) SOFIAPUBVAR tag_typedef_t nutag_dialog; #define NUTAG_METHOD(x) nutag_method, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_method; #define NUTAG_METHOD_REF(x) nutag_method_ref, tag_str_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_method_ref; #define NUTAG_MAX_SUBSCRIPTIONS(x) nutag_max_subscriptions, tag_uint_v(x) SOFIAPUBVAR tag_typedef_t nutag_max_subscriptions; #define NUTAG_MAX_SUBSCRIPTIONS_REF(x) \ nutag_max_subscriptions_ref, tag_uint_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_max_subscriptions_ref; #define NUTAG_UICC(x) nutag_uicc, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_uicc; #define NUTAG_UICC_REF(x) nutag_uicc_ref, tag_str_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_uicc_ref; #define NUTAG_USE_DIALOG(x) nutag_use_dialog, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_use_dialog; #define NUTAG_USE_DIALOG_REF(x) nutag_use_dialog_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_use_dialog_ref; /* Protocol engine parameters, * set by nua_set_params(), get by nua_get_params() */ #define NUTAG_RETRY_COUNT(x) nutag_retry_count, tag_uint_v(x) SOFIAPUBVAR tag_typedef_t nutag_retry_count; #define NUTAG_RETRY_COUNT_REF(x) nutag_retry_count_ref, tag_uint_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_retry_count_ref; #define NUTAG_SOA_NAME(x) nutag_soa_name, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_soa_name; #define NUTAG_SOA_NAME_REF(x) \ nutag_soa_name_ref, tag_str_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_soa_name_ref; #define NUTAG_EARLY_MEDIA(x) nutag_early_media, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_early_media; #define NUTAG_EARLY_MEDIA_REF(x) nutag_early_media_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_early_media_ref; #define NUTAG_ONLY183_100REL(x) nutag_only183_100rel, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_only183_100rel; #define NUTAG_ONLY183_100REL_REF(x) nutag_only183_100rel_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_only183_100rel_ref; #define NUTAG_EARLY_ANSWER(x) nutag_early_answer, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_early_answer; #define NUTAG_EARLY_ANSWER_REF(x) nutag_early_answer_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_early_answer_ref; #define NUTAG_INCLUDE_EXTRA_SDP(x) nutag_include_extra_sdp, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_include_extra_sdp; #define NUTAG_INCLUDE_EXTRA_SDP_REF(x) \ nutag_include_extra_sdp_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_include_extra_sdp_ref; #define NUTAG_ACCEPT_MULTIPART(x) nutag_accept_multipart, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_accept_multipart; #define NUTAG_ACCEPT_MULTIPART_REF(x) \ nutag_accept_multipart_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_accept_multipart_ref; #define NUTAG_INVITE_TIMER(x) nutag_invite_timer, tag_uint_v((x)) SOFIAPUBVAR tag_typedef_t nutag_invite_timer; #define NUTAG_INVITE_TIMER_REF(x) nutag_invite_timer_ref, tag_uint_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_invite_timer_ref; #define NUTAG_SESSION_TIMER(x) nutag_session_timer, tag_uint_v((x)) SOFIAPUBVAR tag_typedef_t nutag_session_timer; #define NUTAG_SESSION_TIMER_REF(x) nutag_session_timer_ref, tag_uint_vr((&(x))) SOFIAPUBVAR tag_typedef_t nutag_session_timer_ref; #define NUTAG_MIN_SE(x) nutag_min_se, tag_uint_v((x)) SOFIAPUBVAR tag_typedef_t nutag_min_se; #define NUTAG_MIN_SE_REF(x) nutag_min_se_ref, tag_uint_vr((&(x))) SOFIAPUBVAR tag_typedef_t nutag_min_se_ref; /** Enumeration type of NUTAG_SESSION_REFRESHER(). */ enum nua_session_refresher { nua_no_refresher, /**< Disable session timer. */ nua_local_refresher, /**< Session refresh by local end. */ nua_remote_refresher, /**< Session refresh by remote end. */ nua_any_refresher /**< No preference (default). */ }; #define NUTAG_SESSION_REFRESHER(x) nutag_session_refresher, tag_int_v((x)) SOFIAPUBVAR tag_typedef_t nutag_session_refresher; #define NUTAG_SESSION_REFRESHER_REF(x) nutag_session_refresher_ref, tag_int_vr((&(x))) SOFIAPUBVAR tag_typedef_t nutag_session_refresher_ref; #define NUTAG_UPDATE_REFRESH(x) nutag_update_refresh, tag_bool_v((x)) SOFIAPUBVAR tag_typedef_t nutag_update_refresh; #define NUTAG_UPDATE_REFRESH_REF(x) nutag_update_refresh_ref, tag_bool_vr((&(x))) SOFIAPUBVAR tag_typedef_t nutag_update_refresh_ref; #define NUTAG_REFRESH_WITHOUT_SDP(x) nutag_refresh_without_sdp, tag_bool_v((x)) SOFIAPUBVAR tag_typedef_t nutag_refresh_without_sdp; #define NUTAG_REFRESH_WITHOUT_SDP_REF(x) \ nutag_refresh_without_sdp_ref, tag_bool_vr((&(x))) SOFIAPUBVAR tag_typedef_t nutag_refresh_without_sdp_ref; #define NUTAG_AUTOALERT(x) nutag_autoalert, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_autoalert; #define NUTAG_AUTOALERT_REF(x) nutag_autoalert_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_autoalert_ref; #define NUTAG_AUTOACK(x) nutag_autoack, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_autoack; #define NUTAG_AUTOACK_REF(x) nutag_autoack_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_autoack_ref; #define NUTAG_AUTOANSWER(x) nutag_autoanswer, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_autoanswer; #define NUTAG_AUTOANSWER_REF(x) nutag_autoanswer_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_autoanswer_ref; #define NUTAG_ENABLEINVITE(x) nutag_enableinvite, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_enableinvite; #define NUTAG_ENABLEINVITE_REF(x) nutag_enableinvite_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_enableinvite_ref; #define NUTAG_ENABLEMESSAGE(x) nutag_enablemessage, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_enablemessage; #define NUTAG_ENABLEMESSAGE_REF(x) nutag_enablemessage_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_enablemessage_ref; #define NUTAG_ENABLEMESSENGER(x) nutag_enablemessenger, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_enablemessenger; #define NUTAG_ENABLEMESSENGER_REF(x) \ nutag_enablemessenger_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_enablemessenger_ref; #define NUTAG_AUTO302(x) nutag_auto302, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_auto302; #define NUTAG_AUTO302_REF(x) nutag_auto302_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_auto302_ref; #define NUTAG_AUTO305(x) nutag_auto305, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_auto305; #define NUTAG_AUTO305_REF(x) nutag_auto305_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_auto305_ref; #define NUTAG_AUTO100(x) nutag_auto100, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_auto100; #define NUTAG_AUTO100_REF(x) nutag_auto100_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_auto100_ref; #define NUTAG_MAX_RETRY_AFTER(x) \ nutag_max_retry_after, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_max_retry_after; #define NUTAG_MAX_RETRY_AFTER_REF(x) \ nutag_max_retry_after_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_max_retry_after_ref; /* Start NRC Boston */ #define NUTAG_SMIME_ENABLE(x) nutag_smime_enable, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_smime_enable; #define NUTAG_SMIME_ENABLE_REF(x) nutag_smime_enable_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_smime_enable_ref; #define NUTAG_SMIME_OPT(x) nutag_smime_opt, tag_int_v(x) SOFIAPUBVAR tag_typedef_t nutag_smime_opt; #define NUTAG_SMIME_OPT_REF(x) nutag_smime_opt_ref, tag_int_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_smime_opt_ref; #define NUTAG_SMIME_PROTECTION_MODE(x) nutag_smime_protection_mode, tag_uint_v(x) SOFIAPUBVAR tag_typedef_t nutag_smime_protection_mode; #define NUTAG_SMIME_PROTECTION_MODE_REF(x) \ nutag_smime_protection_mode_ref, tag_uint_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_smime_protection_mode_ref; #define NUTAG_SMIME_MESSAGE_DIGEST(x) nutag_smime_message_digest, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_smime_message_digest; #define NUTAG_SMIME_MESSAGE_DIGEST_REF(x) \ nutag_smime_message_digest_ref, tag_str_vr((&x)) SOFIAPUBVAR tag_typedef_t nutag_smime_message_digest_ref; #define NUTAG_SMIME_SIGNATURE(x) nutag_smime_signature, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_smime_signature; #define NUTAG_SMIME_SIGNATURE_REF(x) \ nutag_smime_signature_ref, tag_str_vr((&x)) SOFIAPUBVAR tag_typedef_t nutag_smime_signature_ref; #define NUTAG_SMIME_KEY_ENCRYPTION(x) nutag_smime_key_encryption, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_smime_key_encryption; #define NUTAG_SMIME_KEY_ENCRYPTION_REF(x) \ nutag_smime_key_encryption_ref, tag_str_vr((&x)) SOFIAPUBVAR tag_typedef_t nutag_smime_key_encryption_ref; #define NUTAG_SMIME_MESSAGE_ENCRYPTION(x) nutag_smime_message_encryption, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_smime_message_encryption; #define NUTAG_SMIME_MESSAGE_ENCRYPTION_REF(x) \ nutag_smime_message_encryption_ref, tag_str_vr((&x)) SOFIAPUBVAR tag_typedef_t nutag_smime_message_encryption_ref; /* End NRC Boston */ #define NUTAG_CERTIFICATE_DIR(x) nutag_certificate_dir, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_certificate_dir; #define NUTAG_CERTIFICATE_DIR_REF(x) \ nutag_certificate_dir_ref, tag_str_vr((&x)) SOFIAPUBVAR tag_typedef_t nutag_certificate_dir_ref; #define NUTAG_CERTIFICATE_PHRASE(x) nutag_certificate_phrase, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_certificate_phrase; #define NUTAG_CERTIFICATE_PHRASE_REF(x) \ nutag_certificate_phrase_ref, tag_str_vr((&x)) SOFIAPUBVAR tag_typedef_t nutag_certificate_phrase_ref; #define NUTAG_SIPS_URL(x) nutag_sips_url, urltag_url_v(x) SOFIAPUBVAR tag_typedef_t nutag_sips_url; #define NUTAG_SIPS_URL_REF(x) nutag_sips_url_ref, urltag_url_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_sips_url_ref; #define NUTAG_PROXY(x) NTATAG_DEFAULT_PROXY(x) #define NUTAG_PROXY_REF(x) NTATAG_DEFAULT_PROXY_REF(x) #define nutag_proxy ntatag_default_proxy #define NUTAG_INITIAL_ROUTE(x) nutag_initial_route, siptag_route_v(x) SOFIAPUBVAR tag_typedef_t nutag_initial_route; #define NUTAG_INITIAL_ROUTE_REF(x) nutag_initial_route_ref, siptag_route_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_initial_route_ref; #define NUTAG_INITIAL_ROUTE_STR(x) nutag_initial_route_str, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_initial_route_str; #define NUTAG_INITIAL_ROUTE_STR_REF(x) nutag_initial_route_str_ref, tag_str_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_initial_route_str_ref; #define NUTAG_REGISTRAR(x) nutag_registrar, urltag_url_v(x) SOFIAPUBVAR tag_typedef_t nutag_registrar; #define NUTAG_REGISTRAR_REF(x) nutag_registrar_ref, urltag_url_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_registrar_ref; #define NUTAG_OUTBOUND(x) nutag_outbound, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_outbound; #define NUTAG_OUTBOUND_REF(x) nutag_outbound_ref, tag_str_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_outbound_ref; #if notyet #define NUTAG_OUTBOUND_SET1(x) nutag_outbound_set1, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_outbound_set1; #define NUTAG_OUTBOUND_SET1_REF(x) nutag_outbound_set1_ref, tag_str_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_outbound_set1_ref; #define NUTAG_OUTBOUND_SET2(x) nutag_outbound_set2, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_outbound_set2; #define NUTAG_OUTBOUND_SET2_REF(x) nutag_outbound_set2_ref, tag_str_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_outbound_set2_ref; #define NUTAG_OUTBOUND_SET3(x) nutag_outbound_set3, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_outbound_set3; #define NUTAG_OUTBOUND_SET3_REF(x) nutag_outbound_set3_ref, tag_str_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_outbound_set3_ref; #define NUTAG_OUTBOUND_SET4(x) nutag_outbound_set4, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_outbound_set4; #define NUTAG_OUTBOUND_SET4_REF(x) nutag_outbound_set4_ref, tag_str_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_outbound_set4_ref; #endif /* ...notyet */ #define NUTAG_SIP_PARSER(x) NTATAG_MCLASS(x) #define NUTAG_SIP_PARSER_REF(x) NTATAG_MCLASS_REF(x) #define NUTAG_AUTH(x) nutag_auth, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_auth; #define NUTAG_AUTH_REF(x) nutag_auth_ref, tag_str_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_auth_ref; #define NUTAG_AUTH_CACHE(x) nutag_auth_cache, tag_int_v(x) SOFIAPUBVAR tag_typedef_t nutag_auth_cache; #define NUTAG_AUTH_CACHE_REF(x) nutag_auth_cache_ref, tag_int_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_auth_cache_ref; /** Authentication caching policy. @NEW_1_12_6. */ enum nua_auth_cache { /** Include credentials within dialog (default) */ nua_auth_cache_dialog = 0, /** Include credentials only when challenged */ nua_auth_cache_challenged = 1, _nua_auth_cache_invalid }; #define NUTAG_KEEPALIVE(x) nutag_keepalive, tag_uint_v(x) SOFIAPUBVAR tag_typedef_t nutag_keepalive; #define NUTAG_KEEPALIVE_REF(x) nutag_keepalive_ref, tag_uint_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_keepalive_ref; #define NUTAG_KEEPALIVE_STREAM(x) nutag_keepalive_stream, tag_uint_v(x) SOFIAPUBVAR tag_typedef_t nutag_keepalive_stream; #define NUTAG_KEEPALIVE_STREAM_REF(x) \ nutag_keepalive_stream_ref, tag_uint_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_keepalive_stream_ref; #define NUTAG_AUTHTIME(x) nutag_authtime, tag_uint_v(x) SOFIAPUBVAR tag_typedef_t nutag_authtime; #define NUTAG_AUTHTIME_REF(x) nutag_authtime_ref, tag_uint_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_authtime_ref; #define NUTAG_M_DISPLAY(x) nutag_m_display, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_m_display; #define NUTAG_M_DISPLAY_REF(x) nutag_m_display_ref, tag_str_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_m_display_ref; #define NUTAG_M_USERNAME(x) nutag_m_username, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_m_username; #define NUTAG_M_USERNAME_REF(x) nutag_m_username_ref, tag_str_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_m_username_ref; #define NUTAG_M_PARAMS(x) nutag_m_params, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_m_params; #define NUTAG_M_PARAMS_REF(x) nutag_m_params_ref, tag_str_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_m_params_ref; #define NUTAG_M_FEATURES(x) nutag_m_features, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_m_features; #define NUTAG_M_FEATURES_REF(x) nutag_m_features_ref, tag_str_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_m_features_ref; #define NUTAG_EVENT(x) nutag_event, tag_int_v(x) SOFIAPUBVAR tag_typedef_t nutag_event; #define NUTAG_EVENT_REF(x) nutag_event_ref, tag_int_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_event_ref; #define NUTAG_STATUS(x) nutag_status, tag_uint_v(x) SOFIAPUBVAR tag_typedef_t nutag_status; #define NUTAG_STATUS_REF(x) nutag_status_ref, tag_uint_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_status_ref; #define NUTAG_PHRASE(x) nutag_phrase, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_phrase; #define NUTAG_PHRASE_REF(x) nutag_phrase_ref, tag_str_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_phrase_ref; #define NUTAG_HANDLE(x) nutag_handle, nutag_handle_v(x) SOFIAPUBVAR tag_typedef_t nutag_handle; #define NUTAG_HANDLE_REF(x) nutag_handle_ref, nutag_handle_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_handle_ref; #define NUTAG_IDENTITY(x) nutag_identity, nutag_handle_v(x) SOFIAPUBVAR tag_typedef_t nutag_identity; #define NUTAG_IDENTITY_REF(x) nutag_identity_ref, nutag_handle_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_identity_ref; #define NUTAG_INSTANCE(x) nutag_instance, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_instance; #define NUTAG_INSTANCE_REF(x) nutag_instance_ref, tag_str_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_instance_ref; #define NUTAG_NOTIFY_REFER(x) nutag_notify_refer, nutag_handle_v(x) SOFIAPUBVAR tag_typedef_t nutag_notify_refer; #define NUTAG_NOTIFY_REFER_REF(x) nutag_notify_refer_ref, nutag_handle_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_notify_refer_ref; #define NUTAG_REFER_EVENT(x) nutag_refer_event, siptag_event_v(x) SOFIAPUBVAR tag_typedef_t nutag_refer_event; #define NUTAG_REFER_EVENT_REF(x) nutag_refer_event_ref, siptag_event_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_refer_event_ref; #define NUTAG_REFER_PAUSE(x) nutag_refer_pause, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_refer_pause; #define NUTAG_REFER_PAUSE_REF(x) nutag_refer_pause_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_refer_pause_ref; #define NUTAG_USER_AGENT(x) nutag_user_agent, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_user_agent; #define NUTAG_USER_AGENT_REF(x) nutag_user_agent_ref, tag_str_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_user_agent_ref; #define NUTAG_ALLOW(x) nutag_allow, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_allow; #define NUTAG_ALLOW_REF(x) nutag_allow_ref, tag_str_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_allow_ref; #define NUTAG_APPL_METHOD(x) nutag_appl_method, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_appl_method; #define NUTAG_APPL_METHOD_REF(x) nutag_appl_method_ref, tag_str_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_appl_method_ref; #define NUTAG_SUPPORTED(x) nutag_supported, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_supported; #define NUTAG_SUPPORTED_REF(x) nutag_supported_ref, tag_str_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_supported_ref; #define NUTAG_ALLOW_EVENTS(x) nutag_allow_events, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_allow_events; #define NUTAG_ALLOW_EVENTS_REF(x) nutag_allow_events_ref, tag_str_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_allow_events_ref; #define NUTAG_APPL_EVENT(x) nutag_appl_event, tag_str_v(x) SOFIAPUBVAR tag_typedef_t nutag_appl_event; #define NUTAG_APPL_EVENT_REF(x) nutag_appl_event_ref, tag_str_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_appl_event_ref; #define NUTAG_CALLSTATE(x) nutag_callstate, tag_int_v(x) SOFIAPUBVAR tag_typedef_t nutag_callstate; #define NUTAG_CALLSTATE_REF(x) nutag_callstate_ref, tag_int_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_callstate_ref; enum nua_callstate { nua_callstate_init, /**< Initial state */ nua_callstate_authenticating, /**< 401/407 received */ nua_callstate_calling, /**< INVITE sent */ nua_callstate_proceeding, /**< 18X received */ nua_callstate_completing, /**< 2XX received */ nua_callstate_received, /**< INVITE received */ nua_callstate_early, /**< 18X sent (w/SDP) */ nua_callstate_completed, /**< 2XX sent */ nua_callstate_ready, /**< 2XX received, ACK sent, or vice versa */ nua_callstate_terminating, /**< BYE sent */ nua_callstate_terminated /**< BYE complete */ }; /** Get name for NUA call state */ SOFIAPUBFUN char const *nua_callstate_name(enum nua_callstate state); #define NUTAG_SUBSTATE(x) nutag_substate, tag_int_v(x) SOFIAPUBVAR tag_typedef_t nutag_substate; #define NUTAG_SUBSTATE_REF(x) nutag_substate_ref, tag_int_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_substate_ref; /** Parameter type of NUTAG_SUBSTATE() */ enum nua_substate { /** Extended state, considered as active. */ nua_substate_extended = nea_extended, /** Embryonic subscription: SUBSCRIBE sent */ nua_substate_embryonic = nea_embryonic, nua_substate_pending = nea_pending, /**< Pending subscription */ nua_substate_active = nea_active, /**< Active subscription */ nua_substate_terminated = nea_terminated /**< Terminated subscription */ }; /** Return name of subscription state. @NEW_1_12_5. */ SOFIAPUBFUN char const *nua_substate_name(enum nua_substate substate); /** Convert string to enum nua_substate. @NEW_1_12_5. */ SOFIAPUBFUN enum nua_substate nua_substate_make(char const *sip_substate); #define NUTAG_SUB_EXPIRES(x) nutag_sub_expires, tag_uint_v(x) SOFIAPUBVAR tag_typedef_t nutag_sub_expires; #define NUTAG_SUB_EXPIRES_REF(x) nutag_sub_expires_ref, tag_uint_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_sub_expires_ref; #define NUTAG_NEWSUB(x) nutag_newsub, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_newsub; #define NUTAG_NEWSUB_REF(x) nutag_newsub_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_newsub_ref; #define NUTAG_REFER_EXPIRES(x) nutag_refer_expires, tag_uint_v((x)) SOFIAPUBVAR tag_typedef_t nutag_refer_expires; #define NUTAG_REFER_EXPIRES_REF(x) nutag_refer_expires_ref, tag_uint_vr((&(x))) SOFIAPUBVAR tag_typedef_t nutag_refer_expires_ref; #define NUTAG_REFER_WITH_ID(x) nutag_refer_with_id, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_refer_with_id; #define NUTAG_REFER_WITH_ID_REF(x) nutag_refer_with_id_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_refer_with_id_ref; #define NUTAG_MEDIA_FEATURES(x) nutag_media_features, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_media_features; #define NUTAG_MEDIA_FEATURES_REF(x) \ nutag_media_features_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_media_features_ref; #define NUTAG_CALLEE_CAPS(x) nutag_callee_caps, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_callee_caps; #define NUTAG_CALLEE_CAPS_REF(x) \ nutag_callee_caps_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_callee_caps_ref; #define NUTAG_PATH_ENABLE(x) nutag_path_enable, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_path_enable; #define NUTAG_PATH_ENABLE_REF(x) nutag_path_enable_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_path_enable_ref; #define NUTAG_SERVICE_ROUTE_ENABLE(x) nutag_service_route_enable, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_service_route_enable; #define NUTAG_SERVICE_ROUTE_ENABLE_REF(x) \ nutag_service_route_enable_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_service_route_enable_ref; #define NUTAG_MEDIA_ENABLE(x) nutag_media_enable, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_media_enable; #define NUTAG_MEDIA_ENABLE_REF(x) \ nutag_media_enable_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_media_enable_ref; #define NUTAG_OFFER_RECV(x) nutag_offer_recv, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_offer_recv; #define NUTAG_OFFER_RECV_REF(x) nutag_offer_recv_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_offer_recv_ref; #define NUTAG_ANSWER_RECV(x) nutag_answer_recv, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_answer_recv; #define NUTAG_ANSWER_RECV_REF(x) nutag_answer_recv_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_answer_recv_ref; #define NUTAG_OFFER_SENT(x) nutag_offer_sent, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_offer_sent; #define NUTAG_OFFER_SENT_REF(x) nutag_offer_sent_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_offer_sent_ref; #define NUTAG_ANSWER_SENT(x) nutag_answer_sent, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_answer_sent; #define NUTAG_ANSWER_SENT_REF(x) nutag_answer_sent_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_answer_sent_ref; #define NUTAG_DETECT_NETWORK_UPDATES(x) \ nutag_detect_network_updates, tag_int_v(x) SOFIAPUBVAR tag_typedef_t nutag_detect_network_updates; #define NUTAG_DETECT_NETWORK_UPDATES_REF(x) \ nutag_detect_network_updates_ref, tag_int_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_detect_network_updates_ref; #define NUTAG_SHUTDOWN_EVENTS(x) \ nutag_shutdown_events, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_shutdown_events; #define NUTAG_SHUTDOWN_EVENTS_REF(x) \ nutag_shutdown_events_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_shutdown_events_ref; #define NUTAG_DEFERRABLE_TIMERS(x) \ nutag_deferrable_timers, tag_bool_v(x) SOFIAPUBVAR tag_typedef_t nutag_deferrable_timers; #define NUTAG_DEFERRABLE_TIMERS_REF(x) \ nutag_deferrable_timers_ref, tag_bool_vr(&(x)) SOFIAPUBVAR tag_typedef_t nutag_deferrable_timers_ref; /* Pass nua handle as tagged argument */ #if SU_INLINE_TAG_CAST su_inline tag_value_t nutag_handle_v(nua_handle_t *v) { return (tag_value_t)v; } su_inline tag_value_t nutag_handle_vr(nua_handle_t **vp) {return(tag_value_t)vp;} #else #define nutag_handle_v(v) (tag_value_t)(v) #define nutag_handle_vr(v) (tag_value_t)(v) #endif /* Tags for compatibility */ #define NUTAG_USE_LEG(x) NUTAG_USE_DIALOG(x) #define NUTAG_USE_LEG_REF(x) NUTAG_USE_DIALOG_REF(x) #define NUTAG_AF(x) SOATAG_AF((x)) #define NUTAG_AF_REF(x) SOATAG_AF_REF((x)) enum nua_af { nutag_af_any = SOA_AF_ANY, nutag_af_ip4_only = SOA_AF_IP4_ONLY, nutag_af_ip6_only = SOA_AF_IP6_ONLY, nutag_af_ip4_ip6 = SOA_AF_IP4_IP6, nutag_af_ip6_ip4 = SOA_AF_IP6_IP4 }; #define NUTAG_AF_ANY nutag_af_any #define NUTAG_AF_IP4_ONLY nutag_af_ip4_only #define NUTAG_AF_IP6_ONLY nutag_af_ip6_only #define NUTAG_AF_IP4_IP6 nutag_af_ip4_ip6 #define NUTAG_AF_IP6_IP4 nutag_af_ip6_ip4 #define NUTAG_MEDIA_ADDRESS(x) SOATAG_ADDRESS((x)) #define NUTAG_MEDIA_ADDRESS_REF(x) SOATAG_ADDRESS_REF((x)) #define NUTAG_HOLD(x) SOATAG_HOLD((x) ? "*" : NULL) #define NUTAG_ACTIVE_AUDIO(x) SOATAG_ACTIVE_AUDIO((x)) #define NUTAG_ACTIVE_AUDIO_REF(x) SOATAG_ACTIVE_AUDIO_REF((x)) #define NUTAG_ACTIVE_VIDEO(x) SOATAG_ACTIVE_VIDEO((x)) #define NUTAG_ACTIVE_VIDEO_REF(x) SOATAG_ACTIVE_VIDEO_REF((x)) #define NUTAG_ACTIVE_IMAGE(x) SOATAG_ACTIVE_IMAGE((x)) #define NUTAG_ACTIVE_IMAGE_REF(x) SOATAG_ACTIVE_IMAGE_REF((x)) #define NUTAG_ACTIVE_CHAT(x) SOATAG_ACTIVE_CHAT((x)) #define NUTAG_ACTIVE_CHAT_REF(x) SOATAG_ACTIVE_CHAT_REF((x)) enum { nua_active_rejected = SOA_ACTIVE_REJECTED, nua_active_disabled = SOA_ACTIVE_DISABLED, nua_active_inactive = SOA_ACTIVE_INACTIVE, nua_active_sendonly = SOA_ACTIVE_SENDONLY, nua_active_recvonly = SOA_ACTIVE_RECVONLY, nua_active_sendrecv = SOA_ACTIVE_SENDRECV }; #define NUTAG_SRTP_ENABLE(x) SOATAG_SRTP_ENABLE((x)) #define NUTAG_SRTP_ENABLE_REF(x) SOATAG_SRTP_ENABLE_REF((x)) #define NUTAG_SRTP_CONFIDENTIALITY(x) SOATAG_SRTP_CONFIDENTIALITY((x)) #define NUTAG_SRTP_CONFIDENTIALITY_REF(x) SOATAG_SRTP_CONFIDENTIALITY_REF((x)) #define NUTAG_SRTP_INTEGRITY_PROTECTION(x) SOATAG_SRTP_INTEGRITY((x)) #define NUTAG_SRTP_INTEGRITY_PROTECTION_REF(x) SOATAG_SRTP_INTEGRITY_REF((x)) SOFIA_END_DECLS #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/000077500000000000000000000000001223300710500203405ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/ChangeLog000066400000000000000000000027071223300710500221200ustar00rootroot000000000000002005-10-17 Pekka Pessi * In sdp_rtpmap_cmp() use default value "1" for rm_param. M ./libsofia-sip-ua/sdp/sdp.c -3 +30 2005-10-03 Pekka Pessi * Fixed documentation of sdp_parsing_error() and sdp_parsing_error() contradicting with implementation. Use sdp_session() and sdp_message() to check for error. M ./libsofia-sip-ua/sdp/sdp.docs -2 +8 2005-10-03 Kai Vehmanen * sdp_print.c (sdp_printing_error): Fixed return for success to be NULL as defined in function documentation. 2005-09-29 Pekka Pessi * Added SDPTAG_TYPEDEF(). M ./libsofia-sip-ua/sdp/sdp_tag.h +3 * Not including . M ./libsofia-sip-ua/sdp/sdp_tag.h -7 +12 2005-09-28 Pekka Pessi * Handle mode attributes (inactive, sendonly, recvonly, sendrecv). M ./libsofia-sip-ua/sdp/sdp.h -1 +5 M ./libsofia-sip-ua/sdp/sdp_parse.c -12 +44 M ./libsofia-sip-ua/sdp/sdp_print.c -5 +54 * Setting mode flags on config sdp, too. M ./libsofia-sip-ua/sdp/sdp_parse.c -3 +3 * Added sdp_media_match*(), sdp_media_count*() M ./libsofia-sip-ua/sdp/sdp.c +91 M ./libsofia-sip-ua/sdp/sdp.h +20 * Added sdp_list_cmp() and sdp_rtpmap_cmp(). M ./libsofia-sip-ua/sdp/sdp.c -9 +54 M ./libsofia-sip-ua/sdp/sdp.h +6 2005-07-18 Kai Vehmanen * Initial import of the module to Sofia-SIP tree. sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/Doxyfile.in000066400000000000000000000004711223300710500224550ustar00rootroot00000000000000PROJECT_NAME = "sdp" OUTPUT_DIRECTORY = ../docs/html/sdp INPUT = @srcdir@/sdp.docs @srcdir@/sofia-sip @srcdir@ . @INCLUDE_PATH = . @srcdir@ @INCLUDE = ../docs/Doxyfile.conf TAGFILES += ../docs/su.doxytags=../su GENERATE_TAGFILE = ../docs/sdp.doxytags ALIASES += sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/Makefile.am000066400000000000000000000030151223300710500223730ustar00rootroot00000000000000# # Makefile.am for sdp module # # Copyright (C) 2005,2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # ---------------------------------------------------------------------- # Header paths INCLUDES = -I$(srcdir)/../su -I../su # ---------------------------------------------------------------------- # Build targets noinst_LTLIBRARIES = libsdp.la check_PROGRAMS = torture_sdp test_sdp dist_noinst_SCRIPTS = run_test_sdp TESTS = torture_sdp run_test_sdp BUILT_SOURCES = sdp_tag_ref.c # ---------------------------------------------------------------------- # Rules for building the targets nobase_include_sofia_HEADERS = \ sofia-sip/sdp.h sofia-sip/sdp_tag.h libsdp_la_SOURCES = sdp.c sdp_parse.c sdp_print.c \ sdp_tag.c sdp_tag_ref.c COVERAGE_INPUT = $(libsdp_la_SOURCES) $(include_sofia_HEADERS) LDADD = libsdp.la \ ../su/libsu.la test_sdp_LDFLAGS = -static torture_sdp_LDFLAGS = -static # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST = sdp.docs $(BUILT_SOURCES) \ tests/message-1.sdp \ tests/message-2.sdp \ tests/message-3.sdp \ tests/message-4.sdp \ tests/message-5.sdp \ tests/message-6.sdp \ tests/message-7.sdp \ tests/message-8.sdp \ tests/message-9.sdp \ tests/message-10.sdp \ tests/message-11.sdp # ---------------------------------------------------------------------- # Sofia specific rules include $(top_srcdir)/rules/sofia.am sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/Makefile.in000066400000000000000000001354201223300710500224120ustar00rootroot00000000000000# Makefile.in generated by automake 1.14 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 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 sdp module # # Copyright (C) 2005,2006 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # ---------------------------------------------------------------------- # Header paths # common Makefile targets for libsofia-sip-ua(-glib) modules # ---------------------------------------------------------- # # run tests with valgrind # # Copyright (C) 2007 Nokia Corporation. # 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 file contains free software from Makefile.in by the Free Software # Foundation: # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 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. # # Generate lcov output # # # Copyright (C) 2007 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # # Silent compilation w/ Automake 1.9 or 1.10 # ---------------------------------------------------------- # Automake 1.9.6 is not clever enough to override suffix rules within if # if SOFIA_COMPILE_SILENT VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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@ check_PROGRAMS = torture_sdp$(EXEEXT) test_sdp$(EXEEXT) TESTS = torture_sdp$(EXEEXT) run_test_sdp DIST_COMMON = $(top_srcdir)/rules/sofia.am \ $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am \ $(top_srcdir)/rules/silent.am $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(srcdir)/Doxyfile.in \ $(dist_noinst_SCRIPTS) $(top_srcdir)/depcomp \ $(nobase_include_sofia_HEADERS) $(top_srcdir)/test-driver \ ChangeLog README # Use with --enable-ndebug @NDEBUG_TRUE@am__append_1 = -DNDEBUG @HAVE_GENPNG_TRUE@@HAVE_LCOV_TRUE@am__append_2 = --frames @HAVE_LCOV_TRUE@am__append_3 = lcov lcov-report lcov-rerun clean-lcov covcheck uncovered subdir = libsofia-sip-ua/sdp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(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)/m4/sac-coverage.m4 \ $(top_srcdir)/m4/sac-general.m4 \ $(top_srcdir)/m4/sac-openssl.m4 \ $(top_srcdir)/m4/sac-pkg-config.m4 $(top_srcdir)/m4/sac-su2.m4 \ $(top_srcdir)/m4/sac-tport.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libsofia-sip-ua/su/sofia-sip/su_configure.h CONFIG_CLEAN_FILES = Doxyfile CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libsdp_la_LIBADD = am_libsdp_la_OBJECTS = sdp.lo sdp_parse.lo sdp_print.lo sdp_tag.lo \ sdp_tag_ref.lo libsdp_la_OBJECTS = $(am_libsdp_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_sdp_SOURCES = test_sdp.c test_sdp_OBJECTS = test_sdp.$(OBJEXT) test_sdp_LDADD = $(LDADD) am__DEPENDENCIES_1 = test_sdp_DEPENDENCIES = libsdp.la ../su/libsu.la $(am__DEPENDENCIES_1) test_sdp_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(test_sdp_LDFLAGS) $(LDFLAGS) -o $@ torture_sdp_SOURCES = torture_sdp.c torture_sdp_OBJECTS = torture_sdp.$(OBJEXT) torture_sdp_LDADD = $(LDADD) torture_sdp_DEPENDENCIES = libsdp.la ../su/libsu.la \ $(am__DEPENDENCIES_1) torture_sdp_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(torture_sdp_LDFLAGS) $(LDFLAGS) -o $@ SCRIPTS = $(dist_noinst_SCRIPTS) 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) -I$(top_builddir)/libsofia-sip-ua/su/sofia-sip depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f 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) 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 = $(libsdp_la_SOURCES) test_sdp.c torture_sdp.c DIST_SOURCES = $(libsdp_la_SOURCES) test_sdp.c torture_sdp.c 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)$(include_sofiadir)" HEADERS = $(nobase_include_sofia_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)` 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=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ 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_DRIVER = $(SHELL) $(top_srcdir)/test-driver 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) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CHECK_CFLAGS = @CHECK_CFLAGS@ CHECK_LIBS = @CHECK_LIBS@ COVERAGE_FLAGS = @COVERAGE_FLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CWFLAG = @CWFLAG@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV = @GCOV@ GENHTML = @GENHTML@ GENPNG = @GENPNG@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GLIB_VERSION = @GLIB_VERSION@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVER_SOFIA_SIP_UA_AGE = @LIBVER_SOFIA_SIP_UA_AGE@ LIBVER_SOFIA_SIP_UA_CUR = @LIBVER_SOFIA_SIP_UA_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_AGE = @LIBVER_SOFIA_SIP_UA_GLIB_AGE@ LIBVER_SOFIA_SIP_UA_GLIB_CUR = @LIBVER_SOFIA_SIP_UA_GLIB_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_REV = @LIBVER_SOFIA_SIP_UA_GLIB_REV@ LIBVER_SOFIA_SIP_UA_GLIB_SOVER = @LIBVER_SOFIA_SIP_UA_GLIB_SOVER@ LIBVER_SOFIA_SIP_UA_REV = @LIBVER_SOFIA_SIP_UA_REV@ LIBVER_SOFIA_SIP_UA_SOVER = @LIBVER_SOFIA_SIP_UA_SOVER@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MINGW_ENVIRONMENT = @MINGW_ENVIRONMENT@ MKDIR_P = @MKDIR_P@ MOSTLYCLEANFILES = @MOSTLYCLEANFILES@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ RANLIB = @RANLIB@ REPLACE_LIBADD = @REPLACE_LIBADD@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ SOFIA_GLIB_CFLAGS = @SOFIA_GLIB_CFLAGS@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ SOFIA_PLAT_CFLAGS = @SOFIA_PLAT_CFLAGS@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ VERSION = @VERSION@ VER_LIBSOFIA_SIP_UA_MAJOR_MINOR = @VER_LIBSOFIA_SIP_UA_MAJOR_MINOR@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ include_sofiadir = @include_sofiadir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ openssl_CFLAGS = @openssl_CFLAGS@ openssl_LIBS = @openssl_LIBS@ 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@ INCLUDES = -I$(srcdir)/../su -I../su # ---------------------------------------------------------------------- # Build targets noinst_LTLIBRARIES = libsdp.la dist_noinst_SCRIPTS = run_test_sdp BUILT_SOURCES = sdp_tag_ref.c # ---------------------------------------------------------------------- # Rules for building the targets nobase_include_sofia_HEADERS = \ sofia-sip/sdp.h sofia-sip/sdp_tag.h libsdp_la_SOURCES = sdp.c sdp_parse.c sdp_print.c \ sdp_tag.c sdp_tag_ref.c COVERAGE_INPUT = $(libsdp_la_SOURCES) $(include_sofia_HEADERS) LDADD = libsdp.la ../su/libsu.la $(openssl_LIBS) test_sdp_LDFLAGS = -static torture_sdp_LDFLAGS = -static # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST = sdp.docs $(BUILT_SOURCES) \ tests/message-1.sdp \ tests/message-2.sdp \ tests/message-3.sdp \ tests/message-4.sdp \ tests/message-5.sdp \ tests/message-6.sdp \ tests/message-7.sdp \ tests/message-8.sdp \ tests/message-9.sdp \ tests/message-10.sdp \ tests/message-11.sdp sofiasrcdir = ${top_srcdir}/libsofia-sip-ua sofiabuilddir = ${top_builddir}/libsofia-sip-ua AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(SOFIA_CFLAGS) \ $(openssl_CFLAGS) $(SOFIA_PLAT_CFLAGS) $(am__append_1) SOFIA_COVERAGE = $(COVERAGE_FLAGS) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files TAG_AWK = ${sofiasrcdir}/su/tag_dll.awk SUFFIXES = _tag_ref.c _tag.c INTERNAL_INCLUDES = \ -I${sofiasrcdir}/features -I${sofiabuilddir}/features \ -I${sofiasrcdir}/ipt -I${sofiabuilddir}/ipt \ -I${sofiasrcdir}/iptsec -I${sofiabuilddir}/iptsec \ -I${sofiasrcdir}/bnf -I${sofiabuilddir}/bnf \ -I${sofiasrcdir}/http -I${sofiabuilddir}/http \ -I${sofiasrcdir}/msg -I${sofiabuilddir}/msg \ -I${sofiasrcdir}/nth -I${sofiabuilddir}/nth \ -I${sofiasrcdir}/nta -I${sofiabuilddir}/nta \ -I${sofiasrcdir}/nea -I${sofiabuilddir}/nea \ -I${sofiasrcdir}/nua -I${sofiabuilddir}/nua \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sdp -I${sofiabuilddir}/sdp \ -I${sofiasrcdir}/sip -I${sofiabuilddir}/sip \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sresolv -I${sofiabuilddir}/sresolv \ -I${sofiasrcdir}/tport -I${sofiabuilddir}/tport \ -I${sofiasrcdir}/stun -I${sofiabuilddir}/stun \ -I${sofiasrcdir}/url -I${sofiabuilddir}/url \ -I${sofiasrcdir}/su -I${sofiabuilddir}/su PHONY = built-sources clean-built-sources $(am__append_3) VALGRIND = valgrind VALGRINDFLAGS = --tool=memcheck # Scripts @HAVE_LCOV_TRUE@LCOV_UNCOVERED = ${top_srcdir}/scripts/uncovered @HAVE_LCOV_TRUE@LCOV_REPORT = ${top_srcdir}/scripts/lcov-report # Report directory @HAVE_LCOV_TRUE@lcovdir = ${top_builddir}/lcov # Options @HAVE_LCOV_TRUE@GENHTML_OPTIONS = --show-details --legend \ @HAVE_LCOV_TRUE@ $(am__append_2) # Fancy shell command that expands to directory relative to top_builddir @HAVE_LCOV_TRUE@expand_subdir = `pwd|sed "s'\`cd ${top_builddir};pwd\`''"` SOFIA_SILENT = @ LIBTOOL_FLAGS = --silent # From Automake 1.9.6 - LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(LIBTOOL_FLAGS) \ $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) LINK = ${SOFIA_SILENT}test "${SOFIA_SILENT}" != @ || echo ' LINK $@'; \ $(LIBTOOL) --tag=CC --mode=link $(LIBTOOL_FLAGS) \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: _tag_ref.c _tag.c .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.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 libsofia-sip-ua/sdp/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu libsofia-sip-ua/sdp/Makefile .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.am: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): Doxyfile: $(top_builddir)/config.status $(srcdir)/Doxyfile.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ 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}; \ } libsdp.la: $(libsdp_la_OBJECTS) $(libsdp_la_DEPENDENCIES) $(EXTRA_libsdp_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libsdp_la_OBJECTS) $(libsdp_la_LIBADD) $(LIBS) 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_sdp$(EXEEXT): $(test_sdp_OBJECTS) $(test_sdp_DEPENDENCIES) $(EXTRA_test_sdp_DEPENDENCIES) @rm -f test_sdp$(EXEEXT) $(AM_V_CCLD)$(test_sdp_LINK) $(test_sdp_OBJECTS) $(test_sdp_LDADD) $(LIBS) torture_sdp$(EXEEXT): $(torture_sdp_OBJECTS) $(torture_sdp_DEPENDENCIES) $(EXTRA_torture_sdp_DEPENDENCIES) @rm -f torture_sdp$(EXEEXT) $(AM_V_CCLD)$(torture_sdp_LINK) $(torture_sdp_OBJECTS) $(torture_sdp_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sdp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sdp_parse.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sdp_print.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sdp_tag.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sdp_tag_ref.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_sdp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/torture_sdp.Po@am__quote@ .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.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) '$<'` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-nobase_include_sofiaHEADERS: $(nobase_include_sofia_HEADERS) @$(NORMAL_INSTALL) @list='$(nobase_include_sofia_HEADERS)'; test -n "$(include_sofiadir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(include_sofiadir)'"; \ $(MKDIR_P) "$(DESTDIR)$(include_sofiadir)" || exit 1; \ fi; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo " $(MKDIR_P) '$(DESTDIR)$(include_sofiadir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(include_sofiadir)/$$dir"; }; \ echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(include_sofiadir)/$$dir'"; \ $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(include_sofiadir)/$$dir" || exit $$?; }; \ done uninstall-nobase_include_sofiaHEADERS: @$(NORMAL_UNINSTALL) @list='$(nobase_include_sofia_HEADERS)'; test -n "$(include_sofiadir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ dir='$(DESTDIR)$(include_sofiadir)'; $(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; \ else \ 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 $(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 $$? torture_sdp.log: torture_sdp$(EXEEXT) @p='torture_sdp$(EXEEXT)'; \ b='torture_sdp'; \ $(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) run_test_sdp.log: run_test_sdp @p='run_test_sdp'; \ b='run_test_sdp'; \ $(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: $(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: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LTLIBRARIES) $(SCRIPTS) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(include_sofiadir)"; 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: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) -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: 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) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) 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) @HAVE_LCOV_FALSE@clean-local: clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libtool clean-local \ clean-noinstLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -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-nobase_include_sofiaHEADERS 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 -rf ./$(DEPDIR) -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-nobase_include_sofiaHEADERS .MAKE: all check check-am install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libtool clean-local \ 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-nobase_include_sofiaHEADERS 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 \ uninstall-nobase_include_sofiaHEADERS built-sources: $(BUILT_SOURCES) clean-built-sources: -rm -rf $(BUILT_SOURCES) $(BUILT_SOURCES:%=$(srcdir)/%) *_tag_ref.c: $(TAG_AWK) _tag.c_tag_ref.c: $(AWK) -f $(TAG_AWK) NODLL=1 $(TAG_DLL_FLAGS) REF=$@ $< ../bnf/libbnf.la ../http/libhttp.la ../ipt/libipt.la ../iptsec/libiptsec.la \ ../msg/libmsg.la ../nea/libnea.la ../nta/libnta.la ../nth/libnth.la \ ../nua/libnua.la ../sdp/libsdp.la ../sip/libsip.la ../soa/libsoa.la \ ../sresolv/libsresolv.la ../stun/libstun.la ../su/libsu.la \ ../tport/libtport.la ../url/liburl.la: cd $(@D) && $(MAKE) $(@F) checklib: $(noinst_LTLIBRARIES) $(check_LTLIBRARIES) valcheck: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) valcheck-am valcheck-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS # Run tests with valgrind in valcheck-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ list='$(TESTS)'; \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ if case $$tst in \ run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ $${dir}$$tst ;; \ esac ; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ echo "XPASS: $$tst"; \ ;; \ *) \ echo "PASS: $$tst"; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xfail=`expr $$xfail + 1`; \ echo "XFAIL: $$tst"; \ ;; \ *) \ failed=`expr $$failed + 1`; \ echo "FAIL: $$tst"; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ echo "SKIP: $$tst"; \ fi; \ done; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="All $$all tests passed"; \ else \ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all tests failed"; \ else \ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ skipped="($$skip tests were not run)"; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ report=""; \ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ report="Please report to $(PACKAGE_BUGREPORT)"; \ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ echo "$$dashes"; \ echo "$$banner"; \ test -z "$$skipped" || echo "$$skipped"; \ test -z "$$report" || echo "$$report"; \ echo "$$dashes"; \ test "$$failed" -eq 0; \ else :; fi # # Generate pretty coverage report (unless it has been already done) # @HAVE_LCOV_TRUE@lcov: @HAVE_LCOV_TRUE@ @-test -r ${lcovdir}${expand_subdir}/lcov.info \ @HAVE_LCOV_TRUE@ || make lcov-report # Generate pretty coverage report based on current coverage data @HAVE_LCOV_TRUE@lcov-report: @HAVE_LCOV_TRUE@ sub=${expand_subdir} odir=${lcovdir}$$sub ; \ @HAVE_LCOV_TRUE@ rm -rf $$odir ; mkdir -p $$odir && \ @HAVE_LCOV_TRUE@ ${LCOV_REPORT} ${GENHTML_OPTIONS} \ @HAVE_LCOV_TRUE@ --title "${PACKAGE_NAME}-${PACKAGE_VERSION}$$sub" \ @HAVE_LCOV_TRUE@ --srcdir=${srcdir} -o $$odir # Rerun checks before generating report @HAVE_LCOV_TRUE@lcov-rerun: clean-lcov @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) lcov-report # Show all uncovered lines as errors @HAVE_LCOV_TRUE@uncovered: @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} # Run check in current dir and show all uncovered lines as errors @HAVE_LCOV_TRUE@covcheck: @HAVE_LCOV_TRUE@ -find . -name "*.gcda" | xargs rm -rf @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} @HAVE_LCOV_TRUE@clean-local:: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true @HAVE_LCOV_TRUE@clean-lcov: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true # Rules from depend2.am (GENERIC = TRUE, SUBDIROBJ = FALSE, %FASTDEP% = am_fastdepCC) silenced. .c.o: @test "${SOFIA_SILENT}" != @ || echo ' COMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(COMPILE) -c -o $@ $< .c.lo: @test "${SOFIA_SILENT}" != @ || echo ' LTCOMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(LTCOMPILE) -c -o $@ $< # endif # ---------------------------------------------------------------------- # Sofia specific rules # 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: sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/README000066400000000000000000000005501223300710500212200ustar00rootroot00000000000000SDP Parser and Printer ====================== This directory contains SDP parser and printer code. Parser takes an message and returns a corresponding C structure. Printer takes a C structure and returns a SDP message. There is an incomplete documentation in sdp.html on usage of parser and printer. Please refer to RFC 2327 for further information. sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/errata000066400000000000000000000006601223300710500215430ustar00rootroot00000000000000RFC 2327 omissions and errors: * "z=" omitted from zone-adjustments * protocol on media-field is restricted to alpha-numeric, but example (RTP/AVP!) contains also "/" * bwtype is restricted to alpha-numeric, but the RFC text discusses extensions like b=x-y:100 * att-field is restricted to alpha-numeric, but the RFC text discusses extensions like a=x-nokia-foo * The BNF defintions "key-data" and "safe" are incomplete. sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/run_test_sdp000077500000000000000000000006341223300710500230020ustar00rootroot00000000000000#! /bin/sh # # Run the sdp tests # # usage: run_test_sdp [test_program] [test-directory] # test_sdp="${1:-./test_sdp}" sdp_path=`dirname $0` tests="${2:-${sdp_path}/tests}" if test -r $tests/message-1.sdp ; then for n in 1 2 3 4 5 6 7 8 9 10 11; do echo -n "$n: " "$test_sdp" < "$tests/message-$n.sdp" && echo OK done else echo "sdp run-tests: no tests found in $tests, skipping." exit 77 fi sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/sdp.bnf000066400000000000000000000156131223300710500216230ustar00rootroot00000000000000 ; BNF from RFC 2327 announcement = proto-version origin-field session-name-field information-field uri-field email-fields phone-fields connection-field bandwidth-fields time-fields key-field attribute-fields media-descriptions proto-version = "v=" 1*DIGIT CRLF ;this memo describes version 0 origin-field = "o=" username space sess-id space sess-version space nettype space addrtype space addr CRLF session-name-field = "s=" text CRLF information-field = ["i=" text CRLF] uri-field = ["u=" uri CRLF] email-fields = *("e=" email-address CRLF) phone-fields = *("p=" phone-number CRLF) connection-field = ["c=" nettype space addrtype space connection-address CRLF] ;a connection field must be present ;in every media description or at the ;session-level bandwidth-fields = *("b=" bwtype ":" bandwidth CRLF) time-fields = 1*( "t=" start-time space stop-time *(CRLF repeat-fields) CRLF) [zone-adjustments CRLF] repeat-fields = "r=" repeat-interval space typed-time 1*(space typed-time) zone-adjustments = "z=" time space ["-"] typed-time *(space time space ["-"] typed-time) key-field = ["k=" key-type CRLF] key-type = "prompt" | "clear:" key-data | "base64:" key-data | "uri:" uri key-data = email-safe | "~" | " attribute-fields = *("a=" attribute CRLF) media-descriptions = *( media-field information-field *(connection-field) bandwidth-fields key-field attribute-fields ) media-field = "m=" media space port ["/" integer] space proto 1*(space fmt) CRLF media = 1*(alpha-numeric) ;typically "audio", "video", "application" ;or "data" fmt = 1*(alpha-numeric) ;typically an RTP payload type for audio ;and video media proto = 1*(alpha-numeric | "/") ; PPe ;typically "RTP/AVP" or "udp" for IP4 port = 1*(DIGIT) ;should in the range "1024" to "65535" inclusive ;for UDP based media attribute = (att-field ":" att-value) | att-field att-field = 1*(alpha-numeric) att-value = byte-string sess-id = 1*(DIGIT) ;should be unique for this originating username/host sess-version = 1*(DIGIT) ;0 is a new session connection-address = multicast-address | addr multicast-address = 3*(decimal-uchar ".") decimal-uchar "/" ttl [ "/" integer ] ;multicast addresses may be in the range ;224.0.0.0 to 239.255.255.255 ttl = decimal-uchar start-time = time | "0" stop-time = time | "0" time = POS-DIGIT 9*(DIGIT) ;sufficient for 2 more centuries repeat-interval = typed-time typed-time = 1*(DIGIT) [fixed-len-time-unit] fixed-len-time-unit = "d" | "h" | "m" | "s" bwtype = 1*(alpha-numeric) bandwidth = 1*(DIGIT) username = safe ;pretty wide definition, but doesn't include space email-address = email | email "(" email-safe ")" | email-safe "<" email ">" email = ;defined in RFC822 uri= ;defined in RFC1630 phone-number = phone | phone "(" email-safe ")" | email-safe "<" phone ">" phone = "+" POS-DIGIT 1*(space | "-" | DIGIT) ;there must be a space or hyphen between the ;international code and the rest of the number. nettype = "IN" ;list to be extended addrtype = "IP4" | "IP6" ;list to be extended addr = FQDN | unicast-address FQDN = 4*(alpha-numeric|"-"|".") ;fully qualified domain name as specified in RFC1035 unicast-address = IP4-address | IP6-address IP4-address = b1 "." decimal-uchar "." decimal-uchar "." b4 b1 = decimal-uchar ;less than "224"; not "0" or "127" b4 = decimal-uchar ;not "0" IP6-address = ;to be defined text = byte-string ;default is to interpret this as IS0-10646 UTF8 ;ISO 8859-1 requires a "a=charset:ISO-8859-1" ;session-level attribute to be used byte-string = 1*(0x01..0x09|0x0b|0x0c|0x0e..0xff) ;any byte except NUL, CR or LF decimal-uchar = DIGIT | POS-DIGIT DIGIT | ("1" 2*(DIGIT)) | ("2" ("0"|"1"|"2"|"3"|"4") DIGIT) | ("2" "5" ("0"|"1"|"2"|"3"|"4"|"5")) integer = POS-DIGIT *(DIGIT) alpha-numeric = ALPHA | DIGIT DIGIT = "0" | POS-DIGIT POS-DIGIT = "1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9" ALPHA = "a"|"b"|"c"|"d"|"e"|"f"|"g"|"h"|"i"|"j"|"k"| "l"|"m"|"n"|"o "|"p"|"q"|"r"|"s"|"t"|"u"|"v"| "w"|"x"|"y"|"z"|"A"|"B"|"C "|"D"|"E"|"F"|"G"| "H"|"I"|"J"|"K"|"L"|"M"|"N"|"O"|"P"|" Q"|"R"| "S"|"T"|"U"|"V"|"W"|"X"|"Y"|"Z" email-safe = safe | space | tab safe = alpha-numeric | "'" | "'" | "-" | "." | "/" | ":" | "?" | """ | "#" | "$" | "&" | "*" | ";" | "=" | "@" | "[" | "]" | "^" | "_" | "`" | "{" | "|" | "}" | "+" | "~" | " space = %d32 tab = %d9 CRLF = %d13.10 sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/sdp.c000066400000000000000000001367451223300710500213120ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE sdp.c Simple SDP interface. * * @author Pekka Pessi * @author Kai Vehmanen * * @date Created: Fri Feb 18 10:25:08 2000 ppessi */ #include "config.h" #include #include #include #include #include #include #include #include #include #include "sofia-sip/sdp.h" struct align { void *_a; char _b; }; #define ALIGN(v, n) ((n - (intptr_t)(v)) & (n - 1)) #define STRUCT_ALIGN_ (sizeof(struct align) - offsetof(struct align, _b)) #define STRUCT_ALIGN(v) ALIGN(v, sizeof(void *)) #define ASSERT_STRUCT_ALIGN(p) \ (STRUCT_ALIGN(p) ? (void)assert(!"STRUCT_ALIGNED(" #p ")") : (void)0) const unsigned sdp_struct_align_ = sizeof(void *) - STRUCT_ALIGN_; #define STR_XTRA(rv, s) ((s) ? rv += strlen((s)) + 1 : 0) #define PTR_XTRA(rv, p, f) \ ((p) ? (rv += STRUCT_ALIGN(rv) + f(p)) : 0) #define LST_XTRA(rv, l, f) \ ((l) ? (rv += STRUCT_ALIGN(rv) + list_xtra_all((xtra_f*)f, l)) : 0) #define STRUCT_DUP(p, dst, src) \ ASSERT_STRUCT_ALIGN(p); \ ((*(int*)(src) >= (int)sizeof(*src) \ ? (dst = memcpy((p), (src), sizeof(*src))) \ : (dst = memcpy((p), (src), *(int*)(src))), \ memset((p)+*(int*)(src), 0, sizeof(*src) - *(int*)(src))), \ ((p) += sizeof(*src))) #define STRUCT_DUP2(p, dst, src) \ ASSERT_STRUCT_ALIGN(p); assert(*(int*)(src) >= (int)sizeof(*src)); \ (dst = memcpy((p), (src), *(int*)(src)), ((p) += *(int*)(src))) #define STR_DUP(p, dst, src, m) \ ((src->m) ? ((dst->m) = strcpy((p), (src->m)), (p) += strlen((p)) + 1) \ : ((dst->m) = 0)) #define PTR_DUP(p, dst, src, m, dup) \ ((dst->m) = (src->m)?((p += STRUCT_ALIGN(p)), ((dup)(&(p), (src->m)))): 0) #define LST_DUP(p, dst, src, m, dup) \ ((dst->m) = (src->m)?((p += STRUCT_ALIGN(p)),\ list_dup_all((dup_f*)(dup), &(p), src->m)) : 0) #define MED_XTRA_EX(rv, l, c) \ ((l) ? (rv += STRUCT_ALIGN(rv) + media_xtra_ex(l, c)) : 0) #define MED_DUP_EX(p, dst, src, m, dst_c, src_c) \ ((dst->m) = (src->m)?((p += STRUCT_ALIGN(p)),\ media_dup_all(&(p), src->m, dst, dst_c, src_c)) : 0) #define MED_XTRA_ALL(rv, m) \ ((m) ? (rv += STRUCT_ALIGN(rv) + media_xtra_all(m)) : 0) #define MED_DUP_ALL(p, dst, src, m) \ ((dst->m) = (src->m)?((p += STRUCT_ALIGN(p)),\ media_dup_all(&(p), src->m, dst)) : 0) typedef size_t xtra_f(void const *); typedef void *dup_f(char **bb, void const *src); static size_t list_xtra_all(xtra_f *xtra, void const *v); static void *list_dup_all(dup_f *dup, char **bb, void const *vsrc); static size_t session_xtra(sdp_session_t const *o); static sdp_session_t *session_dup(char **pp, sdp_session_t const *o); static size_t origin_xtra(sdp_origin_t const *o); static sdp_origin_t *origin_dup(char **pp, sdp_origin_t const *o); static size_t connection_xtra(sdp_connection_t const *o); static sdp_connection_t *connection_dup(char **pp, sdp_connection_t const *o); static size_t bandwidth_xtra(sdp_bandwidth_t const *o); static sdp_bandwidth_t *bandwidth_dup(char **pp, sdp_bandwidth_t const *o); static size_t time_xtra(sdp_time_t const *o); static sdp_time_t *time_dup(char **pp, sdp_time_t const *o); static size_t repeat_xtra(sdp_repeat_t const *o); static sdp_repeat_t *repeat_dup(char **pp, sdp_repeat_t const *o); static size_t zone_xtra(sdp_zone_t const *o); static sdp_zone_t *zone_dup(char **pp, sdp_zone_t const *o); static size_t key_xtra(sdp_key_t const *o); static sdp_key_t *key_dup(char **pp, sdp_key_t const *o); static size_t attribute_xtra(sdp_attribute_t const *o); static sdp_attribute_t *attribute_dup(char **pp, sdp_attribute_t const *o); static size_t list_xtra(sdp_list_t const *o); static sdp_list_t *list_dup(char **pp, sdp_list_t const *o); static size_t rtpmap_xtra(sdp_rtpmap_t const *o); static sdp_rtpmap_t *rtpmap_dup(char **pp, sdp_rtpmap_t const *o); static size_t media_xtra(sdp_media_t const *o); static sdp_media_t *media_dup(char **pp, sdp_media_t const *o, sdp_session_t *sdp); #ifdef nomore static size_t media_xtra_ex(sdp_media_t const *o, sdp_connection_t const *c); static sdp_media_t *media_dup_ex(char **pp, sdp_media_t const *o, sdp_session_t *sdp, sdp_connection_t *dst_c, sdp_connection_t const *src_c); #endif static size_t media_xtra_all(sdp_media_t const *o); static sdp_media_t *media_dup_all(char **pp, sdp_media_t const *o, sdp_session_t *sdp); /** Define a function body duplicating an SDP structure. */ #define SDP_DUP(type, name) \ sdp_##type##_t *rv; size_t size; char *p, *end; \ if (!name) return NULL; \ size = type##_xtra(name); \ p = su_alloc(h, size); end = p + size; \ rv = type##_dup(&p, name); \ assert(p == end); \ return rv; /** Define a function body duplicating a list of SDP structures. */ #define SDP_LIST_DUP(type, name) \ sdp_##type##_t *rv; size_t size; char *p, *end; \ if (!name) return NULL; \ size = list_xtra_all((xtra_f*)type##_xtra, name); \ rv = su_alloc(h, size); p = (char *)rv; end = p + size; \ list_dup_all((dup_f*)type##_dup, &p, name); \ assert(p == end); \ return rv; /**Duplicate an SDP origin description. * * The function sdp_origin_dup() duplicates (deeply copies) an SDP origin * description @a o allocating memory using memory @a home. * * @param h Memory home * @param o SDP origin description to be duplicated * * @note The duplicated structure is allocated using a single call to * su_alloc() and it can be freed with su_free(). * * @return * If successful, a pointer to newly allocated sdp_origin_t structure is * returned, otherwise NULL is returned. */ sdp_origin_t *sdp_origin_dup(su_home_t *h, sdp_origin_t const *o) { SDP_DUP(origin, o); } /**Duplicate an SDP connection description. * * The function sdp_connection_dup() duplicates (deeply copies) a list of * SDP connection description @a c allocating memory using memory @a home. * * @param h Memory home * @param c SDP connection description to be duplicated * * @note The duplicated list is allocated using a single call to * su_alloc() and it can be freed with su_free(). * * @return * If successful, a pointer to newly allocated sdp_connection_t structure is * returned, otherwise NULL is returned. */ sdp_connection_t *sdp_connection_dup(su_home_t *h, sdp_connection_t const *c) { SDP_LIST_DUP(connection, c); } /**Duplicate an SDP bandwidth description. * * The function sdp_bandwidth_dup() duplicates (deeply copies) a list of SDP * bandwidth descriptions @a b allocating memory using memory @a home. * * @param h Memory home * @param b SDP bandwidth description to be duplicated * * @note The duplicated list is allocated using a single call to * su_alloc() and it can be freed with su_free(). * * @return * If successful, a pointer to newly allocated sdp_bandwidth_t structure is * returned, otherwise NULL is returned. */ sdp_bandwidth_t *sdp_bandwidth_dup(su_home_t *h, sdp_bandwidth_t const *b) { SDP_LIST_DUP(bandwidth, b); } /**Duplicate an SDP time description. * * The function sdp_time_dup() duplicates (deeply copies) a list of SDP time * descriptions @a t allocating memory using memory @a home. * * @param h Memory home * @param t SDP time description to be duplicated * * @note The duplicated list is allocated using a single call to * su_alloc() and it can be freed with su_free(). * * @return * If successful, a pointer to newly allocated sdp_time_t structure is * returned, otherwise NULL is returned. */ sdp_time_t *sdp_time_dup(su_home_t *h, sdp_time_t const *t) { SDP_LIST_DUP(time, t); } /**Duplicate an SDP repeat description. * * The function sdp_repeat_dup() duplicates (deeply copies) an SDP repeat * description @a r allocating memory using memory @a home. * * @param h Memory home * @param r SDP repeat description to be duplicated * * @note The duplicated structure is allocated using a single call to * su_alloc() and it can be freed with su_free(). * * @return * If successful, a pointer to newly allocated sdp_repeat_t structure is * returned, otherwise NULL is returned. */ sdp_repeat_t *sdp_repeat_dup(su_home_t *h, sdp_repeat_t const *r) { SDP_DUP(repeat, r); } /**Duplicate an SDP zone description. * * The function sdp_zone_dup() duplicates (deeply copies) an SDP zone * description @a z allocating memory using memory @a home. * * @param h Memory home * @param z SDP zone description to be duplicated * * @note The duplicated structure is allocated using a single call to * su_alloc() and it can be freed with su_free(). * * @return * If successful, a pointer to newly allocated sdp_zone_t structure is * returned, otherwise NULL is returned. */ sdp_zone_t *sdp_zone_dup(su_home_t *h, sdp_zone_t const *z) { SDP_DUP(zone, z); } /**Duplicate an SDP key description. * * The function sdp_key_dup() duplicates (deeply copies) an SDP key * description @a k allocating memory using memory @a home. * * @param h Memory home * @param k SDP key description to be duplicated * * @note The duplicated structure is allocated using a single call to * su_alloc() and it can be freed with su_free(). * * @return * If successful, a pointer to newly allocated sdp_key_t structure is * returned, otherwise NULL is returned. */ sdp_key_t *sdp_key_dup(su_home_t *h, sdp_key_t const *k) { SDP_DUP(key, k); } /**Duplicate an SDP attribute list. * * The function sdp_attribute_dup() duplicates (deeply copies) an SDP * attribute list @a a allocating memory using memory @a home. * * @param h Memory home * @param a SDP attribute description to be duplicated * * @note The duplicated structure is allocated using a single call to * su_alloc() and it can be freed with su_free(). * * @return * If successful, a pointer to newly allocated sdp_attribute_t structure is * returned, otherwise NULL is returned. */ sdp_attribute_t *sdp_attribute_dup(su_home_t *h, sdp_attribute_t const *a) { SDP_LIST_DUP(attribute, a); } /**Duplicate an SDP list of text. * * The function sdp_list_dup() duplicates (deeply copies) an SDP text * list @a l allocating memory using memory @a home. * * @param h Memory home * @param l SDP list description to be duplicated * * @note The duplicated structure is allocated using a single call to * su_alloc() and it can be freed with su_free(). * * @return * If successful, a pointer to newly allocated sdp_list_t structure is * returned, otherwise NULL is returned. */ sdp_list_t *sdp_list_dup(su_home_t *h, sdp_list_t const *l) { SDP_LIST_DUP(list, l); } /**Duplicate an SDP rtpmap list. * * The function sdp_rtpmap_dup() duplicates (deeply copies) an SDP rtpmap * list @a rm allocating memory using memory @a home. * * @param h Memory home * @param rm SDP rtpmap description to be duplicated * * @note The duplicated structure is allocated using a single call to * su_alloc() and it can be freed with su_free(). * * @return * If successful, a pointer to newly allocated sdp_rtpmap_t structure is * returned, otherwise NULL is returned. */ sdp_rtpmap_t *sdp_rtpmap_dup(su_home_t *h, sdp_rtpmap_t const *rm) { SDP_LIST_DUP(rtpmap, rm); } /**Duplicate an SDP media description. * * The function sdp_media_dup() duplicates (deeply copies) an SDP media * description @a m allocating memory using memory @a home. * * @param h Memory home * @param m SDP media description to be duplicated * @param sdp SDP session description to which the newly allocated * media description is linked * * @note The duplicated structure is allocated using a single call to * su_alloc() and it can be freed with su_free(). * * @return * If successful, a pointer to newly allocated sdp_media_t structure is * returned, otherwise NULL is returned. */ sdp_media_t *sdp_media_dup(su_home_t *h, sdp_media_t const *m, sdp_session_t *sdp) { sdp_media_t *rv; size_t size; char *p, *end; size = media_xtra(m); p = su_alloc(h, size); end = p + size; rv = media_dup(&p, m, sdp); assert(p == end); return rv; } /**Duplicate an SDP media description. * * The function sdp_media_dup_all() duplicates (deeply copies) a list of SDP * media descriptions @a m allocating memory using memory @a home. * * @param h Memory home * @param m list of SDP media descriptions to be duplicated * @param sdp SDP session description to which the newly allocated * media descriptions are linked * * @note The duplicated list is allocated using a single call to * su_alloc() and it can be freed with su_free(). * * @return * If successful, a pointer to a newly allocated list of sdp_media_t * structures is returned, otherwise NULL is returned. */ sdp_media_t *sdp_media_dup_all(su_home_t *h, sdp_media_t const *m, sdp_session_t *sdp) { sdp_media_t *rv; size_t size; char *p, *end; size = media_xtra_all(m); p = su_alloc(h, size); end = p + size; rv = media_dup_all(&p, m, sdp); assert(p == end); return rv; } #ifdef nomore /* really deprecated */ /**Duplicate media description with common address. * * This function is provided in order to avoid duplicate @c c= lines. If * the @c c= line in media description equals to @a src_c, it is not * duplicated but replaced with @a dst_c instead. * * @param home Memory home * @param src SDP media description to be duplicated * @param sdp SDP session description to which the newly allocated * media description is linked * @param dst_c Connection description used instead of duplicate of @a src_c. * @param src_c Connection description not to be duplicated * @return * If successful, a pointer to newly allocated sdp_media_t structure is * returned, otherwise NULL is returned. * * @deprecated * This function is deprecated. Use sdp_media_dup() instead. */ sdp_media_t *sdp_media_dup_ex(su_home_t *home, sdp_media_t const *src, sdp_session_t *sdp, sdp_connection_t *dst_c, sdp_connection_t const *src_c) { sdp_media_t *rv; size_t size; char *p, *end; size = media_xtra_all(src, src_c); p = su_alloc(home, size); end = p + size; rv = media_dup_all(&p, src, sdp, dst_c, src_c); assert(p == end); return rv; } #endif /* ---------------------------------------------------------------------- */ static size_t origin_xtra(sdp_origin_t const *o) { size_t rv = sizeof(*o); STR_XTRA(rv, o->o_username); PTR_XTRA(rv, o->o_address, connection_xtra); return rv; } static sdp_origin_t *origin_dup(char **pp, sdp_origin_t const *src) { char *p; sdp_origin_t *o; p = *pp; STRUCT_DUP(p, o, src); STR_DUP(p, o, src, o_username); PTR_DUP(p, o, src, o_address, connection_dup); assert((size_t)(p - *pp) == origin_xtra(src)); *pp = p; return o; } static size_t connection_xtra(sdp_connection_t const *c) { size_t rv = sizeof(*c); STR_XTRA(rv, c->c_address); return rv; } static sdp_connection_t *connection_dup(char **pp, sdp_connection_t const *src) { char *p; sdp_connection_t *c; p = *pp; STRUCT_DUP(p, c, src); c->c_next = NULL; STR_DUP(p, c, src, c_address); assert((size_t)(p - *pp) == connection_xtra(src)); *pp = p; return c; } static size_t bandwidth_xtra(sdp_bandwidth_t const *b) { size_t rv = sizeof(*b); STR_XTRA(rv, b->b_modifier_name); return rv; } static sdp_bandwidth_t *bandwidth_dup(char **pp, sdp_bandwidth_t const *src) { char *p; sdp_bandwidth_t *b; p = *pp; STRUCT_DUP(p, b, src); b->b_next = NULL; STR_DUP(p, b, src, b_modifier_name); assert((size_t)(p - *pp) == bandwidth_xtra(src)); *pp = p; return b; } static size_t time_xtra(sdp_time_t const *t) { size_t rv = sizeof(*t); PTR_XTRA(rv, t->t_repeat, repeat_xtra); PTR_XTRA(rv, t->t_zone, zone_xtra); return rv; } static sdp_time_t *time_dup(char **pp, sdp_time_t const *src) { char *p; sdp_time_t *t; p = *pp; STRUCT_DUP(p, t, src); t->t_next = NULL; PTR_DUP(p, t, src, t_repeat, repeat_dup); PTR_DUP(p, t, src, t_zone, zone_dup); assert((size_t)(p - *pp) == time_xtra(src)); *pp = p; return t; } static size_t repeat_xtra(sdp_repeat_t const *r) { return (size_t)r->r_size; } static sdp_repeat_t *repeat_dup(char **pp, sdp_repeat_t const *src) { char *p; sdp_repeat_t *r; p = *pp; STRUCT_DUP2(p, r, src); assert((size_t)(p - *pp) == repeat_xtra(src)); *pp = p; return r; } static size_t zone_xtra(sdp_zone_t const *z) { return z->z_size; } static sdp_zone_t *zone_dup(char **pp, sdp_zone_t const *src) { char *p; sdp_zone_t *z; p = *pp; STRUCT_DUP2(p, z, src); assert((size_t)(p - *pp) == zone_xtra(src)); *pp = p; return z; } static size_t key_xtra(sdp_key_t const *k) { size_t rv = sizeof(*k); STR_XTRA(rv, k->k_method_name); STR_XTRA(rv, k->k_material); return rv; } static sdp_key_t *key_dup(char **pp, sdp_key_t const *src) { char *p; sdp_key_t *k; p = *pp; STRUCT_DUP(p, k, src); STR_DUP(p, k, src, k_method_name); STR_DUP(p, k, src, k_material); assert((size_t)(p - *pp) == key_xtra(src)); *pp = p; return k; } static size_t attribute_xtra(sdp_attribute_t const *a) { size_t rv = sizeof(*a); STR_XTRA(rv, a->a_name); STR_XTRA(rv, a->a_value); return rv; } static sdp_attribute_t *attribute_dup(char **pp, sdp_attribute_t const *src) { char *p; sdp_attribute_t *a; p = *pp; STRUCT_DUP(p, a, src); a->a_next = NULL; STR_DUP(p, a, src, a_name); STR_DUP(p, a, src, a_value); assert((size_t)(p - *pp) == attribute_xtra(src)); *pp = p; return a; } static size_t media_xtra(sdp_media_t const *m) { size_t rv = sizeof(*m); STR_XTRA(rv, m->m_type_name); STR_XTRA(rv, m->m_proto_name); LST_XTRA(rv, m->m_format, list_xtra); LST_XTRA(rv, m->m_rtpmaps, rtpmap_xtra); STR_XTRA(rv, m->m_information); LST_XTRA(rv, m->m_connections, connection_xtra); LST_XTRA(rv, m->m_bandwidths, bandwidth_xtra); PTR_XTRA(rv, m->m_key, key_xtra); LST_XTRA(rv, m->m_attributes, attribute_xtra); return rv; } static sdp_media_t *media_dup(char **pp, sdp_media_t const *src, sdp_session_t *sdp) { char *p; sdp_media_t *m; p = *pp; STRUCT_DUP(p, m, src); m->m_next = NULL; STR_DUP(p, m, src, m_type_name); STR_DUP(p, m, src, m_proto_name); LST_DUP(p, m, src, m_format, list_dup); LST_DUP(p, m, src, m_rtpmaps, rtpmap_dup); STR_DUP(p, m, src, m_information); LST_DUP(p, m, src, m_connections, connection_dup); LST_DUP(p, m, src, m_bandwidths, bandwidth_dup); PTR_DUP(p, m, src, m_key, key_dup); LST_DUP(p, m, src, m_attributes, attribute_dup); /* note! we must not implicitly use 'src->m_session' as it might point to a temporary session */ m->m_session = sdp; m->m_rejected = src->m_rejected; m->m_mode = src->m_mode; assert((size_t)(p - *pp) == media_xtra(src)); *pp = p; return m; } #ifdef nomore static int media_xtra_ex(sdp_media_t const *m, sdp_connection_t const *c) { int rv = 0; for (; m; m = m->m_next) { rv += STRUCT_ALIGN(rv); rv += sizeof(*m); STR_XTRA(rv, m->m_type_name); STR_XTRA(rv, m->m_proto_name); LST_XTRA(rv, m->m_format, list_xtra); LST_XTRA(rv, m->m_rtpmaps, rtpmap_xtra); STR_XTRA(rv, m->m_information); if (c != m->m_connections) LST_XTRA(rv, m->m_connections, connection_xtra); LST_XTRA(rv, m->m_bandwidths, bandwidth_xtra); PTR_XTRA(rv, m->m_key, key_xtra); LST_XTRA(rv, m->m_attributes, attribute_xtra); } return rv; } static sdp_media_t *media_dup_ex(char **pp, sdp_media_t const *src, sdp_session_t *sdp, sdp_connection_t *dst_c, sdp_connection_t const *src_c) { char *p; sdp_media_t *retval = NULL, *m, **mm = &retval; int xtra = media_xtra_ex(src, src_c); p = *pp; for (; src; src = src->m_next) { p += STRUCT_ALIGN(p); STRUCT_DUP(p, m, src); m->m_next = NULL; STR_DUP(p, m, src, m_type_name); STR_DUP(p, m, src, m_proto_name); LST_DUP(p, m, src, m_format, list_dup); LST_DUP(p, m, src, m_rtpmaps, rtpmap_dup); STR_DUP(p, m, src, m_information); if (src_c != src->m_connections) LST_DUP(p, m, src, m_connections, connection_dup); else m->m_connections = dst_c; LST_DUP(p, m, src, m_bandwidths, bandwidth_dup); PTR_DUP(p, m, src, m_key, key_dup); LST_DUP(p, m, src, m_attributes, attribute_dup); /* note! we must not implicitly use 'src->m_session' as it might point to a temporary session */ m->m_session = sdp; m->m_rejected = src->m_rejected; m->m_mode = src->m_mode; assert(m); *mm = m; mm = &m->m_next; } assert(p - *pp == xtra); *pp = p; return retval; } #endif static size_t media_xtra_all(sdp_media_t const *m) { size_t rv = 0; for (; m; m = m->m_next) { rv += STRUCT_ALIGN(rv); rv += media_xtra(m); } return rv; } static sdp_media_t *media_dup_all(char **pp, sdp_media_t const *src, sdp_session_t *sdp) { char *p; sdp_media_t *retval = NULL, *m, **mm = &retval; p = *pp; for (; src; src = src->m_next) { p += STRUCT_ALIGN(p); m = media_dup(&p, src, sdp); assert(m); *mm = m; mm = &m->m_next; } *pp = p; return retval; } static size_t list_xtra(sdp_list_t const *l) { size_t rv = sizeof(*l); rv += strlen(l->l_text) + 1; return rv; } static sdp_list_t *list_dup(char **pp, sdp_list_t const *src) { char *p; sdp_list_t *l; p = *pp; STRUCT_DUP(p, l, src); l->l_next = NULL; STR_DUP(p, l, src, l_text); assert((size_t)(p - *pp) == list_xtra(src)); *pp = p; return l; } static size_t rtpmap_xtra(sdp_rtpmap_t const *rm) { size_t rv = sizeof(*rm); STR_XTRA(rv, rm->rm_encoding); STR_XTRA(rv, rm->rm_params); STR_XTRA(rv, rm->rm_fmtp); return rv; } static sdp_rtpmap_t *rtpmap_dup(char **pp, sdp_rtpmap_t const *src) { char *p; sdp_rtpmap_t *rm; p = *pp; STRUCT_DUP(p, rm, src); rm->rm_next = NULL; STR_DUP(p, rm, src, rm_encoding); STR_DUP(p, rm, src, rm_params); STR_DUP(p, rm, src, rm_fmtp); assert((size_t)(p - *pp) == rtpmap_xtra(src)); *pp = p; return rm; } /** Return total size of a list, including size of all nodes */ static size_t list_xtra_all(xtra_f *xtra, void const *v) { size_t rv = 0; sdp_list_t const *l; for (l = v; l; l = l->l_next) { rv += STRUCT_ALIGN(rv); rv += xtra(l); } return rv; } static void *list_dup_all(dup_f *dup, char **pp, void const *vsrc) { char *p; sdp_list_t const *src; sdp_list_t *retval = NULL, *l, **ll = &retval; p = *pp; for (src = vsrc; src; src = src->l_next) { p += STRUCT_ALIGN(p); l = dup(&p, src); assert(l); *ll = l; ll = &l->l_next; } *pp = p; return retval; } #if 0 static size_t XXX_xtra(sdp_XXX_t const *YYY) { size_t rv = sizeof(*YYY); rv += strlen(YYY->YYY_encoding) + 1; if (YYY->YYY_params); rv += strlen(YYY->YYY_params) + 1; return rv; } static sdp_XXX_t *XXX_dup(char **pp, sdp_XXX_t const *src) { char *p; sdp_XXX_t *YYY; p = *pp; ASSERT_STRUCT_ALIGN(p); YYY = memcpy(p, src, src->YYY_size); p += src->YYY_size; YYY->YYY_next = NULL; ZZZ *pp = p; return YYY; } #endif static size_t session_xtra(sdp_session_t const *sdp) { size_t rv = sizeof(*sdp); PTR_XTRA(rv, sdp->sdp_origin, origin_xtra); STR_XTRA(rv, sdp->sdp_subject); STR_XTRA(rv, sdp->sdp_information); STR_XTRA(rv, sdp->sdp_uri); LST_XTRA(rv, sdp->sdp_emails, list_xtra); LST_XTRA(rv, sdp->sdp_phones, list_xtra); LST_XTRA(rv, sdp->sdp_connection, connection_xtra); LST_XTRA(rv, sdp->sdp_bandwidths, bandwidth_xtra); LST_XTRA(rv, sdp->sdp_time, time_xtra); PTR_XTRA(rv, sdp->sdp_key, key_xtra); LST_XTRA(rv, sdp->sdp_attributes, attribute_xtra); STR_XTRA(rv, sdp->sdp_charset); MED_XTRA_ALL(rv, sdp->sdp_media); return rv; } static sdp_session_t *session_dup(char **pp, sdp_session_t const *src) { char *p; sdp_session_t *sdp; p = *pp; STRUCT_DUP(p, sdp, src); sdp->sdp_next = NULL; PTR_DUP(p, sdp, src, sdp_origin, origin_dup); STR_DUP(p, sdp, src, sdp_subject); STR_DUP(p, sdp, src, sdp_information); STR_DUP(p, sdp, src, sdp_uri); LST_DUP(p, sdp, src, sdp_emails, list_dup); LST_DUP(p, sdp, src, sdp_phones, list_dup); LST_DUP(p, sdp, src, sdp_connection, connection_dup); LST_DUP(p, sdp, src, sdp_bandwidths, bandwidth_dup); LST_DUP(p, sdp, src, sdp_time, time_dup); PTR_DUP(p, sdp, src, sdp_key, key_dup); LST_DUP(p, sdp, src, sdp_attributes, attribute_dup); STR_DUP(p, sdp, src, sdp_charset); MED_DUP_ALL(p, sdp, src, sdp_media); assert((size_t)(p - *pp) == session_xtra(src)); *pp = p; return sdp; } /**Duplicate an SDP session description. * * The function sdp_session_dup() duplicates (deeply copies) an SDP * session description @a sdp allocating memory using memory @a home. * * @param h Memory home * @param sdp SDP session description to be duplicated * * @note The duplicated structure is allocated using a single call to * su_alloc() and it can be freed with su_free(). * * @return * If successful, a pointer to newly allocated sdp_session_t structure is * returned, otherwise NULL is returned. */ sdp_session_t *sdp_session_dup(su_home_t *h, sdp_session_t const *sdp) { SDP_DUP(session, sdp); } /* ---------------------------------------------------------------------- */ static size_t session_without_media_xtra(sdp_session_t const *sdp) { size_t rv = sizeof(*sdp); PTR_XTRA(rv, sdp->sdp_origin, origin_xtra); STR_XTRA(rv, sdp->sdp_subject); STR_XTRA(rv, sdp->sdp_information); STR_XTRA(rv, sdp->sdp_uri); LST_XTRA(rv, sdp->sdp_emails, list_xtra); LST_XTRA(rv, sdp->sdp_phones, list_xtra); LST_XTRA(rv, sdp->sdp_connection, connection_xtra); LST_XTRA(rv, sdp->sdp_bandwidths, bandwidth_xtra); LST_XTRA(rv, sdp->sdp_time, time_xtra); PTR_XTRA(rv, sdp->sdp_key, key_xtra); LST_XTRA(rv, sdp->sdp_attributes, attribute_xtra); STR_XTRA(rv, sdp->sdp_charset); return rv; } static sdp_session_t *session_without_media_dup(char **pp, sdp_session_t const *src) { char *p; sdp_session_t *sdp; p = *pp; STRUCT_DUP(p, sdp, src); sdp->sdp_next = NULL; PTR_DUP(p, sdp, src, sdp_origin, origin_dup); STR_DUP(p, sdp, src, sdp_subject); STR_DUP(p, sdp, src, sdp_information); STR_DUP(p, sdp, src, sdp_uri); LST_DUP(p, sdp, src, sdp_emails, list_dup); LST_DUP(p, sdp, src, sdp_phones, list_dup); LST_DUP(p, sdp, src, sdp_connection, connection_dup); LST_DUP(p, sdp, src, sdp_bandwidths, bandwidth_dup); LST_DUP(p, sdp, src, sdp_time, time_dup); PTR_DUP(p, sdp, src, sdp_key, key_dup); LST_DUP(p, sdp, src, sdp_attributes, attribute_dup); STR_DUP(p, sdp, src, sdp_charset); sdp->sdp_media = NULL; assert((size_t)(p - *pp) == session_without_media_xtra(src)); *pp = p; return sdp; } /* SDP_DUP macro requires this */ typedef sdp_session_t sdp_session_without_media_t; /**Duplicate an SDP session description without media descriptions. * * The function sdp_session_dup() duplicates (deeply copies) an SDP session * description @a sdp allocating memory using memory @a home. It does not * copy the media descriptions, however. * * @param h memory h * @param sdp SDP session description to be duplicated * * @note The duplicated structure is allocated using a single call to * su_alloc() and it can be freed with su_free(). * * @return * If successful, a pointer to newly allocated sdp_session_t structure is * returned, otherwise NULL is returned. */ sdp_session_t *sdp_session_dup_without_media(su_home_t *h, sdp_session_t const *sdp) { SDP_DUP(session_without_media, sdp); } /* ---------------------------------------------------------------------- */ /* SDP Tag classes */ #include size_t sdptag_session_xtra(tagi_t const *t, size_t offset) { sdp_session_t const *sdp = (sdp_session_t *)t->t_value; if (sdp) return STRUCT_ALIGN(offset) + session_xtra(sdp); else return 0; } tagi_t *sdptag_session_dup(tagi_t *dst, tagi_t const *src, void **bb) { sdp_session_t *sdp; sdp_session_t const *srcsdp; char *b; assert(src); assert(*bb); b = *bb; b += STRUCT_ALIGN(b); srcsdp = (sdp_session_t *)src->t_value; sdp = srcsdp ? session_dup(&b, srcsdp) : NULL; dst->t_tag = src->t_tag; dst->t_value = (tag_value_t)sdp; *bb = b; return dst + 1; } int sdptag_session_snprintf(tagi_t const *t, char b[], size_t size) { sdp_session_t const *sdp; sdp_printer_t *print; size_t retval; assert(t); if (!t || !t->t_value) { if (size && b) b[0] = 0; return 0; } sdp = (sdp_session_t const *)t->t_value; print = sdp_print(NULL, sdp, b, size, 0); retval = sdp_message_size(print); sdp_printer_free(print); return (int)retval; } /** Tag class for SDP tags. @HIDE */ tag_class_t sdptag_session_class[1] = {{ sizeof(sdptag_session_class), /* tc_next */ NULL, /* tc_len */ NULL, /* tc_move */ NULL, /* tc_xtra */ sdptag_session_xtra, /* tc_dup */ sdptag_session_dup, /* tc_free */ NULL, /* tc_find */ NULL, /* tc_snprintf */ sdptag_session_snprintf, /* tc_filter */ NULL /* msgtag_str_filter */, /* tc_ref_set */ t_ptr_ref_set, }}; /* ---------------------------------------------------------------------- */ /** Compare two session descriptions */ int sdp_session_cmp(sdp_session_t const *a, sdp_session_t const *b) { int rv; sdp_bandwidth_t const *ab, *bb; sdp_attribute_t const *aa, *ba; sdp_media_t const *am, *bm; if ((rv = (a != NULL) - (b != NULL))) return rv; if (a == b) return 0; if ((rv = (a->sdp_version[0] - b->sdp_version[0]))) return rv; if ((rv = sdp_origin_cmp(a->sdp_origin, b->sdp_origin))) return rv; if ((rv = su_strcmp(a->sdp_subject, b->sdp_subject))) return rv; if ((rv = su_strcmp(a->sdp_information, b->sdp_information))) return rv; if ((rv = su_strcmp(a->sdp_uri, b->sdp_uri))) return rv; if ((rv = sdp_list_cmp(a->sdp_emails, b->sdp_emails))) return rv; if ((rv = sdp_list_cmp(a->sdp_phones, b->sdp_phones))) return rv; if ((rv = sdp_connection_cmp(a->sdp_connection, b->sdp_connection))) return rv; for (ab = a->sdp_bandwidths, bb = b->sdp_bandwidths; ab || bb; ab = ab->b_next, bb = bb->b_next) if ((rv = sdp_bandwidth_cmp(a->sdp_bandwidths, b->sdp_bandwidths))) return rv; if ((rv = sdp_time_cmp(a->sdp_time, b->sdp_time))) return rv; if ((rv = sdp_key_cmp(a->sdp_key, b->sdp_key))) return rv; for (aa = a->sdp_attributes, ba = b->sdp_attributes; aa || bb; aa = aa->a_next, ba = ba->a_next) if ((rv = sdp_attribute_cmp(aa, ba))) return rv; for (am = a->sdp_media, bm = b->sdp_media; am || bm; am = am->m_next, bm = bm->m_next) if ((rv = sdp_media_cmp(am, bm))) return rv; return 0; } /** Compare two origin fields */ int sdp_origin_cmp(sdp_origin_t const *a, sdp_origin_t const *b) { int rv; if ((rv = (a != NULL) - (b != NULL))) return rv; if (a == b) return 0; if (a->o_version != b->o_version) return a->o_version < b->o_version ? -1 : 1; if (a->o_id != b->o_id) return a->o_id < b->o_id ? -1 : 1; if ((rv = su_strcasecmp(a->o_username, b->o_username))) return rv; if ((rv = su_strcasecmp(a->o_address->c_address, b->o_address->c_address))) return rv; return 0; } /** Compare two connection fields */ int sdp_connection_cmp(sdp_connection_t const *a, sdp_connection_t const *b) { if (a == b) return 0; if ((a != NULL) != (b != NULL)) return (a != NULL) < (b != NULL) ? -1 : 1; if (a->c_nettype != b->c_nettype) return a->c_nettype < b->c_nettype ? -1 : 1; if (a->c_addrtype != b->c_addrtype) return a->c_addrtype < b->c_addrtype ? -1 : 1; if (a->c_ttl != b->c_ttl) return a->c_ttl < b->c_ttl ? -1 : 1; if (a->c_groups != b->c_groups) return a->c_groups < b->c_groups ? -1 : 1; return strcmp(a->c_address, b->c_address); } /** Compare two bandwidth (b=) fields */ int sdp_bandwidth_cmp(sdp_bandwidth_t const *a, sdp_bandwidth_t const *b) { int rv; if (a == b) return 0; if ((a != NULL) != (b != NULL)) return (a != NULL) < (b != NULL) ? -1 : 1; if (a->b_modifier != b->b_modifier) return a->b_modifier < b->b_modifier ? -1 : 1; if (a->b_modifier == sdp_bw_x && (rv = strcmp(a->b_modifier_name, b->b_modifier_name))) return rv; if (a->b_value != b->b_value) return a->b_value < b->b_value ? -1 : 1; return 0; } /** Compare two time fields */ int sdp_time_cmp(sdp_time_t const *a, sdp_time_t const *b) { int rv; if ((rv = (a != NULL) - (b != NULL))) return rv; if (a == b) return 0; if (a->t_start != b->t_start) return a->t_start < b->t_start ? -1 : 1; if (a->t_stop != b->t_stop) return a->t_stop < b->t_stop ? -1 : 1; if ((rv = sdp_zone_cmp(a->t_zone, b->t_zone))) return rv; if ((rv = sdp_repeat_cmp(a->t_repeat, b->t_repeat))) return rv; return 0; } /** Compare two repeat (r=) fields */ int sdp_repeat_cmp(sdp_repeat_t const *a, sdp_repeat_t const *b) { int i, n; if (a == b) return 0; if ((a != NULL) != (b != NULL)) return (a != NULL) < (b != NULL) ? -1 : 1; if (a->r_interval != b->r_interval) return a->r_interval < b->r_interval ? -1 : 1; if (a->r_duration != b->r_duration) return a->r_duration < b->r_duration ? -1 : 1; n = a->r_number_of_offsets < b->r_number_of_offsets ? a->r_number_of_offsets : b->r_number_of_offsets; for (i = 0; i < n; i++) if (a->r_offsets[i] != b->r_offsets[i]) return a->r_offsets[i] < b->r_offsets[i] ? -1 : 1; if (a->r_number_of_offsets != b->r_number_of_offsets) return a->r_number_of_offsets < b->r_number_of_offsets ? -1 : 1; return 0; } /** Compare two zone (z=) fields */ int sdp_zone_cmp(sdp_zone_t const *a, sdp_zone_t const *b) { int i, n; if (a == b) return 0; if ((a != NULL) != (b != NULL)) return (a != NULL) < (b != NULL) ? -1 : 1; n = a->z_number_of_adjustments < b->z_number_of_adjustments ? a->z_number_of_adjustments : b->z_number_of_adjustments; for (i = 0; i < n; i++) { if (a->z_adjustments[i].z_at != b->z_adjustments[i].z_at) return a->z_adjustments[i].z_at < b->z_adjustments[i].z_at ? -1 : 1; if (a->z_adjustments[i].z_offset != b->z_adjustments[i].z_offset) return a->z_adjustments[i].z_offset < b->z_adjustments[i].z_offset ? -1 : 1; } if (a->z_number_of_adjustments != b->z_number_of_adjustments) return a->z_number_of_adjustments < b->z_number_of_adjustments ? -1 : 1; return 0; } /** Compare two key (k=) fields */ int sdp_key_cmp(sdp_key_t const *a, sdp_key_t const *b) { int rv; if (a == b) return 0; if ((a != NULL) != (b != NULL)) return (a != NULL) < (b != NULL) ? -1 : 1; if (a->k_method != b->k_method) return a->k_method < b->k_method ? -1 : 1; if (a->k_method == sdp_key_x && (rv = su_strcmp(a->k_method_name, b->k_method_name))) return rv; return su_strcmp(a->k_material, b->k_material); } /** Compare two attribute (a=) fields */ int sdp_attribute_cmp(sdp_attribute_t const *a, sdp_attribute_t const *b) { int rv; if (a == b) return 0; if ((a != NULL) != (b != NULL)) return (a != NULL) < (b != NULL) ? -1 : 1; if ((rv = su_strcmp(a->a_name, b->a_name))) return rv; return su_strcmp(a->a_value, b->a_value); } /** Compare two rtpmap structures. */ int sdp_rtpmap_cmp(sdp_rtpmap_t const *a, sdp_rtpmap_t const *b) { int rv; if (a == b) return 0; if ((a != NULL) != (b != NULL)) return (a != NULL) < (b != NULL) ? -1 : 1; if (a->rm_pt != b->rm_pt) return a->rm_pt < b->rm_pt ? -1 : 1; /* Case insensitive encoding */ if ((rv = su_strcmp(a->rm_encoding, b->rm_encoding))) return rv; /* Rate */ if (a->rm_rate != b->rm_rate) return a->rm_rate < b->rm_rate ? -1 : 1; { char const *a_param = "1", *b_param = "1"; if (a->rm_params) a_param = a->rm_params; if (b->rm_params) b_param = b->rm_params; rv = su_strcasecmp(a_param, b_param); if (rv) return rv; } return su_strcasecmp(a->rm_fmtp, b->rm_fmtp); } /** Compare two lists. */ int sdp_list_cmp(sdp_list_t const *a, sdp_list_t const *b) { int rv; for (;a || b; a = a->l_next, b = b->l_next) { if (a == b) return 0; if ((a != NULL) != (b != NULL)) return (a != NULL) < (b != NULL) ? -1 : 1; if ((rv = su_strcmp(a->l_text, b->l_text))) return rv; } return 0; } /** Compare two media (m=) fields */ int sdp_media_cmp(sdp_media_t const *a, sdp_media_t const *b) { int rv; sdp_connection_t const *ac, *bc; sdp_bandwidth_t const *ab, *bb; sdp_rtpmap_t const *arm, *brm; sdp_attribute_t const *aa, *ba; if (a == b) return 0; if ((rv = (a != NULL) - (b != NULL))) return rv; if (a->m_type != b->m_type) return a->m_type < b->m_type ? -1 : 1; if (a->m_type == sdp_media_x) if ((rv = su_strcmp(a->m_type_name, b->m_type_name))) return rv; if (a->m_port != b->m_port) return a->m_port < b->m_port ? -1 : 1; if (a->m_port == 0 /* && b->m_port == 0 */) /* Ignore transport protocol and media list if media has been rejected */ return 0; if (a->m_number_of_ports != b->m_number_of_ports) return a->m_number_of_ports < b->m_number_of_ports ? -1 : 1; if (a->m_proto != b->m_proto) return a->m_proto < b->m_proto ? -1 : 1; if (a->m_proto == sdp_proto_x) if ((rv = su_strcmp(a->m_proto_name, b->m_proto_name))) return rv; if (a->m_mode != b->m_mode) return a->m_mode < b->m_mode ? -1 : 1; for (arm = a->m_rtpmaps, brm = b->m_rtpmaps; arm || brm; arm = arm->rm_next, brm = brm->rm_next) if ((rv = sdp_rtpmap_cmp(arm, brm))) return rv; if ((rv = sdp_list_cmp(a->m_format, b->m_format))) return rv; if ((rv = su_strcmp(a->m_information, b->m_information))) return rv; for (ac = a->m_connections, bc = b->m_connections; ac || bc; ac = ac->c_next, bc = bc->c_next) if ((rv = sdp_connection_cmp(ac, bc))) return rv; for (ab = a->m_bandwidths, bb = b->m_bandwidths; ab || bb; ab = ab->b_next, bb = bb->b_next) if ((rv = sdp_bandwidth_cmp(a->m_bandwidths, b->m_bandwidths))) return rv; if ((rv = sdp_key_cmp(a->m_key, b->m_key))) return rv; for (aa = a->m_attributes, ba = b->m_attributes; aa || bb; aa = aa->a_next, ba = ba->a_next) if ((rv = sdp_attribute_cmp(aa, ba))) return rv; return 0; } /* ---------------------------------------------------------------------- */ sdp_connection_t *sdp_media_connections(sdp_media_t const *m) { if (m) { if (m->m_connections) return m->m_connections; if (m->m_session) return m->m_session->sdp_connection; } return NULL; } /* ---------------------------------------------------------------------- */ /** Find named attribute from given list. */ sdp_attribute_t *sdp_attribute_find(sdp_attribute_t const *a, char const *name) { for (; a; a = a->a_next) { if (su_casematch(a->a_name, name)) break; } return (sdp_attribute_t *)a; } /** Find named attribute from given lists (a or a2). */ sdp_attribute_t *sdp_attribute_find2(sdp_attribute_t const *a, sdp_attribute_t const *a2, char const *name) { for (; a; a = a->a_next) { if (su_casematch(a->a_name, name)) break; } if (a == 0) for (a = a2; a; a = a->a_next) { if (su_casematch(a->a_name, name)) break; } return (sdp_attribute_t *)a; } /** Get session mode from attribute list. */ sdp_mode_t sdp_attribute_mode(sdp_attribute_t const *a, sdp_mode_t defmode) { for (; a; a = a->a_next) { if (su_casematch(a->a_name, "sendrecv")) return sdp_sendrecv; if (su_casematch(a->a_name, "inactive")) return sdp_inactive; if (su_casematch(a->a_name, "recvonly")) return sdp_recvonly; if (su_casematch(a->a_name, "sendonly")) return sdp_sendonly; } return defmode; } /** Convert session mode as #sdp_attribute_t structure. */ sdp_attribute_t *sdp_attribute_by_mode(su_home_t *home, sdp_mode_t mode) { sdp_attribute_t *a; char const *name; if (mode == sdp_inactive) name = "inactive"; else if (mode == sdp_sendonly) name = "sendonly"; else if (mode == sdp_recvonly) name = "recvonly"; else if (mode == sdp_sendrecv) name = "sendrecv"; else return NULL; a = su_salloc(home, sizeof(*a)); if (a) a->a_name = name; return a; } /** Find a mapped attribute. * * A mapped attribute has form 'a=: ' where pt is a RTP * payload type, integer in range 0..127. For example, "a=atmmap" [@RFC3108] * is a mapped attribute. Note that common mapped attributes, "a=rtpmap" and * "a=fmtp" are already parsed as list of #sdp_rtpmap_t in #sdp_media_t. * * @param a pointer to first attribute in the list * @param name name of the attribute * @param pt payload type number (must be 0..127) * @param return_result return value parameter for mapped attribute value * * @return Pointer to a matching attribute structure, or NULL. * * If a matching attribute is found, @a return_result will point to part of * the attribute after the payload type and whitespace. */ sdp_attribute_t *sdp_attribute_mapped_find(sdp_attribute_t const *a, char const *name, int pt, char **return_result) { char pt_value[4]; size_t pt_len; if (return_result) *return_result = NULL; if (0 > pt || pt > 127) return NULL; snprintf(pt_value, sizeof(pt_value), "%u", (unsigned)pt); pt_len = strlen(pt_value); for (; (a = sdp_attribute_find(a, name)); a = a->a_next) { char const *value = a->a_value; size_t wlen; if (strncmp(value, pt_value, pt_len)) continue; wlen = strspn(value + pt_len, " \t"); if (wlen == 0 || value[pt_len + wlen] == '\0') continue; if (return_result) *return_result = (char *)value + pt_len + wlen; return (sdp_attribute_t *)a; } return NULL; } /** Append a (list of) attribute(s) to a list of attributes. */ void sdp_attribute_append(sdp_attribute_t **list, sdp_attribute_t const *a) { assert(list); if (list == NULL || a == NULL) return; for (;*list; list = &(*list)->a_next) ; *list = (sdp_attribute_t *)a; } /**Replace or append a attribute within a list of attributes. * * @retval 1 if replaced existing attribute * @retval 0 if attribute was appended * @retval -1 upon an error */ int sdp_attribute_replace(sdp_attribute_t **list, sdp_attribute_t *a, sdp_attribute_t **return_replaced) { sdp_attribute_t *replaced; assert(list); if (return_replaced) *return_replaced = NULL; if (list == NULL || a == NULL) return -1; assert(a->a_name != NULL); assert(a->a_next == NULL); for (; *list; list = &(*list)->a_next) { if (su_casematch((*list)->a_name, a->a_name)) break; } replaced = *list, *list = a; if (replaced) { a->a_next = replaced->a_next; replaced->a_next = NULL; if (return_replaced) *return_replaced = replaced; return 1; } return 0; } /** Remove a named attribute from a list of attributes. */ sdp_attribute_t *sdp_attribute_remove(sdp_attribute_t **list, char const *name) { sdp_attribute_t *a; assert(list); if (list == NULL) return NULL; if (name == NULL) return NULL; for (a = *list; a; list = &a->a_next, a = *list) { if (su_casematch(name, a->a_name)) break; } if (a) { *list = a->a_next; a->a_next = NULL; } return a; } /* Return 1 if m= line struct matches with given type and name */ unsigned sdp_media_match(sdp_media_t const *m, sdp_media_e type, sdp_text_t *type_name, sdp_proto_e proto, sdp_text_t *proto_name) { if (m == NULL) return 0; if (type == sdp_media_any || m->m_type == sdp_media_any) return 1; if (type_name == NULL) type_name = ""; if (type != m->m_type || (type == sdp_media_x && !su_casematch(m->m_type_name, type_name))) return 0; if (proto == sdp_proto_any || m->m_proto == sdp_proto_any) return 1; if (proto_name == NULL) proto_name = ""; if (proto != m->m_proto || (proto == sdp_proto_x && !su_casematch(m->m_proto_name, proto_name))) return 0; return 1; } /* Return 1 if media type and protocol of m= line structs matches */ unsigned sdp_media_match_with(sdp_media_t const *a, sdp_media_t const *b) { if (a == NULL || b == NULL) return a == b; if (a->m_type == sdp_media_any || b->m_type == sdp_media_any) return 1; if (a->m_type != b->m_type || (a->m_type == sdp_media_x && !su_casematch(b->m_type_name, a->m_type_name))) return 0; if (a->m_proto == sdp_proto_any || b->m_proto == sdp_proto_any) return 1; if (a->m_proto != b->m_proto || (a->m_proto == sdp_proto_x && !su_casematch(b->m_proto_name, a->m_proto_name))) return 0; return 1; } /** Count matching media lines in SDP. */ unsigned sdp_media_count(sdp_session_t const *sdp, sdp_media_e type, sdp_text_t *type_name, sdp_proto_e proto, sdp_text_t *proto_name) { unsigned count = 0; sdp_media_t const *m; if (sdp != NULL) for (m = sdp->sdp_media; m; m = m->m_next) count += sdp_media_match(m, type, type_name, proto, proto_name); return count; } /** Count matching media lines in SDP. */ unsigned sdp_media_count_with(sdp_session_t const *sdp, sdp_media_t const *m0) { unsigned count = 0; sdp_media_t const *m; if (sdp != NULL) for (m = sdp->sdp_media; m; m = m->m_next) count += sdp_media_match_with(m, m0); return count; } /** Return true if media uses RTP */ int sdp_media_uses_rtp(sdp_media_t const *m) { return m && (m->m_proto == sdp_proto_rtp || m->m_proto == sdp_proto_srtp || (m->m_proto == sdp_proto_x && m->m_proto_name && su_casenmatch(m->m_proto_name, "RTP/", 4))); } /** Check if payload type, rtp rate and parameters match in rtpmaps*/ int sdp_rtpmap_match(sdp_rtpmap_t const *a, sdp_rtpmap_t const *b) { char const *aparam, *bparam; if (a == b) return 1; if (a == 0 || b == 0) return 0; if (a->rm_rate != b->rm_rate) return 0; if (!su_casematch(a->rm_encoding, b->rm_encoding)) return 0; aparam = a->rm_params; bparam = b->rm_params; if (aparam == bparam) return 1; if (!aparam) aparam = "1"; if (!bparam) bparam = "1"; if (!su_casematch(aparam, bparam)) return 0; return 1; } /** Search for matching a rtpmap entry from list. * * @note * The a=fmtp: for the codecs are not compared. * * @return * Pointer to first sdp_rtpmap_t entry on the @a list matching with any * sdp_rtpmap_t entry on @a rm. */ sdp_rtpmap_t *sdp_rtpmap_find_matching(sdp_rtpmap_t const *list, sdp_rtpmap_t const *rm) { char const *lparam, *rparam; if (rm == NULL) return NULL; for (; list; list = list->rm_next) { if (rm->rm_rate != list->rm_rate) continue; if (!su_casematch(rm->rm_encoding, list->rm_encoding)) continue; lparam = rm->rm_params; rparam = list->rm_params; if (lparam == rparam) break; if (!lparam) lparam = "1"; if (!rparam) rparam = "1"; if (!su_casematch(lparam, rparam)) continue; break; } return (sdp_rtpmap_t *)list; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/sdp.docs000066400000000000000000000061351223300710500220050ustar00rootroot00000000000000/* -*- c -*- */ /**@MODULEPAGE "sdp" - SDP Module @section sdp_meta Module Meta Information The @b sdp module provides a simple "C" parser interface for SDP [@RFC2327], Session Description Protocol. The parser also implements support for IPv6 addresses as per @RFC3266. The @RFC4566 should be supported, but we have not checked since draft-eitf-mmusic-sdp-new-17 or so. @CONTACT Pekka Pessi @STATUS @SofiaSIP Core library @LICENSE LGPL Contributor(s): - Pekka Pessi - Jari Selin @section sdp_parser SDP Parser SDP parser parses an SDP message and converts it to internally used SDP structure #sdp_session_t. Typically, the SDP parser is used as follows: @code sdp_parser_t *parser = sdp_parse(home, message, len, 0); if (!sdp_session(parser)) { show(sdp_parsing_error(parser)); } else { sdp_session_t *sdp = sdp_session(parser); @endcode Act upon session description, then free the parser: @code } sdp_parser_free(parser); @endcode There are various flags indicating what kind of SDP variants the sdp_parse() accepts. The sanity check run after parsing can be disabled by including flag #sdp_f_insane. The parser can be used to parse syntactically vague configuration files when using flag #sdp_f_config. The parser will then accept * for media, protocol and port, for instance. @section sdp_printer SDP Printer SDP printer converts internally used SDP structure #sdp_session_t to the standard SDP format. Typically, the SDP printer is used as follows: @code char buffer[512]; sdp_printer_t *printer = sdp_print(home, session, buffer, sizeof(buffer), 0); if (sdp_message(printer)) { char const *msg = sdp_message(printer); size_t msgsize = sdp_message_size(printer); @endcode At this point, application can use the SDP message contents, e.g., it can send them to network, and then free the message: @code } else { show_critical_error(sdp_printing_error(printer)); } sdp_printer_free(printer); @endcode @section sdp_example Example Examples on using SDP parser can be found from test_sdp.c and soa.c. Here is an simple example, which decodes an SDP text in @a original, increments the version number in the origin line, and encodes the SDP description again to @a buf. @code size_t increment_sdp_version(char buf[], size_t bsize, char const *original, size_t osize) { su_home_t home[1] = { SU_HOME_INIT(home) }; sdp_parser_t *parser = sdp_parse(home, original, osize, 0); sdp_printer_t *printer; size_t retval = 0; if (sdp_session(parser)) { sdp_session_t *sdp = sdp_session(parser); sdp->sdp_origin->o_version++; printer = sdp_print(home, sdp, buf, bsize, 0); if (sdp_message(printer)) { retval = sdp_message_size(printer); } else { fprintf(stderr, "increment_sdp_version: %s\n", sdp_printing_error(printer)); } sdp_printer_free(printer); } else { fprintf(stderr, "increment_sdp_version: %s\n", sdp_parsing_error(parser)); } sdp_parser_free(parser); su_home_deinit(home); return retval; } @endcode */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/sdp_parse.c000066400000000000000000001427001223300710500224700ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@ingroup sdp_parser * @CFILE sdp_parse.c * @brief Simple SDP parser interface. * * @author Pekka Pessi * @author Kai Vehmanen * * @date Created: Fri Feb 18 10:25:08 2000 ppessi * * @sa @RFC4566, @RFC2327. */ #include "config.h" #include #include #include "sofia-sip/sdp.h" #include #include #include #include #include #include #include /** @typedef struct sdp_parser_s sdp_parser_t; * * SDP parser handle. * * The SDP parser handle returned by sdp_parse() contains either * a successfully parsed SDP session #sdp_session_t or an error message. * If sdp_session() returns non-NULL, parsing was successful. * * @sa #sdp_session_t, sdp_parse(), sdp_session(), sdp_parsing_error(), * sdp_sanity_check(), sdp_parser_home(), sdp_parser_free(), @RFC4566, * @RFC2327. */ struct sdp_parser_s { su_home_t pr_home[1]; union { char pru_error[128]; sdp_session_t pru_session[1]; } pr_output; char *pr_message; sdp_mode_t pr_session_mode; unsigned pr_ok : 1; unsigned pr_strict : 1; unsigned pr_anynet : 1; unsigned pr_mode_0000 : 1; unsigned pr_mode_manual : 1; unsigned pr_insane : 1; unsigned pr_c_missing : 1; unsigned pr_config : 1; }; #define is_posdigit(c) ((c) >= '1' && (c) <= '9') #define is_digit(c) ((c) >= '0' && (c) <= '9') #define is_space(c) ((c) == ' ') #define is_tab(c) ((c) == '\t') #define pr_error pr_output.pru_error #define pr_session pr_output.pru_session #define STRICT(pr) (pr->pr_strict) /* Static parser object used when running out of memory */ static const struct sdp_parser_s no_mem_error = { { SU_HOME_INIT(no_mem_error) }, { "sdp: not enough memory" } }; /* Internal prototypes */ static void parse_message(sdp_parser_t *p); static int parsing_error(sdp_parser_t *p, char const *fmt, ...); /** Parse an SDP message. * * The function sdp_parse() parses an SDP message @a msg of size @a * msgsize. If msgsize is -1, the size of message is calculated using * strlen(). * * Parsing is done according to the given @a flags. * * The SDP message may not contain a NUL. * * The parsing result is stored to an #sdp_session_t structure. * * @param home memory home * @param msg pointer to message * @param msgsize size of the message (excluding final NUL, if any) * @param flags flags affecting the parsing. * * The following flags are used by parser: * * @li #sdp_f_strict Parser should accept only messages conforming strictly * to the specification. * @li #sdp_f_anynet Parser accepts unknown network or address types. * @li #sdp_f_insane Do not run sanity check. * @li #sdp_f_c_missing Sanity check does not require c= for each m= line * @li #sdp_f_mode_0000 Parser regards "c=IN IP4 0.0.0.0" as "a=inactive" * (likewise with c=IN IP6 ::) * @li #sdp_f_mode_manual Do not generate or parse SDP mode * @li #sdp_f_config Parse config files (any line can be missing) * * @return * Always a valid parser handle. * * @todo Parser accepts some non-conforming SDP even with #sdp_f_strict. * * @sa sdp_session(), sdp_parsing_error(), sdp_sanity_check(), * sdp_parser_home(), sdp_parser_free(), @RFC4566, @RFC2327. */ sdp_parser_t * sdp_parse(su_home_t *home, char const msg[], issize_t msgsize, int flags) { sdp_parser_t *p; char *b; size_t len; if (msg == NULL) { p = su_home_clone(home, sizeof(*p)); if (p) parsing_error(p, "invalid input message"); else p = (sdp_parser_t*)&no_mem_error; return p; } if (msgsize == -1) len = strlen(msg); else len = msgsize; if (len > ISSIZE_MAX) len = ISSIZE_MAX; p = su_home_clone(home, sizeof(*p) + len + 1); if (p == NULL) return (sdp_parser_t*)&no_mem_error; b = strncpy((void *)(p + 1), msg, len); b[len] = 0; p->pr_message = b; p->pr_strict = (flags & sdp_f_strict) != 0; p->pr_anynet = (flags & sdp_f_anynet) != 0; p->pr_mode_0000 = (flags & sdp_f_mode_0000) != 0; p->pr_insane = (flags & sdp_f_insane) != 0; p->pr_c_missing = (flags & sdp_f_c_missing) != 0; if (flags & sdp_f_config) p->pr_c_missing = 1, p->pr_config = 1; p->pr_mode_manual = (flags & sdp_f_mode_manual) != 0; p->pr_session_mode = sdp_sendrecv; parse_message(p); return p; } /** Obtain memory home used by parser */ su_home_t *sdp_parser_home(sdp_parser_t *parser) { if (parser != &no_mem_error) return parser->pr_home; else return NULL; } /** Retrieve an SDP session structure. * * The function sdp_session() returns a pointer to the SDP session * structure associated with the SDP parser @a p. The pointer and all the * data in the structure are valid until sdp_parser_free() is called. * * @param p SDP parser * * @return * The function sdp_session() returns a pointer to an parsed SDP message * or NULL, if an error has occurred. */ sdp_session_t * sdp_session(sdp_parser_t *p) { return p && p->pr_ok ? p->pr_session : NULL; } /** Get a parsing error message. * * The function sdp_parsing_error() returns the error message associated * with an SDP parser @a p. * * @param p SDP parser * * @return * The function sdp_parsing_error() returns a C string describing parsing * error, or NULL if no error occurred. */ char const *sdp_parsing_error(sdp_parser_t *p) { return !p->pr_ok ? p->pr_error : NULL; } /** Free an SDP parser. * * The function sdp_parser_free() frees an SDP parser object along with * the memory blocks associated with it. * * @param p pointer to the SDP parser to be freed */ void sdp_parser_free(sdp_parser_t *p) { if (p && p != &no_mem_error) su_home_unref(p->pr_home); } /* ========================================================================= */ /* ========================================================================= * Private part */ /* Parsing tokens */ #define SPACE " " #define TAB "\011" #define CRLF "\015\012" #define ALPHA "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" #define DIGIT "0123456789" #define TOKEN ALPHA DIGIT "-!#$%&'*+.^_`{|}~" /* ========================================================================= */ /* Parsing functions */ static void post_session(sdp_parser_t *p, sdp_session_t *sdp); static void parse_origin(sdp_parser_t *p, char *r, sdp_origin_t **result); static void parse_subject(sdp_parser_t *p, char *r, sdp_text_t **result); static void parse_information(sdp_parser_t *p, char *r, sdp_text_t **result); static void parse_uri(sdp_parser_t *p, char *r, sdp_text_t **result); static void parse_email(sdp_parser_t *p, char *r, sdp_list_t **result); static void parse_phone(sdp_parser_t *p, char *r, sdp_list_t **result); static void parse_connection(sdp_parser_t *p, char *r, sdp_connection_t **result); static void parse_bandwidth(sdp_parser_t *p, char *r, sdp_bandwidth_t **result); static void parse_time(sdp_parser_t *p, char *r, sdp_time_t **result); static void parse_repeat(sdp_parser_t *p, char *r, sdp_repeat_t **result); static void parse_zone(sdp_parser_t *p, char *r, sdp_zone_t **result); static void parse_key(sdp_parser_t *p, char *r, sdp_key_t **result); static void parse_session_attr(sdp_parser_t *p, char *r, sdp_attribute_t **result); static void parse_media(sdp_parser_t *p, char *r, sdp_media_t **result); static void parse_payload(sdp_parser_t *p, char *r, sdp_rtpmap_t **result); static void parse_media_attr(sdp_parser_t *p, char *r, sdp_media_t *m, sdp_attribute_t **result); static int parse_rtpmap(sdp_parser_t *p, char *r, sdp_media_t *m); static int parse_fmtp(sdp_parser_t *p, char *r, sdp_media_t *m); static void parse_text_list(sdp_parser_t *p, char *r, sdp_list_t **result); static void parse_descs(sdp_parser_t *p, char *r, char *m, sdp_media_t **result); static int parse_ul(sdp_parser_t *p, char **r, unsigned long *result, unsigned long max_value); static int parse_ull(sdp_parser_t *p, char **r, uint64_t *result, uint64_t max_value); static void parse_alloc_error(sdp_parser_t *p, const char *typename); static char *next(char **message, const char *sep, const char *strip); static char *token(char **message, const char *sep, const char *legal, const char *strip); #if 0 static void check_mandatory(sdp_parser_t *p, sdp_session_t *sdp); #endif /* ------------------------------------------------------------------------- * Macro PARSE_ALLOC * * Description: * This macro declares a pointer (v) of given type (t). It then allocates * an structure of given type (t). If allocation was succesful, it assigns * the XX_size member with appropriate value. */ #define PARSE_ALLOC(p, t, v) \ t *v = su_salloc(p->pr_home, sizeof(*v)); \ if (!v && (parse_alloc_error(p, #t), 1)) return; /* ------------------------------------------------------------------------- * Macro PARSE_CHECK_REST * * Description: * This macro check if there is extra data at the end of field. */ #define PARSE_CHECK_REST(p, s, n)\ if (*s && (parsing_error(p, "extra data after %s (\"%.04s\")", n, s), 1)) \ return /* ------------------------------------------------------------------------- * Function parse_message() - parse an SDP message * * Description: * This function parses an SDP message, which is copied into the * p->pr_message. The p->pr_message is modified during the parsing, * and parts of it are returned in p->pr_session. * * Parameters: * p - pointer to SDP parser object */ static void parse_message(sdp_parser_t *p) { /* announcement = proto-version origin-field session-name-field information-field uri-field email-fields phone-fields connection-field bandwidth-fields time-fields key-field attribute-fields media-descriptions */ sdp_session_t *sdp = p->pr_session; char *record, *rest; char const *strip; char *message = p->pr_message; char field = '\0'; sdp_list_t **emails = &sdp->sdp_emails; sdp_list_t **phones = &sdp->sdp_phones; sdp_bandwidth_t **bandwidths = &sdp->sdp_bandwidths; sdp_time_t **times = &sdp->sdp_time; sdp_repeat_t **repeats = NULL; sdp_zone_t **zones = NULL; sdp_attribute_t **attributes = &sdp->sdp_attributes; if (!STRICT(p)) strip = SPACE TAB; /* skip initial whitespace */ else strip = ""; p->pr_ok = 1; p->pr_session->sdp_size = sizeof(p->pr_session); /* Require that version comes first */ record = next(&message, CRLF, strip); if (!su_strmatch(record, "v=0")) { if (!p->pr_config || !record || record[1] != '=') { parsing_error(p, "bad SDP message"); return; } } else { record = next(&message, CRLF, strip); } /* XXX - the lines in SDP are in certain order, which we don't check here. For stricter parsing we might want to parse o= and s= next. */ for (; record && p->pr_ok; record = next(&message, CRLF, strip)) { field = record[0]; rest = record + 2; rest += strspn(rest, strip); if (record[1] != '=') { parsing_error(p, "bad line \"%s\"", record); return; } switch (field) { case 'o': parse_origin(p, rest, &sdp->sdp_origin); break; case 's': parse_subject(p, rest, &sdp->sdp_subject); break; case 'i': parse_information(p, rest, &sdp->sdp_information); break; case 'u': parse_uri(p, rest, &sdp->sdp_uri); break; case 'e': parse_email(p, rest, emails); emails = &(*emails)->l_next; break; case 'p': parse_phone(p, rest, phones); phones = &(*phones)->l_next; break; case 'c': parse_connection(p, rest, &sdp->sdp_connection); break; case 'b': parse_bandwidth(p, rest, bandwidths); bandwidths = &(*bandwidths)->b_next; break; case 't': parse_time(p, rest, times); repeats = &(*times)->t_repeat; zones = &(*times)->t_zone; times = &(*times)->t_next; break; case 'r': if (repeats) parse_repeat(p, rest, repeats); else parsing_error(p, "repeat field without time field"); break; case 'z': if (zones) parse_zone(p, rest, zones), zones = NULL; else parsing_error(p, "zone field without time field"); break; case 'k': parse_key(p, rest, &sdp->sdp_key); break; case 'a': parse_session_attr(p, rest, attributes); if (*attributes) attributes = &(*attributes)->a_next; break; case 'm': parse_descs(p, record, message, &sdp->sdp_media); post_session(p, sdp); return; default: parsing_error(p, "unknown field \"%s\"", record); return; } } post_session(p, sdp); } int sdp_connection_is_inaddr_any(sdp_connection_t const *c) { return c && c->c_nettype == sdp_net_in && ((c->c_addrtype == sdp_addr_ip4 && su_strmatch(c->c_address, "0.0.0.0")) || (c->c_addrtype == sdp_addr_ip6 && su_strmatch(c->c_address, "::"))); } /**Postprocess session description. * * Postprocessing includes setting the session backpointer for each media, * doing sanity checks and setting rejected and mode flags. */ static void post_session(sdp_parser_t *p, sdp_session_t *sdp) { sdp_media_t *m; sdp_connection_t const *c; if (!p->pr_ok) return; /* Set session back-pointer */ for (m = sdp->sdp_media; m; m = m->m_next) { m->m_session = sdp; } if (p->pr_config) { if (sdp->sdp_version[0] != 0) parsing_error(p, "Incorrect version"); return; } /* Go through all media and set mode */ for (m = sdp->sdp_media; m; m = m->m_next) { if (m->m_port == 0) { m->m_mode = sdp_inactive; m->m_rejected = 1; continue; } c = sdp_media_connections(m); if (p->pr_mode_0000 && sdp_connection_is_inaddr_any(c)) { /* Reset recvonly flag */ m->m_mode &= ~sdp_recvonly; } } if (p->pr_insane) return; /* Verify that all mandatory fields are present */ if (sdp_sanity_check(p) < 0) return; } /** Validates that all mandatory fields exist * * Checks that all necessary fields (v=, o=) exists in the parsed sdp. If * strict, check that all mandatory fields (c=, o=, s=, t=) are present. * This function also goes through all media, marks rejected media as such, * and updates the mode accordingly. * * @retval 0 if parsed SDP description is valid * @retval -1 if some SDP line is missing * @retval -2 if c= line is missing */ int sdp_sanity_check(sdp_parser_t *p) { sdp_session_t *sdp = p->pr_session; sdp_media_t *m; if (!p || !p->pr_ok) return -1; else if (sdp->sdp_version[0] != 0) return parsing_error(p, "Incorrect version"); else if (!sdp->sdp_origin) return parsing_error(p, "No o= present"); else if (p->pr_strict && !sdp->sdp_subject) return parsing_error(p, "No s= present"); else if (p->pr_strict && !sdp->sdp_time) return parsing_error(p, "No t= present"); /* If there is no session level c= check that one exists for all media */ /* c= line may be missing if this is a RTSP description */ if (!p->pr_c_missing && !sdp->sdp_connection) { for (m = sdp->sdp_media ; m ; m = m->m_next) { if (!m->m_connections && !m->m_rejected) { parsing_error(p, "No c= on either session level or all mediums"); return -2; } } } return 0; } #if 0 /** * Parse a "v=" field * * The function parser_version() parses the SDP version field. * * @param p pointer to SDP parser object * @param r pointer to record data * @param result pointer to which parsed record is assigned */ static void parse_version(sdp_parser_t *p, char *r, sdp_version_t *result) { /* proto-version = "v=" 1*DIGIT CRLF ;[RFC2327] describes version 0 */ if (parse_ul(p, &r, result, 0)) parsing_error(p, "version \"%s\" is invalid", r); else if (*result > 0) parsing_error(p, "unknown version v=%s", r); } #endif /* ------------------------------------------------------------------------- * Function parse_origin() - parse an "o=" field * * Description: * This function parses an SDP origin field. * * Parameters: * p - pointer to SDP parser object * r - pointer to record data * result - pointer to which parsed record is assigned */ static void parse_origin(sdp_parser_t *p, char *r, sdp_origin_t **result) { /* origin-field = "o=" username space sess-id space sess-version space nettype space addrtype space addr CRLF username = safe ;pretty wide definition, but doesn't include space sess-id = 1*(DIGIT) ;should be unique for this originating username/host sess-version = 1*(DIGIT) ;0 is a new session */ PARSE_ALLOC(p, sdp_origin_t, o); *result = o; o->o_username = token(&r, SPACE TAB, NULL, SPACE TAB); if (!o->o_username) { parsing_error(p, "invalid username"); return; } if (parse_ull(p, &r, &o->o_id, 0)) { parsing_error(p, "invalid session id"); return; } if (parse_ull(p, &r, &o->o_version, 0)) { parsing_error(p, "invalid session version"); return; } parse_connection(p, r, &o->o_address); } /* ------------------------------------------------------------------------- * Function parse_subject() - parse an "s=" field * * Description: * This function parses an SDP subject field. * * Parameters: * p - pointer to SDP parser object * r - pointer to record data * result - pointer to which parsed record is assigned */ static void parse_subject(sdp_parser_t *p, char *r, sdp_text_t **result) { /* session-name-field = "s=" text CRLF text = byte-string */ *result = r; } /* ------------------------------------------------------------------------- * Function parse_information() - parse an "i=" field * * Description: * This function parses an SDP information field. * * Parameters: * p - pointer to SDP parser object * r - pointer to record data * result - pointer to which parsed record is assigned */ static void parse_information(sdp_parser_t *p, char *r, sdp_text_t **result) { /* information-field = ["i=" text CRLF] */ *result = r; } /* ------------------------------------------------------------------------- * Function parse_uri() - parse an "u=" field * * Description: * This function parses an SDP URI field. * * Parameters: * p - pointer to SDP parser object * r - pointer to record data * result - pointer to which parsed record is assigned */ static void parse_uri(sdp_parser_t *p, char *r, sdp_text_t **result) { /* uri-field = ["u=" uri CRLF] uri= ;defined in RFC1630 */ /* XXX - no syntax checking here */ *result = r; } /* ------------------------------------------------------------------------- * Function parse_email() - parse an "e=" field * * Description: * This function parses an SDP email field. * * Parameters: * p - pointer to SDP parser object * r - pointer to record data * result - pointer to which parsed record is assigned */ static void parse_email(sdp_parser_t *p, char *r, sdp_list_t **result) { /* email-fields = *("e=" email-address CRLF) email-address = email | email "(" email-safe ")" | email-safe "<" email ">" email = ;defined in RFC822 */ parse_text_list(p, r, result); } /* ------------------------------------------------------------------------- * Function parse_phone() - parse an "p=" field * * Description: * This function parses an SDP phone field. * * Parameters: * p - pointer to SDP parser object * r - pointer to record data * result - pointer to which parsed record is assigned */ static void parse_phone(sdp_parser_t *p, char *r, sdp_list_t **result) { /* phone-fields = *("p=" phone-number CRLF) phone-number = phone | phone "(" email-safe ")" | email-safe "<" phone ">" phone = "+" POS-DIGIT 1*(space | "-" | DIGIT) ;there must be a space or hyphen between the ;international code and the rest of the number. */ parse_text_list(p, r, result); } /* ------------------------------------------------------------------------- * Function parse_connection() - parse an "c=" field * * Description: * This function parses an SDP connection field. * * Parameters: * p - pointer to SDP parser object * r - pointer to record data * result - pointer to which parsed record is assigned */ static void parse_connection(sdp_parser_t *p, char *r, sdp_connection_t **result) { /* connection-field = ["c=" nettype space addrtype space connection-address CRLF] ;a connection field must be present ;in every media description or at the ;session-level nettype = "IN" ;list to be extended addrtype = "IP4" | "IP6" ;list to be extended connection-address = multicast-address | addr multicast-address = 3*(decimal-uchar ".") decimal-uchar "/" ttl [ "/" integer ] ;multicast addresses may be in the range ;224.0.0.0 to 239.255.255.255 ttl = decimal-uchar addr = FQDN | unicast-address FQDN = 4*(alpha-numeric|"-"|".") ;fully qualified domain name as specified in RFC1035 unicast-address = IP4-address | IP6-address IP4-address = b1 "." decimal-uchar "." decimal-uchar "." b4 b1 = decimal-uchar ;less than "224"; not "0" or "127" b4 = decimal-uchar ;not "0" IP6-address = ;to be defined */ PARSE_ALLOC(p, sdp_connection_t, c); *result = c; if (su_casenmatch(r, "IN", 2) && (r[2] == ' ' || r[2] == '\t')) { char *s; /* nettype is internet */ token(&r, SPACE TAB, NULL, NULL); c->c_nettype = sdp_net_in; /* addrtype */ s = token(&r, SPACE TAB, NULL, NULL); if (su_casematch(s, "IP4")) c->c_addrtype = sdp_addr_ip4; else if (su_casematch(s, "IP6")) c->c_addrtype = sdp_addr_ip6; else { parsing_error(p, "unknown IN address type: %s", s); return; } /* address */ s = next(&r, SPACE TAB, SPACE TAB); c->c_address = s; if (!s || !*s) { parsing_error(p, "invalid address"); return; } /* ttl */ s = strchr(s, '/'); if (s) { unsigned long value; *s++ = 0; if (parse_ul(p, &s, &value, 256) || (*s && *s != '/')) { parsing_error(p, "invalid ttl"); return; } c->c_ttl = value; c->c_mcast = 1; /* multiple groups */ value = 1; if (*s++ == '/') if (parse_ul(p, &s, &value, 0) || *s) { parsing_error(p, "invalid number of multicast groups"); return; } c->c_groups = value; } else c->c_groups = 1; } else if (p->pr_anynet) { c->c_nettype = sdp_net_x; c->c_addrtype = sdp_addr_x; c->c_address = r; c->c_ttl = 0; c->c_groups = 1; } else parsing_error(p, "invalid address"); } /* ------------------------------------------------------------------------- * Function parse_bandwidth() - parse an "b=" field * * Description: * This function parses an SDP bandwidth field. * * Parameters: * p - pointer to SDP parser object * r - pointer to record data * result - pointer to which parsed record is assigned */ static void parse_bandwidth(sdp_parser_t *p, char *r, sdp_bandwidth_t **result) { /* bandwidth-fields = *("b=" bwtype ":" bandwidth CRLF) bwtype = token bandwidth = 1*(DIGIT) */ /* NOTE: bwtype can also be like X-barf */ sdp_bandwidth_e modifier; char *name; unsigned long value; name = token(&r, ":", TOKEN, SPACE TAB); if (name == NULL || parse_ul(p, &r, &value, 0)) { parsing_error(p, "invalid bandwidth"); return; } if (su_casematch(name, "CT")) modifier = sdp_bw_ct, name = NULL; else if (su_casematch(name, "AS") == 0) modifier = sdp_bw_as, name = NULL; else modifier = sdp_bw_x; if (STRICT(p)) PARSE_CHECK_REST(p, r, "b"); { PARSE_ALLOC(p, sdp_bandwidth_t, b); *result = b; b->b_modifier = modifier; b->b_modifier_name = name; b->b_value = value; } } /* ------------------------------------------------------------------------- * Function parse_time() - parse an "t=" field * * Description: * This function parses an SDP time field. * * Parameters: * p - pointer to SDP parser object * r - pointer to record data * result - pointer to which parsed record is assigned */ static void parse_time(sdp_parser_t *p, char *r, sdp_time_t **result) { /* time-fields = 1*( "t=" start-time SP stop-time *(CRLF repeat-fields) CRLF) [zone-adjustments CRLF] start-time = time / "0" stop-time = time / "0" time = POS-DIGIT 9*DIGIT ; Decimal representation of NTP time in ; seconds since 1900. The representation ; of NTP time is an unbounded length field ; containing at least 10 digits. Unlike the ; 64-bit representation used elsewhere, time ; in SDP does not wrap in the year 2036. */ PARSE_ALLOC(p, sdp_time_t, t); *result = t; if (parse_ul(p, &r, &t->t_start, 0) || parse_ul(p, &r, &t->t_stop, 0)) parsing_error(p, "invalid time"); else if (STRICT(p)) { PARSE_CHECK_REST(p, r, "t"); } } /** * Parse an "r=" field * * The function parse_repeat() parses an SDP repeat field. * * @param p pointer to SDP parser object * @param r pointer to record data * @param result pointer to which parsed record is assigned * */ static void parse_repeat(sdp_parser_t *p, char *d, sdp_repeat_t **result) { /* repeat-fields = %x72 "=" repeat-interval 2*(SP typed-time) repeat-interval = POS-DIGIT *DIGIT [fixed-len-time-unit] typed-time = 1*DIGIT [fixed-len-time-unit] fixed-len-time-unit = %x64 / %x68 / %x6d / %x73 ; "d" | "h" | "m" | "s" */ unsigned long tt, *interval; size_t i; int n, N; char *s; sdp_repeat_t *r; int strict = STRICT(p); /** Count number of intervals */ for (N = 0, s = d; *s; ) { if (!(is_posdigit(*s) || (!strict && (*s) == '0'))) break; do { s++; } while (is_digit(*s)); if (*s && strchr(strict ? "dhms" : "dhmsDHMS", *s)) s++; N++; if (!(i = strict ? is_space(*s) : strspn(s, SPACE TAB))) break; s += i; } PARSE_CHECK_REST(p, s, "r"); if (N < 2) { parsing_error(p, "invalid repeat"); return; } if (!(r = su_salloc(p->pr_home, offsetof(sdp_repeat_t, r_offsets[N - 1])))) { parse_alloc_error(p, "sdp_repeat_t"); return; } r->r_number_of_offsets = N - 2; r->r_offsets[N - 2] = 0; for (n = 0, interval = &r->r_interval; n < N; n++) { tt = strtoul(d, &d, 10); switch (*d) { case 'd': case 'D': tt *= 24; /* FALLTHROUGH */ case 'h': case 'H': tt *= 60; /* FALLTHROUGH */ case 'm': case 'M': tt *= 60; /* FALLTHROUGH */ case 's': case 'S': d++; break; } interval[n] = tt; while (is_space(*d)) d++; } *result = r; } /* ------------------------------------------------------------------------- * Function parse_zone() - parse an "z=" field * * Description: * This function parses an SDP time zone field. * * Parameters: * p - pointer to SDP parser object * r - pointer to record data * result - pointer to which parsed record is assigned * */ static void parse_zone(sdp_parser_t *p, char *r, sdp_zone_t **result) { char *s; size_t i; int n, N; sdp_zone_t *z; /* zone-adjustments = time space ["-"] typed-time *(space time space ["-"] typed-time) */ /** Count number of timezones, check syntax */ for (N = 0, s = r; *s;) { if (!(is_posdigit(*s) || (!STRICT(p) && (*s) == '0'))) break; do { s++; } while (is_digit(*s)); if (!(i = STRICT(p) ? is_space(*s) : strspn(s, SPACE TAB))) break; s += i; if (!(*s == '-' || is_posdigit(*s) || (!STRICT(p) && (*s) == '0'))) break; do { s++; } while (is_digit(*s)); if (*s && strchr(STRICT(p) ? "dhms" : "dhmsDHMS", *s)) s++; N++; if (!(i = STRICT(p) ? is_space(*s) : strspn(s, SPACE TAB))) break; s += i; } PARSE_CHECK_REST(p, s, "z"); if (N < 1) { parsing_error(p, "invalid timezone"); return; } if (!(z = su_salloc(p->pr_home, offsetof(sdp_zone_t, z_adjustments[N])))) { parse_alloc_error(p, "sdp_zone_t"); return; } z->z_number_of_adjustments = N; for (n = 0; n < N; n++) { unsigned long at = strtoul(r, &r, 10); long offset = strtol(r, &r, 10); switch (*r) { case 'd': case 'D': offset *= 24; /* FALLTHROUGH */ case 'h': case 'H': offset *= 60; /* FALLTHROUGH */ case 'm': case 'M': offset *= 60; /* FALLTHROUGH */ case 's': case 'S': r++; break; } z->z_adjustments[n].z_at = at; z->z_adjustments[n].z_offset = offset; } *result = z; } /* ------------------------------------------------------------------------- * Function parse_key() - parse an "k=" field * * Description: * This function parses an SDP key field. * * Parameters: * p - pointer to SDP parser object * r - pointer to record data * result - pointer to which parsed record is assigned * */ static void parse_key(sdp_parser_t *p, char *r, sdp_key_t **result) { char *s; /* key-field = ["k=" key-type CRLF] key-type = "prompt" | "clear:" key-data | "base64:" key-data | "uri:" uri key-data = email-safe | "~" | " */ s = token(&r, ":", TOKEN, SPACE TAB); if (!s) { parsing_error(p, "invalid key method"); return; } { PARSE_ALLOC(p, sdp_key_t, k); *result = k; /* These are defined as key-sensitive in RFC 4566 */ #define MATCH(s, tok) \ (STRICT(p) ? su_strmatch((s), (tok)) : su_casematch((s), (tok))) if (MATCH(s, "clear")) k->k_method = sdp_key_clear, k->k_method_name = "clear"; else if (MATCH(s, "base64")) k->k_method = sdp_key_base64, k->k_method_name = "base64"; else if (MATCH(s, "uri")) k->k_method = sdp_key_uri, k->k_method_name = "uri"; else if (MATCH(s, "prompt")) k->k_method = sdp_key_prompt, k->k_method_name = "prompt"; else if (!STRICT(p)) k->k_method = sdp_key_x, k->k_method_name = s; else { parsing_error(p, "invalid key method"); return; } k->k_material = r; } } /* ------------------------------------------------------------------------- * Function parse_session_attr() - parse a session "a=" field * * Description: * This function parses an SDP attribute field regarding whole session. * * Parameters: * p - pointer to SDP parser object * r - pointer to record data * result - pointer to which parsed record is assigned */ static void parse_session_attr(sdp_parser_t *p, char *r, sdp_attribute_t **result) { /* attribute-fields = *("a=" attribute CRLF) attribute = (att-field ":" att-value) / att-field att-field = token att-value = byte-string */ char *name = NULL, *value = NULL; if (!(name = token(&r, ":", TOKEN, SPACE TAB))) { parsing_error(p,"invalid attribute name"); return; } if (*r) value = r; else PARSE_CHECK_REST(p, r, "a"); if (su_casematch(name, "charset")) { p->pr_session->sdp_charset = value; return; } if (p->pr_mode_manual) ; else if (su_casematch(name, "inactive")) p->pr_session_mode = sdp_inactive; else if (su_casematch(name, "sendonly")) p->pr_session_mode = sdp_sendonly; else if (su_casematch(name, "recvonly")) p->pr_session_mode = sdp_recvonly; else if (su_casematch(name, "sendrecv")) p->pr_session_mode = sdp_sendrecv; { PARSE_ALLOC(p, sdp_attribute_t, a); *result = a; a->a_name = name; a->a_value = value; } } /* ------------------------------------------------------------------------- * Function parse_media() - parse an "m=" field * * Description: * This function parses an SDP media field. * * Parameters: * p - pointer to SDP parser object * r - pointer to record data * result - pointer to which parsed record is assigned */ static void parse_media(sdp_parser_t *p, char *r, sdp_media_t **result) { /* media-descriptions = *( media-field information-field *(connection-field) bandwidth-fields key-field attribute-fields ) media-field = "m=" media space port ["/" integer] space proto 1*(space fmt) CRLF media = token ;typically "audio", "video", "application" ;or "data" fmt = token ;typically an RTP payload type for audio ;and video media proto = token *("/" token) ;typically "RTP/AVP" or "udp" for IP4 port = 1*(DIGIT) ;should in the range "1024" to "65535" inclusive */ char *s; unsigned long value; PARSE_ALLOC(p, sdp_media_t, m); *result = m; m->m_mode = sdp_sendrecv; s = token(&r, SPACE, TOKEN, NULL); if (!s) { parsing_error(p, "m= invalid media field"); return; } sdp_media_type(m, s); /* Accept m=* in configuration file */ if (p->pr_config && m->m_type == sdp_media_any) { r += strspn(r, SPACE TAB); if (r[0] == '\0') { m->m_proto = sdp_proto_any, m->m_proto_name = "*"; return; } } if (parse_ul(p, &r, &value, 0)) { parsing_error(p, "m= invalid port number"); return; } m->m_port = value; if (*r == '/') { r++; if (parse_ul(p, &r, &value, 0)) { parsing_error(p, "m= invalid port specification"); return; } m->m_number_of_ports = value; } s = token(&r, SPACE, "/" TOKEN, SPACE); if (s == NULL) { parsing_error(p, "m= missing protocol"); return; } if (!STRICT(p) && su_casematch(s, "RTP")) m->m_proto = sdp_proto_rtp, m->m_proto_name = "RTP/AVP"; else sdp_media_transport(m, s); /* RTP format list */ if (*r && sdp_media_has_rtp(m)) { parse_payload(p, r, &m->m_rtpmaps); return; } /* "normal" format list */ if (*r) { sdp_list_t **fmt = &m->m_format; while (r && *r) { PARSE_ALLOC(p, sdp_list_t, l); *fmt = l; l->l_text = token(&r, SPACE TAB, TOKEN, SPACE TAB); fmt = &l->l_next; } } } /** Set media type */ void sdp_media_type(sdp_media_t *m, char const *s) { if (su_strmatch(s, "*")) m->m_type = sdp_media_any, m->m_type_name = "*"; else if (su_casematch(s, "audio")) m->m_type = sdp_media_audio, m->m_type_name = "audio"; else if (su_casematch(s, "video")) m->m_type = sdp_media_video, m->m_type_name = "video"; else if (su_casematch(s, "application")) m->m_type = sdp_media_application, m->m_type_name = "application"; else if (su_casematch(s, "data")) m->m_type = sdp_media_data, m->m_type_name = "data"; else if (su_casematch(s, "control")) m->m_type = sdp_media_control, m->m_type_name = "control"; else if (su_casematch(s, "message")) m->m_type = sdp_media_message, m->m_type_name = "message"; else if (su_casematch(s, "image")) m->m_type = sdp_media_image, m->m_type_name = "image"; else if (su_casematch(s, "red")) m->m_type = sdp_media_red, m->m_type_name = "red"; else m->m_type = sdp_media_x, m->m_type_name = s; } /** Set transport protocol. * * Set the @a m->m_proto to a well-known protocol type as * well as canonize case of @a m_proto_name. */ void sdp_media_transport(sdp_media_t *m, char const *s) { if (m == NULL || s == NULL) ; else if (su_strmatch(s, "*")) m->m_proto = sdp_proto_any, m->m_proto_name = "*"; else if (su_casematch(s, "RTP/AVP")) m->m_proto = sdp_proto_rtp, m->m_proto_name = "RTP/AVP"; else if (su_casematch(s, "RTP/SAVP")) m->m_proto = sdp_proto_srtp, m->m_proto_name = "RTP/SAVP"; else if (su_casematch(s, "udptl")) /* Lower case - be compatible with people living by T.38 examples */ m->m_proto = sdp_proto_udptl, m->m_proto_name = "udptl"; else if (su_casematch(s, "UDP")) m->m_proto = sdp_proto_udp, m->m_proto_name = "UDP"; else if (su_casematch(s, "TCP")) m->m_proto = sdp_proto_tcp, m->m_proto_name = "TCP"; else if (su_casematch(s, "TLS")) m->m_proto = sdp_proto_tls, m->m_proto_name = "TLS"; else m->m_proto = sdp_proto_x, m->m_proto_name = s; } /** Check if media uses RTP as its transport protocol. */ int sdp_media_has_rtp(sdp_media_t const *m) { return m && (m->m_proto == sdp_proto_rtp || m->m_proto == sdp_proto_srtp); } #define RTPMAP(pt, encoding, rate, params) \ { sizeof(sdp_rtpmap_t), NULL, encoding, rate, (char *)params, NULL, 1, pt, 0 } /* rtpmaps for well-known codecs */ static sdp_rtpmap_t const sdp_rtpmap_pcmu = RTPMAP(0, "PCMU", 8000, 0), sdp_rtpmap_1016 = RTPMAP(1, "1016", 8000, 0), sdp_rtpmap_g721 = RTPMAP(2, "G721", 8000, 0), sdp_rtpmap_gsm = RTPMAP(3, "GSM", 8000, 0), sdp_rtpmap_g723 = RTPMAP(4, "G723", 8000, 0), sdp_rtpmap_dvi4_8000 = RTPMAP(5, "DVI4", 8000, 0), sdp_rtpmap_dvi4_16000 = RTPMAP(6, "DVI4", 16000, 0), sdp_rtpmap_lpc = RTPMAP(7, "LPC", 8000, 0), sdp_rtpmap_pcma = RTPMAP(8, "PCMA", 8000, 0), sdp_rtpmap_g722 = RTPMAP(9, "G722", 8000, 0), sdp_rtpmap_l16_2 = RTPMAP(10, "L16", 44100, "2"), sdp_rtpmap_l16 = RTPMAP(11, "L16", 44100, 0), sdp_rtpmap_qcelp = RTPMAP(12, "QCELP", 8000, 0), sdp_rtpmap_cn = RTPMAP(13, "CN", 8000, 0), sdp_rtpmap_mpa = RTPMAP(14, "MPA", 90000, 0), sdp_rtpmap_g728 = RTPMAP(15, "G728", 8000, 0), sdp_rtpmap_dvi4_11025 = RTPMAP(16, "DVI4", 11025, 0), sdp_rtpmap_dvi4_22050 = RTPMAP(17, "DVI4", 22050, 0), sdp_rtpmap_g729 = RTPMAP(18, "G729", 8000, 0), sdp_rtpmap_reserved_cn = RTPMAP(19, "CN", 8000, 0), /* video codecs */ sdp_rtpmap_celb = RTPMAP(25, "CelB", 90000, 0), sdp_rtpmap_jpeg = RTPMAP(26, "JPEG", 90000, 0), sdp_rtpmap_nv = RTPMAP(28, "nv", 90000, 0), sdp_rtpmap_h261 = RTPMAP(31, "H261", 90000, 0), sdp_rtpmap_mpv = RTPMAP(32, "MPV", 90000, 0), sdp_rtpmap_mp2t = RTPMAP(33, "MP2T", 90000, 0), sdp_rtpmap_h263 = RTPMAP(34, "H263", 90000, 0); /** Table of rtpmap structures by payload type numbers. * * The table of reserved payload numbers is constructed from @RFC3551 * and @RFC1890. Note the clock rate of G722. * * Use sdp_rtpmap_dup() to copy these structures. */ sdp_rtpmap_t const * const sdp_rtpmap_well_known[128] = { &sdp_rtpmap_pcmu, /* 0 */ &sdp_rtpmap_1016, /* 1 */ &sdp_rtpmap_g721, /* 2 */ &sdp_rtpmap_gsm, /* 3 */ &sdp_rtpmap_g723, /* 4 */ &sdp_rtpmap_dvi4_8000, /* 5 */ &sdp_rtpmap_dvi4_16000, /* 6 */ &sdp_rtpmap_lpc, /* 7 */ &sdp_rtpmap_pcma, /* 8 */ &sdp_rtpmap_g722, /* 9 */ &sdp_rtpmap_l16_2, /* 10 */ &sdp_rtpmap_l16, /* 11 */ &sdp_rtpmap_qcelp, /* 12 */ &sdp_rtpmap_cn, /* 13 */ &sdp_rtpmap_mpa, /* 14 */ &sdp_rtpmap_g728, /* 15 */ &sdp_rtpmap_dvi4_11025, /* 16 */ &sdp_rtpmap_dvi4_22050, /* 17 */ &sdp_rtpmap_g729, /* 18 */ &sdp_rtpmap_reserved_cn, /* 19 */ NULL, /* 20 */ NULL, /* 21 */ NULL, /* 22 */ NULL, /* 23 */ NULL, /* 24 */ &sdp_rtpmap_celb, /* 25 */ &sdp_rtpmap_jpeg, /* 26 */ NULL, /* 27 */ &sdp_rtpmap_nv, /* 28 */ NULL, /* 29 */ NULL, /* 30 */ &sdp_rtpmap_h261, /* 31 */ &sdp_rtpmap_mpv, /* 32 */ &sdp_rtpmap_mp2t, /* 33 */ &sdp_rtpmap_h263, /* 34 */ NULL, }; /** * The function parse_payload() parses an RTP payload type list, and * creates an rtpmap structure for each payload type. * * @param p pointer to SDP parser object * @param r pointer to record data * @param result pointer to which parsed record is assigned */ static void parse_payload(sdp_parser_t *p, char *r, sdp_rtpmap_t **result) { while (*r) { unsigned long value; if (parse_ul(p, &r, &value, 128) == 0) { PARSE_ALLOC(p, sdp_rtpmap_t, rm); assert(0 <= value && value < 128); *result = rm; result = &rm->rm_next; if (sdp_rtpmap_well_known[value]) { *rm = *sdp_rtpmap_well_known[value]; } else { rm->rm_predef = 1; rm->rm_pt = value; rm->rm_encoding = ""; rm->rm_rate = 0; } } else if (p->pr_config && r[0] == '*' && (r[1] == ' ' || r[1] == '\0')) { PARSE_ALLOC(p, sdp_rtpmap_t, rm); *result = rm; result = &rm->rm_next; rm->rm_predef = 1; rm->rm_any = 1; rm->rm_encoding = "*"; rm->rm_rate = 0; return; } else { parsing_error(p, "m= invalid format for RTP/AVT"); return; } } } /* ------------------------------------------------------------------------- * Function parse_media_attr() - parse a media-specific "a=" field * * Description: * This function parses a media-specific attribute field. * * Parameters: * p - pointer to SDP parser object * r - pointer to record data * result - pointer to which parsed record is assigned */ static void parse_media_attr(sdp_parser_t *p, char *r, sdp_media_t *m, sdp_attribute_t **result) { /* attribute-fields = *("a=" attribute CRLF) attribute = (att-field ":" att-value) / att-field att-field = token att-value = byte-string a=rtpmap: /[/] a=fmtp: */ int rtp = sdp_media_has_rtp(m); char *name = NULL, *value = NULL; int n; if (!(name = token(&r, ":", TOKEN, SPACE TAB))) { parsing_error(p,"invalid attribute name"); return; } if (*r) value = r; else PARSE_CHECK_REST(p, r, "a"); if (p->pr_mode_manual) ; else if (su_casematch(name, "inactive")) { m->m_mode = sdp_inactive; return; } else if (su_casematch(name, "sendonly")) { m->m_mode = sdp_sendonly; return; } else if (su_casematch(name, "recvonly")) { m->m_mode = sdp_recvonly; return; } else if (su_casematch(name, "sendrecv")) { m->m_mode = sdp_sendrecv; return; } if (rtp && su_casematch(name, "rtpmap")) { if ((n = parse_rtpmap(p, r, m)) == 0 || n < -1) return; } else if (rtp && su_casematch(name, "fmtp")) { if ((n = parse_fmtp(p, r, m)) == 0 || n < -1) return; } else { PARSE_ALLOC(p, sdp_attribute_t, a); *result = a; a->a_name = name; a->a_value = value; } } /** Parse rtpmap attribute. * * a=rtpmap: /[/] */ static int parse_rtpmap(sdp_parser_t *p, char *r, sdp_media_t *m) { unsigned long pt, rate; char *encoding, *params; sdp_rtpmap_t *rm; int strict = STRICT(p); if (parse_ul(p, &r, &pt, 128)) { if (strict) parsing_error(p, "a=rtpmap: invalid payload type"); return -1; } for (rm = m->m_rtpmaps; rm; rm = rm->rm_next) if (rm->rm_pt == pt) break; if (!rm) { if (strict) parsing_error(p, "a=rtpmap:%lu: unknown payload type", pt); return -1; } encoding = token(&r, "/", TOKEN, NULL); if (!r) { parsing_error(p, "a=rtpmap:%lu: missing ", pt); return -2; } if (parse_ul(p, &r, &rate, 0)) { parsing_error(p, "a=rtpmap:%lu %s: invalid ", pt, encoding); return -2; } if (*r == '/') params = ++r; else params = 0; rm->rm_predef = 0; rm->rm_encoding = encoding; rm->rm_rate = rate; rm->rm_params = params; return 0; } /** Parse fmtp attribute. * * a=fmtp: */ static int parse_fmtp(sdp_parser_t *p, char *r, sdp_media_t *m) { unsigned long pt; sdp_rtpmap_t *rm; int strict = STRICT(p); if (parse_ul(p, &r, &pt, 128)) { if (strict) parsing_error(p, "a=rtpmap: invalid payload type"); return -1; } for (rm = m->m_rtpmaps; rm; rm = rm->rm_next) if (rm->rm_pt == pt) break; if (!rm) { if (strict) parsing_error(p, "a=fmtp:%lu: unknown payload type", pt); return -1; } rm->rm_fmtp = r; return 0; } /* ------------------------------------------------------------------------- * Function parse_descs() - parse media descriptors * * Description: * This function parses media descriptors at the end of SDP message. * * Parameters: * p - pointer to SDP parser object * record - pointer to first media field * message - pointer to rest * medias - pointer to which parsed media structures are assigned */ static void parse_descs(sdp_parser_t *p, char *record, char *message, sdp_media_t **medias) { char *rest; const char *strip; sdp_media_t *m = NULL; sdp_connection_t **connections = NULL; sdp_bandwidth_t **bandwidths = NULL; sdp_attribute_t **attributes = NULL; if (!STRICT(p)) strip = SPACE TAB; /* skip initial whitespace */ else strip = ""; for (; record && p->pr_ok; record = next(&message, CRLF, strip)) { char field = record[0]; rest = record + 2; rest += strspn(rest, strip); if (record[1] == '=') switch (field) { case 'c': assert(connections); parse_connection(p, rest, connections); connections = &(*connections)->c_next; break; case 'b': assert(bandwidths); parse_bandwidth(p, rest, bandwidths); bandwidths = &(*bandwidths)->b_next; break; case 'k': parse_key(p, rest, &m->m_key); break; case 'a': assert(attributes); parse_media_attr(p, rest, m, attributes); if (*attributes) attributes = &(*attributes)->a_next; break; case 'm': parse_media(p, rest, medias); m = *medias; if (m) { m->m_mode = p->pr_session_mode; medias = &m->m_next; connections = &m->m_connections; bandwidths = &m->m_bandwidths; attributes = &m->m_attributes; } } } } static void parse_text_list(sdp_parser_t *p, char *r, sdp_list_t **result) { PARSE_ALLOC(p, sdp_list_t, l); *result = l; l->l_text = r; } /* * parse_ul: parse an unsigned long */ static int parse_ul(sdp_parser_t *p, char **r, unsigned long *result, unsigned long max) { char *ul = *r; ul += strspn(ul, SPACE TAB); *result = strtoul(ul, r, 10); if (ul != *r && !(max && max <= *result)) { *r += strspn(*r, SPACE TAB); return 0; } return -1; } #if !HAVE_STRTOULL unsigned longlong strtoull(char const *string, char **return_end, int base); #endif /* * parse_ull: parse an unsigned long long */ static int parse_ull(sdp_parser_t *p, char **r, uint64_t *result, uint64_t max) { unsigned longlong ull; char *s = *r; s += strspn(s, SPACE TAB); ull = strtoull(s, r, 10); if (s != *r && !(max && max <= ull)) { *result = (uint64_t)ull; *r += strspn(*r, SPACE TAB); return 0; } return -1; } static char *token(char **message, const char *sep, const char *legal, const char *strip) { size_t n; char *retval = *message; if (strip) retval += strspn(retval, strip); if (legal) n = strspn(retval, legal); else n = strcspn(retval, sep); if (n == 0) return NULL; if (retval[n]) { retval[n++] = '\0'; n += strspn(retval + n, sep); } *message = retval + n; if (*retval == '\0') return NULL; return retval; } static char *next(char **message, const char *sep, const char *strip) { size_t n; char *retval = *message; if (strip[0]) retval += strspn(retval, strip); n = strcspn(retval, sep); if (n == 0) return NULL; if (retval[n]) { retval[n++] = '\0'; n += strspn(retval + n, sep); } *message = retval + n; if (*retval == '\0') return NULL; return retval; } static int parsing_error(sdp_parser_t *p, char const *fmt, ...) { int n; va_list ap; va_start(ap, fmt); memset(p->pr_error, 0, sizeof(p->pr_error)); n = vsnprintf(p->pr_error, sizeof(p->pr_error), fmt, ap); va_end(ap); p->pr_ok = 0; return -1; } static void parse_alloc_error(sdp_parser_t *p, const char *typename) { parsing_error(p, "memory exhausted (while allocating memory for %s)", typename); } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/sdp_print.c000066400000000000000000000460651223300710500225210ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@ingroup sdp_printer * * @CFILE sdp_print.c Simple SDP printer interface. * * @author Pekka Pessi * * @date Created: Fri Feb 18 10:25:08 2000 ppessi */ #include "config.h" #include #include #include "sofia-sip/sdp.h" #include #include #include #include #include #include /* ========================================================================= */ /* Printing API */ /* */ #define SDP_BLOCK (512) #define CRLF "\015\012" typedef unsigned longlong ull; /** @typedef struct sdp_printer_s sdp_printer_t * * SDP printer handle. * * @sa #sdp_session_t, sdp_print(), sdp_printing_error(), * sdp_message(), sdp_message_size(), sdp_printer_free() */ struct sdp_printer_s { int pr_size; su_home_t *pr_home; char *pr_buffer; size_t pr_bsiz; size_t pr_used; /* various flags */ unsigned pr_ok : 1; unsigned pr_strict : 1; unsigned pr_owns_buffer:1; unsigned pr_may_realloc:1; unsigned pr_all_rtpmaps:1; unsigned pr_mode_manual:1; unsigned pr_mode_always:1; }; static struct sdp_printer_s printer_memory_error = { sizeof(printer_memory_error), NULL, "memory exhausted", sizeof(printer_memory_error.pr_buffer), sizeof(printer_memory_error.pr_buffer) }; static void print_session(sdp_printer_t *p, sdp_session_t const *session); static void printing_error(sdp_printer_t *p, const char *fmt, ...); /** Print a SDP description. * * Encode the contents of the SDP session structure #sdp_session_t * to the @a msgbuf. The @a msgbuf has size @a msgsize * bytes. If @a msgbuf is @c NULL, the sdp_print() function allocates the * required buffer from the @a home heap. * * @param home Memory home (may be NULL). * @param session SDP session description structure to be encoded. * @param msgbuf Buffer to which encoding is stored (may be NULL). * @param msgsize Size of @a msgbuf. * @param flags Flags specifying the encoding options. * * The @a flags specify encoding options as follows: * * @li #sdp_f_strict - Printer should only emit messages conforming strictly * to the * specification. * * @li #sdp_f_realloc - If this flag is specified, and @a msgbuf is too * small for the resulting SDP message, @c sdp_print() may allocate a new * buffer for it from the heap. * * @li #sdp_f_print_prefix - The buffer provided by caller already contains * valid data. The result will concatenated to the string in the buffer. * * @li #sdp_f_mode_always - Always add mode attributes to media * * @li #sdp_f_mode_manual - Do not generate mode attributes * * @return * Always return a handle to an #sdp_printer_t object. * * @sa #sdp_printer_t, #sdp_session_t, sdp_printing_error(), * sdp_message(), sdp_message_size(), sdp_printer_free(), * sdp_parse(). */ sdp_printer_t *sdp_print(su_home_t *home, sdp_session_t const *session, char msgbuf[], isize_t msgsize, int flags) { sdp_printer_t *p = su_salloc(home, sizeof(*p)); if (p) { p->pr_size = sizeof(p); p->pr_home = home; p->pr_used = 0; if (msgbuf) { p->pr_may_realloc = (flags & sdp_f_realloc) != 0; p->pr_buffer = msgbuf; p->pr_bsiz = msgsize; if (flags & sdp_f_print_prefix) p->pr_used = strlen(msgbuf); } else { p->pr_owns_buffer = 1; p->pr_buffer = su_alloc(home, SDP_BLOCK); p->pr_bsiz = SDP_BLOCK; } p->pr_strict = (flags & sdp_f_strict) != 0; p->pr_all_rtpmaps = (flags & sdp_f_all_rtpmaps) != 0; p->pr_mode_manual = (flags & sdp_f_mode_manual) != 0; p->pr_mode_always = (flags & sdp_f_mode_always) != 0; if (session) print_session(p, session); else printing_error(p, "NULL session description"); return p; } else { return &printer_memory_error; } } /** @brief Get encoding error. * * Return a message describing the encoding error. * * @param p Pointer to an #sdp_printer_t object. * * @return * Return a pointer to C string describing printing errors, or NULL if no * error was encountered. */ char const *sdp_printing_error(sdp_printer_t *p) { if (p) if (!p->pr_ok) return p->pr_buffer; else return NULL; else return "null sdp_printer_t*"; } /** @brief Get encoded SDP message. * * Return a pointer to a C string containing the SDP message. * * @param p Pointer to an #sdp_printer_t object. * * @return * Return a pointer to a C string containing the encoded SDP message, or * NULL upon an error. */ char const *sdp_message(sdp_printer_t *p) { if (p && p->pr_ok) return p->pr_buffer; else return NULL; } /** @brief Get size of encoded SDP message. * * Return the size of the encoded SDP message. * * @param p Pointer to an #sdp_printer_t object. * * @return * Number of bytes in SDP message excluding final NUL or 0 upon an error. */ isize_t sdp_message_size(sdp_printer_t *p) { if (p && p->pr_ok) return p->pr_used; else return 0; } /** Free a SDP printer. * * Free the printer object @a p and the message buffer possibly associated * with it. * * @param p Pointer to an #sdp_printer_t object. */ void sdp_printer_free(sdp_printer_t *p) { if (p && p != &printer_memory_error) { if (p->pr_owns_buffer && p->pr_buffer) su_free(p->pr_home, p->pr_buffer), p->pr_buffer = NULL; su_free(p->pr_home, p); } } /* ========================================================================= */ static void print_version(sdp_printer_t *p, sdp_version_t const *v); static void print_origin(sdp_printer_t *p, sdp_origin_t const *o); static void print_subject(sdp_printer_t *p, sdp_text_t *s); static void print_information(sdp_printer_t *p, sdp_text_t *i); static void print_uri(sdp_printer_t *p, sdp_text_t *u); static void print_emails(sdp_printer_t *p, sdp_list_t const *e); static void print_phones(sdp_printer_t *p, sdp_list_t const *ph); static void print_connection(sdp_printer_t *p, sdp_connection_t const *c); static void print_connection_list(sdp_printer_t *p, sdp_connection_t const *c); static void print_connection2(sdp_printer_t *p, sdp_connection_t const *c); static void print_bandwidths(sdp_printer_t *p, sdp_bandwidth_t const *b); static void print_time(sdp_printer_t *p, sdp_time_t const *t); static void print_repeat(sdp_printer_t *p, sdp_repeat_t const *r); static void print_zone(sdp_printer_t *p, sdp_zone_t const *z); static void print_typed_time(sdp_printer_t *p, unsigned long t); static void print_key(sdp_printer_t *p, sdp_key_t const *k); static void print_attributes(sdp_printer_t *p, sdp_attribute_t const *a); static void print_charset(sdp_printer_t *p, sdp_text_t *charset); static void print_media(sdp_printer_t *p, sdp_session_t const *, sdp_media_t const *m); static void print_text_list(sdp_printer_t*, const char *, sdp_list_t const *l); static void sdp_printf(sdp_printer_t *p, const char *fmt, ...); static void print_session(sdp_printer_t *p, sdp_session_t const *sdp) { p->pr_ok = 1; if (p->pr_ok && sdp->sdp_version) print_version(p, sdp->sdp_version); if (p->pr_ok && sdp->sdp_origin) print_origin(p, sdp->sdp_origin); if (p->pr_ok && sdp->sdp_subject) print_subject(p, sdp->sdp_subject); if (p->pr_ok && sdp->sdp_information) print_information(p, sdp->sdp_information); if (p->pr_ok && sdp->sdp_uri) print_uri(p, sdp->sdp_uri); if (p->pr_ok && sdp->sdp_emails) print_emails(p, sdp->sdp_emails); if (p->pr_ok && sdp->sdp_phones) print_phones(p, sdp->sdp_phones); if (p->pr_ok && sdp->sdp_connection) print_connection(p, sdp->sdp_connection); if (p->pr_ok && sdp->sdp_bandwidths) print_bandwidths(p, sdp->sdp_bandwidths); if (p->pr_ok) print_time(p, sdp->sdp_time); if (p->pr_ok && sdp->sdp_time) { if (p->pr_ok && sdp->sdp_time->t_repeat) print_repeat(p, sdp->sdp_time->t_repeat); if (p->pr_ok && sdp->sdp_time->t_zone) print_zone(p, sdp->sdp_time->t_zone); } if (p->pr_ok && sdp->sdp_key) print_key(p, sdp->sdp_key); if (p->pr_ok && sdp->sdp_charset) print_charset(p, sdp->sdp_charset); if (p->pr_ok && sdp->sdp_attributes) print_attributes(p, sdp->sdp_attributes); if (p->pr_ok && sdp->sdp_media) print_media(p, sdp, sdp->sdp_media); } static void print_version(sdp_printer_t *p, sdp_version_t const *v) { sdp_printf(p, "v=%lu" CRLF, *v); } static void print_origin(sdp_printer_t *p, sdp_origin_t const *o) { if (!o->o_address || !o->o_address->c_address || o->o_address->c_ttl != 0 || o->o_address->c_groups > 1) { printing_error(p, "o= address malformed"); return; } sdp_printf(p, "o=%s "LLU" "LLU" ", o->o_username, (ull)o->o_id, (ull)o->o_version); print_connection2(p, o->o_address); } static void print_subject(sdp_printer_t *p, sdp_text_t *subject) { sdp_printf(p, "s=%s" CRLF, subject); } static void print_information(sdp_printer_t *p, sdp_text_t *information) { sdp_printf(p, "i=%s" CRLF, information); } static void print_uri(sdp_printer_t *p, sdp_text_t *uri) { sdp_printf(p, "u=%s" CRLF, uri); } static void print_emails(sdp_printer_t *p, sdp_list_t const *emails) { print_text_list(p, "e=%s" CRLF, emails); } static void print_phones(sdp_printer_t *p, sdp_list_t const *phones) { print_text_list(p, "p=%s" CRLF, phones); } static void print_connection(sdp_printer_t *p, sdp_connection_t const *c) { sdp_printf(p, "c="); print_connection2(p, c); } static void print_connection_list(sdp_printer_t *p, sdp_connection_t const *c) { for (; c ; c = c->c_next) { sdp_printf(p, "c="); print_connection2(p, c); } } static void print_connection2(sdp_printer_t *p, sdp_connection_t const *c) { const char *nettype; const char *addrtype; switch (c->c_nettype) { case sdp_net_x: nettype = NULL; break; case sdp_net_in: nettype = "IN "; break; default: printing_error(p, "unknown nettype %u", c->c_nettype); return; } switch (c->c_addrtype) { case sdp_addr_x: addrtype = NULL; break; case sdp_addr_ip4: nettype = "IN "; addrtype = "IP4 "; break; case sdp_addr_ip6: nettype = "IN "; addrtype = "IP6 "; break; default: printing_error(p, "unknown address type %u", c->c_addrtype); return; } if (c->c_address == NULL) { printing_error(p, "missing address"); return; } if (nettype && addrtype) sdp_printf(p, "%s%s%s", nettype, addrtype, c->c_address); else if (nettype) sdp_printf(p, "%s%s%s", nettype, c->c_address); else sdp_printf(p, "%s", c->c_address); if (c->c_mcast || c->c_ttl) { sdp_printf(p, "/%u", c->c_ttl); if (c->c_groups > 1) sdp_printf(p, "/%u", c->c_groups); } sdp_printf(p, CRLF); } static void print_bandwidths(sdp_printer_t *p, sdp_bandwidth_t const *b) { for (; b ; b = b->b_next) { char const *name; switch (b->b_modifier) { case sdp_bw_ct: name = "CT"; break; case sdp_bw_as: name = "AS"; break; default: name = b->b_modifier_name; break; } sdp_printf(p, "b=%s:%lu" CRLF, name, b->b_value); } } static void print_time(sdp_printer_t *p, sdp_time_t const *t) { if (t || p->pr_strict) sdp_printf(p, "t=%lu %lu" CRLF, t ? t->t_start : 0L, t ? t->t_stop : 0L); } static void print_repeat(sdp_printer_t *p, sdp_repeat_t const *r) { int i; sdp_printf(p, "r="); print_typed_time(p, r->r_interval); sdp_printf(p, " "); print_typed_time(p, r->r_duration); for (i = 0; i < r->r_number_of_offsets; i++) { sdp_printf(p, " "); print_typed_time(p, r->r_offsets[i]); } sdp_printf(p, CRLF); } static void print_zone(sdp_printer_t *p, sdp_zone_t const *z) { int i; sdp_printf(p, "z="); for (i = 0; i < z->z_number_of_adjustments; i++) { int negative = z->z_adjustments[i].z_offset < 0L; sdp_printf(p, "%s%lu %s", i > 0 ? " " : "", z->z_adjustments[i].z_at, negative ? "-" : ""); if (negative) print_typed_time(p, -z->z_adjustments[i].z_offset); else print_typed_time(p, z->z_adjustments[i].z_offset); } sdp_printf(p, CRLF); } static void print_typed_time(sdp_printer_t *p, unsigned long t) { if (t % 60 || t == 0) { sdp_printf(p, "%lu", t); } else { t /= 60; if (t % 60) { sdp_printf(p, "%lum", t); /* minutes */ } else { t /= 60; if (t % 24) { sdp_printf(p, "%luh", t); /* hours */ } else { t /= 24; sdp_printf(p, "%lud", t); /* days */ } } } } static void print_key(sdp_printer_t *p, sdp_key_t const *k) { const char *method; int have_material = k->k_material != NULL; switch (k->k_method) { case sdp_key_x: method = k->k_method_name; break; case sdp_key_clear: method = "clear"; break; case sdp_key_base64: method = "base64"; break; case sdp_key_uri: method = "uri"; break; case sdp_key_prompt: method = "prompt"; break; default: printing_error(p, "unknown key method (%d)", k->k_method); return; } sdp_printf(p, "k=%s%s%s" CRLF, method, have_material ? ":" : "", have_material ? k->k_material : ""); } static void print_attributes(sdp_printer_t *p, sdp_attribute_t const *a) { for (;a; a = a->a_next) { char const *name = a->a_name; char const *value = a->a_value; sdp_printf(p, "a=%s%s%s" CRLF, name, value ? ":" : "", value ? value : ""); } } static void print_attributes_without_mode(sdp_printer_t *p, sdp_attribute_t const *a) { for (;a; a = a->a_next) { char const *name = a->a_name; char const *value = a->a_value; if (su_casematch(name, "inactive") || su_casematch(name, "sendonly") || su_casematch(name, "recvonly") || su_casematch(name, "sendrecv")) continue; sdp_printf(p, "a=%s%s%s" CRLF, name, value ? ":" : "", value ? value : ""); } } static void print_charset(sdp_printer_t *p, sdp_text_t *charset) { sdp_printf(p, "a=charset%s%s" CRLF, charset ? ":" : "", charset ? charset : ""); } static void print_media(sdp_printer_t *p, sdp_session_t const *sdp, sdp_media_t const *m) { char const *media, *proto; sdp_rtpmap_t *rm; sdp_mode_t session_mode = sdp_sendrecv; if (!p->pr_mode_manual) session_mode = sdp_attribute_mode(sdp->sdp_attributes, sdp_sendrecv); for (;m ; m = m->m_next) { switch (m->m_type) { case sdp_media_audio: media = "audio"; break; case sdp_media_video: media = "video"; break; case sdp_media_application: media = "application"; break; case sdp_media_data: media = "data"; break; case sdp_media_control: media = "control"; break; case sdp_media_message: media = "message"; break; case sdp_media_image : media = "image"; break; default: media = m->m_type_name; } switch (m->m_proto) { case sdp_proto_tcp: proto = "tcp"; break; case sdp_proto_udp: proto = "udp"; break; case sdp_proto_rtp: proto = "RTP/AVP"; break; case sdp_proto_srtp: proto = "RTP/SAVP"; break; case sdp_proto_udptl: proto = "udptl"; break; case sdp_proto_tls: proto = "tls"; break; default: proto = m->m_proto_name; break; } if (m->m_number_of_ports <= 1) sdp_printf(p, "m=%s %u %s", media, m->m_port, proto); else sdp_printf(p, "m=%s %u/%u %s", media, m->m_port, m->m_number_of_ports, proto); if (m->m_rtpmaps) { for (rm = m->m_rtpmaps; rm; rm = rm->rm_next) { if (rm->rm_any) sdp_printf(p, " *"); else sdp_printf(p, " %u", (unsigned)rm->rm_pt); } } else if (m->m_format) { sdp_list_t *l = m->m_format; for (; l; l = l->l_next) sdp_printf(p, " %s", l->l_text); } else { sdp_printf(p, " 19"); /* SDP syntax requires at least one format. 19 is used by nobody, right?. */ } sdp_printf(p, CRLF); if (m->m_information) print_information(p, m->m_information); if (m->m_connections) #ifdef nomore if (m->m_connections != sdp->sdp_connection) #endif print_connection_list(p, m->m_connections); if (m->m_bandwidths) print_bandwidths(p, m->m_bandwidths); if (m->m_key) print_key(p, m->m_key); for (rm = m->m_rtpmaps; rm; rm = rm->rm_next) { if (!rm->rm_predef || p->pr_all_rtpmaps) sdp_printf(p, "a=rtpmap:%u %s/%lu%s%s" CRLF, rm->rm_pt, rm->rm_encoding, rm->rm_rate, rm->rm_params ? "/" : "", rm->rm_params ? rm->rm_params : ""); if (rm->rm_fmtp) sdp_printf(p, "a=fmtp:%u %s" CRLF, rm->rm_pt, rm->rm_fmtp); } if (!p->pr_mode_manual && !m->m_rejected && (m->m_mode != (unsigned int)session_mode || p->pr_mode_always)) { switch (m->m_mode) { case sdp_inactive: sdp_printf(p, "a=inactive" CRLF); break; case sdp_sendonly: sdp_printf(p, "a=sendonly" CRLF); break; case sdp_recvonly: sdp_printf(p, "a=recvonly" CRLF); break; case sdp_sendrecv: sdp_printf(p, "a=sendrecv" CRLF); break; default: break; } } if (p->pr_mode_manual) print_attributes(p, m->m_attributes); else print_attributes_without_mode(p, m->m_attributes); } } static void print_text_list(sdp_printer_t *p, const char *fmt, sdp_list_t const *l) { for (;l; l = l->l_next) { sdp_printf(p, fmt, l->l_text); } } static void printing_error(sdp_printer_t *p, const char *fmt, ...) { va_list ap; if (p->pr_ok) { int n; va_start(ap, fmt); n = vsnprintf(p->pr_buffer, p->pr_bsiz, fmt, ap); va_end(ap); } p->pr_ok = 0; } static void sdp_printf(sdp_printer_t *p, const char *fmt, ...) { va_list ap; while (p->pr_ok) { int n; va_start(ap, fmt); n = vsnprintf(p->pr_buffer + p->pr_used, p->pr_bsiz - p->pr_used, fmt, ap); va_end(ap); if (n > -1 && (size_t)n < p->pr_bsiz - p->pr_used) { p->pr_used += n; break; } else { if (p->pr_owns_buffer) { p->pr_buffer = su_realloc(p->pr_home, p->pr_buffer, 2 * p->pr_bsiz); if (p->pr_buffer) { p->pr_bsiz = 2 * p->pr_bsiz; continue; } p->pr_owns_buffer = 0; } else if (p->pr_may_realloc) { char *buffer; size_t size; if (p->pr_bsiz < SDP_BLOCK) size = SDP_BLOCK; else size = 2 * p->pr_bsiz; buffer = su_alloc(p->pr_home, size); if (buffer) { p->pr_owns_buffer = 1; p->pr_buffer = memcpy(buffer, p->pr_buffer, p->pr_bsiz); p->pr_bsiz = size; continue; } } p->pr_ok = 0; p->pr_buffer = "Memory exhausted"; } } } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/sdp_tag.c000066400000000000000000000024121223300710500221240ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@internal * @file sdp_tag.c * @brief SDP Tags * * @author Pekka Pessi * * @date Created: Mon May 12 12:11:30 2003 ppessi * */ #include "config.h" #include #define TAG_NAMESPACE "sdp" #include tag_typedef_t sdptag_any = NSTAG_TYPEDEF(*); tag_typedef_t sdptag_session = {{ TAG_NAMESPACE, "session", sdptag_session_class }}; sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/sofia-sip/000077500000000000000000000000001223300710500222325ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/sofia-sip/sdp.h000066400000000000000000000464151223300710500232030ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef SDP_H #define SDP_H /**@file sofia-sip/sdp.h Simple SDP (RFC 2327) Interface. * * @author Pekka Pessi * @author Kai Vehmanen * * @date Created: Fri Feb 18 08:54:48 2000 ppessi */ #ifndef SU_ALLOC_H #include #endif #ifndef SU_TYPES_H #include #endif SOFIA_BEGIN_DECLS /** SDP session description */ typedef struct sdp_session_s sdp_session_t; /** SDP version "v=" line */ typedef unsigned long sdp_version_t; /** SDP origin "o=" line */ typedef struct sdp_origin_s sdp_origin_t; /** SDP connection "c=" line */ typedef struct sdp_connection_s sdp_connection_t; /** SDP bandwidth "b=" line */ typedef struct sdp_bandwidth_s sdp_bandwidth_t; /** SDP time "t=" line */ typedef struct sdp_time_s sdp_time_t; /** SDP repeat "r=" line */ typedef struct sdp_repeat_s sdp_repeat_t; /** SDP timezone "z=" line */ typedef struct sdp_zone_s sdp_zone_t; /** SDP encryption key "k=" line */ typedef struct sdp_key_s sdp_key_t; /** SDP attribute "a=" line */ typedef struct sdp_attribute_s sdp_attribute_t; /** SDP media "m=" line */ typedef struct sdp_media_s sdp_media_t; /** SDP list ("e=", "p=" lines) */ typedef struct sdp_list_s sdp_list_t; /** SDP rtpmap attribute */ typedef struct sdp_rtpmap_s sdp_rtpmap_t; /** Message text */ typedef char const sdp_text_t; #define SDP_MIME_TYPE "application/sdp" enum { SDP_CURRENT_VERSION = 0 }; /** Session description */ struct sdp_session_s { int sdp_size; /**< sizeof sdp_session_t */ sdp_session_t *sdp_next; /**< Next description in list */ sdp_version_t sdp_version[1]; /**< SDP version */ sdp_origin_t *sdp_origin; /**< Owner/creator and session ID */ sdp_text_t *sdp_subject; /**< Session name */ sdp_text_t *sdp_information; /**< Session information */ sdp_text_t *sdp_uri; /**< URi of description */ sdp_list_t *sdp_emails; /**< E-mail address(s) */ sdp_list_t *sdp_phones; /**< Phone number(s) */ sdp_connection_t *sdp_connection; /**< Group (or member) address */ sdp_bandwidth_t *sdp_bandwidths; /**< Session bandwidth */ sdp_time_t *sdp_time; /**< Session active time */ sdp_key_t *sdp_key; /**< Session key */ sdp_attribute_t *sdp_attributes; /**< Session attributes */ sdp_text_t *sdp_charset; /**< SDP charset (default is UTF8) */ sdp_media_t *sdp_media; /**< Media descriptors */ }; /** Session description identification */ struct sdp_origin_s { int o_size; /**< sizeof sdp_origin_t */ sdp_text_t *o_username; /**< Username of originator */ uint64_t o_id; /**< Session identification */ uint64_t o_version; /**< Version of session description */ sdp_connection_t *o_address; /**< Address of originator */ }; /** Network type */ typedef enum { sdp_net_x = 0, /**< Unknown network type */ sdp_net_in = 1 /**< Internet */ } sdp_nettype_e; /** Address type */ typedef enum { sdp_addr_x = 0, /**< Unknown address type */ sdp_addr_ip4 = 1, /**< IPv4 address */ sdp_addr_ip6 = 2, /**< IPv6 address */ } sdp_addrtype_e; /** SDP connection - host or group address */ struct sdp_connection_s { int c_size; /**< Size fo sdp_connection_t */ sdp_connection_t *c_next; /**< Next connection in list */ sdp_nettype_e c_nettype; /**< Network type */ sdp_addrtype_e c_addrtype; /**< Address type */ sdp_text_t *c_address; /**< Host or group address */ unsigned c_ttl : 8; /**< Time to live (scope) */ unsigned c_mcast : 1; /**< True if multicast */ unsigned : 0; unsigned c_groups; /**< Number of groups (if multiple) */ }; /** Bandwdith type */ typedef enum { sdp_bw_x, /**< Unknown bandwidth type */ sdp_bw_ct, /**< Conference total */ sdp_bw_as, /**< Application-specific */ } sdp_bandwidth_e; /** Session or media bandwidth. */ struct sdp_bandwidth_s { int b_size; /**< Size fo sdp_bandwidth_t */ sdp_bandwidth_t *b_next; /**< Next bw description in list */ sdp_bandwidth_e b_modifier; /**< Meaning of value (total, or per application). */ sdp_text_t *b_modifier_name; /**< Modifier if not well-known */ unsigned long b_value; /**< Bandwidth in kilobits per second */ }; /** Active time description. */ struct sdp_time_s { int t_size; /**< sizeof sdp_time_t in bytes */ sdp_time_t *t_next; /**< Next time description in list */ unsigned long t_start; /**< Start time (seconds since 1900) */ unsigned long t_stop; /**< Stop time (seconds since 1900) */ sdp_repeat_t *t_repeat; /**< Repeat information */ sdp_zone_t *t_zone; /**< Time Zone infromation */ }; /** Description of repetition. */ struct sdp_repeat_s { int r_size; /**< Size of structure including * r_offsets[r_number_of_offsets] */ int r_number_of_offsets; /**< Number of offsets in list */ unsigned long r_interval; /**< Time between activations */ unsigned long r_duration; /**< Duration of activation */ unsigned long r_offsets[1]; /**< List of offsets from start-time */ }; /** Timezone */ struct sdp_zone_s { /** Size of structure including z_adjustments[z_number_of_adjustments] */ int z_size; int z_number_of_adjustments; /**< Number of adjustments in list */ struct { unsigned long z_at; /**< Adjustment time */ long z_offset; /**< Adjustment offset */ } z_adjustments[1]; /**< List of timezone adjustments */ }; /** Mechanism to be used to obtain session key */ typedef enum { sdp_key_x, /**< Unknown mechanism */ sdp_key_clear, /**< Key is included untransformed */ sdp_key_base64, /**< Key is encoded with base64 */ sdp_key_uri, /**< URI used to obtain a key */ sdp_key_prompt /**< No key is included, prompt user for key */ } sdp_key_method_e; /** Session key */ struct sdp_key_s { int k_size; /**< sizeof sdp_key_t */ sdp_key_method_e k_method; /**< Mechanism used to obtain key */ sdp_text_t *k_method_name; /**< Mechanism if not known */ sdp_text_t *k_material; /**< Encryption key */ }; /** Session or media attribute */ struct sdp_attribute_s { int a_size; /**< sizeof sdp_attribute_t */ sdp_attribute_t *a_next; /**< Next attribute in list */ sdp_text_t *a_name; /**< Attribute name */ sdp_text_t *a_value; /**< Attribute value */ }; /** Media type @sa RFC2327 page 18. */ typedef enum { sdp_media_x = 0, /**< Unknown media */ sdp_media_any, /**< * wildcard */ sdp_media_audio, /**< Audio */ sdp_media_video, /**< Video */ sdp_media_application, /**< Conferencing */ sdp_media_data, /**< Bulk data transfer */ sdp_media_control, /**< Additional conference control */ sdp_media_message, /**< Messaging sessions*/ sdp_media_image, /**< Image browsing sessions, * e.g., JPIP or T.38. */ sdp_media_red /**< Redundancy. @NEW_1_12_4. */ } sdp_media_e; /** Media transport protocol. */ typedef enum { sdp_proto_x = 0, /**< Unknown transport */ sdp_proto_tcp = 6, /**< TCP */ sdp_proto_udp = 17, /**< Plain UDP */ sdp_proto_rtp = 256, /**< RTP/AVP */ sdp_proto_srtp = 257, /**< RTP/SAVP */ sdp_proto_udptl = 258, /**< UDPTL. @NEW_1_12_4. */ sdp_proto_tls = 511, /**< TLS over TCP */ sdp_proto_any = 512 /**< * wildcard */ } sdp_proto_e; /** Session mode. @note Identical to rtp_mode_t. */ typedef enum { sdp_inactive = 0, sdp_sendonly = 1, sdp_recvonly = 2, sdp_sendrecv = sdp_sendonly | sdp_recvonly } sdp_mode_t; /** Media announcement. * * This structure describes one media type, e.g., audio. The description * contains the transport address (IP address and port) used for the group, * the transport protocol used, the media formats or RTP payload types, and * optionally media-specific bandwidth specification, encryption key and * attributes. * * There is a pointer (m_user) for the application data, too. */ struct sdp_media_s { int m_size; /**< sizeof sdp_media_t */ sdp_media_t *m_next; /**< Next media announcement */ sdp_session_t *m_session; /**< Back-pointer to session level */ sdp_media_e m_type; /**< Media type */ sdp_text_t *m_type_name; /**< Media type name */ unsigned long m_port; /**< Transport port number */ unsigned long m_number_of_ports; /**< Number of ports (if multiple) */ sdp_proto_e m_proto; /**< Transport protocol */ sdp_text_t *m_proto_name; /**< Transport protocol name */ sdp_list_t *m_format; /**< List of media formats */ sdp_rtpmap_t *m_rtpmaps; /**< List of RTP maps */ sdp_text_t *m_information; /**< Media information */ sdp_connection_t *m_connections; /**< List of addresses used */ sdp_bandwidth_t *m_bandwidths; /**< Bandwidth specification */ sdp_key_t *m_key; /**< Media key */ sdp_attribute_t *m_attributes; /**< Media attributes */ void *m_user; /**< User data. */ /** Rejected media */ unsigned m_rejected : 1; /** Inactive, recvonly, sendonly, sendrecv */ /* sdp_mode_t */ unsigned m_mode : 2; unsigned : 0; }; /** Text list */ struct sdp_list_s { int l_size; /**< sizeof sdp_list_t */ sdp_list_t *l_next; /**< Next text entry in list */ sdp_text_t *l_text; /**< Text as C string */ }; /** Mapping from RTP payload to codec. * * The sdp_rtpmap_t() structure defines a mapping from an RTP payload to a * particular codec. In case of well-known payloads, the sdp_rtpmap_t() * structure may be predefined, that is, generated by SDP parser without * corresponding "a" line in the SDP. The sdp_rtpmap_t() structure may also * contain the @c fmtp attribute, which is used to convey format-specific * parameters. */ struct sdp_rtpmap_s { int rm_size; /**< sizeof sdp_rtpmap_t */ sdp_rtpmap_t *rm_next; /**< Next RTP map entry */ sdp_text_t *rm_encoding; /**< Codec name */ unsigned long rm_rate; /**< Sampling rate */ sdp_text_t *rm_params; /**< Format-specific parameters */ sdp_text_t *rm_fmtp; /**< Contents of fmtp */ unsigned rm_predef : 1; /**< is this entry well-known? */ unsigned rm_pt : 7; /**< Payload type */ unsigned rm_any : 1; /**< Wildcard entry */ unsigned :0; }; SOFIAPUBVAR sdp_rtpmap_t const * const sdp_rtpmap_well_known[128]; /** Duplicate an SDP session description structure. */ SOFIAPUBFUN sdp_session_t *sdp_session_dup(su_home_t *, sdp_session_t const *); /** Duplicate an SDP origin structure. */ SOFIAPUBFUN sdp_origin_t *sdp_origin_dup(su_home_t *, sdp_origin_t const *); /** Duplicate an SDP connection structure. */ SOFIAPUBFUN sdp_connection_t *sdp_connection_dup(su_home_t *, sdp_connection_t const *); /** Duplicate an SDP bandwidth structure. */ SOFIAPUBFUN sdp_bandwidth_t *sdp_bandwidth_dup(su_home_t *, sdp_bandwidth_t const *); /** Duplicate an SDP time structure. */ SOFIAPUBFUN sdp_time_t *sdp_time_dup(su_home_t *, sdp_time_t const *); /** Duplicate an SDP repeat structure. */ SOFIAPUBFUN sdp_repeat_t *sdp_repeat_dup(su_home_t *, sdp_repeat_t const *); /** Duplicate an SDP timezone structure. */ SOFIAPUBFUN sdp_zone_t *sdp_zone_dup(su_home_t *, sdp_zone_t const *); /** Duplicate an SDP key structure. */ SOFIAPUBFUN sdp_key_t *sdp_key_dup(su_home_t *, sdp_key_t const *); /** Duplicate an SDP attribute structure. */ SOFIAPUBFUN sdp_attribute_t *sdp_attribute_dup(su_home_t *, sdp_attribute_t const *); /** Duplicate an SDP media description structure. */ SOFIAPUBFUN sdp_media_t *sdp_media_dup(su_home_t *, sdp_media_t const *, sdp_session_t *); /** Duplicate a list of SDP media description structures. */ SOFIAPUBFUN sdp_media_t *sdp_media_dup_all(su_home_t *, sdp_media_t const *, sdp_session_t *); /** Duplicate a list structure. */ SOFIAPUBFUN sdp_list_t *sdp_list_dup(su_home_t *, sdp_list_t const *); /** Duplicate an rtpmap structure. */ SOFIAPUBFUN sdp_rtpmap_t *sdp_rtpmap_dup(su_home_t *, sdp_rtpmap_t const *); /** Compare two session descriptions. */ SOFIAPUBFUN int sdp_session_cmp(sdp_session_t const *a, sdp_session_t const *b); /** Compare two origin fields */ SOFIAPUBFUN int sdp_origin_cmp(sdp_origin_t const *a, sdp_origin_t const *b); /** Compare two connection fields */ SOFIAPUBFUN int sdp_connection_cmp(sdp_connection_t const *, sdp_connection_t const *b); /** Compare two bandwidth (b=) fields */ SOFIAPUBFUN int sdp_bandwidth_cmp(sdp_bandwidth_t const *a, sdp_bandwidth_t const *b); /** Compare two time fields */ SOFIAPUBFUN int sdp_time_cmp(sdp_time_t const *a, sdp_time_t const *b); /* Compare two repeat (r=) fields */ SOFIAPUBFUN int sdp_repeat_cmp(sdp_repeat_t const *a, sdp_repeat_t const *b); /* Compare two zone (z=) fields */ SOFIAPUBFUN int sdp_zone_cmp(sdp_zone_t const *a, sdp_zone_t const *b); /** Compare two key (k=) fields. */ SOFIAPUBFUN int sdp_key_cmp(sdp_key_t const *a, sdp_key_t const *b); /** Compare two attribute (a=) fields */ SOFIAPUBFUN int sdp_attribute_cmp(sdp_attribute_t const *, sdp_attribute_t const *); /** Compare two media (m=) descriptions */ SOFIAPUBFUN int sdp_media_cmp(sdp_media_t const *, sdp_media_t const *); /** Compare two rtpmap structures. */ SOFIAPUBFUN int sdp_rtpmap_cmp(sdp_rtpmap_t const *a, sdp_rtpmap_t const *b); /** Compare two text lists */ SOFIAPUBFUN int sdp_list_cmp(sdp_list_t const *a, sdp_list_t const *b); /** Get connections of a media description */ SOFIAPUBFUN sdp_connection_t *sdp_media_connections(sdp_media_t const *m); /** Check if media uses RTP as its transport protocol */ SOFIAPUBFUN int sdp_media_has_rtp(sdp_media_t const *m); /** Set media type */ SOFIAPUBFUN void sdp_media_type(sdp_media_t *m, char const *s); /** Set transport protocol */ SOFIAPUBFUN void sdp_media_transport(sdp_media_t *m, char const *s); /** Find named attribute from given list. */ SOFIAPUBFUN sdp_attribute_t *sdp_attribute_find(sdp_attribute_t const *a, char const *name); /** Find named attribute from given lists. */ SOFIAPUBFUN sdp_attribute_t *sdp_attribute_find2(sdp_attribute_t const *a, sdp_attribute_t const *a2, char const *name); /** Get session mode from attribute list. */ SOFIAPUBFUN sdp_mode_t sdp_attribute_mode(sdp_attribute_t const *a, sdp_mode_t defmode); /** Get session mode from attribute list. */ SOFIAPUBFUN sdp_attribute_t *sdp_attribute_by_mode(su_home_t *, sdp_mode_t mode); /** Find a mapped attribute. */ SOFIAPUBFUN sdp_attribute_t *sdp_attribute_mapped_find(sdp_attribute_t const *a, char const *name, int pt, char **return_result); /** Append a attribute to a list of attributes. */ SOFIAPUBFUN void sdp_attribute_append(sdp_attribute_t **list, sdp_attribute_t const *a); /** Replace a attribute within a list of attributes. */ SOFIAPUBFUN int sdp_attribute_replace(sdp_attribute_t **list, sdp_attribute_t *a, sdp_attribute_t **return_replaced); /** Remove a named attribute from a list of attributes. */ SOFIAPUBFUN sdp_attribute_t *sdp_attribute_remove(sdp_attribute_t **list, char const *name); /* Return 1 if m= line struct matches with given type and name */ SOFIAPUBFUN unsigned sdp_media_match(sdp_media_t const *m, sdp_media_e type, sdp_text_t *type_name, sdp_proto_e proto, sdp_text_t *proto_name); SOFIAPUBFUN unsigned sdp_media_match_with(sdp_media_t const *a, sdp_media_t const *b); /** Count media lines in SDP. */ SOFIAPUBFUN unsigned sdp_media_count(sdp_session_t const *sdp, sdp_media_e type, sdp_text_t *type_name, sdp_proto_e proto, sdp_text_t *proto_name); SOFIAPUBFUN unsigned sdp_media_count_with(sdp_session_t const *sdp, sdp_media_t const *m0); /** Return true if media uses RTP */ SOFIAPUBFUN int sdp_media_uses_rtp(sdp_media_t const *m); /** Check if payload type, rtp rate and parameters match in rtpmaps*/ SOFIAPUBFUN int sdp_rtpmap_match(sdp_rtpmap_t const *, sdp_rtpmap_t const *); /** Search for matching rtpmap from list */ SOFIAPUBFUN sdp_rtpmap_t *sdp_rtpmap_find_matching(sdp_rtpmap_t const *list, sdp_rtpmap_t const *rm); /* ======================================================================== */ /** Flags given to sdp_parse()/sdp_print(). */ enum sdp_parse_flags_e { /** Accept only conforming SDP */ sdp_f_strict = 1, /** Accept any network type. */ sdp_f_anynet = 2, /** Reallocate message. */ sdp_f_realloc = 4, /** Include well-known rtpmaps in message, too */ sdp_f_all_rtpmaps = 8, /** Print buffer already contains a valid prefix */ sdp_f_print_prefix = 16, /** Connection line with INADDR_ANY is considered equal to sendonly */ sdp_f_mode_0000 = 32, /** Don't run sanity check */ sdp_f_insane = 64, /** Don't require c= for each media line */ sdp_f_c_missing = 128, /** Parse SDP config files */ sdp_f_config = 256, /** Do not generate or parse SDP mode */ sdp_f_mode_manual = 512, /** Always generate media-level mode attributes */ sdp_f_mode_always = 1024 }; /** SDP parser handle. */ typedef struct sdp_parser_s sdp_parser_t; typedef sdp_parser_t *sdp_parser; SOFIAPUBFUN sdp_parser_t *sdp_parse(su_home_t *, char const msg[], issize_t msgsize, int flags); SOFIAPUBFUN char const *sdp_parsing_error(sdp_parser_t *p); SOFIAPUBFUN sdp_session_t *sdp_session(sdp_parser_t *p); SOFIAPUBFUN void sdp_parser_free(sdp_parser_t *p); SOFIAPUBFUN int sdp_sanity_check(sdp_parser_t *); SOFIAPUBFUN su_home_t *sdp_parser_home(sdp_parser_t *); /* ======================================================================== */ /** SDP printer handle */ typedef struct sdp_printer_s sdp_printer_t; typedef sdp_printer_t *sdp_printer; SOFIAPUBFUN sdp_printer_t *sdp_print(su_home_t *, sdp_session_t const *, char msgbuf[], isize_t maxmsgsize, int flags); SOFIAPUBFUN char const *sdp_printing_error(sdp_printer_t *p); SOFIAPUBFUN char const *sdp_message(sdp_printer_t *p); SOFIAPUBFUN isize_t sdp_message_size(sdp_printer_t *p); SOFIAPUBFUN void sdp_printer_free(sdp_printer_t *p); #define sdp_mapped_attribute_find sdp_attribute_mapped_find #define sdp_free_parser sdp_parser_free #define sdp_free_printer sdp_printer_free SOFIA_END_DECLS #endif /* SDP_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/sofia-sip/sdp_tag.h000066400000000000000000000044371223300710500240340ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef SDP_TAG_H /** Defined when has been included. */ #define SDP_TAG_H /**@file sofia-sip/sdp_tag.h * @brief SDP tags * * @author Pekka Pessi * * @date Created: Mon May 12 12:06:20 EEST 2003 ppessi * @{ */ #ifndef SU_TAG_H #include #endif #ifndef SU_TAG_CLASS_H #include #endif SOFIA_BEGIN_DECLS struct sdp_session_s; /** Filter tag matching any sdp tag. */ #define SDPTAG_ANY() sdptag_any, ((tag_value_t)0) SDP_DLL extern tag_typedef_t sdptag_any; /* Tags for parameters */ SDP_DLL extern tag_typedef_t sdptag_session; /** SDP session description. @HI */ #define SDPTAG_SESSION(x) \ sdptag_session, sdptag_session_v((x)) SDP_DLL extern tag_typedef_t sdptag_session_ref; #define SDPTAG_SESSION_REF(x) \ sdptag_session_ref, sdptag_session_vr(&(x)) /* Functions for typesafe parameter passing */ #if SU_HAVE_INLINE su_inline tag_value_t sdptag_session_v(struct sdp_session_s const *v) { return (tag_value_t)v; } su_inline tag_value_t sdptag_session_vr(struct sdp_session_s const **vp) { return (tag_value_t)vp; } #else #define sdptag_session_v(v) (tag_value_t)(v) #define sdptag_session_vr(vp) (tag_value_t)(vp) #endif /* Tag classes */ extern tag_class_t sdptag_session_class[]; #define SDPTAG_TYPEDEF(name) \ {{ TAG_NAMESPACE, #name, sdptag_session_class }} SOFIA_END_DECLS #endif /* !defined(SDP_TAG_H) */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/test_sdp.c000066400000000000000000000057561223300710500223460ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@internal * * @CFILE test_sdp.c * * Simple SDP tester * * @author Pekka Pessi * * @date Created : Fri Feb 18 10:25:08 2000 ppessi */ #include "config.h" #include #include #include #include #include "sofia-sip/sdp.h" int diff(const char *olds, const char *news, int *linep, int *pos) { const char *o, *n; *linep = 0; for (o = olds, n = news; *o && *n && *o == *n ; o++, n++) { if (*o == '\n') ++*linep; } *pos = o - olds; return *o != *n; } int main(int argc, char *argv[]) { char buffer[2048]; int n; su_home_t *home = su_home_new(sizeof *home); int exitcode = 1; FILE *f; if (argv[1] && strcmp(argv[1], "-")) f = fopen(argv[1], "rb"); else f = stdin; n = fread(buffer, 1, sizeof(buffer) - 1, f); buffer[n] = 0; if (feof(f)) { sdp_parser_t *p = sdp_parse(home, buffer, n + 1, 0); su_home_check(home); su_home_check((su_home_t *)p); if (sdp_session(p)) { sdp_session_t *sdp, *dup; sdp_printer_t *printer; sdp = sdp_session(p); dup = sdp_session_dup(home, sdp); su_home_check(home); sdp_parser_free(p), p = NULL; su_home_check(home); printer = sdp_print(home, dup, NULL, 0, 0); su_home_check(home); if (sdp_message(printer)) { int line, pos; if (diff(buffer, sdp_message(printer), &line, &pos)) { fprintf(stdout, "test_sdp:%d: messages differ:\n", line); fputs(buffer, stdout); fprintf(stdout, ">>>new message:\n"); fputs(sdp_message(printer), stdout); } else { exitcode = 0; } } else { fprintf(stderr, "test_sdp: %s\n", sdp_printing_error(printer)); } sdp_printer_free(printer); su_home_check(home); } else { fprintf(stderr, "test_sdp: %s\n", sdp_parsing_error(p)); sdp_parser_free(p); exit(1); } } else { if (ferror(f)) { perror("test_sdp"); } else { fprintf(stderr, "test_sdp: maximum length of sdp messages is %u bytes\n", (unsigned)sizeof(buffer)); } exit(1); } su_home_unref(home); return exitcode; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/tests/000077500000000000000000000000001223300710500215025ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/tests/message-1.sdp000066400000000000000000000000051223300710500237670ustar00rootroot00000000000000v=1 sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/tests/message-10.sdp000066400000000000000000000015301223300710500240530ustar00rootroot00000000000000v=0 o=ppessi 2890844526 13 IN IP4 126.16.64.4 s=Testing sdp parser quirks i=A Seminar on the session description protocol u=http://www.cs.ucl.ac.uk/staff/M.Handley/sdp.03.ps e=mjh@isi.edu (Mark Handley) e=mjh@mail.isi.edu (Mark Handley) p=+358 9 4376 1 p=+1 442 555 6782 c=IN IP4 224.2.17.12/127/2 b=CT:512 t=2873397496 2873404696 r=7d 1h 1d 1d 1d 1d 1d z=2882844526 -1h 2898848070 0 k=uri:shttp://foo.bar.com/session/key a=recvonly m=audio 49230 RTP/AVP 0 96 97 98 99 100 b=AS:360 a=rtpmap:96 L8/8000 a=rtpmap:97 L16/8000 a=rtpmap:98 L16/11025/2 a=rtpmap:99 GSM-EFR/8000 a=rtpmap:100 X-AMR/8000 a=fmtp:100 mode-set=4,5,6 interleaving crc vad=on use-redundancy=1 m=video 51372/2 RTP/AVP 31 c=IN IP4 224.2.17.12/127 c=IN IP4 224.2.17.13/127 b=AS:16 a=rtpmap:31 H261/90000 m=application 32416 udp wb b=AS:32 a=orient:portrait sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/tests/message-11.sdp000066400000000000000000000015101223300710500240520ustar00rootroot00000000000000v=0 o=- 3250588766 0 IN IP4 77.75.1.10 s=- c=IN IP4 77.75.1.10 t=0 0 m=audio 54424 RTP/AVP 18 99 101 102 103 15 104 4 105 106 107 108 125 109 100 8 0 a=rtpmap:18 G729/8000 a=fmtp:18 annexb=no a=rtpmap:99 G.729a/8000 a=rtpmap:101 G.726-16/8000 a=rtpmap:102 G.726-24/8000 a=rtpmap:103 G.726-32/8000 a=rtpmap:15 G728/8000 a=rtpmap:104 G.723.1-H/8000 a=rtpmap:4 G723/8000 a=rtpmap:105 G.723.1-L/8000 a=rtpmap:106 G.729b/8000 a=rtpmap:107 G.723.1a-H/8000 a=rtpmap:108 G.723.1a-L/8000 a=rtpmap:125 G.nX64/8000 a=rtpmap:109 AMR/8000 a=rtpmap:100 X-NSE/8000 a=fmtp:100 192-194,200-202 a=rtpmap:8 PCMA/8000 a=rtpmap:0 PCMU/8000 a=maxptime:20 a=maxptime:30 a=ptime:20 a=ptime:30 a=X-cap: 1 audio RTP/AVP 100 a=X-cap: 2 image udptl t38 a=X-sqn:0 a=X-cpar: a=rtpmap:100 X-NSE/8000 a=X-cpar: a=fmtp:100 192-194,200-202 sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/tests/message-2.sdp000066400000000000000000000005561223300710500240030ustar00rootroot00000000000000v=0 o=mhandley 2890844526 2890842807 IN IP4 126.16.64.4 s=SDP Seminar i=A Seminar on the session description protocol u=http://www.cs.ucl.ac.uk/staff/M.Handley/sdp.03.ps e=mjh@isi.edu (Mark Handley) c=IN IP4 224.2.17.12/127 t=2873397496 2873404696 a=recvonly m=audio 49170 RTP/AVP 0 m=video 51372 RTP/AVP 31 m=application 32416 udp wb a=orient:portrait sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/tests/message-3.sdp000066400000000000000000000002721223300710500237770ustar00rootroot00000000000000v=0 o=user1 53655765 2353687637 IN IP4 128.3.4.5 s=Mbone Audio i=Discussion of Mbone Engineering Issues e=mbone@somewhere.com c=IN IP4 224.2.0.1/127 t=0 0 m=audio 3456 RTP/AVP 0 sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/tests/message-4.sdp000066400000000000000000000001511223300710500237740ustar00rootroot00000000000000v=0 o=bell 53655765 2353687637 IN IP4 128.3.4.5 c=IN IP4 135.180.144.94 m=audio 3456 RTP/AVP 0 3 4 5 sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/tests/message-5.sdp000066400000000000000000000001711223300710500237770ustar00rootroot00000000000000v=0 o=watson 4858949 4858949 IN IP4 192.1.2.3 s=I'm on my way c=IN IP4 boston.bell-tel.com m=audio 5004 RTP/AVP 0 3 sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/tests/message-6.sdp000066400000000000000000000001571223300710500240040ustar00rootroot00000000000000v=0 s=Let's talk c=IN IP4 north.east.isi.edu b=CT:128 m=audio 3456 RTP/AVP 5 0 7 m=video 2232 RTP/AVP 31 sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/tests/message-7.sdp000066400000000000000000000004231223300710500240010ustar00rootroot00000000000000v=0 o=alice 2890844526 2890844526 IN IP4 host.anywhere.com i=First example from RFC 2543 page 136 c=IN IP4 host.anywhere.com m=audio 49170 RTP/AVP 0 a=rtpmap:0 PCMU/8000 m=video 51372 RTP/AVP 31 a=rtpmap:31 H261/90000 m=video 53000 RTP/AVP 32 a=rtpmap:32 MPV/90000 sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/tests/message-8.sdp000066400000000000000000000004131223300710500240010ustar00rootroot00000000000000v=0 o=bob 2890844730 2890844730 IN IP4 host.example.com i=First example from RFC 2543 page 136 c=IN IP4 host.example.com m=audio 47920 RTP/AVP 0 1 a=rtpmap:0 PCMU/8000 a=rtpmap:1 1016/8000 m=video 0 RTP/AVP 31 m=video 53000 RTP/AVP 32 a=rtpmap:32 MPV/90000 sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/tests/message-9.sdp000066400000000000000000000011561223300710500240070ustar00rootroot00000000000000v=0 o=ppessi 2890844526 0 IN IP4 126.16.64.4 s=Testing sdp parser quirks i=A Seminar on the session description protocol u=http://www.cs.ucl.ac.uk/staff/M.Handley/sdp.03.ps e=mjh@isi.edu (Mark Handley) c=IN IP4 224.2.17.12/127/2 b=CT:512 t=2873397496 2873404696 a=recvonly m=audio 49230 RTP/AVP 0 96 97 98 99 100 b=AS:360 a=rtpmap:96 L8/8000 a=rtpmap:97 L16/8000 a=rtpmap:98 L16/11025/2 a=rtpmap:99 GSM-EFR/8000 a=rtpmap:100 X-AMR/8000 m=video 51372/2 RTP/AVP 31 c=IN IP4 224.2.17.12/127 c=IN IP4 224.2.17.13/127 b=AS:16 a=rtpmap:31 H261/90000 m=application 32416 udp wb b=AS:32 a=orient:portrait sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sdp/torture_sdp.c000066400000000000000000000622131223300710500230620ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@internal * * @CFILE sdp_torture.c * * Torture testing sdp module. * * @author Pekka Pessi * @author Kai Vehmanen * * @date Created: Tue Mar 6 18:33:42 2001 ppessi */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #define TSTFLAGS tstflags #include int tstflags; char const *name = "torture_sdp.c"; FILE *null; static char const e0_msg[] = "foo"; static char const e1_msg[] = "v=1\n" "s=/sdp_torture\n" "o=sdp_torture 0 0 IN IP4 0.0.0.0\n" "m=audio 0 RTP/AVP 96 97 98 10 99 8 0\n" "a=rtpmap:96 X-AMR-WB/16000\n" "a=rtpmap:97 X-AMR/8000\n" "a=rtpmap:98 GSM-EFR/8000\n" "a=rtpmap:10 L16/16000\n" "a=rtpmap:99 G723/8000\n" "a=rtpmap:8 PCMA/8000\n" "a=rtpmap:0 PCMU/8000\n" "m=video 0 *"; static int test_error(void) { su_home_t *home = su_home_new(sizeof *home); sdp_parser_t *parser; BEGIN(); su_home_check(home); TEST0(home); TEST_1((parser = sdp_parse(home, e0_msg, sizeof(e0_msg), 0))); TEST_1(sdp_session(parser) == NULL); TEST_1(sdp_parsing_error(parser)); sdp_parser_free(parser); TEST_1((parser = sdp_parse(home, e1_msg, sizeof(e1_msg), 0))); TEST_1(sdp_session(parser) == NULL); TEST_1(sdp_parsing_error(parser)); sdp_parser_free(parser); /* destroy the home objects */ su_home_check(home); su_home_zap(home); END(); } static char const s0_msg[] = "v=0\n" "s=/sdp_torture\n" "o=sdp_torture 0 0 IN IP4 0.0.0.0\n" "m=audio 0 RTP/AVP 96 97 98 10 99 8 0\n" "a=rtpmap:96 X-AMR-WB/16000\n" "a=rtpmap:97 X-AMR/8000\n" "a=rtpmap:98 GSM-EFR/8000\n" "a=rtpmap:10 L16/16000\n" "a=rtpmap:99 G723/8000\n" "a=rtpmap:8 PCMA/8000\n" "a=rtpmap:0 PCMU/8000\n" "m=video 0 *\n" "m=* 0 RTP/AVP *\n" ; static int test_session(void) { su_home_t *home = su_home_new(sizeof *home), *home2 = su_home_create(); sdp_session_t *sdp_src, *sdp_target; sdp_session_t const *sdp = NULL; sdp_parser_t *parser; sdp_printer_t *printer; sdp_media_t *m; char buffer[512]; tagi_t *lst, *dup; BEGIN(); su_home_check(home); TEST_1(home); su_home_check(home2); TEST_1(home2); TEST_1((parser = sdp_parse(home, s0_msg, sizeof(s0_msg), sdp_f_config))); TEST_1((sdp_src = sdp_session(parser))); TEST_1(sdp_src->sdp_media); TEST_1(sdp_src->sdp_media->m_session); TEST_P(sdp_src->sdp_media->m_session, sdp_src); /* clone the session using 'home2' */ TEST_1((sdp_target = sdp_session_dup(home2, sdp_src))); /* Check comparing */ TEST(sdp_session_cmp(sdp_src, sdp_target), 0); /* check the cloned session */ TEST_1(sdp_target->sdp_subject); TEST_S(sdp_target->sdp_subject, "/sdp_torture"); strcpy((char*)sdp_target->sdp_subject, "garbage"); TEST_S(sdp_src->sdp_subject, "/sdp_torture"); TEST_1(sdp_target->sdp_origin); TEST_1(sdp_target->sdp_origin->o_username); TEST_S(sdp_target->sdp_origin->o_username, "sdp_torture"); strcpy((char*)sdp_target->sdp_origin->o_username, "garbage"); TEST_S(sdp_src->sdp_origin->o_username, "sdp_torture"); TEST_1(m = sdp_target->sdp_media); TEST_P(m->m_session, sdp_target); TEST_1(sdp_src->sdp_media->m_session != sdp_target->sdp_media->m_session); TEST(m->m_type, sdp_media_audio); TEST_S(m->m_type_name, "audio"); TEST(m->m_port, 0); TEST(m->m_number_of_ports, 0); TEST(m->m_proto, sdp_proto_rtp); TEST_S(m->m_proto_name, "RTP/AVP"); /* FIXME: add more tests */ /* frees all data created by the parser including 'sdp_src' */ sdp_parser_free(parser); /* destroy the first home instance */ su_home_check(home); su_home_unref(home); /* access all cloned data by printing it */ printer = sdp_print(home2, sdp_target, buffer, sizeof(buffer), 0); if (printer != NULL) { char const *msg = sdp_message(printer); if (tstflags & tst_verbatim) { printf("sdp_torture.c: parsed SDP message:\"%s\".\n", msg); } sdp_printer_free(printer); } TEST_1(lst = tl_list(SDPTAG_SESSION(sdp_target), TAG_NULL())); TEST_1(dup = tl_adup(home2, lst)); if (tstflags & tst_verbatim) tl_print(stdout, "dup:\n", dup); else tl_print(null, "dup:\n", dup); TEST(tl_gets(dup, SDPTAG_SESSION_REF(sdp), TAG_END()), 1); /* access all copied data by printing it */ printer = sdp_print(home2, sdp, buffer, sizeof(buffer), 0); if (printer != NULL) { char const *msg = sdp_message(printer); if (tstflags & tst_verbatim) { printf("sdp_torture.c: " "SDP message passed through tag list:\n\"%s\".\n", msg); } sdp_printer_free(printer); } su_free(home2, dup); tl_vfree(lst); /* destroy the second home object */ su_home_check(home2); su_home_unref(home2); END(); } static char const s1_msg[] = "v=0\r\n" "o=- 2435697 2435697 IN IP4 172.21.137.44\r\n" "s=-\r\n" "c=IN IP4 172.21.137.44\r\n" "t=0 0\r\n" "a=sendonly\r\n" "m=video 49154 RTP/AVP 96 24 25 26 28 31 32 33 34\r\n" "a=rtpmap:96 H263-1998/90000\r\n" "m=audio 49152 RTP/AVP 97 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19\r\n" "a=rtpmap 97 AMR/8000\r\n" "a=fmtp:97 mode-set=\"0,1,2,3,4\"\r\n" "a=ptime:400\r\n"; static char const s2_msg[] = "v=0\r\n" "o=- 308519342 2 IN IP4 172.168.1.55\r\n" "s=-\r\n" "c=IN IP4 172.168.1.55\r\n" "t=0 0\r\n" "a=recvonly\r\n" "m=video 59154 RTP/AVP 96\r\n" "b=AS:64\r\n" "a=rtpmap:96 H263-1998/90000\r\n" "a=framerate:8\r\n" "a=fmtp:96 QCIF=4\r\n" "m=audio 59152 RTP/AVP 97\r\n" "b=AS:8\r\n" "a=rtpmap:97 AMR/8000\r\n" "a=fmtp:97 mode-set=\"0\"\r\n" "a=maxptime:500\r\n"; static int test_session2(void) { su_home_t *home = su_home_new(sizeof *home); sdp_session_t const *sdp = NULL; sdp_parser_t *parser; sdp_media_t *m; sdp_rtpmap_t *rm; BEGIN(); su_home_check(home); TEST_1(home); TEST_1((parser = sdp_parse(home, s1_msg, sizeof(s1_msg), 0))); TEST_1((sdp = sdp_session(parser))); TEST_1(m = sdp->sdp_media); TEST(m->m_mode, sdp_sendonly); TEST_P(m->m_session, sdp); TEST_1(rm = m->m_rtpmaps); TEST(rm->rm_pt, 96); TEST_S(rm->rm_encoding, "H263-1998"); TEST(rm->rm_rate, 90000); { #define RTPMAP(pt, type, rate, params) \ { sizeof(sdp_rtpmap_t), NULL, type, rate, (char *)params, NULL, 1, pt, 0 } /* rtpmaps for well-known video codecs */ static sdp_rtpmap_t const sdp_rtpmap_celb = RTPMAP(25, "CelB", 90000, 0), sdp_rtpmap_jpeg = RTPMAP(26, "JPEG", 90000, 0), sdp_rtpmap_nv = RTPMAP(28, "nv", 90000, 0), sdp_rtpmap_h261 = RTPMAP(31, "H261", 90000, 0), sdp_rtpmap_mpv = RTPMAP(32, "MPV", 90000, 0), sdp_rtpmap_mp2t = RTPMAP(33, "MP2T", 90000, 0), sdp_rtpmap_h263 = RTPMAP(34, "H263", 90000, 0); TEST_1(rm = rm->rm_next); TEST_S(rm->rm_encoding, ""); TEST(rm->rm_rate, 0); TEST_1(rm = rm->rm_next); TEST_P(sdp_rtpmap_find_matching(&sdp_rtpmap_celb, rm), &sdp_rtpmap_celb); TEST_1(rm = rm->rm_next); TEST_P(sdp_rtpmap_find_matching(&sdp_rtpmap_jpeg, rm), &sdp_rtpmap_jpeg); TEST_1(rm = rm->rm_next); TEST_P(sdp_rtpmap_find_matching(&sdp_rtpmap_nv, rm), &sdp_rtpmap_nv); TEST_1(rm = rm->rm_next); TEST_P(sdp_rtpmap_find_matching(&sdp_rtpmap_h261, rm), &sdp_rtpmap_h261); TEST_1(rm = rm->rm_next); TEST_P(sdp_rtpmap_find_matching(&sdp_rtpmap_mpv, rm), &sdp_rtpmap_mpv); TEST_1(rm = rm->rm_next); TEST_P(sdp_rtpmap_find_matching(&sdp_rtpmap_mp2t, rm), &sdp_rtpmap_mp2t); TEST_1(rm = rm->rm_next); TEST_P(sdp_rtpmap_find_matching(&sdp_rtpmap_h263, rm), &sdp_rtpmap_h263); TEST_1(!rm->rm_next); } TEST_1(m = m->m_next); TEST(m->m_mode, sdp_sendonly); TEST_P(m->m_session, sdp); TEST_1(rm = m->m_rtpmaps); TEST(rm->rm_pt, 97); TEST_S(rm->rm_encoding, "AMR"); TEST(rm->rm_rate, 8000); TEST_S(rm->rm_fmtp, "mode-set=\"0,1,2,3,4\""); { /* rtpmaps for well-known audio codecs */ static sdp_rtpmap_t const sdp_rtpmap_pcmu = RTPMAP(0, "PCMU", 8000, "1"), sdp_rtpmap_1016 = RTPMAP(1, "1016", 8000, "1"), sdp_rtpmap_g721 = RTPMAP(2, "G721", 8000, "1"), sdp_rtpmap_gsm = RTPMAP(3, "GSM", 8000, "1"), sdp_rtpmap_g723 = RTPMAP(4, "G723", 8000, "1"), sdp_rtpmap_dvi4_8000 = RTPMAP(5, "DVI4", 8000, "1"), sdp_rtpmap_dvi4_16000 = RTPMAP(6, "DVI4", 16000, "1"), sdp_rtpmap_lpc = RTPMAP(7, "LPC", 8000, "1"), sdp_rtpmap_pcma = RTPMAP(8, "PCMA", 8000, "1"), sdp_rtpmap_g722 = RTPMAP(9, "G722", 8000, "1"), sdp_rtpmap_l16 = RTPMAP(10, "L16", 44100, "2"), sdp_rtpmap_l16_stereo = RTPMAP(11, "L16", 44100, "1"), sdp_rtpmap_qcelp = RTPMAP(12, "QCELP", 8000, "1"), sdp_rtpmap_cn = RTPMAP(13, "CN", 8000, "1"), sdp_rtpmap_mpa = RTPMAP(14, "MPA", 90000, 0), sdp_rtpmap_g728 = RTPMAP(15, "G728", 8000, "1"), sdp_rtpmap_dvi4_11025 = RTPMAP(16, "DVI4", 11025, "1"), sdp_rtpmap_dvi4_22050 = RTPMAP(17, "DVI4", 22050, "1"), sdp_rtpmap_g729 = RTPMAP(18, "G729", 8000, "1"), sdp_rtpmap_cn_reserved = RTPMAP(19, "CN", 8000, "1"); TEST_1(rm = rm->rm_next); TEST_1(sdp_rtpmap_match(&sdp_rtpmap_pcmu, rm)); TEST_P(sdp_rtpmap_find_matching(&sdp_rtpmap_pcmu, rm), &sdp_rtpmap_pcmu); TEST_1(rm = rm->rm_next); TEST_1(sdp_rtpmap_match(&sdp_rtpmap_1016, rm)); TEST_P(sdp_rtpmap_find_matching(&sdp_rtpmap_1016, rm), &sdp_rtpmap_1016); TEST_1(rm = rm->rm_next); TEST_1(sdp_rtpmap_match(&sdp_rtpmap_g721, rm)); TEST_P(sdp_rtpmap_find_matching(&sdp_rtpmap_g721, rm), &sdp_rtpmap_g721); TEST_1(rm = rm->rm_next); TEST_1(sdp_rtpmap_match(&sdp_rtpmap_gsm, rm)); TEST_P(sdp_rtpmap_find_matching(&sdp_rtpmap_gsm, rm), &sdp_rtpmap_gsm); TEST_1(rm = rm->rm_next); TEST_1(sdp_rtpmap_match(&sdp_rtpmap_g723, rm)); TEST_P(sdp_rtpmap_find_matching(&sdp_rtpmap_g723, rm), &sdp_rtpmap_g723); TEST_1(rm = rm->rm_next); TEST_1(sdp_rtpmap_match(&sdp_rtpmap_dvi4_8000, rm)); TEST_P(sdp_rtpmap_find_matching(&sdp_rtpmap_dvi4_8000, rm), &sdp_rtpmap_dvi4_8000); TEST_1(rm = rm->rm_next); TEST_1(sdp_rtpmap_match(&sdp_rtpmap_dvi4_16000, rm)); TEST_P(sdp_rtpmap_find_matching(&sdp_rtpmap_dvi4_16000, rm), &sdp_rtpmap_dvi4_16000); TEST_1(rm = rm->rm_next); TEST_1(sdp_rtpmap_match(&sdp_rtpmap_lpc, rm)); TEST_P(sdp_rtpmap_find_matching(&sdp_rtpmap_lpc, rm), &sdp_rtpmap_lpc); TEST_1(rm = rm->rm_next); TEST_1(sdp_rtpmap_match(&sdp_rtpmap_pcma, rm)); TEST_P(sdp_rtpmap_find_matching(&sdp_rtpmap_pcma, rm), &sdp_rtpmap_pcma); TEST_1(rm = rm->rm_next); TEST_1(sdp_rtpmap_match(&sdp_rtpmap_g722, rm)); TEST_P(sdp_rtpmap_find_matching(&sdp_rtpmap_g722, rm), &sdp_rtpmap_g722); TEST_1(rm = rm->rm_next); TEST_1(sdp_rtpmap_match(&sdp_rtpmap_l16, rm)); TEST_P(sdp_rtpmap_find_matching(&sdp_rtpmap_l16, rm), &sdp_rtpmap_l16); TEST_1(rm = rm->rm_next); TEST_1(sdp_rtpmap_match(&sdp_rtpmap_l16_stereo, rm)); TEST_P(sdp_rtpmap_find_matching(&sdp_rtpmap_l16_stereo, rm), &sdp_rtpmap_l16_stereo); TEST_1(rm = rm->rm_next); TEST_1(sdp_rtpmap_match(&sdp_rtpmap_qcelp, rm)); TEST_P(sdp_rtpmap_find_matching(&sdp_rtpmap_qcelp, rm), &sdp_rtpmap_qcelp); TEST_1(rm = rm->rm_next); TEST_1(sdp_rtpmap_match(&sdp_rtpmap_cn, rm)); TEST_P(sdp_rtpmap_find_matching(&sdp_rtpmap_cn, rm), &sdp_rtpmap_cn); TEST_1(rm = rm->rm_next); TEST_1(sdp_rtpmap_match(&sdp_rtpmap_mpa, rm)); TEST_P(sdp_rtpmap_find_matching(&sdp_rtpmap_mpa, rm), &sdp_rtpmap_mpa); TEST_1(rm = rm->rm_next); TEST_1(sdp_rtpmap_match(&sdp_rtpmap_g728, rm)); TEST_P(sdp_rtpmap_find_matching(&sdp_rtpmap_g728, rm), &sdp_rtpmap_g728); TEST_1(rm = rm->rm_next); TEST_1(sdp_rtpmap_match(&sdp_rtpmap_dvi4_11025, rm)); TEST_P(sdp_rtpmap_find_matching(&sdp_rtpmap_dvi4_11025, rm), &sdp_rtpmap_dvi4_11025); TEST_1(rm = rm->rm_next); TEST_1(sdp_rtpmap_match(&sdp_rtpmap_dvi4_22050, rm)); TEST_P(sdp_rtpmap_find_matching(&sdp_rtpmap_dvi4_22050, rm), &sdp_rtpmap_dvi4_22050); TEST_1(rm = rm->rm_next); TEST_1(sdp_rtpmap_match(&sdp_rtpmap_g729, rm)); TEST_P(sdp_rtpmap_find_matching(&sdp_rtpmap_g729, rm), &sdp_rtpmap_g729); TEST_1(rm = rm->rm_next); TEST_1(sdp_rtpmap_match(&sdp_rtpmap_cn_reserved, rm)); TEST_P(sdp_rtpmap_find_matching(&sdp_rtpmap_cn_reserved, rm), &sdp_rtpmap_cn_reserved); TEST_1(!rm->rm_next); } TEST_1((parser = sdp_parse(home, s2_msg, sizeof (s2_msg), 0))); TEST_1((sdp = sdp_session(parser))); TEST_1(m = sdp->sdp_media); TEST(m->m_mode, sdp_recvonly); TEST_P(m->m_session, sdp); TEST_1(m->m_rtpmaps); TEST(m->m_rtpmaps->rm_pt, 96); TEST_S(m->m_rtpmaps->rm_encoding, "H263-1998"); TEST(m->m_rtpmaps->rm_rate, 90000); TEST_S(m->m_rtpmaps->rm_fmtp, "QCIF=4"); TEST_1(m = sdp->sdp_media->m_next); TEST(m->m_mode, sdp_recvonly); TEST_P(m->m_session, sdp); TEST_1(m->m_rtpmaps); TEST(m->m_rtpmaps->rm_pt, 97); TEST_S(m->m_rtpmaps->rm_encoding, "AMR"); TEST(m->m_rtpmaps->rm_rate, 8000); TEST_S(m->m_rtpmaps->rm_fmtp, "mode-set=\"0\""); su_home_unref(home); END(); } static char const s3_msg[] = "v=0\r\n" "o=- 2435697 2435697 IN IP4 172.21.137.44\r\n" "s=-\r\n" "t=0 0\r\n" "m=video 49154 RTP/AVP 34\r\n" "c=IN IP4 172.21.137.44\r\n" "m=audio 49152 RTP/AVP 8 0\r\n" "c=IN IP4 172.21.137.44\r\n" "m=message 0 MSRP/TCP *\r\n" ; static int test_sanity(void) { su_home_t *home = su_home_new(sizeof *home); sdp_parser_t *parser; BEGIN(); su_home_check(home); TEST_1(home); TEST_1((parser = sdp_parse(home, s3_msg, sizeof(s3_msg) - 1, 0))); TEST_1(sdp_sanity_check(parser) == 0); su_home_unref(home); END(); } static char const pint_msg[] = "v=0\r\n" "o=- 2353687640 2353687640 IN IP4 128.3.4.5\r\n" "s=marketing\r\n" "e=john.jones.3@chinet.net\r\n" "c=TN RFC2543 +1-201-406-4090\r\n" "t=2353687640 0\r\n" "m=audio 1 voice -\r\n" ; static char const pint_torture_msg[] = "v=0\r\n" "o=- 2353687640 2353687640 IN IP4 128.3.4.5\r\n" "s=marketing\r\n" "c= TN RFC2543 123\r\n" "a=phone-context:+97252\r\n" "t=2353687640 0\r\n" "m= text 1 fax plain\r\n" "a=fmtp:plain spr:fi6MeoclEjaF3EDfYHlkqx1zn8A1lMoiJFUHpQ5Xo\r\n" ; static int test_pint(void) { su_home_t *home = su_home_new(sizeof *home); sdp_parser_t *parser; sdp_session_t *sdp; sdp_printer_t *printer; char const *m; BEGIN(); su_home_check(home); TEST_1(home); TEST_1((parser = sdp_parse(home, pint_msg, sizeof(pint_msg) - 1, sdp_f_anynet))); TEST_1((sdp = sdp_session(parser))); TEST_1((printer = sdp_print(home, sdp, NULL, -1, 0))); TEST_1((m = sdp_message(printer))); TEST_S(m, pint_msg); TEST(sdp_message_size(printer), sizeof(pint_msg) - 1); TEST_1((parser = sdp_parse(home, pint_torture_msg, sizeof(pint_torture_msg) - 1, sdp_f_anynet))); TEST_1((sdp = sdp_session(parser))); su_home_check(home); su_home_unref(home); END(); } static sdp_list_t const l0[1] = {{ sizeof(l0), NULL, "foo" }}; static sdp_list_t const l1[1] = {{ sizeof(l1), (sdp_list_t *)l0, "bar" }}; /** Test list things */ int test_list(void) { su_home_t *home = su_home_new(sizeof *home); sdp_list_t *l; BEGIN(); su_home_check(home); TEST_1(home); TEST_1((l = sdp_list_dup(home, l0))); TEST_P(l->l_next, NULL); TEST_S(l->l_text, "foo"); TEST_1((l = sdp_list_dup(home, l1))); TEST_1(l->l_next != NULL); TEST_1(l->l_next->l_next == NULL); TEST_S(l->l_text, "bar"); TEST_S(l->l_next->l_text, "foo"); su_home_check(home); su_home_unref(home); END(); } static sdp_rtpmap_t const rm0[1] = {{ sizeof(rm0), NULL, "AMR", 8000, "1", "mode-set=4,5,6 interleaving crc use-redundancy=1", 0, 96, 0 }}; static sdp_rtpmap_t const rm1[1] = {{ sizeof(rm1), (sdp_rtpmap_t *)rm0, "PCMA", 8000, "1", NULL, 1, 8, 0, }}; /** Test rtpmap-related things */ int test_rtpmap(void) { su_home_t *home = su_home_new(sizeof *home); sdp_rtpmap_t *rm; BEGIN(); su_home_check(home); TEST_1(home); TEST_1((rm = sdp_rtpmap_dup(home, rm0))); TEST_P(rm->rm_next, NULL); TEST_S(rm->rm_encoding, "AMR"); TEST_S(rm->rm_params, "1"); TEST(rm->rm_pt, 96); TEST_S(rm->rm_fmtp, "mode-set=4,5,6 interleaving crc use-redundancy=1"); TEST_1((rm = sdp_rtpmap_dup(home, rm1))); TEST_1(rm->rm_next != NULL); TEST_1(rm->rm_next->rm_next == NULL); TEST_S(rm->rm_encoding, "PCMA"); TEST_S(rm->rm_params, "1"); TEST(rm->rm_pt, 8); su_home_check(home); su_home_unref(home); END(); } static sdp_attribute_t const a0[1] = {{ sizeof(a0), NULL, "foo", "2"}}; static sdp_attribute_t const a1[1] = {{ sizeof(a1), (sdp_attribute_t *)a0, "bar", "1" }}; static int test_attribute(void) { su_home_t *home = su_home_new(sizeof *home); sdp_attribute_t *a, *a_new, *list, *replaced; BEGIN(); su_home_check(home); TEST_1(home); TEST_1((a = sdp_attribute_dup(home, a0))); TEST_P(a->a_next, NULL); TEST_S(a->a_name, "foo"); TEST_S(a->a_value, "2"); strcpy((char *)a->a_name, "FOO"); TEST_S(a0->a_name, "foo"); strcpy((char *)a->a_value, "X"); TEST_S(a0->a_value, "2"); TEST_1((a = sdp_attribute_dup(home, a1))); TEST_1(a->a_next != NULL); TEST_1(a->a_next->a_next == NULL); TEST_S(a->a_name, "bar"); TEST_S(a->a_value, "1"); TEST_S(a->a_next->a_name, "foo"); TEST_S(a->a_next->a_value, "2"); list = a; TEST_P(sdp_attribute_remove(&list, NULL), NULL); TEST_P(sdp_attribute_remove(&list, "kuik"), NULL); TEST_P(sdp_attribute_remove(&list, "barf"), NULL); TEST_P(sdp_attribute_remove(&list, "bar"), a); TEST_1(a_new = sdp_attribute_dup(home, a)); replaced = (void *)-1; TEST(sdp_attribute_replace(&list, NULL, &replaced), -1); TEST_P(replaced, NULL); TEST(sdp_attribute_replace(&list, a, &replaced), 0); TEST_P(replaced, NULL); TEST(sdp_attribute_replace(&list, a_new, &replaced), 1); TEST_P(replaced, a); TEST_VOID(sdp_attribute_append(&list, a)); TEST_P(sdp_attribute_remove(&list, "bAr"), a_new); TEST_P(sdp_attribute_remove(&list, "BAR"), a); TEST_P(sdp_attribute_remove(&list, "bar"), NULL); su_home_check(home); su_home_unref(home); END(); } static int test_connection(void) { BEGIN(); END(); } static char const media_msg[] = "v=0\n" "s=/sdp_torture\n" "o=sdp_torture 0 0 IN IP4 1.2.3.4\n" "c=IN IP4 1.2.3.4\n" "m=audio 0 RTP/AVP 96 97 98 10 99 8 0\n" "a=rtpmap:96 X-AMR-WB/16000\n" "a=rtpmap:97 X-AMR/8000\n" "a=rtpmap:98 GSM-EFR/8000\n" "a=rtpmap:10 L16/16000\n" "a=rtpmap:99 G723/8000\n" "a=rtpmap:8 PCMA/8000\n" "a=rtpmap:0 PCMU/8000\n" "m=video 0 RTP/AVP 31\n" "c=IN IP4 2.3.4.5\n"; static sdp_media_t const m0[1] = {{ sizeof(m0), NULL, NULL, sdp_media_audio, NULL, 1234, 5, sdp_proto_udp, "udp", }}; static int test_media(void) { su_home_t *home = su_home_new(sizeof *home); sdp_media_t *media; sdp_session_t *sdp; sdp_parser_t *parser; BEGIN(); su_home_check(home); TEST_1(home); TEST_1((parser = sdp_parse(home, media_msg, sizeof(media_msg), 0))); TEST_1((sdp = sdp_session(parser))); TEST_1((media = sdp_media_dup(home, m0, sdp))); /* Check comparing */ TEST(sdp_media_cmp(media, m0), 0); TEST(media->m_type, sdp_media_audio); TEST(media->m_port, 1234); TEST(media->m_number_of_ports, 5); TEST_P(media->m_session, sdp); /* FIXME: add more tests */ media->m_next = (sdp_media_t *)m0; TEST_1((media = sdp_media_dup_all(home, media, sdp))); TEST_P(media->m_connections, NULL); TEST_1(media->m_next); TEST_P(media->m_next->m_connections, NULL); TEST_P(sdp_media_connections(media), sdp->sdp_connection); TEST_P(sdp_media_connections(media->m_next), sdp->sdp_connection); sdp_parser_free(parser); su_home_check(home); su_home_unref(home); END(); } static int test_origin(void) { BEGIN(); END(); } static int test_bandwidth(void) { BEGIN(); END(); } static char const t_msg[] = "v=0\n" "s=/sdp_torture\n" "o=sdp_torture 1 1 IN IP4 1.2.3.4\n" "c=IN IP4 1.2.3.4\n" "t=3309789956 3309793556\n" "t=3309789956 3309793557\n" "t=3309789955 3309793557\n" "r=604800 3600 0 90000\n" "z=2882844526 -1h 2898848070 0\n" "t=3309789955 3309793557\n" "r=604800 3600 0 90000\n" "z=2882844526 -1h 2898848070 0\n" ; static int test_time(void) { sdp_parser_t *parser; sdp_session_t *sdp; sdp_time_t *t, t1[1], t2[1]; BEGIN(); TEST_1((parser = sdp_parse(NULL, t_msg, sizeof(t_msg), 0))); TEST_1((sdp = sdp_session(parser))); TEST_1((t = sdp->sdp_time)); *t1 = *t; t1->t_next = NULL; *t2 = *t1; TEST_1(sdp_time_cmp(t1, t1) == 0); TEST_1(sdp_time_cmp(t1, t2) == 0); TEST_1(sdp_time_cmp(t2, t1) == 0); TEST_1((t = t->t_next)); *t1 = *t; t1->t_next = NULL; TEST_1(sdp_time_cmp(t1, t2) > 0); TEST_1(sdp_time_cmp(t2, t1) < 0); TEST_1((t = t->t_next)); *t2 = *t; t2->t_next = NULL; TEST_1(t2->t_zone); TEST_1(t2->t_repeat); TEST_1(sdp_time_cmp(t2, t2) == 0); TEST_1(sdp_time_cmp(t1, t2) > 0); TEST_1(sdp_time_cmp(t2, t1) < 0); TEST_1((t = t->t_next)); *t1 = *t; t1->t_next = NULL; TEST_1(t1->t_zone); TEST_1(t1->t_repeat); TEST_1(sdp_time_cmp(t1, t1) == 0); TEST_1(sdp_time_cmp(t2, t2) == 0); TEST_1(sdp_time_cmp(t1, t2) == 0); sdp_parser_free(parser); END(); } static int test_key(void) { BEGIN(); END(); } #include #include static int test_build(void) { sdp_session_t *sdp, *dup; sdp_origin_t *o; sdp_time_t *t; sdp_connection_t *c; sdp_media_t *m, *m1; sdp_rtpmap_t *rm; sdp_list_t *l, *l1; sdp_attribute_t *a; su_home_t *home; sdp_printer_t *printer; char const *data; BEGIN(); srand(time(NULL)); TEST_1(home = su_home_new(sizeof *home)); /* * Allocate an SDP structure using su_salloc(). * su_salloc() puts memory area size to the beginning of structure * and zeroes rest of the structure. */ TEST_1(sdp = su_salloc(home, sizeof(*sdp))); TEST_1(o = su_salloc(home, sizeof(*o))); TEST_1(t = su_salloc(home, sizeof(*t))); TEST_1(c = su_salloc(home, sizeof(*c))); TEST_1(m = su_salloc(home, sizeof(*m))); TEST_1(rm = su_salloc(home, sizeof(*rm))); sdp->sdp_origin = o; sdp->sdp_time = t; /* zero time is fine for SIP */ sdp->sdp_connection = c; sdp->sdp_media = m; o->o_username = "test"; o->o_id = rand(); o->o_version = 1; o->o_address = c; c->c_nettype = sdp_net_in; c->c_addrtype = sdp_addr_ip4; c->c_address = "172.21.40.40"; m->m_session = sdp; m->m_type = sdp_media_audio; m->m_type_name = "audio"; m->m_port = 5004; m->m_proto = sdp_proto_rtp; m->m_proto_name = "RTP/AVP"; m->m_rtpmaps = rm; rm->rm_predef = 1; rm->rm_pt = 8; rm->rm_encoding = "PCMA"; rm->rm_rate = 8000; TEST_1(m1 = su_salloc(home, sizeof(*m1))); TEST_1(l = su_salloc(home, sizeof(*l))); TEST_1(l1 = su_salloc(home, sizeof(*l1))); TEST_1(a = su_salloc(home, sizeof(*a))); m->m_next = m1; m1->m_session = sdp; m1->m_type = sdp_media_message; m->m_type_name = "message"; m1->m_port = 5060; m1->m_proto = sdp_proto_tcp; m->m_proto_name = "TCP"; m1->m_format = l; m1->m_attributes = a; l->l_text = "sip"; l->l_next = l1; l1->l_text = "cpim"; a->a_name = "user"; a->a_value = "chat-81273845"; TEST_1(dup = sdp_session_dup(home, sdp)); TEST_1(printer = sdp_print(home, dup, NULL, 0, 0)); TEST_1(data = sdp_message(printer)); if (tstflags & tst_verbatim) printf("sdp_torture.c: built SDP message:\"%s\".\n", data); sdp_printer_free(printer); END(); } void usage(int exitcode) { fprintf(stderr, "usage: %s [-v] [-a]\n", name); exit(exitcode); } int main(int argc, char *argv[]) { int retval = 0; int i; for (i = 1; argv[i]; i++) { if (su_strmatch(argv[i], "-v")) tstflags |= tst_verbatim; else if (su_strmatch(argv[i], "-a")) tstflags |= tst_abort; else usage(1); } null = fopen("/dev/null", "ab"); retval |= test_error(); fflush(stdout); retval |= test_session(); fflush(stdout); retval |= test_session2(); fflush(stdout); retval |= test_pint(); fflush(stdout); retval |= test_sanity(); fflush(stdout); retval |= test_list(); fflush(stdout); retval |= test_rtpmap(); fflush(stdout); retval |= test_origin(); fflush(stdout); retval |= test_connection(); fflush(stdout); retval |= test_bandwidth(); fflush(stdout); retval |= test_time(); fflush(stdout); retval |= test_key(); fflush(stdout); retval |= test_attribute(); fflush(stdout); retval |= test_media(); fflush(stdout); retval |= test_build(); fflush(stdout); return retval; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/000077500000000000000000000000001223300710500203455ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/ADD-A-HEADER000066400000000000000000000112411223300710500217630ustar00rootroot00000000000000Adding a SIP Header to Sofia SIP ================================ by Pekka Pessi (2002-08-16, last updated 2007-09-19) There are two recommended ways to extend the Sofia SIP parser, including a standard header in extra headers or putting the extension headers into a separate library. In the text below, we use "Example" header as our example with following ABNF: sip-example = "Example" COLON 1*DIGIT IF YOUR HEADER IS A STANDARD ONE -------------------------------- * In , add: - Add typedef to the header structure. You should add a typedef line like this: typedef struct sip_example_s sip_example_t; Note that the typedefs are documented together with the implementation in the .c file. - Add the actual header structure: The header structure would look like below. The first field MUST be a sip_common_t structure, second field MUST be a pointer to next header with same name. As a convention, if there can be only one header field of this kind, the type of the "next" pointer is sip_error_t. The fields representing the header value are located after the mandatory fields, usually in the order they are present in the header contents. In this case, the Example header consist of a 32-bit integer: /**@ingroup sip_example * @brief Structure for Example header. */ struct sip_example_s { sip_common_t ex_common[1]; /**< Common fragment info. */ sip_error_t *ex_next; /**< Link to next (dummy). */ unsigned long ex_value; /**< Value of example. */ }; * Add entry to sip_extra_headers.txt: - In this case: example @NEW_2_0 /* Example header */ - The first is the base C name used for functions and types related to the type. The AWK script msg_parser.awk automatically creates the default prototypes and tags for the newly created header. It will complain about mismatches between header name and the base name. - If the entry is before #### DEFAULT HEADER LIST ENDS HERE #### the new header is added to the default parser - If after, the new header is added only to the extended parser. - The extended parser will be used after call to sip_update_default_mclass(NULL) * Write parsing tests for your new headers in torture_sip.c: Add all relevant parsing/processing cases you can think of at the end of function sip_header_test() or add a testing function of your own. * Add implementation in a suitable ".c" file - For an simple example, see implementation of Date header in sip_basic.c - Add a documentation group with @defgroup - Document the typedef - Add header class structure - Add parsing and printing functions: + sip_example_d(), sip_example_e() - Add functions used when copying the header structure: + sip_example_dup_xtra(), sip_example_dup_one() * If you added a .c file, add to the Makefile.am - remember to run autogen.sh unless you have given --enable-maintainer-mode to configure script * Run "make check" after you are ready * Run "make check" after you are ready. Really. IF YOUR HEADERS ARE COMPLETELY NON-STANDARD ------------------------------------------- * Add a separate library package for them - There is an example package sofia-sip-2543.tar.gz, available from sofia-sip.sourceforge.net See the extension package for 1) - Create a header template for your header just like sofia-sip/rfc2543.h.in (found in package), e.g, sip_example.h.in: ---8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<--- /**@file sip_example.h.in * * Template for . */ #ifndef SIP_EXAMPLE_H /** Defined when has been included. */ #define SIP_EXAMPLE_H /**@file sip_example.h * * @brief Example header. * * #AUTO# * * @author Pekka Pessi . * * @date Created: Fri May 27 18:40:38 EEST 2005 ppessi */ #ifndef SIP_H #include #endif #ifndef SIP_HEADER_H #include #endif /**@ingroup sip_example * @brief Structure for @b Example header. */ struct sip_example_s { sip_common_t ex_common[1]; /**< Common fragment info */ sip_error_t *ex_next; /**< Link to next (dummy). */ uint32_t ex_value; /**< Value of Example */ }; typedef struct sip_example_s sip_example_t; struct sip_example_dummy_structure { /* === Headers start here */ sip_example_t *sip_example; /**< Example */ /* === Headers end here */ }; #endif /** !defined(SIP_EXAMPLE_H) */ --->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8--- sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/ChangeLog000066400000000000000000000034731223300710500221260ustar00rootroot000000000000002006-01-25 Kai Vehmanen * Doxyfile (INPUT): Missing sip_dll.c broke refdoc build. Now changed so that individual are not listed anymore in INPUT. 2006-01-10 Kai Vehmanen * Doxyfile: References to removed files sip_internal.h and sip_extensions.h caused fatal doxygen error. 2005-10-21 Pekka Pessi * sip_contact_create_from_via_with_transport() now converts tport name to lcase. M ./libsofia-sip-ua/sip/sip_util.c -10 +25 2005-10-12 Pekka Pessi * Contact generated by nta now contains URL transport parameter. The transport=UDP was left out from contact URL always. Now it is left out only if both UDP and TCP are supported. Added utility function sip_contact_create_from_via_with_transport(). M ./libsofia-sip-ua/nta/nta.c -2 +14 M ./libsofia-sip-ua/sip/sip_util.c -10 +28 M ./libsofia-sip-ua/sip/sip_util.h +6 2005-08-01 Pekka Pessi * Makefile.am: Added sip_bad_mask. * sip_mime.c: Fixed sip_accept_encoding_d() and sip_accept_language_d() to accept empty list. * sip_util.c: sip_header_as_string() can now return an empty string, too. * sip.h: Putting Proxy-Require in the beginning of hte message. * torture_sip.c: Added tests for privacy. * sip_security.c: Added error checking in Privacy: accept commas-separated list, too. * sip_parser.h: Added header classification masks. * sip_mime.c: Using apndlist format for various Accept headers. * sip_feature.c: Using msg_commalist_d() to decode Allow, Require, Proxy-Require, Supported, and Unsupported. * sip_basic.c: Not encoding comment in Contact. Always using name-addr form for Route headers. 2005-07-18 Kai Vehmanen * Initial import of the module to Sofia-SIP tree. sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/Doxyfile.in000066400000000000000000000014451223300710500224640ustar00rootroot00000000000000PROJECT_NAME = "sip" OUTPUT_DIRECTORY = ../docs/html/sip INPUT = @srcdir@/sofia-sip sofia-sip @srcdir@/sip.docs @srcdir@/sip_parser.docs @srcdir@ . @INCLUDE_PATH = . @srcdir@ @INCLUDE = ../docs/Doxyfile.conf TAGFILES += \ ../docs/su.doxytags=../su \ ../docs/ipt.doxytags=../ipt \ ../docs/bnf.doxytags=../bnf \ ../docs/url.doxytags=../url \ ../docs/msg.doxytags=../msg \ ../docs/sdp.doxytags=../sdp \ ../docs/iptsec.doxytags=../iptsec \ ../docs/nta.doxytags=../nta \ ../docs/nua.doxytags=../nua GENERATE_TAGFILE = ../docs/sip.doxytags ALIASES += \ "SIP_TAG=@ingroup sip_tag\n" \ "SIP_HEADER=@ingroup sip_headers\n@defgroup" \ "SIP_PARSER=\n" @INCLUDE = sip.doxyaliases PREDEFINED += SU_HAVE_EXPERIMENTAL=1 IMAGE_PATH += @srcdir@/images sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/GRAMMAR000066400000000000000000000561321223300710500213650ustar00rootroot00000000000000/* SIP grammar from RFC3261 * * alphanum = ALPHA / DIGIT * * reserved = ";" / "/" / "?" / ":" / "@" / "&" / "=" / "+" * / "$" / "," * unreserved = alphanum / mark * mark = "-" / "_" / "." / "!" / "~" / "*" / "'" * / "(" / ")" * escaped = "%" HEXDIG HEXDIG * * LWS = [*WSP CRLF] 1*WSP ; linear whitespace * SWS = [LWS] ; sep whitespace * * HCOLON = *( SP / HTAB ) ":" SWS * * TEXT-UTF8-TRIM = 1*TEXT-UTF8char *(*LWS TEXT-UTF8char) * TEXT-UTF8char = %x21-7E / UTF8-NONASCII * UTF8-NONASCII = %xC0-DF 1UTF8-CONT * / %xE0-EF 2UTF8-CONT * / %xF0-F7 3UTF8-CONT * / %xF8-Fb 4UTF8-CONT * / %xFC-FD 5UTF8-CONT * UTF8-CONT = %x80-BF * * LHEX = DIGIT / %x61-66 ;lowercase a-f * * token = 1*(alphanum / "-" / "." / "!" / "%" / "*" * / "_" / "+" / "`" / "'" / "~" ) * separators = "(" / ")" / "<" / ">" / "@" / * "," / ";" / ":" / "\" / DQUOTE / * "/" / "[" / "]" / "?" / "=" / * "{" / "}" / SP / HTAB * word = 1*(alphanum / "-" / "." / "!" / "%" / "*" / * "_" / "+" / "`" / "'" / "~" / * "(" / ")" / "<" / ">" / * ":" / "\" / DQUOTE / * "/" / "[" / "]" / "?" / * "{" / "}" ) * * STAR = SWS "*" SWS ; asterisk * SLASH = SWS "/" SWS ; slash * EQUAL = SWS "=" SWS ; equal * LPAREN = SWS "(" SWS ; left parenthesis * RPAREN = SWS ")" SWS ; right parenthesis * RAQUOT = ">" SWS ; right angle quote * LAQUOT = SWS "<"; left angle quote * COMMA = SWS "," SWS ; comma * SEMI = SWS ";" SWS ; semicolon * COLON = SWS ":" SWS ; colon * LDQUOT = SWS DQUOTE; open double quotation mark * RDQUOT = DQUOTE SWS ; close double quotation mark * * comment = LPAREN *(ctext / quoted-pair / comment) RPAREN * ctext = %x21-27 / %x2A-5B / %x5D-7E / UTF8-NONASCII * / LWS * * quoted-string = SWS DQUOTE *(qdtext / quoted-pair ) DQUOTE * qdtext = LWS / %x21 / %x23-5B / %x5D-7E * / UTF8-NONASCII * * quoted-pair = "\" (%x00-09 / %x0B-0C * / %x0E-7F) * * SIP-URI = "sip:" [ userinfo ] hostport * uri-parameters [ headers ] * SIPS-URI = "sips:" [ userinfo ] hostport * uri-parameters [ headers ] * userinfo = ( user / telephone-subscriber ) [ ":" password ] "@" * user = 1*( unreserved / escaped / user-unreserved ) * user-unreserved = "&" / "=" / "+" / "$" / "," / ";" / "?" / "/" * password = *( unreserved / escaped / * "&" / "=" / "+" / "$" / "," ) * hostport = host [ ":" port ] * host = hostname / IPv4address / IPv6reference * hostname = *( domainlabel "." ) toplabel [ "." ] * domainlabel = alphanum * / alphanum *( alphanum / "-" ) alphanum * toplabel = ALPHA / ALPHA *( alphanum / "-" ) alphanum * IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT * IPv6reference = "[" IPv6address "]" * IPv6address = hexpart [ ":" IPv4address ] * hexpart = hexseq / hexseq "::" [ hexseq ] / "::" [ hexseq ] * hexseq = hex4 *( ":" hex4) * hex4 = 1*4HEXDIG * port = 1*DIGIT * * uri-parameters = *( ";" uri-parameter) * uri-parameter = transport-param / user-param / method-param * / ttl-param / maddr-param / lr-param / other-param * transport-param = "transport=" * ( "udp" / "tcp" / "sctp" / "tls" * / other-transport) * other-transport = token * user-param = "user=" ( "phone" / "ip" / other-user) * other-user = token * method-param = "method=" Method * ttl-param = "ttl=" ttl * maddr-param = "maddr=" host * lr-param = "lr" * other-param = pname [ "=" pvalue ] * pname = 1*paramchar * pvalue = 1*paramchar * paramchar = param-unreserved / unreserved / escaped * param-unreserved = "[" / "]" / "/" / ":" / "&" / "+" / "$" * * headers = "?" header *( "&" header ) * header = hname "=" hvalue * hname = 1*( hnv-unreserved / unreserved / escaped ) * hvalue = *( hnv-unreserved / unreserved / escaped ) * hnv-unreserved = "[" / "]" / "/" / "?" / ":" / "+" / "$" * * SIP-message = Request / Response * Request = Request-Line * *( message-header ) * CRLF * [ message-body ] * Request-Line = Method SP Request-URI SP SIP-Version CRLF * Request-URI = SIP-URI / SIPS-URI / absoluteURI * absoluteURI = scheme ":" ( hier-part / opaque-part ) * hier-part = ( net-path / abs-path ) [ "?" query ] * net-path = "//" authority [ abs-path ] * abs-path = "/" path-segments * opaque-part = uric-no-slash *uric * uric = reserved / unreserved / escaped * uric-no-slash = unreserved / escaped / ";" / "?" / ":" / "@" * / "&" / "=" / "+" / "$" / "," * path-segments = segment *( "/" segment ) * segment = *pchar *( ";" param ) * param = *pchar * pchar = unreserved / escaped / * ":" / "@" / "&" / "=" / "+" / "$" / "," * scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) * authority = srvr / reg-name * srvr = [ [ userinfo "@" ] hostport ] * reg-name = 1*( unreserved / escaped / "$" / "," * / ";" / ":" / "@" / "&" / "=" / "+" ) * query = *uric * SIP-Version = "SIP" "/" 1*DIGIT "." 1*DIGIT * * message-header = (Accept * / Accept-Encoding * / Accept-Language * / Alert-Info * / Allow * / Authentication-Info * / Authorization * / Call-ID * / Call-Info * / Contact * / Content-Disposition * / Content-Encoding * / Content-Language * / Content-Length * / Content-Type * / CSeq * / Date * / Error-Info * / Expires * / From * / In-Reply-To * / Max-Forwards * / MIME-Version * / Min-Expires * / Organization * / Priority * / Proxy-Authenticate * / Proxy-Authorization * / Proxy-Require * / Record-Route * / Reply-To * / Require * / Retry-After * / Route * / Server * / Subject * / Supported * / Timestamp * / To * / Unsupported * / User-Agent * / Via * / Warning * / WWW-Authenticate * / extension-header) CRLF * * INVITEm = %x49.4E.56.49.54.45 ; INVITE in caps * ACKm = %x41.43.4B ; ACK in caps * OPTIONSm = %x4F.50.54.49.4F.4E.53 ; OPTIONS in caps * BYEm = %x42.59.45 ; BYE in caps * CANCELm = %x43.41.4E.43.45.4C ; CANCEL in caps * REGISTERm = %x52.45.47.49.53.54.45.52 ; REGISTER in caps * Method = INVITEm / ACKm / OPTIONSm / BYEm * / CANCELm / REGISTERm * / extension-method * extension-method = token * Response = Status-Line * *( message-header ) * CRLF * [ message-body ] * * Status-Line = SIP-Version SP Status-Code SP Reason-Phrase CRLF * Status-Code = Informational * / Redirection * / Success * / Client-Error * / Server-Error * / Global-Failure * / extension-code * extension-code = 3DIGIT * Reason-Phrase = *(reserved / unreserved / escaped * / UTF8-NONASCII / UTF8-CONT / SP / HTAB) * * Informational = "100" ; Trying * / "180" ; Ringing * / "181" ; Call Is Being Forwarded * / "182" ; Queued * / "183" ; Session Progress * * Success = "200" ; OK * * Redirection = "300" ; Multiple Choices * / "301" ; Moved Permanently * / "302" ; Moved Temporarily * / "305" ; Use Proxy * / "380" ; Alternative Service * * Client-Error = "400" ; Bad Request * / "401" ; Unauthorized * / "402" ; Payment Required * / "403" ; Forbidden * / "404" ; Not Found * / "405" ; Method Not Allowed * / "406" ; Not Acceptable * / "407" ; Proxy Authentication Required * / "408" ; Request Timeout * / "410" ; Gone * / "413" ; Request Entity Too Large * / "414" ; Request-URI Too Large * / "415" ; Unsupported Media Type * / "416" ; Unsupported URI Scheme * / "420" ; Bad Extension * / "421" ; Extension Required * / "423" ; Interval Too Brief * / "480" ; Temporarily not available * / "481" ; Call Leg/Transaction Does Not Exist * / "482" ; Loop Detected * / "483" ; Too Many Hops * / "484" ; Address Incomplete * / "485" ; Ambiguous * / "486" ; Busy Here * / "487" ; Request Terminated * / "488" ; Not Acceptable Here * / "491" ; Request Pending * / "493" ; Undecipherable * * Server-Error = "500" ; Internal Server Error * / "501" ; Not Implemented * / "502" ; Bad Gateway * / "503" ; Service Unavailable * / "504" ; Server Time-out * / "505" ; SIP Version not supported * / "513" ; Message Too Large * * Global-Failure = "600" ; Busy Everywhere * / "603" ; Decline * / "604" ; Does not exist anywhere * / "606" ; Not Acceptable * * Accept = "Accept" HCOLON * [ accept-range *(COMMA accept-range) ] * accept-range = media-range *(SEMI accept-param) * ; Why not SLASH ? //PPe * media-range = ( "*" "/" "*" * / ( m-type SLASH "*" ) * / ( m-type SLASH m-subtype ) * ) *( SEMI m-parameter ) * accept-param = ("q" EQUAL qvalue) / generic-param * qvalue = ( "0" [ "." 0*3DIGIT ] ) * / ( "1" [ "." 0*3("0") ] ) * generic-param = token [ EQUAL gen-value ] * gen-value = token / host / quoted-string * * Accept-Encoding = "Accept-Encoding" HCOLON * [ encoding *(COMMA encoding) ] * encoding = codings *(SEMI accept-param) * codings = content-coding / "*" * content-coding = token * * Accept-Language = "Accept-Language" HCOLON * [ language *(COMMA language) ] * language = language-range *(SEMI accept-param) * language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) / "*" ) * * Alert-Info = "Alert-Info" HCOLON alert-param *(COMMA alert-param) * alert-param = LAQUOT absoluteURI RAQUOT *( SEMI generic-param ) * * Allow = "Allow" HCOLON [Method *(COMMA Method)] * * Authorization = "Authorization" HCOLON credentials * credentials = ("Digest" LWS digest-response) * / other-response * digest-response = dig-resp *(COMMA dig-resp) * dig-resp = username / realm / nonce / digest-uri * / dresponse / algorithm / cnonce * / opaque / message-qop * / nonce-count / auth-param * username = "username" EQUAL username-value * username-value = quoted-string * digest-uri = "uri" EQUAL LDQUOT digest-uri-value RDQUOT * digest-uri-value = rquest-uri ; Equal to request-uri as specified * by HTTP/1.1 * message-qop = "qop" EQUAL qop-value * cnonce = "cnonce" EQUAL cnonce-value * cnonce-value = nonce-value * nonce-count = "nc" EQUAL nc-value * nc-value = 8LHEX * dresponse = "response" EQUAL request-digest * request-digest = LDQUOT 32LHEX RDQUOT * auth-param = auth-param-name EQUAL * ( token / quoted-string ) * auth-param-name = token * other-response = auth-scheme LWS auth-param * *(COMMA auth-param) * auth-scheme = token * * Authentication-Info = "Authentication-Info" HCOLON ainfo * *(COMMA ainfo) * ainfo = nextnonce / message-qop * / response-auth / cnonce * / nonce-count * nextnonce = "nextnonce" EQUAL nonce-value * response-auth = "rspauth" EQUAL response-digest * response-digest = LDQUOT *LHEX RDQUOT * * Call-ID = ( "Call-ID" / "i" ) HCOLON callid * callid = word [ "@" word ] * * Call-Info = "Call-Info" HCOLON info *(COMMA info) * info = LAQUOT absoluteURI RAQUOT *( SEMI info-param) * info-param = ( "purpose" EQUAL ( "icon" / "info" * / "card" / token ) ) / generic-param * * Contact = ("Contact" / "m" ) HCOLON * ( STAR / (contact-param *(COMMA contact-param))) * contact-param = (name-addr / addr-spec) *(SEMI contact-params) * name-addr = [ display-name ] LAQUOT addr-spec RAQUOT * addr-spec = SIP-URI / SIPS-URI / absoluteURI * display-name = *(token LWS)/ quoted-string * * contact-params = c-p-q / c-p-expires * / contact-extension * c-p-q = "q" EQUAL qvalue * c-p-expires = "expires" EQUAL delta-seconds * contact-extension = generic-param * delta-seconds = 1*DIGIT * * Content-Disposition = "Content-Disposition" HCOLON * disp-type *( SEMI disp-param ) * disp-type = "render" / "session" / "icon" / "alert" * / disp-extension-token * disp-param = handling-param / generic-param * handling-param = "handling" EQUAL * ( "optional" / "required" * / other-handling ) * other-handling = token * disp-extension-token = token * * Content-Encoding = ( "Content-Encoding" / "e" ) HCOLON * content-coding *(COMMA content-coding) * * Content-Language = "Content-Language" HCOLON * language-tag *(COMMA language-tag) * language-tag = primary-tag *( "-" subtag ) * primary-tag = 1*8ALPHA * subtag = 1*8ALPHA * * Content-Length = ( "Content-Length" / "l" ) HCOLON 1*DIGIT * Content-Type = ( "Content-Type" / "c" ) HCOLON media-type * media-type = m-type SLASH m-subtype *(SEMI m-parameter) * m-type = discrete-type / composite-type * discrete-type = "text" / "image" / "audio" / "video" * / "application" / extension-token * composite-type = "message" / "multipart" / extension-token * extension-token = ietf-token / x-token * ietf-token = token * x-token = "x-" token * m-subtype = extension-token / iana-token * iana-token = token * m-parameter = m-attribute EQUAL m-value * m-attribute = token * m-value = token / quoted-string * * CSeq = "CSeq" HCOLON 1*DIGIT LWS Method * * Date = "Date" HCOLON SIP-date * SIP-date = rfc1123-date * rfc1123-date = wkday "," SP date1 SP time SP "GMT" * date1 = 2DIGIT SP month SP 4DIGIT * ; day month year (e.g., 02 Jun 1982) * time = 2DIGIT ":" 2DIGIT ":" 2DIGIT * ; 00:00:00 - 23:59:59 * wkday = "Mon" / "Tue" / "Wed" * / "Thu" / "Fri" / "Sat" / "Sun" * month = "Jan" / "Feb" / "Mar" / "Apr" * / "May" / "Jun" / "Jul" / "Aug" * / "Sep" / "Oct" / "Nov" / "Dec" * * Error-Info = "Error-Info" HCOLON error-uri *(COMMA error-uri) * error-uri = LAQUOT absoluteURI RAQUOT *( SEMI generic-param ) * * Expires = "Expires" HCOLON delta-seconds * From = ( "From" / "f" ) HCOLON from-spec * from-spec = ( name-addr / addr-spec ) * *( SEMI from-param ) * from-param = tag-param / generic-param * tag-param = "tag" EQUAL token * * In-Reply-To = "In-Reply-To" HCOLON callid *(COMMA callid) * * Max-Forwards = "Max-Forwards" HCOLON 1*DIGIT * * MIME-Version = "MIME-Version" HCOLON 1*DIGIT "." 1*DIGIT * * Min-Expires = "Min-Expires" HCOLON delta-seconds * * Organization = "Organization" HCOLON [TEXT-UTF8-TRIM] * * Priority = "Priority" HCOLON priority-value * priority-value = "emergency" / "urgent" / "normal" * / "non-urgent" / other-priority * other-priority = token * * Proxy-Authenticate = "Proxy-Authenticate" HCOLON challenge * challenge = ("Digest" LWS digest-cln *(COMMA digest-cln)) * / other-challenge * other-challenge = auth-scheme LWS auth-param * *(COMMA auth-param) * digest-cln = realm / domain / nonce * / opaque / stale / algorithm * / qop-options / auth-param * realm = "realm" EQUAL realm-value * realm-value = quoted-string * domain = "domain" EQUAL LDQUOT URI * *( 1*SP URI ) RDQUOT * URI = absoluteURI / abs-path * nonce = "nonce" EQUAL nonce-value * nonce-value = quoted-string * opaque = "opaque" EQUAL quoted-string * stale = "stale" EQUAL ( "true" / "false" ) * algorithm = "algorithm" EQUAL ( "MD5" / "MD5-sess" * / token ) * qop-options = "qop" EQUAL LDQUOT qop-value * *("," qop-value) RDQUOT * qop-value = "auth" / "auth-int" / token * * Proxy-Authorization = "Proxy-Authorization" HCOLON credentials * * Proxy-Require = "Proxy-Require" HCOLON option-tag * *(COMMA option-tag) * option-tag = token * * Record-Route = "Record-Route" HCOLON rec-route *(COMMA rec-route) * rec-route = name-addr *( SEMI rr-param ) * rr-param = generic-param * * Reply-To = "Reply-To" HCOLON rplyto-spec * rplyto-spec = ( name-addr / addr-spec ) * *( SEMI rplyto-param ) * rplyto-param = generic-param * Require = "Require" HCOLON option-tag *(COMMA option-tag) * * Retry-After = "Retry-After" HCOLON delta-seconds * [ comment ] *( SEMI retry-param ) * * retry-param = ("duration" EQUAL delta-seconds) * / generic-param * * Route = "Route" HCOLON route-param *(COMMA route-param) * route-param = name-addr *( SEMI rr-param ) * * Server = "Server" HCOLON server-val *(LWS server-val) * server-val = product / comment * product = token [SLASH product-version] * product-version = token * * Subject = ( "Subject" / "s" ) HCOLON [TEXT-UTF8-TRIM] * * Supported = ( "Supported" / "k" ) HCOLON * [option-tag *(COMMA option-tag)] * * Timestamp = "Timestamp" HCOLON 1*(DIGIT) * [ "." *(DIGIT) ] [ LWS delay ] * delay = *(DIGIT) [ "." *(DIGIT) ] * * To = ( "To" / "t" ) HCOLON ( name-addr * / addr-spec ) *( SEMI to-param ) * to-param = tag-param / generic-param * * Unsupported = "Unsupported" HCOLON option-tag *(COMMA option-tag) * User-Agent = "User-Agent" HCOLON server-val *(LWS server-val) * * Via = ( "Via" / "v" ) HCOLON via-parm *(COMMA via-parm) * via-parm = sent-protocol LWS sent-by *( SEMI via-params ) * via-params = via-ttl / via-maddr * / via-received / via-branch * / via-extension * via-ttl = "ttl" EQUAL ttl * via-maddr = "maddr" EQUAL host * via-received = "received" EQUAL (IPv4address / IPv6address) * via-branch = "branch" EQUAL token * via-extension = generic-param * sent-protocol = protocol-name SLASH protocol-version * SLASH transport * protocol-name = "SIP" / token * protocol-version = token * transport = "UDP" / "TCP" / "TLS" / "SCTP" * / other-transport * sent-by = host [ COLON port ] * ttl = 1*3DIGIT ; 0 to 255 * * Warning = "Warning" HCOLON warning-value *(COMMA warning-value) * warning-value = warn-code SP warn-agent SP warn-text * warn-code = 3DIGIT * warn-agent = hostport / pseudonym * ; the name or pseudonym of the server adding * ; the Warning header, for use in debugging * warn-text = quoted-string * pseudonym = token * * WWW-Authenticate = "WWW-Authenticate" HCOLON challenge * * extension-header = header-name HCOLON header-value * header-name = token * header-value = *(TEXT-UTF8char / UTF8-CONT / LWS) * message-body = *OCTET */sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/Makefile.am000066400000000000000000000122721223300710500224050ustar00rootroot00000000000000# # Makefile.am for sip module # # ---------------------------------------------------------------------- # Header paths INCLUDES = -I$(srcdir)/../bnf -I../bnf \ -I$(srcdir)/../ipt -I../ipt \ -I$(srcdir)/../msg -I../msg \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su # ---------------------------------------------------------------------- # Build targets noinst_LTLIBRARIES = libsip.la check_PROGRAMS = torture_sip \ test_sip_msg validator test_date # ---------------------------------------------------------------------- # Rules for building the targets GENERATED_H = sofia-sip/sip_hclasses.h \ sofia-sip/sip_protos.h sofia-sip/sip_tag.h \ sofia-sip/sip_extra.h H_IN = sofia-sip/sip_hclasses.h.in \ sofia-sip/sip_protos.h.in sofia-sip/sip_tag.h.in \ sofia-sip/sip_extra.h.in PUBLIC_H = sofia-sip/sip.h sofia-sip/sip_util.h \ sofia-sip/sip_header.h sofia-sip/sip_parser.h \ sofia-sip/sip_tag_class.h sofia-sip/sip_status.h GENERATED_C = sip_tag.c sip_parser_table.c BUILT_SOURCES = $(GENERATED_H) $(GENERATED_C) sip_tag_ref.c nobase_include_sofia_HEADERS = $(GENERATED_H) $(PUBLIC_H) $(H_IN) libsip_la_SOURCES = $(INTERNAL_H) \ sip_parser.c sip_header.c sip_util.c sip_pref_util.c \ sip_basic.c sip_extra.c sip_feature.c sip_mime.c \ sip_security.c sip_event.c sip_prack.c \ sip_refer.c sip_session.c \ sip_caller_prefs.c sip_reason.c \ sip_status.c sip_time.c \ sip_tag_class.c sip_inlined.c \ $(BUILT_SOURCES) COVERAGE_INPUT = $(libsip_la_SOURCES) $(include_sofia_HEADERS) LDADD = libsip.la \ ../msg/libmsg.la \ ../bnf/libbnf.la \ ../url/liburl.la \ ../ipt/libipt.la \ ../su/libsu.la torture_sip_LDFLAGS = -static test_sip_msg_LDFLAGS = -static test_date_LDFLAGS = -static # ---------------------------------------------------------------------- # Install and distribution rules # note: srcdir needs to be specified, otherwise # breaks make distcheck target EXTRA_DIST = sip.docs sip_parser.docs sip.doxyaliases \ ADD-A-HEADER GRAMMAR sip_bad_mask \ sip_parser_table.c.in sip_tag.c.in \ sip_extra_headers.txt \ images/sip-parser.eps images/sip-parser.gif \ images/sip-parser2.eps images/sip-parser2.gif \ images/sip-parser3.eps images/sip-parser3.gif \ images/sip-parser4.eps images/sip-parser4.gif \ tests/own0.txt tests/own1.txt tests/own2.txt tests/own3.txt \ tests/own4.txt tests/own5.txt tests/own6.txt tests/own8.txt \ tests/test1.txt tests/test-ack-1.txt tests/test2.txt tests/test3.txt \ tests/test4.txt tests/test5.txt tests/test6.txt tests/test7.txt \ tests/test8.txt tests/test9.txt tests/test10.txt tests/test10b.txt \ tests/test10c.txt tests/test11.txt tests/test12.txt tests/test13.txt \ tests/test14-req.txt tests/test14.txt tests/test15.txt \ tests/test16.txt tests/test17.txt tests/test18.txt tests/test19.txt \ tests/test1a.txt tests/test20.txt tests/test21.txt tests/test22.txt \ tests/test23.txt tests/test24.txt tests/test25.txt tests/test26.txt \ tests/test27.txt tests/test28.txt tests/test29.txt tests/test30.txt \ tests/test31.txt tests/test32.txt tests/test33.txt tests/test34.txt \ tests/test35.txt tests/test36.txt tests/test37.txt tests/test38.txt \ tests/test39.txt tests/test40.txt tests/test41.txt tests/test42.txt # ---------------------------------------------------------------------- # Tests TESTS = torture_sip run_test_sip_msg run_test_date dist_noinst_SCRIPTS = run_test_sip_msg run_test_date # ---------------------------------------------------------------------- # Sofia specific rules include $(top_srcdir)/rules/sofia.am MSG_PARSER_AWK = $(srcdir)/../msg/msg_parser.awk AWK_SIP_AWK = LC_ALL=C $(AWK) -f $(MSG_PARSER_AWK) module=sip SS_SIP_H = ${srcdir}/sofia-sip/sip.h EXTRA = ${srcdir}/sip_extra_headers.txt ${GENERATED_H} ${GENERATED_C}: ${SS_SIP_H} ${MSG_PARSER_AWK} sofia-sip/sip_hclasses.h: ${srcdir}/sofia-sip/sip_hclasses.h.in @-mkdir sofia-sip 2>/dev/null || true ${AWK_SIP_AWK} PR=$@ TEMPLATE=${srcdir}/sofia-sip/sip_hclasses.h.in \ ${SS_SIP_H} sofia-sip/sip_protos.h: ${srcdir}/sofia-sip/sip_protos.h.in @-mkdir sofia-sip 2>/dev/null || true ${AWK_SIP_AWK} PR=$@ TEMPLATE=${srcdir}/sofia-sip/sip_protos.h.in \ ${SS_SIP_H} sofia-sip/sip_tag.h: ${srcdir}/sofia-sip/sip_tag.h.in @-mkdir sofia-sip 2>/dev/null || true ${AWK_SIP_AWK} PR=$@ TEMPLATE=${srcdir}/sofia-sip/sip_tag.h.in \ ${SS_SIP_H} sip_tag.c: ${srcdir}/sip_tag.c.in ${EXTRA} ${AWK_SIP_AWK} PR=$@ TEMPLATE=${srcdir}/sip_tag.c.in \ ${SS_SIP_H} ${EXTRA} # Note: sip_bad_mask is used by nta to weed out bad messages sip_parser_table.c: ${srcdir}/sip_parser_table.c.in ${EXTRA} sip_bad_mask ${AWK_SIP_AWK} PT=$@ TEMPLATE=${srcdir}/sip_parser_table.c.in \ FLAGFILE=${srcdir}/sip_bad_mask \ MC_HASH_SIZE=127 MC_SHORT_SIZE=26 \ ${SS_SIP_H} ${EXTRA} sofia-sip/sip_extra.h: ${srcdir}/sofia-sip/sip_extra.h.in ${EXTRA} @-mkdir -p sofia-sip 2>/dev/null ${AWK_SIP_AWK} PR=$@ NO_FIRST=1 NO_LAST=1 \ PACKAGE_NAME="${PACKAGE_NAME}" \ PACKAGE_VERSION="${PACKAGE_VERSION}" \ TEMPLATE1=${srcdir}/sofia-sip/sip_hclasses.h.in \ TEMPLATE2=${srcdir}/sofia-sip/sip_protos.h.in \ TEMPLATE3=${srcdir}/sofia-sip/sip_tag.h.in \ TEMPLATE=${srcdir}/sofia-sip/sip_extra.h.in ${EXTRA} sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/Makefile.in000066400000000000000000001533341223300710500224230ustar00rootroot00000000000000# Makefile.in generated by automake 1.14 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 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 sip module # # ---------------------------------------------------------------------- # Header paths # common Makefile targets for libsofia-sip-ua(-glib) modules # ---------------------------------------------------------- # # run tests with valgrind # # Copyright (C) 2007 Nokia Corporation. # 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 file contains free software from Makefile.in by the Free Software # Foundation: # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 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. # # Generate lcov output # # # Copyright (C) 2007 Nokia Corporation # Contact: Pekka Pessi # Licensed under LGPL. See file COPYING. # # Silent compilation w/ Automake 1.9 or 1.10 # ---------------------------------------------------------- # Automake 1.9.6 is not clever enough to override suffix rules within if # if SOFIA_COMPILE_SILENT VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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@ check_PROGRAMS = torture_sip$(EXEEXT) test_sip_msg$(EXEEXT) \ validator$(EXEEXT) test_date$(EXEEXT) TESTS = torture_sip$(EXEEXT) run_test_sip_msg run_test_date DIST_COMMON = $(top_srcdir)/rules/sofia.am \ $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am \ $(top_srcdir)/rules/silent.am $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(srcdir)/Doxyfile.in \ $(dist_noinst_SCRIPTS) $(top_srcdir)/depcomp \ $(nobase_include_sofia_HEADERS) $(top_srcdir)/test-driver \ ChangeLog # Use with --enable-ndebug @NDEBUG_TRUE@am__append_1 = -DNDEBUG @HAVE_GENPNG_TRUE@@HAVE_LCOV_TRUE@am__append_2 = --frames @HAVE_LCOV_TRUE@am__append_3 = lcov lcov-report lcov-rerun clean-lcov covcheck uncovered subdir = libsofia-sip-ua/sip ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(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)/m4/sac-coverage.m4 \ $(top_srcdir)/m4/sac-general.m4 \ $(top_srcdir)/m4/sac-openssl.m4 \ $(top_srcdir)/m4/sac-pkg-config.m4 $(top_srcdir)/m4/sac-su2.m4 \ $(top_srcdir)/m4/sac-tport.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libsofia-sip-ua/su/sofia-sip/su_configure.h CONFIG_CLEAN_FILES = Doxyfile CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libsip_la_LIBADD = am__objects_1 = am__objects_2 = sip_tag.lo sip_parser_table.lo am__objects_3 = $(am__objects_1) $(am__objects_2) sip_tag_ref.lo am_libsip_la_OBJECTS = sip_parser.lo sip_header.lo sip_util.lo \ sip_pref_util.lo sip_basic.lo sip_extra.lo sip_feature.lo \ sip_mime.lo sip_security.lo sip_event.lo sip_prack.lo \ sip_refer.lo sip_session.lo sip_caller_prefs.lo sip_reason.lo \ sip_status.lo sip_time.lo sip_tag_class.lo sip_inlined.lo \ $(am__objects_3) libsip_la_OBJECTS = $(am_libsip_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_date_SOURCES = test_date.c test_date_OBJECTS = test_date.$(OBJEXT) test_date_LDADD = $(LDADD) am__DEPENDENCIES_1 = test_date_DEPENDENCIES = libsip.la ../msg/libmsg.la ../bnf/libbnf.la \ ../url/liburl.la ../ipt/libipt.la ../su/libsu.la \ $(am__DEPENDENCIES_1) test_date_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(test_date_LDFLAGS) $(LDFLAGS) -o $@ test_sip_msg_SOURCES = test_sip_msg.c test_sip_msg_OBJECTS = test_sip_msg.$(OBJEXT) test_sip_msg_LDADD = $(LDADD) test_sip_msg_DEPENDENCIES = libsip.la ../msg/libmsg.la \ ../bnf/libbnf.la ../url/liburl.la ../ipt/libipt.la \ ../su/libsu.la $(am__DEPENDENCIES_1) test_sip_msg_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(test_sip_msg_LDFLAGS) $(LDFLAGS) -o $@ torture_sip_SOURCES = torture_sip.c torture_sip_OBJECTS = torture_sip.$(OBJEXT) torture_sip_LDADD = $(LDADD) torture_sip_DEPENDENCIES = libsip.la ../msg/libmsg.la ../bnf/libbnf.la \ ../url/liburl.la ../ipt/libipt.la ../su/libsu.la \ $(am__DEPENDENCIES_1) torture_sip_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(torture_sip_LDFLAGS) $(LDFLAGS) -o $@ validator_SOURCES = validator.c validator_OBJECTS = validator.$(OBJEXT) validator_LDADD = $(LDADD) validator_DEPENDENCIES = libsip.la ../msg/libmsg.la ../bnf/libbnf.la \ ../url/liburl.la ../ipt/libipt.la ../su/libsu.la \ $(am__DEPENDENCIES_1) SCRIPTS = $(dist_noinst_SCRIPTS) 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) -I$(top_builddir)/libsofia-sip-ua/su/sofia-sip depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f 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) 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 = $(libsip_la_SOURCES) test_date.c test_sip_msg.c \ torture_sip.c validator.c DIST_SOURCES = $(libsip_la_SOURCES) test_date.c test_sip_msg.c \ torture_sip.c validator.c 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)$(include_sofiadir)" HEADERS = $(nobase_include_sofia_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)` 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=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ 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_DRIVER = $(SHELL) $(top_srcdir)/test-driver 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) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CHECK_CFLAGS = @CHECK_CFLAGS@ CHECK_LIBS = @CHECK_LIBS@ COVERAGE_FLAGS = @COVERAGE_FLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CWFLAG = @CWFLAG@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV = @GCOV@ GENHTML = @GENHTML@ GENPNG = @GENPNG@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GLIB_VERSION = @GLIB_VERSION@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVER_SOFIA_SIP_UA_AGE = @LIBVER_SOFIA_SIP_UA_AGE@ LIBVER_SOFIA_SIP_UA_CUR = @LIBVER_SOFIA_SIP_UA_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_AGE = @LIBVER_SOFIA_SIP_UA_GLIB_AGE@ LIBVER_SOFIA_SIP_UA_GLIB_CUR = @LIBVER_SOFIA_SIP_UA_GLIB_CUR@ LIBVER_SOFIA_SIP_UA_GLIB_REV = @LIBVER_SOFIA_SIP_UA_GLIB_REV@ LIBVER_SOFIA_SIP_UA_GLIB_SOVER = @LIBVER_SOFIA_SIP_UA_GLIB_SOVER@ LIBVER_SOFIA_SIP_UA_REV = @LIBVER_SOFIA_SIP_UA_REV@ LIBVER_SOFIA_SIP_UA_SOVER = @LIBVER_SOFIA_SIP_UA_SOVER@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MINGW_ENVIRONMENT = @MINGW_ENVIRONMENT@ MKDIR_P = @MKDIR_P@ MOSTLYCLEANFILES = @MOSTLYCLEANFILES@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ RANLIB = @RANLIB@ REPLACE_LIBADD = @REPLACE_LIBADD@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ SOFIA_GLIB_CFLAGS = @SOFIA_GLIB_CFLAGS@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ SOFIA_PLAT_CFLAGS = @SOFIA_PLAT_CFLAGS@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ VERSION = @VERSION@ VER_LIBSOFIA_SIP_UA_MAJOR_MINOR = @VER_LIBSOFIA_SIP_UA_MAJOR_MINOR@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ include_sofiadir = @include_sofiadir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ openssl_CFLAGS = @openssl_CFLAGS@ openssl_LIBS = @openssl_LIBS@ 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@ INCLUDES = -I$(srcdir)/../bnf -I../bnf \ -I$(srcdir)/../ipt -I../ipt \ -I$(srcdir)/../msg -I../msg \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su # ---------------------------------------------------------------------- # Build targets noinst_LTLIBRARIES = libsip.la # ---------------------------------------------------------------------- # Rules for building the targets GENERATED_H = sofia-sip/sip_hclasses.h \ sofia-sip/sip_protos.h sofia-sip/sip_tag.h \ sofia-sip/sip_extra.h H_IN = sofia-sip/sip_hclasses.h.in \ sofia-sip/sip_protos.h.in sofia-sip/sip_tag.h.in \ sofia-sip/sip_extra.h.in PUBLIC_H = sofia-sip/sip.h sofia-sip/sip_util.h \ sofia-sip/sip_header.h sofia-sip/sip_parser.h \ sofia-sip/sip_tag_class.h sofia-sip/sip_status.h GENERATED_C = sip_tag.c sip_parser_table.c BUILT_SOURCES = $(GENERATED_H) $(GENERATED_C) sip_tag_ref.c nobase_include_sofia_HEADERS = $(GENERATED_H) $(PUBLIC_H) $(H_IN) libsip_la_SOURCES = $(INTERNAL_H) \ sip_parser.c sip_header.c sip_util.c sip_pref_util.c \ sip_basic.c sip_extra.c sip_feature.c sip_mime.c \ sip_security.c sip_event.c sip_prack.c \ sip_refer.c sip_session.c \ sip_caller_prefs.c sip_reason.c \ sip_status.c sip_time.c \ sip_tag_class.c sip_inlined.c \ $(BUILT_SOURCES) COVERAGE_INPUT = $(libsip_la_SOURCES) $(include_sofia_HEADERS) LDADD = libsip.la ../msg/libmsg.la ../bnf/libbnf.la ../url/liburl.la \ ../ipt/libipt.la ../su/libsu.la $(openssl_LIBS) torture_sip_LDFLAGS = -static test_sip_msg_LDFLAGS = -static test_date_LDFLAGS = -static # ---------------------------------------------------------------------- # Install and distribution rules # note: srcdir needs to be specified, otherwise # breaks make distcheck target EXTRA_DIST = sip.docs sip_parser.docs sip.doxyaliases \ ADD-A-HEADER GRAMMAR sip_bad_mask \ sip_parser_table.c.in sip_tag.c.in \ sip_extra_headers.txt \ images/sip-parser.eps images/sip-parser.gif \ images/sip-parser2.eps images/sip-parser2.gif \ images/sip-parser3.eps images/sip-parser3.gif \ images/sip-parser4.eps images/sip-parser4.gif \ tests/own0.txt tests/own1.txt tests/own2.txt tests/own3.txt \ tests/own4.txt tests/own5.txt tests/own6.txt tests/own8.txt \ tests/test1.txt tests/test-ack-1.txt tests/test2.txt tests/test3.txt \ tests/test4.txt tests/test5.txt tests/test6.txt tests/test7.txt \ tests/test8.txt tests/test9.txt tests/test10.txt tests/test10b.txt \ tests/test10c.txt tests/test11.txt tests/test12.txt tests/test13.txt \ tests/test14-req.txt tests/test14.txt tests/test15.txt \ tests/test16.txt tests/test17.txt tests/test18.txt tests/test19.txt \ tests/test1a.txt tests/test20.txt tests/test21.txt tests/test22.txt \ tests/test23.txt tests/test24.txt tests/test25.txt tests/test26.txt \ tests/test27.txt tests/test28.txt tests/test29.txt tests/test30.txt \ tests/test31.txt tests/test32.txt tests/test33.txt tests/test34.txt \ tests/test35.txt tests/test36.txt tests/test37.txt tests/test38.txt \ tests/test39.txt tests/test40.txt tests/test41.txt tests/test42.txt dist_noinst_SCRIPTS = run_test_sip_msg run_test_date sofiasrcdir = ${top_srcdir}/libsofia-sip-ua sofiabuilddir = ${top_builddir}/libsofia-sip-ua AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(SOFIA_CFLAGS) \ $(openssl_CFLAGS) $(SOFIA_PLAT_CFLAGS) $(am__append_1) SOFIA_COVERAGE = $(COVERAGE_FLAGS) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files TAG_AWK = ${sofiasrcdir}/su/tag_dll.awk SUFFIXES = _tag_ref.c _tag.c INTERNAL_INCLUDES = \ -I${sofiasrcdir}/features -I${sofiabuilddir}/features \ -I${sofiasrcdir}/ipt -I${sofiabuilddir}/ipt \ -I${sofiasrcdir}/iptsec -I${sofiabuilddir}/iptsec \ -I${sofiasrcdir}/bnf -I${sofiabuilddir}/bnf \ -I${sofiasrcdir}/http -I${sofiabuilddir}/http \ -I${sofiasrcdir}/msg -I${sofiabuilddir}/msg \ -I${sofiasrcdir}/nth -I${sofiabuilddir}/nth \ -I${sofiasrcdir}/nta -I${sofiabuilddir}/nta \ -I${sofiasrcdir}/nea -I${sofiabuilddir}/nea \ -I${sofiasrcdir}/nua -I${sofiabuilddir}/nua \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sdp -I${sofiabuilddir}/sdp \ -I${sofiasrcdir}/sip -I${sofiabuilddir}/sip \ -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ -I${sofiasrcdir}/sresolv -I${sofiabuilddir}/sresolv \ -I${sofiasrcdir}/tport -I${sofiabuilddir}/tport \ -I${sofiasrcdir}/stun -I${sofiabuilddir}/stun \ -I${sofiasrcdir}/url -I${sofiabuilddir}/url \ -I${sofiasrcdir}/su -I${sofiabuilddir}/su PHONY = built-sources clean-built-sources $(am__append_3) VALGRIND = valgrind VALGRINDFLAGS = --tool=memcheck # Scripts @HAVE_LCOV_TRUE@LCOV_UNCOVERED = ${top_srcdir}/scripts/uncovered @HAVE_LCOV_TRUE@LCOV_REPORT = ${top_srcdir}/scripts/lcov-report # Report directory @HAVE_LCOV_TRUE@lcovdir = ${top_builddir}/lcov # Options @HAVE_LCOV_TRUE@GENHTML_OPTIONS = --show-details --legend \ @HAVE_LCOV_TRUE@ $(am__append_2) # Fancy shell command that expands to directory relative to top_builddir @HAVE_LCOV_TRUE@expand_subdir = `pwd|sed "s'\`cd ${top_builddir};pwd\`''"` SOFIA_SILENT = @ LIBTOOL_FLAGS = --silent # From Automake 1.9.6 - LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(LIBTOOL_FLAGS) \ $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) LINK = ${SOFIA_SILENT}test "${SOFIA_SILENT}" != @ || echo ' LINK $@'; \ $(LIBTOOL) --tag=CC --mode=link $(LIBTOOL_FLAGS) \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ # ---------------------------------------------------------------------- # Sofia specific rules MSG_PARSER_AWK = $(srcdir)/../msg/msg_parser.awk AWK_SIP_AWK = LC_ALL=C $(AWK) -f $(MSG_PARSER_AWK) module=sip SS_SIP_H = ${srcdir}/sofia-sip/sip.h EXTRA = ${srcdir}/sip_extra_headers.txt all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: _tag_ref.c _tag.c .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.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 libsofia-sip-ua/sip/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu libsofia-sip-ua/sip/Makefile .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(top_srcdir)/rules/lcov.am $(top_srcdir)/rules/silent.am: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): Doxyfile: $(top_builddir)/config.status $(srcdir)/Doxyfile.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ 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}; \ } libsip.la: $(libsip_la_OBJECTS) $(libsip_la_DEPENDENCIES) $(EXTRA_libsip_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libsip_la_OBJECTS) $(libsip_la_LIBADD) $(LIBS) 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_date$(EXEEXT): $(test_date_OBJECTS) $(test_date_DEPENDENCIES) $(EXTRA_test_date_DEPENDENCIES) @rm -f test_date$(EXEEXT) $(AM_V_CCLD)$(test_date_LINK) $(test_date_OBJECTS) $(test_date_LDADD) $(LIBS) test_sip_msg$(EXEEXT): $(test_sip_msg_OBJECTS) $(test_sip_msg_DEPENDENCIES) $(EXTRA_test_sip_msg_DEPENDENCIES) @rm -f test_sip_msg$(EXEEXT) $(AM_V_CCLD)$(test_sip_msg_LINK) $(test_sip_msg_OBJECTS) $(test_sip_msg_LDADD) $(LIBS) torture_sip$(EXEEXT): $(torture_sip_OBJECTS) $(torture_sip_DEPENDENCIES) $(EXTRA_torture_sip_DEPENDENCIES) @rm -f torture_sip$(EXEEXT) $(AM_V_CCLD)$(torture_sip_LINK) $(torture_sip_OBJECTS) $(torture_sip_LDADD) $(LIBS) validator$(EXEEXT): $(validator_OBJECTS) $(validator_DEPENDENCIES) $(EXTRA_validator_DEPENDENCIES) @rm -f validator$(EXEEXT) $(AM_V_CCLD)$(LINK) $(validator_OBJECTS) $(validator_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_basic.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_caller_prefs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_event.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_extra.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_feature.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_header.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_inlined.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_mime.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_parser.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_parser_table.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_prack.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_pref_util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_reason.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_refer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_security.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_session.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_status.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_tag.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_tag_class.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_tag_ref.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_time.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_date.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_sip_msg.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/torture_sip.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/validator.Po@am__quote@ .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.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) '$<'` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-nobase_include_sofiaHEADERS: $(nobase_include_sofia_HEADERS) @$(NORMAL_INSTALL) @list='$(nobase_include_sofia_HEADERS)'; test -n "$(include_sofiadir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(include_sofiadir)'"; \ $(MKDIR_P) "$(DESTDIR)$(include_sofiadir)" || exit 1; \ fi; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo " $(MKDIR_P) '$(DESTDIR)$(include_sofiadir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(include_sofiadir)/$$dir"; }; \ echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(include_sofiadir)/$$dir'"; \ $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(include_sofiadir)/$$dir" || exit $$?; }; \ done uninstall-nobase_include_sofiaHEADERS: @$(NORMAL_UNINSTALL) @list='$(nobase_include_sofia_HEADERS)'; test -n "$(include_sofiadir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ dir='$(DESTDIR)$(include_sofiadir)'; $(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; \ else \ 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 $(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 $$? torture_sip.log: torture_sip$(EXEEXT) @p='torture_sip$(EXEEXT)'; \ b='torture_sip'; \ $(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) run_test_sip_msg.log: run_test_sip_msg @p='run_test_sip_msg'; \ b='run_test_sip_msg'; \ $(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) run_test_date.log: run_test_date @p='run_test_date'; \ b='run_test_date'; \ $(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: $(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: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LTLIBRARIES) $(SCRIPTS) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(include_sofiadir)"; 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: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) -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: 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) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) 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) @HAVE_LCOV_FALSE@clean-local: clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libtool clean-local \ clean-noinstLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -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-nobase_include_sofiaHEADERS 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 -rf ./$(DEPDIR) -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-nobase_include_sofiaHEADERS .MAKE: all check check-am install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libtool clean-local \ 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-nobase_include_sofiaHEADERS 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 \ uninstall-nobase_include_sofiaHEADERS built-sources: $(BUILT_SOURCES) clean-built-sources: -rm -rf $(BUILT_SOURCES) $(BUILT_SOURCES:%=$(srcdir)/%) *_tag_ref.c: $(TAG_AWK) _tag.c_tag_ref.c: $(AWK) -f $(TAG_AWK) NODLL=1 $(TAG_DLL_FLAGS) REF=$@ $< ../bnf/libbnf.la ../http/libhttp.la ../ipt/libipt.la ../iptsec/libiptsec.la \ ../msg/libmsg.la ../nea/libnea.la ../nta/libnta.la ../nth/libnth.la \ ../nua/libnua.la ../sdp/libsdp.la ../sip/libsip.la ../soa/libsoa.la \ ../sresolv/libsresolv.la ../stun/libstun.la ../su/libsu.la \ ../tport/libtport.la ../url/liburl.la: cd $(@D) && $(MAKE) $(@F) checklib: $(noinst_LTLIBRARIES) $(check_LTLIBRARIES) valcheck: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) valcheck-am valcheck-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS # Run tests with valgrind in valcheck-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ list='$(TESTS)'; \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ if case $$tst in \ run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ $${dir}$$tst ;; \ esac ; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ echo "XPASS: $$tst"; \ ;; \ *) \ echo "PASS: $$tst"; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xfail=`expr $$xfail + 1`; \ echo "XFAIL: $$tst"; \ ;; \ *) \ failed=`expr $$failed + 1`; \ echo "FAIL: $$tst"; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ echo "SKIP: $$tst"; \ fi; \ done; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="All $$all tests passed"; \ else \ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all tests failed"; \ else \ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ skipped="($$skip tests were not run)"; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ report=""; \ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ report="Please report to $(PACKAGE_BUGREPORT)"; \ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ echo "$$dashes"; \ echo "$$banner"; \ test -z "$$skipped" || echo "$$skipped"; \ test -z "$$report" || echo "$$report"; \ echo "$$dashes"; \ test "$$failed" -eq 0; \ else :; fi # # Generate pretty coverage report (unless it has been already done) # @HAVE_LCOV_TRUE@lcov: @HAVE_LCOV_TRUE@ @-test -r ${lcovdir}${expand_subdir}/lcov.info \ @HAVE_LCOV_TRUE@ || make lcov-report # Generate pretty coverage report based on current coverage data @HAVE_LCOV_TRUE@lcov-report: @HAVE_LCOV_TRUE@ sub=${expand_subdir} odir=${lcovdir}$$sub ; \ @HAVE_LCOV_TRUE@ rm -rf $$odir ; mkdir -p $$odir && \ @HAVE_LCOV_TRUE@ ${LCOV_REPORT} ${GENHTML_OPTIONS} \ @HAVE_LCOV_TRUE@ --title "${PACKAGE_NAME}-${PACKAGE_VERSION}$$sub" \ @HAVE_LCOV_TRUE@ --srcdir=${srcdir} -o $$odir # Rerun checks before generating report @HAVE_LCOV_TRUE@lcov-rerun: clean-lcov @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) lcov-report # Show all uncovered lines as errors @HAVE_LCOV_TRUE@uncovered: @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} # Run check in current dir and show all uncovered lines as errors @HAVE_LCOV_TRUE@covcheck: @HAVE_LCOV_TRUE@ -find . -name "*.gcda" | xargs rm -rf @HAVE_LCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check @HAVE_LCOV_TRUE@ ${LCOV_UNCOVERED} --lcov-dir=${lcovdir} --srcdir=${srcdir} @HAVE_LCOV_TRUE@clean-local:: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true @HAVE_LCOV_TRUE@clean-lcov: @HAVE_LCOV_TRUE@ -rm -rf ${lcovdir}`pwd|sed "s'\`cd ${top_builddir};pwd\`''"` @HAVE_LCOV_TRUE@ find . -name "*.gcda" | xargs rm -f || true # Rules from depend2.am (GENERIC = TRUE, SUBDIROBJ = FALSE, %FASTDEP% = am_fastdepCC) silenced. .c.o: @test "${SOFIA_SILENT}" != @ || echo ' COMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(COMPILE) -c -o $@ $< .c.lo: @test "${SOFIA_SILENT}" != @ || echo ' LTCOMPILE $@' @am__fastdepCC_TRUE@ ${SOFIA_SILENT}if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR="$(DEPDIR)" $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< @AMDEP_FALSE@@am__fastdepCC_FALSE@ ${SOFIA_SILENT}$(LTCOMPILE) -c -o $@ $< # endif ${GENERATED_H} ${GENERATED_C}: ${SS_SIP_H} ${MSG_PARSER_AWK} sofia-sip/sip_hclasses.h: ${srcdir}/sofia-sip/sip_hclasses.h.in @-mkdir sofia-sip 2>/dev/null || true ${AWK_SIP_AWK} PR=$@ TEMPLATE=${srcdir}/sofia-sip/sip_hclasses.h.in \ ${SS_SIP_H} sofia-sip/sip_protos.h: ${srcdir}/sofia-sip/sip_protos.h.in @-mkdir sofia-sip 2>/dev/null || true ${AWK_SIP_AWK} PR=$@ TEMPLATE=${srcdir}/sofia-sip/sip_protos.h.in \ ${SS_SIP_H} sofia-sip/sip_tag.h: ${srcdir}/sofia-sip/sip_tag.h.in @-mkdir sofia-sip 2>/dev/null || true ${AWK_SIP_AWK} PR=$@ TEMPLATE=${srcdir}/sofia-sip/sip_tag.h.in \ ${SS_SIP_H} sip_tag.c: ${srcdir}/sip_tag.c.in ${EXTRA} ${AWK_SIP_AWK} PR=$@ TEMPLATE=${srcdir}/sip_tag.c.in \ ${SS_SIP_H} ${EXTRA} # Note: sip_bad_mask is used by nta to weed out bad messages sip_parser_table.c: ${srcdir}/sip_parser_table.c.in ${EXTRA} sip_bad_mask ${AWK_SIP_AWK} PT=$@ TEMPLATE=${srcdir}/sip_parser_table.c.in \ FLAGFILE=${srcdir}/sip_bad_mask \ MC_HASH_SIZE=127 MC_SHORT_SIZE=26 \ ${SS_SIP_H} ${EXTRA} sofia-sip/sip_extra.h: ${srcdir}/sofia-sip/sip_extra.h.in ${EXTRA} @-mkdir -p sofia-sip 2>/dev/null ${AWK_SIP_AWK} PR=$@ NO_FIRST=1 NO_LAST=1 \ PACKAGE_NAME="${PACKAGE_NAME}" \ PACKAGE_VERSION="${PACKAGE_VERSION}" \ TEMPLATE1=${srcdir}/sofia-sip/sip_hclasses.h.in \ TEMPLATE2=${srcdir}/sofia-sip/sip_protos.h.in \ TEMPLATE3=${srcdir}/sofia-sip/sip_tag.h.in \ TEMPLATE=${srcdir}/sofia-sip/sip_extra.h.in ${EXTRA} # 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: sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/images/000077500000000000000000000000001223300710500216125ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/images/sip-parser.eps000066400000000000000000005035461223300710500244250ustar00rootroot00000000000000EEA%!PS-Adobe-3.0 EPSF-3.0 %%Creator: ImageMark Software Labs %%For: () () %%Title: G:\Docs\Sofia\Graphics\sip-parser.eps %%CreationDate: () () %%BoundingBox: 0 0 401 340 %%DocumentProcessColors: Black %%ColorUsage:Color %%DocumentFonts: Helvetica %%+Helvetica-Bold %%+Helvetica-Oblique %%+Helvetica-BoldOblique %%+Times-Roman %%+Times-Bold %%+Times-Italic %%+Times-BoldItalic %%+Courier %%+Courier-Bold %%+Courier-Oblique %%+Courier-BoldOblique %%+Symbol %%DocumentSuppliedResources: procset Adobe_level2_AI5 1.2 0 %%+ procset Adobe_screens_AI5 1.0 0 %%+ procset Adobe_typography_AI5 1.0 0 %%+ procset Adobe_ColorImage_AI6 1.1 0 %%+ procset Adobe_blend_AI5 1.0 0 %%+ procset Adobe_pattern_AI5 1.0 0 %%+ procset Adobe_Illustrator_AI5 1.0 0 %AI5_FileFormat 3.0 %AI3_ColorUsage: Color %AI3_TemplateBox: 0 0 401 340 %AI3_TileBox: 0 0 401 340 %AI3_DocumentPreview: None %%Template: %%PageOrigin:0.0000 0.0000 %AI7_GridSettings: 72 8 72 8 1 0 0.8 0.8 0.8 0.9 0.9 0.9 %%EndComments %%BeginProlog %%BeginResource: procset Adobe_level2_AI5 1.2 0 %%Title: (Adobe Illustrator (R) Version 5.0 Level 2 Emulation) %%Version: 1.2 0 %%CreationDate: (04/10/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /Adobe_level2_AI5 25 dict dup begin put /packedarray where not { userdict begin /packedarray { array astore readonly } bind def /setpacking /pop load def /currentpacking false def end 0 } if pop userdict /defaultpacking currentpacking put true setpacking /initialize { Adobe_level2_AI5 begin } bind def /terminate { currentdict Adobe_level2_AI5 eq { end } if } bind def mark /setcustomcolor where not { /findcmykcustomcolor { 0 6 packedarray } bind def /findrgbcustomcolor { 1 5 packedarray } bind def /setcustomcolor { exch aload pop 0 eq { pop 4 { 4 index mul 4 1 roll } repeat 5 -1 roll pop setcmykcolor } { pop 3 { 1 exch sub 3 index mul 1 exch sub 3 1 roll } repeat 4 -1 roll pop setrgbcolor } ifelse } def } if /gt38? mark {version cvr cvx exec} stopped {cleartomark true} {38 gt exch pop} ifelse def userdict /deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt put userdict /level2? systemdict /languagelevel known dup { pop systemdict /languagelevel get 2 ge } if put /level2ScreenFreq { begin 60 HalftoneType 1 eq { pop Frequency } if HalftoneType 2 eq { pop GrayFrequency } if HalftoneType 5 eq { pop Default level2ScreenFreq } if end } bind def userdict /currentScreenFreq level2? {currenthalftone level2ScreenFreq} {currentscreen pop pop} ifelse put level2? not { /setcmykcolor where not { /setcmykcolor { exch .11 mul add exch .59 mul add exch .3 mul add 1 exch sub setgray } def } if /currentcmykcolor where not { /currentcmykcolor { 0 0 0 1 currentgray sub } def } if /setoverprint where not { /setoverprint /pop load def } if /selectfont where not { /selectfont { exch findfont exch dup type /arraytype eq { makefont } { scalefont } ifelse setfont } bind def } if /cshow where not { /cshow { [ 0 0 5 -1 roll aload pop ] cvx bind forall } bind def } if } if cleartomark /anyColor? { add add add 0 ne } bind def /testColor { gsave setcmykcolor currentcmykcolor grestore } bind def /testCMYKColorThrough { testColor anyColor? } bind def userdict /composite? level2? { gsave 1 1 1 1 setcmykcolor currentcmykcolor grestore add add add 4 eq } { 1 0 0 0 testCMYKColorThrough 0 1 0 0 testCMYKColorThrough 0 0 1 0 testCMYKColorThrough 0 0 0 1 testCMYKColorThrough and and and } ifelse put composite? not { userdict begin gsave /cyan? 1 0 0 0 testCMYKColorThrough def /magenta? 0 1 0 0 testCMYKColorThrough def /yellow? 0 0 1 0 testCMYKColorThrough def /black? 0 0 0 1 testCMYKColorThrough def grestore /isCMYKSep? cyan? magenta? yellow? black? or or or def /customColor? isCMYKSep? not def end } if end defaultpacking setpacking %%EndResource %%BeginResource: procset Adobe_typography_AI5 1.0 1 %%Title: (Typography Operators) %%Version: 1.0 %%CreationDate:(03/26/93) () %%Copyright: ((C) 1987-1993 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_typography_AI5 54 dict dup begin put /initialize { begin begin Adobe_typography_AI5 begin Adobe_typography_AI5 { dup xcheck { bind } if pop pop } forall end end end Adobe_typography_AI5 begin } def /terminate { currentdict Adobe_typography_AI5 eq { end } if } def /modifyEncoding { /_tempEncode exch ddef /_pntr 0 ddef { counttomark -1 roll dup type dup /marktype eq { pop pop exit } { /nametype eq { _tempEncode /_pntr dup load dup 3 1 roll 1 add ddef 3 -1 roll put } { /_pntr exch ddef } ifelse } ifelse } loop _tempEncode } def /TE { StandardEncoding 256 array copy modifyEncoding /_nativeEncoding exch def } def % /TZ { dup type /arraytype eq { /_wv exch def } { /_wv 0 def } ifelse /_useNativeEncoding exch def pop pop findfont _wv type /arraytype eq { _wv makeblendedfont } if dup length 2 add dict begin mark exch { 1 index /FID ne { def } if cleartomark mark } forall pop /FontName exch def counttomark 0 eq { 1 _useNativeEncoding eq { /Encoding _nativeEncoding def } if cleartomark } { /Encoding load 256 array copy modifyEncoding /Encoding exch def } ifelse FontName currentdict end definefont pop } def /tr { _ax _ay 3 2 roll } def /trj { _cx _cy _sp _ax _ay 6 5 roll } def /a0 { /Tx { dup currentpoint 3 2 roll tr _psf newpath moveto tr _ctm _pss } ddef /Tj { dup currentpoint 3 2 roll trj _pjsf newpath moveto trj _ctm _pjss } ddef } def /a1 { /Tx { dup currentpoint 4 2 roll gsave dup currentpoint 3 2 roll tr _psf newpath moveto tr _ctm _pss grestore 3 1 roll moveto tr sp } ddef /Tj { dup currentpoint 4 2 roll gsave dup currentpoint 3 2 roll trj _pjsf newpath moveto trj _ctm _pjss grestore 3 1 roll moveto tr jsp } ddef } def /e0 { /Tx { tr _psf } ddef /Tj { trj _pjsf } ddef } def /e1 { /Tx { dup currentpoint 4 2 roll gsave tr _psf grestore 3 1 roll moveto tr sp } ddef /Tj { dup currentpoint 4 2 roll gsave trj _pjsf grestore 3 1 roll moveto tr jsp } ddef } def /i0 { /Tx { tr sp } ddef /Tj { trj jsp } ddef } def /i1 { W N } def /o0 { /Tx { tr sw rmoveto } ddef /Tj { trj swj rmoveto } ddef } def /r0 { /Tx { tr _ctm _pss } ddef /Tj { trj _ctm _pjss } ddef } def /r1 { /Tx { dup currentpoint 4 2 roll currentpoint gsave newpath moveto tr _ctm _pss grestore 3 1 roll moveto tr sp } ddef /Tj { dup currentpoint 4 2 roll currentpoint gsave newpath moveto trj _ctm _pjss grestore 3 1 roll moveto tr jsp } ddef } def /To { pop _ctm currentmatrix pop } def /TO { iTe _ctm setmatrix newpath } def /Tp { pop _tm astore pop _ctm setmatrix _tDict begin /W { } def /h { } def } def /TP { end iTm 0 0 moveto } def /Tr { _render 3 le { currentpoint newpath moveto } if dup 8 eq { pop 0 } { dup 9 eq { pop 1 } if } ifelse dup /_render exch ddef _renderStart exch get load exec } def /iTm { _ctm setmatrix _tm concat 0 _rise translate _hs 1 scale } def /Tm { _tm astore pop iTm 0 0 moveto } def /Td { _mtx translate _tm _tm concatmatrix pop iTm 0 0 moveto } def /iTe { _render -1 eq { } { _renderEnd _render get dup null ne { load exec } { pop } ifelse } ifelse /_render -1 ddef } def /Ta { pop } def /Tf { dup 1000 div /_fScl exch ddef % selectfont } def /Tl { pop 0 exch _leading astore pop } def /Tt { pop } def /TW { 3 npop } def /Tw { /_cx exch ddef } def /TC { 3 npop } def /Tc { /_ax exch ddef } def /Ts { /_rise exch ddef currentpoint iTm moveto } def /Ti { 3 npop } def /Tz { 100 div /_hs exch ddef iTm } def /TA { pop } def /Tq { pop } def /Th { pop pop pop pop pop } def /TX { pop } def /Tk { exch pop _fScl mul neg 0 rmoveto } def /TK { 2 npop } def /T* { _leading aload pop neg Td } def /T*- { _leading aload pop Td } def /T- { _hyphen Tx } def /T+ { } def /TR { _ctm currentmatrix pop _tm astore pop iTm 0 0 moveto } def /TS { currentfont 3 1 roll /_Symbol_ _fScl 1000 mul selectfont 0 eq { Tx } { Tj } ifelse setfont } def /Xb { pop pop } def /Tb /Xb load def /Xe { pop pop pop pop } def /Te /Xe load def /XB { } def /TB /XB load def currentdict readonly pop end setpacking %%EndResource %%BeginResource: procset Adobe_screens_AI5 1.2 0 %%Title: (Adobe Illustrator (R) Version 5.0 Custom Halftone Screens ProcSet) %%Version: 1.2 0 %%CreationDate: (03/24/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking systemdict begin userdict /Adobe_screens_AI5 15 dict dup begin put /initialize { Adobe_screens_AI5 begin /screenid deviceDPI 600 gt composite? not or { -1 } { deviceDPI currentScreenFreq dup dup 60 ge exch 150 le and deviceDPI 300 le and { pop 60 } if div 1.41421 div 0.5 add cvi } ifelse def 2 screenid eq { /customsize 16 def /customdata /customdata2 def setcustomscreen } if 3 screenid eq { /customsize 24 def /customdata /customdata3 def setcustomscreen } if 4 screenid eq { /customsize 16 def /customdata /customdata4 def setcustomscreen } if 5 screenid eq { /customsize 20 def /customdata /customdata5 def setcustomscreen } if 6 screenid eq { /customsize 24 def /customdata /customdata6 def setcustomscreen } if 7 screenid eq { /customsize 28 def /customdata /customdata7 def setcustomscreen } if 8 screenid eq { /customsize 16 def /customdata /customdata8 def setcustomscreen } if } def /terminate { currentdict Adobe_screens_AI5 eq { end } if } def /setcustomscreen { deviceDPI customsize div 0 { 1 add 2 div customsize mul cvi exch 1 add 2 div customsize mul cvi exch customsize mul add customdata load exch get 256 div } setscreen } def /customdata2 28 28 mul string def currentfile customdata2 readhexstring 4180E8694988E2634382EA6B4B8AE061A01939C8A81737C2A21B3BCAAA1636C0 F8795998F6775796FA7B5B9AF57656952ED8B80727D6B60F2FDABA0626D5B50E 4E8DE6674786EE6F4F8EE5664685ED6EAD1434C6A61F3FCEAE1232C5A51E3ECD F3745493FE7F5F9EF1725291FD7E5E9D24D3B30C2CDEBE0222D1B10A2ADDBD04 4483EB6C4C8BE1624281E96A4A89E364A31C3CCBAB1535C1A11A3AC9A91838C3 FB7C5C9BF4755594F97A5A99F778589730DBBB0525D4B40D2DD9B90828D7B710 508FE4654584EC6D4D8CE7684887EF70AF1131C4A41D3DCCAC1333C7A72040CF F0715190FC7D5D9CF2735392FF80609F21D0B00929DCBC0323D2B20B2BDFBF01 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata3 28 28 mul string def currentfile customdata3 readhexstring 011DC7F5E73D0421CBF3E43A021EC8F6E83E0522CCF2E43A2B648BC4A0762F68 8AC39E732C658CC5A177306989C29D72D5B6521A6192D9B55219608FD6B6531B 6193DAB451185F8FFCEE440C28D2FCED430B27D1FDEF450C29D3FBEC420A26D0 BEA77D366F83BCA77C356E87BFA87E377082BBA67B346D86145B99E0AE4A1259 98DFB14E155C9AE1AD4A115897DEB04D0623CDF4E63C0420CAF8EA400723CDF4 E53B031FC9F7E93F316988C19F752E678EC6A378326A88C09F742D668DC6A278 DBB350175E91D8B8551C6395DCB24F165D90D7B7541C6294FAEC420925CFFFF1 470E2BD5F9EB410824CEFEF0460D2AD4BAA57A336C85BEAA80397180B9A47933 6B84BDA97F387181105797DDAF4C145A9CE3AB480F5696DDAE4B13599BE2AC49 021EC8F6E83E0522CCF2E43A011DC7F5E73D0421CBF3E43A2C658CC5A1773069 89C29D722B648BC4A0762F688AC39E73D6B6531B6193DAB451185F8FD5B6521A 6192D9B55219608FFDEF450C29D3FBEC420A26D0FCEE440C28D2FCED430B27D1 BFA87E377082BBA67B346D86BEA77D366F83BCA77C356E87155C9AE1AD4A1158 97DEB04D145B99E0AE4A125998DFB14E0723CDF4E53B031FC9F7E93F0623CDF4 E63C0420CAF8EA40326A88C09F742D668DC6A278316988C19F752E678EC6A378 DCB24F165D90D7B7541C6294DBB350175E91D8B8551C6395F9EB410824CEFEF0 460D2AD4FAEC420925CFFFF1470E2BD5B9A479336B84BDA97F387181BAA57A33 6C85BEAA803971800F5696DDAE4B13599BE2AC49105797DDAF4C145A9CE3AB48 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata4 28 28 mul string def currentfile customdata4 readhexstring 1139B8E0FAD2531B133BBAE2F8D05119417180A6AE9A7B4B437382A5AD987949 C08867272F6F92CAC28A66262E6E90C8E8DE5F070F37B6F2EADD5E060E36B5F0 FED6571F173FBEE6FDD5561E163EBDE5AB9E7F4F477786A1A99D7E4E467685A3 2C6C96CEC68E62222A6A95CDC58D64240C34B3F6EED95A020A32B1F5EDDB5C04 143CBBE3F9D1521A123AB9E1FBD3541C447483A4AC997A4A427281A7AF9B7C4C C38B65252D6D91C9C1896828307093CBEBDC5D050D35B4F1E9DF60081038B7F3 FCD4551D153DBCE4FFD758201840BFE7A89C7D4D457584A2AA9F8050487887A0 296994CCC48C63232B6B97CFC78F61210931B0F4ECDA5B030B33B2F7EFD85901 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata5 28 28 mul string def currentfile customdata5 readhexstring 010B34C3EBFCF7CE3F16020C35C4EDFBF6CD3E15102552A4D6EADDB5632B1126 54A5D5EADCB3622A3958768499C19E8C7C5E3A59778498C19D8B7B5DC8A99370 47334C7587AFC9AA936F46324B7485AEF1E5BC6B1E0A2351A3D8F2E4BC6A1E09 2351A2D7FFF9D14219050F38C6EFFEF9D04118040E37C6EFE8E0B7662D142856 A8D3E7DFB7652D132856A7D4BF9C8E7F603D5B7A8195BE9A8E7E603C5B798297 314A7389B2CCAD906D442F497289B1CBAC926E4508214FA1DBF4E2B9671B0720 4EA0DAF4E3BA691C030D36C5EDFBF6CD3F16010C34C3ECFDF8CF4017122654A6 D4E9DDB4622A112553A5D6EBDEB5642C3B59788397C09C8B7C5D3A58778599C2 9E8C7D5FCAAB926E46314B7486AFC8AA947048334D7587B0F2E4BB691D082250 A1D8F1E6BD6B1F0A2452A3D9FDF8CF4118030E36C5EEFFFAD1421A050F38C7F0 E6DFB6642C132755A7D3E8E1B8662E152957A8D2BE9A8D7E5F3B5A798296BF9B 8F80613D5C7B80952F487188B1CAAC916D443049728AB3CCAE906C43061F4D9F DAF3E2BA681C07214FA0DBF5E1B8671A00000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata6 28 28 mul string def currentfile customdata6 readhexstring 081A44B6E0F2FDECC150250C091B45B6E1F3FCEBC04F240C1D336199C7D8DCD3 A56C37221E33619AC8D7DBD2A46B36214864798091AEB1958C7E694C49657A81 90ADB0948B7D684BB99D8475593C405C7888A1BEBA9E8574583B3F5B7888A0BD E4CBAA712E1215326098CFE8E4CCA9712D1114315F97CEE7F5F1C6552B040719 43B5DFFAF6F0C6542A03061842B4DEF9FFEDC352270E0B1C47B8E3F4FEECC251 260D0A1C46B7E2F4DAD5A76E39232035639CCAD5D9D4A66D38231F34629BC9D6 AF938E806A4E4A677C838FABAE928D7F694D4A667B828FAC3E5A778AA3BFBC9F 8772563A3D597689A2BEBB9F8673573A14305E97D1EAE6CDA76F2B0F132F5D96 D0E9E5CDA8702C10051742B3DDFCF8EEC4522801041641B2DDFBF7EFC5532902 091B45B6E1F3FCEBC04F240C081A44B6E0F2FDECC150250C1E33619AC8D7DBD2 A46B36211D336199C7D8DCD3A56C372249657A8190ADB0948B7D684B48647980 91AEB1958C7E694CBA9E8574583B3F5B7888A0BDB99D8475593C405C7888A1BE E4CCA9712D1114315F97CEE7E4CBAA712E1215326098CFE8F6F0C6542A030618 42B4DEF9F5F1C6552B04071943B5DFFAFEECC251260D0A1C46B7E2F4FFEDC352 270E0B1C47B8E3F4D9D4A66D38231F34629BC9D6DAD5A76E39232035639CCAD5 AE928D7F694D4A667B828FACAF938E806A4E4A677C838FAB3D597689A2BEBB9F 8673573A3E5A778AA3BFBC9F8772563A132F5D96D0E9E5CDA8702C1014305E97 D1EAE6CDA76F2B0F041641B2DDFBF7EFC5532902051742B3DDFCF8EEC4522801 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata7 28 28 mul string def currentfile customdata7 readhexstring 01061B44B7E1F5FEFBE6BD4A210C01071B45B8E1F6FDFBE6BC4A200B09132A54 A7D1EAF5EED9B05D331609142B55A8D2EAF4EED9AF5C32161D2D3D6993C1CBE0 CEC59B7140301E2E3D6A93C0CADFCDC49A713F3047576C7B828DA2B6A48F867E 6F5A48576C7C828CA1B6A38F867E6E59BAAA958A78634E4451667A8498ADBAAB 968977624E4350657A8398ADE3D4C99F7539251A273C6892C2D7E4D4C89E7539 241A273B6891C1D6F8F2DDB460371005122A53A7D0ECF9F2DDB360360F051229 53A6D0EBFFFDE8BE4C220D03081D46B9E3F7FFFCE7BD4B210D02071C46B8E2F7 F3F0DBB15E34180B152C56A9D3E8F3EFDAB05D34170A142C55A9D2E9DFCCC69C 7341321F2F3F6B94BFC9DECCC59C7241311F2E3E6A94BFCAB5A38E8780705B49 596D7D808BA0B4A28D877F6F5B48586D7C818BA043506479859AAFBCAC978876 614C424F64798499AEBBAB968977624D19263B6791C3D8E5D6C79D7337231825 3A6690C3D7E5D5C79E74382304112952A5CFEDFAF0DBB25E350E03102851A5CE ECF9F1DCB25F360E01071B45B8E1F6FDFBE6BC4A200B01061B44B7E1F5FEFBE6 BD4A210C09142B55A8D2EAF4EED9AF5C321609132A54A7D1EAF5EED9B05D3316 1E2E3D6A93C0CADFCDC49A713F301D2D3D6993C1CBE0CEC59B71403048576C7C 828CA1B6A38F867E6E5947576C7B828DA2B6A48F867E6F5ABAAB968977624E43 50657A8398ADBAAA958A78634E4451667A8498ADE4D4C89E7539241A273B6891 C1D6E3D4C99F7539251A273C6892C2D7F9F2DDB360360F05122953A6D0EBF8F2 DDB460371005122A53A7D0ECFFFCE7BD4B210D02071C46B8E2F7FFFDE8BE4C22 0D03081D46B9E3F7F3EFDAB05D34170A142C55A9D2E9F3F0DBB15E34180B152C 56A9D3E8DECCC59C7241311F2E3E6A94BFCADFCCC69C7341321F2F3F6B94BFC9 B4A28D877F6F5B48586D7C818BA0B5A38E8780705B49596D7D808BA0424F6479 8499AEBBAB968977624D43506479859AAFBCAC978876614C18253A6690C3D7E5 D5C79E74382319263B6791C3D8E5D6C79D73372303102851A5CEECF9F1DCB25F 360E04112952A5CFEDFAF0DBB25E350E pop pop /customdata8 28 28 mul string def currentfile customdata8 readhexstring 050F2747B6D6EEF8FEF4DCBC4D2D1507111D375F9EC6E0E9EBE6CCA4653D1F13 2939556F8EA8C1D1D3C3AE9475573B2B4961717D808999B1B39B8B867F73634B B8A090827A6A5A42445C6C7C8492A2BAD8C8AA97785232222434546E8DACCADA F0E2CFA768401A0A0C1C365E9DC5E4F2FAF7DFBF50301802040E2646B5D5EDFC FFF5DDBD4E2E160806102848B7D7EFF9EAE7CDA5663E2014121E38609FC7E1E8 D2C2AF9576583C2C2A3A56708FA9C0D0B29A8A878074644C4A62727E818898B0 435B6B7B8593A3BBB9A19183796959412333536D8CADCBDBD9C9AB9677513121 0B1B355D9CC4E5F3F1E3CEA6673F1909030D2545B4D4ECFDFBF6DEBE4F2F1701 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop end end defaultpacking setpacking %%EndResource %%BeginResource: procset AGM_Gradient_Sep 1.0 0 %%Title: (AGM Gradient Procset) %%Version: 1.0 0 %%CreationDate: (4/26/96) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /AGM_Gradient_Sep 5 dict dup begin put /AGM_Gradient_Sep_private 100 dict def /initialize{ AGM_Gradient_Sep begin AGM_Gradient_Sep_private begin _compositeJob{ initializeSinglePassSeps }{ initializeMultiPassSeps }ifelse initializeSeps AGM_Gradient_private begin /_fillSD newSpotDict def /_rampSD newSpotDict def /_nCustomColorSD nd end AGM_Gradient_Sep_private { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall AGM_Gradient_Sep { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall end currentdict readonly pop end }def /terminate{ currentdict AGM_Gradient_Sep eq{ end }if }def AGM_Gradient_Sep_private begin /initializeSeps{ _noImage not _level2PS not and{ /_whiteBytes 1 makeByte8 pt /knockOut{ 8 setImageParms _whiteBytes /_image load 5 execImage }def /linealFill{ mySave 8 setImageParms _color{ _nCustomColorSD begin cyan magenta yellow black _spotColor{ spot1 begin /tintImage tintValue 1 exch sub makeByte8 def end spot2 begin /tintImage tintValue 1 exch sub makeByte8 def end }if end 4{ makeByte8 4 1 roll }repeat true 4 _nCustomColorSD ncolorimage }{ _nCustomColorSD/black get 1 exch sub makeByte8 _nCustomColorSD bwImage }ifelse myRestore }def }{ /knockOut{ gsave false setoverprint 1 setgray 0 0 1 1 rectfill grestore }def }ifelse /newSpotDict{ 11 dict dup begin /nSpots 2 def /spot1 7 dict def /spot2 7 dict def end }def /initSpotData { begin /name nd /tintImage nd /tintValue nd /spot_C nd /spot_M nd /spot_Y nd /spot_K nd end }def /initSpotDict{ begin /cyanInk false def /magentaInk false def /yellowInk false def /blackInk false def /cyan nd /magenta nd /yellow nd /black nd spot1 initSpotData spot2 initSpotData end }def /copySpotDict{ /_dst xp begin cyanInk magentaInk yellowInk blackInk cyan magenta yellow black spot1 spot2 end _dst begin /spot1 spot1 maxlength dict def /spot2 spot2 maxlength dict def spot2 copy pop spot1 copy pop /black xd /yellow xd /magenta xd /cyan xd /blackInk xd /yellowInk xd /magentaInk xd /cyanInk xd end }def /setCustomColor { 1 index /Black eq{ 6 1 roll 5 npop 1 exch sub setgray }{ 6 1 roll _ccAry1 astore exch dup null eq{ pop 0 }if setcustomcolor }ifelse }def /setCStop{ /_colorStyle exch pt _colorStyle 0 eq{ 0 0 0 4 -1 roll 1 exch sub _spotColor{ /_colorStyle 3 pt /Black 1 index 1 exch sub }if }if _colorStyle 2 eq{ 3 npop }if _rampSD _fillSD copySpotDict _colorStyle 4 eq{ pop 9 2 roll 3 npop 6 -2 roll } if _colorStyle 3 eq _colorStyle 4 eq or{ _fillSD begin exch dup spot1/name get eq{ spot1 spot2 }{ spot2 spot1 }ifelse begin begin /name xd 1 exch sub /tintValue xd 4{ tintValue mul 4 1 roll }repeat _spotColor not{ /tintValue null def }if end /tintValue 0 def end end }if _fillSD nsetcustomcolor }def /renderCMYK{ spot1/name get null eq spot2/name get null eq and dup not{ pop spot1 spotConverted }if dup not{ pop spot2 spotConverted }if }def /fill_ /fill load def /fillOvp{ currentoverprint{ _inRipSep{ currentcolorspace 0 get dup /DeviceGray eq 1 index /DeviceCMYK eq or{ pop currentcmykcolor add add add 0 eq{ newpath }if }{ /Separation eq{ currentcolor 0 eq{ newpath }if }if }ifelse }{ currentgray 1 eq{ newpath }if }ifelse }if fill_ }def /fill{ _nCustomColorSD begin renderCMYK { fillOvp }{ spot1 begin gsave name null ne{ spot_C spot_M spot_Y spot_K name tintValue setCustomColor }{ 1 setgray }ifelse fillOvp grestore end spot2 begin name null ne{ gsave true setoverprint spot_C spot_M spot_Y spot_K name tintValue setCustomColor fillOvp grestore }if end newpath }ifelse end }def /expandSpot{ _spotColor{ /_len xp _rampSD begin spot1 begin tintImage null ne{ tintImage _len expandOne /tintImage xd }if end spot2 begin tintImage null ne{ tintImage _len expandOne /tintImage xd }if end end }{ pop }ifelse }def /rampImage{ _rampSD begin _color{ /cyanInk _cyanData 0 ne def /magentaInk _magentaData 0 ne def /yellowInk _yellowData 0 ne def /blackInk _blackData 0 ne def _nSamples setImageParms _nSamples expandSpot _cyanData _magentaData _yellowData _blackData _nSamples 4 expandColor true 4 _rampSD ncolorimage }{ /cyanInk false def /magentaInk false def /yellowInk false def /blackInk true def _nSamples setImageParms _blackData _rampSD bwImage }ifelse end }def /nsetcustomcolor where{ pop }{ /nsetcustomcolor { /_nCustomColorSD xp _nCustomColorSD begin 4 copy /black xd /yellow xd /magenta xd /cyan xd 4 copy 0 ne /blackInk xd 0 ne /yellowInk xd 0 ne /magentaInk xd 0 ne /cyanInk xd end setcmykcolor }def }ifelse /nsetcustomcolorend where{ pop }{ /nsetcustomcolorend { /_nCustomColorSD null pt }def }ifelse }def /initializeSinglePassSeps{ /_decodeNorm [0 1] pt /_decodeInvert [1 0] pt /spotConverted { begin name null eq{ false }{ tintValue null eq tintImage null eq and{ true }{ false currentpagedevice/SeparationOrder get{name eq or}forall not }ifelse }ifelse end }def /dictImage { 20 dict dup begin /Dict xd /Decode xd /DataSource xd /ImageMatrix xd /BitsPerComponent xd /Height xd /Width xd /ImageType 1 def Dict end /_image load 1 execImage }def /bwImage{ begin gsave currentoverprint{ blackInk{ [/Separation /Black /DeviceGray{}] setcolorspace _decodeInvert dictImage }{ 5 npop }ifelse }{ /DeviceGray setcolorspace _decodeNorm dictImage }ifelse grestore end }def /ncolorimage where{ pop }{ /ncolorimage{ begin renderCMYK { cyanInk magentaInk and yellowInk and blackInk and not currentoverprint and { pop pop gsave cyanInk{ 8 copy [/Separation /Cyan /DeviceGray{}] setcolorspace 3 npop _decodeNorm dictImage }if magentaInk{ 8 copy [/Separation /Magenta /DeviceGray{}] setcolorspace 4 -1 roll 3 npop _decodeNorm dictImage }if yellowInk{ 8 copy [/Separation /Yellow /DeviceGray{}] setcolorspace 4 -2 roll 3 npop _decodeNorm dictImage }if blackInk{ 4 -3 roll [/Separation /Black /DeviceGray{}] setcolorspace 3 npop _decodeNorm dictImage }{ 8 npop }ifelse grestore }{ /_colorimage load 10 execImage }ifelse }{ 6 npop gsave spot1 begin name null ne tintImage null ne and{ [/Separation name /DeviceGray{}] setcolorspace 4 copy tintImage name /Black eq{ _decodeNorm }{ _decodeInvert }ifelse dictImage }{ 1 setgray fill }ifelse end spot2 begin true setoverprint name null ne tintImage null ne and{ [/Separation name /DeviceGray{}] setcolorspace tintImage name /Black eq{ _decodeNorm }{ _decodeInvert }ifelse dictImage }{ 4 npop 1 setgray fill }ifelse end grestore }ifelse end }def }ifelse }def /initializeMultiPassSeps{ /_isCMYKSep _cyanPlate _magentaPlate or _yellowPlate or _blackPlate or pt /invertXfer{ [ { 1 exch sub }/exec load systemdict /currenttransfer get exec /exec load ] cvx systemdict /settransfer get exec }def /ccThrough{ gsave 1 setCustomColor currentcmykcolor grestore add add add 0 ne }def /spotConverted { begin _isCMYKSep not{ false }{ name null eq{ false }{ tintValue null eq tintImage null eq and{ true }{ spot_C spot_M spot_Y spot_K name ccThrough }ifelse }ifelse }ifelse end }def /spotChannel { _isCMYKSep{ pop false }{ begin name null eq{ false }{ spot_C spot_M spot_Y spot_K name ccThrough }ifelse end }ifelse }def /getChannelData { _isCMYKSep dup{ pop renderCMYK }if { _blackPlate{ 4 1 roll 3 npop blackInk }{ _yellowPlate{ 4 2 roll 3 npop yellowInk }{ _magentaPlate{ 4 3 roll 3 npop magentaInk }{ 3 npop cyanInk }ifelse }ifelse }ifelse { true /nonZeroData }{ true /zeroData }ifelse }{ 4 npop spot1/name get null ne spot1 spotChannel and{ spot1/tintImage get dup null ne{ false /nonZeroData }{ pop false /noData }ifelse }{ spot2/name get null ne spot2 spotChannel and{ spot2/tintImage get dup null ne{ false /nonZeroData }{ pop false /noData }ifelse }{ false /noData }ifelse }ifelse }ifelse }def /renderChannelData { /_tmp xp _tmp /nonZeroData ne currentoverprint and{ pop _tmp /zeroData eq{pop}if 4 npop }{ _tmp /nonZeroData eq{ { invertXfer }if systemdict/image get 5 execImage }{ pop _tmp /zeroData eq{pop}if 4 npop knockOut }ifelse }ifelse }def /bwImage{ begin gsave dup dup dup getChannelData exch pop false exch renderChannelData grestore end }def /ncolorimage{ begin pop pop gsave spot2/name get null ne spot2 spotChannel and{ true setoverprint }if getChannelData renderChannelData grestore end }def }def end end defaultpacking setpacking %%EndResource %%BeginResource: procset AGM_Gradient 1.0 0 %%Title: (AGM Gradient Procset) %%Version: 1.0 0 %%CreationDate: (4/26/96) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /AGM_Gradient 20 dict dup begin put /AGM_Gradient_private 200 dict def /initialize { AGM_Gradient begin AGM_Gradient_private begin initializeVars /bd systemdict/mark get def /ed _level2PS { (>>) }{ (counttomark 2 idiv dup dict begin {def} repeat pop currentdict end) } ifelse cvx def _level2PS{ initializeLev2 }{ initializeLev1 }ifelse queryDevice initializeShading initializeOps _producingSeps{ AGM_Gradient_Sep/initialize get exec }{ initializeComposite }ifelse _illustrator{ /f{}def /F{}def /s{}def /S{}def /b{}def /B{}def }if /image where{ /image get /_image xd }if /colorimage where{ /colorimage get /_colorimage xd }if /rectfill where dup{ exch pop not _producingSeps or }{ not }ifelse { /rectfill{ gsave newpath 4 2 roll moveto 1 index 0 rlineto 0 1 index rlineto 1 index neg 0 rlineto pop pop closepath fill grestore }def }if /linealImage _noImage{ /rectImage load }{ _producingSeps{ AGM_Gradient_Sep/AGM_Gradient_Sep_private get begin /rampImage load end }{ /rampImage load }ifelse }ifelse def AGM_Gradient_private { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall AGM_Gradient { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall end currentdict readonly pop end }def /initializeAI { pop pop AGM_Gradient/AGM_Gradient_private get /_illustrator true put AGM_Gradient/initialize get exec AGM_Gradient begin }def /unload{ systemdict/languagelevel known{ systemdict/languagelevel get 2 ge{ userdict/AGM_Gradient_Sep 2 copy known{ undef }{ pop pop }ifelse userdict/AGM_Gradient 2 copy known{ undef }{ pop pop }ifelse }if }if }def /terminate{ currentdict AGM_Gradient eq{ end }if }def AGM_Gradient_private begin /initializeVars{ /_d255 256 array def 0 1 255{ _d255 exch dup 255 div put }bind for /_d255- 256 array def 0 1 255{ _d255- exch 1 _d255 2 index get sub put }bind for /_sSave nd /_dUserSpace matrix defaultmatrix def /_bUMatrix matrix def /_imageMatrix matrix def /_saveMatrix matrix def /_xm matrix def /_ccAry1 5 array def /_level2PS systemdict/languagelevel known dup{ pop systemdict/languagelevel get 2 ge }if def /_level3PS _level2PS systemdict/shfill known and def currentdict /_illustrator known not{ /_illustrator false def }if }def /initializeOps { AGM_Gradient begin currentdict/Bc known not{ /Bc{ _renderFlag 2 eq{ 6 npop }{ pushBSpace _rampIndex 0 eq{ pop pop setCStop }if linealFill popBSpace }ifelse }def }if currentdict/Bg known not{ /Bg{ 10 npop /_gradName xp /_renderFlag xp _renderFlag 2 ne{ _illustrator{ _of setoverprint }if _illustrator _eo and _renderFlag 3 eq or{ eoclip }{ clip }ifelse _gradNames _gradName 2 copy known{ get mark exch aload pop /_gradType xp 1 sub dup /_rampIndex xp /_maxRampIndex xp mark exch aload pop 0 0 }if pop pop getRampData }{ mark mark }ifelse }def }if currentdict/Bm known not{ /Bm{ _renderFlag 2 ne{ _gradType 0 eq{ linealRamp }{ radialGrad }ifelse }{ 6 npop }ifelse }def }if currentdict/Bh known not{ /Bh{ 2 npop /_yHi xp /_xHi xp /_radHilite _xHi 0 ne _yHi 0 ne or pt }def }if currentdict/Bn known not{ /Bn{ AGM_Gradient_private begin dict /_gradNames xp end }def }if currentdict/Bd known not{ /Bd{ AGM_Gradient begin AGM_Gradient_private begin /_nColorsBd xp /_gradType xp /_gradName xp }def }if currentdict/BD known not{ /BD{ currentdict/_gradNames known not{ /_gradNames 20 dict def }if ] _nColorsBd _gradType ] _gradName exch /_gradNames xput end end }def }if currentdict/Bb known not{ /Bb{ AGM_Gradient begin AGM_Gradient_private begin _producingSeps{ AGM_Gradient_Sep/AGM_Gradient_Sep_private get begin }if mySave }def }if currentdict/BB known not{ /BB{ /_tmp xp cleartomark cleartomark _tmp dup _renderFlag myRestore _producingSeps{ end }if _illustrator end end { 2 ne exch 0 gt and{ 2 eq{ s }{ S }ifelse }{ pop newpath }ifelse }{ pop newpath }ifelse }def }if currentdict/Xm known not{ /Xm{ _xm astore pop }def }if end }def /queryDevice{ /_inRipSep _level2PS{ currentpagedevice/Separations 2 copy known{ get }{ pop pop false }ifelse }{ false }ifelse def /_noImage /lv1Fix where{ pop lv1Fix }{ false }ifelse def /_useShells where{ pop }{ /_useShells true def }ifelse /_useSmoothShade where{ pop }{ /_useSmoothShade false def }ifelse /_cyanPlate 1 0 0 0 testCMYKColorThrough def /_magentaPlate 0 1 0 0 testCMYKColorThrough def /_yellowPlate 0 0 1 0 testCMYKColorThrough def /_blackPlate 0 0 0 1 testCMYKColorThrough def /_compositeJob _cyanPlate _magentaPlate and _yellowPlate and _blackPlate and def /_compositeSpotDevice where{ pop }{ /_compositeSpotDevice _compositeJob not _inRipSep or{ 1 }{ 0 }ifelse def }ifelse /_producingSeps _compositeSpotDevice 0 ne def /_deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt def /_dpiThreshold where{ pop }{ /_dpiThreshold 600 def }ifelse /_screenFreqThreshold where{ pop }{ /_screenFreqThreshold 150 def }ifelse /_contoneDevice where{ pop }{ /_contoneDevice false def }ifelse /_subSampleOK _deviceDPI _dpiThreshold le currentScreenFreq _screenFreqThreshold le and _contoneDevice not and _producingSeps not and def }def /initializeLev1{ /makeByte8{ /_tmp 0 pt 255 mul cvi 8 string 8{ dup _tmp 3 index put /_tmp _tmp 1 add pt }repeat exch pop }def /currentScreenFreq{ currentscreen pop pop }def /_byte 1 string def /colorimage where{ pop }{ /colorimage{ pop pop /_blackTmp xp /_yellowTmp xp /_magentaTmp xp /_cyanTmp xp /_cnt 0 pt [ _byte dup 0 _cyanTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .3 /mul cvx _magentaTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .59 /mul cvx _yellowTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .11 /mul cvx _blackTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx /add cvx /add cvx /add cvx 1 /exch cvx /sub cvx /dup cvx 0 /lt cvx{ pop 0 }/if cvx /dup cvx 1 /gt cvx{ pop 1 }/if cvx 255 /mul cvx /cvi cvx 256 /mod cvx /dup cvx 0 /lt cvx{ pop 0 }/if cvx /put cvx /_cnt dup cvx 1 /add cvx /pt cvx ] cvx bind /_image load 5 execImage }def }ifelse }def /initializeLev2{ /level2ScreenFreq{ begin 60 HalftoneType 1 eq{ pop Frequency }if HalftoneType 2 eq{ pop GrayFrequency }if HalftoneType 5 eq{ pop Default level2ScreenFreq }if end }def /currentScreenFreq{ currenthalftone level2ScreenFreq }def }def /initializeShading{ _useSmoothShade _level3PS and{ /_usingSmoothShade true pt initializeLev3_Ops }{ /_usingSmoothShade false pt }ifelse }def /initializeLev3_Ops { /initShFill{ /_index _gradType 0 eq {0}{_maxRampIndex 1 sub} ifelse pt /_rampFuncsArray _maxRampIndex array pt /_boundsArray _maxRampIndex 1 sub array pt /_encodeArray _maxRampIndex 2 mul array pt /_beginCoord _rampPoint pt /_colorSpace null pt /_firstFill _rampIndex _maxRampIndex eq pt /_lastFill false pt }def /getRampColorSpace{ _nSamples 1 gt{ /_ndx 0 pt [blendColor] cvx exec }if /_C0 [currentcolor] pt /_C0_Space currentcolorspace pt _nSamples 1 gt{ /_ndx _nSamples 1 sub pt [blendColor] cvx exec }if /_C1 [currentcolor] pt /_C1_Space currentcolorspace pt _C0_Space _C1_Space eq{ /_rampColorSpace _C0_Space pt }{ (colorspace conflict!) == showpage stop }ifelse _spotColor{ nsetcustomcolorend }if }def /linealShFill{ popBSpace _xm aload pop pushBSpace /_size _index 1 add pt _size _maxRampIndex lt { /_rampFuncsArray _rampFuncsArray 0 _size getinterval pt /_boundsArray _boundsArray 0 _size 1 sub getinterval pt /_encodeArray _encodeArray 0 _size 2 mul getinterval pt }if bd /ShadingType 2 /ColorSpace _colorSpace /Function bd /FunctionType 3 /Domain [0 1] /Functions _rampFuncsArray /Bounds _boundsArray /Encode _encodeArray ed /Extend [_firstFill _lastFill] /Domain [0 1] /Coords [_beginCoord 0 _endCoord 0] ed shfill }def /radialShFill{ /_size _maxRampIndex _index sub pt _size _maxRampIndex lt { /_rampFuncsArray _rampFuncsArray _index _size getinterval pt /_boundsArray _boundsArray _index _size 1 sub getinterval pt /_encodeArray _encodeArray _index 2 mul _size 2 mul getinterval pt }if /_rampLen _beginCoord _endCoord sub pt bd /ShadingType 3 /ColorSpace _colorSpace /Function bd /FunctionType 3 /Domain [0 1] /Functions _rampFuncsArray /Bounds _boundsArray /Encode _encodeArray ed /Extend [_lastFill _firstFill] /Domain [0 1] /Coords [_xHi _rampLen mul _yHi _rampLen mul _endCoord 0 0 _beginCoord] ed shfill _radHilite{ _xHi _rampLen mul _yHi _rampLen mul translate }if }def /fillRamp{ /_invert _midPoint 0.5 lt pt _rampIndex _maxRampIndex eq { initShFill }if getRampColorSpace _colorSpace null eq{ /_colorSpace _rampColorSpace pt }{ _colorSpace _rampColorSpace ne{ /_index _index 1 _gradType 0 eq{ sub pt linealShFill }{ add pt radialShFill }ifelse initShFill /_colorSpace _rampColorSpace pt } if }ifelse /_endCoord _endPoint pt _rampFuncsArray _index bd /FunctionType 2 /Domain [0 1] /N 0.5 log _invert{1 _midPoint sub}{_midPoint}ifelse log div _gradType 0 eq{ _invert{/C1}{/C0}ifelse _C0 _invert{/C0}{/C1}ifelse _C1 }{ _invert{/C0}{/C1}ifelse _C1 _invert{/C1}{/C0}ifelse _C0 }ifelse ed put _rampIndex 1 ne{ _boundsArray _index _gradType 1 eq{1 sub}if _endCoord put } if 0 1 _invert {exch}if _encodeArray _index 2 mul 1 add 3 -1 roll put _encodeArray _index 2 mul 3 -1 roll put _rampIndex 1 eq { /_lastFill true pt _gradType 0 eq{ linealShFill }{ radialShFill }ifelse }if /_index _index 1 _gradType 0 eq{ add pt }{ sub pt }ifelse }def /radialRamp /fillRamp load def /rampImage /fillRamp load def AGM_Gradient begin /Bc{ 6 npop }def end }def /initializeComposite{ /bwImage{ pop /_image load 5 execImage }def currentdict/rampImage known not{ /rampImage{ _color{ _nSamples setImageParms _rgbRamp{ _redData _greenData _blueData _nSamples 3 expandColor true 3 null ncolorimage }{ _cyanData _magentaData _yellowData _blackData _nSamples 4 expandColor true 4 null ncolorimage }ifelse }{ _nSamples setImageParms _blackData null bwImage }ifelse }def }if /setCStop{ /_colorStyle exch pt _colorStyle 0 eq{ 1 exch sub 0 0 0 4 -1 roll }if _colorStyle 2 eq{ setrgbcolor 4 npop }if _colorStyle 3 eq{ 1 exch sub /_tmp xp pop 4{ _tmp mul 4 1 roll }repeat }if _colorStyle 4 eq{ 3 -1 roll pop pop 1 exch sub /_tmp xp 3{ 1 exch sub _tmp mul 1 exch sub 3 1 roll }repeat setrgbcolor 4 npop }if _colorStyle 2 ne _colorStyle 4 ne and{ null nsetcustomcolor }if }def /nsetcustomcolor { pop setcmykcolor }def /nsetcustomcolorend { }def /ncolorimage{ pop /_colorimage load 10 execImage }def _noImage not _level2PS not and{ /linealFill{ 8 setImageParms _color{ currentcmykcolor 4{ makeByte8 4 1 roll }repeat true 4 null ncolorimage }{ currentgray makeByte8 null bwImage }ifelse }def }if }def /npop{ {pop}repeat }def /xd{ exch def }def /nd{ null def }def /pt{ AGM_Gradient_private 3 1 roll put }def /xp{ exch pt }def /xput{ dup load dup length exch maxlength eq{ dup dup load dup length 2 mul dict copy def }if load begin def end }def /mySave{ save /_sSave xp }def /myRestore{ _sSave type /savetype eq{ _sSave restore }if }def /gMark{ counttomark 2 add -1 roll }def /execImage{ /_tmp xp { exec }stopped{ $error /errorname get /undefinedresult ne{ stop }{ _tmp npop }ifelse }if }def /pushBSpace{ newpath gsave _bUMatrix astore concat }def /popBSpace{ grestore }def /setImageParms{ 1 8 2 index 0 0 1 0 0 _imageMatrix astore }def /linealFill{ 0 0 1 1 rectfill }def /testCMYKColorThrough{ gsave setcmykcolor currentcmykcolor grestore add add add 0 ne }def /expandOne { /_tmp xp dup type /stringtype ne{ _tmp string exch dup 0 ne{ 255 mul cvi 0 1 _tmp 1 sub{ 3 copy exch put pop }for }if pop }if }def /expandColor{ /_channels xp /_len xp _channels{ _len expandOne _channels 1 roll }repeat }def /blendColor{ _color{ _rgbRamp _producingSeps not and{ _redData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _greenData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _blueData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if /setrgbcolor cvx }{ _cyanData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _magentaData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _yellowData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _blackData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _spotColor{ _rampSD begin /_rampSD cvx /begin cvx spot1 begin tintImage dup type /stringtype eq{ /_ndx cvx /get cvx _d255- /exch cvx /get cvx }{ dup null ne{ name type /nametype ne{ 1 exch sub }if }if }ifelse end /spot1 cvx /tintValue 3 -1 /roll cvx /put cvx spot2 begin tintImage dup type /stringtype eq{ /_ndx cvx /get cvx _d255- /exch cvx /get cvx }{ dup null ne{ name type /nametype ne{ 1 exch sub }if }if }ifelse end /spot2 cvx /tintValue 3 -1 /roll cvx /put cvx /end cvx end /_rampSD cvx /nsetcustomcolor cvx }{ /setcmykcolor cvx }ifelse }ifelse }{ _blackData /_ndx cvx /get cvx _d255 /exch cvx /get cvx _usingSmoothShade{ 1 /exch cvx /sub cvx 0 0 0 4 -1 /roll cvx /setcmykcolor cvx }{ /setgray cvx }ifelse }ifelse }def /linealRamp{ pushBSpace _ramp{ linealImage }{ linealFill }ifelse popBSpace /_rampIndex _rampIndex 1 sub pt _rampIndex 0 gt{ getRampData }if }def /radialGrad{ /_firstShell true pt _usingSmoothShade not{ fill }if pushBSpace _radHilite{ _xHi _yHi _bUMatrix idtransform /_yHi xp /_xHi xp _rampPoint 1 lt{ 1 _rampPoint sub dup _xHi mul exch _yHi mul translate }if }if _rampIndex{ radialRamp /_rampIndex _rampIndex 1 sub pt _rampIndex 0 gt{ getRampData }if }repeat popBSpace }def /getNSamples{ 0 exch { dup type /stringtype eq{ length exch pop exit }if pop }forall dup 0 eq{ pop 1 }if }def /getRampData{ /_rampType gMark pt /_color _rampType 0 gt pt /_ccRGB _rampType 5 eq _rampType 6 eq or pt /_rgbRamp _rampType 4 eq _ccRGB or pt /_ccProcess _rampType 2 eq _rampType 3 eq or pt _producingSeps{ _rampSD initSpotDict /_spotColor _ccProcess _ccRGB or pt }{ /_spotColor false pt }ifelse /_ramp true pt 100 div /_rampPoint xp 100 div /_midPoint xp dup /_colorStyle xp _colorStyle 0 eq{ 2 }{ _colorStyle 1 eq{ 5 }{ _colorStyle 2 eq{ 8 }{ _colorStyle 3 eq{ _producingSeps{ _rampSD begin spot1 begin /name 3 index def /spot_K 4 index def /spot_Y 5 index def /spot_M 6 index def /spot_C 7 index def end end }if 7 }{ _producingSeps{ _rampSD begin spot1 begin /name 4 index def /spot_K 8 index def /spot_Y 9 index def /spot_M 10 index def /spot_C 11 index def end end }if 11 } ifelse }ifelse }ifelse }ifelse /_tmp xp _tmp index 100 div /_endPoint xp _gradType 1 eq{ _tmp 1 add index 100 div /_midPoint xp }if _producingSeps{ _tmp 2 add index /_nextColorStyle xp _nextColorStyle 3 eq{ /_tmp _tmp 4 add pt _tmp index dup _rampSD begin spot1 /name get ne{ spot2 begin /name xd /spot_K _tmp 2 add index def /spot_Y _tmp 3 add index def /spot_M _tmp 4 add index def /spot_C _tmp 5 add index def end }{ pop }ifelse end }if _nextColorStyle 4 eq{ /_tmp _tmp 5 add pt _tmp index dup _rampSD begin spot1 /name get ne{ spot2 begin /name xd /spot_K _tmp 5 add index def /spot_Y _tmp 6 add index def /spot_M _tmp 7 add index def /spot_C _tmp 8 add index def end }{ pop }ifelse end }if }if _rampType 3 eq _rampType 6 eq or{ /_tint2Data gMark pt }if _ccProcess _ccRGB or{ /_tint1Data gMark pt }if _rgbRamp{ /_blueData gMark pt /_greenData gMark pt /_redData gMark pt }if _producingSeps{ _rampSD begin _ccProcess _ccRGB or{ _rampType 3 eq _rampType 6 eq or{ spot2 begin /tintImage _gradType 0 eq{ _tint2Data }{ _tint1Data }ifelse def name null eq{ /name /Black def }if end }if spot1 begin /tintImage _gradType 0 eq _rampType 2 eq or _rampType 5 eq or{ _tint1Data }{ _tint2Data }ifelse def _rampType 2 eq _rampType 5 eq or{ name null eq{ /name spot2 /name get def spot2 /name null put }if }{ name null eq{ /name /Black def }if }ifelse end }if end }if /_blackData gMark pt _rampType 0 gt{ counttomark 4 add -3 roll /_yellowData xp /_magentaData xp /_cyanData xp }if _ramp{ /_nSamples [ _rampType 0 eq {_blackData}if _rampType 1 eq {_cyanData _magentaData _yellowData _blackData}if _rampType 2 eq {_cyanData _magentaData _yellowData _blackData _tint1Data}if _rampType 3 eq {_cyanData _magentaData _yellowData _blackData _tint1Data _tint2Data}if _rampType 4 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData}if _rampType 5 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData _tint1Data}if _rampType 6 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData _tint1Data _tint2Data}if ] getNSamples pt _usingSmoothShade not {/_ramp _nSamples 1 gt pt} if } if setCStop }def /rectImage{ gsave /_sInc 1 pt /_bInc 1 _nSamples div pt /_uRampLen 1 0 dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt pt /_pChange _uRampLen 0 eq{0}{_nSamples _uRampLen div}ifelse pt 0 _nSamples [ /dup cvx /_ndx /exch cvx /pt cvx blendColor 0 0 _bInc 1 /rectfill cvx _bInc 0 /translate cvx _sInc /add cvx ] cvx bind repeat pop _spotColor{ nsetcustomcolorend }if grestore }def /radialInit{ /_nRadSamples _nSamples dup 0 eq{pop 1}if pt /_sInc -1 pt /_rampLen _rampPoint _endPoint sub pt /_bInc _rampLen _nSamples div neg pt /_optimize false pt _subSampleOK{ /_uRampLen _rampLen 0 dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt 0 _rampLen dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt 2 copy lt{ exch }if pop pt /_pChange _uRampLen 0 eq{ 0 }{ _nSamples _uRampLen div }ifelse pt _pChange .5 gt dup /_optimize xp{ /_nRadSamples _uRampLen 2 div round cvi dup 1 le{pop 2}if pt /_bInc _rampLen _nRadSamples div neg pt /_sInc _nSamples 1 sub _nRadSamples 1 sub div neg pt }if }if _radHilite{ /_xBCInc _xHi _rampLen mul _nRadSamples div pt /_yBCInc _yHi _rampLen mul _nRadSamples div pt }if }def currentdict/radialRamp known not{ /radialRamp{ /_saveMatrix _saveMatrix currentmatrix def radialInit _rampPoint _nSamples 1 sub _nRadSamples [ /dup cvx _optimize{ /round cvx /cvi cvx }if /_ndx /exch cvx /pt cvx _useShells{ /_firstShell cvx{ /_firstShell false pt }{ 0 0 3 index 360 0 arcn fill }/ifelse cvx }if blendColor _useShells{ 0 0 3 /index cvx 0 360 /arc cvx }{ 0 0 3 /index cvx 0 360 /arc cvx /fill cvx }ifelse /exch cvx _bInc /add cvx /exch cvx _sInc /add cvx _radHilite{ _xBCInc _yBCInc /translate cvx }if ] cvx bind repeat pop pop _saveMatrix setmatrix _radHilite{ _xHi _rampLen mul _yHi _rampLen mul translate }if _useShells _rampIndex 1 eq and{ fill }if _spotColor{ nsetcustomcolorend }if }def }if end end defaultpacking setpacking %%EndResource %%BeginProcSet: Adobe_ColorImage_AI6 1.1 0 userdict /Adobe_ColorImage_AI6 known not { userdict /Adobe_ColorImage_AI6 24 dict put } if userdict /Adobe_ColorImage_AI6 get begin /initialize { Adobe_ColorImage_AI6 begin Adobe_ColorImage_AI6 { dup type /arraytype eq { dup xcheck { bind } if } if pop pop } forall } def /terminate { end } def currentdict /Adobe_ColorImage_AI6_Vars known not { /Adobe_ColorImage_AI6_Vars 15 dict def } if Adobe_ColorImage_AI6_Vars begin /channelcount 0 def /sourcecount 0 def /sourcearray 4 array def /plateindex -1 def /XIMask 0 def /XIBinary 0 def /XIChannelCount 0 def /XIBitsPerPixel 0 def /XIImageHeight 0 def /XIImageWidth 0 def /XIImageMatrix null def /XIBuffer null def /XIDataProc null def /XIVersion 6 def end /WalkRGBString null def /WalkCMYKString null def /StuffRGBIntoGrayString null def /RGBToGrayImageProc null def /StuffCMYKIntoGrayString null def /CMYKToGrayImageProc null def /ColorImageCompositeEmulator null def /SeparateCMYKImageProc null def /FourEqual null def /TestPlateIndex null def currentdict /_colorimage known not { /colorimage where { /colorimage get /_colorimage exch def } { /_colorimage null def } ifelse } if /_currenttransfer systemdict /currenttransfer get def /colorimage null def /XI null def /WalkRGBString { 0 3 index dup length 1 sub 0 3 3 -1 roll { 3 getinterval { } forall 5 index exec 3 index } for 5 { pop } repeat } def /WalkCMYKString { 0 3 index dup length 1 sub 0 4 3 -1 roll { 4 getinterval { } forall 6 index exec 3 index } for 5 { pop } repeat } def /StuffRGBIntoGrayString { .11 mul exch .59 mul add exch .3 mul add cvi 3 copy put pop 1 add } def /RGBToGrayImageProc { Adobe_ColorImage_AI6_Vars begin sourcearray 0 get exec dup length 3 idiv string dup 3 1 roll /StuffRGBIntoGrayString load exch WalkRGBString end } def /StuffCMYKIntoGrayString { exch .11 mul add exch .59 mul add exch .3 mul add dup 255 gt { pop 255 } if 255 exch sub cvi 3 copy put pop 1 add } def /CMYKToGrayImageProc { Adobe_ColorImage_AI6_Vars begin sourcearray 0 get exec dup length 4 idiv string dup 3 1 roll /StuffCMYKIntoGrayString load exch WalkCMYKString end } def /ColorImageCompositeEmulator { pop true eq { Adobe_ColorImage_AI6_Vars /sourcecount get 5 add { pop } repeat } { Adobe_ColorImage_AI6_Vars /channelcount get 1 ne { Adobe_ColorImage_AI6_Vars begin sourcearray 0 3 -1 roll put channelcount 3 eq { /RGBToGrayImageProc } { /CMYKToGrayImageProc } ifelse load end } if image } ifelse } def /SeparateCMYKImageProc { Adobe_ColorImage_AI6_Vars begin sourcecount 0 ne { sourcearray plateindex get exec } { sourcearray 0 get exec dup length 4 idiv string 0 2 index plateindex 4 2 index length 1 sub { get 255 exch sub 3 copy put pop 1 add 2 index } for pop pop exch pop } ifelse end } def /FourEqual { 4 index ne { pop pop pop false } { 4 index ne { pop pop false } { 4 index ne { pop false } { 4 index eq } ifelse } ifelse } ifelse } def /TestPlateIndex { Adobe_ColorImage_AI6_Vars begin /plateindex -1 def /setcmykcolor where { pop gsave 1 0 0 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 1 0 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 0 1 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 0 0 1 setcmykcolor systemdict /currentgray get exec 1 exch sub grestore 1 0 0 0 FourEqual { /plateindex 0 def } { 0 1 0 0 FourEqual { /plateindex 1 def } { 0 0 1 0 FourEqual { /plateindex 2 def } { 0 0 0 1 FourEqual { /plateindex 3 def } { 0 0 0 0 FourEqual { /plateindex 5 def } if } ifelse } ifelse } ifelse } ifelse pop pop pop pop } if plateindex end } def /colorimage { Adobe_ColorImage_AI6_Vars begin /channelcount 1 index def /sourcecount 2 index 1 eq { channelcount 1 sub } { 0 } ifelse def 4 sourcecount add index dup 8 eq exch 1 eq or not end { /_colorimage load null ne { _colorimage } { Adobe_ColorImage_AI6_Vars /sourcecount get 7 add { pop } repeat } ifelse } { dup 3 eq TestPlateIndex dup -1 eq exch 5 eq or or { /_colorimage load null eq { ColorImageCompositeEmulator } { dup 1 eq { pop pop image } { Adobe_ColorImage_AI6_Vars /plateindex get 5 eq { gsave 0 _currenttransfer exec 1 _currenttransfer exec eq { 0 _currenttransfer exec 0.5 lt } { 0 _currenttransfer exec 1 _currenttransfer exec gt } ifelse { { pop 0 } } { { pop 1 } } ifelse systemdict /settransfer get exec } if _colorimage Adobe_ColorImage_AI6_Vars /plateindex get 5 eq { grestore } if } ifelse } ifelse } { dup 1 eq { pop pop image } { pop pop Adobe_ColorImage_AI6_Vars begin sourcecount -1 0 { exch sourcearray 3 1 roll put } for /SeparateCMYKImageProc load end systemdict /image get exec } ifelse } ifelse } ifelse } def /XG { pop pop } def /XF { 13 {pop} repeat } def /Xh { Adobe_ColorImage_AI6_Vars begin gsave /XIMask exch 0 ne def /XIImageHeight exch def /XIImageWidth exch def /XIImageMatrix exch def 0 0 moveto XIImageMatrix concat XIImageWidth XIImageHeight scale XIMask { /_lp /null ddef _fc /_lp /imagemask ddef } if /XIVersion 7 def end } def /XH { Adobe_ColorImage_AI6_Vars begin /XIVersion 6 def grestore end } def /XI { Adobe_ColorImage_AI6_Vars begin gsave /XIMask exch 0 ne def /XIBinary exch 0 ne def pop pop /XIChannelCount exch def /XIBitsPerPixel exch def /XIImageHeight exch def /XIImageWidth exch def pop pop pop pop /XIImageMatrix exch def XIBitsPerPixel 1 eq { XIImageWidth 8 div ceiling cvi } { XIImageWidth XIChannelCount mul } ifelse /XIBuffer exch string def XIBinary { /XIDataProc { currentfile XIBuffer readstring pop } def XIVersion 6 le { currentfile 128 string readline pop pop } if } { /XIDataProc { currentfile XIBuffer readhexstring pop } def } ifelse XIVersion 6 le { 0 0 moveto XIImageMatrix concat XIImageWidth XIImageHeight scale XIMask { /_lp /null ddef _fc /_lp /imagemask ddef } if } if XIMask { XIImageWidth XIImageHeight false [ XIImageWidth 0 0 XIImageHeight neg 0 0 ] /XIDataProc load imagemask } { XIImageWidth XIImageHeight XIBitsPerPixel [ XIImageWidth 0 0 XIImageHeight neg 0 0 ] /XIDataProc load XIChannelCount 1 eq { gsave 0 setgray image grestore } { false XIChannelCount colorimage } ifelse } ifelse grestore end } def end %%EndProcSet %%BeginResource: procset Adobe_Illustrator_AI5 1.1 0 %%Title: (Adobe Illustrator (R) Version 5.0 Full Prolog) %%Version: 1.1 0 %%CreationDate: (3/7/1994) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_Illustrator_AI5_vars 81 dict dup begin put /_eo false def /_lp /none def /_pf { } def /_ps { } def /_psf { } def /_pss { } def /_pjsf { } def /_pjss { } def /_pola 0 def /_doClip 0 def /cf currentflat def /_tm matrix def /_renderStart [ /e0 /r0 /a0 /o0 /e1 /r1 /a1 /i0 ] def /_renderEnd [ null null null null /i1 /i1 /i1 /i1 ] def /_render -1 def /_rise 0 def /_ax 0 def /_ay 0 def /_cx 0 def /_cy 0 def /_leading [ 0 0 ] def /_ctm matrix def /_mtx matrix def /_sp 16#020 def /_hyphen (-) def /_fScl 0 def /_cnt 0 def /_hs 1 def /_nativeEncoding 0 def /_useNativeEncoding 0 def /_tempEncode 0 def /_pntr 0 def /_tDict 2 dict def /_wv 0 def /Tx { } def /Tj { } def /CRender { } def /_AI3_savepage { } def /_gf null def /_cf 4 array def /_if null def /_of false def /_fc { } def /_gs null def /_cs 4 array def /_is null def /_os false def /_sc { } def /_pd 1 dict def /_ed 15 dict def /_pm matrix def /_fm null def /_fd null def /_fdd null def /_sm null def /_sd null def /_sdd null def /_i null def /discardSave null def /buffer 256 string def /beginString null def /endString null def /endStringLength null def /layerCnt 1 def /layerCount 1 def /perCent (%) 0 get def /perCentSeen? false def /newBuff null def /newBuffButFirst null def /newBuffLast null def /clipForward? false def end userdict /Adobe_Illustrator_AI5 known not { userdict /Adobe_Illustrator_AI5 91 dict put } if userdict /Adobe_Illustrator_AI5 get begin /initialize { Adobe_Illustrator_AI5 dup begin Adobe_Illustrator_AI5_vars begin discardDict { bind pop pop } forall dup /nc get begin { dup xcheck 1 index type /operatortype ne and { bind } if pop pop } forall end newpath } def /terminate { end end } def /_ null def /ddef { Adobe_Illustrator_AI5_vars 3 1 roll put } def /xput { dup load dup length exch maxlength eq { dup dup load dup length 2 mul dict copy def } if load begin def end } def /npop { { pop } repeat } def /sw { dup length exch stringwidth exch 5 -1 roll 3 index mul add 4 1 roll 3 1 roll mul add } def /swj { dup 4 1 roll dup length exch stringwidth exch 5 -1 roll 3 index mul add 4 1 roll 3 1 roll mul add 6 2 roll /_cnt 0 ddef { 1 index eq { /_cnt _cnt 1 add ddef } if } forall pop exch _cnt mul exch _cnt mul 2 index add 4 1 roll 2 index add 4 1 roll pop pop } def /ss { 4 1 roll { 2 npop (0) exch 2 copy 0 exch put pop gsave false charpath currentpoint 4 index setmatrix stroke grestore moveto 2 copy rmoveto } exch cshow 3 npop } def /jss { 4 1 roll { 2 npop (0) exch 2 copy 0 exch put gsave _sp eq { exch 6 index 6 index 6 index 5 -1 roll widthshow currentpoint } { false charpath currentpoint 4 index setmatrix stroke } ifelse grestore moveto 2 copy rmoveto } exch cshow 6 npop } def /sp { { 2 npop (0) exch 2 copy 0 exch put pop false charpath 2 copy rmoveto } exch cshow 2 npop } def /jsp { { 2 npop (0) exch 2 copy 0 exch put _sp eq { exch 5 index 5 index 5 index 5 -1 roll widthshow } { false charpath } ifelse 2 copy rmoveto } exch cshow 5 npop } def /pl { transform 0.25 sub round 0.25 add exch 0.25 sub round 0.25 add exch itransform } def /setstrokeadjust where { pop true setstrokeadjust /c { curveto } def /C /c load def /v { currentpoint 6 2 roll curveto } def /V /v load def /y { 2 copy curveto } def /Y /y load def /l { lineto } def /L /l load def /m { moveto } def } { /c { pl curveto } def /C /c load def /v { currentpoint 6 2 roll pl curveto } def /V /v load def /y { pl 2 copy curveto } def /Y /y load def /l { pl lineto } def /L /l load def /m { pl moveto } def } ifelse /d { setdash } def /cf { } def /i { dup 0 eq { pop cf } if setflat } def /j { setlinejoin } def /J { setlinecap } def /M { setmiterlimit } def /w { setlinewidth } def /XR { 0 ne /_eo exch ddef } def /H { } def /h { closepath } def /N { _pola 0 eq { _doClip 1 eq { _eo {eoclip} {clip} ifelse /_doClip 0 ddef } if newpath } { /CRender { N } ddef } ifelse } def /n { N } def /F { _pola 0 eq { _doClip 1 eq { gsave _pf grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _fc /_doClip 0 ddef } { _pf } ifelse } { /CRender { F } ddef } ifelse } def /f { closepath F } def /S { _pola 0 eq { _doClip 1 eq { gsave _ps grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _sc /_doClip 0 ddef } { _ps } ifelse } { /CRender { S } ddef } ifelse } def /s { closepath S } def /B { _pola 0 eq { _doClip 1 eq gsave F grestore { gsave S grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _sc /_doClip 0 ddef } { S } ifelse } { /CRender { B } ddef } ifelse } def /b { closepath B } def /W { /_doClip 1 ddef } def /* { count 0 ne { dup type /stringtype eq { pop } if } if newpath } def /u { } def /U { } def /q { _pola 0 eq { gsave } if } def /Q { _pola 0 eq { grestore } if } def /*u { _pola 1 add /_pola exch ddef } def /*U { _pola 1 sub /_pola exch ddef _pola 0 eq { CRender } if } def /D { pop } def /*w { } def /*W { } def /` { /_i save ddef clipForward? { nulldevice } if 6 1 roll 4 npop concat pop userdict begin /showpage { } def 0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit [] 0 setdash /setstrokeadjust where {pop false setstrokeadjust} if newpath 0 setgray false setoverprint } def /~ { end _i restore } def /O { 0 ne /_of exch ddef /_lp /none ddef } def /R { 0 ne /_os exch ddef /_lp /none ddef } def /g { /_gf exch ddef /_fc { _lp /fill ne { _of setoverprint _gf setgray /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /G { /_gs exch ddef /_sc { _lp /stroke ne { _os setoverprint _gs setgray /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /k { _cf astore pop /_fc { _lp /fill ne { _of setoverprint _cf aload pop setcmykcolor /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /K { _cs astore pop /_sc { _lp /stroke ne { _os setoverprint _cs aload pop setcmykcolor /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /x { /_gf exch ddef findcmykcustomcolor /_if exch ddef /_fc { _lp /fill ne { _of setoverprint _if _gf 1 exch sub setcustomcolor /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /X { /_gs exch ddef findcmykcustomcolor /_is exch ddef /_sc { _lp /stroke ne { _os setoverprint _is _gs 1 exch sub setcustomcolor /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /A { pop } def /annotatepage { userdict /annotatepage 2 copy known {get exec} {pop pop} ifelse } def /XT { pop pop } def /discard { save /discardSave exch store discardDict begin /endString exch store gt38? { 2 add } if load stopped pop end discardSave restore } bind def userdict /discardDict 7 dict dup begin put /pre38Initialize { /endStringLength endString length store /newBuff buffer 0 endStringLength getinterval store /newBuffButFirst newBuff 1 endStringLength 1 sub getinterval store /newBuffLast newBuff endStringLength 1 sub 1 getinterval store } def /shiftBuffer { newBuff 0 newBuffButFirst putinterval newBuffLast 0 currentfile read not { stop } if put } def 0 { pre38Initialize mark currentfile newBuff readstring exch pop { { newBuff endString eq { cleartomark stop } if shiftBuffer } loop } { stop } ifelse } def 1 { pre38Initialize /beginString exch store mark currentfile newBuff readstring exch pop { { newBuff beginString eq { /layerCount dup load 1 add store } { newBuff endString eq { /layerCount dup load 1 sub store layerCount 0 eq { cleartomark stop } if } if } ifelse shiftBuffer } loop } if } def 2 { mark { currentfile buffer readline not { stop } if endString eq { cleartomark stop } if } loop } def 3 { /beginString exch store /layerCnt 1 store mark { currentfile buffer readline not { stop } if dup beginString eq { pop /layerCnt dup load 1 add store } { endString eq { layerCnt 1 eq { cleartomark stop } { /layerCnt dup load 1 sub store } ifelse } if } ifelse } loop } def end userdict /clipRenderOff 15 dict dup begin put { /n /N /s /S /f /F /b /B } { { _doClip 1 eq { /_doClip 0 ddef _eo {eoclip} {clip} ifelse } if newpath } def } forall /Tr /pop load def /Bb {} def /BB /pop load def /Bg {12 npop} def /Bm {6 npop} def /Bc /Bm load def /Bh {4 npop} def end /Lb { 4 npop 6 1 roll pop 4 1 roll pop pop pop 0 eq { 0 eq { (%AI5_BeginLayer) 1 (%AI5_EndLayer--) discard } { /clipForward? true def /Tx /pop load def /Tj /pop load def currentdict end clipRenderOff begin begin } ifelse } { 0 eq { save /discardSave exch store } if } ifelse } bind def /LB { discardSave dup null ne { restore } { pop clipForward? { currentdict end end begin /clipForward? false ddef } if } ifelse } bind def /Pb { pop pop 0 (%AI5_EndPalette) discard } bind def /Np { 0 (%AI5_End_NonPrinting--) discard } bind def /Ln /pop load def /Ap /pop load def /Ar { 72 exch div 0 dtransform dup mul exch dup mul add sqrt dup 1 lt { pop 1 } if setflat } def /Mb { q } def /Md { } def /MB { Q } def /nc 3 dict def nc begin /setgray { pop } bind def /setcmykcolor { 4 npop } bind def /setcustomcolor { 2 npop } bind def currentdict readonly pop end end setpacking %%EndResource %%BeginResource: procset Adobe_blend_AI5 1.4 0 %%Title: (Adobe Illustrator (R) Version 5.0 Blend ProcSet) %%Version: 1.4 0 %%CreationDate: (11/19/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /Adobe_blend_AI5 70 dict dup begin put /bd { bind def } bind def /xs { exch store } bd /nullProc { { } } def /initialize { pop pop Adobe_blend_AI5 begin Adobe_blend_AI5_vars begin /_contoneDevice where { pop } { /_contoneDevice false def } ifelse /_dpiThreshold where { pop } { /_dpiThreshold 600 def } ifelse /_screenFreqThreshold where { pop } { /_screenFreqThreshold 150 def } ifelse /tRectOK? deviceDPI _dpiThreshold le currentScreenFreq _screenFreqThreshold le and _contoneDevice not and def /invertXfer { [ { 1 exch sub } /exec load systemdict/currenttransfer get exec /exec load ] cvx systemdict/settransfer get exec } bd /spotDict 3 dict dup begin /nSpots 2 def /spot1 7 dict def /spot2 7 dict def end def composite? { /_setgray_ /setgray load def /_fill_ /fill load def /_image_ /image load def } { /_setgray_ systemdict/setgray get def /_fill_ systemdict/fill get def /_image_ systemdict/image get def } ifelse } bd /terminate { currentdict Adobe_blend_AI5_vars eq { end currentdict Adobe_blend_AI5 eq { end } if } if } bd /_compositeSpotDevice where { begin _compositeSpotDevice 0 ne {userdict /composite? true put} if end } { /_compositeSpotDevice 0 def } ifelse /nullString () def /d255 256 array def 0 1 255 { d255 exch dup 255 div put } bind for /d255- 256 array def 0 1 255 { d255- exch 1 d255 2 index get sub put } bind for /dUserSpace matrix defaultmatrix def currentdict /Adobe_blend_AI5_vars 89 dict dup begin put { /f /F /s /S /b /B } { null def } bind forall /byte 1 string def /sSave null def /setSSave { save /sSave exch store } bind def /Bm null def /doBlend null def /startC? false def /endC? false def /fCMYK? null def /startTint 0 def /endTint 0 def /bSMatrix matrix def /bUMatrix matrix def /dMatrix matrix def /inLine? true def /pTState? false def /bHi? false def /yHi 0 def /xHi 0 def /noImg /lv1Fix where { pop lv1Fix } { false } ifelse def /ccAry1 5 array def /ccTint 0 def /spotColor? false def /colorimage? true def [ /tint1Data /tint2Data /spotDict /bAxis /ubAxis /pChange /optimize? /nSamples /sInc /blendProc /_bn /xBCInc /yBCInc /bInc /bRender /cBName /cBType /nColors /color? /blend? /colorType /cData /cDataLen /bDataLen /rampPoint /midPoint /endPoint /blendLength /blackData /yeData /mgData /cyData /cnt1 /ndx /_fill /tmp counttomark { null def } bind repeat pop currentdict end currentdict end exch begin begin /unitSq { 0 0 moveto 0 1 lineto 1 1 lineto 1 0 lineto closepath } bd /gMark { counttomark 2 add -1 roll } bd /setCustomColor { dup /ccTint exch store 1 exch sub 6 1 roll ccAry1 astore exch setcustomcolor } bd /currentCustomColor { ccAry1 aload pop ccTint } bd /nsetcustomcolor where { pop } { /nsetcustomcolor { pop setcmykcolor } bd } ifelse /nsetcustomcolorend where { pop } { /nsetcustomcolorend { } bd } ifelse /setBSpace { newpath bUMatrix astore concat unitSq } bd /setCStop { dup 0 eq { pop spotColor? { dup 1 exch sub /ccTint exch def ccAry1 4 /Black put } if setgray } { 1 eq { setcmykcolor } { composite? not colorType 2 lt and { forceCMYK } { setCustomColor } ifelse } ifelse } ifelse } bd /makeByte { /tmp 0 store 255 mul cvi 8 string 8 { dup tmp 3 index put /tmp tmp 1 add store } repeat exch pop } bd /setImgSpace { cDataLen 1 8 2 index 0 0 1 0 0 dMatrix astore } bd /bwImage { setImgSpace cData /_image_ load { exec } stopped { $error /errorname get /undefinedresult ne { stop } { pop pop pop pop pop } ifelse } if } bd level2? { /bFill { _fill } def /bCImg { /cDataLen bDataLen store setImgSpace setSSave expandSpot cyData mgData yeData cData expandCMYK true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd } if /expandOne { dup type /stringtype ne { cDataLen string exch dup 0 ne { 255 mul cvi 0 1 cDataLen 1 sub { 3 copy exch put pop } for } if pop } if } bd /expandSpot { spotColor? { spotDict begin spot1 begin tintImage type /nulltype ne { tintImage expandOne /tintImage exch def } if end spot2 begin tintImage type /nulltype ne { tintImage expandOne /tintImage exch def } if end end } if } bd /expandCMYK { 4 { expandOne 4 1 roll } repeat } bd /colorimage where dup { exch pop /ncolorimage where { pop } { /ncolorimage {pop colorimage} bd } ifelse } if not { /ncolorimage where { pop } { /colorimage? false store /ncolorimage { pop pop pop setSSave /blackData xs /yeData xs /mgData xs /cyData xs /cnt1 0 store [ byte dup 0 cyData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .3 /mul cvx } { .3 mul } ifelse mgData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .59 /mul cvx } { .59 mul } ifelse yeData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .11 /mul cvx } { .11 mul } ifelse blackData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx } if /add cvx /add cvx /add cvx 1 /exch cvx /sub cvx /dup cvx 0 /lt cvx { pop 0 } /if cvx /dup cvx 1 /gt cvx { pop 1 } /if cvx 255 /mul cvx /cvi cvx 256 /mod cvx /dup cvx 0 /lt cvx { pop 0 } /if cvx /put cvx /cnt1 dup cvx 1 /add cvx /store cvx ] cvx bind _image_ sSave restore } bd } ifelse } if level2? not { /bCImg { /cDataLen bDataLen store setImgSpace setSSave expandSpot cyData mgData yeData cData colorimage? { expandCMYK } if true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd /bwFill { setSSave /cDataLen 8 store /cData currentgray makeByte store bwImage sSave restore } bd /c1ImgFill { setSSave /cDataLen 8 store setImgSpace spotColor? { spotDict begin spot1 begin currentCustomColor makeByte /tintImage exch def /name exch def /spot_K exch def /spot_Y exch def /spot_M exch def /spot_C exch def end spot2 initSpotData end } if currentcmykcolor 4 { makeByte 4 1 roll } repeat true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd /bFill noImg { { _fill } } { { color? { c1ImgFill } { bwFill } ifelse } } ifelse bd } if composite? { /bCFun { color? { cyData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if mgData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if yeData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if cData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if spotColor? { spotDict begin /spotDict cvx /begin cvx spot1 begin tintImage dup type /stringtype eq { /ndx cvx /get cvx d255- /exch cvx /get cvx } { dup type /nulltype ne { name type /nametype ne {1 exch sub} if } if } ifelse end /spot1 cvx /tintValue 3 -1 /roll cvx /put cvx spot2 begin tintImage dup type /stringtype eq { /ndx cvx /get cvx d255- /exch cvx /get cvx } { dup type /nulltype ne { name type /nametype ne {1 exch sub} if } if } ifelse end /spot2 cvx /tintValue 3 -1 /roll cvx /put cvx /end cvx end /spotDict cvx /nsetcustomcolor cvx } { /setcmykcolor cvx } ifelse } { cData /ndx cvx /get cvx d255 /exch cvx /get cvx /setgray cvx } ifelse } bd /Bc { newpath gsave setBSpace nColors 1 eq { pop pop setCStop } if bFill grestore } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { linImg } { bFill } ifelse grestore nColors 1 gt { getRData } if } bd /rdBm { /nColors dup load 1 sub store _fill gsave bUMatrix astore concat bHi? { xHi yHi bUMatrix idtransform /yHi exch store /xHi exch store rampPoint 1 lt { 1 rampPoint sub dup xHi mul exch yHi mul translate } if } if nColors { 0 0 rampPoint 0 360 arc _fill blend? bHi? or { rdBlend } if nColors 1 gt { getRData } if /nColors dup load 1 sub store } repeat /nColors 1 store grestore } bd /cGetRData { setCStop /blend? cData type /stringtype eq dup not color? and { pop cyData type /stringtype eq mgData type /stringtype eq yeData type /stringtype eq or or } if store } def /cGetRData } if /eCStop { mark 1 index 3 mul 3 add dup 8 gt { pop 8 } if 1 roll cleartomark } bd composite? not { /knockOut level2? { { 0 0 0 0 setcmykcolor _fill } } { /bFill noImg { { _fill } } { { _of true eq { currentgray 1 ne { bwFill } if } { bwFill } ifelse } } ifelse def /whiteByte 1 makeByte def noImg { { 0 0 0 0 setcmykcolor _fill } } { { cBType 0 eq { setSSave /cData whiteByte store /cDataLen 8 store bwImage sSave restore } { _fill } ifelse } } ifelse } ifelse bd /bCFun { cData dup type /stringtype ne { color? { 1 exch sub } if } { /ndx cvx /get cvx color? customColor? not and { d255- } { d255 } ifelse /exch cvx /get cvx } ifelse /_setgray_ cvx } bd /eCCBlend { dup 3 eq { pop mark 7 1 roll 6 copy ccThrough? dup /blend? xs { /startC? true store setCustomColor customColor? { /cData tint1Data store setCDataLen } if /endC? 3 index 3 eq { 4 index 1 ne } { false } ifelse store } if cleartomark stop } if 1 eq { pop pop pop } if pop /startC? false store 6 { 8 index } repeat ccThrough? dup /blend? xs { /endC? true store blend? not { stop } if customColor? { /cData tint1Data store setCDataLen } if } if } bd /handleOP { _of not { knockOut } if } bd /handleROP { _of not { 0 0 0 0 setcmykcolor _fill } { newpath } ifelse } bd /rdBm { /nColors dup load 1 sub store blend? { _fill } { handleROP } ifelse gsave bUMatrix astore concat bHi? { xHi yHi bUMatrix idtransform /yHi exch store /xHi exch store rampPoint 1 lt { 1 rampPoint sub dup xHi mul exch yHi mul translate } if } if nColors { 0 0 rampPoint 0 360 arc blend? { cData type /stringtype ne bHi? not and { cData color? { 1 exch sub } if _setgray_ _fill_ } { cData type /stringtype ne { /cDataLen 1 store /bDataLen 1 store } if rdBlend } ifelse } { handleROP pTState? { /bAxis rampPoint endPoint sub store xHi bAxis mul yHi bAxis mul translate } if } ifelse nColors 1 gt { getRData } if /nColors dup load 1 sub store } repeat /nColors 1 store grestore } bd /ccThrough? { gsave pop 0 setCustomColor currentcmykcolor grestore anyColor? } bd /forceCMYK { exch pop 1 exch sub 5 1 roll 4 { 4 index mul 4 1 roll } repeat 0 cCMYKData dup /cData ne { dup /yeData eq { pop 1 add } { /mgData eq { 2 } { 3 } ifelse add } ifelse 0 } if pop index 0 eq { pop pop pop pop 0 0 0 0 } if setcmykcolor pop /fCMYK? true store } bd /endCapSepBc { pop pop dup 0 eq { pop setgray } { 1 eq { setcmykcolor } { colorType 1 eq { forceCMYK } { fCMYK? { forceCMYK } { setCustomColor } ifelse } ifelse } ifelse } ifelse currentcmykcolor anyColor? blend? and { bFill } { handleOP } ifelse } bd } if /cCMYKData 0 def composite? dup not { pop customColor? } if not { /cCMYKData /cyData /mgData /yeData /cData black? not { yellow? { exch } { magenta? { 3 } { 4 } ifelse -1 roll } ifelse } if 4 1 roll pop pop pop store /Bc { gsave setBSpace nColors 1 gt { blend? currentcmykcolor anyColor? and { bFill } { handleOP } ifelse } { endCapSepBc } ifelse grestore newpath } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { cCMYKData load dup type /stringtype eq { dup length /cDataLen xs /cData xs gsave colorType 0 ne noImg not and { invertXfer } if linImg grestore } { pop bFill } ifelse } { handleOP } ifelse grestore nColors 1 gt { getRData } if } bd /cmykGetRData { /fCMYK? false store blend? { { cmykDataProcs colorType get exec } stopped pop blend? { /cData cCMYKData load store setCDataLen } if } if } def /cmykDataProcs [ { pop black? dup /blend? xs { setgray 0 } if pop } { cCMYKData load dup type /stringtype ne { 0 0 0 cyan? not { 4 magenta? { 1 } { yellow? { 2 } { 3 } ifelse } ifelse roll } if 4 copy add add add 0 eq { /blend? false store } if setcmykcolor /startC? true store /endC? true store eCStop stop } if pop dup 0 eq { pop setgray } { 1 eq { setcmykcolor } { forceCMYK } ifelse } ifelse } bind /eCCBlend load { cBType 1 eq { tint1Data tint2Data /tint1Data xs /tint2Data xs } if 0 eq { black? { setgray } { 0 0 0 4 -1 roll 1 exch sub setcmykcolor } ifelse black? { /blend? true store } if 6 { 8 index } repeat ccThrough? { /blend? true store } { black? { /cData tint1Data store setCDataLen } { /blend? false store } ifelse } ifelse } { mark 7 1 roll 6 copy ccThrough? { forceCMYK pop stop } if 9 index 0 eq { black? dup /blend? xs { pop 1 setgray /cData tint2Data store setCDataLen 0 } if pop } { /blend? 6 { 16 index } repeat ccThrough? store blend? { forceCMYK } if } ifelse cleartomark } ifelse } bind ] def /cmykGetRData } if composite? dup not { pop isCMYKSep? } if not { /endCapSepBc { /white? false store pop pop dup 0 eq { pop /white? 1 index 1 eq store setgray } { 1 eq { setcmykcolor } { setCustomColor } ifelse } ifelse % currentcmykcolor anyColor? endC? or blend? and { bFill } { handleOP } ifelse } bd /Bc { gsave setBSpace nColors 1 gt { blend? startC? and { bFill } { handleOP } ifelse } { endCapSepBc } ifelse grestore newpath } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { cData type /stringtype eq { linImg } { bFill } ifelse } { handleOP } ifelse grestore nColors 1 gt { getRData } if } bd /discardCMY { counttomark 4 add -3 roll pop pop pop } bd /testTopCC { 6 copy ccThrough? } bd /getCRamp { { ccDataProcs colorType 2 sub get exec } stopped pop blend? cDataLen 0 eq and { /cDataLen bDataLen store } if } bd /ccGetRData { /fCMYK? false store /startC? false store /endC? false store colorType 2 lt { /blend? false def } if blend? { getCRamp } { setCStop } ifelse blend? { /blend? cData 1 ne store blend? { cData dup type /stringtype ne { 1 exch sub /cData xs 0 } if pop } if } if } def /ccDataProcs [ /eCCBlend load { cBType 1 eq { tint1Data tint2Data /tint1Data xs /tint2Data xs } if 0 eq { /blend? false store pop } { mark 7 1 roll testTopCC { /blend? 1 index 1 ne store /startC? blend? store /endC? false store blend? not { cleartomark stop } if /cData tint1Data store setCDataLen setCustomColor pop stop } if cleartomark } ifelse 2 index 0 eq { /blend? false store } { mark 6 { 9 index } repeat testTopCC dup /blend? xs { /blend? 1 index 1 ne store /endC? blend? store /startC? false store blend? not { cleartomark stop } if /cData tint2Data store setCDataLen } if cleartomark } ifelse } bind ] def /ccGetRData } if load Adobe_blend_AI5_vars /getData 3 -1 roll put /setCDataLen { /cDataLen 0 cData dup type /stringtype eq { length exch } if pop store } bd /initSpotData { begin /name null def /tintImage null def /tintValue null def /spot_C null def /spot_M null def /spot_Y null def /spot_K null def end } bd /getRData { /colorType gMark store _compositeSpotDevice 0 ne { spotDict begin spot1 initSpotData spot2 initSpotData end /spotColor? colorType 2 eq colorType 3 eq or def } { /spotColor? false store } ifelse /blend? true store 0 0 0 0 setcmykcolor 100 div /rampPoint xs % (between 13 and 87%) 100 div /midPoint xs dup 0 eq { 2 } { dup 1 eq { 5 } { _compositeSpotDevice 0 ne { spotDict begin spot1 begin /name 3 index def /spot_K 4 index def /spot_Y 5 index def /spot_M 6 index def /spot_C 7 index def end end } if 7 } ifelse } ifelse /tmp exch def tmp index 100 div /endPoint xs _compositeSpotDevice 0 ne { tmp 2 add index 3 eq { /tmp tmp 4 add def tmp index dup spotDict begin spot1/name get ne { spot2 begin /name exch def /spot_K tmp 2 add index def /spot_Y tmp 3 add index def /spot_M tmp 4 add index def /spot_C tmp 5 add index def end } { pop } ifelse end } if } if /color? colorType 0 gt store colorType 3 eq { /tint2Data gMark store } if colorType 2 ge { /tint1Data gMark store } if _compositeSpotDevice 0 ne { spotDict begin colorType 2 ge { colorType 3 eq { spot2 begin /tintImage cBType 0 eq {tint2Data} {tint1Data} ifelse def name null eq {/name /Black def} if end } if spot1 begin /tintImage cBType 0 eq colorType 2 eq or {tint1Data} {tint2Data} ifelse def colorType 2 eq { name null eq { /name spot2/name get def spot2/name null put } if } { name null eq {/name /Black def} if } ifelse end } if end } if /cData gMark store setCDataLen colorType 0 gt { counttomark 4 add -3 roll /yeData xs /mgData xs /cyData xs } if blend? { /bDataLen cDataLen dup 0 eq color? and { [ cyData mgData yeData ] { dup type /stringtype eq { length exch pop exit } if pop } forall } if store bDataLen 0 eq { /bDataLen 1 store } if getData blend? { composite? cDataLen 0 eq and { /cDataLen bDataLen store } if } if } { setCStop } ifelse } bd /Bg { 0 0 0 0 setcmykcolor 6 { pop } repeat /blendLength xs pop pop pop /cBName xs /bRender xs bRender 2 ne { composite? not { _of setoverprint } if _eo {eoclip} {clip} ifelse _bn cBName 2 copy known { get mark exch aload pop /cBType xs /nColors xs mark exch aload pop 0 0 } if pop pop getRData cBType 0 eq { /linealBm } { bHi? { /pTState? nColors 2 gt store } if /doBlend /rdBlend load store /rdBm } ifelse } { inLine? not { mark mark } if /Bc dup { cleartomark mark } bd /nullProc } ifelse load /Bm xs } bd /linImg noImg { { newpath doRctBlend } } { { /doBlend color? composite? and { /bCImg } { /bwImage } ifelse load store 0 0 moveto tRectOK? composite? and { { mark 0 1 dtransform atan cvi 90 mod 0 eq 1 0 dtransform atan cvi 90 mod 0 eq } stopped { cleartomark } { and exch pop { newpath doRctBlend } { doBlend } ifelse } ifelse } { doBlend } ifelse } } ifelse bd /doRctBlend { gsave /sInc 1 store /nSamples bDataLen store /bInc 1 bDataLen div store /ubAxis 1 0 dtransform dUserSpace idtransform dup mul exch dup mul add sqrt store /pChange ubAxis 0 eq { 0 } { bDataLen ubAxis div } ifelse store pChange .5 gt noImg not and dup /optimize? xs { /nSamples ubAxis 2 div round cvi dup 1 le { pop 2 } if store /bInc 1 nSamples div store /sInc bDataLen 1 sub nSamples 1 sub div store } if 0 nSamples [ /dup cvx optimize? { /round cvx /cvi cvx } if /ndx /exch cvx /store cvx bCFun /rectfill where dup { exch pop _compositeSpotDevice 1 ne and } if { 0 0 bInc 1 /rectfill cvx } { 0 0 /moveto cvx bInc 0 /lineto cvx bInc 1 /lineto cvx 0 1 /lineto cvx /closepath cvx /_fill_ cvx } ifelse bInc 0 /translate cvx sInc /add cvx ] cvx bind repeat pop spotColor? {nsetcustomcolorend} if grestore } bd /rdPrep { /nSamples bDataLen dup 0 eq { pop 1 } if store /sInc -1 store /bAxis rampPoint endPoint sub store /bInc bAxis bDataLen div neg store /optimize? false store tRectOK? { /ubAxis bAxis 0 dtransform dUserSpace idtransform dup mul exch dup mul add sqrt 0 bAxis dtransform dUserSpace idtransform dup mul exch dup mul add sqrt 2 copy lt { exch } if pop store /pChange ubAxis 0 eq { 0 } { bDataLen ubAxis div } ifelse store pChange .5 gt noImg not and dup /optimize? xs { /nSamples ubAxis 2 div round cvi dup 1 le { pop 2 } if store /bInc bAxis nSamples div neg store /sInc bDataLen 1 sub nSamples 1 sub div neg store } if } if bHi? { /xBCInc xHi bAxis mul nSamples div store /yBCInc yHi bAxis mul nSamples div store } if } bd /rdBlend { newpath gsave rdPrep rampPoint bDataLen 1 sub nSamples [ /dup cvx optimize? { /round cvx /cvi cvx } if /ndx /exch cvx /store cvx bCFun 0 0 3 /index cvx 0 360 /arc cvx /_fill_ cvx /exch cvx bInc /add cvx /exch cvx sInc /add cvx bHi? { xBCInc yBCInc /translate cvx } if ] cvx bind repeat pop pop spotColor? {nsetcustomcolorend} if grestore pTState? { xHi bAxis mul yHi bAxis mul translate } if } bd /Bh { pop pop /pTState? false store 2 copy 0 ne exch 0 ne or dup /bHi? xs { /yHi xs /xHi xs 0 0 } if pop pop } bd /BD { inLine? not { ] nColors cBType ] _bn cBName 3 -1 roll put end } if } bd /Bn { 1 add dict dup nullString null put /_bn xs } bd /Bd { Adobe_blend_AI5_vars begin 3 -1 roll dup nullString eq dup { setSSave } if /inLine? exch def /cBName exch def /nColors exch def /cBType exch def } bd /Bb { sSave null eq { Adobe_blend_AI5_vars begin setSSave } if composite? { /_fill /fill load store } { /__fill /fill load store /_fill { _of true eq { currentgray 1 ne { __fill } if } { __fill } ifelse } def } ifelse /fill { } def } bd /BB { /cBType xs cleartomark cleartomark cBType dup bRender sSave dup type /savetype eq { restore 0 } if pop currentdict Adobe_blend_AI5_vars eq { end } if 2 ne exch 0 gt and { 2 eq { s } { S } ifelse } { pop newpath } ifelse } bd currentdict readonly pop end end defaultpacking setpacking %%EndResource %%BeginResource: procset Adobe_pattern_AI5 1.1 0 %%Title: (Adobe Illustrator (R) Version 5.0 Pattern Operators) %%Version: 1.1 0 %%CreationDate: (03/26/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_Illustrator_AI5 known not { userdict /Adobe_Illustrator_AI5 95 dict put } if userdict /Adobe_Illustrator_AI5 get begin /@ { } def /& { } def /dp { dup null eq { pop _dp 0 ne { 0 1 _dp 1 sub _dl mod { _da exch get 3 get } for _dp 1 sub _dl mod 1 add packedarray _da 0 get aload pop 8 -1 roll 5 -1 roll pop 4 1 roll definepattern pop } if } { _dp 0 ne _dp _dl mod 0 eq and { null dp } if 7 packedarray _da exch _dp _dl mod exch put _dp _dl mod _da 0 get 4 get 2 packedarray /_dp _dp 1 add def } ifelse } def /E { _ed begin dup 0 get type /arraytype ne { 0 { dup 1 add index type /arraytype eq { 1 add } { exit } ifelse } loop array astore } if /_dd exch def /_ury exch def /_urx exch def /_lly exch def /_llx exch def /_n exch def /_y 0 def /_dl 4 def /_dp 0 def /_da _dl array def 0 1 _dd length 1 sub { /_d exch _dd exch get def 0 2 _d length 2 sub { /_x exch def /_c _d _x get _ ne def /_r _d _x 1 add get cvlit def _r _ ne { _urx _llx sub _ury _lly sub [ 1 0 0 1 0 0 ] [ /save cvx _llx neg _lly neg /translate cvx _c { nc /begin cvx } if _r dup type /stringtype eq { cvx } { { exec } /forall cvx } ifelse _c { /end cvx } if /restore cvx ] cvx /_fn 12 _n length add string def _y _fn cvs pop /_y _y 1 add def _fn 12 _n putinterval _fn _c false dp _d exch _x 1 add exch put } if } for } for null dp _n _dd /_pd end xput } def /fc { _fm dup concatmatrix pop } def /p { /_fm exch ddef 9 -2 roll _pm translate fc 7 -2 roll _pm scale fc 5 -1 roll _pm rotate fc 4 -2 roll exch 0 ne { dup _pm rotate fc 1 -1 _pm scale fc neg _pm rotate fc } { pop } ifelse dup _pm rotate fc exch dup sin exch cos div 1 0 0 1 0 6 2 roll _pm astore fc neg _pm rotate fc _pd exch get /_fdd exch ddef /_pf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm patternfill } { pop fill } ifelse grestore pop } for pop } for restore newpath } ddef /_psf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm 9 copy 6 npop patternashow } { pop 6 copy 3 npop hvashow } ifelse grestore pop } for pop } for restore sw rmoveto } ddef /_pjsf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm 12 copy 6 npop patternawidthshow } { pop 9 copy 3 npop hvawidthshow } ifelse grestore pop } for pop } for restore swj rmoveto } ddef /_lp /none ddef } def /sc { _sm dup concatmatrix pop } def /P { /_sm exch ddef 9 -2 roll _pm translate sc 7 -2 roll _pm scale sc 5 -1 roll _pm rotate sc 4 -2 roll exch 0 ne { dup _pm rotate sc 1 -1 _pm scale sc neg _pm rotate sc } { pop } ifelse dup _pm rotate sc exch dup sin exch cos div 1 0 0 1 0 6 2 roll _pm astore sc neg _pm rotate sc _pd exch get /_sdd exch ddef /_ps { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm patternstroke } { pop stroke } ifelse grestore pop } for pop } for restore newpath } ddef /_pss { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm 10 copy 6 npop patternashowstroke } { pop 7 copy 3 npop ss } ifelse grestore pop } for pop } for restore pop sw rmoveto } ddef /_pjss { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm 13 copy 6 npop patternawidthshowstroke } { pop 10 copy 3 npop jss } ifelse grestore pop } for pop } for restore pop swj rmoveto } ddef /_lp /none ddef } def end userdict /Adobe_pattern_AI5 18 dict dup begin put /initialize { /definepattern where { pop } { begin begin Adobe_pattern_AI5 begin Adobe_pattern_AI5 { dup xcheck { bind } if pop pop } forall mark cachestatus 7 1 roll pop pop pop pop exch pop exch { { 10000 add dup 2 index gt { exit } if dup setcachelimit } loop } stopped cleartomark end end end Adobe_pattern_AI5 begin } ifelse } def /terminate { currentdict Adobe_pattern_AI5 eq { end } if } def errordict /nocurrentpoint { pop stop } put errordict /invalidaccess { pop stop } put /patternencoding 256 array def 0 1 255 { patternencoding exch ( ) 2 copy exch 0 exch put cvn put } for /definepattern { 17 dict begin /uniform exch def /cache exch def /key exch def /procarray exch def /mtx exch matrix invertmatrix def /height exch def /width exch def /ctm matrix currentmatrix def /ptm matrix def /str 32 string def /slice 9 dict def slice /s 1 put slice /q 256 procarray length div sqrt floor cvi put slice /b 0 put /FontBBox [ 0 0 0 0 ] def /FontMatrix mtx matrix copy def /Encoding patternencoding def /FontType 3 def /BuildChar { exch begin /setstrokeadjust where {pop true setstrokeadjust} if slice begin dup q dup mul mod s idiv /i exch def dup q dup mul mod s mod /j exch def q dup mul idiv procarray exch get /xl j width s div mul def /xg j 1 add width s div mul def /yl i height s div mul def /yg i 1 add height s div mul def uniform { 1 1 } { width 0 dtransform dup mul exch dup mul add sqrt dup 1 add exch div 0 height dtransform dup mul exch dup mul add sqrt dup 1 add exch div } ifelse width 0 cache { xl 4 index mul yl 4 index mul xg 6 index mul yg 6 index mul setcachedevice } { setcharwidth } ifelse gsave scale newpath xl yl moveto xg yl lineto xg yg lineto xl yg lineto closepath clip newpath end end exec grestore } def key currentdict definefont end } def /patterncachesize { gsave newpath 0 0 moveto width 0 lineto width height lineto 0 height lineto closepath patternmatrix setmatrix pathbbox exch ceiling 4 -1 roll floor sub 3 1 roll ceiling exch floor sub mul 1 add grestore } def /patterncachelimit { cachestatus 7 1 roll 6 npop 8 mul } def /patternpath { exch dup begin setfont ctm setmatrix concat slice exch /b exch slice /q get dup mul mul put FontMatrix concat uniform { width 0 dtransform round width div exch round width div exch 0 height dtransform round height div exch height div exch 0 0 transform round exch round exch ptm astore setmatrix } { ptm currentmatrix pop } ifelse { currentpoint } stopped not { 2 npop pathbbox true 4 index 3 index eq 4 index 3 index eq and { pop false { { 2 npop } { 3 npop true } { 7 npop true } { pop true } pathforall } stopped { 5 npop true } if } if { height div ceiling height mul 4 1 roll width div ceiling width mul 4 1 roll height div floor height mul 4 1 roll width div floor width mul 4 1 roll 2 index sub height div ceiling cvi exch 3 index sub width div ceiling cvi exch 4 2 roll moveto FontMatrix mtx invertmatrix dup dup 4 get exch 5 get rmoveto ptm ptm concatmatrix pop slice /s patterncachesize patterncachelimit div ceiling sqrt ceiling cvi dup slice /q get gt { pop slice /q get } if put 0 1 slice /s get dup mul 1 sub { slice /b get add gsave 0 1 str length 1 sub { str exch 2 index put } for pop dup { gsave ptm setmatrix 1 index str length idiv { str show } repeat 1 index str length mod str exch 0 exch getinterval show grestore 0 height rmoveto } repeat grestore } for 2 npop } { 4 npop } ifelse } if end } def /patternclip { _eo {eoclip} {clip} ifelse } def /patternstrokepath { strokepath } def /patternmatrix matrix def /patternfill { dup type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get } if gsave patternclip Adobe_pattern_AI5 /patternpath get exec grestore newpath } def /patternstroke { dup type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get } if gsave patternstrokepath true { { { newpath moveto } { lineto } { curveto } { closepath 3 copy Adobe_pattern_AI5 /patternfill get exec } pathforall 3 npop } stopped { 5 npop patternclip Adobe_pattern_AI5 /patternfill get exec } if } { patternclip Adobe_pattern_AI5 /patternfill get exec } ifelse grestore newpath } def /vpatternawidthshow { 6 1 roll /_hvay exch ddef /_hvax exch ddef /_hvwb exch ddef /_hvcy exch ddef /_hvcx exch ddef { dup cstring dup length 1 eq _charorientation 1 eq and { -90 rotate currentpoint _fontRotateAdjust add moveto gsave false charpath currentpoint 5 index 5 index 5 index Adobe_pattern_AI5 /patternfill get exec grestore _fontRotateAdjust sub moveto _hvwb eq { _hvcx _hvcy rmoveto } if _hvax _hvay rmoveto 90 rotate } { currentpoint _fontHeight sub _hvax sub 3 index _hvwb eq { _hvcx sub } if currentpoint exch 4 index stringwidth pop 2 div sub exch _fontAscent sub moveto gsave 2 index false charpath 6 index 6 index 6 index Adobe_pattern_AI5 /patternfill get exec grestore newpath moveto pop pop } ifelse } cforall 3 npop } def /hpatternawidthshow { { dup cstring exch gsave 3 index eq { 5 index 5 index rmoveto } if false charpath currentpoint 9 index 9 index 9 index Adobe_pattern_AI5 /patternfill get exec grestore newpath moveto 2 copy rmoveto } cforall 8 npop } def /patternashow { 0 0 0 6 3 roll patternawidthshow } def /patternawidthshow { 6 index type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get 7 1 roll } if _lineorientation 0 eq { hpatternawidthshow } { vpatternawidthshow } ifelse } def /vpatternawidthshowstroke { 7 1 roll 6 1 roll /_hvay exch ddef /_hvax exch ddef /_hvwb exch ddef /_hvcy exch ddef /_hvcx exch ddef { dup cstring dup length 1 eq _charorientation 1 eq and { -90 rotate currentpoint _fontRotateAdjust add moveto gsave false charpath currentpoint 3 index setmatrix 6 index 6 index 6 index Adobe_pattern_AI5 /patternstroke get exec grestore _fontRotateAdjust sub moveto _hvwb eq { _hvcx _hvcy rmoveto } if _hvax _hvay rmoveto 90 rotate } { currentpoint _fontHeight sub _hvax sub 3 index _hvwb eq { _hvcx sub } if currentpoint exch 4 index stringwidth pop 2 div sub exch _fontAscent sub moveto gsave 2 index false charpath 4 index setmatrix 7 index 7 index 7 index Adobe_pattern_AI5 /patternstroke get exec grestore newpath moveto pop pop } ifelse } cforall 4 npop } def /hpatternawidthshowstroke { 7 1 roll { dup cstring exch gsave 3 index eq { 5 index 5 index rmoveto } if false charpath currentpoint 7 index setmatrix 10 index 10 index 10 index Adobe_pattern_AI5 /patternstroke get exec grestore newpath moveto 2 copy rmoveto } cforall 9 npop } def /patternashowstroke { 0 0 0 7 3 roll patternawidthshowstroke } def /patternawidthshowstroke { 7 index type /dicttype eq { patternmatrix /patternmatrix get 8 1 roll } if _lineorientation 0 eq { hpatternawidthshowstroke } { vpatternawidthshowstroke } ifelse } def end setpacking %%EndResource %%EndProlog %%BeginSetup Adobe_level2_AI5 /initialize get exec Adobe_screens_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_typography_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_blend_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_pattern_AI5 /initialize get exec Adobe_ColorImage_AI6 /initialize get exec Adobe_Illustrator_AI5 /initialize get exec [ 39/quotesingle 96/grave 130/quotesinglbase 131/florin 132/quotedblbase 133/ellipsis 134/dagger 135/daggerdbl 136/circumflex 137/perthousand 138/Scaron 139/guilsinglleft 140/OE 145/quoteleft 146/quoteright 147/quotedblleft 148/quotedblright 149/bullet 150/endash 151/emdash 152/tilde 153/trademark 154/scaron 155/guilsinglright 156/oe 157/dotlessi 159/Ydieresis 164/currency 166/brokenbar 168/dieresis 169/copyright 170/ordfeminine 172/logicalnot 174/registered 175/macron 176/ring 177/plusminus 178/twosuperior 179/threesuperior 180/acute 181/mu 183/periodcentered 184/cedilla 185/onesuperior 186/ordmasculine 188/onequarter 189/onehalf 190/threequarters 192/Agrave 193/Aacute 194/Acircumflex 195/Atilde 196/Adieresis 197/Aring 198/AE 199/Ccedilla 200/Egrave 201/Eacute 202/Ecircumflex 203/Edieresis 204/Igrave 205/Iacute 206/Icircumflex 207/Idieresis 208/Eth 209/Ntilde 210/Ograve 211/Oacute 212/Ocircumflex 213/Otilde 214/Odieresis 215/multiply 216/Oslash 217/Ugrave 218/Uacute 219/Ucircumflex 220/Udieresis 221/Yacute 222/Thorn 223/germandbls 224/agrave 225/aacute 226/acircumflex 227/atilde 228/adieresis 229/aring 230/ae 231/ccedilla 232/egrave 233/eacute 234/ecircumflex 235/edieresis 236/igrave 237/iacute 238/icircumflex 239/idieresis 240/eth 241/ntilde 242/ograve 243/oacute 244/ocircumflex 245/otilde 246/odieresis 247/divide 248/oslash 249/ugrave 250/uacute 251/ucircumflex 252/udieresis 253/yacute 254/thorn 255/ydieresis TE %AI3_BeginEncoding: _Helvetica Helvetica [ /_Helvetica/Helvetica 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-Bold Helvetica-Bold [ /_Helvetica-Bold/Helvetica-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-Oblique Helvetica-Oblique [ /_Helvetica-Oblique/Helvetica-Oblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-BoldOblique Helvetica-BoldOblique [ /_Helvetica-BoldOblique/Helvetica-BoldOblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Roman Times-Roman [ /_Times-Roman/Times-Roman 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Bold Times-Bold [ /_Times-Bold/Times-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Italic Times-Italic [ /_Times-Italic/Times-Italic 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-BoldItalic Times-BoldItalic [ /_Times-BoldItalic/Times-BoldItalic 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier Courier [ /_Courier/Courier 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-Bold Courier-Bold [ /_Courier-Bold/Courier-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-Oblique Courier-Oblique [ /_Courier-Oblique/Courier-Oblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-BoldOblique Courier-BoldOblique [ /_Courier-BoldOblique/Courier-BoldOblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Symbol Symbol [ /_Symbol/Symbol 0 0 1 TZ %AI3_EndEncoding AdobeType %%EndSetup 1 XR u 0.000 0.000 0.000 0.247 k [] 0 d 0.000 0.000 0.000 1.000 K 1 j 239.2500 108.7500 m 245.2500 114.0000 L 291.7500 111.0000 L 323.2500 117.0000 L 329.2500 114.0000 L 323.2500 108.7500 L 312.7500 111.0000 L 281.2500 105.7500 L 239.2500 108.7500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 323.2500 108.7500 m 323.2500 6.0000 L 329.2500 11.2500 L 329.2500 114.0000 L 323.2500 108.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 239.2500 6.0000 m 281.2500 3.0000 L 312.7500 9.0000 L 323.2500 6.0000 L 323.2500 108.7500 L 312.7500 111.0000 L 281.2500 105.7500 L 239.2500 108.7500 L 239.2500 6.0000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 239.2500 177.7500 m 245.2500 183.7500 L 291.7500 180.7500 L 323.2500 186.0000 L 329.2500 183.7500 L 323.2500 177.7500 L 312.7500 180.7500 L 281.2500 174.7500 L 239.2500 177.7500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 323.2500 177.7500 m 323.2500 118.5000 L 329.2500 123.7500 L 329.2500 183.7500 L 323.2500 177.7500 L B U u 0.000 0.000 0.000 0.000 k 239.2500 118.5000 m 281.2500 115.5000 L 312.7500 120.7500 L 323.2500 118.5000 L 323.2500 177.7500 L 312.7500 180.7500 L 281.2500 174.7500 L 239.2500 177.7500 L 239.2500 118.5000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 57.7500 243.7500 m 64.5000 251.2500 L 64.5000 264.7500 L 57.7500 258.0000 L 57.7500 243.7500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1.5000 258.0000 m 57.7500 258.0000 L 64.5000 264.7500 L 8.2500 264.7500 L 1.5000 258.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 1.5000 243.7500 m 57.7500 243.7500 L 57.7500 258.0000 L 1.5000 258.0000 L 1.5000 243.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 3.7500 248.2500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (m_frags_tail\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 57.7500 258.0000 m 64.5000 264.7500 L 64.5000 279.0000 L 57.7500 272.2500 L 57.7500 258.0000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1.5000 272.2500 m 57.7500 272.2500 L 64.5000 279.0000 L 8.2500 279.0000 L 1.5000 272.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 1.5000 258.0000 m 57.7500 258.0000 L 57.7500 272.2500 L 1.5000 272.2500 L 1.5000 258.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 3.7500 262.5000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (m_null\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 57.7500 272.2500 m 64.5000 279.0000 L 64.5000 293.2500 L 57.7500 285.7500 L 57.7500 272.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1.5000 285.7500 m 57.7500 285.7500 L 64.5000 293.2500 L 8.2500 293.2500 L 1.5000 285.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 1.5000 272.2500 m 57.7500 272.2500 L 57.7500 285.7500 L 1.5000 285.7500 L 1.5000 272.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 3.7500 276.7500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (m_frags\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 170.2500 314.2500 m 176.2500 321.0000 L 176.2500 335.2500 L 170.2500 328.5000 L 170.2500 314.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 127.5000 328.5000 m 170.2500 328.5000 L 176.2500 335.2500 L 135.0000 335.2500 L 127.5000 328.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 127.5000 314.2500 m 170.2500 314.2500 L 170.2500 328.5000 L 127.5000 328.5000 L 127.5000 314.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 129.7500 318.7500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (h_succ\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 170.2500 272.2500 m 176.2500 279.0000 L 176.2500 293.2500 L 170.2500 285.7500 L 170.2500 272.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 127.5000 272.2500 m 170.2500 272.2500 L 170.2500 285.7500 L 127.5000 285.7500 L 127.5000 272.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 145.5000 276.7500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (\205\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 170.2500 230.2500 m 176.2500 237.0000 L 176.2500 251.2500 L 170.2500 243.7500 L 170.2500 230.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 127.5000 243.7500 m 170.2500 243.7500 L 176.2500 251.2500 L 135.0000 251.2500 L 127.5000 243.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 127.5000 230.2500 m 170.2500 230.2500 L 170.2500 243.7500 L 127.5000 243.7500 L 127.5000 230.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 129.7500 234.7500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (h_succ\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 170.2500 146.2500 m 176.2500 153.7500 L 176.2500 167.2500 L 170.2500 160.5000 L 170.2500 146.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 127.5000 160.5000 m 170.2500 160.5000 L 176.2500 167.2500 L 135.0000 167.2500 L 127.5000 160.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 127.5000 146.2500 m 170.2500 146.2500 L 170.2500 160.5000 L 127.5000 160.5000 L 127.5000 146.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 129.7500 150.7500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (h_succ\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 170.2500 62.2500 m 176.2500 69.0000 L 176.2500 83.2500 L 170.2500 76.5000 L 170.2500 62.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 127.5000 76.5000 m 170.2500 76.5000 L 176.2500 83.2500 L 135.0000 83.2500 L 127.5000 76.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 127.5000 62.2500 m 170.2500 62.2500 L 170.2500 76.5000 L 127.5000 76.5000 L 127.5000 62.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 129.7500 66.7500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (h_succ\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 170.2500 187.5000 m 176.2500 195.0000 L 176.2500 208.5000 L 170.2500 201.7500 L 170.2500 187.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 127.5000 187.5000 m 170.2500 187.5000 L 170.2500 201.7500 L 127.5000 201.7500 L 127.5000 187.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 145.5000 192.7500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (\205\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 170.2500 104.2500 m 176.2500 111.0000 L 176.2500 125.2500 L 170.2500 118.5000 L 170.2500 104.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 127.5000 104.2500 m 170.2500 104.2500 L 170.2500 118.5000 L 127.5000 118.5000 L 127.5000 104.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 145.5000 108.7500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (\205\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 170.2500 20.2500 m 176.2500 27.0000 L 176.2500 41.2500 L 170.2500 33.7500 L 170.2500 20.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 127.5000 20.2500 m 170.2500 20.2500 L 170.2500 33.7500 L 127.5000 33.7500 L 127.5000 20.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 145.5000 24.7500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (\205\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 170.2500 300.0000 m 176.2500 307.5000 L 176.2500 321.0000 L 170.2500 314.2500 L 170.2500 300.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 127.5000 300.0000 m 170.2500 300.0000 L 170.2500 314.2500 L 127.5000 314.2500 L 127.5000 300.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 142.5000 304.5000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (h_prev\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 170.2500 216.0000 m 176.2500 222.7500 L 176.2500 237.0000 L 170.2500 230.2500 L 170.2500 216.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 127.5000 216.0000 m 170.2500 216.0000 L 170.2500 230.2500 L 127.5000 230.2500 L 127.5000 216.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 142.5000 220.5000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (h_prev\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 1 j 132.7500 223.5000 m 132.7500 222.7500 L 132.7500 222.7500 L 132.7500 222.0000 L 133.5000 221.2500 L 133.5000 221.2500 L 134.2500 220.5000 L 135.0000 220.5000 L 135.7500 221.2500 L 135.7500 221.2500 L 136.5000 222.0000 L 136.5000 222.0000 L 136.5000 222.7500 L 136.5000 223.5000 L 136.5000 224.2500 L 136.5000 224.2500 L 135.7500 225.0000 L 135.0000 225.0000 L 134.2500 225.0000 L 134.2500 225.0000 L 133.5000 224.2500 L 132.7500 224.2500 L 132.7500 223.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 121.5000 320.2500 m 127.5000 321.0000 L 125.2500 315.7500 L 121.5000 320.2500 L F U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 170.2500 132.0000 m 176.2500 139.5000 L 176.2500 153.7500 L 170.2500 146.2500 L 170.2500 132.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 127.5000 132.0000 m 170.2500 132.0000 L 170.2500 146.2500 L 127.5000 146.2500 L 127.5000 132.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 142.5000 137.2500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (h_prev\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 1 j 132.7500 140.2500 m 132.7500 139.5000 L 132.7500 138.7500 L 132.7500 138.0000 L 133.5000 138.0000 L 133.5000 137.2500 L 134.2500 137.2500 L 135.0000 137.2500 L 135.7500 137.2500 L 135.7500 138.0000 L 136.5000 138.0000 L 136.5000 138.7500 L 136.5000 139.5000 L 136.5000 139.5000 L 136.5000 140.2500 L 136.5000 141.0000 L 135.7500 141.0000 L 135.0000 141.0000 L 134.2500 141.7500 L 134.2500 141.0000 L 133.5000 141.0000 L 132.7500 140.2500 L 132.7500 140.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 121.5000 235.5000 m 127.5000 237.0000 L 125.2500 231.7500 L 121.5000 235.5000 L F U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 170.2500 48.0000 m 176.2500 54.7500 L 176.2500 69.0000 L 170.2500 62.2500 L 170.2500 48.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 127.5000 48.0000 m 170.2500 48.0000 L 170.2500 62.2500 L 127.5000 62.2500 L 127.5000 48.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 142.5000 52.5000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (h_prev\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 1 j 132.7500 55.5000 m 132.7500 55.5000 L 132.7500 54.7500 L 132.7500 54.0000 L 133.5000 53.2500 L 133.5000 53.2500 L 134.2500 53.2500 L 135.0000 53.2500 L 135.7500 53.2500 L 135.7500 53.2500 L 136.5000 54.0000 L 136.5000 54.7500 L 136.5000 54.7500 L 136.5000 55.5000 L 136.5000 56.2500 L 136.5000 56.2500 L 135.7500 57.0000 L 135.0000 57.0000 L 134.2500 57.0000 L 134.2500 57.0000 L 133.5000 57.0000 L 132.7500 56.2500 L 132.7500 55.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 121.5000 152.2500 m 127.5000 153.7500 L 125.2500 147.7500 L 121.5000 152.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 165.0000 153.0000 m 164.2500 152.2500 L 164.2500 152.2500 L 163.5000 151.5000 L 163.5000 151.5000 L 162.7500 151.5000 L 162.0000 151.5000 L 161.2500 151.5000 L 161.2500 152.2500 L 161.2500 153.0000 L 160.5000 153.0000 L 160.5000 153.7500 L 161.2500 154.5000 L 161.2500 155.2500 L 162.0000 155.2500 L 162.7500 155.2500 L 162.7500 155.2500 L 163.5000 155.2500 L 164.2500 155.2500 L 164.2500 154.5000 L 165.0000 153.7500 L 165.0000 153.7500 L 165.0000 153.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 144.7500 84.7500 m 141.7500 79.5000 L 147.7500 80.2500 L 144.7500 84.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 165.0000 236.2500 m 164.2500 235.5000 L 164.2500 235.5000 L 163.5000 234.7500 L 163.5000 234.7500 L 162.7500 234.7500 L 162.0000 234.7500 L 161.2500 235.5000 L 161.2500 235.5000 L 161.2500 236.2500 L 160.5000 237.0000 L 160.5000 237.7500 L 161.2500 237.7500 L 161.2500 238.5000 L 162.0000 238.5000 L 162.7500 239.2500 L 162.7500 239.2500 L 163.5000 238.5000 L 164.2500 238.5000 L 164.2500 237.7500 L 165.0000 237.7500 L 165.0000 237.0000 L 165.0000 236.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 144.7500 168.7500 m 141.7500 164.2500 L 147.7500 164.2500 L 144.7500 168.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 165.0000 321.0000 m 164.2500 320.2500 L 164.2500 319.5000 L 163.5000 319.5000 L 163.5000 319.5000 L 162.7500 319.5000 L 162.0000 319.5000 L 161.2500 319.5000 L 161.2500 320.2500 L 161.2500 320.2500 L 160.5000 321.0000 L 160.5000 321.7500 L 161.2500 322.5000 L 161.2500 322.5000 L 162.0000 323.2500 L 162.7500 323.2500 L 162.7500 323.2500 L 163.5000 323.2500 L 164.2500 322.5000 L 164.2500 322.5000 L 165.0000 321.7500 L 165.0000 321.0000 L 165.0000 321.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 144.7500 252.7500 m 141.7500 247.5000 L 147.7500 247.5000 L 144.7500 252.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 48.7500 249.0000 m 49.5000 249.0000 L 49.5000 249.7500 L 50.2500 250.5000 L 50.2500 250.5000 L 50.2500 251.2500 L 50.2500 252.0000 L 49.5000 252.7500 L 49.5000 252.7500 L 48.7500 252.7500 L 48.0000 252.7500 L 47.2500 252.7500 L 47.2500 252.7500 L 46.5000 252.0000 L 46.5000 252.0000 L 45.7500 251.2500 L 46.5000 250.5000 L 46.5000 249.7500 L 46.5000 249.7500 L 47.2500 249.0000 L 48.0000 249.0000 L 48.0000 249.0000 L 48.7500 249.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 122.2500 72.0000 m 127.5000 69.0000 L 122.2500 66.7500 L 122.2500 72.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 50.2500 279.7500 m 50.2500 279.0000 L 50.2500 278.2500 L 50.2500 278.2500 L 49.5000 277.5000 L 49.5000 277.5000 L 48.7500 276.7500 L 48.0000 276.7500 L 47.2500 277.5000 L 47.2500 277.5000 L 46.5000 277.5000 L 46.5000 278.2500 L 45.7500 279.0000 L 46.5000 279.7500 L 46.5000 279.7500 L 46.5000 280.5000 L 47.2500 280.5000 L 48.0000 281.2500 L 48.0000 281.2500 L 48.7500 281.2500 L 49.5000 280.5000 L 49.5000 280.5000 L 50.2500 279.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 125.2500 315.7500 m 127.5000 321.0000 L 121.5000 320.2500 L 125.2500 315.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 132.7500 306.0000 m 132.7500 306.7500 L 132.7500 306.7500 L 132.7500 307.5000 L 132.7500 308.2500 L 133.5000 308.2500 L 133.5000 309.0000 L 134.2500 309.0000 L 135.0000 309.0000 L 135.7500 309.0000 L 135.7500 309.0000 L 136.5000 308.2500 L 136.5000 307.5000 L 136.5000 307.5000 L 136.5000 306.7500 L 136.5000 306.0000 L 136.5000 306.0000 L 135.7500 305.2500 L 135.0000 305.2500 L 134.2500 305.2500 L 134.2500 305.2500 L 133.5000 305.2500 L 132.7500 306.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 62.2500 268.5000 m 57.7500 264.7500 L 63.7500 263.2500 L 62.2500 268.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 160.5000 69.0000 m 161.2500 68.2500 L 161.2500 68.2500 L 161.2500 67.5000 L 162.0000 67.5000 L 162.7500 66.7500 L 162.7500 66.7500 L 163.5000 67.5000 L 164.2500 67.5000 L 164.2500 68.2500 L 165.0000 68.2500 L 165.0000 69.0000 L 165.0000 69.7500 L 164.2500 70.5000 L 164.2500 70.5000 L 163.5000 71.2500 L 163.5000 71.2500 L 162.7500 71.2500 L 162.0000 71.2500 L 161.2500 70.5000 L 161.2500 70.5000 L 161.2500 69.7500 L 160.5000 69.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 61.5000 260.2500 m 57.7500 264.7500 L 63.7500 265.5000 L 61.5000 260.2500 L F U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 170.2500 201.7500 m 176.2500 208.5000 L 176.2500 222.7500 L 170.2500 216.0000 L 170.2500 201.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 127.5000 201.7500 m 170.2500 201.7500 L 170.2500 216.0000 L 127.5000 216.0000 L 127.5000 201.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 129.7500 206.2500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (h_data\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 170.2500 285.7500 m 176.2500 293.2500 L 176.2500 307.5000 L 170.2500 300.0000 L 170.2500 285.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 127.5000 285.7500 m 170.2500 285.7500 L 170.2500 300.0000 L 127.5000 300.0000 L 127.5000 285.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 129.7500 291.0000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (h_data\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 170.2500 118.5000 m 176.2500 125.2500 L 176.2500 139.5000 L 170.2500 132.0000 L 170.2500 118.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 127.5000 118.5000 m 170.2500 118.5000 L 170.2500 132.0000 L 127.5000 132.0000 L 127.5000 118.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 129.7500 123.0000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (h_data\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 170.2500 33.7500 m 176.2500 41.2500 L 176.2500 54.7500 L 170.2500 48.0000 L 170.2500 33.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 127.5000 33.7500 m 170.2500 33.7500 L 170.2500 48.0000 L 127.5000 48.0000 L 127.5000 33.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 129.7500 39.0000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (h_data\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 239.2500 213.0000 m 245.2500 219.0000 L 291.7500 216.0000 L 323.2500 221.2500 L 329.2500 219.0000 L 323.2500 213.0000 L 312.7500 216.0000 L 281.2500 210.0000 L 239.2500 213.0000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 323.2500 213.0000 m 323.2500 180.7500 L 329.2500 186.0000 L 329.2500 219.0000 L 323.2500 213.0000 L B U u 0.000 0.000 0.000 0.000 k 239.2500 180.7500 m 281.2500 177.7500 L 312.7500 183.7500 L 323.2500 180.7500 L 323.2500 213.0000 L 312.7500 216.0000 L 281.2500 210.0000 L 239.2500 213.0000 L 239.2500 180.7500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 239.2500 237.0000 m 245.2500 242.2500 L 291.7500 240.0000 L 323.2500 245.2500 L 329.2500 242.2500 L 323.2500 237.0000 L 312.7500 240.0000 L 281.2500 234.0000 L 239.2500 237.0000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 323.2500 237.0000 m 323.2500 216.0000 L 329.2500 221.2500 L 329.2500 242.2500 L 323.2500 237.0000 L B U u 0.000 0.000 0.000 0.000 k 239.2500 216.0000 m 281.2500 213.0000 L 312.7500 219.0000 L 323.2500 216.0000 L 323.2500 237.0000 L 312.7500 240.0000 L 281.2500 234.0000 L 239.2500 237.0000 L 239.2500 216.0000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 239.2500 262.5000 m 245.2500 267.7500 L 291.7500 264.7500 L 323.2500 270.7500 L 329.2500 267.7500 L 323.2500 262.5000 L 312.7500 264.7500 L 281.2500 259.5000 L 239.2500 262.5000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 323.2500 262.5000 m 323.2500 240.0000 L 329.2500 245.2500 L 329.2500 267.7500 L 323.2500 262.5000 L B U u 0.000 0.000 0.000 0.000 k 239.2500 240.0000 m 281.2500 237.0000 L 312.7500 242.2500 L 323.2500 240.0000 L 323.2500 262.5000 L 312.7500 264.7500 L 281.2500 259.5000 L 239.2500 262.5000 L 239.2500 240.0000 L B U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 165.0000 293.2500 m 165.0000 294.0000 L 164.2500 294.0000 L 164.2500 294.7500 L 163.5000 294.7500 L 163.5000 294.7500 L 162.7500 294.7500 L 162.0000 294.7500 L 161.2500 294.7500 L 161.2500 294.0000 L 161.2500 294.0000 L 160.5000 293.2500 L 161.2500 292.5000 L 161.2500 291.7500 L 161.2500 291.7500 L 162.0000 291.0000 L 162.7500 291.0000 L 163.5000 291.0000 L 163.5000 291.0000 L 164.2500 291.7500 L 164.2500 291.7500 L 165.0000 292.5000 L 165.0000 293.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 237.7500 256.5000 m 239.2500 251.2500 L 233.2500 252.7500 L 237.7500 256.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 165.0000 208.5000 m 165.0000 208.5000 L 164.2500 207.7500 L 164.2500 207.0000 L 163.5000 207.0000 L 163.5000 207.0000 L 162.7500 207.0000 L 162.0000 207.0000 L 161.2500 207.0000 L 161.2500 207.7500 L 161.2500 208.5000 L 160.5000 208.5000 L 161.2500 209.2500 L 161.2500 210.0000 L 161.2500 210.0000 L 162.0000 210.7500 L 162.7500 210.7500 L 163.5000 210.7500 L 163.5000 210.7500 L 164.2500 210.0000 L 164.2500 210.0000 L 165.0000 209.2500 L 165.0000 208.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 236.2500 221.2500 m 239.2500 226.5000 L 233.2500 225.7500 L 236.2500 221.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 165.0000 125.2500 m 165.0000 124.5000 L 164.2500 124.5000 L 164.2500 123.7500 L 163.5000 123.7500 L 163.5000 123.0000 L 162.7500 123.0000 L 162.0000 123.7500 L 161.2500 123.7500 L 161.2500 124.5000 L 161.2500 124.5000 L 160.5000 125.2500 L 161.2500 126.0000 L 161.2500 126.7500 L 161.2500 126.7500 L 162.0000 127.5000 L 162.7500 127.5000 L 163.5000 127.5000 L 163.5000 127.5000 L 164.2500 126.7500 L 164.2500 126.7500 L 165.0000 126.0000 L 165.0000 125.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 238.5000 190.5000 m 239.2500 197.2500 L 234.0000 193.5000 L 238.5000 190.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 165.0000 42.0000 m 165.0000 41.2500 L 165.0000 40.5000 L 164.2500 39.7500 L 164.2500 39.7500 L 163.5000 39.0000 L 163.5000 39.0000 L 162.7500 39.0000 L 162.0000 39.0000 L 161.2500 39.7500 L 161.2500 39.7500 L 161.2500 40.5000 L 160.5000 41.2500 L 161.2500 41.2500 L 161.2500 42.0000 L 161.2500 42.7500 L 162.0000 42.7500 L 162.7500 42.7500 L 162.7500 42.7500 L 163.5000 42.7500 L 164.2500 42.7500 L 164.2500 42.0000 L 165.0000 42.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 239.2500 142.5000 m 239.2500 148.5000 L 234.7500 144.7500 L 239.2500 142.5000 L F U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 239.2500 328.5000 m 245.2500 333.7500 L 291.7500 330.7500 L 323.2500 336.7500 L 329.2500 333.7500 L 323.2500 328.5000 L 312.7500 330.7500 L 281.2500 325.5000 L 239.2500 328.5000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 323.2500 328.5000 m 323.2500 272.2500 L 329.2500 277.5000 L 329.2500 333.7500 L 323.2500 328.5000 L B U u 0.000 0.000 0.000 0.000 k 239.2500 272.2500 m 281.2500 269.2500 L 312.7500 274.5000 L 323.2500 272.2500 L 323.2500 328.5000 L 312.7500 330.7500 L 281.2500 325.5000 L 239.2500 328.5000 L 239.2500 272.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 336.7500 182.2500 m 372.0000 182.2500 L 372.0000 193.5000 L 336.7500 193.5000 L 336.7500 182.2500 L F U 0 To 1.0000 0.0000 0.0000 1.0000 338.2500 185.2500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (message\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 1 j 334.5000 57.0000 m 369.0000 57.0000 L 369.0000 68.2500 L 334.5000 68.2500 L 334.5000 57.0000 L F U 0 To 1.0000 0.0000 0.0000 1.0000 335.2500 60.0000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (message\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 1 j 336.7500 291.7500 m 372.0000 291.7500 L 372.0000 303.0000 L 336.7500 303.0000 L 336.7500 291.7500 L F U 0 To 1.0000 0.0000 0.0000 1.0000 338.2500 294.7500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (message\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 1 j 267.7500 314.2500 m 267.7500 33.7500 L 253.5000 33.7500 L 281.2500 20.2500 L 309.7500 33.7500 L 295.5000 33.7500 L 295.5000 314.2500 L 267.7500 314.2500 L F U 0 To 0.0000 1.0000 -1.0000 0.0000 283.0525 123.7500 0 Tp TP /_Helvetica 11.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (Message stream\r) Tx TO 0.000 0.000 0.000 1.000 K %%PageTrailer gsave annotatepage grestore showpage %%Trailer Adobe_Illustrator_AI5 /terminate get exec Adobe_pattern_AI5 /terminate get exec Adobe_blend_AI5 /terminate get exec Adobe_ColorImage_AI6 /terminate get exec Adobe_typography_AI5 /terminate get exec Adobe_screens_AI5 /terminate get exec Adobe_level2_AI5 /terminate get exec %%EOF II* q(``8 9 x"iW!"#$&'_)E+,x./=1'223457}9:<= ?@@@=AoAACE2                               sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/images/sip-parser.gif000066400000000000000000000227771223300710500244050ustar00rootroot00000000000000GIF87a,@ڋ޼@≦:@L > ĢV*!`Jp+ٚ4ޥɠJ kOY!WhA&3w82IR ЙrF7j8& +yj{YPǠk26{ e:wCh im] ^*> Gx.!*fL/Zve`$V=7Hߊq:(8CW[E)Ȱ5rLFJ 6H86T91 ,o X>ңSʂYđ;"-nji\j2jquHLN+Iѵlɫ ul쉨8CJP9 tQ-oZ9 wYМ _MFӴm}Y\#sOI%ޱh\T.:2klZ`԰V W.sh-ϫȉ W@m2S]syLJ{w RMɧ]z0Ӟ`3k҇=.Q}]dEbFA9#Jɵaf4hv|:ϋ蓷=LP&gQfMPȚ:(zt雛f*'j +|يlv䑤z`kFg ] M$5 UE%B٧JO$>'%Zl;d6WY9辞*5.!7K}7`gp~ *SU/ Ëϋe-<ӗsci>onI#~A[u#+Y=9Q3^يvH9׷X>\Rc.:_mkγGmջ_W'nY̝o?-^ ?ʀ3 o s^R@%ZU>1@wS Ih YwBO wDՏv7l Wh`nq0$fPfAE2qGtF[En8bK0ù41ta\(Tj(ƌU2ÏԌC o Wq"B7^gq>D{OAH˕0!%ɇI!"G2Dp4!(]I-7#J n-|Ɇk|!?""ʀMޏa5esԎ'n10!}DJ:h WM(Gn/Tv:!т$g7Y|{ 4hPm'P@hƖ6 \O4тo"D(܁&2cJ&Mbӡ9 R[Hws$:hg;DTJ{"+%IcMz>o%$,T:XU3DP;QԃɅGp++j^Nea^ɊӮ^ԫH!7dA}̄G C~ VW 錧KՔȣmNJc:WՋv2iTQ|Jf谶^2vy4#UMUr$T ZB+DթiS9lQXؚ7W+ءrP)"I3Zos= kEۍ:ɻrz@%'!'W'0u'NdЯ><O(.-VUxE 0c|P|8|Z%}ZC;"}/Cd`ULRR^ePJ\im{g eV/<[GYI]l:O1êEϳbFja msֺ6.MopS*vί\u{hO㑔k}Ww!%% E],:\d.Ӹ~JlQ-7V5 Mk_K+܇l֙"7UL뮛^hy/үtKWz6 q-['[ .sC}I]sqܕ| 8$.Fs|'-QuKKyg#΋KdO_̠oWBްqoR{Hݾ[{l~l[ghzU|1z$W}5˕t]_&B%6#G;yg bnQπvw vzXwA}dVWYP-#R~xe%^eur'vwfMrOBy.bra 8z"A@v'w hz9s6J]46^.؀XLZXur4TLR%)|W!W$ lH:D^~QEU aavRp(gi"qF)hx[3I!0v5 hgGy/V~tg H8R?V4ȎVŒ/&Y^yt%H,S{Ii ؁vxJH /Xpח(iEIIXGr5MysҦ*ᆔ(Y j(#lr?VXU'}D$!RY{(i Ah->q {jCfX.CjPO)W9ro V'o)* ՜5ysVy,LIog O1XɞA)yq(y|c1!TZkbX\N ga89LP9.zE؞GV1I@nn9w=Aj9is)y; M#1j!@iJߖN lȁfy9ei =EX ٦l꥟;q v-p[y ZgVרzjJKj6~:zEtڟ\* *XfzUsbtŜ$L*6H zGAH9j*jW _Eria̵? rlƩgnV|뇏^8NbY{n$[}JY,Ǭˑz=ansNԷ<LJȉgyD̤콮 q͆ {QPۅzzh}lz\ ˟|NUVXfٺ\cۇ 8m1ly\hƀQA|L۪֤̖ N"=Ia OU߷SͶF,~Ž]4ĸ=-L84h-z]ո:Ր8.Xו ӋM晍׼,m}M͂(s]'L[y"6ՌGls.5̊꧵ ­-/ԥ =eZ,4pkuf،.ꎾ7>*@񌄩Vy^j'}WM`ɍ}į٦>ݎOɬ \q7U^p-̸tEJhkvȹVF5w^,'?^Ѓ[ c=+vԾ x[F֎>N/fzm}hܰKPUI51[8,aoAqtWjVql~!ae}cyu/=[)sWP* ȡ#Iwմ]P9ݏQT,M+/ cQEԷ0\ %WnFq B׮ENNقK,O -)țisA<rQ֒#11u ;DuRU8T)Xںzj)c"I/a9M^<䶥[-HݫAGu 6hc7*F^n%{ӕ3lyTCʉoV9~#AN\*&C8mlO[/ꪬ|h{w#*L'\6i'#_ʉNz o Iݭ59hyC\mɃb-SkI# si.Qx**B.4ϳ5t* &ĪA2Hq ODQE1AкhѻS4D J Ӣ$&7!;0;.%G;+jATS,J̒(A7P6RL\2!Hîv KT38ä,t=<0FJ7ɫTTT41I D "u۔8R5S]]I*YtT@E4MCEge҆Sڦ[?-l'vW7prkBY<-u`T {m[E8nJr[ݷ~ҝIˊ15T}}72FJTy%R4TIT3ߒyyLdhp!XdFzY"5~h4#bNkBQf_myF:(->>d{VhΔI|SC |g`Kmwbmμ"ڎkM}ZS7qתwAYsfok|#8bx?Syf4]z`@]t^.o`lvDp_vnc?}oy2MƇm4$FAL| _=i lG uZ]|L,=>:?) {s{ʖA zol`ѥ&0ސAD1D)NuVC$-:Rƺ)R)BG0is(F.αQfǠAs8["9Hy%XQ$1.$ R*.l}$aIRƔA8MC )8ղ_e*}wGrt yG,& EdYYogCV*#3ωr.t%(<]./7EˇL=OAΰ#tC|ytsKmpNb@ѕ vu˔s \y6'R#'uok[!"ioL;ֻ̿ ms2`yȺzD _٥GDXq-uJaտ]Id Bw`s |\88f-+|>𐑼>8;+$= m+b^6uVSF:@*xYQ&d܅|M&,ɎT[Molw*D5>MU(9,p&{UpZvNtS{\ka.D{8H.4Fj)o[hP /S-檒 M99Vmk(+g֨^-il6sv͝OUc֯A*U4;]\|\䖉f_yrw_:VW6zW}r!'mc"]vFmh|lHmCzjubw^5i$~ǂknN,A49 o;w1Щ<38ur+&流luhc{]ۓ"RK3n?_Ntzӻ{Ʋx!]fM\s+o~ $NnsS vK>G#@Nv>^۫&s=Ӱ6ut>/n0̇"?;>CG^e/Ћ//Mn|-(0H-nӧOL F!S<#5F!'Sh0#p,q1mqp1ڐp]ǰoMeqƑ>1,֑@2ģ)x  Q ;n1^6#?R,GRR,rD.&R%ӱ%׍^q&0p'u2&,~VZDOa !&YR/2*?j*0{RbD)%@S))((z2%#,/R1!0s S-2$r1%/)I2+3'g5Ӂ23/s/-(ES,AC4hF4G533(-6?pBN .26g4ׄ3AjђX7.NL:۸O%+<S/1+389M*œ9>+R@{r s1X&A ؾ?T--ţӡ$|FHFuG{<&YDw;ZjF2Im3#JPrB1@JKE=($(/1JI54.M#γPBn@OLt7+L NN!`5Ht>QtNiP-T_P ?0Q!R!>AACtS݇PqeQE56iTSK7Is5_V 5V;?)UN4TuHEhF)NS/U%5k7狶̬lXQo5Z#k5JQǔT\G!M}GCܓp|5X[S]]ݸgXY#]>V]L/ب4T׵a5a3u,UJ_]biU9KOĮs'bUa=`.e9$NQ.VeWPef_k[qgs}>fTVhsYVZC?eco6jmi%jkhi vbVHqcKBPPki6Ld* nVn+1USeloA 9loTVVmwI7̶T'R+39s3N7>) }{ (counttomark 2 idiv dup dict begin {def} repeat pop currentdict end) } ifelse cvx def _level2PS{ initializeLev2 }{ initializeLev1 }ifelse queryDevice initializeShading initializeOps _producingSeps{ AGM_Gradient_Sep/initialize get exec }{ initializeComposite }ifelse _illustrator{ /f{}def /F{}def /s{}def /S{}def /b{}def /B{}def }if /image where{ /image get /_image xd }if /colorimage where{ /colorimage get /_colorimage xd }if /rectfill where dup{ exch pop not _producingSeps or }{ not }ifelse { /rectfill{ gsave newpath 4 2 roll moveto 1 index 0 rlineto 0 1 index rlineto 1 index neg 0 rlineto pop pop closepath fill grestore }def }if /linealImage _noImage{ /rectImage load }{ _producingSeps{ AGM_Gradient_Sep/AGM_Gradient_Sep_private get begin /rampImage load end }{ /rampImage load }ifelse }ifelse def AGM_Gradient_private { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall AGM_Gradient { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall end currentdict readonly pop end }def /initializeAI { pop pop AGM_Gradient/AGM_Gradient_private get /_illustrator true put AGM_Gradient/initialize get exec AGM_Gradient begin }def /unload{ systemdict/languagelevel known{ systemdict/languagelevel get 2 ge{ userdict/AGM_Gradient_Sep 2 copy known{ undef }{ pop pop }ifelse userdict/AGM_Gradient 2 copy known{ undef }{ pop pop }ifelse }if }if }def /terminate{ currentdict AGM_Gradient eq{ end }if }def AGM_Gradient_private begin /initializeVars{ /_d255 256 array def 0 1 255{ _d255 exch dup 255 div put }bind for /_d255- 256 array def 0 1 255{ _d255- exch 1 _d255 2 index get sub put }bind for /_sSave nd /_dUserSpace matrix defaultmatrix def /_bUMatrix matrix def /_imageMatrix matrix def /_saveMatrix matrix def /_xm matrix def /_ccAry1 5 array def /_level2PS systemdict/languagelevel known dup{ pop systemdict/languagelevel get 2 ge }if def /_level3PS _level2PS systemdict/shfill known and def currentdict /_illustrator known not{ /_illustrator false def }if }def /initializeOps { AGM_Gradient begin currentdict/Bc known not{ /Bc{ _renderFlag 2 eq{ 6 npop }{ pushBSpace _rampIndex 0 eq{ pop pop setCStop }if linealFill popBSpace }ifelse }def }if currentdict/Bg known not{ /Bg{ 10 npop /_gradName xp /_renderFlag xp _renderFlag 2 ne{ _illustrator{ _of setoverprint }if _illustrator _eo and _renderFlag 3 eq or{ eoclip }{ clip }ifelse _gradNames _gradName 2 copy known{ get mark exch aload pop /_gradType xp 1 sub dup /_rampIndex xp /_maxRampIndex xp mark exch aload pop 0 0 }if pop pop getRampData }{ mark mark }ifelse }def }if currentdict/Bm known not{ /Bm{ _renderFlag 2 ne{ _gradType 0 eq{ linealRamp }{ radialGrad }ifelse }{ 6 npop }ifelse }def }if currentdict/Bh known not{ /Bh{ 2 npop /_yHi xp /_xHi xp /_radHilite _xHi 0 ne _yHi 0 ne or pt }def }if currentdict/Bn known not{ /Bn{ AGM_Gradient_private begin dict /_gradNames xp end }def }if currentdict/Bd known not{ /Bd{ AGM_Gradient begin AGM_Gradient_private begin /_nColorsBd xp /_gradType xp /_gradName xp }def }if currentdict/BD known not{ /BD{ currentdict/_gradNames known not{ /_gradNames 20 dict def }if ] _nColorsBd _gradType ] _gradName exch /_gradNames xput end end }def }if currentdict/Bb known not{ /Bb{ AGM_Gradient begin AGM_Gradient_private begin _producingSeps{ AGM_Gradient_Sep/AGM_Gradient_Sep_private get begin }if mySave }def }if currentdict/BB known not{ /BB{ /_tmp xp cleartomark cleartomark _tmp dup _renderFlag myRestore _producingSeps{ end }if _illustrator end end { 2 ne exch 0 gt and{ 2 eq{ s }{ S }ifelse }{ pop newpath }ifelse }{ pop newpath }ifelse }def }if currentdict/Xm known not{ /Xm{ _xm astore pop }def }if end }def /queryDevice{ /_inRipSep _level2PS{ currentpagedevice/Separations 2 copy known{ get }{ pop pop false }ifelse }{ false }ifelse def /_noImage /lv1Fix where{ pop lv1Fix }{ false }ifelse def /_useShells where{ pop }{ /_useShells true def }ifelse /_useSmoothShade where{ pop }{ /_useSmoothShade false def }ifelse /_cyanPlate 1 0 0 0 testCMYKColorThrough def /_magentaPlate 0 1 0 0 testCMYKColorThrough def /_yellowPlate 0 0 1 0 testCMYKColorThrough def /_blackPlate 0 0 0 1 testCMYKColorThrough def /_compositeJob _cyanPlate _magentaPlate and _yellowPlate and _blackPlate and def /_compositeSpotDevice where{ pop }{ /_compositeSpotDevice _compositeJob not _inRipSep or{ 1 }{ 0 }ifelse def }ifelse /_producingSeps _compositeSpotDevice 0 ne def /_deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt def /_dpiThreshold where{ pop }{ /_dpiThreshold 600 def }ifelse /_screenFreqThreshold where{ pop }{ /_screenFreqThreshold 150 def }ifelse /_contoneDevice where{ pop }{ /_contoneDevice false def }ifelse /_subSampleOK _deviceDPI _dpiThreshold le currentScreenFreq _screenFreqThreshold le and _contoneDevice not and _producingSeps not and def }def /initializeLev1{ /makeByte8{ /_tmp 0 pt 255 mul cvi 8 string 8{ dup _tmp 3 index put /_tmp _tmp 1 add pt }repeat exch pop }def /currentScreenFreq{ currentscreen pop pop }def /_byte 1 string def /colorimage where{ pop }{ /colorimage{ pop pop /_blackTmp xp /_yellowTmp xp /_magentaTmp xp /_cyanTmp xp /_cnt 0 pt [ _byte dup 0 _cyanTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .3 /mul cvx _magentaTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .59 /mul cvx _yellowTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .11 /mul cvx _blackTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx /add cvx /add cvx /add cvx 1 /exch cvx /sub cvx /dup cvx 0 /lt cvx{ pop 0 }/if cvx /dup cvx 1 /gt cvx{ pop 1 }/if cvx 255 /mul cvx /cvi cvx 256 /mod cvx /dup cvx 0 /lt cvx{ pop 0 }/if cvx /put cvx /_cnt dup cvx 1 /add cvx /pt cvx ] cvx bind /_image load 5 execImage }def }ifelse }def /initializeLev2{ /level2ScreenFreq{ begin 60 HalftoneType 1 eq{ pop Frequency }if HalftoneType 2 eq{ pop GrayFrequency }if HalftoneType 5 eq{ pop Default level2ScreenFreq }if end }def /currentScreenFreq{ currenthalftone level2ScreenFreq }def }def /initializeShading{ _useSmoothShade _level3PS and{ /_usingSmoothShade true pt initializeLev3_Ops }{ /_usingSmoothShade false pt }ifelse }def /initializeLev3_Ops { /initShFill{ /_index _gradType 0 eq {0}{_maxRampIndex 1 sub} ifelse pt /_rampFuncsArray _maxRampIndex array pt /_boundsArray _maxRampIndex 1 sub array pt /_encodeArray _maxRampIndex 2 mul array pt /_beginCoord _rampPoint pt /_colorSpace null pt /_firstFill _rampIndex _maxRampIndex eq pt /_lastFill false pt }def /getRampColorSpace{ _nSamples 1 gt{ /_ndx 0 pt [blendColor] cvx exec }if /_C0 [currentcolor] pt /_C0_Space currentcolorspace pt _nSamples 1 gt{ /_ndx _nSamples 1 sub pt [blendColor] cvx exec }if /_C1 [currentcolor] pt /_C1_Space currentcolorspace pt _C0_Space _C1_Space eq{ /_rampColorSpace _C0_Space pt }{ (colorspace conflict!) == showpage stop }ifelse _spotColor{ nsetcustomcolorend }if }def /linealShFill{ popBSpace _xm aload pop pushBSpace /_size _index 1 add pt _size _maxRampIndex lt { /_rampFuncsArray _rampFuncsArray 0 _size getinterval pt /_boundsArray _boundsArray 0 _size 1 sub getinterval pt /_encodeArray _encodeArray 0 _size 2 mul getinterval pt }if bd /ShadingType 2 /ColorSpace _colorSpace /Function bd /FunctionType 3 /Domain [0 1] /Functions _rampFuncsArray /Bounds _boundsArray /Encode _encodeArray ed /Extend [_firstFill _lastFill] /Domain [0 1] /Coords [_beginCoord 0 _endCoord 0] ed shfill }def /radialShFill{ /_size _maxRampIndex _index sub pt _size _maxRampIndex lt { /_rampFuncsArray _rampFuncsArray _index _size getinterval pt /_boundsArray _boundsArray _index _size 1 sub getinterval pt /_encodeArray _encodeArray _index 2 mul _size 2 mul getinterval pt }if /_rampLen _beginCoord _endCoord sub pt bd /ShadingType 3 /ColorSpace _colorSpace /Function bd /FunctionType 3 /Domain [0 1] /Functions _rampFuncsArray /Bounds _boundsArray /Encode _encodeArray ed /Extend [_lastFill _firstFill] /Domain [0 1] /Coords [_xHi _rampLen mul _yHi _rampLen mul _endCoord 0 0 _beginCoord] ed shfill _radHilite{ _xHi _rampLen mul _yHi _rampLen mul translate }if }def /fillRamp{ /_invert _midPoint 0.5 lt pt _rampIndex _maxRampIndex eq { initShFill }if getRampColorSpace _colorSpace null eq{ /_colorSpace _rampColorSpace pt }{ _colorSpace _rampColorSpace ne{ /_index _index 1 _gradType 0 eq{ sub pt linealShFill }{ add pt radialShFill }ifelse initShFill /_colorSpace _rampColorSpace pt } if }ifelse /_endCoord _endPoint pt _rampFuncsArray _index bd /FunctionType 2 /Domain [0 1] /N 0.5 log _invert{1 _midPoint sub}{_midPoint}ifelse log div _gradType 0 eq{ _invert{/C1}{/C0}ifelse _C0 _invert{/C0}{/C1}ifelse _C1 }{ _invert{/C0}{/C1}ifelse _C1 _invert{/C1}{/C0}ifelse _C0 }ifelse ed put _rampIndex 1 ne{ _boundsArray _index _gradType 1 eq{1 sub}if _endCoord put } if 0 1 _invert {exch}if _encodeArray _index 2 mul 1 add 3 -1 roll put _encodeArray _index 2 mul 3 -1 roll put _rampIndex 1 eq { /_lastFill true pt _gradType 0 eq{ linealShFill }{ radialShFill }ifelse }if /_index _index 1 _gradType 0 eq{ add pt }{ sub pt }ifelse }def /radialRamp /fillRamp load def /rampImage /fillRamp load def AGM_Gradient begin /Bc{ 6 npop }def end }def /initializeComposite{ /bwImage{ pop /_image load 5 execImage }def currentdict/rampImage known not{ /rampImage{ _color{ _nSamples setImageParms _rgbRamp{ _redData _greenData _blueData _nSamples 3 expandColor true 3 null ncolorimage }{ _cyanData _magentaData _yellowData _blackData _nSamples 4 expandColor true 4 null ncolorimage }ifelse }{ _nSamples setImageParms _blackData null bwImage }ifelse }def }if /setCStop{ /_colorStyle exch pt _colorStyle 0 eq{ 1 exch sub 0 0 0 4 -1 roll }if _colorStyle 2 eq{ setrgbcolor 4 npop }if _colorStyle 3 eq{ 1 exch sub /_tmp xp pop 4{ _tmp mul 4 1 roll }repeat }if _colorStyle 4 eq{ 3 -1 roll pop pop 1 exch sub /_tmp xp 3{ 1 exch sub _tmp mul 1 exch sub 3 1 roll }repeat setrgbcolor 4 npop }if _colorStyle 2 ne _colorStyle 4 ne and{ null nsetcustomcolor }if }def /nsetcustomcolor { pop setcmykcolor }def /nsetcustomcolorend { }def /ncolorimage{ pop /_colorimage load 10 execImage }def _noImage not _level2PS not and{ /linealFill{ 8 setImageParms _color{ currentcmykcolor 4{ makeByte8 4 1 roll }repeat true 4 null ncolorimage }{ currentgray makeByte8 null bwImage }ifelse }def }if }def /npop{ {pop}repeat }def /xd{ exch def }def /nd{ null def }def /pt{ AGM_Gradient_private 3 1 roll put }def /xp{ exch pt }def /xput{ dup load dup length exch maxlength eq{ dup dup load dup length 2 mul dict copy def }if load begin def end }def /mySave{ save /_sSave xp }def /myRestore{ _sSave type /savetype eq{ _sSave restore }if }def /gMark{ counttomark 2 add -1 roll }def /execImage{ /_tmp xp { exec }stopped{ $error /errorname get /undefinedresult ne{ stop }{ _tmp npop }ifelse }if }def /pushBSpace{ newpath gsave _bUMatrix astore concat }def /popBSpace{ grestore }def /setImageParms{ 1 8 2 index 0 0 1 0 0 _imageMatrix astore }def /linealFill{ 0 0 1 1 rectfill }def /testCMYKColorThrough{ gsave setcmykcolor currentcmykcolor grestore add add add 0 ne }def /expandOne { /_tmp xp dup type /stringtype ne{ _tmp string exch dup 0 ne{ 255 mul cvi 0 1 _tmp 1 sub{ 3 copy exch put pop }for }if pop }if }def /expandColor{ /_channels xp /_len xp _channels{ _len expandOne _channels 1 roll }repeat }def /blendColor{ _color{ _rgbRamp _producingSeps not and{ _redData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _greenData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _blueData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if /setrgbcolor cvx }{ _cyanData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _magentaData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _yellowData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _blackData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _spotColor{ _rampSD begin /_rampSD cvx /begin cvx spot1 begin tintImage dup type /stringtype eq{ /_ndx cvx /get cvx _d255- /exch cvx /get cvx }{ dup null ne{ name type /nametype ne{ 1 exch sub }if }if }ifelse end /spot1 cvx /tintValue 3 -1 /roll cvx /put cvx spot2 begin tintImage dup type /stringtype eq{ /_ndx cvx /get cvx _d255- /exch cvx /get cvx }{ dup null ne{ name type /nametype ne{ 1 exch sub }if }if }ifelse end /spot2 cvx /tintValue 3 -1 /roll cvx /put cvx /end cvx end /_rampSD cvx /nsetcustomcolor cvx }{ /setcmykcolor cvx }ifelse }ifelse }{ _blackData /_ndx cvx /get cvx _d255 /exch cvx /get cvx _usingSmoothShade{ 1 /exch cvx /sub cvx 0 0 0 4 -1 /roll cvx /setcmykcolor cvx }{ /setgray cvx }ifelse }ifelse }def /linealRamp{ pushBSpace _ramp{ linealImage }{ linealFill }ifelse popBSpace /_rampIndex _rampIndex 1 sub pt _rampIndex 0 gt{ getRampData }if }def /radialGrad{ /_firstShell true pt _usingSmoothShade not{ fill }if pushBSpace _radHilite{ _xHi _yHi _bUMatrix idtransform /_yHi xp /_xHi xp _rampPoint 1 lt{ 1 _rampPoint sub dup _xHi mul exch _yHi mul translate }if }if _rampIndex{ radialRamp /_rampIndex _rampIndex 1 sub pt _rampIndex 0 gt{ getRampData }if }repeat popBSpace }def /getNSamples{ 0 exch { dup type /stringtype eq{ length exch pop exit }if pop }forall dup 0 eq{ pop 1 }if }def /getRampData{ /_rampType gMark pt /_color _rampType 0 gt pt /_ccRGB _rampType 5 eq _rampType 6 eq or pt /_rgbRamp _rampType 4 eq _ccRGB or pt /_ccProcess _rampType 2 eq _rampType 3 eq or pt _producingSeps{ _rampSD initSpotDict /_spotColor _ccProcess _ccRGB or pt }{ /_spotColor false pt }ifelse /_ramp true pt 100 div /_rampPoint xp 100 div /_midPoint xp dup /_colorStyle xp _colorStyle 0 eq{ 2 }{ _colorStyle 1 eq{ 5 }{ _colorStyle 2 eq{ 8 }{ _colorStyle 3 eq{ _producingSeps{ _rampSD begin spot1 begin /name 3 index def /spot_K 4 index def /spot_Y 5 index def /spot_M 6 index def /spot_C 7 index def end end }if 7 }{ _producingSeps{ _rampSD begin spot1 begin /name 4 index def /spot_K 8 index def /spot_Y 9 index def /spot_M 10 index def /spot_C 11 index def end end }if 11 } ifelse }ifelse }ifelse }ifelse /_tmp xp _tmp index 100 div /_endPoint xp _gradType 1 eq{ _tmp 1 add index 100 div /_midPoint xp }if _producingSeps{ _tmp 2 add index /_nextColorStyle xp _nextColorStyle 3 eq{ /_tmp _tmp 4 add pt _tmp index dup _rampSD begin spot1 /name get ne{ spot2 begin /name xd /spot_K _tmp 2 add index def /spot_Y _tmp 3 add index def /spot_M _tmp 4 add index def /spot_C _tmp 5 add index def end }{ pop }ifelse end }if _nextColorStyle 4 eq{ /_tmp _tmp 5 add pt _tmp index dup _rampSD begin spot1 /name get ne{ spot2 begin /name xd /spot_K _tmp 5 add index def /spot_Y _tmp 6 add index def /spot_M _tmp 7 add index def /spot_C _tmp 8 add index def end }{ pop }ifelse end }if }if _rampType 3 eq _rampType 6 eq or{ /_tint2Data gMark pt }if _ccProcess _ccRGB or{ /_tint1Data gMark pt }if _rgbRamp{ /_blueData gMark pt /_greenData gMark pt /_redData gMark pt }if _producingSeps{ _rampSD begin _ccProcess _ccRGB or{ _rampType 3 eq _rampType 6 eq or{ spot2 begin /tintImage _gradType 0 eq{ _tint2Data }{ _tint1Data }ifelse def name null eq{ /name /Black def }if end }if spot1 begin /tintImage _gradType 0 eq _rampType 2 eq or _rampType 5 eq or{ _tint1Data }{ _tint2Data }ifelse def _rampType 2 eq _rampType 5 eq or{ name null eq{ /name spot2 /name get def spot2 /name null put }if }{ name null eq{ /name /Black def }if }ifelse end }if end }if /_blackData gMark pt _rampType 0 gt{ counttomark 4 add -3 roll /_yellowData xp /_magentaData xp /_cyanData xp }if _ramp{ /_nSamples [ _rampType 0 eq {_blackData}if _rampType 1 eq {_cyanData _magentaData _yellowData _blackData}if _rampType 2 eq {_cyanData _magentaData _yellowData _blackData _tint1Data}if _rampType 3 eq {_cyanData _magentaData _yellowData _blackData _tint1Data _tint2Data}if _rampType 4 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData}if _rampType 5 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData _tint1Data}if _rampType 6 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData _tint1Data _tint2Data}if ] getNSamples pt _usingSmoothShade not {/_ramp _nSamples 1 gt pt} if } if setCStop }def /rectImage{ gsave /_sInc 1 pt /_bInc 1 _nSamples div pt /_uRampLen 1 0 dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt pt /_pChange _uRampLen 0 eq{0}{_nSamples _uRampLen div}ifelse pt 0 _nSamples [ /dup cvx /_ndx /exch cvx /pt cvx blendColor 0 0 _bInc 1 /rectfill cvx _bInc 0 /translate cvx _sInc /add cvx ] cvx bind repeat pop _spotColor{ nsetcustomcolorend }if grestore }def /radialInit{ /_nRadSamples _nSamples dup 0 eq{pop 1}if pt /_sInc -1 pt /_rampLen _rampPoint _endPoint sub pt /_bInc _rampLen _nSamples div neg pt /_optimize false pt _subSampleOK{ /_uRampLen _rampLen 0 dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt 0 _rampLen dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt 2 copy lt{ exch }if pop pt /_pChange _uRampLen 0 eq{ 0 }{ _nSamples _uRampLen div }ifelse pt _pChange .5 gt dup /_optimize xp{ /_nRadSamples _uRampLen 2 div round cvi dup 1 le{pop 2}if pt /_bInc _rampLen _nRadSamples div neg pt /_sInc _nSamples 1 sub _nRadSamples 1 sub div neg pt }if }if _radHilite{ /_xBCInc _xHi _rampLen mul _nRadSamples div pt /_yBCInc _yHi _rampLen mul _nRadSamples div pt }if }def currentdict/radialRamp known not{ /radialRamp{ /_saveMatrix _saveMatrix currentmatrix def radialInit _rampPoint _nSamples 1 sub _nRadSamples [ /dup cvx _optimize{ /round cvx /cvi cvx }if /_ndx /exch cvx /pt cvx _useShells{ /_firstShell cvx{ /_firstShell false pt }{ 0 0 3 index 360 0 arcn fill }/ifelse cvx }if blendColor _useShells{ 0 0 3 /index cvx 0 360 /arc cvx }{ 0 0 3 /index cvx 0 360 /arc cvx /fill cvx }ifelse /exch cvx _bInc /add cvx /exch cvx _sInc /add cvx _radHilite{ _xBCInc _yBCInc /translate cvx }if ] cvx bind repeat pop pop _saveMatrix setmatrix _radHilite{ _xHi _rampLen mul _yHi _rampLen mul translate }if _useShells _rampIndex 1 eq and{ fill }if _spotColor{ nsetcustomcolorend }if }def }if end end defaultpacking setpacking %%EndResource %%BeginProcSet: Adobe_ColorImage_AI6 1.1 0 userdict /Adobe_ColorImage_AI6 known not { userdict /Adobe_ColorImage_AI6 24 dict put } if userdict /Adobe_ColorImage_AI6 get begin /initialize { Adobe_ColorImage_AI6 begin Adobe_ColorImage_AI6 { dup type /arraytype eq { dup xcheck { bind } if } if pop pop } forall } def /terminate { end } def currentdict /Adobe_ColorImage_AI6_Vars known not { /Adobe_ColorImage_AI6_Vars 15 dict def } if Adobe_ColorImage_AI6_Vars begin /channelcount 0 def /sourcecount 0 def /sourcearray 4 array def /plateindex -1 def /XIMask 0 def /XIBinary 0 def /XIChannelCount 0 def /XIBitsPerPixel 0 def /XIImageHeight 0 def /XIImageWidth 0 def /XIImageMatrix null def /XIBuffer null def /XIDataProc null def /XIVersion 6 def end /WalkRGBString null def /WalkCMYKString null def /StuffRGBIntoGrayString null def /RGBToGrayImageProc null def /StuffCMYKIntoGrayString null def /CMYKToGrayImageProc null def /ColorImageCompositeEmulator null def /SeparateCMYKImageProc null def /FourEqual null def /TestPlateIndex null def currentdict /_colorimage known not { /colorimage where { /colorimage get /_colorimage exch def } { /_colorimage null def } ifelse } if /_currenttransfer systemdict /currenttransfer get def /colorimage null def /XI null def /WalkRGBString { 0 3 index dup length 1 sub 0 3 3 -1 roll { 3 getinterval { } forall 5 index exec 3 index } for 5 { pop } repeat } def /WalkCMYKString { 0 3 index dup length 1 sub 0 4 3 -1 roll { 4 getinterval { } forall 6 index exec 3 index } for 5 { pop } repeat } def /StuffRGBIntoGrayString { .11 mul exch .59 mul add exch .3 mul add cvi 3 copy put pop 1 add } def /RGBToGrayImageProc { Adobe_ColorImage_AI6_Vars begin sourcearray 0 get exec dup length 3 idiv string dup 3 1 roll /StuffRGBIntoGrayString load exch WalkRGBString end } def /StuffCMYKIntoGrayString { exch .11 mul add exch .59 mul add exch .3 mul add dup 255 gt { pop 255 } if 255 exch sub cvi 3 copy put pop 1 add } def /CMYKToGrayImageProc { Adobe_ColorImage_AI6_Vars begin sourcearray 0 get exec dup length 4 idiv string dup 3 1 roll /StuffCMYKIntoGrayString load exch WalkCMYKString end } def /ColorImageCompositeEmulator { pop true eq { Adobe_ColorImage_AI6_Vars /sourcecount get 5 add { pop } repeat } { Adobe_ColorImage_AI6_Vars /channelcount get 1 ne { Adobe_ColorImage_AI6_Vars begin sourcearray 0 3 -1 roll put channelcount 3 eq { /RGBToGrayImageProc } { /CMYKToGrayImageProc } ifelse load end } if image } ifelse } def /SeparateCMYKImageProc { Adobe_ColorImage_AI6_Vars begin sourcecount 0 ne { sourcearray plateindex get exec } { sourcearray 0 get exec dup length 4 idiv string 0 2 index plateindex 4 2 index length 1 sub { get 255 exch sub 3 copy put pop 1 add 2 index } for pop pop exch pop } ifelse end } def /FourEqual { 4 index ne { pop pop pop false } { 4 index ne { pop pop false } { 4 index ne { pop false } { 4 index eq } ifelse } ifelse } ifelse } def /TestPlateIndex { Adobe_ColorImage_AI6_Vars begin /plateindex -1 def /setcmykcolor where { pop gsave 1 0 0 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 1 0 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 0 1 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 0 0 1 setcmykcolor systemdict /currentgray get exec 1 exch sub grestore 1 0 0 0 FourEqual { /plateindex 0 def } { 0 1 0 0 FourEqual { /plateindex 1 def } { 0 0 1 0 FourEqual { /plateindex 2 def } { 0 0 0 1 FourEqual { /plateindex 3 def } { 0 0 0 0 FourEqual { /plateindex 5 def } if } ifelse } ifelse } ifelse } ifelse pop pop pop pop } if plateindex end } def /colorimage { Adobe_ColorImage_AI6_Vars begin /channelcount 1 index def /sourcecount 2 index 1 eq { channelcount 1 sub } { 0 } ifelse def 4 sourcecount add index dup 8 eq exch 1 eq or not end { /_colorimage load null ne { _colorimage } { Adobe_ColorImage_AI6_Vars /sourcecount get 7 add { pop } repeat } ifelse } { dup 3 eq TestPlateIndex dup -1 eq exch 5 eq or or { /_colorimage load null eq { ColorImageCompositeEmulator } { dup 1 eq { pop pop image } { Adobe_ColorImage_AI6_Vars /plateindex get 5 eq { gsave 0 _currenttransfer exec 1 _currenttransfer exec eq { 0 _currenttransfer exec 0.5 lt } { 0 _currenttransfer exec 1 _currenttransfer exec gt } ifelse { { pop 0 } } { { pop 1 } } ifelse systemdict /settransfer get exec } if _colorimage Adobe_ColorImage_AI6_Vars /plateindex get 5 eq { grestore } if } ifelse } ifelse } { dup 1 eq { pop pop image } { pop pop Adobe_ColorImage_AI6_Vars begin sourcecount -1 0 { exch sourcearray 3 1 roll put } for /SeparateCMYKImageProc load end systemdict /image get exec } ifelse } ifelse } ifelse } def /XG { pop pop } def /XF { 13 {pop} repeat } def /Xh { Adobe_ColorImage_AI6_Vars begin gsave /XIMask exch 0 ne def /XIImageHeight exch def /XIImageWidth exch def /XIImageMatrix exch def 0 0 moveto XIImageMatrix concat XIImageWidth XIImageHeight scale XIMask { /_lp /null ddef _fc /_lp /imagemask ddef } if /XIVersion 7 def end } def /XH { Adobe_ColorImage_AI6_Vars begin /XIVersion 6 def grestore end } def /XI { Adobe_ColorImage_AI6_Vars begin gsave /XIMask exch 0 ne def /XIBinary exch 0 ne def pop pop /XIChannelCount exch def /XIBitsPerPixel exch def /XIImageHeight exch def /XIImageWidth exch def pop pop pop pop /XIImageMatrix exch def XIBitsPerPixel 1 eq { XIImageWidth 8 div ceiling cvi } { XIImageWidth XIChannelCount mul } ifelse /XIBuffer exch string def XIBinary { /XIDataProc { currentfile XIBuffer readstring pop } def XIVersion 6 le { currentfile 128 string readline pop pop } if } { /XIDataProc { currentfile XIBuffer readhexstring pop } def } ifelse XIVersion 6 le { 0 0 moveto XIImageMatrix concat XIImageWidth XIImageHeight scale XIMask { /_lp /null ddef _fc /_lp /imagemask ddef } if } if XIMask { XIImageWidth XIImageHeight false [ XIImageWidth 0 0 XIImageHeight neg 0 0 ] /XIDataProc load imagemask } { XIImageWidth XIImageHeight XIBitsPerPixel [ XIImageWidth 0 0 XIImageHeight neg 0 0 ] /XIDataProc load XIChannelCount 1 eq { gsave 0 setgray image grestore } { false XIChannelCount colorimage } ifelse } ifelse grestore end } def end %%EndProcSet %%BeginResource: procset Adobe_Illustrator_AI5 1.1 0 %%Title: (Adobe Illustrator (R) Version 5.0 Full Prolog) %%Version: 1.1 0 %%CreationDate: (3/7/1994) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_Illustrator_AI5_vars 81 dict dup begin put /_eo false def /_lp /none def /_pf { } def /_ps { } def /_psf { } def /_pss { } def /_pjsf { } def /_pjss { } def /_pola 0 def /_doClip 0 def /cf currentflat def /_tm matrix def /_renderStart [ /e0 /r0 /a0 /o0 /e1 /r1 /a1 /i0 ] def /_renderEnd [ null null null null /i1 /i1 /i1 /i1 ] def /_render -1 def /_rise 0 def /_ax 0 def /_ay 0 def /_cx 0 def /_cy 0 def /_leading [ 0 0 ] def /_ctm matrix def /_mtx matrix def /_sp 16#020 def /_hyphen (-) def /_fScl 0 def /_cnt 0 def /_hs 1 def /_nativeEncoding 0 def /_useNativeEncoding 0 def /_tempEncode 0 def /_pntr 0 def /_tDict 2 dict def /_wv 0 def /Tx { } def /Tj { } def /CRender { } def /_AI3_savepage { } def /_gf null def /_cf 4 array def /_if null def /_of false def /_fc { } def /_gs null def /_cs 4 array def /_is null def /_os false def /_sc { } def /_pd 1 dict def /_ed 15 dict def /_pm matrix def /_fm null def /_fd null def /_fdd null def /_sm null def /_sd null def /_sdd null def /_i null def /discardSave null def /buffer 256 string def /beginString null def /endString null def /endStringLength null def /layerCnt 1 def /layerCount 1 def /perCent (%) 0 get def /perCentSeen? false def /newBuff null def /newBuffButFirst null def /newBuffLast null def /clipForward? false def end userdict /Adobe_Illustrator_AI5 known not { userdict /Adobe_Illustrator_AI5 91 dict put } if userdict /Adobe_Illustrator_AI5 get begin /initialize { Adobe_Illustrator_AI5 dup begin Adobe_Illustrator_AI5_vars begin discardDict { bind pop pop } forall dup /nc get begin { dup xcheck 1 index type /operatortype ne and { bind } if pop pop } forall end newpath } def /terminate { end end } def /_ null def /ddef { Adobe_Illustrator_AI5_vars 3 1 roll put } def /xput { dup load dup length exch maxlength eq { dup dup load dup length 2 mul dict copy def } if load begin def end } def /npop { { pop } repeat } def /sw { dup length exch stringwidth exch 5 -1 roll 3 index mul add 4 1 roll 3 1 roll mul add } def /swj { dup 4 1 roll dup length exch stringwidth exch 5 -1 roll 3 index mul add 4 1 roll 3 1 roll mul add 6 2 roll /_cnt 0 ddef { 1 index eq { /_cnt _cnt 1 add ddef } if } forall pop exch _cnt mul exch _cnt mul 2 index add 4 1 roll 2 index add 4 1 roll pop pop } def /ss { 4 1 roll { 2 npop (0) exch 2 copy 0 exch put pop gsave false charpath currentpoint 4 index setmatrix stroke grestore moveto 2 copy rmoveto } exch cshow 3 npop } def /jss { 4 1 roll { 2 npop (0) exch 2 copy 0 exch put gsave _sp eq { exch 6 index 6 index 6 index 5 -1 roll widthshow currentpoint } { false charpath currentpoint 4 index setmatrix stroke } ifelse grestore moveto 2 copy rmoveto } exch cshow 6 npop } def /sp { { 2 npop (0) exch 2 copy 0 exch put pop false charpath 2 copy rmoveto } exch cshow 2 npop } def /jsp { { 2 npop (0) exch 2 copy 0 exch put _sp eq { exch 5 index 5 index 5 index 5 -1 roll widthshow } { false charpath } ifelse 2 copy rmoveto } exch cshow 5 npop } def /pl { transform 0.25 sub round 0.25 add exch 0.25 sub round 0.25 add exch itransform } def /setstrokeadjust where { pop true setstrokeadjust /c { curveto } def /C /c load def /v { currentpoint 6 2 roll curveto } def /V /v load def /y { 2 copy curveto } def /Y /y load def /l { lineto } def /L /l load def /m { moveto } def } { /c { pl curveto } def /C /c load def /v { currentpoint 6 2 roll pl curveto } def /V /v load def /y { pl 2 copy curveto } def /Y /y load def /l { pl lineto } def /L /l load def /m { pl moveto } def } ifelse /d { setdash } def /cf { } def /i { dup 0 eq { pop cf } if setflat } def /j { setlinejoin } def /J { setlinecap } def /M { setmiterlimit } def /w { setlinewidth } def /XR { 0 ne /_eo exch ddef } def /H { } def /h { closepath } def /N { _pola 0 eq { _doClip 1 eq { _eo {eoclip} {clip} ifelse /_doClip 0 ddef } if newpath } { /CRender { N } ddef } ifelse } def /n { N } def /F { _pola 0 eq { _doClip 1 eq { gsave _pf grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _fc /_doClip 0 ddef } { _pf } ifelse } { /CRender { F } ddef } ifelse } def /f { closepath F } def /S { _pola 0 eq { _doClip 1 eq { gsave _ps grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _sc /_doClip 0 ddef } { _ps } ifelse } { /CRender { S } ddef } ifelse } def /s { closepath S } def /B { _pola 0 eq { _doClip 1 eq gsave F grestore { gsave S grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _sc /_doClip 0 ddef } { S } ifelse } { /CRender { B } ddef } ifelse } def /b { closepath B } def /W { /_doClip 1 ddef } def /* { count 0 ne { dup type /stringtype eq { pop } if } if newpath } def /u { } def /U { } def /q { _pola 0 eq { gsave } if } def /Q { _pola 0 eq { grestore } if } def /*u { _pola 1 add /_pola exch ddef } def /*U { _pola 1 sub /_pola exch ddef _pola 0 eq { CRender } if } def /D { pop } def /*w { } def /*W { } def /` { /_i save ddef clipForward? { nulldevice } if 6 1 roll 4 npop concat pop userdict begin /showpage { } def 0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit [] 0 setdash /setstrokeadjust where {pop false setstrokeadjust} if newpath 0 setgray false setoverprint } def /~ { end _i restore } def /O { 0 ne /_of exch ddef /_lp /none ddef } def /R { 0 ne /_os exch ddef /_lp /none ddef } def /g { /_gf exch ddef /_fc { _lp /fill ne { _of setoverprint _gf setgray /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /G { /_gs exch ddef /_sc { _lp /stroke ne { _os setoverprint _gs setgray /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /k { _cf astore pop /_fc { _lp /fill ne { _of setoverprint _cf aload pop setcmykcolor /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /K { _cs astore pop /_sc { _lp /stroke ne { _os setoverprint _cs aload pop setcmykcolor /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /x { /_gf exch ddef findcmykcustomcolor /_if exch ddef /_fc { _lp /fill ne { _of setoverprint _if _gf 1 exch sub setcustomcolor /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /X { /_gs exch ddef findcmykcustomcolor /_is exch ddef /_sc { _lp /stroke ne { _os setoverprint _is _gs 1 exch sub setcustomcolor /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /A { pop } def /annotatepage { userdict /annotatepage 2 copy known {get exec} {pop pop} ifelse } def /XT { pop pop } def /discard { save /discardSave exch store discardDict begin /endString exch store gt38? { 2 add } if load stopped pop end discardSave restore } bind def userdict /discardDict 7 dict dup begin put /pre38Initialize { /endStringLength endString length store /newBuff buffer 0 endStringLength getinterval store /newBuffButFirst newBuff 1 endStringLength 1 sub getinterval store /newBuffLast newBuff endStringLength 1 sub 1 getinterval store } def /shiftBuffer { newBuff 0 newBuffButFirst putinterval newBuffLast 0 currentfile read not { stop } if put } def 0 { pre38Initialize mark currentfile newBuff readstring exch pop { { newBuff endString eq { cleartomark stop } if shiftBuffer } loop } { stop } ifelse } def 1 { pre38Initialize /beginString exch store mark currentfile newBuff readstring exch pop { { newBuff beginString eq { /layerCount dup load 1 add store } { newBuff endString eq { /layerCount dup load 1 sub store layerCount 0 eq { cleartomark stop } if } if } ifelse shiftBuffer } loop } if } def 2 { mark { currentfile buffer readline not { stop } if endString eq { cleartomark stop } if } loop } def 3 { /beginString exch store /layerCnt 1 store mark { currentfile buffer readline not { stop } if dup beginString eq { pop /layerCnt dup load 1 add store } { endString eq { layerCnt 1 eq { cleartomark stop } { /layerCnt dup load 1 sub store } ifelse } if } ifelse } loop } def end userdict /clipRenderOff 15 dict dup begin put { /n /N /s /S /f /F /b /B } { { _doClip 1 eq { /_doClip 0 ddef _eo {eoclip} {clip} ifelse } if newpath } def } forall /Tr /pop load def /Bb {} def /BB /pop load def /Bg {12 npop} def /Bm {6 npop} def /Bc /Bm load def /Bh {4 npop} def end /Lb { 4 npop 6 1 roll pop 4 1 roll pop pop pop 0 eq { 0 eq { (%AI5_BeginLayer) 1 (%AI5_EndLayer--) discard } { /clipForward? true def /Tx /pop load def /Tj /pop load def currentdict end clipRenderOff begin begin } ifelse } { 0 eq { save /discardSave exch store } if } ifelse } bind def /LB { discardSave dup null ne { restore } { pop clipForward? { currentdict end end begin /clipForward? false ddef } if } ifelse } bind def /Pb { pop pop 0 (%AI5_EndPalette) discard } bind def /Np { 0 (%AI5_End_NonPrinting--) discard } bind def /Ln /pop load def /Ap /pop load def /Ar { 72 exch div 0 dtransform dup mul exch dup mul add sqrt dup 1 lt { pop 1 } if setflat } def /Mb { q } def /Md { } def /MB { Q } def /nc 3 dict def nc begin /setgray { pop } bind def /setcmykcolor { 4 npop } bind def /setcustomcolor { 2 npop } bind def currentdict readonly pop end end setpacking %%EndResource %%BeginResource: procset Adobe_blend_AI5 1.4 0 %%Title: (Adobe Illustrator (R) Version 5.0 Blend ProcSet) %%Version: 1.4 0 %%CreationDate: (11/19/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /Adobe_blend_AI5 70 dict dup begin put /bd { bind def } bind def /xs { exch store } bd /nullProc { { } } def /initialize { pop pop Adobe_blend_AI5 begin Adobe_blend_AI5_vars begin /_contoneDevice where { pop } { /_contoneDevice false def } ifelse /_dpiThreshold where { pop } { /_dpiThreshold 600 def } ifelse /_screenFreqThreshold where { pop } { /_screenFreqThreshold 150 def } ifelse /tRectOK? deviceDPI _dpiThreshold le currentScreenFreq _screenFreqThreshold le and _contoneDevice not and def /invertXfer { [ { 1 exch sub } /exec load systemdict/currenttransfer get exec /exec load ] cvx systemdict/settransfer get exec } bd /spotDict 3 dict dup begin /nSpots 2 def /spot1 7 dict def /spot2 7 dict def end def composite? { /_setgray_ /setgray load def /_fill_ /fill load def /_image_ /image load def } { /_setgray_ systemdict/setgray get def /_fill_ systemdict/fill get def /_image_ systemdict/image get def } ifelse } bd /terminate { currentdict Adobe_blend_AI5_vars eq { end currentdict Adobe_blend_AI5 eq { end } if } if } bd /_compositeSpotDevice where { begin _compositeSpotDevice 0 ne {userdict /composite? true put} if end } { /_compositeSpotDevice 0 def } ifelse /nullString () def /d255 256 array def 0 1 255 { d255 exch dup 255 div put } bind for /d255- 256 array def 0 1 255 { d255- exch 1 d255 2 index get sub put } bind for /dUserSpace matrix defaultmatrix def currentdict /Adobe_blend_AI5_vars 89 dict dup begin put { /f /F /s /S /b /B } { null def } bind forall /byte 1 string def /sSave null def /setSSave { save /sSave exch store } bind def /Bm null def /doBlend null def /startC? false def /endC? false def /fCMYK? null def /startTint 0 def /endTint 0 def /bSMatrix matrix def /bUMatrix matrix def /dMatrix matrix def /inLine? true def /pTState? false def /bHi? false def /yHi 0 def /xHi 0 def /noImg /lv1Fix where { pop lv1Fix } { false } ifelse def /ccAry1 5 array def /ccTint 0 def /spotColor? false def /colorimage? true def [ /tint1Data /tint2Data /spotDict /bAxis /ubAxis /pChange /optimize? /nSamples /sInc /blendProc /_bn /xBCInc /yBCInc /bInc /bRender /cBName /cBType /nColors /color? /blend? /colorType /cData /cDataLen /bDataLen /rampPoint /midPoint /endPoint /blendLength /blackData /yeData /mgData /cyData /cnt1 /ndx /_fill /tmp counttomark { null def } bind repeat pop currentdict end currentdict end exch begin begin /unitSq { 0 0 moveto 0 1 lineto 1 1 lineto 1 0 lineto closepath } bd /gMark { counttomark 2 add -1 roll } bd /setCustomColor { dup /ccTint exch store 1 exch sub 6 1 roll ccAry1 astore exch setcustomcolor } bd /currentCustomColor { ccAry1 aload pop ccTint } bd /nsetcustomcolor where { pop } { /nsetcustomcolor { pop setcmykcolor } bd } ifelse /nsetcustomcolorend where { pop } { /nsetcustomcolorend { } bd } ifelse /setBSpace { newpath bUMatrix astore concat unitSq } bd /setCStop { dup 0 eq { pop spotColor? { dup 1 exch sub /ccTint exch def ccAry1 4 /Black put } if setgray } { 1 eq { setcmykcolor } { composite? not colorType 2 lt and { forceCMYK } { setCustomColor } ifelse } ifelse } ifelse } bd /makeByte { /tmp 0 store 255 mul cvi 8 string 8 { dup tmp 3 index put /tmp tmp 1 add store } repeat exch pop } bd /setImgSpace { cDataLen 1 8 2 index 0 0 1 0 0 dMatrix astore } bd /bwImage { setImgSpace cData /_image_ load { exec } stopped { $error /errorname get /undefinedresult ne { stop } { pop pop pop pop pop } ifelse } if } bd level2? { /bFill { _fill } def /bCImg { /cDataLen bDataLen store setImgSpace setSSave expandSpot cyData mgData yeData cData expandCMYK true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd } if /expandOne { dup type /stringtype ne { cDataLen string exch dup 0 ne { 255 mul cvi 0 1 cDataLen 1 sub { 3 copy exch put pop } for } if pop } if } bd /expandSpot { spotColor? { spotDict begin spot1 begin tintImage type /nulltype ne { tintImage expandOne /tintImage exch def } if end spot2 begin tintImage type /nulltype ne { tintImage expandOne /tintImage exch def } if end end } if } bd /expandCMYK { 4 { expandOne 4 1 roll } repeat } bd /colorimage where dup { exch pop /ncolorimage where { pop } { /ncolorimage {pop colorimage} bd } ifelse } if not { /ncolorimage where { pop } { /colorimage? false store /ncolorimage { pop pop pop setSSave /blackData xs /yeData xs /mgData xs /cyData xs /cnt1 0 store [ byte dup 0 cyData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .3 /mul cvx } { .3 mul } ifelse mgData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .59 /mul cvx } { .59 mul } ifelse yeData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .11 /mul cvx } { .11 mul } ifelse blackData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx } if /add cvx /add cvx /add cvx 1 /exch cvx /sub cvx /dup cvx 0 /lt cvx { pop 0 } /if cvx /dup cvx 1 /gt cvx { pop 1 } /if cvx 255 /mul cvx /cvi cvx 256 /mod cvx /dup cvx 0 /lt cvx { pop 0 } /if cvx /put cvx /cnt1 dup cvx 1 /add cvx /store cvx ] cvx bind _image_ sSave restore } bd } ifelse } if level2? not { /bCImg { /cDataLen bDataLen store setImgSpace setSSave expandSpot cyData mgData yeData cData colorimage? { expandCMYK } if true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd /bwFill { setSSave /cDataLen 8 store /cData currentgray makeByte store bwImage sSave restore } bd /c1ImgFill { setSSave /cDataLen 8 store setImgSpace spotColor? { spotDict begin spot1 begin currentCustomColor makeByte /tintImage exch def /name exch def /spot_K exch def /spot_Y exch def /spot_M exch def /spot_C exch def end spot2 initSpotData end } if currentcmykcolor 4 { makeByte 4 1 roll } repeat true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd /bFill noImg { { _fill } } { { color? { c1ImgFill } { bwFill } ifelse } } ifelse bd } if composite? { /bCFun { color? { cyData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if mgData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if yeData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if cData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if spotColor? { spotDict begin /spotDict cvx /begin cvx spot1 begin tintImage dup type /stringtype eq { /ndx cvx /get cvx d255- /exch cvx /get cvx } { dup type /nulltype ne { name type /nametype ne {1 exch sub} if } if } ifelse end /spot1 cvx /tintValue 3 -1 /roll cvx /put cvx spot2 begin tintImage dup type /stringtype eq { /ndx cvx /get cvx d255- /exch cvx /get cvx } { dup type /nulltype ne { name type /nametype ne {1 exch sub} if } if } ifelse end /spot2 cvx /tintValue 3 -1 /roll cvx /put cvx /end cvx end /spotDict cvx /nsetcustomcolor cvx } { /setcmykcolor cvx } ifelse } { cData /ndx cvx /get cvx d255 /exch cvx /get cvx /setgray cvx } ifelse } bd /Bc { newpath gsave setBSpace nColors 1 eq { pop pop setCStop } if bFill grestore } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { linImg } { bFill } ifelse grestore nColors 1 gt { getRData } if } bd /rdBm { /nColors dup load 1 sub store _fill gsave bUMatrix astore concat bHi? { xHi yHi bUMatrix idtransform /yHi exch store /xHi exch store rampPoint 1 lt { 1 rampPoint sub dup xHi mul exch yHi mul translate } if } if nColors { 0 0 rampPoint 0 360 arc _fill blend? bHi? or { rdBlend } if nColors 1 gt { getRData } if /nColors dup load 1 sub store } repeat /nColors 1 store grestore } bd /cGetRData { setCStop /blend? cData type /stringtype eq dup not color? and { pop cyData type /stringtype eq mgData type /stringtype eq yeData type /stringtype eq or or } if store } def /cGetRData } if /eCStop { mark 1 index 3 mul 3 add dup 8 gt { pop 8 } if 1 roll cleartomark } bd composite? not { /knockOut level2? { { 0 0 0 0 setcmykcolor _fill } } { /bFill noImg { { _fill } } { { _of true eq { currentgray 1 ne { bwFill } if } { bwFill } ifelse } } ifelse def /whiteByte 1 makeByte def noImg { { 0 0 0 0 setcmykcolor _fill } } { { cBType 0 eq { setSSave /cData whiteByte store /cDataLen 8 store bwImage sSave restore } { _fill } ifelse } } ifelse } ifelse bd /bCFun { cData dup type /stringtype ne { color? { 1 exch sub } if } { /ndx cvx /get cvx color? customColor? not and { d255- } { d255 } ifelse /exch cvx /get cvx } ifelse /_setgray_ cvx } bd /eCCBlend { dup 3 eq { pop mark 7 1 roll 6 copy ccThrough? dup /blend? xs { /startC? true store setCustomColor customColor? { /cData tint1Data store setCDataLen } if /endC? 3 index 3 eq { 4 index 1 ne } { false } ifelse store } if cleartomark stop } if 1 eq { pop pop pop } if pop /startC? false store 6 { 8 index } repeat ccThrough? dup /blend? xs { /endC? true store blend? not { stop } if customColor? { /cData tint1Data store setCDataLen } if } if } bd /handleOP { _of not { knockOut } if } bd /handleROP { _of not { 0 0 0 0 setcmykcolor _fill } { newpath } ifelse } bd /rdBm { /nColors dup load 1 sub store blend? { _fill } { handleROP } ifelse gsave bUMatrix astore concat bHi? { xHi yHi bUMatrix idtransform /yHi exch store /xHi exch store rampPoint 1 lt { 1 rampPoint sub dup xHi mul exch yHi mul translate } if } if nColors { 0 0 rampPoint 0 360 arc blend? { cData type /stringtype ne bHi? not and { cData color? { 1 exch sub } if _setgray_ _fill_ } { cData type /stringtype ne { /cDataLen 1 store /bDataLen 1 store } if rdBlend } ifelse } { handleROP pTState? { /bAxis rampPoint endPoint sub store xHi bAxis mul yHi bAxis mul translate } if } ifelse nColors 1 gt { getRData } if /nColors dup load 1 sub store } repeat /nColors 1 store grestore } bd /ccThrough? { gsave pop 0 setCustomColor currentcmykcolor grestore anyColor? } bd /forceCMYK { exch pop 1 exch sub 5 1 roll 4 { 4 index mul 4 1 roll } repeat 0 cCMYKData dup /cData ne { dup /yeData eq { pop 1 add } { /mgData eq { 2 } { 3 } ifelse add } ifelse 0 } if pop index 0 eq { pop pop pop pop 0 0 0 0 } if setcmykcolor pop /fCMYK? true store } bd /endCapSepBc { pop pop dup 0 eq { pop setgray } { 1 eq { setcmykcolor } { colorType 1 eq { forceCMYK } { fCMYK? { forceCMYK } { setCustomColor } ifelse } ifelse } ifelse } ifelse currentcmykcolor anyColor? blend? and { bFill } { handleOP } ifelse } bd } if /cCMYKData 0 def composite? dup not { pop customColor? } if not { /cCMYKData /cyData /mgData /yeData /cData black? not { yellow? { exch } { magenta? { 3 } { 4 } ifelse -1 roll } ifelse } if 4 1 roll pop pop pop store /Bc { gsave setBSpace nColors 1 gt { blend? currentcmykcolor anyColor? and { bFill } { handleOP } ifelse } { endCapSepBc } ifelse grestore newpath } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { cCMYKData load dup type /stringtype eq { dup length /cDataLen xs /cData xs gsave colorType 0 ne noImg not and { invertXfer } if linImg grestore } { pop bFill } ifelse } { handleOP } ifelse grestore nColors 1 gt { getRData } if } bd /cmykGetRData { /fCMYK? false store blend? { { cmykDataProcs colorType get exec } stopped pop blend? { /cData cCMYKData load store setCDataLen } if } if } def /cmykDataProcs [ { pop black? dup /blend? xs { setgray 0 } if pop } { cCMYKData load dup type /stringtype ne { 0 0 0 cyan? not { 4 magenta? { 1 } { yellow? { 2 } { 3 } ifelse } ifelse roll } if 4 copy add add add 0 eq { /blend? false store } if setcmykcolor /startC? true store /endC? true store eCStop stop } if pop dup 0 eq { pop setgray } { 1 eq { setcmykcolor } { forceCMYK } ifelse } ifelse } bind /eCCBlend load { cBType 1 eq { tint1Data tint2Data /tint1Data xs /tint2Data xs } if 0 eq { black? { setgray } { 0 0 0 4 -1 roll 1 exch sub setcmykcolor } ifelse black? { /blend? true store } if 6 { 8 index } repeat ccThrough? { /blend? true store } { black? { /cData tint1Data store setCDataLen } { /blend? false store } ifelse } ifelse } { mark 7 1 roll 6 copy ccThrough? { forceCMYK pop stop } if 9 index 0 eq { black? dup /blend? xs { pop 1 setgray /cData tint2Data store setCDataLen 0 } if pop } { /blend? 6 { 16 index } repeat ccThrough? store blend? { forceCMYK } if } ifelse cleartomark } ifelse } bind ] def /cmykGetRData } if composite? dup not { pop isCMYKSep? } if not { /endCapSepBc { /white? false store pop pop dup 0 eq { pop /white? 1 index 1 eq store setgray } { 1 eq { setcmykcolor } { setCustomColor } ifelse } ifelse % currentcmykcolor anyColor? endC? or blend? and { bFill } { handleOP } ifelse } bd /Bc { gsave setBSpace nColors 1 gt { blend? startC? and { bFill } { handleOP } ifelse } { endCapSepBc } ifelse grestore newpath } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { cData type /stringtype eq { linImg } { bFill } ifelse } { handleOP } ifelse grestore nColors 1 gt { getRData } if } bd /discardCMY { counttomark 4 add -3 roll pop pop pop } bd /testTopCC { 6 copy ccThrough? } bd /getCRamp { { ccDataProcs colorType 2 sub get exec } stopped pop blend? cDataLen 0 eq and { /cDataLen bDataLen store } if } bd /ccGetRData { /fCMYK? false store /startC? false store /endC? false store colorType 2 lt { /blend? false def } if blend? { getCRamp } { setCStop } ifelse blend? { /blend? cData 1 ne store blend? { cData dup type /stringtype ne { 1 exch sub /cData xs 0 } if pop } if } if } def /ccDataProcs [ /eCCBlend load { cBType 1 eq { tint1Data tint2Data /tint1Data xs /tint2Data xs } if 0 eq { /blend? false store pop } { mark 7 1 roll testTopCC { /blend? 1 index 1 ne store /startC? blend? store /endC? false store blend? not { cleartomark stop } if /cData tint1Data store setCDataLen setCustomColor pop stop } if cleartomark } ifelse 2 index 0 eq { /blend? false store } { mark 6 { 9 index } repeat testTopCC dup /blend? xs { /blend? 1 index 1 ne store /endC? blend? store /startC? false store blend? not { cleartomark stop } if /cData tint2Data store setCDataLen } if cleartomark } ifelse } bind ] def /ccGetRData } if load Adobe_blend_AI5_vars /getData 3 -1 roll put /setCDataLen { /cDataLen 0 cData dup type /stringtype eq { length exch } if pop store } bd /initSpotData { begin /name null def /tintImage null def /tintValue null def /spot_C null def /spot_M null def /spot_Y null def /spot_K null def end } bd /getRData { /colorType gMark store _compositeSpotDevice 0 ne { spotDict begin spot1 initSpotData spot2 initSpotData end /spotColor? colorType 2 eq colorType 3 eq or def } { /spotColor? false store } ifelse /blend? true store 0 0 0 0 setcmykcolor 100 div /rampPoint xs % (between 13 and 87%) 100 div /midPoint xs dup 0 eq { 2 } { dup 1 eq { 5 } { _compositeSpotDevice 0 ne { spotDict begin spot1 begin /name 3 index def /spot_K 4 index def /spot_Y 5 index def /spot_M 6 index def /spot_C 7 index def end end } if 7 } ifelse } ifelse /tmp exch def tmp index 100 div /endPoint xs _compositeSpotDevice 0 ne { tmp 2 add index 3 eq { /tmp tmp 4 add def tmp index dup spotDict begin spot1/name get ne { spot2 begin /name exch def /spot_K tmp 2 add index def /spot_Y tmp 3 add index def /spot_M tmp 4 add index def /spot_C tmp 5 add index def end } { pop } ifelse end } if } if /color? colorType 0 gt store colorType 3 eq { /tint2Data gMark store } if colorType 2 ge { /tint1Data gMark store } if _compositeSpotDevice 0 ne { spotDict begin colorType 2 ge { colorType 3 eq { spot2 begin /tintImage cBType 0 eq {tint2Data} {tint1Data} ifelse def name null eq {/name /Black def} if end } if spot1 begin /tintImage cBType 0 eq colorType 2 eq or {tint1Data} {tint2Data} ifelse def colorType 2 eq { name null eq { /name spot2/name get def spot2/name null put } if } { name null eq {/name /Black def} if } ifelse end } if end } if /cData gMark store setCDataLen colorType 0 gt { counttomark 4 add -3 roll /yeData xs /mgData xs /cyData xs } if blend? { /bDataLen cDataLen dup 0 eq color? and { [ cyData mgData yeData ] { dup type /stringtype eq { length exch pop exit } if pop } forall } if store bDataLen 0 eq { /bDataLen 1 store } if getData blend? { composite? cDataLen 0 eq and { /cDataLen bDataLen store } if } if } { setCStop } ifelse } bd /Bg { 0 0 0 0 setcmykcolor 6 { pop } repeat /blendLength xs pop pop pop /cBName xs /bRender xs bRender 2 ne { composite? not { _of setoverprint } if _eo {eoclip} {clip} ifelse _bn cBName 2 copy known { get mark exch aload pop /cBType xs /nColors xs mark exch aload pop 0 0 } if pop pop getRData cBType 0 eq { /linealBm } { bHi? { /pTState? nColors 2 gt store } if /doBlend /rdBlend load store /rdBm } ifelse } { inLine? not { mark mark } if /Bc dup { cleartomark mark } bd /nullProc } ifelse load /Bm xs } bd /linImg noImg { { newpath doRctBlend } } { { /doBlend color? composite? and { /bCImg } { /bwImage } ifelse load store 0 0 moveto tRectOK? composite? and { { mark 0 1 dtransform atan cvi 90 mod 0 eq 1 0 dtransform atan cvi 90 mod 0 eq } stopped { cleartomark } { and exch pop { newpath doRctBlend } { doBlend } ifelse } ifelse } { doBlend } ifelse } } ifelse bd /doRctBlend { gsave /sInc 1 store /nSamples bDataLen store /bInc 1 bDataLen div store /ubAxis 1 0 dtransform dUserSpace idtransform dup mul exch dup mul add sqrt store /pChange ubAxis 0 eq { 0 } { bDataLen ubAxis div } ifelse store pChange .5 gt noImg not and dup /optimize? xs { /nSamples ubAxis 2 div round cvi dup 1 le { pop 2 } if store /bInc 1 nSamples div store /sInc bDataLen 1 sub nSamples 1 sub div store } if 0 nSamples [ /dup cvx optimize? { /round cvx /cvi cvx } if /ndx /exch cvx /store cvx bCFun /rectfill where dup { exch pop _compositeSpotDevice 1 ne and } if { 0 0 bInc 1 /rectfill cvx } { 0 0 /moveto cvx bInc 0 /lineto cvx bInc 1 /lineto cvx 0 1 /lineto cvx /closepath cvx /_fill_ cvx } ifelse bInc 0 /translate cvx sInc /add cvx ] cvx bind repeat pop spotColor? {nsetcustomcolorend} if grestore } bd /rdPrep { /nSamples bDataLen dup 0 eq { pop 1 } if store /sInc -1 store /bAxis rampPoint endPoint sub store /bInc bAxis bDataLen div neg store /optimize? false store tRectOK? { /ubAxis bAxis 0 dtransform dUserSpace idtransform dup mul exch dup mul add sqrt 0 bAxis dtransform dUserSpace idtransform dup mul exch dup mul add sqrt 2 copy lt { exch } if pop store /pChange ubAxis 0 eq { 0 } { bDataLen ubAxis div } ifelse store pChange .5 gt noImg not and dup /optimize? xs { /nSamples ubAxis 2 div round cvi dup 1 le { pop 2 } if store /bInc bAxis nSamples div neg store /sInc bDataLen 1 sub nSamples 1 sub div neg store } if } if bHi? { /xBCInc xHi bAxis mul nSamples div store /yBCInc yHi bAxis mul nSamples div store } if } bd /rdBlend { newpath gsave rdPrep rampPoint bDataLen 1 sub nSamples [ /dup cvx optimize? { /round cvx /cvi cvx } if /ndx /exch cvx /store cvx bCFun 0 0 3 /index cvx 0 360 /arc cvx /_fill_ cvx /exch cvx bInc /add cvx /exch cvx sInc /add cvx bHi? { xBCInc yBCInc /translate cvx } if ] cvx bind repeat pop pop spotColor? {nsetcustomcolorend} if grestore pTState? { xHi bAxis mul yHi bAxis mul translate } if } bd /Bh { pop pop /pTState? false store 2 copy 0 ne exch 0 ne or dup /bHi? xs { /yHi xs /xHi xs 0 0 } if pop pop } bd /BD { inLine? not { ] nColors cBType ] _bn cBName 3 -1 roll put end } if } bd /Bn { 1 add dict dup nullString null put /_bn xs } bd /Bd { Adobe_blend_AI5_vars begin 3 -1 roll dup nullString eq dup { setSSave } if /inLine? exch def /cBName exch def /nColors exch def /cBType exch def } bd /Bb { sSave null eq { Adobe_blend_AI5_vars begin setSSave } if composite? { /_fill /fill load store } { /__fill /fill load store /_fill { _of true eq { currentgray 1 ne { __fill } if } { __fill } ifelse } def } ifelse /fill { } def } bd /BB { /cBType xs cleartomark cleartomark cBType dup bRender sSave dup type /savetype eq { restore 0 } if pop currentdict Adobe_blend_AI5_vars eq { end } if 2 ne exch 0 gt and { 2 eq { s } { S } ifelse } { pop newpath } ifelse } bd currentdict readonly pop end end defaultpacking setpacking %%EndResource %%BeginResource: procset Adobe_pattern_AI5 1.1 0 %%Title: (Adobe Illustrator (R) Version 5.0 Pattern Operators) %%Version: 1.1 0 %%CreationDate: (03/26/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_Illustrator_AI5 known not { userdict /Adobe_Illustrator_AI5 95 dict put } if userdict /Adobe_Illustrator_AI5 get begin /@ { } def /& { } def /dp { dup null eq { pop _dp 0 ne { 0 1 _dp 1 sub _dl mod { _da exch get 3 get } for _dp 1 sub _dl mod 1 add packedarray _da 0 get aload pop 8 -1 roll 5 -1 roll pop 4 1 roll definepattern pop } if } { _dp 0 ne _dp _dl mod 0 eq and { null dp } if 7 packedarray _da exch _dp _dl mod exch put _dp _dl mod _da 0 get 4 get 2 packedarray /_dp _dp 1 add def } ifelse } def /E { _ed begin dup 0 get type /arraytype ne { 0 { dup 1 add index type /arraytype eq { 1 add } { exit } ifelse } loop array astore } if /_dd exch def /_ury exch def /_urx exch def /_lly exch def /_llx exch def /_n exch def /_y 0 def /_dl 4 def /_dp 0 def /_da _dl array def 0 1 _dd length 1 sub { /_d exch _dd exch get def 0 2 _d length 2 sub { /_x exch def /_c _d _x get _ ne def /_r _d _x 1 add get cvlit def _r _ ne { _urx _llx sub _ury _lly sub [ 1 0 0 1 0 0 ] [ /save cvx _llx neg _lly neg /translate cvx _c { nc /begin cvx } if _r dup type /stringtype eq { cvx } { { exec } /forall cvx } ifelse _c { /end cvx } if /restore cvx ] cvx /_fn 12 _n length add string def _y _fn cvs pop /_y _y 1 add def _fn 12 _n putinterval _fn _c false dp _d exch _x 1 add exch put } if } for } for null dp _n _dd /_pd end xput } def /fc { _fm dup concatmatrix pop } def /p { /_fm exch ddef 9 -2 roll _pm translate fc 7 -2 roll _pm scale fc 5 -1 roll _pm rotate fc 4 -2 roll exch 0 ne { dup _pm rotate fc 1 -1 _pm scale fc neg _pm rotate fc } { pop } ifelse dup _pm rotate fc exch dup sin exch cos div 1 0 0 1 0 6 2 roll _pm astore fc neg _pm rotate fc _pd exch get /_fdd exch ddef /_pf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm patternfill } { pop fill } ifelse grestore pop } for pop } for restore newpath } ddef /_psf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm 9 copy 6 npop patternashow } { pop 6 copy 3 npop hvashow } ifelse grestore pop } for pop } for restore sw rmoveto } ddef /_pjsf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm 12 copy 6 npop patternawidthshow } { pop 9 copy 3 npop hvawidthshow } ifelse grestore pop } for pop } for restore swj rmoveto } ddef /_lp /none ddef } def /sc { _sm dup concatmatrix pop } def /P { /_sm exch ddef 9 -2 roll _pm translate sc 7 -2 roll _pm scale sc 5 -1 roll _pm rotate sc 4 -2 roll exch 0 ne { dup _pm rotate sc 1 -1 _pm scale sc neg _pm rotate sc } { pop } ifelse dup _pm rotate sc exch dup sin exch cos div 1 0 0 1 0 6 2 roll _pm astore sc neg _pm rotate sc _pd exch get /_sdd exch ddef /_ps { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm patternstroke } { pop stroke } ifelse grestore pop } for pop } for restore newpath } ddef /_pss { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm 10 copy 6 npop patternashowstroke } { pop 7 copy 3 npop ss } ifelse grestore pop } for pop } for restore pop sw rmoveto } ddef /_pjss { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm 13 copy 6 npop patternawidthshowstroke } { pop 10 copy 3 npop jss } ifelse grestore pop } for pop } for restore pop swj rmoveto } ddef /_lp /none ddef } def end userdict /Adobe_pattern_AI5 18 dict dup begin put /initialize { /definepattern where { pop } { begin begin Adobe_pattern_AI5 begin Adobe_pattern_AI5 { dup xcheck { bind } if pop pop } forall mark cachestatus 7 1 roll pop pop pop pop exch pop exch { { 10000 add dup 2 index gt { exit } if dup setcachelimit } loop } stopped cleartomark end end end Adobe_pattern_AI5 begin } ifelse } def /terminate { currentdict Adobe_pattern_AI5 eq { end } if } def errordict /nocurrentpoint { pop stop } put errordict /invalidaccess { pop stop } put /patternencoding 256 array def 0 1 255 { patternencoding exch ( ) 2 copy exch 0 exch put cvn put } for /definepattern { 17 dict begin /uniform exch def /cache exch def /key exch def /procarray exch def /mtx exch matrix invertmatrix def /height exch def /width exch def /ctm matrix currentmatrix def /ptm matrix def /str 32 string def /slice 9 dict def slice /s 1 put slice /q 256 procarray length div sqrt floor cvi put slice /b 0 put /FontBBox [ 0 0 0 0 ] def /FontMatrix mtx matrix copy def /Encoding patternencoding def /FontType 3 def /BuildChar { exch begin /setstrokeadjust where {pop true setstrokeadjust} if slice begin dup q dup mul mod s idiv /i exch def dup q dup mul mod s mod /j exch def q dup mul idiv procarray exch get /xl j width s div mul def /xg j 1 add width s div mul def /yl i height s div mul def /yg i 1 add height s div mul def uniform { 1 1 } { width 0 dtransform dup mul exch dup mul add sqrt dup 1 add exch div 0 height dtransform dup mul exch dup mul add sqrt dup 1 add exch div } ifelse width 0 cache { xl 4 index mul yl 4 index mul xg 6 index mul yg 6 index mul setcachedevice } { setcharwidth } ifelse gsave scale newpath xl yl moveto xg yl lineto xg yg lineto xl yg lineto closepath clip newpath end end exec grestore } def key currentdict definefont end } def /patterncachesize { gsave newpath 0 0 moveto width 0 lineto width height lineto 0 height lineto closepath patternmatrix setmatrix pathbbox exch ceiling 4 -1 roll floor sub 3 1 roll ceiling exch floor sub mul 1 add grestore } def /patterncachelimit { cachestatus 7 1 roll 6 npop 8 mul } def /patternpath { exch dup begin setfont ctm setmatrix concat slice exch /b exch slice /q get dup mul mul put FontMatrix concat uniform { width 0 dtransform round width div exch round width div exch 0 height dtransform round height div exch height div exch 0 0 transform round exch round exch ptm astore setmatrix } { ptm currentmatrix pop } ifelse { currentpoint } stopped not { 2 npop pathbbox true 4 index 3 index eq 4 index 3 index eq and { pop false { { 2 npop } { 3 npop true } { 7 npop true } { pop true } pathforall } stopped { 5 npop true } if } if { height div ceiling height mul 4 1 roll width div ceiling width mul 4 1 roll height div floor height mul 4 1 roll width div floor width mul 4 1 roll 2 index sub height div ceiling cvi exch 3 index sub width div ceiling cvi exch 4 2 roll moveto FontMatrix mtx invertmatrix dup dup 4 get exch 5 get rmoveto ptm ptm concatmatrix pop slice /s patterncachesize patterncachelimit div ceiling sqrt ceiling cvi dup slice /q get gt { pop slice /q get } if put 0 1 slice /s get dup mul 1 sub { slice /b get add gsave 0 1 str length 1 sub { str exch 2 index put } for pop dup { gsave ptm setmatrix 1 index str length idiv { str show } repeat 1 index str length mod str exch 0 exch getinterval show grestore 0 height rmoveto } repeat grestore } for 2 npop } { 4 npop } ifelse } if end } def /patternclip { _eo {eoclip} {clip} ifelse } def /patternstrokepath { strokepath } def /patternmatrix matrix def /patternfill { dup type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get } if gsave patternclip Adobe_pattern_AI5 /patternpath get exec grestore newpath } def /patternstroke { dup type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get } if gsave patternstrokepath true { { { newpath moveto } { lineto } { curveto } { closepath 3 copy Adobe_pattern_AI5 /patternfill get exec } pathforall 3 npop } stopped { 5 npop patternclip Adobe_pattern_AI5 /patternfill get exec } if } { patternclip Adobe_pattern_AI5 /patternfill get exec } ifelse grestore newpath } def /vpatternawidthshow { 6 1 roll /_hvay exch ddef /_hvax exch ddef /_hvwb exch ddef /_hvcy exch ddef /_hvcx exch ddef { dup cstring dup length 1 eq _charorientation 1 eq and { -90 rotate currentpoint _fontRotateAdjust add moveto gsave false charpath currentpoint 5 index 5 index 5 index Adobe_pattern_AI5 /patternfill get exec grestore _fontRotateAdjust sub moveto _hvwb eq { _hvcx _hvcy rmoveto } if _hvax _hvay rmoveto 90 rotate } { currentpoint _fontHeight sub _hvax sub 3 index _hvwb eq { _hvcx sub } if currentpoint exch 4 index stringwidth pop 2 div sub exch _fontAscent sub moveto gsave 2 index false charpath 6 index 6 index 6 index Adobe_pattern_AI5 /patternfill get exec grestore newpath moveto pop pop } ifelse } cforall 3 npop } def /hpatternawidthshow { { dup cstring exch gsave 3 index eq { 5 index 5 index rmoveto } if false charpath currentpoint 9 index 9 index 9 index Adobe_pattern_AI5 /patternfill get exec grestore newpath moveto 2 copy rmoveto } cforall 8 npop } def /patternashow { 0 0 0 6 3 roll patternawidthshow } def /patternawidthshow { 6 index type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get 7 1 roll } if _lineorientation 0 eq { hpatternawidthshow } { vpatternawidthshow } ifelse } def /vpatternawidthshowstroke { 7 1 roll 6 1 roll /_hvay exch ddef /_hvax exch ddef /_hvwb exch ddef /_hvcy exch ddef /_hvcx exch ddef { dup cstring dup length 1 eq _charorientation 1 eq and { -90 rotate currentpoint _fontRotateAdjust add moveto gsave false charpath currentpoint 3 index setmatrix 6 index 6 index 6 index Adobe_pattern_AI5 /patternstroke get exec grestore _fontRotateAdjust sub moveto _hvwb eq { _hvcx _hvcy rmoveto } if _hvax _hvay rmoveto 90 rotate } { currentpoint _fontHeight sub _hvax sub 3 index _hvwb eq { _hvcx sub } if currentpoint exch 4 index stringwidth pop 2 div sub exch _fontAscent sub moveto gsave 2 index false charpath 4 index setmatrix 7 index 7 index 7 index Adobe_pattern_AI5 /patternstroke get exec grestore newpath moveto pop pop } ifelse } cforall 4 npop } def /hpatternawidthshowstroke { 7 1 roll { dup cstring exch gsave 3 index eq { 5 index 5 index rmoveto } if false charpath currentpoint 7 index setmatrix 10 index 10 index 10 index Adobe_pattern_AI5 /patternstroke get exec grestore newpath moveto 2 copy rmoveto } cforall 9 npop } def /patternashowstroke { 0 0 0 7 3 roll patternawidthshowstroke } def /patternawidthshowstroke { 7 index type /dicttype eq { patternmatrix /patternmatrix get 8 1 roll } if _lineorientation 0 eq { hpatternawidthshowstroke } { vpatternawidthshowstroke } ifelse } def end setpacking %%EndResource %%EndProlog %%BeginSetup Adobe_level2_AI5 /initialize get exec Adobe_screens_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_typography_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_blend_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_pattern_AI5 /initialize get exec Adobe_ColorImage_AI6 /initialize get exec Adobe_Illustrator_AI5 /initialize get exec [ 39/quotesingle 96/grave 130/quotesinglbase 131/florin 132/quotedblbase 133/ellipsis 134/dagger 135/daggerdbl 136/circumflex 137/perthousand 138/Scaron 139/guilsinglleft 140/OE 145/quoteleft 146/quoteright 147/quotedblleft 148/quotedblright 149/bullet 150/endash 151/emdash 152/tilde 153/trademark 154/scaron 155/guilsinglright 156/oe 157/dotlessi 159/Ydieresis 164/currency 166/brokenbar 168/dieresis 169/copyright 170/ordfeminine 172/logicalnot 174/registered 175/macron 176/ring 177/plusminus 178/twosuperior 179/threesuperior 180/acute 181/mu 183/periodcentered 184/cedilla 185/onesuperior 186/ordmasculine 188/onequarter 189/onehalf 190/threequarters 192/Agrave 193/Aacute 194/Acircumflex 195/Atilde 196/Adieresis 197/Aring 198/AE 199/Ccedilla 200/Egrave 201/Eacute 202/Ecircumflex 203/Edieresis 204/Igrave 205/Iacute 206/Icircumflex 207/Idieresis 208/Eth 209/Ntilde 210/Ograve 211/Oacute 212/Ocircumflex 213/Otilde 214/Odieresis 215/multiply 216/Oslash 217/Ugrave 218/Uacute 219/Ucircumflex 220/Udieresis 221/Yacute 222/Thorn 223/germandbls 224/agrave 225/aacute 226/acircumflex 227/atilde 228/adieresis 229/aring 230/ae 231/ccedilla 232/egrave 233/eacute 234/ecircumflex 235/edieresis 236/igrave 237/iacute 238/icircumflex 239/idieresis 240/eth 241/ntilde 242/ograve 243/oacute 244/ocircumflex 245/otilde 246/odieresis 247/divide 248/oslash 249/ugrave 250/uacute 251/ucircumflex 252/udieresis 253/yacute 254/thorn 255/ydieresis TE %AI3_BeginEncoding: _Helvetica Helvetica [ /_Helvetica/Helvetica 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-Bold Helvetica-Bold [ /_Helvetica-Bold/Helvetica-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-Oblique Helvetica-Oblique [ /_Helvetica-Oblique/Helvetica-Oblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-BoldOblique Helvetica-BoldOblique [ /_Helvetica-BoldOblique/Helvetica-BoldOblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Roman Times-Roman [ /_Times-Roman/Times-Roman 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Bold Times-Bold [ /_Times-Bold/Times-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Italic Times-Italic [ /_Times-Italic/Times-Italic 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-BoldItalic Times-BoldItalic [ /_Times-BoldItalic/Times-BoldItalic 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier Courier [ /_Courier/Courier 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-Bold Courier-Bold [ /_Courier-Bold/Courier-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-Oblique Courier-Oblique [ /_Courier-Oblique/Courier-Oblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-BoldOblique Courier-BoldOblique [ /_Courier-BoldOblique/Courier-BoldOblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Symbol Symbol [ /_Symbol/Symbol 0 0 1 TZ %AI3_EndEncoding AdobeType %%EndSetup 1 XR u 0.000 0.000 0.000 0.247 k [] 0 d 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 186.0000 51.7500 m 193.5000 59.2500 L 213.0000 55.5000 L 228.7500 62.2500 L 236.2500 59.2500 L 228.7500 51.7500 L 223.5000 55.5000 L 207.7500 48.0000 L 186.0000 51.7500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 228.7500 51.7500 m 228.7500 18.0000 L 236.2500 24.7500 L 236.2500 59.2500 L 228.7500 51.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 18.0000 m 207.7500 14.2500 L 223.5000 21.0000 L 228.7500 18.0000 L 228.7500 51.7500 L 223.5000 55.5000 L 207.7500 48.0000 L 186.0000 51.7500 L 186.0000 18.0000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 228.7500 66.0000 m 236.2500 72.7500 L 236.2500 87.0000 L 228.7500 80.2500 L 228.7500 66.0000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 186.0000 80.2500 m 228.7500 80.2500 L 236.2500 87.0000 L 193.5000 87.0000 L 186.0000 80.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 66.0000 m 228.7500 66.0000 L 228.7500 80.2500 L 186.0000 80.2500 L 186.0000 66.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 70.5000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sh_succ\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 228.7500 51.7500 m 236.2500 59.2500 L 236.2500 72.7500 L 228.7500 66.0000 L 228.7500 51.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 51.7500 m 228.7500 51.7500 L 228.7500 66.0000 L 186.0000 66.0000 L 186.0000 51.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 56.2500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sh_prev\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 228.7500 23.2500 m 236.2500 30.7500 L 236.2500 45.0000 L 228.7500 37.5000 L 228.7500 23.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 23.2500 m 228.7500 23.2500 L 228.7500 37.5000 L 186.0000 37.5000 L 186.0000 23.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 28.5000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (cs_next\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 228.7500 37.5000 m 236.2500 45.0000 L 236.2500 59.2500 L 228.7500 51.7500 L 228.7500 37.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 37.5000 m 228.7500 37.5000 L 228.7500 51.7500 L 186.0000 51.7500 L 186.0000 37.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 42.0000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sh_data\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 186.0000 123.0000 m 193.5000 129.7500 L 213.0000 126.0000 L 228.7500 133.5000 L 236.2500 129.7500 L 228.7500 123.0000 L 223.5000 126.0000 L 207.7500 119.2500 L 186.0000 123.0000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 228.7500 123.0000 m 228.7500 88.5000 L 236.2500 96.0000 L 236.2500 129.7500 L 228.7500 123.0000 L B U u 0.000 0.000 0.000 0.000 k 186.0000 88.5000 m 207.7500 85.5000 L 223.5000 92.2500 L 228.7500 88.5000 L 228.7500 123.0000 L 223.5000 126.0000 L 207.7500 119.2500 L 186.0000 123.0000 L 186.0000 88.5000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 228.7500 137.2500 m 236.2500 144.0000 L 236.2500 158.2500 L 228.7500 150.7500 L 228.7500 137.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 186.0000 150.7500 m 228.7500 150.7500 L 236.2500 158.2500 L 193.5000 158.2500 L 186.0000 150.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 137.2500 m 228.7500 137.2500 L 228.7500 150.7500 L 186.0000 150.7500 L 186.0000 137.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 141.7500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sh_succ\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 228.7500 123.0000 m 236.2500 129.7500 L 236.2500 144.0000 L 228.7500 137.2500 L 228.7500 123.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 123.0000 m 228.7500 123.0000 L 228.7500 137.2500 L 186.0000 137.2500 L 186.0000 123.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 127.5000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sh_prev\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 228.7500 94.5000 m 236.2500 101.2500 L 236.2500 115.5000 L 228.7500 108.7500 L 228.7500 94.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 94.5000 m 228.7500 94.5000 L 228.7500 108.7500 L 186.0000 108.7500 L 186.0000 94.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 99.0000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (i_next\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 228.7500 108.7500 m 236.2500 115.5000 L 236.2500 129.7500 L 228.7500 123.0000 L 228.7500 108.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 108.7500 m 228.7500 108.7500 L 228.7500 123.0000 L 186.0000 123.0000 L 186.0000 108.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 113.2500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sh_data\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 186.0000 193.5000 m 193.5000 201.0000 L 213.0000 197.2500 L 228.7500 204.0000 L 236.2500 201.0000 L 228.7500 193.5000 L 223.5000 197.2500 L 207.7500 189.7500 L 186.0000 193.5000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 228.7500 193.5000 m 228.7500 159.7500 L 236.2500 166.5000 L 236.2500 201.0000 L 228.7500 193.5000 L B U u 0.000 0.000 0.000 0.000 k 186.0000 159.7500 m 207.7500 156.0000 L 223.5000 163.5000 L 228.7500 159.7500 L 228.7500 193.5000 L 223.5000 197.2500 L 207.7500 189.7500 L 186.0000 193.5000 L 186.0000 159.7500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 228.7500 207.7500 m 236.2500 215.2500 L 236.2500 228.7500 L 228.7500 222.0000 L 228.7500 207.7500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 186.0000 222.0000 m 228.7500 222.0000 L 236.2500 228.7500 L 193.5000 228.7500 L 186.0000 222.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 207.7500 m 228.7500 207.7500 L 228.7500 222.0000 L 186.0000 222.0000 L 186.0000 207.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 212.2500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sh_succ\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 228.7500 193.5000 m 236.2500 201.0000 L 236.2500 215.2500 L 228.7500 207.7500 L 228.7500 193.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 193.5000 m 228.7500 193.5000 L 228.7500 207.7500 L 186.0000 207.7500 L 186.0000 193.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 198.0000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sh_prev\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 228.7500 165.0000 m 236.2500 172.5000 L 236.2500 186.7500 L 228.7500 179.2500 L 228.7500 165.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 165.0000 m 228.7500 165.0000 L 228.7500 179.2500 L 186.0000 179.2500 L 186.0000 165.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 170.2500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (a_next\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 228.7500 179.2500 m 236.2500 186.7500 L 236.2500 201.0000 L 228.7500 193.5000 L 228.7500 179.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 179.2500 m 228.7500 179.2500 L 228.7500 193.5000 L 186.0000 193.5000 L 186.0000 179.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 184.5000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sh_data\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 186.0000 264.7500 m 193.5000 271.5000 L 213.0000 267.7500 L 228.7500 275.2500 L 236.2500 271.5000 L 228.7500 264.7500 L 223.5000 267.7500 L 207.7500 261.0000 L 186.0000 264.7500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 228.7500 264.7500 m 228.7500 230.2500 L 236.2500 237.7500 L 236.2500 271.5000 L 228.7500 264.7500 L B U u 0.000 0.000 0.000 0.000 k 186.0000 230.2500 m 207.7500 227.2500 L 223.5000 234.0000 L 228.7500 230.2500 L 228.7500 264.7500 L 223.5000 267.7500 L 207.7500 261.0000 L 186.0000 264.7500 L 186.0000 230.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 228.7500 279.0000 m 236.2500 285.7500 L 236.2500 300.0000 L 228.7500 292.5000 L 228.7500 279.0000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 186.0000 292.5000 m 228.7500 292.5000 L 236.2500 300.0000 L 193.5000 300.0000 L 186.0000 292.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 279.0000 m 228.7500 279.0000 L 228.7500 292.5000 L 186.0000 292.5000 L 186.0000 279.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 283.5000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sh_succ\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 228.7500 264.7500 m 236.2500 271.5000 L 236.2500 285.7500 L 228.7500 279.0000 L 228.7500 264.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 264.7500 m 228.7500 264.7500 L 228.7500 279.0000 L 186.0000 279.0000 L 186.0000 264.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 269.2500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sh_prev\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 228.7500 236.2500 m 236.2500 243.0000 L 236.2500 257.2500 L 228.7500 250.5000 L 228.7500 236.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 236.2500 m 228.7500 236.2500 L 228.7500 250.5000 L 186.0000 250.5000 L 186.0000 236.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 240.7500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (a_next\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 228.7500 250.5000 m 236.2500 257.2500 L 236.2500 271.5000 L 228.7500 264.7500 L 228.7500 250.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 250.5000 m 228.7500 250.5000 L 228.7500 264.7500 L 186.0000 264.7500 L 186.0000 250.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 255.0000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sh_data\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 1.000 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 223.5000 285.7500 m 223.5000 286.5000 L 223.5000 286.5000 L 223.5000 287.2500 L 222.7500 287.2500 L 222.0000 288.0000 L 221.2500 288.0000 L 221.2500 288.0000 L 220.5000 287.2500 L 219.7500 287.2500 L 219.7500 286.5000 L 219.7500 285.7500 L 219.7500 285.0000 L 219.7500 285.0000 L 220.5000 284.2500 L 220.5000 284.2500 L 221.2500 283.5000 L 222.0000 283.5000 L 222.7500 283.5000 L 222.7500 284.2500 L 223.5000 284.2500 L 223.5000 285.0000 L 223.5000 285.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 228.0000 226.5000 m 222.0000 225.7500 L 224.2500 231.0000 L 228.0000 226.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 223.5000 214.5000 m 223.5000 215.2500 L 223.5000 216.0000 L 223.5000 216.0000 L 222.7500 216.7500 L 222.0000 216.7500 L 221.2500 216.7500 L 221.2500 216.7500 L 220.5000 216.7500 L 219.7500 216.0000 L 219.7500 215.2500 L 219.7500 215.2500 L 219.7500 214.5000 L 219.7500 213.7500 L 220.5000 213.7500 L 220.5000 213.0000 L 221.2500 213.0000 L 222.0000 213.0000 L 222.7500 213.0000 L 222.7500 213.0000 L 223.5000 213.7500 L 223.5000 214.5000 L 223.5000 214.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 228.0000 156.0000 m 222.0000 154.5000 L 224.2500 160.5000 L 228.0000 156.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 223.5000 143.2500 m 223.5000 144.0000 L 223.5000 144.7500 L 223.5000 144.7500 L 222.7500 145.5000 L 222.7500 146.2500 L 222.0000 146.2500 L 221.2500 146.2500 L 221.2500 146.2500 L 220.5000 145.5000 L 219.7500 144.7500 L 219.7500 144.7500 L 219.7500 144.0000 L 219.7500 143.2500 L 219.7500 143.2500 L 220.5000 142.5000 L 221.2500 141.7500 L 221.2500 141.7500 L 222.0000 141.7500 L 222.7500 141.7500 L 222.7500 142.5000 L 223.5000 143.2500 L 223.5000 143.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 228.0000 84.0000 m 222.0000 84.0000 L 225.0000 88.5000 L 228.0000 84.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 223.5000 202.5000 m 223.5000 201.7500 L 223.5000 201.0000 L 223.5000 200.2500 L 223.5000 200.2500 L 223.5000 199.5000 L 222.7500 198.7500 L 222.7500 198.7500 L 222.0000 198.7500 L 221.2500 198.7500 L 220.5000 198.7500 L 220.5000 199.5000 L 219.7500 199.5000 L 219.7500 200.2500 L 219.7500 201.0000 L 219.7500 201.7500 L 220.5000 201.7500 L 220.5000 202.5000 L 221.2500 202.5000 L 222.0000 202.5000 L 222.0000 202.5000 L 222.7500 202.5000 L 223.5000 202.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 238.5000 291.0000 m 232.5000 289.5000 L 237.7500 285.7500 L 238.5000 291.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 223.5000 131.2500 m 223.5000 130.5000 L 223.5000 130.5000 L 223.5000 129.7500 L 223.5000 129.0000 L 223.5000 128.2500 L 222.7500 128.2500 L 222.7500 127.5000 L 222.0000 127.5000 L 221.2500 127.5000 L 220.5000 128.2500 L 220.5000 128.2500 L 219.7500 129.0000 L 219.7500 129.7500 L 219.7500 129.7500 L 219.7500 130.5000 L 220.5000 131.2500 L 220.5000 131.2500 L 221.2500 132.0000 L 222.0000 132.0000 L 222.0000 132.0000 L 222.7500 131.2500 L 223.5000 131.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 238.5000 220.5000 m 232.5000 218.2500 L 237.7500 214.5000 L 238.5000 220.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 223.5000 60.0000 m 223.5000 60.0000 L 223.5000 59.2500 L 223.5000 58.5000 L 223.5000 57.7500 L 223.5000 57.7500 L 222.7500 57.0000 L 222.0000 57.0000 L 222.0000 57.0000 L 221.2500 57.0000 L 220.5000 57.0000 L 220.5000 57.7500 L 219.7500 58.5000 L 219.7500 58.5000 L 219.7500 59.2500 L 219.7500 60.0000 L 220.5000 60.0000 L 220.5000 60.7500 L 221.2500 60.7500 L 222.0000 60.7500 L 222.7500 60.7500 L 222.7500 60.7500 L 223.5000 60.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 238.5000 148.5000 m 232.5000 147.7500 L 237.0000 143.2500 L 238.5000 148.5000 L F U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 186.0000 335.2500 m 193.5000 342.7500 L 213.0000 339.0000 L 228.7500 345.7500 L 236.2500 342.7500 L 228.7500 335.2500 L 223.5000 339.0000 L 207.7500 331.5000 L 186.0000 335.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 228.7500 335.2500 m 228.7500 301.5000 L 236.2500 308.2500 L 236.2500 342.7500 L 228.7500 335.2500 L B U u 0.000 0.000 0.000 0.000 k 186.0000 301.5000 m 207.7500 297.7500 L 223.5000 305.2500 L 228.7500 301.5000 L 228.7500 335.2500 L 223.5000 339.0000 L 207.7500 331.5000 L 186.0000 335.2500 L 186.0000 301.5000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 228.7500 349.5000 m 236.2500 357.0000 L 236.2500 370.5000 L 228.7500 363.7500 L 228.7500 349.5000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 186.0000 363.7500 m 228.7500 363.7500 L 236.2500 370.5000 L 193.5000 370.5000 L 186.0000 363.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 349.5000 m 228.7500 349.5000 L 228.7500 363.7500 L 186.0000 363.7500 L 186.0000 349.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 354.0000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sh_succ\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 228.7500 335.2500 m 236.2500 342.7500 L 236.2500 357.0000 L 228.7500 349.5000 L 228.7500 335.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 335.2500 m 228.7500 335.2500 L 228.7500 349.5000 L 186.0000 349.5000 L 186.0000 335.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 339.7500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sh_prev\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 228.7500 306.7500 m 236.2500 314.2500 L 236.2500 328.5000 L 228.7500 321.0000 L 228.7500 306.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 306.7500 m 228.7500 306.7500 L 228.7500 321.0000 L 186.0000 321.0000 L 186.0000 306.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 312.0000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (v_next\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 228.7500 321.0000 m 236.2500 328.5000 L 236.2500 342.7500 L 228.7500 335.2500 L 228.7500 321.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 321.0000 m 228.7500 321.0000 L 228.7500 335.2500 L 186.0000 335.2500 L 186.0000 321.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 326.2500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sh_data\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 186.0000 406.5000 m 193.5000 413.2500 L 213.0000 409.5000 L 228.7500 417.0000 L 236.2500 413.2500 L 228.7500 406.5000 L 223.5000 409.5000 L 207.7500 402.7500 L 186.0000 406.5000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 228.7500 406.5000 m 228.7500 372.0000 L 236.2500 379.5000 L 236.2500 413.2500 L 228.7500 406.5000 L B U u 0.000 0.000 0.000 0.000 k 186.0000 372.0000 m 207.7500 369.0000 L 223.5000 375.7500 L 228.7500 372.0000 L 228.7500 406.5000 L 223.5000 409.5000 L 207.7500 402.7500 L 186.0000 406.5000 L 186.0000 372.0000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 228.7500 420.7500 m 236.2500 427.5000 L 236.2500 441.7500 L 228.7500 435.0000 L 228.7500 420.7500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 186.0000 435.0000 m 228.7500 435.0000 L 236.2500 441.7500 L 193.5000 441.7500 L 186.0000 435.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 420.7500 m 228.7500 420.7500 L 228.7500 435.0000 L 186.0000 435.0000 L 186.0000 420.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 425.2500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sh_succ\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 228.7500 406.5000 m 236.2500 413.2500 L 236.2500 427.5000 L 228.7500 420.7500 L 228.7500 406.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 406.5000 m 228.7500 406.5000 L 228.7500 420.7500 L 186.0000 420.7500 L 186.0000 406.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 411.0000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sh_prev\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 228.7500 378.0000 m 236.2500 384.7500 L 236.2500 399.0000 L 228.7500 392.2500 L 228.7500 378.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 378.0000 m 228.7500 378.0000 L 228.7500 392.2500 L 186.0000 392.2500 L 186.0000 378.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 382.5000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (v_next\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 228.7500 392.2500 m 236.2500 399.0000 L 236.2500 413.2500 L 228.7500 406.5000 L 228.7500 392.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 392.2500 m 228.7500 392.2500 L 228.7500 406.5000 L 186.0000 406.5000 L 186.0000 392.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 396.7500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sh_data\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 1.000 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 223.5000 426.7500 m 223.5000 427.5000 L 223.5000 428.2500 L 223.5000 428.2500 L 223.5000 429.0000 L 222.7500 429.0000 L 222.0000 429.7500 L 222.0000 429.7500 L 221.2500 429.7500 L 220.5000 429.0000 L 220.5000 429.0000 L 219.7500 428.2500 L 219.7500 427.5000 L 219.7500 427.5000 L 219.7500 426.7500 L 220.5000 426.0000 L 220.5000 426.0000 L 221.2500 425.2500 L 222.0000 425.2500 L 222.7500 425.2500 L 222.7500 426.0000 L 223.5000 426.0000 L 223.5000 426.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 228.0000 366.7500 m 222.0000 367.5000 L 225.7500 372.0000 L 228.0000 366.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 223.5000 273.0000 m 223.5000 272.2500 L 223.5000 271.5000 L 223.5000 270.7500 L 223.5000 270.7500 L 223.5000 270.0000 L 222.7500 270.0000 L 222.0000 269.2500 L 221.2500 269.2500 L 221.2500 270.0000 L 220.5000 270.0000 L 219.7500 270.7500 L 219.7500 270.7500 L 219.7500 271.5000 L 219.7500 272.2500 L 219.7500 273.0000 L 220.5000 273.0000 L 220.5000 273.7500 L 221.2500 273.7500 L 222.0000 273.7500 L 222.7500 273.7500 L 222.7500 273.0000 L 223.5000 273.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 238.5000 360.0000 m 232.5000 360.0000 L 236.2500 355.5000 L 238.5000 360.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 223.5000 355.5000 m 223.5000 356.2500 L 223.5000 357.0000 L 223.5000 357.7500 L 223.5000 357.7500 L 222.7500 358.5000 L 222.0000 358.5000 L 222.0000 358.5000 L 221.2500 358.5000 L 220.5000 358.5000 L 220.5000 357.7500 L 219.7500 357.7500 L 219.7500 357.0000 L 219.7500 356.2500 L 219.7500 355.5000 L 220.5000 355.5000 L 220.5000 354.7500 L 221.2500 354.7500 L 222.0000 354.7500 L 222.7500 354.7500 L 222.7500 354.7500 L 223.5000 355.5000 L 223.5000 355.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 228.0000 296.2500 m 222.0000 296.2500 L 225.7500 301.5000 L 228.0000 296.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 223.5000 343.5000 m 223.5000 342.7500 L 223.5000 342.7500 L 223.5000 342.0000 L 223.5000 341.2500 L 223.5000 341.2500 L 222.7500 340.5000 L 222.0000 340.5000 L 221.2500 340.5000 L 221.2500 340.5000 L 220.5000 341.2500 L 219.7500 341.2500 L 219.7500 342.0000 L 219.7500 342.7500 L 219.7500 342.7500 L 219.7500 343.5000 L 220.5000 344.2500 L 220.5000 344.2500 L 221.2500 344.2500 L 222.0000 344.2500 L 222.7500 344.2500 L 222.7500 344.2500 L 223.5000 343.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 238.5000 431.2500 m 232.5000 431.2500 L 236.2500 426.0000 L 238.5000 431.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 219.7500 384.7500 m 219.7500 385.5000 L 219.7500 385.5000 L 220.5000 386.2500 L 220.5000 387.0000 L 221.2500 387.0000 L 222.0000 387.0000 L 222.0000 387.0000 L 222.7500 387.0000 L 223.5000 386.2500 L 223.5000 386.2500 L 223.5000 385.5000 L 223.5000 384.7500 L 223.5000 384.0000 L 223.5000 384.0000 L 222.7500 383.2500 L 222.7500 383.2500 L 222.0000 383.2500 L 221.2500 383.2500 L 220.5000 383.2500 L 220.5000 383.2500 L 219.7500 384.0000 L 219.7500 384.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 180.0000 357.7500 m 186.0000 357.0000 L 183.0000 362.2500 L 180.0000 357.7500 L F U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 72.7500 236.2500 m 80.2500 243.0000 L 80.2500 257.2500 L 72.7500 250.5000 L 72.7500 236.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 16.5000 250.5000 m 72.7500 250.5000 L 80.2500 257.2500 L 23.2500 257.2500 L 16.5000 250.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 16.5000 236.2500 m 72.7500 236.2500 L 72.7500 250.5000 L 16.5000 250.5000 L 16.5000 236.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 18.7500 240.7500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (m_frags_tail\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 72.7500 250.5000 m 80.2500 257.2500 L 80.2500 271.5000 L 72.7500 264.7500 L 72.7500 250.5000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 16.5000 264.7500 m 72.7500 264.7500 L 80.2500 271.5000 L 23.2500 271.5000 L 16.5000 264.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 16.5000 250.5000 m 72.7500 250.5000 L 72.7500 264.7500 L 16.5000 264.7500 L 16.5000 250.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 18.7500 255.0000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (m_null\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 72.7500 264.7500 m 80.2500 271.5000 L 80.2500 285.7500 L 72.7500 279.0000 L 72.7500 264.7500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 16.5000 279.0000 m 72.7500 279.0000 L 80.2500 285.7500 L 23.2500 285.7500 L 16.5000 279.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 16.5000 264.7500 m 72.7500 264.7500 L 72.7500 279.0000 L 16.5000 279.0000 L 16.5000 264.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 18.7500 269.2500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (m_frags\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 186.0000 477.0000 m 193.5000 484.5000 L 213.0000 480.7500 L 228.7500 487.5000 L 236.2500 484.5000 L 228.7500 477.0000 L 223.5000 480.7500 L 207.7500 474.0000 L 186.0000 477.0000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 228.7500 477.0000 m 228.7500 443.2500 L 236.2500 450.0000 L 236.2500 484.5000 L 228.7500 477.0000 L B U u 0.000 0.000 0.000 0.000 k 186.0000 443.2500 m 207.7500 439.5000 L 223.5000 447.0000 L 228.7500 443.2500 L 228.7500 477.0000 L 223.5000 480.7500 L 207.7500 474.0000 L 186.0000 477.0000 L 186.0000 443.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 228.7500 491.2500 m 236.2500 498.7500 L 236.2500 512.2500 L 228.7500 505.5000 L 228.7500 491.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 186.0000 505.5000 m 228.7500 505.5000 L 236.2500 512.2500 L 193.5000 512.2500 L 186.0000 505.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 491.2500 m 228.7500 491.2500 L 228.7500 505.5000 L 186.0000 505.5000 L 186.0000 491.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 495.7500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sh_succ\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 228.7500 477.0000 m 236.2500 484.5000 L 236.2500 498.7500 L 228.7500 491.2500 L 228.7500 477.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 477.0000 m 228.7500 477.0000 L 228.7500 491.2500 L 186.0000 491.2500 L 186.0000 477.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 481.5000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sh_prev\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 228.7500 448.5000 m 236.2500 456.0000 L 236.2500 470.2500 L 228.7500 462.7500 L 228.7500 448.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 448.5000 m 228.7500 448.5000 L 228.7500 462.7500 L 186.0000 462.7500 L 186.0000 448.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 453.7500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (rq_next\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 228.7500 462.7500 m 236.2500 470.2500 L 236.2500 484.5000 L 228.7500 477.0000 L 228.7500 462.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 462.7500 m 228.7500 462.7500 L 228.7500 477.0000 L 186.0000 477.0000 L 186.0000 462.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 188.2500 468.0000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sh_data\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 1.000 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 223.5000 187.5000 m 222.7500 188.2500 L 222.7500 188.2500 L 222.0000 188.2500 L 221.2500 188.2500 L 220.5000 188.2500 L 220.5000 188.2500 L 219.7500 187.5000 L 219.7500 186.7500 L 219.7500 186.7500 L 219.7500 186.0000 L 219.7500 185.2500 L 220.5000 185.2500 L 221.2500 184.5000 L 221.2500 184.5000 L 222.0000 184.5000 L 222.7500 184.5000 L 223.5000 185.2500 L 223.5000 185.2500 L 223.5000 186.0000 L 223.5000 186.7500 L 223.5000 187.5000 L 223.5000 187.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 279.7500 231.7500 m 285.7500 232.5000 L 282.7500 227.2500 L 279.7500 231.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 222.7500 117.7500 m 222.0000 117.7500 L 222.0000 117.7500 L 221.2500 117.7500 L 220.5000 117.7500 L 220.5000 117.0000 L 219.7500 116.2500 L 219.7500 116.2500 L 219.7500 115.5000 L 219.7500 114.7500 L 220.5000 114.0000 L 220.5000 114.0000 L 221.2500 114.0000 L 222.0000 113.2500 L 222.0000 114.0000 L 222.7500 114.0000 L 223.5000 114.0000 L 223.5000 114.7500 L 223.5000 115.5000 L 223.5000 116.2500 L 223.5000 116.2500 L 223.5000 117.0000 L 222.7500 117.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 280.5000 211.5000 m 285.7500 215.2500 L 285.0000 208.5000 L 280.5000 211.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 223.5000 327.0000 m 223.5000 327.7500 L 223.5000 327.7500 L 223.5000 328.5000 L 223.5000 329.2500 L 223.5000 330.0000 L 222.7500 330.0000 L 222.0000 330.0000 L 222.0000 330.7500 L 221.2500 330.0000 L 220.5000 330.0000 L 220.5000 330.0000 L 219.7500 329.2500 L 219.7500 328.5000 L 219.7500 327.7500 L 219.7500 327.7500 L 220.5000 327.0000 L 220.5000 326.2500 L 221.2500 326.2500 L 222.0000 326.2500 L 222.7500 326.2500 L 222.7500 326.2500 L 223.5000 327.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 282.7500 280.5000 m 285.7500 275.2500 L 279.7500 276.7500 L 282.7500 280.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 223.5000 257.2500 m 223.5000 258.0000 L 223.5000 258.7500 L 223.5000 258.7500 L 222.7500 259.5000 L 222.0000 259.5000 L 221.2500 259.5000 L 221.2500 259.5000 L 220.5000 258.7500 L 219.7500 258.7500 L 219.7500 258.0000 L 219.7500 257.2500 L 219.7500 257.2500 L 219.7500 256.5000 L 220.5000 255.7500 L 220.5000 255.7500 L 221.2500 255.7500 L 222.0000 255.0000 L 222.7500 255.7500 L 222.7500 255.7500 L 223.5000 256.5000 L 223.5000 256.5000 L 223.5000 257.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 280.5000 257.2500 m 285.7500 254.2500 L 279.7500 251.2500 L 280.5000 257.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 223.5000 498.0000 m 223.5000 498.0000 L 223.5000 498.7500 L 223.5000 499.5000 L 223.5000 499.5000 L 222.7500 500.2500 L 222.0000 500.2500 L 222.0000 500.2500 L 221.2500 500.2500 L 220.5000 500.2500 L 220.5000 499.5000 L 219.7500 499.5000 L 219.7500 498.7500 L 219.7500 498.0000 L 219.7500 497.2500 L 220.5000 497.2500 L 220.5000 496.5000 L 221.2500 496.5000 L 222.0000 496.5000 L 222.7500 496.5000 L 222.7500 496.5000 L 223.5000 497.2500 L 223.5000 498.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 228.0000 438.0000 m 222.0000 438.0000 L 225.7500 443.2500 L 228.0000 438.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 223.5000 414.7500 m 223.5000 414.0000 L 223.5000 413.2500 L 223.5000 413.2500 L 223.5000 412.5000 L 223.5000 411.7500 L 222.7500 411.7500 L 222.0000 411.0000 L 221.2500 411.0000 L 221.2500 411.7500 L 220.5000 411.7500 L 219.7500 412.5000 L 219.7500 412.5000 L 219.7500 413.2500 L 219.7500 414.0000 L 219.7500 414.7500 L 220.5000 414.7500 L 220.5000 415.5000 L 221.2500 415.5000 L 222.0000 415.5000 L 222.7500 415.5000 L 222.7500 414.7500 L 223.5000 414.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 238.5000 502.5000 m 232.5000 501.7500 L 236.2500 497.2500 L 238.5000 502.5000 L F U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 101.2500 255.7500 m 108.0000 263.2500 L 136.5000 259.5000 L 158.2500 267.0000 L 165.0000 263.2500 L 158.2500 255.7500 L 150.7500 259.5000 L 129.7500 252.7500 L 101.2500 255.7500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 158.2500 255.7500 m 158.2500 175.5000 L 165.0000 182.2500 L 165.0000 263.2500 L 158.2500 255.7500 L B U u 0.000 0.000 0.000 0.000 k 101.2500 175.5000 m 129.7500 171.7500 L 150.7500 178.5000 L 158.2500 175.5000 L 158.2500 255.7500 L 150.7500 259.5000 L 129.7500 252.7500 L 101.2500 255.7500 L 101.2500 175.5000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 158.2500 236.2500 m 165.0000 243.0000 L 165.0000 257.2500 L 158.2500 250.5000 L 158.2500 236.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 236.2500 m 158.2500 236.2500 L 158.2500 250.5000 L 101.2500 250.5000 L 101.2500 236.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 240.7500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sip_from\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 158.2500 222.0000 m 165.0000 228.7500 L 165.0000 243.0000 L 158.2500 236.2500 L 158.2500 222.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 222.0000 m 158.2500 222.0000 L 158.2500 236.2500 L 101.2500 236.2500 L 101.2500 222.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 226.5000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sip_to\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 158.2500 207.7500 m 165.0000 215.2500 L 165.0000 228.7500 L 158.2500 222.0000 L 158.2500 207.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 207.7500 m 158.2500 207.7500 L 158.2500 222.0000 L 101.2500 222.0000 L 101.2500 207.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 212.2500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sip_contact\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 158.2500 179.2500 m 165.0000 186.7500 L 165.0000 201.0000 L 158.2500 193.5000 L 158.2500 179.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 179.2500 m 158.2500 179.2500 L 158.2500 193.5000 L 101.2500 193.5000 L 101.2500 179.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 184.5000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sip_cseq\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 158.2500 193.5000 m 165.0000 201.0000 L 165.0000 215.2500 L 158.2500 207.7500 L 158.2500 193.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 193.5000 m 158.2500 193.5000 L 158.2500 207.7500 L 101.2500 207.7500 L 101.2500 193.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 198.0000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sip_call_id\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 101.2500 300.0000 m 108.0000 306.7500 L 136.5000 303.7500 L 158.2500 310.5000 L 165.0000 306.7500 L 158.2500 300.0000 L 150.7500 303.7500 L 129.7500 296.2500 L 101.2500 300.0000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 158.2500 300.0000 m 158.2500 260.2500 L 165.0000 267.0000 L 165.0000 306.7500 L 158.2500 300.0000 L B U u 0.000 0.000 0.000 0.000 k 101.2500 260.2500 m 129.7500 256.5000 L 150.7500 264.0000 L 158.2500 260.2500 L 158.2500 300.0000 L 150.7500 303.7500 L 129.7500 296.2500 L 101.2500 300.0000 L 101.2500 260.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 158.2500 306.7500 m 165.0000 314.2500 L 165.0000 328.5000 L 158.2500 321.0000 L 158.2500 306.7500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 101.2500 321.0000 m 158.2500 321.0000 L 165.0000 328.5000 L 108.0000 328.5000 L 101.2500 321.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 306.7500 m 158.2500 306.7500 L 158.2500 321.0000 L 101.2500 321.0000 L 101.2500 306.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 312.0000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sip_request\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 158.2500 292.5000 m 165.0000 300.0000 L 165.0000 314.2500 L 158.2500 306.7500 L 158.2500 292.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 292.5000 m 158.2500 292.5000 L 158.2500 306.7500 L 101.2500 306.7500 L 101.2500 292.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 297.7500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sip_status\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 158.2500 279.0000 m 165.0000 285.7500 L 165.0000 300.0000 L 158.2500 292.5000 L 158.2500 279.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 279.0000 m 158.2500 279.0000 L 158.2500 292.5000 L 101.2500 292.5000 L 101.2500 279.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 283.5000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sip_via\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 158.2500 264.7500 m 165.0000 271.5000 L 165.0000 285.7500 L 158.2500 279.0000 L 158.2500 264.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 264.7500 m 158.2500 264.7500 L 158.2500 279.0000 L 101.2500 279.0000 L 101.2500 264.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 269.2500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sip_route\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 1.000 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 149.2500 316.5000 m 148.5000 316.5000 L 147.7500 315.7500 L 147.0000 315.7500 L 147.0000 315.0000 L 146.2500 315.0000 L 146.2500 314.2500 L 146.2500 313.5000 L 147.0000 312.7500 L 147.0000 312.7500 L 147.7500 312.0000 L 147.7500 312.0000 L 148.5000 312.0000 L 149.2500 312.0000 L 150.0000 312.7500 L 150.0000 312.7500 L 150.7500 313.5000 L 150.7500 314.2500 L 150.7500 314.2500 L 150.0000 315.0000 L 150.0000 315.7500 L 149.2500 315.7500 L 149.2500 316.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 182.2500 493.5000 m 186.0000 498.7500 L 188.2500 492.7500 L 182.2500 493.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 151.5000 288.0000 m 150.7500 288.0000 L 150.0000 288.0000 L 150.0000 287.2500 L 149.2500 287.2500 L 149.2500 286.5000 L 148.5000 285.7500 L 148.5000 285.7500 L 149.2500 285.0000 L 149.2500 284.2500 L 150.0000 284.2500 L 150.0000 283.5000 L 150.7500 283.5000 L 151.5000 283.5000 L 152.2500 284.2500 L 152.2500 284.2500 L 153.0000 285.0000 L 153.0000 285.7500 L 153.0000 286.5000 L 153.0000 286.5000 L 152.2500 287.2500 L 152.2500 287.2500 L 151.5000 288.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 182.2500 423.0000 m 186.0000 427.5000 L 187.5000 421.5000 L 182.2500 423.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 152.2500 244.5000 m 151.5000 245.2500 L 150.7500 245.2500 L 150.7500 245.2500 L 150.0000 245.2500 L 149.2500 244.5000 L 149.2500 244.5000 L 148.5000 243.7500 L 148.5000 243.0000 L 149.2500 242.2500 L 149.2500 242.2500 L 149.2500 241.5000 L 150.0000 241.5000 L 150.7500 241.5000 L 151.5000 241.5000 L 151.5000 241.5000 L 152.2500 241.5000 L 153.0000 242.2500 L 153.0000 243.0000 L 153.0000 243.0000 L 153.0000 243.7500 L 152.2500 244.5000 L 152.2500 244.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 180.7500 283.5000 m 186.0000 285.7500 L 185.2500 279.7500 L 180.7500 283.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 153.0000 228.0000 m 153.0000 228.7500 L 153.0000 229.5000 L 153.0000 230.2500 L 152.2500 230.2500 L 152.2500 231.0000 L 151.5000 231.0000 L 150.7500 231.0000 L 150.0000 231.0000 L 150.0000 231.0000 L 149.2500 230.2500 L 149.2500 229.5000 L 148.5000 229.5000 L 148.5000 228.7500 L 149.2500 228.0000 L 149.2500 228.0000 L 150.0000 227.2500 L 150.7500 227.2500 L 150.7500 227.2500 L 151.5000 227.2500 L 152.2500 227.2500 L 152.2500 228.0000 L 153.0000 228.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 182.2500 219.7500 m 186.0000 215.2500 L 180.0000 214.5000 L 182.2500 219.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 152.2500 198.7500 m 152.2500 199.5000 L 153.0000 199.5000 L 153.0000 200.2500 L 153.0000 201.0000 L 153.0000 201.7500 L 152.2500 201.7500 L 152.2500 202.5000 L 151.5000 202.5000 L 150.7500 202.5000 L 150.0000 202.5000 L 150.0000 202.5000 L 149.2500 201.7500 L 149.2500 201.7500 L 148.5000 201.0000 L 148.5000 200.2500 L 149.2500 199.5000 L 149.2500 199.5000 L 150.0000 198.7500 L 150.0000 198.7500 L 150.7500 198.7500 L 151.5000 198.7500 L 152.2500 198.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 186.0000 150.0000 m 186.0000 144.0000 L 180.7500 147.0000 L 186.0000 150.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 151.5000 184.5000 m 152.2500 184.5000 L 152.2500 185.2500 L 153.0000 186.0000 L 153.0000 186.0000 L 153.0000 186.7500 L 153.0000 187.5000 L 152.2500 188.2500 L 152.2500 188.2500 L 151.5000 188.2500 L 150.7500 188.2500 L 150.0000 188.2500 L 150.0000 188.2500 L 149.2500 187.5000 L 149.2500 187.5000 L 148.5000 186.7500 L 148.5000 186.0000 L 149.2500 186.0000 L 149.2500 185.2500 L 150.0000 184.5000 L 150.0000 184.5000 L 150.7500 184.5000 L 151.5000 184.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 187.5000 79.5000 m 186.0000 72.7500 L 182.2500 77.2500 L 187.5000 79.5000 L F U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 72.7500 279.0000 m 80.2500 285.7500 L 80.2500 300.0000 L 72.7500 292.5000 L 72.7500 279.0000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 16.5000 292.5000 m 72.7500 292.5000 L 80.2500 300.0000 L 23.2500 300.0000 L 16.5000 292.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 16.5000 279.0000 m 72.7500 279.0000 L 72.7500 292.5000 L 16.5000 292.5000 L 16.5000 279.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 18.7500 283.5000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (m_object\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 1.000 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 223.5000 72.0000 m 223.5000 72.0000 L 223.5000 72.7500 L 223.5000 73.5000 L 223.5000 73.5000 L 223.5000 74.2500 L 222.7500 75.0000 L 222.7500 75.0000 L 222.0000 75.0000 L 221.2500 75.0000 L 220.5000 75.0000 L 220.5000 74.2500 L 219.7500 74.2500 L 219.7500 73.5000 L 219.7500 72.7500 L 219.7500 72.7500 L 219.7500 72.0000 L 220.5000 71.2500 L 221.2500 71.2500 L 221.2500 71.2500 L 222.0000 71.2500 L 222.7500 71.2500 L 223.5000 72.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 12.0000 252.7500 m 16.5000 257.2500 L 18.0000 251.2500 L 12.0000 252.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 223.5000 485.2500 m 223.5000 484.5000 L 223.5000 484.5000 L 223.5000 483.7500 L 223.5000 483.0000 L 222.7500 482.2500 L 222.7500 482.2500 L 222.0000 482.2500 L 221.2500 482.2500 L 220.5000 482.2500 L 220.5000 483.0000 L 219.7500 483.0000 L 219.7500 483.7500 L 219.7500 484.5000 L 219.7500 485.2500 L 219.7500 485.2500 L 220.5000 486.0000 L 221.2500 486.0000 L 221.2500 486.0000 L 222.0000 486.0000 L 222.7500 486.0000 L 223.5000 486.0000 L 223.5000 485.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 12.7500 262.5000 m 16.5000 257.2500 L 18.0000 263.2500 L 12.7500 262.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 63.0000 241.5000 m 63.7500 241.5000 L 64.5000 241.5000 L 65.2500 241.5000 L 65.2500 242.2500 L 65.2500 243.0000 L 65.2500 243.7500 L 65.2500 243.7500 L 65.2500 244.5000 L 64.5000 245.2500 L 63.7500 245.2500 L 63.7500 245.2500 L 63.0000 245.2500 L 62.2500 245.2500 L 62.2500 244.5000 L 61.5000 244.5000 L 61.5000 243.7500 L 61.5000 243.0000 L 61.5000 242.2500 L 61.5000 242.2500 L 62.2500 241.5000 L 63.0000 241.5000 L 63.0000 241.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 181.5000 76.5000 m 186.0000 72.7500 L 180.7500 71.2500 L 181.5000 76.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 223.5000 468.7500 m 223.5000 469.5000 L 223.5000 470.2500 L 223.5000 471.0000 L 223.5000 471.0000 L 222.7500 471.7500 L 222.7500 471.7500 L 222.0000 472.5000 L 221.2500 472.5000 L 220.5000 471.7500 L 220.5000 471.7500 L 219.7500 471.0000 L 219.7500 471.0000 L 219.7500 470.2500 L 219.7500 469.5000 L 219.7500 468.7500 L 220.5000 468.7500 L 221.2500 468.0000 L 221.2500 468.0000 L 222.0000 468.0000 L 222.7500 468.0000 L 223.5000 468.7500 L 223.5000 468.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 288.7500 319.5000 m 285.7500 314.2500 L 283.5000 319.5000 L 288.7500 319.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 223.5000 396.0000 m 223.5000 396.7500 L 223.5000 397.5000 L 223.5000 398.2500 L 223.5000 398.2500 L 223.5000 399.0000 L 222.7500 399.0000 L 222.0000 399.7500 L 221.2500 399.7500 L 221.2500 399.0000 L 220.5000 399.0000 L 219.7500 398.2500 L 219.7500 398.2500 L 219.7500 397.5000 L 219.7500 396.7500 L 219.7500 396.0000 L 220.5000 396.0000 L 221.2500 395.2500 L 221.2500 395.2500 L 222.0000 395.2500 L 222.7500 395.2500 L 222.7500 396.0000 L 223.5000 396.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 286.5000 302.2500 m 285.7500 296.2500 L 281.2500 300.7500 L 286.5000 302.2500 L F U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 72.7500 292.5000 m 80.2500 300.0000 L 80.2500 314.2500 L 72.7500 306.7500 L 72.7500 292.5000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 16.5000 306.7500 m 72.7500 306.7500 L 80.2500 314.2500 L 23.2500 314.2500 L 16.5000 306.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 16.5000 292.5000 m 72.7500 292.5000 L 72.7500 306.7500 L 16.5000 306.7500 L 16.5000 292.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 18.7500 297.7500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (m_buffer\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 1.000 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 65.2500 286.5000 m 65.2500 285.7500 L 65.2500 285.7500 L 65.2500 285.0000 L 65.2500 284.2500 L 64.5000 284.2500 L 63.7500 283.5000 L 63.0000 283.5000 L 63.0000 283.5000 L 62.2500 284.2500 L 61.5000 284.2500 L 61.5000 285.0000 L 61.5000 285.7500 L 61.5000 286.5000 L 61.5000 286.5000 L 62.2500 287.2500 L 62.2500 287.2500 L 63.0000 288.0000 L 63.7500 288.0000 L 63.7500 288.0000 L 64.5000 287.2500 L 65.2500 287.2500 L 65.2500 286.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 100.5000 308.2500 m 101.2500 314.2500 L 96.0000 311.2500 L 100.5000 308.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 63.0000 302.2500 m 63.7500 302.2500 L 64.5000 301.5000 L 65.2500 301.5000 L 65.2500 300.7500 L 65.2500 300.7500 L 65.2500 300.0000 L 65.2500 299.2500 L 65.2500 298.5000 L 64.5000 298.5000 L 64.5000 297.7500 L 63.7500 297.7500 L 63.0000 297.7500 L 62.2500 298.5000 L 62.2500 298.5000 L 61.5000 299.2500 L 61.5000 299.2500 L 61.5000 300.0000 L 61.5000 300.7500 L 61.5000 301.5000 L 62.2500 301.5000 L 63.0000 302.2500 L 63.0000 302.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 339.7500 330.0000 m 342.0000 324.7500 L 345.0000 330.0000 L 339.7500 330.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 223.5000 45.0000 m 223.5000 44.2500 L 223.5000 44.2500 L 223.5000 43.5000 L 222.7500 42.7500 L 222.7500 42.7500 L 222.0000 42.7500 L 221.2500 42.7500 L 220.5000 42.7500 L 220.5000 43.5000 L 219.7500 43.5000 L 219.7500 44.2500 L 219.7500 45.0000 L 219.7500 45.7500 L 219.7500 45.7500 L 220.5000 46.5000 L 221.2500 46.5000 L 221.2500 46.5000 L 222.0000 46.5000 L 222.7500 46.5000 L 223.5000 46.5000 L 223.5000 45.7500 L 223.5000 45.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 288.0000 195.0000 m 285.7500 201.0000 L 282.7500 195.0000 L 288.0000 195.0000 L F U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 498.0000 306.7500 m 505.5000 314.2500 L 505.5000 328.5000 L 498.0000 321.0000 L 498.0000 306.7500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 285.7500 321.0000 m 498.0000 321.0000 L 505.5000 328.5000 L 292.5000 328.5000 L 285.7500 321.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 285.7500 306.7500 m 498.0000 306.7500 L 498.0000 321.0000 L 285.7500 321.0000 L 285.7500 306.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 288.0000 312.7500 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (BYE sip:joe@example.com SIP/2.0\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 498.0000 285.7500 m 505.5000 292.5000 L 505.5000 314.2500 L 498.0000 306.7500 L 498.0000 285.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 285.7500 285.7500 m 498.0000 285.7500 L 498.0000 306.7500 L 285.7500 306.7500 L 285.7500 285.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 288.0000 298.5000 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (Via: SIP/2.0/UDP sip.example.edu\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 288.0000 289.5000 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k ( ;branch=d7f2e89c.74a72681\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 498.0000 264.7500 m 505.5000 271.5000 L 505.5000 292.5000 L 498.0000 285.7500 L 498.0000 264.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 285.7500 264.7500 m 498.0000 264.7500 L 498.0000 285.7500 L 285.7500 285.7500 L 285.7500 264.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 288.0000 277.5000 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (Via: SIP/2.0/UDP pc104.example.edu:1030\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 288.0000 267.7500 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k ( ;maddr=110.213.33.19\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 498.0000 243.0000 m 505.5000 250.5000 L 505.5000 271.5000 L 498.0000 264.7500 L 498.0000 243.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 285.7500 243.0000 m 498.0000 243.0000 L 498.0000 264.7500 L 285.7500 264.7500 L 285.7500 243.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 288.0000 256.5000 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (From: Bobby Brown \r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 288.0000 246.7500 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k ( ;tag=77241a86\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 498.0000 222.0000 m 505.5000 228.7500 L 505.5000 250.5000 L 498.0000 243.0000 L 498.0000 222.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 285.7500 222.0000 m 498.0000 222.0000 L 498.0000 243.0000 L 285.7500 243.0000 L 285.7500 222.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 288.0000 234.7500 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (To: Joe User \r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 288.0000 225.7500 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k ( ;tag=7c6276c1\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 498.0000 207.7500 m 505.5000 215.2500 L 505.5000 228.7500 L 498.0000 222.0000 L 498.0000 207.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 285.7500 207.7500 m 498.0000 207.7500 L 498.0000 222.0000 L 285.7500 222.0000 L 285.7500 207.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 288.0000 213.7500 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (Call-ID: 4c4e911b@pc104.example.edu\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 498.0000 193.5000 m 505.5000 201.0000 L 505.5000 215.2500 L 498.0000 207.7500 L 498.0000 193.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 285.7500 193.5000 m 498.0000 193.5000 L 498.0000 207.7500 L 285.7500 207.7500 L 285.7500 193.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 288.0000 199.5000 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (CSeq: 2\r) Tx TO 0.000 0.000 0.000 1.000 K %%PageTrailer gsave annotatepage grestore showpage %%Trailer Adobe_Illustrator_AI5 /terminate get exec Adobe_pattern_AI5 /terminate get exec Adobe_blend_AI5 /terminate get exec Adobe_ColorImage_AI6 /terminate get exec Adobe_typography_AI5 /terminate get exec Adobe_screens_AI5 /terminate get exec Adobe_level2_AI5 /terminate get exec %%EOF II*(@$$77II[[mm33MMff33JJ``ww33JJ``ww33GG\\pp""11@@OO^^nn}}""++33<>FFMMUUll""11@@OO^^nn}}33GG\\pp33JJ``ww33MMff33PPmm33MMff33JJ``ww33MMff((77EETTbbqq--DD[[qq::WWuu::WWuu::WWuu$$77II[[mm::WWuu""DDff""DDff))RRzz""DDff::WWuu33MMff""++33<xBGbKbQiSZq]aeJil-ntvx+|g}#c؃Bćˉ‹;Cڔ7.%Ix> ". sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/images/sip-parser2.gif000066400000000000000000000410371223300710500244550ustar00rootroot00000000000000GIF87a,@ڋF扦ʶ lz Ģh!7DJT:ܮ v4×1 i-3y'pTG7rX)I8hax%iz:YiwPiUڊwɫ*p'J<SƞGڮ/kϟ!N-;׿ :ӐLć*&DltGX!p3֏2x 1f,掃%kE$GX.KUҖ͡"q dJI-QRTՉc֭\ jd]++΂X.3ðV(ڹ1[}ho1^ZٰVz~Tկtm *+[~Y/1ȹCYg;P&#a0Qov<*ܷEٺfq7[ufxm&/Z[{`"z1tٲ>~;u,ۿ/+ wO(s' `-8&yWsQB5p%f e$#7JԔkF[֟x5ؙ3'8a[/L~ߏ<^40eO:yJ] P,q2brӛ}mn)qr {uFU*ܠ6HrPQᥣ(Iz[B%X )O }) Lp!ܗ6džԲwf~#a;Ms:0 Z|KaX7 #oXc5fB.-:Fw+Z}?Sc³Ueowߵ>4e[O/AH[Cz@İdz2Y*nL* #DJ[٨F;qdJ ZqA[L BqTaȾ8]N $+zAc`fI!WGd$<3 nile<8-Fh1/#a[dbG]B{St Z2͔%T |fepF!O',Ѱ7Mv0T+OSzlp2Vbha]9.0s0AG+^0c+b;!ZPRh6 E6q!͞a{2KyMp]ԧG@j&ϊZOmN?}oF3*:zP+THV,U |KYwWExd,~y Ѱmc sO ˊΣEC|&VjWRQl![W?չ-yftŋLW˪U O{ۜ^'UƋs5;\bJD!lK9u=e놴f}Ԏ}KBDyA\!iZ4 7bT]A'T7ӕm|{ S9^YJ8yxS5X"H&ƩGR,]P"*ɐ[VM&AhDA9_2|P3ia/i.TΝ|$UԬѴqo-`զr̄~2Ngخ=:kG3>Gzŕ4I\4Wv9 3OWIRYcԨΦAb3{]kzEJf,:&`ǰh ,2IDQ[ڜ~6ݚ5\5]!Qbn[#X#6p{PX2hPe%4|fx9#R5Ñ [9.;}K܊<(=둫޶N]˼FY߸D8۩1"B 0Ϗ3ҟP:!\}} ]/{<_;\$ .[eG/yʯv.y?B1"87މ&w;DAwf'}G o|{f.ɘ39{>&jlrHūg'3C~:Ь)9P!V*._E>UHZ+/{m|!ϸ;՝DZlD8٠}KJVk7.s(CW7ZuBvW|ub5a駀 z4mc70=1-RW'eMEuQejԖ=6OY9d=~38kKuH]9ĕhHpfx`16+ DgnRYI |Qg"<dgwsC^#i NWix ]Ƹi jG)6۸KFY떤}J7"NI7>emڊdqd*ukAGGKkj1@!PyKc;˺G!j`0YF&Z~gKz5`秊sKT;b{uh)ˈE2:zyiL2"vJ{ 'xN&nH,?U7nR ¶@Y+2%wFLLQ"v)<˚\ʻlnLq HLh t\Î ͌m+G,wܮ bLص;l!Iն6 ̛;̀&Ƶ7 z6G7zmқFh|XbǏ@>{# \kt&mvE5 ҙCOfN`񬢖z/f1}ekKFEݹԉ|ڒ7Qmiޥ8xK Ԡ\-4}ET0T̋.u6''ekւ-7קhs{܈kKĆv}5~,AI|mP~ġ:{~;ٝX˝ɩ=xq,۳Mi)Vp p,ۼpٕ-ݿṁl̪Q ,8m4v1ԛ,ڽLO}ԮݔDbzSp#-)lX&M[hHU+F*.pILc  ry\=AȅW9(<hLd(c҂ Ʀ-kAK>3ڕ$>Z y|b6>u$b/9zwO>Hkt9HJ|=\N'-"˳+lxjnSޅ)z<~q(lNţ1ギpkW 5zj+q틕%^&헏Q˽}.hנknڦ\z[i^,ߤ"a3O;Dy¡(yA "؉kAZa檢 wݭ^Mn1^N{MF݋ЮD[q)W=>2mm@}ݫ߽R^ l1IHz|t 5)"RƵqNj-R^3R'#|bkP׫v5*% .-yx'ٹ!O>Qfv\lJ󀦼qY^LH uo~th_N-[(D:sH/k9-Jlx/7{r6OoCp/Bfȯlȿ:oǏ’ o2m:< pV[@%Z{|b~uQ\Z_?X|p8HGH >YVYy<}]2[M,Oy [VB>M<58~WNf;k6R=BR*eKd:\[ bֈvhk=<"^X݄^V"%'3 W 2;=/8R>HM)T0Q:9@OcegikmoqD`~Y[j亼4VuaQ],gyq {/wU8F$;sqPO$x:u2N, ESxx ~6 OxJ<>?>;Õ5 sh?[l.\:˹ !4Ͱ&•Nzh/CYZN@J# 5 Ni1Cj謦iN[-uDH7"CDeI_γ/'=G\!+ӫFl ? :.$^s CPOekR oH/:5uɑDN13kATw!1= 9-;(;@@mLNB E9bcPb{5AHuASFU-I=1>msLq s:m(UoOQ]@alXhKi=Xİxí,B_6ít\-jdLJ' f`Tt+Dԑ.DE&[+[x5ʾhQ_/#*z_~%GJO\oOݻv:pKI (Dg~sQ&={ [݆Ù G fP~ leЗt))o2`temq{#Nx"u#DZDz1+a\oD%.MTi}"L6<90nY gB1) oHi{v/ވ08< )DǗn;\Gr dG5\<)F 3(yA0i2d 7LJ)a9P`N\-\lg:('2`(%ɘJ,GҔf 1x"MG|rPYƄfǺrQ3;_nfb9N죧|68O+6P6fBJ4bj n}d $5 F')bD{,Q-P(ʹA^sGvS٣\e!Q@/mSJi9R;Dȫ)Qj]ScQ+_2qfEj=N4^yeMSiWq U\ZPu)_!{5&k% Ey)–1\"&YњbRqԈM#Z rmgъteSz(%+lkѭ0p*gҼM\k[S-jWRb+RֵHu5zwdDK7 H@fgZ į5+;IVnfߚeK_ !N`[ҰQ\^e( ;/@ϛetH3w6Nb!gێjs=Z/{᝵rU/t $/kZ̏9k9_;eC2&̰{tY$J͌j&әod {d-۩74.Ǽ=DKnn[?blG=_FzĮ}}{=`G|giXn|ý,`>='YZ37=|Y‹lZȋ ! mB"0۲iͦ/>pCoG@kiPkp5$nS JzGPd@jKNqw ?mټ Њ*Pp j = 0qlFE!UM(fs Q밊+Q1X?j ( -<<wfƅ圐˟Y1_JYq%ߐuoPl'0'P&haQVQ @&(p$耦q ρp1qߧ`rՑ1Qoޡ tpJTEQq1 r!1!2"iϮf %"\ R 12$ $g"yC$U!9e1qp%eG%7)^r&I$&c|R'1(o$'1]L$r*Pd**R+ +*3i,&1r-Gmm. .+ێ/Z0_0M-M.O1ӾRD?Vπ*.D /<GXE&Ƥ(GS<4 JZ ј*ezF`36N,Gd_3sd,7s SP2~36K3ΪLQ;D;2S8>/h}N3$]@ A&E#$"l t?I=w9ѮKvx(LBAKA!&v X3DU?R/1a$-tFi)A"DwtdTSH̊,*OО)!SHJ͒H׺4r sLɴLԏFP@oMKGB QV,lH42/tɭu+LNc :(hG*6HER3Jl58%UGIV4t-auH]U?S To1M|tuWE Ǜ4R[J5 Xg5W/Z[5L9m'E\CMRmu\ɕ8ltDki\[ap@صctX_OU-8#Gu5a3,ÅLNGrԡNs\z>d &k5O4e_-U7U WbveA*pZ-Iyb}|ɒd HK-NBTfUNm2:vfqr3=ǖlEH GSm4j//R&'6 oUo|%wpp)Juv46^;f5p^V3r1U/0׵GrmٖYJPnW(AgI@Rp6OqSR& H6{*ȼ2vh\s]Rv 2׳PsQzxvuqHh[B2 ױd8ycey j_#ݷ0 sK}zה?[tbF'Vu)jqׂ%5nEW|6[HxCV[@?xOl37fE "qWAkw.Īu%:qfmh4;*}oKS$t4WOsTM%AXtS썃%NxYq!Xg~5G 0dAOnfxʘ"՘Oe^159P4?Y SfE'P w͊4BP1O}{/s9V9q1XhLֈXw)w$ז.٘ kX7 81~U93oIm9uNѤV6\:lyj9'w_ٞ m^52=RYYf8V 95Z3jUv+[z]y$yzq%ڭ4n{٩zsZ7QGKww)mhx0:]ښVK0xձz*mo9t zMlYXLu{kՉ-`6TeB:,a Eo:WeҬ׎76S/iyr*ϚI[7wiZ|Egڶ ywۨAz^[+/Ƶ{[%gu3YX{eu}:Sq T۬;Iey[yU]9Z{PbWX8Npٜ|걾ǘ,'kQ>՞r+҃=ѣ=ZUѫ9CU:KI]JUǟ};ݷ7|Y~9.zÇ$h_{E&O57s>ޢy*>-7DQ}/s*0SĜ:]v_*DI# [g2qC2>Eygz?6ӽSj_ҋjE@!n6;nRƭ3vm^+À; n *2(#B[*&QM.i gd/4Y^-뺣VyV!\aٔםX%f&#_i#܁jgL+lԚ+S/ppi2*npè K q#76xxs*9lz7ιsg`h4?WլzviԲ@}2( 7rf`%V"h3t%%aJ,>qLt.'hP=%B/C$j?ԈEْͨU ԢH]Ъj΋k궪LCM跭c~j$tD`Ž{4mPÍ9%&I˅'M{,牫Cvhzf;H ctCI3Pߜ{)Hfwem]^#g4kbqYr~E!4u/Z@I|vnt{6WU2߃ 6 j(ځ`( tI|˨L#1X-SDן@ + 1M\I*M89!>ɑTvQ Xa9fhe4y_rQ=RUk",uřQdNfVQ XThkۢ5ߖ)#VDԩ|i~''-ƦdjasBBɪy 6+b򒦤:Rp֥^W [ےJ+Ϗ*^~]jeZ}{m榭KYEhVFJzp"x껯Kնh-XlETzl~ XW"ѷ<2%|2)2-21|Vdu)88%~qa晖Xl/YOC3^BYPR$2@eS5quƘI^9*˜,C.o~*6׊DyMqK# a[-6{Mꫪj1iRזi4zuZs>m׽ɼ<R|eǜH eG-j+Y^M,.M"@(+Zq_c.ͪT=]n60!#%Jd1j|! l]8p|j `"EOLbta632mJ֋Vv9'wȘ@l #lӾw"^٪ܭFo+ ;96QCtϑYn/-xH+wS'7n;֬&IIE*^bMqq\2B{ u|ӝ.=ͩOx!4(wTPN>qAQeg|]E3jmE4|&=)JSґ0#6@{~J[Hy>/ƔSVf􁀿:Ϳ5riJP?ۅTzӬG<#ET6?SbPFPnS eU9Pby*/Eu,#'_{̆5,IUUp4,`ŦLccnHJ^ΒBD$Aʞz)x>UwԎs؇oFxV5ܢf@uPqƟdEmPm oDJقW=m '6WY4[Y·/_+تefl*v 5yUrb߉ؑT ~/A |ZS$ԍV||7K-Ǐ&P_Bvj)vz{Z!OSSTyb(;eĭGSl5wMi@frqkL $*xz%KWٌ"Bxʆ>4eю~4aFҎnYoZE m6QE褻HQ>ɫ\ᕯ԰8pfFtu+ԆzKvE N9udtq-Vn=n肽b8O r56S 6ox;4'_ʖ1Q~qtkp}ࠕq/.ɲ,߉]̅)%IvS N(No+]xxn϶ҳu:LbϚ1NBfl7{zCb3Q dgzֹ'ж> _? EW#[}fiY&p jѭcOBNq̞(+@]Ro`x^eN7Rw*wbk|5,xۗqqwd,IN?XU%K4yW֞?R{pEh&-=;w+CD*>D=< ͘q^[_G FTMOK(UU RyPRrZn`o}VyU  `VEWzy_iqSaЙPY)H I!RjYɠay[z܀HN%Y!Y%_"$=L G!~9@`-"#r Z$b%^h")[*",C+_52I`,_)"Q!"0eX›j0Nc0>!὞I}me`qc2Xʍ Lֽ]c.^f^@: ZI!#I^HS <~GNd@$GDzU c#L,uJƐd%%쵎5LH>]9}[%֢1c:#2N_;1ݐ%BʝWB!Sh, bU^R#$ "/|*NX%a2$%ca_`eW`6&DYDm)dA|&gk*2! JDҝ1#fkkJazH _YU fo J8j`9n#.j#E6ZJ51M^MZM>>o>t'X1$Z8NC`]^tyq9&{Φ1'|Li'J`5~ PR_e.Fޏ&,I~%u6l&gYejE-_ZzcBfL<&+V^f"1YXXz 2ܙ4؁/E4YlBYg7M)Qљ)Ʃ)ƨ"- s:eUA;룞`DTf)ҫ+?R P*编$Uj)$XMZ->l_ Z$if+4bJlF0B-\Eb˺lȹ^r^v+lb,꒛d ݬ\njkQB vٓ"m$lB"hz*N ) D !O(l-ۂmھޭctmmޢNg؉YrU|"K~Ͳ\)J1\e}Y! amk`"j鞮27T+. .&Rn ή9/rPMV>9>m\Dթ>i/kB[Zmbo'ihoޮ׎X#lCYj pfθC)0!6 /:eOY0Blw0O"B#^- p6m;ip 7m'Mrj1V\հ ύmD0*/91*%K>M>?y#r/I1ٱqʄ / WpniP.2 /~Y$ZZ&qh!Q0Êr1_V]gIh&+2&rn Ej%Gj)2/{273\ 3yB&2>+k qٶz(7r9C7Se!++3226 1+#93v"h$##;3[ٺyeZt,3/? 0@_2;^ADw_ΊydSkCF/7V-uq Vx9 8bx_ :9nb48%k'PK8nKz<pp*#zOLb~yTe(/:czcnjm"5s٩x{?{FY#2笶cL{/gj{k;1l*{(SE{x#]7Bmg':|YoqDOJf-<'R#C1_80S{Otȋl3f[rnrϸ͟n7xי[|plG ?ͥc#}~rv)zRKnOW8[s=*s{X û*#xs.[߸}g/x=}]l].[h'y ʆ:lFbl3<;*>>>~w>~>>ìC?g;sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/images/sip-parser3.eps000066400000000000000000007143171223300710500245100ustar00rootroot00000000000000%!PS-Adobe-3.0 EPSF-3.0 %%Creator: ImageMark Software Labs %%For: () () %%Title: G:\Docs\Sofia\Graphics\sip-parser3.eps %%CreationDate: () () %%BoundingBox: 0 0 556 378 %%DocumentProcessColors: Black %%ColorUsage:Color %%DocumentFonts: Helvetica %%+Helvetica-Bold %%+Helvetica-Oblique %%+Helvetica-BoldOblique %%+Times-Roman %%+Times-Bold %%+Times-Italic %%+Times-BoldItalic %%+Courier %%+Courier-Bold %%+Courier-Oblique %%+Courier-BoldOblique %%+Symbol %%DocumentSuppliedResources: procset Adobe_level2_AI5 1.2 0 %%+ procset Adobe_screens_AI5 1.0 0 %%+ procset Adobe_typography_AI5 1.0 0 %%+ procset Adobe_ColorImage_AI6 1.1 0 %%+ procset Adobe_blend_AI5 1.0 0 %%+ procset Adobe_pattern_AI5 1.0 0 %%+ procset Adobe_Illustrator_AI5 1.0 0 %AI5_FileFormat 3.0 %AI3_ColorUsage: Color %AI3_TemplateBox: 0 0 556 378 %AI3_TileBox: 0 0 556 378 %AI3_DocumentPreview: None %%Template: %%PageOrigin:0.0000 0.0000 %AI7_GridSettings: 72 8 72 8 1 0 0.8 0.8 0.8 0.9 0.9 0.9 %%EndComments %%BeginProlog %%BeginResource: procset Adobe_level2_AI5 1.2 0 %%Title: (Adobe Illustrator (R) Version 5.0 Level 2 Emulation) %%Version: 1.2 0 %%CreationDate: (04/10/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /Adobe_level2_AI5 25 dict dup begin put /packedarray where not { userdict begin /packedarray { array astore readonly } bind def /setpacking /pop load def /currentpacking false def end 0 } if pop userdict /defaultpacking currentpacking put true setpacking /initialize { Adobe_level2_AI5 begin } bind def /terminate { currentdict Adobe_level2_AI5 eq { end } if } bind def mark /setcustomcolor where not { /findcmykcustomcolor { 0 6 packedarray } bind def /findrgbcustomcolor { 1 5 packedarray } bind def /setcustomcolor { exch aload pop 0 eq { pop 4 { 4 index mul 4 1 roll } repeat 5 -1 roll pop setcmykcolor } { pop 3 { 1 exch sub 3 index mul 1 exch sub 3 1 roll } repeat 4 -1 roll pop setrgbcolor } ifelse } def } if /gt38? mark {version cvr cvx exec} stopped {cleartomark true} {38 gt exch pop} ifelse def userdict /deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt put userdict /level2? systemdict /languagelevel known dup { pop systemdict /languagelevel get 2 ge } if put /level2ScreenFreq { begin 60 HalftoneType 1 eq { pop Frequency } if HalftoneType 2 eq { pop GrayFrequency } if HalftoneType 5 eq { pop Default level2ScreenFreq } if end } bind def userdict /currentScreenFreq level2? {currenthalftone level2ScreenFreq} {currentscreen pop pop} ifelse put level2? not { /setcmykcolor where not { /setcmykcolor { exch .11 mul add exch .59 mul add exch .3 mul add 1 exch sub setgray } def } if /currentcmykcolor where not { /currentcmykcolor { 0 0 0 1 currentgray sub } def } if /setoverprint where not { /setoverprint /pop load def } if /selectfont where not { /selectfont { exch findfont exch dup type /arraytype eq { makefont } { scalefont } ifelse setfont } bind def } if /cshow where not { /cshow { [ 0 0 5 -1 roll aload pop ] cvx bind forall } bind def } if } if cleartomark /anyColor? { add add add 0 ne } bind def /testColor { gsave setcmykcolor currentcmykcolor grestore } bind def /testCMYKColorThrough { testColor anyColor? } bind def userdict /composite? level2? { gsave 1 1 1 1 setcmykcolor currentcmykcolor grestore add add add 4 eq } { 1 0 0 0 testCMYKColorThrough 0 1 0 0 testCMYKColorThrough 0 0 1 0 testCMYKColorThrough 0 0 0 1 testCMYKColorThrough and and and } ifelse put composite? not { userdict begin gsave /cyan? 1 0 0 0 testCMYKColorThrough def /magenta? 0 1 0 0 testCMYKColorThrough def /yellow? 0 0 1 0 testCMYKColorThrough def /black? 0 0 0 1 testCMYKColorThrough def grestore /isCMYKSep? cyan? magenta? yellow? black? or or or def /customColor? isCMYKSep? not def end } if end defaultpacking setpacking %%EndResource %%BeginResource: procset Adobe_typography_AI5 1.0 1 %%Title: (Typography Operators) %%Version: 1.0 %%CreationDate:(03/26/93) () %%Copyright: ((C) 1987-1993 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_typography_AI5 54 dict dup begin put /initialize { begin begin Adobe_typography_AI5 begin Adobe_typography_AI5 { dup xcheck { bind } if pop pop } forall end end end Adobe_typography_AI5 begin } def /terminate { currentdict Adobe_typography_AI5 eq { end } if } def /modifyEncoding { /_tempEncode exch ddef /_pntr 0 ddef { counttomark -1 roll dup type dup /marktype eq { pop pop exit } { /nametype eq { _tempEncode /_pntr dup load dup 3 1 roll 1 add ddef 3 -1 roll put } { /_pntr exch ddef } ifelse } ifelse } loop _tempEncode } def /TE { StandardEncoding 256 array copy modifyEncoding /_nativeEncoding exch def } def % /TZ { dup type /arraytype eq { /_wv exch def } { /_wv 0 def } ifelse /_useNativeEncoding exch def pop pop findfont _wv type /arraytype eq { _wv makeblendedfont } if dup length 2 add dict begin mark exch { 1 index /FID ne { def } if cleartomark mark } forall pop /FontName exch def counttomark 0 eq { 1 _useNativeEncoding eq { /Encoding _nativeEncoding def } if cleartomark } { /Encoding load 256 array copy modifyEncoding /Encoding exch def } ifelse FontName currentdict end definefont pop } def /tr { _ax _ay 3 2 roll } def /trj { _cx _cy _sp _ax _ay 6 5 roll } def /a0 { /Tx { dup currentpoint 3 2 roll tr _psf newpath moveto tr _ctm _pss } ddef /Tj { dup currentpoint 3 2 roll trj _pjsf newpath moveto trj _ctm _pjss } ddef } def /a1 { /Tx { dup currentpoint 4 2 roll gsave dup currentpoint 3 2 roll tr _psf newpath moveto tr _ctm _pss grestore 3 1 roll moveto tr sp } ddef /Tj { dup currentpoint 4 2 roll gsave dup currentpoint 3 2 roll trj _pjsf newpath moveto trj _ctm _pjss grestore 3 1 roll moveto tr jsp } ddef } def /e0 { /Tx { tr _psf } ddef /Tj { trj _pjsf } ddef } def /e1 { /Tx { dup currentpoint 4 2 roll gsave tr _psf grestore 3 1 roll moveto tr sp } ddef /Tj { dup currentpoint 4 2 roll gsave trj _pjsf grestore 3 1 roll moveto tr jsp } ddef } def /i0 { /Tx { tr sp } ddef /Tj { trj jsp } ddef } def /i1 { W N } def /o0 { /Tx { tr sw rmoveto } ddef /Tj { trj swj rmoveto } ddef } def /r0 { /Tx { tr _ctm _pss } ddef /Tj { trj _ctm _pjss } ddef } def /r1 { /Tx { dup currentpoint 4 2 roll currentpoint gsave newpath moveto tr _ctm _pss grestore 3 1 roll moveto tr sp } ddef /Tj { dup currentpoint 4 2 roll currentpoint gsave newpath moveto trj _ctm _pjss grestore 3 1 roll moveto tr jsp } ddef } def /To { pop _ctm currentmatrix pop } def /TO { iTe _ctm setmatrix newpath } def /Tp { pop _tm astore pop _ctm setmatrix _tDict begin /W { } def /h { } def } def /TP { end iTm 0 0 moveto } def /Tr { _render 3 le { currentpoint newpath moveto } if dup 8 eq { pop 0 } { dup 9 eq { pop 1 } if } ifelse dup /_render exch ddef _renderStart exch get load exec } def /iTm { _ctm setmatrix _tm concat 0 _rise translate _hs 1 scale } def /Tm { _tm astore pop iTm 0 0 moveto } def /Td { _mtx translate _tm _tm concatmatrix pop iTm 0 0 moveto } def /iTe { _render -1 eq { } { _renderEnd _render get dup null ne { load exec } { pop } ifelse } ifelse /_render -1 ddef } def /Ta { pop } def /Tf { dup 1000 div /_fScl exch ddef % selectfont } def /Tl { pop 0 exch _leading astore pop } def /Tt { pop } def /TW { 3 npop } def /Tw { /_cx exch ddef } def /TC { 3 npop } def /Tc { /_ax exch ddef } def /Ts { /_rise exch ddef currentpoint iTm moveto } def /Ti { 3 npop } def /Tz { 100 div /_hs exch ddef iTm } def /TA { pop } def /Tq { pop } def /Th { pop pop pop pop pop } def /TX { pop } def /Tk { exch pop _fScl mul neg 0 rmoveto } def /TK { 2 npop } def /T* { _leading aload pop neg Td } def /T*- { _leading aload pop Td } def /T- { _hyphen Tx } def /T+ { } def /TR { _ctm currentmatrix pop _tm astore pop iTm 0 0 moveto } def /TS { currentfont 3 1 roll /_Symbol_ _fScl 1000 mul selectfont 0 eq { Tx } { Tj } ifelse setfont } def /Xb { pop pop } def /Tb /Xb load def /Xe { pop pop pop pop } def /Te /Xe load def /XB { } def /TB /XB load def currentdict readonly pop end setpacking %%EndResource %%BeginResource: procset Adobe_screens_AI5 1.2 0 %%Title: (Adobe Illustrator (R) Version 5.0 Custom Halftone Screens ProcSet) %%Version: 1.2 0 %%CreationDate: (03/24/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking systemdict begin userdict /Adobe_screens_AI5 15 dict dup begin put /initialize { Adobe_screens_AI5 begin /screenid deviceDPI 600 gt composite? not or { -1 } { deviceDPI currentScreenFreq dup dup 60 ge exch 150 le and deviceDPI 300 le and { pop 60 } if div 1.41421 div 0.5 add cvi } ifelse def 2 screenid eq { /customsize 16 def /customdata /customdata2 def setcustomscreen } if 3 screenid eq { /customsize 24 def /customdata /customdata3 def setcustomscreen } if 4 screenid eq { /customsize 16 def /customdata /customdata4 def setcustomscreen } if 5 screenid eq { /customsize 20 def /customdata /customdata5 def setcustomscreen } if 6 screenid eq { /customsize 24 def /customdata /customdata6 def setcustomscreen } if 7 screenid eq { /customsize 28 def /customdata /customdata7 def setcustomscreen } if 8 screenid eq { /customsize 16 def /customdata /customdata8 def setcustomscreen } if } def /terminate { currentdict Adobe_screens_AI5 eq { end } if } def /setcustomscreen { deviceDPI customsize div 0 { 1 add 2 div customsize mul cvi exch 1 add 2 div customsize mul cvi exch customsize mul add customdata load exch get 256 div } setscreen } def /customdata2 28 28 mul string def currentfile customdata2 readhexstring 4180E8694988E2634382EA6B4B8AE061A01939C8A81737C2A21B3BCAAA1636C0 F8795998F6775796FA7B5B9AF57656952ED8B80727D6B60F2FDABA0626D5B50E 4E8DE6674786EE6F4F8EE5664685ED6EAD1434C6A61F3FCEAE1232C5A51E3ECD F3745493FE7F5F9EF1725291FD7E5E9D24D3B30C2CDEBE0222D1B10A2ADDBD04 4483EB6C4C8BE1624281E96A4A89E364A31C3CCBAB1535C1A11A3AC9A91838C3 FB7C5C9BF4755594F97A5A99F778589730DBBB0525D4B40D2DD9B90828D7B710 508FE4654584EC6D4D8CE7684887EF70AF1131C4A41D3DCCAC1333C7A72040CF F0715190FC7D5D9CF2735392FF80609F21D0B00929DCBC0323D2B20B2BDFBF01 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata3 28 28 mul string def currentfile customdata3 readhexstring 011DC7F5E73D0421CBF3E43A021EC8F6E83E0522CCF2E43A2B648BC4A0762F68 8AC39E732C658CC5A177306989C29D72D5B6521A6192D9B55219608FD6B6531B 6193DAB451185F8FFCEE440C28D2FCED430B27D1FDEF450C29D3FBEC420A26D0 BEA77D366F83BCA77C356E87BFA87E377082BBA67B346D86145B99E0AE4A1259 98DFB14E155C9AE1AD4A115897DEB04D0623CDF4E63C0420CAF8EA400723CDF4 E53B031FC9F7E93F316988C19F752E678EC6A378326A88C09F742D668DC6A278 DBB350175E91D8B8551C6395DCB24F165D90D7B7541C6294FAEC420925CFFFF1 470E2BD5F9EB410824CEFEF0460D2AD4BAA57A336C85BEAA80397180B9A47933 6B84BDA97F387181105797DDAF4C145A9CE3AB480F5696DDAE4B13599BE2AC49 021EC8F6E83E0522CCF2E43A011DC7F5E73D0421CBF3E43A2C658CC5A1773069 89C29D722B648BC4A0762F688AC39E73D6B6531B6193DAB451185F8FD5B6521A 6192D9B55219608FFDEF450C29D3FBEC420A26D0FCEE440C28D2FCED430B27D1 BFA87E377082BBA67B346D86BEA77D366F83BCA77C356E87155C9AE1AD4A1158 97DEB04D145B99E0AE4A125998DFB14E0723CDF4E53B031FC9F7E93F0623CDF4 E63C0420CAF8EA40326A88C09F742D668DC6A278316988C19F752E678EC6A378 DCB24F165D90D7B7541C6294DBB350175E91D8B8551C6395F9EB410824CEFEF0 460D2AD4FAEC420925CFFFF1470E2BD5B9A479336B84BDA97F387181BAA57A33 6C85BEAA803971800F5696DDAE4B13599BE2AC49105797DDAF4C145A9CE3AB48 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata4 28 28 mul string def currentfile customdata4 readhexstring 1139B8E0FAD2531B133BBAE2F8D05119417180A6AE9A7B4B437382A5AD987949 C08867272F6F92CAC28A66262E6E90C8E8DE5F070F37B6F2EADD5E060E36B5F0 FED6571F173FBEE6FDD5561E163EBDE5AB9E7F4F477786A1A99D7E4E467685A3 2C6C96CEC68E62222A6A95CDC58D64240C34B3F6EED95A020A32B1F5EDDB5C04 143CBBE3F9D1521A123AB9E1FBD3541C447483A4AC997A4A427281A7AF9B7C4C C38B65252D6D91C9C1896828307093CBEBDC5D050D35B4F1E9DF60081038B7F3 FCD4551D153DBCE4FFD758201840BFE7A89C7D4D457584A2AA9F8050487887A0 296994CCC48C63232B6B97CFC78F61210931B0F4ECDA5B030B33B2F7EFD85901 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata5 28 28 mul string def currentfile customdata5 readhexstring 010B34C3EBFCF7CE3F16020C35C4EDFBF6CD3E15102552A4D6EADDB5632B1126 54A5D5EADCB3622A3958768499C19E8C7C5E3A59778498C19D8B7B5DC8A99370 47334C7587AFC9AA936F46324B7485AEF1E5BC6B1E0A2351A3D8F2E4BC6A1E09 2351A2D7FFF9D14219050F38C6EFFEF9D04118040E37C6EFE8E0B7662D142856 A8D3E7DFB7652D132856A7D4BF9C8E7F603D5B7A8195BE9A8E7E603C5B798297 314A7389B2CCAD906D442F497289B1CBAC926E4508214FA1DBF4E2B9671B0720 4EA0DAF4E3BA691C030D36C5EDFBF6CD3F16010C34C3ECFDF8CF4017122654A6 D4E9DDB4622A112553A5D6EBDEB5642C3B59788397C09C8B7C5D3A58778599C2 9E8C7D5FCAAB926E46314B7486AFC8AA947048334D7587B0F2E4BB691D082250 A1D8F1E6BD6B1F0A2452A3D9FDF8CF4118030E36C5EEFFFAD1421A050F38C7F0 E6DFB6642C132755A7D3E8E1B8662E152957A8D2BE9A8D7E5F3B5A798296BF9B 8F80613D5C7B80952F487188B1CAAC916D443049728AB3CCAE906C43061F4D9F DAF3E2BA681C07214FA0DBF5E1B8671A00000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata6 28 28 mul string def currentfile customdata6 readhexstring 081A44B6E0F2FDECC150250C091B45B6E1F3FCEBC04F240C1D336199C7D8DCD3 A56C37221E33619AC8D7DBD2A46B36214864798091AEB1958C7E694C49657A81 90ADB0948B7D684BB99D8475593C405C7888A1BEBA9E8574583B3F5B7888A0BD E4CBAA712E1215326098CFE8E4CCA9712D1114315F97CEE7F5F1C6552B040719 43B5DFFAF6F0C6542A03061842B4DEF9FFEDC352270E0B1C47B8E3F4FEECC251 260D0A1C46B7E2F4DAD5A76E39232035639CCAD5D9D4A66D38231F34629BC9D6 AF938E806A4E4A677C838FABAE928D7F694D4A667B828FAC3E5A778AA3BFBC9F 8772563A3D597689A2BEBB9F8673573A14305E97D1EAE6CDA76F2B0F132F5D96 D0E9E5CDA8702C10051742B3DDFCF8EEC4522801041641B2DDFBF7EFC5532902 091B45B6E1F3FCEBC04F240C081A44B6E0F2FDECC150250C1E33619AC8D7DBD2 A46B36211D336199C7D8DCD3A56C372249657A8190ADB0948B7D684B48647980 91AEB1958C7E694CBA9E8574583B3F5B7888A0BDB99D8475593C405C7888A1BE E4CCA9712D1114315F97CEE7E4CBAA712E1215326098CFE8F6F0C6542A030618 42B4DEF9F5F1C6552B04071943B5DFFAFEECC251260D0A1C46B7E2F4FFEDC352 270E0B1C47B8E3F4D9D4A66D38231F34629BC9D6DAD5A76E39232035639CCAD5 AE928D7F694D4A667B828FACAF938E806A4E4A677C838FAB3D597689A2BEBB9F 8673573A3E5A778AA3BFBC9F8772563A132F5D96D0E9E5CDA8702C1014305E97 D1EAE6CDA76F2B0F041641B2DDFBF7EFC5532902051742B3DDFCF8EEC4522801 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata7 28 28 mul string def currentfile customdata7 readhexstring 01061B44B7E1F5FEFBE6BD4A210C01071B45B8E1F6FDFBE6BC4A200B09132A54 A7D1EAF5EED9B05D331609142B55A8D2EAF4EED9AF5C32161D2D3D6993C1CBE0 CEC59B7140301E2E3D6A93C0CADFCDC49A713F3047576C7B828DA2B6A48F867E 6F5A48576C7C828CA1B6A38F867E6E59BAAA958A78634E4451667A8498ADBAAB 968977624E4350657A8398ADE3D4C99F7539251A273C6892C2D7E4D4C89E7539 241A273B6891C1D6F8F2DDB460371005122A53A7D0ECF9F2DDB360360F051229 53A6D0EBFFFDE8BE4C220D03081D46B9E3F7FFFCE7BD4B210D02071C46B8E2F7 F3F0DBB15E34180B152C56A9D3E8F3EFDAB05D34170A142C55A9D2E9DFCCC69C 7341321F2F3F6B94BFC9DECCC59C7241311F2E3E6A94BFCAB5A38E8780705B49 596D7D808BA0B4A28D877F6F5B48586D7C818BA043506479859AAFBCAC978876 614C424F64798499AEBBAB968977624D19263B6791C3D8E5D6C79D7337231825 3A6690C3D7E5D5C79E74382304112952A5CFEDFAF0DBB25E350E03102851A5CE ECF9F1DCB25F360E01071B45B8E1F6FDFBE6BC4A200B01061B44B7E1F5FEFBE6 BD4A210C09142B55A8D2EAF4EED9AF5C321609132A54A7D1EAF5EED9B05D3316 1E2E3D6A93C0CADFCDC49A713F301D2D3D6993C1CBE0CEC59B71403048576C7C 828CA1B6A38F867E6E5947576C7B828DA2B6A48F867E6F5ABAAB968977624E43 50657A8398ADBAAA958A78634E4451667A8498ADE4D4C89E7539241A273B6891 C1D6E3D4C99F7539251A273C6892C2D7F9F2DDB360360F05122953A6D0EBF8F2 DDB460371005122A53A7D0ECFFFCE7BD4B210D02071C46B8E2F7FFFDE8BE4C22 0D03081D46B9E3F7F3EFDAB05D34170A142C55A9D2E9F3F0DBB15E34180B152C 56A9D3E8DECCC59C7241311F2E3E6A94BFCADFCCC69C7341321F2F3F6B94BFC9 B4A28D877F6F5B48586D7C818BA0B5A38E8780705B49596D7D808BA0424F6479 8499AEBBAB968977624D43506479859AAFBCAC978876614C18253A6690C3D7E5 D5C79E74382319263B6791C3D8E5D6C79D73372303102851A5CEECF9F1DCB25F 360E04112952A5CFEDFAF0DBB25E350E pop pop /customdata8 28 28 mul string def currentfile customdata8 readhexstring 050F2747B6D6EEF8FEF4DCBC4D2D1507111D375F9EC6E0E9EBE6CCA4653D1F13 2939556F8EA8C1D1D3C3AE9475573B2B4961717D808999B1B39B8B867F73634B B8A090827A6A5A42445C6C7C8492A2BAD8C8AA97785232222434546E8DACCADA F0E2CFA768401A0A0C1C365E9DC5E4F2FAF7DFBF50301802040E2646B5D5EDFC FFF5DDBD4E2E160806102848B7D7EFF9EAE7CDA5663E2014121E38609FC7E1E8 D2C2AF9576583C2C2A3A56708FA9C0D0B29A8A878074644C4A62727E818898B0 435B6B7B8593A3BBB9A19183796959412333536D8CADCBDBD9C9AB9677513121 0B1B355D9CC4E5F3F1E3CEA6673F1909030D2545B4D4ECFDFBF6DEBE4F2F1701 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop end end defaultpacking setpacking %%EndResource %%BeginResource: procset AGM_Gradient_Sep 1.0 0 %%Title: (AGM Gradient Procset) %%Version: 1.0 0 %%CreationDate: (4/26/96) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /AGM_Gradient_Sep 5 dict dup begin put /AGM_Gradient_Sep_private 100 dict def /initialize{ AGM_Gradient_Sep begin AGM_Gradient_Sep_private begin _compositeJob{ initializeSinglePassSeps }{ initializeMultiPassSeps }ifelse initializeSeps AGM_Gradient_private begin /_fillSD newSpotDict def /_rampSD newSpotDict def /_nCustomColorSD nd end AGM_Gradient_Sep_private { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall AGM_Gradient_Sep { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall end currentdict readonly pop end }def /terminate{ currentdict AGM_Gradient_Sep eq{ end }if }def AGM_Gradient_Sep_private begin /initializeSeps{ _noImage not _level2PS not and{ /_whiteBytes 1 makeByte8 pt /knockOut{ 8 setImageParms _whiteBytes /_image load 5 execImage }def /linealFill{ mySave 8 setImageParms _color{ _nCustomColorSD begin cyan magenta yellow black _spotColor{ spot1 begin /tintImage tintValue 1 exch sub makeByte8 def end spot2 begin /tintImage tintValue 1 exch sub makeByte8 def end }if end 4{ makeByte8 4 1 roll }repeat true 4 _nCustomColorSD ncolorimage }{ _nCustomColorSD/black get 1 exch sub makeByte8 _nCustomColorSD bwImage }ifelse myRestore }def }{ /knockOut{ gsave false setoverprint 1 setgray 0 0 1 1 rectfill grestore }def }ifelse /newSpotDict{ 11 dict dup begin /nSpots 2 def /spot1 7 dict def /spot2 7 dict def end }def /initSpotData { begin /name nd /tintImage nd /tintValue nd /spot_C nd /spot_M nd /spot_Y nd /spot_K nd end }def /initSpotDict{ begin /cyanInk false def /magentaInk false def /yellowInk false def /blackInk false def /cyan nd /magenta nd /yellow nd /black nd spot1 initSpotData spot2 initSpotData end }def /copySpotDict{ /_dst xp begin cyanInk magentaInk yellowInk blackInk cyan magenta yellow black spot1 spot2 end _dst begin /spot1 spot1 maxlength dict def /spot2 spot2 maxlength dict def spot2 copy pop spot1 copy pop /black xd /yellow xd /magenta xd /cyan xd /blackInk xd /yellowInk xd /magentaInk xd /cyanInk xd end }def /setCustomColor { 1 index /Black eq{ 6 1 roll 5 npop 1 exch sub setgray }{ 6 1 roll _ccAry1 astore exch dup null eq{ pop 0 }if setcustomcolor }ifelse }def /setCStop{ /_colorStyle exch pt _colorStyle 0 eq{ 0 0 0 4 -1 roll 1 exch sub _spotColor{ /_colorStyle 3 pt /Black 1 index 1 exch sub }if }if _colorStyle 2 eq{ 3 npop }if _rampSD _fillSD copySpotDict _colorStyle 4 eq{ pop 9 2 roll 3 npop 6 -2 roll } if _colorStyle 3 eq _colorStyle 4 eq or{ _fillSD begin exch dup spot1/name get eq{ spot1 spot2 }{ spot2 spot1 }ifelse begin begin /name xd 1 exch sub /tintValue xd 4{ tintValue mul 4 1 roll }repeat _spotColor not{ /tintValue null def }if end /tintValue 0 def end end }if _fillSD nsetcustomcolor }def /renderCMYK{ spot1/name get null eq spot2/name get null eq and dup not{ pop spot1 spotConverted }if dup not{ pop spot2 spotConverted }if }def /fill_ /fill load def /fillOvp{ currentoverprint{ _inRipSep{ currentcolorspace 0 get dup /DeviceGray eq 1 index /DeviceCMYK eq or{ pop currentcmykcolor add add add 0 eq{ newpath }if }{ /Separation eq{ currentcolor 0 eq{ newpath }if }if }ifelse }{ currentgray 1 eq{ newpath }if }ifelse }if fill_ }def /fill{ _nCustomColorSD begin renderCMYK { fillOvp }{ spot1 begin gsave name null ne{ spot_C spot_M spot_Y spot_K name tintValue setCustomColor }{ 1 setgray }ifelse fillOvp grestore end spot2 begin name null ne{ gsave true setoverprint spot_C spot_M spot_Y spot_K name tintValue setCustomColor fillOvp grestore }if end newpath }ifelse end }def /expandSpot{ _spotColor{ /_len xp _rampSD begin spot1 begin tintImage null ne{ tintImage _len expandOne /tintImage xd }if end spot2 begin tintImage null ne{ tintImage _len expandOne /tintImage xd }if end end }{ pop }ifelse }def /rampImage{ _rampSD begin _color{ /cyanInk _cyanData 0 ne def /magentaInk _magentaData 0 ne def /yellowInk _yellowData 0 ne def /blackInk _blackData 0 ne def _nSamples setImageParms _nSamples expandSpot _cyanData _magentaData _yellowData _blackData _nSamples 4 expandColor true 4 _rampSD ncolorimage }{ /cyanInk false def /magentaInk false def /yellowInk false def /blackInk true def _nSamples setImageParms _blackData _rampSD bwImage }ifelse end }def /nsetcustomcolor where{ pop }{ /nsetcustomcolor { /_nCustomColorSD xp _nCustomColorSD begin 4 copy /black xd /yellow xd /magenta xd /cyan xd 4 copy 0 ne /blackInk xd 0 ne /yellowInk xd 0 ne /magentaInk xd 0 ne /cyanInk xd end setcmykcolor }def }ifelse /nsetcustomcolorend where{ pop }{ /nsetcustomcolorend { /_nCustomColorSD null pt }def }ifelse }def /initializeSinglePassSeps{ /_decodeNorm [0 1] pt /_decodeInvert [1 0] pt /spotConverted { begin name null eq{ false }{ tintValue null eq tintImage null eq and{ true }{ false currentpagedevice/SeparationOrder get{name eq or}forall not }ifelse }ifelse end }def /dictImage { 20 dict dup begin /Dict xd /Decode xd /DataSource xd /ImageMatrix xd /BitsPerComponent xd /Height xd /Width xd /ImageType 1 def Dict end /_image load 1 execImage }def /bwImage{ begin gsave currentoverprint{ blackInk{ [/Separation /Black /DeviceGray{}] setcolorspace _decodeInvert dictImage }{ 5 npop }ifelse }{ /DeviceGray setcolorspace _decodeNorm dictImage }ifelse grestore end }def /ncolorimage where{ pop }{ /ncolorimage{ begin renderCMYK { cyanInk magentaInk and yellowInk and blackInk and not currentoverprint and { pop pop gsave cyanInk{ 8 copy [/Separation /Cyan /DeviceGray{}] setcolorspace 3 npop _decodeNorm dictImage }if magentaInk{ 8 copy [/Separation /Magenta /DeviceGray{}] setcolorspace 4 -1 roll 3 npop _decodeNorm dictImage }if yellowInk{ 8 copy [/Separation /Yellow /DeviceGray{}] setcolorspace 4 -2 roll 3 npop _decodeNorm dictImage }if blackInk{ 4 -3 roll [/Separation /Black /DeviceGray{}] setcolorspace 3 npop _decodeNorm dictImage }{ 8 npop }ifelse grestore }{ /_colorimage load 10 execImage }ifelse }{ 6 npop gsave spot1 begin name null ne tintImage null ne and{ [/Separation name /DeviceGray{}] setcolorspace 4 copy tintImage name /Black eq{ _decodeNorm }{ _decodeInvert }ifelse dictImage }{ 1 setgray fill }ifelse end spot2 begin true setoverprint name null ne tintImage null ne and{ [/Separation name /DeviceGray{}] setcolorspace tintImage name /Black eq{ _decodeNorm }{ _decodeInvert }ifelse dictImage }{ 4 npop 1 setgray fill }ifelse end grestore }ifelse end }def }ifelse }def /initializeMultiPassSeps{ /_isCMYKSep _cyanPlate _magentaPlate or _yellowPlate or _blackPlate or pt /invertXfer{ [ { 1 exch sub }/exec load systemdict /currenttransfer get exec /exec load ] cvx systemdict /settransfer get exec }def /ccThrough{ gsave 1 setCustomColor currentcmykcolor grestore add add add 0 ne }def /spotConverted { begin _isCMYKSep not{ false }{ name null eq{ false }{ tintValue null eq tintImage null eq and{ true }{ spot_C spot_M spot_Y spot_K name ccThrough }ifelse }ifelse }ifelse end }def /spotChannel { _isCMYKSep{ pop false }{ begin name null eq{ false }{ spot_C spot_M spot_Y spot_K name ccThrough }ifelse end }ifelse }def /getChannelData { _isCMYKSep dup{ pop renderCMYK }if { _blackPlate{ 4 1 roll 3 npop blackInk }{ _yellowPlate{ 4 2 roll 3 npop yellowInk }{ _magentaPlate{ 4 3 roll 3 npop magentaInk }{ 3 npop cyanInk }ifelse }ifelse }ifelse { true /nonZeroData }{ true /zeroData }ifelse }{ 4 npop spot1/name get null ne spot1 spotChannel and{ spot1/tintImage get dup null ne{ false /nonZeroData }{ pop false /noData }ifelse }{ spot2/name get null ne spot2 spotChannel and{ spot2/tintImage get dup null ne{ false /nonZeroData }{ pop false /noData }ifelse }{ false /noData }ifelse }ifelse }ifelse }def /renderChannelData { /_tmp xp _tmp /nonZeroData ne currentoverprint and{ pop _tmp /zeroData eq{pop}if 4 npop }{ _tmp /nonZeroData eq{ { invertXfer }if systemdict/image get 5 execImage }{ pop _tmp /zeroData eq{pop}if 4 npop knockOut }ifelse }ifelse }def /bwImage{ begin gsave dup dup dup getChannelData exch pop false exch renderChannelData grestore end }def /ncolorimage{ begin pop pop gsave spot2/name get null ne spot2 spotChannel and{ true setoverprint }if getChannelData renderChannelData grestore end }def }def end end defaultpacking setpacking %%EndResource %%BeginResource: procset AGM_Gradient 1.0 0 %%Title: (AGM Gradient Procset) %%Version: 1.0 0 %%CreationDate: (4/26/96) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /AGM_Gradient 20 dict dup begin put /AGM_Gradient_private 200 dict def /initialize { AGM_Gradient begin AGM_Gradient_private begin initializeVars /bd systemdict/mark get def /ed _level2PS { (>>) }{ (counttomark 2 idiv dup dict begin {def} repeat pop currentdict end) } ifelse cvx def _level2PS{ initializeLev2 }{ initializeLev1 }ifelse queryDevice initializeShading initializeOps _producingSeps{ AGM_Gradient_Sep/initialize get exec }{ initializeComposite }ifelse _illustrator{ /f{}def /F{}def /s{}def /S{}def /b{}def /B{}def }if /image where{ /image get /_image xd }if /colorimage where{ /colorimage get /_colorimage xd }if /rectfill where dup{ exch pop not _producingSeps or }{ not }ifelse { /rectfill{ gsave newpath 4 2 roll moveto 1 index 0 rlineto 0 1 index rlineto 1 index neg 0 rlineto pop pop closepath fill grestore }def }if /linealImage _noImage{ /rectImage load }{ _producingSeps{ AGM_Gradient_Sep/AGM_Gradient_Sep_private get begin /rampImage load end }{ /rampImage load }ifelse }ifelse def AGM_Gradient_private { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall AGM_Gradient { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall end currentdict readonly pop end }def /initializeAI { pop pop AGM_Gradient/AGM_Gradient_private get /_illustrator true put AGM_Gradient/initialize get exec AGM_Gradient begin }def /unload{ systemdict/languagelevel known{ systemdict/languagelevel get 2 ge{ userdict/AGM_Gradient_Sep 2 copy known{ undef }{ pop pop }ifelse userdict/AGM_Gradient 2 copy known{ undef }{ pop pop }ifelse }if }if }def /terminate{ currentdict AGM_Gradient eq{ end }if }def AGM_Gradient_private begin /initializeVars{ /_d255 256 array def 0 1 255{ _d255 exch dup 255 div put }bind for /_d255- 256 array def 0 1 255{ _d255- exch 1 _d255 2 index get sub put }bind for /_sSave nd /_dUserSpace matrix defaultmatrix def /_bUMatrix matrix def /_imageMatrix matrix def /_saveMatrix matrix def /_xm matrix def /_ccAry1 5 array def /_level2PS systemdict/languagelevel known dup{ pop systemdict/languagelevel get 2 ge }if def /_level3PS _level2PS systemdict/shfill known and def currentdict /_illustrator known not{ /_illustrator false def }if }def /initializeOps { AGM_Gradient begin currentdict/Bc known not{ /Bc{ _renderFlag 2 eq{ 6 npop }{ pushBSpace _rampIndex 0 eq{ pop pop setCStop }if linealFill popBSpace }ifelse }def }if currentdict/Bg known not{ /Bg{ 10 npop /_gradName xp /_renderFlag xp _renderFlag 2 ne{ _illustrator{ _of setoverprint }if _illustrator _eo and _renderFlag 3 eq or{ eoclip }{ clip }ifelse _gradNames _gradName 2 copy known{ get mark exch aload pop /_gradType xp 1 sub dup /_rampIndex xp /_maxRampIndex xp mark exch aload pop 0 0 }if pop pop getRampData }{ mark mark }ifelse }def }if currentdict/Bm known not{ /Bm{ _renderFlag 2 ne{ _gradType 0 eq{ linealRamp }{ radialGrad }ifelse }{ 6 npop }ifelse }def }if currentdict/Bh known not{ /Bh{ 2 npop /_yHi xp /_xHi xp /_radHilite _xHi 0 ne _yHi 0 ne or pt }def }if currentdict/Bn known not{ /Bn{ AGM_Gradient_private begin dict /_gradNames xp end }def }if currentdict/Bd known not{ /Bd{ AGM_Gradient begin AGM_Gradient_private begin /_nColorsBd xp /_gradType xp /_gradName xp }def }if currentdict/BD known not{ /BD{ currentdict/_gradNames known not{ /_gradNames 20 dict def }if ] _nColorsBd _gradType ] _gradName exch /_gradNames xput end end }def }if currentdict/Bb known not{ /Bb{ AGM_Gradient begin AGM_Gradient_private begin _producingSeps{ AGM_Gradient_Sep/AGM_Gradient_Sep_private get begin }if mySave }def }if currentdict/BB known not{ /BB{ /_tmp xp cleartomark cleartomark _tmp dup _renderFlag myRestore _producingSeps{ end }if _illustrator end end { 2 ne exch 0 gt and{ 2 eq{ s }{ S }ifelse }{ pop newpath }ifelse }{ pop newpath }ifelse }def }if currentdict/Xm known not{ /Xm{ _xm astore pop }def }if end }def /queryDevice{ /_inRipSep _level2PS{ currentpagedevice/Separations 2 copy known{ get }{ pop pop false }ifelse }{ false }ifelse def /_noImage /lv1Fix where{ pop lv1Fix }{ false }ifelse def /_useShells where{ pop }{ /_useShells true def }ifelse /_useSmoothShade where{ pop }{ /_useSmoothShade false def }ifelse /_cyanPlate 1 0 0 0 testCMYKColorThrough def /_magentaPlate 0 1 0 0 testCMYKColorThrough def /_yellowPlate 0 0 1 0 testCMYKColorThrough def /_blackPlate 0 0 0 1 testCMYKColorThrough def /_compositeJob _cyanPlate _magentaPlate and _yellowPlate and _blackPlate and def /_compositeSpotDevice where{ pop }{ /_compositeSpotDevice _compositeJob not _inRipSep or{ 1 }{ 0 }ifelse def }ifelse /_producingSeps _compositeSpotDevice 0 ne def /_deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt def /_dpiThreshold where{ pop }{ /_dpiThreshold 600 def }ifelse /_screenFreqThreshold where{ pop }{ /_screenFreqThreshold 150 def }ifelse /_contoneDevice where{ pop }{ /_contoneDevice false def }ifelse /_subSampleOK _deviceDPI _dpiThreshold le currentScreenFreq _screenFreqThreshold le and _contoneDevice not and _producingSeps not and def }def /initializeLev1{ /makeByte8{ /_tmp 0 pt 255 mul cvi 8 string 8{ dup _tmp 3 index put /_tmp _tmp 1 add pt }repeat exch pop }def /currentScreenFreq{ currentscreen pop pop }def /_byte 1 string def /colorimage where{ pop }{ /colorimage{ pop pop /_blackTmp xp /_yellowTmp xp /_magentaTmp xp /_cyanTmp xp /_cnt 0 pt [ _byte dup 0 _cyanTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .3 /mul cvx _magentaTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .59 /mul cvx _yellowTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .11 /mul cvx _blackTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx /add cvx /add cvx /add cvx 1 /exch cvx /sub cvx /dup cvx 0 /lt cvx{ pop 0 }/if cvx /dup cvx 1 /gt cvx{ pop 1 }/if cvx 255 /mul cvx /cvi cvx 256 /mod cvx /dup cvx 0 /lt cvx{ pop 0 }/if cvx /put cvx /_cnt dup cvx 1 /add cvx /pt cvx ] cvx bind /_image load 5 execImage }def }ifelse }def /initializeLev2{ /level2ScreenFreq{ begin 60 HalftoneType 1 eq{ pop Frequency }if HalftoneType 2 eq{ pop GrayFrequency }if HalftoneType 5 eq{ pop Default level2ScreenFreq }if end }def /currentScreenFreq{ currenthalftone level2ScreenFreq }def }def /initializeShading{ _useSmoothShade _level3PS and{ /_usingSmoothShade true pt initializeLev3_Ops }{ /_usingSmoothShade false pt }ifelse }def /initializeLev3_Ops { /initShFill{ /_index _gradType 0 eq {0}{_maxRampIndex 1 sub} ifelse pt /_rampFuncsArray _maxRampIndex array pt /_boundsArray _maxRampIndex 1 sub array pt /_encodeArray _maxRampIndex 2 mul array pt /_beginCoord _rampPoint pt /_colorSpace null pt /_firstFill _rampIndex _maxRampIndex eq pt /_lastFill false pt }def /getRampColorSpace{ _nSamples 1 gt{ /_ndx 0 pt [blendColor] cvx exec }if /_C0 [currentcolor] pt /_C0_Space currentcolorspace pt _nSamples 1 gt{ /_ndx _nSamples 1 sub pt [blendColor] cvx exec }if /_C1 [currentcolor] pt /_C1_Space currentcolorspace pt _C0_Space _C1_Space eq{ /_rampColorSpace _C0_Space pt }{ (colorspace conflict!) == showpage stop }ifelse _spotColor{ nsetcustomcolorend }if }def /linealShFill{ popBSpace _xm aload pop pushBSpace /_size _index 1 add pt _size _maxRampIndex lt { /_rampFuncsArray _rampFuncsArray 0 _size getinterval pt /_boundsArray _boundsArray 0 _size 1 sub getinterval pt /_encodeArray _encodeArray 0 _size 2 mul getinterval pt }if bd /ShadingType 2 /ColorSpace _colorSpace /Function bd /FunctionType 3 /Domain [0 1] /Functions _rampFuncsArray /Bounds _boundsArray /Encode _encodeArray ed /Extend [_firstFill _lastFill] /Domain [0 1] /Coords [_beginCoord 0 _endCoord 0] ed shfill }def /radialShFill{ /_size _maxRampIndex _index sub pt _size _maxRampIndex lt { /_rampFuncsArray _rampFuncsArray _index _size getinterval pt /_boundsArray _boundsArray _index _size 1 sub getinterval pt /_encodeArray _encodeArray _index 2 mul _size 2 mul getinterval pt }if /_rampLen _beginCoord _endCoord sub pt bd /ShadingType 3 /ColorSpace _colorSpace /Function bd /FunctionType 3 /Domain [0 1] /Functions _rampFuncsArray /Bounds _boundsArray /Encode _encodeArray ed /Extend [_lastFill _firstFill] /Domain [0 1] /Coords [_xHi _rampLen mul _yHi _rampLen mul _endCoord 0 0 _beginCoord] ed shfill _radHilite{ _xHi _rampLen mul _yHi _rampLen mul translate }if }def /fillRamp{ /_invert _midPoint 0.5 lt pt _rampIndex _maxRampIndex eq { initShFill }if getRampColorSpace _colorSpace null eq{ /_colorSpace _rampColorSpace pt }{ _colorSpace _rampColorSpace ne{ /_index _index 1 _gradType 0 eq{ sub pt linealShFill }{ add pt radialShFill }ifelse initShFill /_colorSpace _rampColorSpace pt } if }ifelse /_endCoord _endPoint pt _rampFuncsArray _index bd /FunctionType 2 /Domain [0 1] /N 0.5 log _invert{1 _midPoint sub}{_midPoint}ifelse log div _gradType 0 eq{ _invert{/C1}{/C0}ifelse _C0 _invert{/C0}{/C1}ifelse _C1 }{ _invert{/C0}{/C1}ifelse _C1 _invert{/C1}{/C0}ifelse _C0 }ifelse ed put _rampIndex 1 ne{ _boundsArray _index _gradType 1 eq{1 sub}if _endCoord put } if 0 1 _invert {exch}if _encodeArray _index 2 mul 1 add 3 -1 roll put _encodeArray _index 2 mul 3 -1 roll put _rampIndex 1 eq { /_lastFill true pt _gradType 0 eq{ linealShFill }{ radialShFill }ifelse }if /_index _index 1 _gradType 0 eq{ add pt }{ sub pt }ifelse }def /radialRamp /fillRamp load def /rampImage /fillRamp load def AGM_Gradient begin /Bc{ 6 npop }def end }def /initializeComposite{ /bwImage{ pop /_image load 5 execImage }def currentdict/rampImage known not{ /rampImage{ _color{ _nSamples setImageParms _rgbRamp{ _redData _greenData _blueData _nSamples 3 expandColor true 3 null ncolorimage }{ _cyanData _magentaData _yellowData _blackData _nSamples 4 expandColor true 4 null ncolorimage }ifelse }{ _nSamples setImageParms _blackData null bwImage }ifelse }def }if /setCStop{ /_colorStyle exch pt _colorStyle 0 eq{ 1 exch sub 0 0 0 4 -1 roll }if _colorStyle 2 eq{ setrgbcolor 4 npop }if _colorStyle 3 eq{ 1 exch sub /_tmp xp pop 4{ _tmp mul 4 1 roll }repeat }if _colorStyle 4 eq{ 3 -1 roll pop pop 1 exch sub /_tmp xp 3{ 1 exch sub _tmp mul 1 exch sub 3 1 roll }repeat setrgbcolor 4 npop }if _colorStyle 2 ne _colorStyle 4 ne and{ null nsetcustomcolor }if }def /nsetcustomcolor { pop setcmykcolor }def /nsetcustomcolorend { }def /ncolorimage{ pop /_colorimage load 10 execImage }def _noImage not _level2PS not and{ /linealFill{ 8 setImageParms _color{ currentcmykcolor 4{ makeByte8 4 1 roll }repeat true 4 null ncolorimage }{ currentgray makeByte8 null bwImage }ifelse }def }if }def /npop{ {pop}repeat }def /xd{ exch def }def /nd{ null def }def /pt{ AGM_Gradient_private 3 1 roll put }def /xp{ exch pt }def /xput{ dup load dup length exch maxlength eq{ dup dup load dup length 2 mul dict copy def }if load begin def end }def /mySave{ save /_sSave xp }def /myRestore{ _sSave type /savetype eq{ _sSave restore }if }def /gMark{ counttomark 2 add -1 roll }def /execImage{ /_tmp xp { exec }stopped{ $error /errorname get /undefinedresult ne{ stop }{ _tmp npop }ifelse }if }def /pushBSpace{ newpath gsave _bUMatrix astore concat }def /popBSpace{ grestore }def /setImageParms{ 1 8 2 index 0 0 1 0 0 _imageMatrix astore }def /linealFill{ 0 0 1 1 rectfill }def /testCMYKColorThrough{ gsave setcmykcolor currentcmykcolor grestore add add add 0 ne }def /expandOne { /_tmp xp dup type /stringtype ne{ _tmp string exch dup 0 ne{ 255 mul cvi 0 1 _tmp 1 sub{ 3 copy exch put pop }for }if pop }if }def /expandColor{ /_channels xp /_len xp _channels{ _len expandOne _channels 1 roll }repeat }def /blendColor{ _color{ _rgbRamp _producingSeps not and{ _redData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _greenData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _blueData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if /setrgbcolor cvx }{ _cyanData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _magentaData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _yellowData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _blackData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _spotColor{ _rampSD begin /_rampSD cvx /begin cvx spot1 begin tintImage dup type /stringtype eq{ /_ndx cvx /get cvx _d255- /exch cvx /get cvx }{ dup null ne{ name type /nametype ne{ 1 exch sub }if }if }ifelse end /spot1 cvx /tintValue 3 -1 /roll cvx /put cvx spot2 begin tintImage dup type /stringtype eq{ /_ndx cvx /get cvx _d255- /exch cvx /get cvx }{ dup null ne{ name type /nametype ne{ 1 exch sub }if }if }ifelse end /spot2 cvx /tintValue 3 -1 /roll cvx /put cvx /end cvx end /_rampSD cvx /nsetcustomcolor cvx }{ /setcmykcolor cvx }ifelse }ifelse }{ _blackData /_ndx cvx /get cvx _d255 /exch cvx /get cvx _usingSmoothShade{ 1 /exch cvx /sub cvx 0 0 0 4 -1 /roll cvx /setcmykcolor cvx }{ /setgray cvx }ifelse }ifelse }def /linealRamp{ pushBSpace _ramp{ linealImage }{ linealFill }ifelse popBSpace /_rampIndex _rampIndex 1 sub pt _rampIndex 0 gt{ getRampData }if }def /radialGrad{ /_firstShell true pt _usingSmoothShade not{ fill }if pushBSpace _radHilite{ _xHi _yHi _bUMatrix idtransform /_yHi xp /_xHi xp _rampPoint 1 lt{ 1 _rampPoint sub dup _xHi mul exch _yHi mul translate }if }if _rampIndex{ radialRamp /_rampIndex _rampIndex 1 sub pt _rampIndex 0 gt{ getRampData }if }repeat popBSpace }def /getNSamples{ 0 exch { dup type /stringtype eq{ length exch pop exit }if pop }forall dup 0 eq{ pop 1 }if }def /getRampData{ /_rampType gMark pt /_color _rampType 0 gt pt /_ccRGB _rampType 5 eq _rampType 6 eq or pt /_rgbRamp _rampType 4 eq _ccRGB or pt /_ccProcess _rampType 2 eq _rampType 3 eq or pt _producingSeps{ _rampSD initSpotDict /_spotColor _ccProcess _ccRGB or pt }{ /_spotColor false pt }ifelse /_ramp true pt 100 div /_rampPoint xp 100 div /_midPoint xp dup /_colorStyle xp _colorStyle 0 eq{ 2 }{ _colorStyle 1 eq{ 5 }{ _colorStyle 2 eq{ 8 }{ _colorStyle 3 eq{ _producingSeps{ _rampSD begin spot1 begin /name 3 index def /spot_K 4 index def /spot_Y 5 index def /spot_M 6 index def /spot_C 7 index def end end }if 7 }{ _producingSeps{ _rampSD begin spot1 begin /name 4 index def /spot_K 8 index def /spot_Y 9 index def /spot_M 10 index def /spot_C 11 index def end end }if 11 } ifelse }ifelse }ifelse }ifelse /_tmp xp _tmp index 100 div /_endPoint xp _gradType 1 eq{ _tmp 1 add index 100 div /_midPoint xp }if _producingSeps{ _tmp 2 add index /_nextColorStyle xp _nextColorStyle 3 eq{ /_tmp _tmp 4 add pt _tmp index dup _rampSD begin spot1 /name get ne{ spot2 begin /name xd /spot_K _tmp 2 add index def /spot_Y _tmp 3 add index def /spot_M _tmp 4 add index def /spot_C _tmp 5 add index def end }{ pop }ifelse end }if _nextColorStyle 4 eq{ /_tmp _tmp 5 add pt _tmp index dup _rampSD begin spot1 /name get ne{ spot2 begin /name xd /spot_K _tmp 5 add index def /spot_Y _tmp 6 add index def /spot_M _tmp 7 add index def /spot_C _tmp 8 add index def end }{ pop }ifelse end }if }if _rampType 3 eq _rampType 6 eq or{ /_tint2Data gMark pt }if _ccProcess _ccRGB or{ /_tint1Data gMark pt }if _rgbRamp{ /_blueData gMark pt /_greenData gMark pt /_redData gMark pt }if _producingSeps{ _rampSD begin _ccProcess _ccRGB or{ _rampType 3 eq _rampType 6 eq or{ spot2 begin /tintImage _gradType 0 eq{ _tint2Data }{ _tint1Data }ifelse def name null eq{ /name /Black def }if end }if spot1 begin /tintImage _gradType 0 eq _rampType 2 eq or _rampType 5 eq or{ _tint1Data }{ _tint2Data }ifelse def _rampType 2 eq _rampType 5 eq or{ name null eq{ /name spot2 /name get def spot2 /name null put }if }{ name null eq{ /name /Black def }if }ifelse end }if end }if /_blackData gMark pt _rampType 0 gt{ counttomark 4 add -3 roll /_yellowData xp /_magentaData xp /_cyanData xp }if _ramp{ /_nSamples [ _rampType 0 eq {_blackData}if _rampType 1 eq {_cyanData _magentaData _yellowData _blackData}if _rampType 2 eq {_cyanData _magentaData _yellowData _blackData _tint1Data}if _rampType 3 eq {_cyanData _magentaData _yellowData _blackData _tint1Data _tint2Data}if _rampType 4 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData}if _rampType 5 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData _tint1Data}if _rampType 6 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData _tint1Data _tint2Data}if ] getNSamples pt _usingSmoothShade not {/_ramp _nSamples 1 gt pt} if } if setCStop }def /rectImage{ gsave /_sInc 1 pt /_bInc 1 _nSamples div pt /_uRampLen 1 0 dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt pt /_pChange _uRampLen 0 eq{0}{_nSamples _uRampLen div}ifelse pt 0 _nSamples [ /dup cvx /_ndx /exch cvx /pt cvx blendColor 0 0 _bInc 1 /rectfill cvx _bInc 0 /translate cvx _sInc /add cvx ] cvx bind repeat pop _spotColor{ nsetcustomcolorend }if grestore }def /radialInit{ /_nRadSamples _nSamples dup 0 eq{pop 1}if pt /_sInc -1 pt /_rampLen _rampPoint _endPoint sub pt /_bInc _rampLen _nSamples div neg pt /_optimize false pt _subSampleOK{ /_uRampLen _rampLen 0 dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt 0 _rampLen dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt 2 copy lt{ exch }if pop pt /_pChange _uRampLen 0 eq{ 0 }{ _nSamples _uRampLen div }ifelse pt _pChange .5 gt dup /_optimize xp{ /_nRadSamples _uRampLen 2 div round cvi dup 1 le{pop 2}if pt /_bInc _rampLen _nRadSamples div neg pt /_sInc _nSamples 1 sub _nRadSamples 1 sub div neg pt }if }if _radHilite{ /_xBCInc _xHi _rampLen mul _nRadSamples div pt /_yBCInc _yHi _rampLen mul _nRadSamples div pt }if }def currentdict/radialRamp known not{ /radialRamp{ /_saveMatrix _saveMatrix currentmatrix def radialInit _rampPoint _nSamples 1 sub _nRadSamples [ /dup cvx _optimize{ /round cvx /cvi cvx }if /_ndx /exch cvx /pt cvx _useShells{ /_firstShell cvx{ /_firstShell false pt }{ 0 0 3 index 360 0 arcn fill }/ifelse cvx }if blendColor _useShells{ 0 0 3 /index cvx 0 360 /arc cvx }{ 0 0 3 /index cvx 0 360 /arc cvx /fill cvx }ifelse /exch cvx _bInc /add cvx /exch cvx _sInc /add cvx _radHilite{ _xBCInc _yBCInc /translate cvx }if ] cvx bind repeat pop pop _saveMatrix setmatrix _radHilite{ _xHi _rampLen mul _yHi _rampLen mul translate }if _useShells _rampIndex 1 eq and{ fill }if _spotColor{ nsetcustomcolorend }if }def }if end end defaultpacking setpacking %%EndResource %%BeginProcSet: Adobe_ColorImage_AI6 1.1 0 userdict /Adobe_ColorImage_AI6 known not { userdict /Adobe_ColorImage_AI6 24 dict put } if userdict /Adobe_ColorImage_AI6 get begin /initialize { Adobe_ColorImage_AI6 begin Adobe_ColorImage_AI6 { dup type /arraytype eq { dup xcheck { bind } if } if pop pop } forall } def /terminate { end } def currentdict /Adobe_ColorImage_AI6_Vars known not { /Adobe_ColorImage_AI6_Vars 15 dict def } if Adobe_ColorImage_AI6_Vars begin /channelcount 0 def /sourcecount 0 def /sourcearray 4 array def /plateindex -1 def /XIMask 0 def /XIBinary 0 def /XIChannelCount 0 def /XIBitsPerPixel 0 def /XIImageHeight 0 def /XIImageWidth 0 def /XIImageMatrix null def /XIBuffer null def /XIDataProc null def /XIVersion 6 def end /WalkRGBString null def /WalkCMYKString null def /StuffRGBIntoGrayString null def /RGBToGrayImageProc null def /StuffCMYKIntoGrayString null def /CMYKToGrayImageProc null def /ColorImageCompositeEmulator null def /SeparateCMYKImageProc null def /FourEqual null def /TestPlateIndex null def currentdict /_colorimage known not { /colorimage where { /colorimage get /_colorimage exch def } { /_colorimage null def } ifelse } if /_currenttransfer systemdict /currenttransfer get def /colorimage null def /XI null def /WalkRGBString { 0 3 index dup length 1 sub 0 3 3 -1 roll { 3 getinterval { } forall 5 index exec 3 index } for 5 { pop } repeat } def /WalkCMYKString { 0 3 index dup length 1 sub 0 4 3 -1 roll { 4 getinterval { } forall 6 index exec 3 index } for 5 { pop } repeat } def /StuffRGBIntoGrayString { .11 mul exch .59 mul add exch .3 mul add cvi 3 copy put pop 1 add } def /RGBToGrayImageProc { Adobe_ColorImage_AI6_Vars begin sourcearray 0 get exec dup length 3 idiv string dup 3 1 roll /StuffRGBIntoGrayString load exch WalkRGBString end } def /StuffCMYKIntoGrayString { exch .11 mul add exch .59 mul add exch .3 mul add dup 255 gt { pop 255 } if 255 exch sub cvi 3 copy put pop 1 add } def /CMYKToGrayImageProc { Adobe_ColorImage_AI6_Vars begin sourcearray 0 get exec dup length 4 idiv string dup 3 1 roll /StuffCMYKIntoGrayString load exch WalkCMYKString end } def /ColorImageCompositeEmulator { pop true eq { Adobe_ColorImage_AI6_Vars /sourcecount get 5 add { pop } repeat } { Adobe_ColorImage_AI6_Vars /channelcount get 1 ne { Adobe_ColorImage_AI6_Vars begin sourcearray 0 3 -1 roll put channelcount 3 eq { /RGBToGrayImageProc } { /CMYKToGrayImageProc } ifelse load end } if image } ifelse } def /SeparateCMYKImageProc { Adobe_ColorImage_AI6_Vars begin sourcecount 0 ne { sourcearray plateindex get exec } { sourcearray 0 get exec dup length 4 idiv string 0 2 index plateindex 4 2 index length 1 sub { get 255 exch sub 3 copy put pop 1 add 2 index } for pop pop exch pop } ifelse end } def /FourEqual { 4 index ne { pop pop pop false } { 4 index ne { pop pop false } { 4 index ne { pop false } { 4 index eq } ifelse } ifelse } ifelse } def /TestPlateIndex { Adobe_ColorImage_AI6_Vars begin /plateindex -1 def /setcmykcolor where { pop gsave 1 0 0 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 1 0 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 0 1 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 0 0 1 setcmykcolor systemdict /currentgray get exec 1 exch sub grestore 1 0 0 0 FourEqual { /plateindex 0 def } { 0 1 0 0 FourEqual { /plateindex 1 def } { 0 0 1 0 FourEqual { /plateindex 2 def } { 0 0 0 1 FourEqual { /plateindex 3 def } { 0 0 0 0 FourEqual { /plateindex 5 def } if } ifelse } ifelse } ifelse } ifelse pop pop pop pop } if plateindex end } def /colorimage { Adobe_ColorImage_AI6_Vars begin /channelcount 1 index def /sourcecount 2 index 1 eq { channelcount 1 sub } { 0 } ifelse def 4 sourcecount add index dup 8 eq exch 1 eq or not end { /_colorimage load null ne { _colorimage } { Adobe_ColorImage_AI6_Vars /sourcecount get 7 add { pop } repeat } ifelse } { dup 3 eq TestPlateIndex dup -1 eq exch 5 eq or or { /_colorimage load null eq { ColorImageCompositeEmulator } { dup 1 eq { pop pop image } { Adobe_ColorImage_AI6_Vars /plateindex get 5 eq { gsave 0 _currenttransfer exec 1 _currenttransfer exec eq { 0 _currenttransfer exec 0.5 lt } { 0 _currenttransfer exec 1 _currenttransfer exec gt } ifelse { { pop 0 } } { { pop 1 } } ifelse systemdict /settransfer get exec } if _colorimage Adobe_ColorImage_AI6_Vars /plateindex get 5 eq { grestore } if } ifelse } ifelse } { dup 1 eq { pop pop image } { pop pop Adobe_ColorImage_AI6_Vars begin sourcecount -1 0 { exch sourcearray 3 1 roll put } for /SeparateCMYKImageProc load end systemdict /image get exec } ifelse } ifelse } ifelse } def /XG { pop pop } def /XF { 13 {pop} repeat } def /Xh { Adobe_ColorImage_AI6_Vars begin gsave /XIMask exch 0 ne def /XIImageHeight exch def /XIImageWidth exch def /XIImageMatrix exch def 0 0 moveto XIImageMatrix concat XIImageWidth XIImageHeight scale XIMask { /_lp /null ddef _fc /_lp /imagemask ddef } if /XIVersion 7 def end } def /XH { Adobe_ColorImage_AI6_Vars begin /XIVersion 6 def grestore end } def /XI { Adobe_ColorImage_AI6_Vars begin gsave /XIMask exch 0 ne def /XIBinary exch 0 ne def pop pop /XIChannelCount exch def /XIBitsPerPixel exch def /XIImageHeight exch def /XIImageWidth exch def pop pop pop pop /XIImageMatrix exch def XIBitsPerPixel 1 eq { XIImageWidth 8 div ceiling cvi } { XIImageWidth XIChannelCount mul } ifelse /XIBuffer exch string def XIBinary { /XIDataProc { currentfile XIBuffer readstring pop } def XIVersion 6 le { currentfile 128 string readline pop pop } if } { /XIDataProc { currentfile XIBuffer readhexstring pop } def } ifelse XIVersion 6 le { 0 0 moveto XIImageMatrix concat XIImageWidth XIImageHeight scale XIMask { /_lp /null ddef _fc /_lp /imagemask ddef } if } if XIMask { XIImageWidth XIImageHeight false [ XIImageWidth 0 0 XIImageHeight neg 0 0 ] /XIDataProc load imagemask } { XIImageWidth XIImageHeight XIBitsPerPixel [ XIImageWidth 0 0 XIImageHeight neg 0 0 ] /XIDataProc load XIChannelCount 1 eq { gsave 0 setgray image grestore } { false XIChannelCount colorimage } ifelse } ifelse grestore end } def end %%EndProcSet %%BeginResource: procset Adobe_Illustrator_AI5 1.1 0 %%Title: (Adobe Illustrator (R) Version 5.0 Full Prolog) %%Version: 1.1 0 %%CreationDate: (3/7/1994) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_Illustrator_AI5_vars 81 dict dup begin put /_eo false def /_lp /none def /_pf { } def /_ps { } def /_psf { } def /_pss { } def /_pjsf { } def /_pjss { } def /_pola 0 def /_doClip 0 def /cf currentflat def /_tm matrix def /_renderStart [ /e0 /r0 /a0 /o0 /e1 /r1 /a1 /i0 ] def /_renderEnd [ null null null null /i1 /i1 /i1 /i1 ] def /_render -1 def /_rise 0 def /_ax 0 def /_ay 0 def /_cx 0 def /_cy 0 def /_leading [ 0 0 ] def /_ctm matrix def /_mtx matrix def /_sp 16#020 def /_hyphen (-) def /_fScl 0 def /_cnt 0 def /_hs 1 def /_nativeEncoding 0 def /_useNativeEncoding 0 def /_tempEncode 0 def /_pntr 0 def /_tDict 2 dict def /_wv 0 def /Tx { } def /Tj { } def /CRender { } def /_AI3_savepage { } def /_gf null def /_cf 4 array def /_if null def /_of false def /_fc { } def /_gs null def /_cs 4 array def /_is null def /_os false def /_sc { } def /_pd 1 dict def /_ed 15 dict def /_pm matrix def /_fm null def /_fd null def /_fdd null def /_sm null def /_sd null def /_sdd null def /_i null def /discardSave null def /buffer 256 string def /beginString null def /endString null def /endStringLength null def /layerCnt 1 def /layerCount 1 def /perCent (%) 0 get def /perCentSeen? false def /newBuff null def /newBuffButFirst null def /newBuffLast null def /clipForward? false def end userdict /Adobe_Illustrator_AI5 known not { userdict /Adobe_Illustrator_AI5 91 dict put } if userdict /Adobe_Illustrator_AI5 get begin /initialize { Adobe_Illustrator_AI5 dup begin Adobe_Illustrator_AI5_vars begin discardDict { bind pop pop } forall dup /nc get begin { dup xcheck 1 index type /operatortype ne and { bind } if pop pop } forall end newpath } def /terminate { end end } def /_ null def /ddef { Adobe_Illustrator_AI5_vars 3 1 roll put } def /xput { dup load dup length exch maxlength eq { dup dup load dup length 2 mul dict copy def } if load begin def end } def /npop { { pop } repeat } def /sw { dup length exch stringwidth exch 5 -1 roll 3 index mul add 4 1 roll 3 1 roll mul add } def /swj { dup 4 1 roll dup length exch stringwidth exch 5 -1 roll 3 index mul add 4 1 roll 3 1 roll mul add 6 2 roll /_cnt 0 ddef { 1 index eq { /_cnt _cnt 1 add ddef } if } forall pop exch _cnt mul exch _cnt mul 2 index add 4 1 roll 2 index add 4 1 roll pop pop } def /ss { 4 1 roll { 2 npop (0) exch 2 copy 0 exch put pop gsave false charpath currentpoint 4 index setmatrix stroke grestore moveto 2 copy rmoveto } exch cshow 3 npop } def /jss { 4 1 roll { 2 npop (0) exch 2 copy 0 exch put gsave _sp eq { exch 6 index 6 index 6 index 5 -1 roll widthshow currentpoint } { false charpath currentpoint 4 index setmatrix stroke } ifelse grestore moveto 2 copy rmoveto } exch cshow 6 npop } def /sp { { 2 npop (0) exch 2 copy 0 exch put pop false charpath 2 copy rmoveto } exch cshow 2 npop } def /jsp { { 2 npop (0) exch 2 copy 0 exch put _sp eq { exch 5 index 5 index 5 index 5 -1 roll widthshow } { false charpath } ifelse 2 copy rmoveto } exch cshow 5 npop } def /pl { transform 0.25 sub round 0.25 add exch 0.25 sub round 0.25 add exch itransform } def /setstrokeadjust where { pop true setstrokeadjust /c { curveto } def /C /c load def /v { currentpoint 6 2 roll curveto } def /V /v load def /y { 2 copy curveto } def /Y /y load def /l { lineto } def /L /l load def /m { moveto } def } { /c { pl curveto } def /C /c load def /v { currentpoint 6 2 roll pl curveto } def /V /v load def /y { pl 2 copy curveto } def /Y /y load def /l { pl lineto } def /L /l load def /m { pl moveto } def } ifelse /d { setdash } def /cf { } def /i { dup 0 eq { pop cf } if setflat } def /j { setlinejoin } def /J { setlinecap } def /M { setmiterlimit } def /w { setlinewidth } def /XR { 0 ne /_eo exch ddef } def /H { } def /h { closepath } def /N { _pola 0 eq { _doClip 1 eq { _eo {eoclip} {clip} ifelse /_doClip 0 ddef } if newpath } { /CRender { N } ddef } ifelse } def /n { N } def /F { _pola 0 eq { _doClip 1 eq { gsave _pf grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _fc /_doClip 0 ddef } { _pf } ifelse } { /CRender { F } ddef } ifelse } def /f { closepath F } def /S { _pola 0 eq { _doClip 1 eq { gsave _ps grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _sc /_doClip 0 ddef } { _ps } ifelse } { /CRender { S } ddef } ifelse } def /s { closepath S } def /B { _pola 0 eq { _doClip 1 eq gsave F grestore { gsave S grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _sc /_doClip 0 ddef } { S } ifelse } { /CRender { B } ddef } ifelse } def /b { closepath B } def /W { /_doClip 1 ddef } def /* { count 0 ne { dup type /stringtype eq { pop } if } if newpath } def /u { } def /U { } def /q { _pola 0 eq { gsave } if } def /Q { _pola 0 eq { grestore } if } def /*u { _pola 1 add /_pola exch ddef } def /*U { _pola 1 sub /_pola exch ddef _pola 0 eq { CRender } if } def /D { pop } def /*w { } def /*W { } def /` { /_i save ddef clipForward? { nulldevice } if 6 1 roll 4 npop concat pop userdict begin /showpage { } def 0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit [] 0 setdash /setstrokeadjust where {pop false setstrokeadjust} if newpath 0 setgray false setoverprint } def /~ { end _i restore } def /O { 0 ne /_of exch ddef /_lp /none ddef } def /R { 0 ne /_os exch ddef /_lp /none ddef } def /g { /_gf exch ddef /_fc { _lp /fill ne { _of setoverprint _gf setgray /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /G { /_gs exch ddef /_sc { _lp /stroke ne { _os setoverprint _gs setgray /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /k { _cf astore pop /_fc { _lp /fill ne { _of setoverprint _cf aload pop setcmykcolor /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /K { _cs astore pop /_sc { _lp /stroke ne { _os setoverprint _cs aload pop setcmykcolor /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /x { /_gf exch ddef findcmykcustomcolor /_if exch ddef /_fc { _lp /fill ne { _of setoverprint _if _gf 1 exch sub setcustomcolor /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /X { /_gs exch ddef findcmykcustomcolor /_is exch ddef /_sc { _lp /stroke ne { _os setoverprint _is _gs 1 exch sub setcustomcolor /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /A { pop } def /annotatepage { userdict /annotatepage 2 copy known {get exec} {pop pop} ifelse } def /XT { pop pop } def /discard { save /discardSave exch store discardDict begin /endString exch store gt38? { 2 add } if load stopped pop end discardSave restore } bind def userdict /discardDict 7 dict dup begin put /pre38Initialize { /endStringLength endString length store /newBuff buffer 0 endStringLength getinterval store /newBuffButFirst newBuff 1 endStringLength 1 sub getinterval store /newBuffLast newBuff endStringLength 1 sub 1 getinterval store } def /shiftBuffer { newBuff 0 newBuffButFirst putinterval newBuffLast 0 currentfile read not { stop } if put } def 0 { pre38Initialize mark currentfile newBuff readstring exch pop { { newBuff endString eq { cleartomark stop } if shiftBuffer } loop } { stop } ifelse } def 1 { pre38Initialize /beginString exch store mark currentfile newBuff readstring exch pop { { newBuff beginString eq { /layerCount dup load 1 add store } { newBuff endString eq { /layerCount dup load 1 sub store layerCount 0 eq { cleartomark stop } if } if } ifelse shiftBuffer } loop } if } def 2 { mark { currentfile buffer readline not { stop } if endString eq { cleartomark stop } if } loop } def 3 { /beginString exch store /layerCnt 1 store mark { currentfile buffer readline not { stop } if dup beginString eq { pop /layerCnt dup load 1 add store } { endString eq { layerCnt 1 eq { cleartomark stop } { /layerCnt dup load 1 sub store } ifelse } if } ifelse } loop } def end userdict /clipRenderOff 15 dict dup begin put { /n /N /s /S /f /F /b /B } { { _doClip 1 eq { /_doClip 0 ddef _eo {eoclip} {clip} ifelse } if newpath } def } forall /Tr /pop load def /Bb {} def /BB /pop load def /Bg {12 npop} def /Bm {6 npop} def /Bc /Bm load def /Bh {4 npop} def end /Lb { 4 npop 6 1 roll pop 4 1 roll pop pop pop 0 eq { 0 eq { (%AI5_BeginLayer) 1 (%AI5_EndLayer--) discard } { /clipForward? true def /Tx /pop load def /Tj /pop load def currentdict end clipRenderOff begin begin } ifelse } { 0 eq { save /discardSave exch store } if } ifelse } bind def /LB { discardSave dup null ne { restore } { pop clipForward? { currentdict end end begin /clipForward? false ddef } if } ifelse } bind def /Pb { pop pop 0 (%AI5_EndPalette) discard } bind def /Np { 0 (%AI5_End_NonPrinting--) discard } bind def /Ln /pop load def /Ap /pop load def /Ar { 72 exch div 0 dtransform dup mul exch dup mul add sqrt dup 1 lt { pop 1 } if setflat } def /Mb { q } def /Md { } def /MB { Q } def /nc 3 dict def nc begin /setgray { pop } bind def /setcmykcolor { 4 npop } bind def /setcustomcolor { 2 npop } bind def currentdict readonly pop end end setpacking %%EndResource %%BeginResource: procset Adobe_blend_AI5 1.4 0 %%Title: (Adobe Illustrator (R) Version 5.0 Blend ProcSet) %%Version: 1.4 0 %%CreationDate: (11/19/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /Adobe_blend_AI5 70 dict dup begin put /bd { bind def } bind def /xs { exch store } bd /nullProc { { } } def /initialize { pop pop Adobe_blend_AI5 begin Adobe_blend_AI5_vars begin /_contoneDevice where { pop } { /_contoneDevice false def } ifelse /_dpiThreshold where { pop } { /_dpiThreshold 600 def } ifelse /_screenFreqThreshold where { pop } { /_screenFreqThreshold 150 def } ifelse /tRectOK? deviceDPI _dpiThreshold le currentScreenFreq _screenFreqThreshold le and _contoneDevice not and def /invertXfer { [ { 1 exch sub } /exec load systemdict/currenttransfer get exec /exec load ] cvx systemdict/settransfer get exec } bd /spotDict 3 dict dup begin /nSpots 2 def /spot1 7 dict def /spot2 7 dict def end def composite? { /_setgray_ /setgray load def /_fill_ /fill load def /_image_ /image load def } { /_setgray_ systemdict/setgray get def /_fill_ systemdict/fill get def /_image_ systemdict/image get def } ifelse } bd /terminate { currentdict Adobe_blend_AI5_vars eq { end currentdict Adobe_blend_AI5 eq { end } if } if } bd /_compositeSpotDevice where { begin _compositeSpotDevice 0 ne {userdict /composite? true put} if end } { /_compositeSpotDevice 0 def } ifelse /nullString () def /d255 256 array def 0 1 255 { d255 exch dup 255 div put } bind for /d255- 256 array def 0 1 255 { d255- exch 1 d255 2 index get sub put } bind for /dUserSpace matrix defaultmatrix def currentdict /Adobe_blend_AI5_vars 89 dict dup begin put { /f /F /s /S /b /B } { null def } bind forall /byte 1 string def /sSave null def /setSSave { save /sSave exch store } bind def /Bm null def /doBlend null def /startC? false def /endC? false def /fCMYK? null def /startTint 0 def /endTint 0 def /bSMatrix matrix def /bUMatrix matrix def /dMatrix matrix def /inLine? true def /pTState? false def /bHi? false def /yHi 0 def /xHi 0 def /noImg /lv1Fix where { pop lv1Fix } { false } ifelse def /ccAry1 5 array def /ccTint 0 def /spotColor? false def /colorimage? true def [ /tint1Data /tint2Data /spotDict /bAxis /ubAxis /pChange /optimize? /nSamples /sInc /blendProc /_bn /xBCInc /yBCInc /bInc /bRender /cBName /cBType /nColors /color? /blend? /colorType /cData /cDataLen /bDataLen /rampPoint /midPoint /endPoint /blendLength /blackData /yeData /mgData /cyData /cnt1 /ndx /_fill /tmp counttomark { null def } bind repeat pop currentdict end currentdict end exch begin begin /unitSq { 0 0 moveto 0 1 lineto 1 1 lineto 1 0 lineto closepath } bd /gMark { counttomark 2 add -1 roll } bd /setCustomColor { dup /ccTint exch store 1 exch sub 6 1 roll ccAry1 astore exch setcustomcolor } bd /currentCustomColor { ccAry1 aload pop ccTint } bd /nsetcustomcolor where { pop } { /nsetcustomcolor { pop setcmykcolor } bd } ifelse /nsetcustomcolorend where { pop } { /nsetcustomcolorend { } bd } ifelse /setBSpace { newpath bUMatrix astore concat unitSq } bd /setCStop { dup 0 eq { pop spotColor? { dup 1 exch sub /ccTint exch def ccAry1 4 /Black put } if setgray } { 1 eq { setcmykcolor } { composite? not colorType 2 lt and { forceCMYK } { setCustomColor } ifelse } ifelse } ifelse } bd /makeByte { /tmp 0 store 255 mul cvi 8 string 8 { dup tmp 3 index put /tmp tmp 1 add store } repeat exch pop } bd /setImgSpace { cDataLen 1 8 2 index 0 0 1 0 0 dMatrix astore } bd /bwImage { setImgSpace cData /_image_ load { exec } stopped { $error /errorname get /undefinedresult ne { stop } { pop pop pop pop pop } ifelse } if } bd level2? { /bFill { _fill } def /bCImg { /cDataLen bDataLen store setImgSpace setSSave expandSpot cyData mgData yeData cData expandCMYK true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd } if /expandOne { dup type /stringtype ne { cDataLen string exch dup 0 ne { 255 mul cvi 0 1 cDataLen 1 sub { 3 copy exch put pop } for } if pop } if } bd /expandSpot { spotColor? { spotDict begin spot1 begin tintImage type /nulltype ne { tintImage expandOne /tintImage exch def } if end spot2 begin tintImage type /nulltype ne { tintImage expandOne /tintImage exch def } if end end } if } bd /expandCMYK { 4 { expandOne 4 1 roll } repeat } bd /colorimage where dup { exch pop /ncolorimage where { pop } { /ncolorimage {pop colorimage} bd } ifelse } if not { /ncolorimage where { pop } { /colorimage? false store /ncolorimage { pop pop pop setSSave /blackData xs /yeData xs /mgData xs /cyData xs /cnt1 0 store [ byte dup 0 cyData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .3 /mul cvx } { .3 mul } ifelse mgData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .59 /mul cvx } { .59 mul } ifelse yeData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .11 /mul cvx } { .11 mul } ifelse blackData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx } if /add cvx /add cvx /add cvx 1 /exch cvx /sub cvx /dup cvx 0 /lt cvx { pop 0 } /if cvx /dup cvx 1 /gt cvx { pop 1 } /if cvx 255 /mul cvx /cvi cvx 256 /mod cvx /dup cvx 0 /lt cvx { pop 0 } /if cvx /put cvx /cnt1 dup cvx 1 /add cvx /store cvx ] cvx bind _image_ sSave restore } bd } ifelse } if level2? not { /bCImg { /cDataLen bDataLen store setImgSpace setSSave expandSpot cyData mgData yeData cData colorimage? { expandCMYK } if true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd /bwFill { setSSave /cDataLen 8 store /cData currentgray makeByte store bwImage sSave restore } bd /c1ImgFill { setSSave /cDataLen 8 store setImgSpace spotColor? { spotDict begin spot1 begin currentCustomColor makeByte /tintImage exch def /name exch def /spot_K exch def /spot_Y exch def /spot_M exch def /spot_C exch def end spot2 initSpotData end } if currentcmykcolor 4 { makeByte 4 1 roll } repeat true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd /bFill noImg { { _fill } } { { color? { c1ImgFill } { bwFill } ifelse } } ifelse bd } if composite? { /bCFun { color? { cyData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if mgData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if yeData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if cData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if spotColor? { spotDict begin /spotDict cvx /begin cvx spot1 begin tintImage dup type /stringtype eq { /ndx cvx /get cvx d255- /exch cvx /get cvx } { dup type /nulltype ne { name type /nametype ne {1 exch sub} if } if } ifelse end /spot1 cvx /tintValue 3 -1 /roll cvx /put cvx spot2 begin tintImage dup type /stringtype eq { /ndx cvx /get cvx d255- /exch cvx /get cvx } { dup type /nulltype ne { name type /nametype ne {1 exch sub} if } if } ifelse end /spot2 cvx /tintValue 3 -1 /roll cvx /put cvx /end cvx end /spotDict cvx /nsetcustomcolor cvx } { /setcmykcolor cvx } ifelse } { cData /ndx cvx /get cvx d255 /exch cvx /get cvx /setgray cvx } ifelse } bd /Bc { newpath gsave setBSpace nColors 1 eq { pop pop setCStop } if bFill grestore } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { linImg } { bFill } ifelse grestore nColors 1 gt { getRData } if } bd /rdBm { /nColors dup load 1 sub store _fill gsave bUMatrix astore concat bHi? { xHi yHi bUMatrix idtransform /yHi exch store /xHi exch store rampPoint 1 lt { 1 rampPoint sub dup xHi mul exch yHi mul translate } if } if nColors { 0 0 rampPoint 0 360 arc _fill blend? bHi? or { rdBlend } if nColors 1 gt { getRData } if /nColors dup load 1 sub store } repeat /nColors 1 store grestore } bd /cGetRData { setCStop /blend? cData type /stringtype eq dup not color? and { pop cyData type /stringtype eq mgData type /stringtype eq yeData type /stringtype eq or or } if store } def /cGetRData } if /eCStop { mark 1 index 3 mul 3 add dup 8 gt { pop 8 } if 1 roll cleartomark } bd composite? not { /knockOut level2? { { 0 0 0 0 setcmykcolor _fill } } { /bFill noImg { { _fill } } { { _of true eq { currentgray 1 ne { bwFill } if } { bwFill } ifelse } } ifelse def /whiteByte 1 makeByte def noImg { { 0 0 0 0 setcmykcolor _fill } } { { cBType 0 eq { setSSave /cData whiteByte store /cDataLen 8 store bwImage sSave restore } { _fill } ifelse } } ifelse } ifelse bd /bCFun { cData dup type /stringtype ne { color? { 1 exch sub } if } { /ndx cvx /get cvx color? customColor? not and { d255- } { d255 } ifelse /exch cvx /get cvx } ifelse /_setgray_ cvx } bd /eCCBlend { dup 3 eq { pop mark 7 1 roll 6 copy ccThrough? dup /blend? xs { /startC? true store setCustomColor customColor? { /cData tint1Data store setCDataLen } if /endC? 3 index 3 eq { 4 index 1 ne } { false } ifelse store } if cleartomark stop } if 1 eq { pop pop pop } if pop /startC? false store 6 { 8 index } repeat ccThrough? dup /blend? xs { /endC? true store blend? not { stop } if customColor? { /cData tint1Data store setCDataLen } if } if } bd /handleOP { _of not { knockOut } if } bd /handleROP { _of not { 0 0 0 0 setcmykcolor _fill } { newpath } ifelse } bd /rdBm { /nColors dup load 1 sub store blend? { _fill } { handleROP } ifelse gsave bUMatrix astore concat bHi? { xHi yHi bUMatrix idtransform /yHi exch store /xHi exch store rampPoint 1 lt { 1 rampPoint sub dup xHi mul exch yHi mul translate } if } if nColors { 0 0 rampPoint 0 360 arc blend? { cData type /stringtype ne bHi? not and { cData color? { 1 exch sub } if _setgray_ _fill_ } { cData type /stringtype ne { /cDataLen 1 store /bDataLen 1 store } if rdBlend } ifelse } { handleROP pTState? { /bAxis rampPoint endPoint sub store xHi bAxis mul yHi bAxis mul translate } if } ifelse nColors 1 gt { getRData } if /nColors dup load 1 sub store } repeat /nColors 1 store grestore } bd /ccThrough? { gsave pop 0 setCustomColor currentcmykcolor grestore anyColor? } bd /forceCMYK { exch pop 1 exch sub 5 1 roll 4 { 4 index mul 4 1 roll } repeat 0 cCMYKData dup /cData ne { dup /yeData eq { pop 1 add } { /mgData eq { 2 } { 3 } ifelse add } ifelse 0 } if pop index 0 eq { pop pop pop pop 0 0 0 0 } if setcmykcolor pop /fCMYK? true store } bd /endCapSepBc { pop pop dup 0 eq { pop setgray } { 1 eq { setcmykcolor } { colorType 1 eq { forceCMYK } { fCMYK? { forceCMYK } { setCustomColor } ifelse } ifelse } ifelse } ifelse currentcmykcolor anyColor? blend? and { bFill } { handleOP } ifelse } bd } if /cCMYKData 0 def composite? dup not { pop customColor? } if not { /cCMYKData /cyData /mgData /yeData /cData black? not { yellow? { exch } { magenta? { 3 } { 4 } ifelse -1 roll } ifelse } if 4 1 roll pop pop pop store /Bc { gsave setBSpace nColors 1 gt { blend? currentcmykcolor anyColor? and { bFill } { handleOP } ifelse } { endCapSepBc } ifelse grestore newpath } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { cCMYKData load dup type /stringtype eq { dup length /cDataLen xs /cData xs gsave colorType 0 ne noImg not and { invertXfer } if linImg grestore } { pop bFill } ifelse } { handleOP } ifelse grestore nColors 1 gt { getRData } if } bd /cmykGetRData { /fCMYK? false store blend? { { cmykDataProcs colorType get exec } stopped pop blend? { /cData cCMYKData load store setCDataLen } if } if } def /cmykDataProcs [ { pop black? dup /blend? xs { setgray 0 } if pop } { cCMYKData load dup type /stringtype ne { 0 0 0 cyan? not { 4 magenta? { 1 } { yellow? { 2 } { 3 } ifelse } ifelse roll } if 4 copy add add add 0 eq { /blend? false store } if setcmykcolor /startC? true store /endC? true store eCStop stop } if pop dup 0 eq { pop setgray } { 1 eq { setcmykcolor } { forceCMYK } ifelse } ifelse } bind /eCCBlend load { cBType 1 eq { tint1Data tint2Data /tint1Data xs /tint2Data xs } if 0 eq { black? { setgray } { 0 0 0 4 -1 roll 1 exch sub setcmykcolor } ifelse black? { /blend? true store } if 6 { 8 index } repeat ccThrough? { /blend? true store } { black? { /cData tint1Data store setCDataLen } { /blend? false store } ifelse } ifelse } { mark 7 1 roll 6 copy ccThrough? { forceCMYK pop stop } if 9 index 0 eq { black? dup /blend? xs { pop 1 setgray /cData tint2Data store setCDataLen 0 } if pop } { /blend? 6 { 16 index } repeat ccThrough? store blend? { forceCMYK } if } ifelse cleartomark } ifelse } bind ] def /cmykGetRData } if composite? dup not { pop isCMYKSep? } if not { /endCapSepBc { /white? false store pop pop dup 0 eq { pop /white? 1 index 1 eq store setgray } { 1 eq { setcmykcolor } { setCustomColor } ifelse } ifelse % currentcmykcolor anyColor? endC? or blend? and { bFill } { handleOP } ifelse } bd /Bc { gsave setBSpace nColors 1 gt { blend? startC? and { bFill } { handleOP } ifelse } { endCapSepBc } ifelse grestore newpath } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { cData type /stringtype eq { linImg } { bFill } ifelse } { handleOP } ifelse grestore nColors 1 gt { getRData } if } bd /discardCMY { counttomark 4 add -3 roll pop pop pop } bd /testTopCC { 6 copy ccThrough? } bd /getCRamp { { ccDataProcs colorType 2 sub get exec } stopped pop blend? cDataLen 0 eq and { /cDataLen bDataLen store } if } bd /ccGetRData { /fCMYK? false store /startC? false store /endC? false store colorType 2 lt { /blend? false def } if blend? { getCRamp } { setCStop } ifelse blend? { /blend? cData 1 ne store blend? { cData dup type /stringtype ne { 1 exch sub /cData xs 0 } if pop } if } if } def /ccDataProcs [ /eCCBlend load { cBType 1 eq { tint1Data tint2Data /tint1Data xs /tint2Data xs } if 0 eq { /blend? false store pop } { mark 7 1 roll testTopCC { /blend? 1 index 1 ne store /startC? blend? store /endC? false store blend? not { cleartomark stop } if /cData tint1Data store setCDataLen setCustomColor pop stop } if cleartomark } ifelse 2 index 0 eq { /blend? false store } { mark 6 { 9 index } repeat testTopCC dup /blend? xs { /blend? 1 index 1 ne store /endC? blend? store /startC? false store blend? not { cleartomark stop } if /cData tint2Data store setCDataLen } if cleartomark } ifelse } bind ] def /ccGetRData } if load Adobe_blend_AI5_vars /getData 3 -1 roll put /setCDataLen { /cDataLen 0 cData dup type /stringtype eq { length exch } if pop store } bd /initSpotData { begin /name null def /tintImage null def /tintValue null def /spot_C null def /spot_M null def /spot_Y null def /spot_K null def end } bd /getRData { /colorType gMark store _compositeSpotDevice 0 ne { spotDict begin spot1 initSpotData spot2 initSpotData end /spotColor? colorType 2 eq colorType 3 eq or def } { /spotColor? false store } ifelse /blend? true store 0 0 0 0 setcmykcolor 100 div /rampPoint xs % (between 13 and 87%) 100 div /midPoint xs dup 0 eq { 2 } { dup 1 eq { 5 } { _compositeSpotDevice 0 ne { spotDict begin spot1 begin /name 3 index def /spot_K 4 index def /spot_Y 5 index def /spot_M 6 index def /spot_C 7 index def end end } if 7 } ifelse } ifelse /tmp exch def tmp index 100 div /endPoint xs _compositeSpotDevice 0 ne { tmp 2 add index 3 eq { /tmp tmp 4 add def tmp index dup spotDict begin spot1/name get ne { spot2 begin /name exch def /spot_K tmp 2 add index def /spot_Y tmp 3 add index def /spot_M tmp 4 add index def /spot_C tmp 5 add index def end } { pop } ifelse end } if } if /color? colorType 0 gt store colorType 3 eq { /tint2Data gMark store } if colorType 2 ge { /tint1Data gMark store } if _compositeSpotDevice 0 ne { spotDict begin colorType 2 ge { colorType 3 eq { spot2 begin /tintImage cBType 0 eq {tint2Data} {tint1Data} ifelse def name null eq {/name /Black def} if end } if spot1 begin /tintImage cBType 0 eq colorType 2 eq or {tint1Data} {tint2Data} ifelse def colorType 2 eq { name null eq { /name spot2/name get def spot2/name null put } if } { name null eq {/name /Black def} if } ifelse end } if end } if /cData gMark store setCDataLen colorType 0 gt { counttomark 4 add -3 roll /yeData xs /mgData xs /cyData xs } if blend? { /bDataLen cDataLen dup 0 eq color? and { [ cyData mgData yeData ] { dup type /stringtype eq { length exch pop exit } if pop } forall } if store bDataLen 0 eq { /bDataLen 1 store } if getData blend? { composite? cDataLen 0 eq and { /cDataLen bDataLen store } if } if } { setCStop } ifelse } bd /Bg { 0 0 0 0 setcmykcolor 6 { pop } repeat /blendLength xs pop pop pop /cBName xs /bRender xs bRender 2 ne { composite? not { _of setoverprint } if _eo {eoclip} {clip} ifelse _bn cBName 2 copy known { get mark exch aload pop /cBType xs /nColors xs mark exch aload pop 0 0 } if pop pop getRData cBType 0 eq { /linealBm } { bHi? { /pTState? nColors 2 gt store } if /doBlend /rdBlend load store /rdBm } ifelse } { inLine? not { mark mark } if /Bc dup { cleartomark mark } bd /nullProc } ifelse load /Bm xs } bd /linImg noImg { { newpath doRctBlend } } { { /doBlend color? composite? and { /bCImg } { /bwImage } ifelse load store 0 0 moveto tRectOK? composite? and { { mark 0 1 dtransform atan cvi 90 mod 0 eq 1 0 dtransform atan cvi 90 mod 0 eq } stopped { cleartomark } { and exch pop { newpath doRctBlend } { doBlend } ifelse } ifelse } { doBlend } ifelse } } ifelse bd /doRctBlend { gsave /sInc 1 store /nSamples bDataLen store /bInc 1 bDataLen div store /ubAxis 1 0 dtransform dUserSpace idtransform dup mul exch dup mul add sqrt store /pChange ubAxis 0 eq { 0 } { bDataLen ubAxis div } ifelse store pChange .5 gt noImg not and dup /optimize? xs { /nSamples ubAxis 2 div round cvi dup 1 le { pop 2 } if store /bInc 1 nSamples div store /sInc bDataLen 1 sub nSamples 1 sub div store } if 0 nSamples [ /dup cvx optimize? { /round cvx /cvi cvx } if /ndx /exch cvx /store cvx bCFun /rectfill where dup { exch pop _compositeSpotDevice 1 ne and } if { 0 0 bInc 1 /rectfill cvx } { 0 0 /moveto cvx bInc 0 /lineto cvx bInc 1 /lineto cvx 0 1 /lineto cvx /closepath cvx /_fill_ cvx } ifelse bInc 0 /translate cvx sInc /add cvx ] cvx bind repeat pop spotColor? {nsetcustomcolorend} if grestore } bd /rdPrep { /nSamples bDataLen dup 0 eq { pop 1 } if store /sInc -1 store /bAxis rampPoint endPoint sub store /bInc bAxis bDataLen div neg store /optimize? false store tRectOK? { /ubAxis bAxis 0 dtransform dUserSpace idtransform dup mul exch dup mul add sqrt 0 bAxis dtransform dUserSpace idtransform dup mul exch dup mul add sqrt 2 copy lt { exch } if pop store /pChange ubAxis 0 eq { 0 } { bDataLen ubAxis div } ifelse store pChange .5 gt noImg not and dup /optimize? xs { /nSamples ubAxis 2 div round cvi dup 1 le { pop 2 } if store /bInc bAxis nSamples div neg store /sInc bDataLen 1 sub nSamples 1 sub div neg store } if } if bHi? { /xBCInc xHi bAxis mul nSamples div store /yBCInc yHi bAxis mul nSamples div store } if } bd /rdBlend { newpath gsave rdPrep rampPoint bDataLen 1 sub nSamples [ /dup cvx optimize? { /round cvx /cvi cvx } if /ndx /exch cvx /store cvx bCFun 0 0 3 /index cvx 0 360 /arc cvx /_fill_ cvx /exch cvx bInc /add cvx /exch cvx sInc /add cvx bHi? { xBCInc yBCInc /translate cvx } if ] cvx bind repeat pop pop spotColor? {nsetcustomcolorend} if grestore pTState? { xHi bAxis mul yHi bAxis mul translate } if } bd /Bh { pop pop /pTState? false store 2 copy 0 ne exch 0 ne or dup /bHi? xs { /yHi xs /xHi xs 0 0 } if pop pop } bd /BD { inLine? not { ] nColors cBType ] _bn cBName 3 -1 roll put end } if } bd /Bn { 1 add dict dup nullString null put /_bn xs } bd /Bd { Adobe_blend_AI5_vars begin 3 -1 roll dup nullString eq dup { setSSave } if /inLine? exch def /cBName exch def /nColors exch def /cBType exch def } bd /Bb { sSave null eq { Adobe_blend_AI5_vars begin setSSave } if composite? { /_fill /fill load store } { /__fill /fill load store /_fill { _of true eq { currentgray 1 ne { __fill } if } { __fill } ifelse } def } ifelse /fill { } def } bd /BB { /cBType xs cleartomark cleartomark cBType dup bRender sSave dup type /savetype eq { restore 0 } if pop currentdict Adobe_blend_AI5_vars eq { end } if 2 ne exch 0 gt and { 2 eq { s } { S } ifelse } { pop newpath } ifelse } bd currentdict readonly pop end end defaultpacking setpacking %%EndResource %%BeginResource: procset Adobe_pattern_AI5 1.1 0 %%Title: (Adobe Illustrator (R) Version 5.0 Pattern Operators) %%Version: 1.1 0 %%CreationDate: (03/26/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_Illustrator_AI5 known not { userdict /Adobe_Illustrator_AI5 95 dict put } if userdict /Adobe_Illustrator_AI5 get begin /@ { } def /& { } def /dp { dup null eq { pop _dp 0 ne { 0 1 _dp 1 sub _dl mod { _da exch get 3 get } for _dp 1 sub _dl mod 1 add packedarray _da 0 get aload pop 8 -1 roll 5 -1 roll pop 4 1 roll definepattern pop } if } { _dp 0 ne _dp _dl mod 0 eq and { null dp } if 7 packedarray _da exch _dp _dl mod exch put _dp _dl mod _da 0 get 4 get 2 packedarray /_dp _dp 1 add def } ifelse } def /E { _ed begin dup 0 get type /arraytype ne { 0 { dup 1 add index type /arraytype eq { 1 add } { exit } ifelse } loop array astore } if /_dd exch def /_ury exch def /_urx exch def /_lly exch def /_llx exch def /_n exch def /_y 0 def /_dl 4 def /_dp 0 def /_da _dl array def 0 1 _dd length 1 sub { /_d exch _dd exch get def 0 2 _d length 2 sub { /_x exch def /_c _d _x get _ ne def /_r _d _x 1 add get cvlit def _r _ ne { _urx _llx sub _ury _lly sub [ 1 0 0 1 0 0 ] [ /save cvx _llx neg _lly neg /translate cvx _c { nc /begin cvx } if _r dup type /stringtype eq { cvx } { { exec } /forall cvx } ifelse _c { /end cvx } if /restore cvx ] cvx /_fn 12 _n length add string def _y _fn cvs pop /_y _y 1 add def _fn 12 _n putinterval _fn _c false dp _d exch _x 1 add exch put } if } for } for null dp _n _dd /_pd end xput } def /fc { _fm dup concatmatrix pop } def /p { /_fm exch ddef 9 -2 roll _pm translate fc 7 -2 roll _pm scale fc 5 -1 roll _pm rotate fc 4 -2 roll exch 0 ne { dup _pm rotate fc 1 -1 _pm scale fc neg _pm rotate fc } { pop } ifelse dup _pm rotate fc exch dup sin exch cos div 1 0 0 1 0 6 2 roll _pm astore fc neg _pm rotate fc _pd exch get /_fdd exch ddef /_pf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm patternfill } { pop fill } ifelse grestore pop } for pop } for restore newpath } ddef /_psf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm 9 copy 6 npop patternashow } { pop 6 copy 3 npop hvashow } ifelse grestore pop } for pop } for restore sw rmoveto } ddef /_pjsf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm 12 copy 6 npop patternawidthshow } { pop 9 copy 3 npop hvawidthshow } ifelse grestore pop } for pop } for restore swj rmoveto } ddef /_lp /none ddef } def /sc { _sm dup concatmatrix pop } def /P { /_sm exch ddef 9 -2 roll _pm translate sc 7 -2 roll _pm scale sc 5 -1 roll _pm rotate sc 4 -2 roll exch 0 ne { dup _pm rotate sc 1 -1 _pm scale sc neg _pm rotate sc } { pop } ifelse dup _pm rotate sc exch dup sin exch cos div 1 0 0 1 0 6 2 roll _pm astore sc neg _pm rotate sc _pd exch get /_sdd exch ddef /_ps { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm patternstroke } { pop stroke } ifelse grestore pop } for pop } for restore newpath } ddef /_pss { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm 10 copy 6 npop patternashowstroke } { pop 7 copy 3 npop ss } ifelse grestore pop } for pop } for restore pop sw rmoveto } ddef /_pjss { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm 13 copy 6 npop patternawidthshowstroke } { pop 10 copy 3 npop jss } ifelse grestore pop } for pop } for restore pop swj rmoveto } ddef /_lp /none ddef } def end userdict /Adobe_pattern_AI5 18 dict dup begin put /initialize { /definepattern where { pop } { begin begin Adobe_pattern_AI5 begin Adobe_pattern_AI5 { dup xcheck { bind } if pop pop } forall mark cachestatus 7 1 roll pop pop pop pop exch pop exch { { 10000 add dup 2 index gt { exit } if dup setcachelimit } loop } stopped cleartomark end end end Adobe_pattern_AI5 begin } ifelse } def /terminate { currentdict Adobe_pattern_AI5 eq { end } if } def errordict /nocurrentpoint { pop stop } put errordict /invalidaccess { pop stop } put /patternencoding 256 array def 0 1 255 { patternencoding exch ( ) 2 copy exch 0 exch put cvn put } for /definepattern { 17 dict begin /uniform exch def /cache exch def /key exch def /procarray exch def /mtx exch matrix invertmatrix def /height exch def /width exch def /ctm matrix currentmatrix def /ptm matrix def /str 32 string def /slice 9 dict def slice /s 1 put slice /q 256 procarray length div sqrt floor cvi put slice /b 0 put /FontBBox [ 0 0 0 0 ] def /FontMatrix mtx matrix copy def /Encoding patternencoding def /FontType 3 def /BuildChar { exch begin /setstrokeadjust where {pop true setstrokeadjust} if slice begin dup q dup mul mod s idiv /i exch def dup q dup mul mod s mod /j exch def q dup mul idiv procarray exch get /xl j width s div mul def /xg j 1 add width s div mul def /yl i height s div mul def /yg i 1 add height s div mul def uniform { 1 1 } { width 0 dtransform dup mul exch dup mul add sqrt dup 1 add exch div 0 height dtransform dup mul exch dup mul add sqrt dup 1 add exch div } ifelse width 0 cache { xl 4 index mul yl 4 index mul xg 6 index mul yg 6 index mul setcachedevice } { setcharwidth } ifelse gsave scale newpath xl yl moveto xg yl lineto xg yg lineto xl yg lineto closepath clip newpath end end exec grestore } def key currentdict definefont end } def /patterncachesize { gsave newpath 0 0 moveto width 0 lineto width height lineto 0 height lineto closepath patternmatrix setmatrix pathbbox exch ceiling 4 -1 roll floor sub 3 1 roll ceiling exch floor sub mul 1 add grestore } def /patterncachelimit { cachestatus 7 1 roll 6 npop 8 mul } def /patternpath { exch dup begin setfont ctm setmatrix concat slice exch /b exch slice /q get dup mul mul put FontMatrix concat uniform { width 0 dtransform round width div exch round width div exch 0 height dtransform round height div exch height div exch 0 0 transform round exch round exch ptm astore setmatrix } { ptm currentmatrix pop } ifelse { currentpoint } stopped not { 2 npop pathbbox true 4 index 3 index eq 4 index 3 index eq and { pop false { { 2 npop } { 3 npop true } { 7 npop true } { pop true } pathforall } stopped { 5 npop true } if } if { height div ceiling height mul 4 1 roll width div ceiling width mul 4 1 roll height div floor height mul 4 1 roll width div floor width mul 4 1 roll 2 index sub height div ceiling cvi exch 3 index sub width div ceiling cvi exch 4 2 roll moveto FontMatrix mtx invertmatrix dup dup 4 get exch 5 get rmoveto ptm ptm concatmatrix pop slice /s patterncachesize patterncachelimit div ceiling sqrt ceiling cvi dup slice /q get gt { pop slice /q get } if put 0 1 slice /s get dup mul 1 sub { slice /b get add gsave 0 1 str length 1 sub { str exch 2 index put } for pop dup { gsave ptm setmatrix 1 index str length idiv { str show } repeat 1 index str length mod str exch 0 exch getinterval show grestore 0 height rmoveto } repeat grestore } for 2 npop } { 4 npop } ifelse } if end } def /patternclip { _eo {eoclip} {clip} ifelse } def /patternstrokepath { strokepath } def /patternmatrix matrix def /patternfill { dup type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get } if gsave patternclip Adobe_pattern_AI5 /patternpath get exec grestore newpath } def /patternstroke { dup type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get } if gsave patternstrokepath true { { { newpath moveto } { lineto } { curveto } { closepath 3 copy Adobe_pattern_AI5 /patternfill get exec } pathforall 3 npop } stopped { 5 npop patternclip Adobe_pattern_AI5 /patternfill get exec } if } { patternclip Adobe_pattern_AI5 /patternfill get exec } ifelse grestore newpath } def /vpatternawidthshow { 6 1 roll /_hvay exch ddef /_hvax exch ddef /_hvwb exch ddef /_hvcy exch ddef /_hvcx exch ddef { dup cstring dup length 1 eq _charorientation 1 eq and { -90 rotate currentpoint _fontRotateAdjust add moveto gsave false charpath currentpoint 5 index 5 index 5 index Adobe_pattern_AI5 /patternfill get exec grestore _fontRotateAdjust sub moveto _hvwb eq { _hvcx _hvcy rmoveto } if _hvax _hvay rmoveto 90 rotate } { currentpoint _fontHeight sub _hvax sub 3 index _hvwb eq { _hvcx sub } if currentpoint exch 4 index stringwidth pop 2 div sub exch _fontAscent sub moveto gsave 2 index false charpath 6 index 6 index 6 index Adobe_pattern_AI5 /patternfill get exec grestore newpath moveto pop pop } ifelse } cforall 3 npop } def /hpatternawidthshow { { dup cstring exch gsave 3 index eq { 5 index 5 index rmoveto } if false charpath currentpoint 9 index 9 index 9 index Adobe_pattern_AI5 /patternfill get exec grestore newpath moveto 2 copy rmoveto } cforall 8 npop } def /patternashow { 0 0 0 6 3 roll patternawidthshow } def /patternawidthshow { 6 index type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get 7 1 roll } if _lineorientation 0 eq { hpatternawidthshow } { vpatternawidthshow } ifelse } def /vpatternawidthshowstroke { 7 1 roll 6 1 roll /_hvay exch ddef /_hvax exch ddef /_hvwb exch ddef /_hvcy exch ddef /_hvcx exch ddef { dup cstring dup length 1 eq _charorientation 1 eq and { -90 rotate currentpoint _fontRotateAdjust add moveto gsave false charpath currentpoint 3 index setmatrix 6 index 6 index 6 index Adobe_pattern_AI5 /patternstroke get exec grestore _fontRotateAdjust sub moveto _hvwb eq { _hvcx _hvcy rmoveto } if _hvax _hvay rmoveto 90 rotate } { currentpoint _fontHeight sub _hvax sub 3 index _hvwb eq { _hvcx sub } if currentpoint exch 4 index stringwidth pop 2 div sub exch _fontAscent sub moveto gsave 2 index false charpath 4 index setmatrix 7 index 7 index 7 index Adobe_pattern_AI5 /patternstroke get exec grestore newpath moveto pop pop } ifelse } cforall 4 npop } def /hpatternawidthshowstroke { 7 1 roll { dup cstring exch gsave 3 index eq { 5 index 5 index rmoveto } if false charpath currentpoint 7 index setmatrix 10 index 10 index 10 index Adobe_pattern_AI5 /patternstroke get exec grestore newpath moveto 2 copy rmoveto } cforall 9 npop } def /patternashowstroke { 0 0 0 7 3 roll patternawidthshowstroke } def /patternawidthshowstroke { 7 index type /dicttype eq { patternmatrix /patternmatrix get 8 1 roll } if _lineorientation 0 eq { hpatternawidthshowstroke } { vpatternawidthshowstroke } ifelse } def end setpacking %%EndResource %%EndProlog %%BeginSetup Adobe_level2_AI5 /initialize get exec Adobe_screens_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_typography_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_blend_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_pattern_AI5 /initialize get exec Adobe_ColorImage_AI6 /initialize get exec Adobe_Illustrator_AI5 /initialize get exec [ 39/quotesingle 96/grave 130/quotesinglbase 131/florin 132/quotedblbase 133/ellipsis 134/dagger 135/daggerdbl 136/circumflex 137/perthousand 138/Scaron 139/guilsinglleft 140/OE 145/quoteleft 146/quoteright 147/quotedblleft 148/quotedblright 149/bullet 150/endash 151/emdash 152/tilde 153/trademark 154/scaron 155/guilsinglright 156/oe 157/dotlessi 159/Ydieresis 164/currency 166/brokenbar 168/dieresis 169/copyright 170/ordfeminine 172/logicalnot 174/registered 175/macron 176/ring 177/plusminus 178/twosuperior 179/threesuperior 180/acute 181/mu 183/periodcentered 184/cedilla 185/onesuperior 186/ordmasculine 188/onequarter 189/onehalf 190/threequarters 192/Agrave 193/Aacute 194/Acircumflex 195/Atilde 196/Adieresis 197/Aring 198/AE 199/Ccedilla 200/Egrave 201/Eacute 202/Ecircumflex 203/Edieresis 204/Igrave 205/Iacute 206/Icircumflex 207/Idieresis 208/Eth 209/Ntilde 210/Ograve 211/Oacute 212/Ocircumflex 213/Otilde 214/Odieresis 215/multiply 216/Oslash 217/Ugrave 218/Uacute 219/Ucircumflex 220/Udieresis 221/Yacute 222/Thorn 223/germandbls 224/agrave 225/aacute 226/acircumflex 227/atilde 228/adieresis 229/aring 230/ae 231/ccedilla 232/egrave 233/eacute 234/ecircumflex 235/edieresis 236/igrave 237/iacute 238/icircumflex 239/idieresis 240/eth 241/ntilde 242/ograve 243/oacute 244/ocircumflex 245/otilde 246/odieresis 247/divide 248/oslash 249/ugrave 250/uacute 251/ucircumflex 252/udieresis 253/yacute 254/thorn 255/ydieresis TE %AI3_BeginEncoding: _Helvetica Helvetica [ /_Helvetica/Helvetica 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-Bold Helvetica-Bold [ /_Helvetica-Bold/Helvetica-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-Oblique Helvetica-Oblique [ /_Helvetica-Oblique/Helvetica-Oblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-BoldOblique Helvetica-BoldOblique [ /_Helvetica-BoldOblique/Helvetica-BoldOblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Roman Times-Roman [ /_Times-Roman/Times-Roman 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Bold Times-Bold [ /_Times-Bold/Times-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Italic Times-Italic [ /_Times-Italic/Times-Italic 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-BoldItalic Times-BoldItalic [ /_Times-BoldItalic/Times-BoldItalic 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier Courier [ /_Courier/Courier 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-Bold Courier-Bold [ /_Courier-Bold/Courier-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-Oblique Courier-Oblique [ /_Courier-Oblique/Courier-Oblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-BoldOblique Courier-BoldOblique [ /_Courier-BoldOblique/Courier-BoldOblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Symbol Symbol [ /_Symbol/Symbol 0 0 1 TZ %AI3_EndEncoding AdobeType %%EndSetup 1 XR u 0.000 0.000 0.000 0.247 k [] 0 d 0.000 0.000 0.000 1.000 K 1 j 311.2500 255.7500 m 318.0000 262.5000 L 346.5000 259.5000 L 367.5000 266.2500 L 374.2500 262.5000 L 367.5000 255.7500 L 360.0000 259.5000 L 339.0000 252.0000 L 311.2500 255.7500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 367.5000 255.7500 m 367.5000 237.0000 L 374.2500 243.7500 L 374.2500 262.5000 L 367.5000 255.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 311.2500 237.0000 m 339.0000 233.2500 L 360.0000 240.0000 L 367.5000 237.0000 L 367.5000 255.7500 L 360.0000 259.5000 L 339.0000 252.0000 L 311.2500 255.7500 L 311.2500 237.0000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 101.2500 227.2500 m 108.7500 234.7500 L 136.5000 231.0000 L 157.5000 237.7500 L 165.0000 234.7500 L 157.5000 227.2500 L 150.7500 231.0000 L 129.7500 224.2500 L 101.2500 227.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 157.5000 227.2500 m 157.5000 208.5000 L 165.0000 216.0000 L 165.0000 234.7500 L 157.5000 227.2500 L B U u 0.000 0.000 0.000 0.000 k 101.2500 208.5000 m 129.7500 205.5000 L 150.7500 212.2500 L 157.5000 208.5000 L 157.5000 227.2500 L 150.7500 231.0000 L 129.7500 224.2500 L 101.2500 227.2500 L 101.2500 208.5000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 361.5000 199.5000 m 369.0000 206.2500 L 369.0000 220.5000 L 361.5000 213.7500 L 361.5000 199.5000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 227.2500 213.7500 m 361.5000 213.7500 L 369.0000 220.5000 L 234.0000 220.5000 L 227.2500 213.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 227.2500 199.5000 m 361.5000 199.5000 L 361.5000 213.7500 L 227.2500 213.7500 L 227.2500 199.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 229.5000 204.0000 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (branch=8d7f2e89c.74a72681\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 3.0000 93.7500 m 10.5000 100.5000 L 38.2500 97.5000 L 59.2500 104.2500 L 66.7500 100.5000 L 59.2500 93.7500 L 52.5000 97.5000 L 31.5000 90.0000 L 3.0000 93.7500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 59.2500 93.7500 m 59.2500 66.7500 L 66.7500 74.2500 L 66.7500 100.5000 L 59.2500 93.7500 L B U u 0.000 0.000 0.000 0.000 k 3.0000 66.7500 m 31.5000 63.7500 L 52.5000 70.5000 L 59.2500 66.7500 L 59.2500 93.7500 L 52.5000 97.5000 L 31.5000 90.0000 L 3.0000 93.7500 L 3.0000 66.7500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 3.0000 177.7500 m 10.5000 184.5000 L 38.2500 181.5000 L 59.2500 188.2500 L 66.7500 184.5000 L 59.2500 177.7500 L 52.5000 181.5000 L 31.5000 174.0000 L 3.0000 177.7500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 59.2500 177.7500 m 59.2500 97.5000 L 66.7500 105.0000 L 66.7500 184.5000 L 59.2500 177.7500 L B U u 0.000 0.000 0.000 0.000 k 3.0000 97.5000 m 31.5000 94.5000 L 52.5000 101.2500 L 59.2500 97.5000 L 59.2500 177.7500 L 52.5000 181.5000 L 31.5000 174.0000 L 3.0000 177.7500 L 3.0000 97.5000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 59.2500 158.2500 m 66.7500 165.0000 L 66.7500 179.2500 L 59.2500 172.5000 L 59.2500 158.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 3.0000 158.2500 m 59.2500 158.2500 L 59.2500 172.5000 L 3.0000 172.5000 L 3.0000 158.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 5.2500 162.7500 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sip_from\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 59.2500 144.0000 m 66.7500 151.5000 L 66.7500 165.0000 L 59.2500 158.2500 L 59.2500 144.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 3.0000 144.0000 m 59.2500 144.0000 L 59.2500 158.2500 L 3.0000 158.2500 L 3.0000 144.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 5.2500 148.5000 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sip_to\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 59.2500 129.7500 m 66.7500 137.2500 L 66.7500 151.5000 L 59.2500 144.0000 L 59.2500 129.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 3.0000 129.7500 m 59.2500 129.7500 L 59.2500 144.0000 L 3.0000 144.0000 L 3.0000 129.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 5.2500 135.0000 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sip_contact\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 59.2500 102.0000 m 66.7500 108.7500 L 66.7500 123.0000 L 59.2500 116.2500 L 59.2500 102.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 3.0000 102.0000 m 59.2500 102.0000 L 59.2500 116.2500 L 3.0000 116.2500 L 3.0000 102.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 5.2500 106.5000 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sip_cseq\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 59.2500 116.2500 m 66.7500 123.0000 L 66.7500 137.2500 L 59.2500 129.7500 L 59.2500 116.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 3.0000 116.2500 m 59.2500 116.2500 L 59.2500 129.7500 L 3.0000 129.7500 L 3.0000 116.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 5.2500 120.7500 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sip_call_id\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 59.2500 74.2500 m 66.7500 81.0000 L 66.7500 95.2500 L 59.2500 87.7500 L 59.2500 74.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 3.0000 74.2500 m 59.2500 74.2500 L 59.2500 87.7500 L 3.0000 87.7500 L 3.0000 74.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 5.2500 78.7500 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sip_cntn_len\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 59.2500 60.0000 m 66.7500 66.7500 L 66.7500 81.0000 L 59.2500 74.2500 L 59.2500 60.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 3.0000 60.0000 m 59.2500 60.0000 L 59.2500 74.2500 L 3.0000 74.2500 L 3.0000 60.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 5.2500 64.5000 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sip_payload\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 3.0000 220.5000 m 10.5000 227.2500 L 38.2500 224.2500 L 59.2500 231.0000 L 66.7500 227.2500 L 59.2500 220.5000 L 52.5000 224.2500 L 31.5000 216.7500 L 3.0000 220.5000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 59.2500 220.5000 m 59.2500 182.2500 L 66.7500 189.0000 L 66.7500 227.2500 L 59.2500 220.5000 L B U u 0.000 0.000 0.000 0.000 k 3.0000 182.2500 m 31.5000 178.5000 L 52.5000 185.2500 L 59.2500 182.2500 L 59.2500 220.5000 L 52.5000 224.2500 L 31.5000 216.7500 L 3.0000 220.5000 L 3.0000 182.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 59.2500 227.2500 m 66.7500 234.7500 L 66.7500 249.0000 L 59.2500 241.5000 L 59.2500 227.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 3.0000 241.5000 m 59.2500 241.5000 L 66.7500 249.0000 L 10.5000 249.0000 L 3.0000 241.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 3.0000 227.2500 m 59.2500 227.2500 L 59.2500 241.5000 L 3.0000 241.5000 L 3.0000 227.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 5.2500 232.5000 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sip_request\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 59.2500 213.7500 m 66.7500 220.5000 L 66.7500 234.7500 L 59.2500 227.2500 L 59.2500 213.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 3.0000 213.7500 m 59.2500 213.7500 L 59.2500 227.2500 L 3.0000 227.2500 L 3.0000 213.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 5.2500 218.2500 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sip_status\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 59.2500 199.5000 m 66.7500 206.2500 L 66.7500 220.5000 L 59.2500 213.7500 L 59.2500 199.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 3.0000 199.5000 m 59.2500 199.5000 L 59.2500 213.7500 L 3.0000 213.7500 L 3.0000 199.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 5.2500 204.0000 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sip_via\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 59.2500 186.0000 m 66.7500 192.7500 L 66.7500 206.2500 L 59.2500 199.5000 L 59.2500 186.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 3.0000 186.0000 m 59.2500 186.0000 L 59.2500 199.5000 L 3.0000 199.5000 L 3.0000 186.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 5.2500 190.5000 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sip_route\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 157.5000 354.0000 m 165.0000 360.7500 L 165.0000 375.0000 L 157.5000 368.2500 L 157.5000 354.0000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 101.2500 368.2500 m 157.5000 368.2500 L 165.0000 375.0000 L 108.7500 375.0000 L 101.2500 368.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 354.0000 m 157.5000 354.0000 L 157.5000 368.2500 L 101.2500 368.2500 L 101.2500 354.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 358.5000 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (rq_common\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 157.5000 339.7500 m 165.0000 346.5000 L 165.0000 360.7500 L 157.5000 354.0000 L 157.5000 339.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 339.7500 m 157.5000 339.7500 L 157.5000 354.0000 L 101.2500 354.0000 L 101.2500 339.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 344.2500 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (rq_method\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 157.5000 325.5000 m 165.0000 333.0000 L 165.0000 346.5000 L 157.5000 339.7500 L 157.5000 325.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 325.5000 m 157.5000 325.5000 L 157.5000 339.7500 L 101.2500 339.7500 L 101.2500 325.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 330.7500 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (rq_url\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 157.5000 312.0000 m 165.0000 318.7500 L 165.0000 333.0000 L 157.5000 325.5000 L 157.5000 312.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 312.0000 m 157.5000 312.0000 L 157.5000 325.5000 L 101.2500 325.5000 L 101.2500 312.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 316.5000 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (rq_version\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 221.2500 307.5000 m 228.7500 314.2500 L 228.7500 328.5000 L 221.2500 321.7500 L 221.2500 307.5000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 178.5000 321.7500 m 221.2500 321.7500 L 228.7500 328.5000 L 186.0000 328.5000 L 178.5000 321.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 178.5000 307.5000 m 221.2500 307.5000 L 221.2500 321.7500 L 178.5000 321.7500 L 178.5000 307.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 180.7500 312.0000 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (SIP/2.0\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 1 j 153.0000 347.2500 m 152.2500 348.0000 L 152.2500 348.0000 L 151.5000 348.7500 L 151.5000 348.7500 L 150.7500 348.7500 L 150.0000 348.7500 L 149.2500 348.7500 L 149.2500 348.0000 L 148.5000 348.0000 L 148.5000 347.2500 L 148.5000 346.5000 L 148.5000 345.7500 L 149.2500 345.7500 L 149.2500 345.0000 L 150.0000 345.0000 L 150.7500 345.0000 L 151.5000 345.0000 L 151.5000 345.0000 L 152.2500 345.7500 L 152.2500 345.7500 L 153.0000 346.5000 L 153.0000 347.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 173.2500 353.2500 m 178.5000 351.0000 L 174.0000 347.2500 L 173.2500 353.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 153.0000 333.0000 m 152.2500 333.7500 L 152.2500 333.7500 L 152.2500 334.5000 L 151.5000 334.5000 L 150.7500 334.5000 L 150.0000 334.5000 L 150.0000 334.5000 L 149.2500 334.5000 L 149.2500 333.7500 L 148.5000 333.7500 L 148.5000 333.0000 L 148.5000 332.2500 L 149.2500 331.5000 L 149.2500 331.5000 L 150.0000 330.7500 L 150.0000 330.7500 L 150.7500 330.7500 L 151.5000 330.7500 L 152.2500 331.5000 L 152.2500 331.5000 L 152.2500 332.2500 L 153.0000 333.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 173.2500 335.2500 m 178.5000 333.0000 L 173.2500 330.0000 L 173.2500 335.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 153.0000 318.7500 m 153.0000 318.7500 L 152.2500 319.5000 L 152.2500 320.2500 L 151.5000 320.2500 L 151.5000 321.0000 L 150.7500 321.0000 L 150.0000 321.0000 L 149.2500 320.2500 L 149.2500 320.2500 L 148.5000 319.5000 L 148.5000 318.7500 L 148.5000 318.7500 L 148.5000 318.0000 L 149.2500 317.2500 L 149.2500 317.2500 L 150.0000 316.5000 L 150.7500 316.5000 L 151.5000 316.5000 L 151.5000 317.2500 L 152.2500 317.2500 L 152.2500 318.0000 L 153.0000 318.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 174.0000 318.0000 m 178.5000 314.2500 L 173.2500 312.7500 L 174.0000 318.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 51.0000 236.2500 m 50.2500 237.0000 L 49.5000 236.2500 L 49.5000 236.2500 L 48.7500 236.2500 L 48.0000 235.5000 L 48.0000 234.7500 L 48.0000 234.7500 L 48.0000 234.0000 L 48.7500 233.2500 L 48.7500 233.2500 L 49.5000 232.5000 L 49.5000 232.5000 L 50.2500 232.5000 L 51.0000 232.5000 L 51.7500 233.2500 L 51.7500 233.2500 L 51.7500 234.0000 L 51.7500 234.7500 L 51.7500 235.5000 L 51.7500 235.5000 L 51.0000 236.2500 L 51.0000 236.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 96.7500 357.0000 m 101.2500 360.7500 L 102.0000 354.7500 L 96.7500 357.0000 L F U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 157.5000 283.5000 m 165.0000 291.0000 L 165.0000 304.5000 L 157.5000 297.7500 L 157.5000 283.5000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 101.2500 297.7500 m 157.5000 297.7500 L 165.0000 304.5000 L 108.7500 304.5000 L 101.2500 297.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 283.5000 m 157.5000 283.5000 L 157.5000 297.7500 L 101.2500 297.7500 L 101.2500 283.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 288.0000 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (v_common\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 157.5000 255.7500 m 165.0000 262.5000 L 165.0000 276.7500 L 157.5000 270.0000 L 157.5000 255.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 255.7500 m 157.5000 255.7500 L 157.5000 270.0000 L 101.2500 270.0000 L 101.2500 255.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 260.2500 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (v_protocol\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 157.5000 241.5000 m 165.0000 249.0000 L 165.0000 262.5000 L 157.5000 255.7500 L 157.5000 241.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 241.5000 m 157.5000 241.5000 L 157.5000 255.7500 L 101.2500 255.7500 L 101.2500 241.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 246.0000 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (v_host\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 157.5000 227.2500 m 165.0000 234.7500 L 165.0000 249.0000 L 157.5000 241.5000 L 157.5000 227.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 227.2500 m 157.5000 227.2500 L 157.5000 241.5000 L 101.2500 241.5000 L 101.2500 227.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 232.5000 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (v_port\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 157.5000 213.7500 m 165.0000 220.5000 L 165.0000 234.7500 L 157.5000 227.2500 L 157.5000 213.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 213.7500 m 157.5000 213.7500 L 157.5000 227.2500 L 101.2500 227.2500 L 101.2500 213.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 218.2500 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (v_params\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 1 j 152.2500 219.7500 m 153.0000 220.5000 L 153.0000 221.2500 L 152.2500 221.2500 L 152.2500 222.0000 L 151.5000 222.0000 L 150.7500 222.7500 L 150.7500 222.7500 L 150.0000 222.7500 L 149.2500 222.0000 L 149.2500 222.0000 L 148.5000 221.2500 L 148.5000 220.5000 L 148.5000 220.5000 L 148.5000 219.7500 L 149.2500 219.0000 L 150.0000 219.0000 L 150.0000 218.2500 L 150.7500 218.2500 L 151.5000 219.0000 L 151.5000 219.0000 L 152.2500 219.0000 L 152.2500 219.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 174.7500 214.5000 m 178.5000 210.0000 L 172.5000 209.2500 L 174.7500 214.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 153.0000 262.5000 m 152.2500 263.2500 L 152.2500 264.0000 L 152.2500 264.0000 L 151.5000 264.7500 L 150.7500 264.7500 L 150.0000 264.7500 L 150.0000 264.7500 L 149.2500 264.0000 L 149.2500 264.0000 L 148.5000 263.2500 L 148.5000 262.5000 L 148.5000 261.7500 L 149.2500 261.7500 L 149.2500 261.0000 L 150.0000 261.0000 L 150.0000 261.0000 L 150.7500 261.0000 L 151.5000 261.0000 L 152.2500 261.0000 L 152.2500 261.7500 L 152.2500 261.7500 L 153.0000 262.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 173.2500 265.5000 m 178.5000 262.5000 L 173.2500 260.2500 L 173.2500 265.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 153.0000 248.2500 m 153.0000 249.0000 L 152.2500 249.7500 L 152.2500 249.7500 L 151.5000 250.5000 L 151.5000 250.5000 L 150.7500 250.5000 L 150.0000 250.5000 L 149.2500 250.5000 L 149.2500 249.7500 L 148.5000 249.7500 L 148.5000 249.0000 L 148.5000 248.2500 L 148.5000 247.5000 L 149.2500 247.5000 L 149.2500 246.7500 L 150.0000 246.7500 L 150.7500 246.7500 L 151.5000 246.7500 L 151.5000 246.7500 L 152.2500 247.5000 L 152.2500 247.5000 L 153.0000 248.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 173.2500 249.0000 m 178.5000 246.0000 L 173.2500 243.7500 L 173.2500 249.0000 L F U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 206.2500 203.2500 m 213.0000 210.0000 L 213.0000 224.2500 L 206.2500 216.7500 L 206.2500 203.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 178.5000 216.7500 m 206.2500 216.7500 L 213.0000 224.2500 L 186.0000 224.2500 L 178.5000 216.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 178.5000 203.2500 m 206.2500 203.2500 L 206.2500 216.7500 L 178.5000 216.7500 L 178.5000 203.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 206.2500 189.0000 m 213.0000 195.7500 L 213.0000 210.0000 L 206.2500 203.2500 L 206.2500 189.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 178.5000 189.0000 m 206.2500 189.0000 L 206.2500 203.2500 L 178.5000 203.2500 L 178.5000 189.0000 L B U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 203.2500 210.0000 m 203.2500 210.0000 L 203.2500 210.7500 L 202.5000 211.5000 L 202.5000 211.5000 L 201.7500 212.2500 L 201.0000 212.2500 L 201.0000 212.2500 L 200.2500 211.5000 L 199.5000 211.5000 L 199.5000 210.7500 L 199.5000 210.0000 L 199.5000 210.0000 L 199.5000 209.2500 L 199.5000 208.5000 L 200.2500 208.5000 L 201.0000 207.7500 L 201.0000 207.7500 L 201.7500 207.7500 L 202.5000 208.5000 L 203.2500 208.5000 L 203.2500 209.2500 L 203.2500 210.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 222.0000 210.0000 m 227.2500 206.2500 L 221.2500 204.7500 L 222.0000 210.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 53.2500 208.5000 m 53.2500 208.5000 L 52.5000 208.5000 L 51.7500 208.5000 L 51.0000 208.5000 L 51.0000 207.7500 L 50.2500 207.0000 L 50.2500 207.0000 L 50.2500 206.2500 L 50.2500 205.5000 L 51.0000 205.5000 L 51.7500 204.7500 L 51.7500 204.7500 L 52.5000 204.7500 L 53.2500 204.7500 L 53.2500 204.7500 L 54.0000 205.5000 L 54.0000 205.5000 L 54.7500 206.2500 L 54.7500 207.0000 L 54.0000 207.7500 L 54.0000 207.7500 L 53.2500 208.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 96.7500 287.2500 m 101.2500 291.0000 L 101.2500 285.0000 L 96.7500 287.2500 L F U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 157.5000 270.0000 m 165.0000 276.7500 L 165.0000 291.0000 L 157.5000 283.5000 L 157.5000 270.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 270.0000 m 157.5000 270.0000 L 157.5000 283.5000 L 101.2500 283.5000 L 101.2500 270.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 274.5000 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (v_next\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 367.5000 312.0000 m 374.2500 318.7500 L 374.2500 333.0000 L 367.5000 325.5000 L 367.5000 312.0000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 311.2500 325.5000 m 367.5000 325.5000 L 374.2500 333.0000 L 318.0000 333.0000 L 311.2500 325.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 311.2500 312.0000 m 367.5000 312.0000 L 367.5000 325.5000 L 311.2500 325.5000 L 311.2500 312.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 313.5000 316.5000 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (v_common\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 367.5000 283.5000 m 374.2500 291.0000 L 374.2500 304.5000 L 367.5000 297.7500 L 367.5000 283.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 311.2500 283.5000 m 367.5000 283.5000 L 367.5000 297.7500 L 311.2500 297.7500 L 311.2500 283.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 313.5000 288.0000 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (v_protocol\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 367.5000 270.0000 m 374.2500 276.7500 L 374.2500 291.0000 L 367.5000 283.5000 L 367.5000 270.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 311.2500 270.0000 m 367.5000 270.0000 L 367.5000 283.5000 L 311.2500 283.5000 L 311.2500 270.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 313.5000 274.5000 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (v_host\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 367.5000 255.7500 m 374.2500 262.5000 L 374.2500 276.7500 L 367.5000 270.0000 L 367.5000 255.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 311.2500 255.7500 m 367.5000 255.7500 L 367.5000 270.0000 L 311.2500 270.0000 L 311.2500 255.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 313.5000 260.2500 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (v_port\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 367.5000 241.5000 m 374.2500 249.0000 L 374.2500 262.5000 L 367.5000 255.7500 L 367.5000 241.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 311.2500 241.5000 m 367.5000 241.5000 L 367.5000 255.7500 L 311.2500 255.7500 L 311.2500 241.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 313.5000 246.0000 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (v_params\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 367.5000 297.7500 m 374.2500 304.5000 L 374.2500 318.7500 L 367.5000 312.0000 L 367.5000 297.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 311.2500 297.7500 m 367.5000 297.7500 L 367.5000 312.0000 L 311.2500 312.0000 L 311.2500 297.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 313.5000 302.2500 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (v_next\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 1 j 152.2500 277.5000 m 152.2500 277.5000 L 152.2500 278.2500 L 151.5000 278.2500 L 150.7500 279.0000 L 150.7500 279.0000 L 150.0000 278.2500 L 149.2500 278.2500 L 149.2500 277.5000 L 148.5000 277.5000 L 148.5000 276.7500 L 148.5000 276.0000 L 149.2500 276.0000 L 149.2500 275.2500 L 150.0000 274.5000 L 150.0000 274.5000 L 150.7500 274.5000 L 151.5000 274.5000 L 152.2500 275.2500 L 152.2500 275.2500 L 152.2500 276.0000 L 153.0000 276.7500 L 152.2500 277.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 305.2500 320.2500 m 311.2500 318.7500 L 306.7500 315.0000 L 305.2500 320.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 362.2500 290.2500 m 362.2500 291.0000 L 362.2500 291.7500 L 362.2500 291.7500 L 361.5000 292.5000 L 360.7500 292.5000 L 360.7500 292.5000 L 360.0000 292.5000 L 359.2500 292.5000 L 358.5000 291.7500 L 358.5000 291.7500 L 358.5000 291.0000 L 358.5000 290.2500 L 358.5000 290.2500 L 358.5000 289.5000 L 359.2500 288.7500 L 360.0000 288.7500 L 360.0000 288.7500 L 360.7500 288.7500 L 361.5000 288.7500 L 362.2500 289.5000 L 362.2500 289.5000 L 362.2500 290.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 383.2500 290.2500 m 388.5000 286.5000 L 382.5000 285.0000 L 383.2500 290.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 362.2500 276.0000 m 362.2500 276.7500 L 362.2500 277.5000 L 362.2500 278.2500 L 361.5000 278.2500 L 361.5000 278.2500 L 360.7500 279.0000 L 360.0000 279.0000 L 359.2500 278.2500 L 359.2500 278.2500 L 358.5000 277.5000 L 358.5000 277.5000 L 358.5000 276.7500 L 358.5000 276.0000 L 358.5000 275.2500 L 359.2500 275.2500 L 359.2500 274.5000 L 360.0000 274.5000 L 360.7500 274.5000 L 361.5000 274.5000 L 361.5000 275.2500 L 362.2500 276.0000 L 362.2500 276.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 384.0000 273.7500 m 388.5000 270.0000 L 382.5000 268.5000 L 384.0000 273.7500 L F U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 541.5000 227.2500 m 548.2500 234.7500 L 548.2500 249.0000 L 541.5000 241.5000 L 541.5000 227.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 437.2500 241.5000 m 541.5000 241.5000 L 548.2500 249.0000 L 444.7500 249.0000 L 437.2500 241.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 437.2500 227.2500 m 541.5000 227.2500 L 541.5000 241.5000 L 437.2500 241.5000 L 437.2500 227.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 439.5000 232.5000 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (maddr=110.213.33.19\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 1 j 362.2500 247.5000 m 362.2500 248.2500 L 362.2500 249.0000 L 362.2500 249.7500 L 362.2500 249.7500 L 361.5000 250.5000 L 360.7500 250.5000 L 360.7500 250.5000 L 360.0000 250.5000 L 359.2500 250.5000 L 358.5000 249.7500 L 358.5000 249.7500 L 358.5000 249.0000 L 358.5000 248.2500 L 358.5000 247.5000 L 358.5000 247.5000 L 359.2500 246.7500 L 360.0000 246.7500 L 360.0000 246.7500 L 360.7500 246.7500 L 361.5000 246.7500 L 361.5000 247.5000 L 362.2500 247.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 384.7500 239.2500 m 388.5000 234.7500 L 382.5000 234.7500 L 384.7500 239.2500 L F U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 416.2500 227.2500 m 423.7500 234.7500 L 423.7500 249.0000 L 416.2500 241.5000 L 416.2500 227.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 388.5000 241.5000 m 416.2500 241.5000 L 423.7500 249.0000 L 395.2500 249.0000 L 388.5000 241.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 388.5000 227.2500 m 416.2500 227.2500 L 416.2500 241.5000 L 388.5000 241.5000 L 388.5000 227.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 416.2500 213.7500 m 423.7500 220.5000 L 423.7500 234.7500 L 416.2500 227.2500 L 416.2500 213.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 388.5000 213.7500 m 416.2500 213.7500 L 416.2500 227.2500 L 388.5000 227.2500 L 388.5000 213.7500 L B U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 414.0000 234.7500 m 414.0000 235.5000 L 413.2500 235.5000 L 413.2500 236.2500 L 412.5000 236.2500 L 411.7500 237.0000 L 411.7500 237.0000 L 411.0000 236.2500 L 410.2500 236.2500 L 410.2500 235.5000 L 409.5000 235.5000 L 409.5000 234.7500 L 409.5000 234.0000 L 410.2500 233.2500 L 410.2500 233.2500 L 411.0000 232.5000 L 411.7500 232.5000 L 411.7500 232.5000 L 412.5000 232.5000 L 413.2500 233.2500 L 413.2500 233.2500 L 414.0000 234.0000 L 414.0000 234.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 432.0000 237.0000 m 437.2500 234.7500 L 432.0000 231.7500 L 432.0000 237.0000 L F U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 412.5000 244.5000 m 419.2500 251.2500 L 419.2500 265.5000 L 412.5000 258.7500 L 412.5000 244.5000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 388.5000 258.7500 m 412.5000 258.7500 L 419.2500 265.5000 L 395.2500 265.5000 L 388.5000 258.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 388.5000 244.5000 m 412.5000 244.5000 L 412.5000 258.7500 L 388.5000 258.7500 L 388.5000 244.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 390.7500 249.0000 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (1030\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 269.2500 238.5000 m 276.0000 246.0000 L 276.0000 259.5000 L 269.2500 252.7500 L 269.2500 238.5000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 178.5000 252.7500 m 269.2500 252.7500 L 276.0000 259.5000 L 186.0000 259.5000 L 178.5000 252.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 178.5000 238.5000 m 269.2500 238.5000 L 269.2500 252.7500 L 178.5000 252.7500 L 178.5000 238.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 180.7500 243.7500 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sip.example.edu\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 240.7500 255.7500 m 248.2500 262.5000 L 248.2500 276.7500 L 240.7500 270.0000 L 240.7500 255.7500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 178.5000 270.0000 m 240.7500 270.0000 L 248.2500 276.7500 L 186.0000 276.7500 L 178.5000 270.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 178.5000 255.7500 m 240.7500 255.7500 L 240.7500 270.0000 L 178.5000 270.0000 L 178.5000 255.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 180.7500 260.2500 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (SIP/2.0/UDP\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 157.5000 158.2500 m 165.0000 165.0000 L 165.0000 179.2500 L 157.5000 172.5000 L 157.5000 158.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 101.2500 172.5000 m 157.5000 172.5000 L 165.0000 179.2500 L 108.7500 179.2500 L 101.2500 172.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 158.2500 m 157.5000 158.2500 L 157.5000 172.5000 L 101.2500 172.5000 L 101.2500 158.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 162.7500 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (a_common\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 157.5000 129.7500 m 165.0000 137.2500 L 165.0000 151.5000 L 157.5000 144.0000 L 157.5000 129.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 129.7500 m 157.5000 129.7500 L 157.5000 144.0000 L 101.2500 144.0000 L 101.2500 129.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 135.0000 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (a_display\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 157.5000 116.2500 m 165.0000 123.0000 L 165.0000 137.2500 L 157.5000 129.7500 L 157.5000 116.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 116.2500 m 157.5000 116.2500 L 157.5000 129.7500 L 101.2500 129.7500 L 101.2500 116.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 120.7500 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (a_url\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 157.5000 87.7500 m 165.0000 95.2500 L 165.0000 108.7500 L 157.5000 102.0000 L 157.5000 87.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 87.7500 m 157.5000 87.7500 L 157.5000 102.0000 L 101.2500 102.0000 L 101.2500 87.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 93.0000 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (a_tag\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 157.5000 102.0000 m 165.0000 108.7500 L 165.0000 123.0000 L 157.5000 116.2500 L 157.5000 102.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 102.0000 m 157.5000 102.0000 L 157.5000 116.2500 L 101.2500 116.2500 L 101.2500 102.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 106.5000 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (a_params\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 157.5000 144.0000 m 165.0000 151.5000 L 165.0000 165.0000 L 157.5000 158.2500 L 157.5000 144.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 144.0000 m 157.5000 144.0000 L 157.5000 158.2500 L 101.2500 158.2500 L 101.2500 144.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 148.5000 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (a_next\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 1 j 54.7500 151.5000 m 54.0000 152.2500 L 54.0000 153.0000 L 53.2500 153.0000 L 52.5000 153.0000 L 52.5000 153.0000 L 51.7500 153.0000 L 51.0000 153.0000 L 51.0000 152.2500 L 50.2500 151.5000 L 50.2500 151.5000 L 50.2500 150.7500 L 51.0000 150.0000 L 51.0000 149.2500 L 51.7500 149.2500 L 51.7500 149.2500 L 52.5000 149.2500 L 53.2500 149.2500 L 54.0000 149.2500 L 54.0000 150.0000 L 54.0000 150.7500 L 54.7500 151.5000 L 54.7500 151.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 95.2500 166.5000 m 101.2500 165.0000 L 96.7500 161.2500 L 95.2500 166.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 153.0000 123.0000 m 152.2500 123.7500 L 152.2500 124.5000 L 151.5000 124.5000 L 151.5000 125.2500 L 150.7500 125.2500 L 150.0000 125.2500 L 149.2500 124.5000 L 149.2500 124.5000 L 148.5000 123.7500 L 148.5000 123.7500 L 148.5000 123.0000 L 148.5000 122.2500 L 149.2500 121.5000 L 149.2500 121.5000 L 150.0000 121.5000 L 150.7500 120.7500 L 151.5000 120.7500 L 151.5000 121.5000 L 152.2500 121.5000 L 152.2500 122.2500 L 153.0000 123.0000 L 153.0000 123.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 173.2500 128.2500 m 178.5000 126.0000 L 173.2500 123.0000 L 173.2500 128.2500 L F U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 283.5000 325.5000 m 290.2500 333.0000 L 290.2500 346.5000 L 283.5000 339.7500 L 283.5000 325.5000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 178.5000 339.7500 m 283.5000 339.7500 L 290.2500 346.5000 L 186.0000 346.5000 L 178.5000 339.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 178.5000 325.5000 m 283.5000 325.5000 L 283.5000 339.7500 L 178.5000 339.7500 L 178.5000 325.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 180.7500 330.7500 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sip:joe@example.com\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 198.7500 344.2500 m 206.2500 351.0000 L 206.2500 365.2500 L 198.7500 357.7500 L 198.7500 344.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 178.5000 357.7500 m 198.7500 357.7500 L 206.2500 365.2500 L 186.0000 365.2500 L 178.5000 357.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 178.5000 344.2500 m 198.7500 344.2500 L 198.7500 357.7500 L 178.5000 357.7500 L 178.5000 344.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 180.7500 348.7500 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (BYE\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 1 j 152.2500 138.0000 m 152.2500 138.0000 L 152.2500 138.7500 L 151.5000 138.7500 L 150.7500 139.5000 L 150.7500 139.5000 L 150.0000 138.7500 L 149.2500 138.7500 L 149.2500 138.0000 L 148.5000 138.0000 L 148.5000 137.2500 L 148.5000 136.5000 L 148.5000 135.7500 L 149.2500 135.7500 L 150.0000 135.0000 L 150.0000 135.0000 L 150.7500 135.0000 L 151.5000 135.0000 L 152.2500 135.7500 L 152.2500 135.7500 L 152.2500 136.5000 L 153.0000 137.2500 L 152.2500 138.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 172.5000 145.5000 m 178.5000 144.0000 L 174.0000 140.2500 L 172.5000 145.5000 L F U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 367.5000 172.5000 m 374.2500 179.2500 L 374.2500 192.7500 L 367.5000 186.0000 L 367.5000 172.5000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 311.2500 186.0000 m 367.5000 186.0000 L 374.2500 192.7500 L 318.0000 192.7500 L 311.2500 186.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 311.2500 172.5000 m 367.5000 172.5000 L 367.5000 186.0000 L 311.2500 186.0000 L 311.2500 172.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 313.5000 177.0000 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (a_common\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 367.5000 144.0000 m 374.2500 151.5000 L 374.2500 165.0000 L 367.5000 158.2500 L 367.5000 144.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 311.2500 144.0000 m 367.5000 144.0000 L 367.5000 158.2500 L 311.2500 158.2500 L 311.2500 144.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 313.5000 148.5000 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (a_display\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 367.5000 129.7500 m 374.2500 137.2500 L 374.2500 151.5000 L 367.5000 144.0000 L 367.5000 129.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 311.2500 129.7500 m 367.5000 129.7500 L 367.5000 144.0000 L 311.2500 144.0000 L 311.2500 129.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 313.5000 135.0000 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (a_url\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 367.5000 102.0000 m 374.2500 108.7500 L 374.2500 123.0000 L 367.5000 116.2500 L 367.5000 102.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 311.2500 102.0000 m 367.5000 102.0000 L 367.5000 116.2500 L 311.2500 116.2500 L 311.2500 102.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 313.5000 106.5000 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (a_tag\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 367.5000 116.2500 m 374.2500 123.0000 L 374.2500 137.2500 L 367.5000 129.7500 L 367.5000 116.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 311.2500 116.2500 m 367.5000 116.2500 L 367.5000 129.7500 L 311.2500 129.7500 L 311.2500 116.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 313.5000 120.7500 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (a_params\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 367.5000 158.2500 m 374.2500 165.0000 L 374.2500 179.2500 L 367.5000 172.5000 L 367.5000 158.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 311.2500 158.2500 m 367.5000 158.2500 L 367.5000 172.5000 L 311.2500 172.5000 L 311.2500 158.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 313.5000 162.7500 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (a_next\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 507.7500 116.2500 m 514.5000 123.0000 L 514.5000 137.2500 L 507.7500 129.7500 L 507.7500 116.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 437.2500 129.7500 m 507.7500 129.7500 L 514.5000 137.2500 L 444.7500 137.2500 L 437.2500 129.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 437.2500 116.2500 m 507.7500 116.2500 L 507.7500 129.7500 L 437.2500 129.7500 L 437.2500 116.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 439.5000 120.7500 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (tag=77241a86\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 416.2500 116.2500 m 423.7500 123.0000 L 423.7500 137.2500 L 416.2500 129.7500 L 416.2500 116.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 388.5000 129.7500 m 416.2500 129.7500 L 423.7500 137.2500 L 395.2500 137.2500 L 388.5000 129.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 388.5000 116.2500 m 416.2500 116.2500 L 416.2500 129.7500 L 388.5000 129.7500 L 388.5000 116.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 416.2500 102.0000 m 423.7500 108.7500 L 423.7500 123.0000 L 416.2500 116.2500 L 416.2500 102.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 388.5000 102.0000 m 416.2500 102.0000 L 416.2500 116.2500 L 388.5000 116.2500 L 388.5000 102.0000 L B U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 362.2500 137.2500 m 362.2500 138.0000 L 362.2500 138.7500 L 361.5000 138.7500 L 360.7500 138.7500 L 360.7500 139.5000 L 360.0000 138.7500 L 359.2500 138.7500 L 359.2500 138.7500 L 358.5000 138.0000 L 358.5000 137.2500 L 358.5000 137.2500 L 358.5000 136.5000 L 358.5000 135.7500 L 359.2500 135.7500 L 360.0000 135.0000 L 360.0000 135.0000 L 360.7500 135.0000 L 361.5000 135.0000 L 361.5000 135.7500 L 362.2500 136.5000 L 362.2500 136.5000 L 362.2500 137.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 382.5000 141.7500 m 388.5000 140.2500 L 383.2500 136.5000 L 382.5000 141.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 414.0000 123.0000 m 414.0000 123.7500 L 413.2500 124.5000 L 413.2500 124.5000 L 412.5000 125.2500 L 411.7500 125.2500 L 411.7500 125.2500 L 411.0000 125.2500 L 410.2500 124.5000 L 410.2500 124.5000 L 409.5000 123.7500 L 409.5000 123.0000 L 409.5000 122.2500 L 410.2500 122.2500 L 410.2500 121.5000 L 411.0000 121.5000 L 411.7500 120.7500 L 411.7500 120.7500 L 412.5000 121.5000 L 413.2500 121.5000 L 413.2500 122.2500 L 414.0000 122.2500 L 414.0000 123.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 432.0000 126.0000 m 437.2500 123.0000 L 432.0000 120.0000 L 432.0000 126.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 361.5000 107.2500 m 360.7500 107.2500 L 360.7500 107.2500 L 360.0000 107.2500 L 359.2500 107.2500 L 359.2500 108.0000 L 358.5000 108.0000 L 358.5000 108.7500 L 358.5000 109.5000 L 358.5000 109.5000 L 358.5000 110.2500 L 359.2500 111.0000 L 360.0000 111.0000 L 360.0000 111.0000 L 360.7500 111.0000 L 361.5000 111.0000 L 361.5000 110.2500 L 362.2500 110.2500 L 362.2500 109.5000 L 362.2500 108.7500 L 362.2500 108.0000 L 362.2500 108.0000 L 361.5000 107.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 438.7500 117.0000 m 437.2500 123.0000 L 433.5000 118.5000 L 438.7500 117.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 362.2500 151.5000 m 362.2500 152.2500 L 361.5000 153.0000 L 361.5000 153.0000 L 360.7500 153.0000 L 360.0000 153.0000 L 359.2500 153.0000 L 359.2500 153.0000 L 358.5000 152.2500 L 358.5000 151.5000 L 358.5000 151.5000 L 358.5000 150.7500 L 358.5000 150.0000 L 359.2500 150.0000 L 359.2500 149.2500 L 360.0000 149.2500 L 360.7500 149.2500 L 361.5000 149.2500 L 361.5000 149.2500 L 362.2500 150.0000 L 362.2500 150.7500 L 362.2500 150.7500 L 362.2500 151.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 382.5000 159.7500 m 388.5000 158.2500 L 384.0000 154.5000 L 382.5000 159.7500 L F U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 480.0000 132.7500 m 486.7500 140.2500 L 486.7500 153.7500 L 480.0000 147.0000 L 480.0000 132.7500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 388.5000 147.0000 m 480.0000 147.0000 L 486.7500 153.7500 L 395.2500 153.7500 L 388.5000 147.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 388.5000 132.7500 m 480.0000 132.7500 L 480.0000 147.0000 L 388.5000 147.0000 L 388.5000 132.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 390.7500 142.5000 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sip:bb@example.ed\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 390.7500 132.7500 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k (u\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 444.7500 151.5000 m 451.5000 158.2500 L 451.5000 172.5000 L 444.7500 165.0000 L 444.7500 151.5000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 388.5000 165.0000 m 444.7500 165.0000 L 451.5000 172.5000 L 395.2500 172.5000 L 388.5000 165.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 388.5000 151.5000 m 444.7500 151.5000 L 444.7500 165.0000 L 388.5000 165.0000 L 388.5000 151.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 390.7500 160.5000 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (Bobby\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 390.7500 150.7500 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k (Brown\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 1 j 362.2500 123.0000 m 362.2500 123.7500 L 362.2500 124.5000 L 361.5000 124.5000 L 361.5000 125.2500 L 360.7500 125.2500 L 360.0000 125.2500 L 359.2500 125.2500 L 359.2500 124.5000 L 358.5000 124.5000 L 358.5000 123.7500 L 358.5000 123.0000 L 358.5000 122.2500 L 358.5000 122.2500 L 359.2500 121.5000 L 359.2500 121.5000 L 360.0000 120.7500 L 360.7500 120.7500 L 361.5000 121.5000 L 361.5000 121.5000 L 362.2500 122.2500 L 362.2500 122.2500 L 362.2500 123.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 383.2500 126.0000 m 388.5000 123.0000 L 383.2500 120.0000 L 383.2500 126.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 54.0000 165.7500 m 54.7500 165.7500 L 54.7500 165.0000 L 54.0000 164.2500 L 54.0000 163.5000 L 53.2500 163.5000 L 53.2500 163.5000 L 52.5000 163.5000 L 51.7500 163.5000 L 51.0000 163.5000 L 51.0000 163.5000 L 50.2500 164.2500 L 50.2500 165.0000 L 50.2500 165.7500 L 50.2500 165.7500 L 51.0000 166.5000 L 51.0000 167.2500 L 51.7500 167.2500 L 52.5000 167.2500 L 53.2500 167.2500 L 53.2500 167.2500 L 54.0000 166.5000 L 54.0000 165.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 305.2500 177.0000 m 311.2500 179.2500 L 306.0000 182.2500 L 305.2500 177.0000 L F U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 367.5000 45.7500 m 374.2500 53.2500 L 374.2500 66.7500 L 367.5000 60.0000 L 367.5000 45.7500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 311.2500 60.0000 m 367.5000 60.0000 L 374.2500 66.7500 L 318.0000 66.7500 L 311.2500 60.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 311.2500 45.7500 m 367.5000 45.7500 L 367.5000 60.0000 L 311.2500 60.0000 L 311.2500 45.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 313.5000 50.2500 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (i_common\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 367.5000 18.0000 m 374.2500 24.7500 L 374.2500 39.0000 L 367.5000 32.2500 L 367.5000 18.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 311.2500 18.0000 m 367.5000 18.0000 L 367.5000 32.2500 L 311.2500 32.2500 L 311.2500 18.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 313.5000 22.5000 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (i_id\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 367.5000 3.7500 m 374.2500 10.5000 L 374.2500 24.7500 L 367.5000 18.0000 L 367.5000 3.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 311.2500 3.7500 m 367.5000 3.7500 L 367.5000 18.0000 L 311.2500 18.0000 L 311.2500 3.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 313.5000 8.2500 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (i_hash\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 340.5000 8.2500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k (=1876\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 367.5000 32.2500 m 374.2500 39.0000 L 374.2500 53.2500 L 367.5000 45.7500 L 367.5000 32.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 311.2500 32.2500 m 367.5000 32.2500 L 367.5000 45.7500 L 311.2500 45.7500 L 311.2500 32.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 313.5000 36.7500 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (i_next\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 157.5000 32.2500 m 165.0000 39.0000 L 165.0000 53.2500 L 157.5000 45.7500 L 157.5000 32.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 101.2500 45.7500 m 157.5000 45.7500 L 165.0000 53.2500 L 108.7500 53.2500 L 101.2500 45.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 32.2500 m 157.5000 32.2500 L 157.5000 45.7500 L 101.2500 45.7500 L 101.2500 32.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 36.7500 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (cs_common\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 157.5000 3.7500 m 165.0000 10.5000 L 165.0000 24.7500 L 157.5000 18.0000 L 157.5000 3.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 3.7500 m 157.5000 3.7500 L 157.5000 18.0000 L 101.2500 18.0000 L 101.2500 3.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 8.2500 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (cs_seq\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 133.5000 8.2500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 k ( = 2\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 157.5000 18.0000 m 165.0000 24.7500 L 165.0000 39.0000 L 157.5000 32.2500 L 157.5000 18.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 101.2500 18.0000 m 157.5000 18.0000 L 157.5000 32.2500 L 101.2500 32.2500 L 101.2500 18.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 103.5000 22.5000 0 Tp TP /_Helvetica-Bold 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (cs_next\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 1 j 53.2500 121.5000 m 54.0000 121.5000 L 54.0000 122.2500 L 54.7500 123.0000 L 54.7500 123.7500 L 54.0000 123.7500 L 54.0000 124.5000 L 53.2500 124.5000 L 53.2500 125.2500 L 52.5000 125.2500 L 51.7500 125.2500 L 51.0000 124.5000 L 51.0000 124.5000 L 50.2500 123.7500 L 50.2500 123.0000 L 50.2500 123.0000 L 50.2500 122.2500 L 51.0000 121.5000 L 51.7500 121.5000 L 51.7500 120.7500 L 52.5000 120.7500 L 53.2500 121.5000 L 53.2500 121.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 306.0000 55.5000 m 311.2500 53.2500 L 306.0000 50.2500 L 306.0000 55.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 53.2500 107.2500 m 54.0000 108.0000 L 54.0000 108.0000 L 54.7500 108.7500 L 54.7500 109.5000 L 54.0000 110.2500 L 54.0000 110.2500 L 53.2500 111.0000 L 53.2500 111.0000 L 52.5000 111.0000 L 51.7500 111.0000 L 51.0000 111.0000 L 51.0000 110.2500 L 50.2500 109.5000 L 50.2500 109.5000 L 50.2500 108.7500 L 50.2500 108.0000 L 51.0000 108.0000 L 51.0000 107.2500 L 51.7500 107.2500 L 52.5000 107.2500 L 53.2500 107.2500 L 53.2500 107.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 100.5000 45.0000 m 101.2500 39.0000 L 96.0000 42.0000 L 100.5000 45.0000 L F U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 297.0000 102.0000 m 304.5000 108.7500 L 304.5000 123.0000 L 297.0000 116.2500 L 297.0000 102.0000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 227.2500 116.2500 m 297.0000 116.2500 L 304.5000 123.0000 L 234.0000 123.0000 L 227.2500 116.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 227.2500 102.0000 m 297.0000 102.0000 L 297.0000 116.2500 L 227.2500 116.2500 L 227.2500 102.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 229.5000 106.5000 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (tag=7c6276c1\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 206.2500 102.0000 m 213.0000 108.7500 L 213.0000 123.0000 L 206.2500 116.2500 L 206.2500 102.0000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 178.5000 116.2500 m 206.2500 116.2500 L 213.0000 123.0000 L 186.0000 123.0000 L 178.5000 116.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 178.5000 102.0000 m 206.2500 102.0000 L 206.2500 116.2500 L 178.5000 116.2500 L 178.5000 102.0000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 206.2500 87.7500 m 213.0000 95.2500 L 213.0000 108.7500 L 206.2500 102.0000 L 206.2500 87.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 178.5000 87.7500 m 206.2500 87.7500 L 206.2500 102.0000 L 178.5000 102.0000 L 178.5000 87.7500 L B U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 203.2500 108.7500 m 203.2500 109.5000 L 203.2500 110.2500 L 202.5000 110.2500 L 202.5000 111.0000 L 201.7500 111.0000 L 201.0000 111.0000 L 200.2500 111.0000 L 200.2500 110.2500 L 199.5000 110.2500 L 199.5000 109.5000 L 199.5000 108.7500 L 199.5000 108.7500 L 199.5000 108.0000 L 200.2500 107.2500 L 200.2500 107.2500 L 201.0000 107.2500 L 201.7500 107.2500 L 202.5000 107.2500 L 202.5000 107.2500 L 203.2500 108.0000 L 203.2500 108.7500 L 203.2500 108.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 221.2500 111.7500 m 227.2500 108.7500 L 221.2500 106.5000 L 221.2500 111.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 151.5000 93.0000 m 151.5000 93.0000 L 150.7500 93.0000 L 150.0000 93.0000 L 149.2500 93.0000 L 149.2500 93.7500 L 148.5000 93.7500 L 148.5000 94.5000 L 148.5000 95.2500 L 148.5000 96.0000 L 149.2500 96.0000 L 149.2500 96.7500 L 150.0000 96.7500 L 150.7500 96.7500 L 150.7500 96.7500 L 151.5000 96.7500 L 152.2500 96.7500 L 152.2500 96.0000 L 153.0000 95.2500 L 153.0000 94.5000 L 152.2500 94.5000 L 152.2500 93.7500 L 151.5000 93.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 228.0000 102.7500 m 227.2500 108.7500 L 222.7500 105.0000 L 228.0000 102.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 153.0000 108.7500 m 152.2500 109.5000 L 152.2500 110.2500 L 152.2500 110.2500 L 151.5000 111.0000 L 150.7500 111.0000 L 150.0000 111.0000 L 150.0000 111.0000 L 149.2500 110.2500 L 149.2500 110.2500 L 148.5000 109.5000 L 148.5000 108.7500 L 148.5000 108.7500 L 149.2500 108.0000 L 149.2500 107.2500 L 150.0000 107.2500 L 150.0000 107.2500 L 150.7500 107.2500 L 151.5000 107.2500 L 152.2500 107.2500 L 152.2500 108.0000 L 152.2500 108.7500 L 153.0000 108.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 173.2500 111.7500 m 178.5000 108.7500 L 173.2500 106.5000 L 173.2500 111.7500 L F U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 283.5000 119.2500 m 290.2500 126.0000 L 290.2500 140.2500 L 283.5000 132.7500 L 283.5000 119.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 178.5000 132.7500 m 283.5000 132.7500 L 290.2500 140.2500 L 186.0000 140.2500 L 178.5000 132.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 178.5000 119.2500 m 283.5000 119.2500 L 283.5000 132.7500 L 178.5000 132.7500 L 178.5000 119.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 180.7500 123.7500 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sip:joe@example.com\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 227.2500 137.2500 m 234.0000 144.0000 L 234.0000 158.2500 L 227.2500 151.5000 L 227.2500 137.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 178.5000 151.5000 m 227.2500 151.5000 L 234.0000 158.2500 L 186.0000 158.2500 L 178.5000 151.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 178.5000 137.2500 m 227.2500 137.2500 L 227.2500 151.5000 L 178.5000 151.5000 L 178.5000 137.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 180.7500 141.7500 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (Joe User\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 530.2500 18.0000 m 537.0000 24.7500 L 537.0000 39.0000 L 530.2500 32.2500 L 530.2500 18.0000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 390.0000 32.2500 m 530.2500 32.2500 L 537.0000 39.0000 L 396.7500 39.0000 L 390.0000 32.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 390.0000 18.0000 m 530.2500 18.0000 L 530.2500 32.2500 L 390.0000 32.2500 L 390.0000 18.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 392.2500 22.5000 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (4c4e911b@pc104.example.edu\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 1 j 362.2500 24.7500 m 362.2500 25.5000 L 362.2500 26.2500 L 361.5000 26.2500 L 361.5000 27.0000 L 360.7500 27.0000 L 360.0000 27.0000 L 359.2500 27.0000 L 359.2500 26.2500 L 358.5000 26.2500 L 358.5000 25.5000 L 358.5000 24.7500 L 358.5000 24.0000 L 358.5000 24.0000 L 359.2500 23.2500 L 359.2500 23.2500 L 360.0000 22.5000 L 360.7500 22.5000 L 361.5000 23.2500 L 361.5000 23.2500 L 362.2500 24.0000 L 362.2500 24.0000 L 362.2500 24.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 384.0000 27.7500 m 390.0000 24.7500 L 384.0000 22.5000 L 384.0000 27.7500 L F U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 480.0000 262.5000 m 486.7500 270.0000 L 486.7500 283.5000 L 480.0000 276.7500 L 480.0000 262.5000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 388.5000 276.7500 m 480.0000 276.7500 L 486.7500 283.5000 L 395.2500 283.5000 L 388.5000 276.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 388.5000 262.5000 m 480.0000 262.5000 L 480.0000 276.7500 L 388.5000 276.7500 L 388.5000 262.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 390.7500 267.0000 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (pc104.example.edu\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 1 j 451.5000 279.7500 m 458.2500 286.5000 L 458.2500 300.7500 L 451.5000 293.2500 L 451.5000 279.7500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 388.5000 293.2500 m 451.5000 293.2500 L 458.2500 300.7500 L 395.2500 300.7500 L 388.5000 293.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 388.5000 279.7500 m 451.5000 279.7500 L 451.5000 293.2500 L 388.5000 293.2500 L 388.5000 279.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 390.7500 284.2500 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (SIP/2.0/UDP\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 1 j 362.2500 261.7500 m 362.2500 262.5000 L 362.2500 263.2500 L 362.2500 263.2500 L 361.5000 264.0000 L 361.5000 264.7500 L 360.7500 264.7500 L 360.0000 264.7500 L 360.0000 264.7500 L 359.2500 264.0000 L 358.5000 264.0000 L 358.5000 263.2500 L 358.5000 262.5000 L 358.5000 262.5000 L 358.5000 261.7500 L 359.2500 261.0000 L 359.2500 261.0000 L 360.0000 261.0000 L 360.7500 260.2500 L 360.7500 261.0000 L 361.5000 261.0000 L 362.2500 261.7500 L 362.2500 261.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 384.0000 255.7500 m 388.5000 251.2500 L 382.5000 251.2500 L 384.0000 255.7500 L F U %%PageTrailer gsave annotatepage grestore showpage %%Trailer Adobe_Illustrator_AI5 /terminate get exec Adobe_pattern_AI5 /terminate get exec Adobe_blend_AI5 /terminate get exec Adobe_ColorImage_AI6 /terminate get exec Adobe_typography_AI5 /terminate get exec Adobe_screens_AI5 /terminate get exec Adobe_level2_AI5 /terminate get exec %%EOF II*~(@$$77II[[mm33MMff33JJ``ww33JJ``ww33GG\\pp""11@@OO^^nn}}""++33<>FFMMUUll""11@@OO^^nn}}33GG\\pp33JJ``ww33MMff33PPmm33MMff33JJ``ww33MMff((77EETTbbqq--DD[[qq::WWuu::WWuu::WWuu$$77II[[mm::WWuu""DDff""DDff))RRzz""DDff::WWuu33MMff""++33<[PץhЩ(p̪<  sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/images/sip-parser3.gif000066400000000000000000000343261223300710500244610ustar00rootroot00000000000000GIF87a , @޼@E扦ʶ L- Ģ ț JԪ%-=[Nۢy\7\M (8HXhȕW磈Gw8'9xdI7g:Zjj*9@JC+ ,f J\l| x!̰,=M]-ݔY1 ;9~ Gy7myW2O߉;<H@ :Yت ҂;z|Q#VʕCH%c*BN4Uek8.[6fwAڛsY:uצu~8/kr=sga= s :7Vt`/f)[BC^2LuBU`ݴтTFMQQ!D!@qG|ay%F3j؆ST6/Z2IRU.8)ʣQGS27^jC% NIn<Ʉ!#.i(ηP@YL|ɢRZBy>4iBr#L8` V)E4T#h-wVV0,׮!9UwZ'!:ķ% ^׏݋o~pnnEc\D9hak&ioJpkk,>~n뱤&2BR0h*ehep5Ϛ73ښDfq]2 u/tni*u<'I5\,]vPs)X-P<)| ,휟Ҷv;_"yG ٦6R7ٚO-8##f]&qEKؐ>n?jof[JU֏б|C<{6l5]nee3䂬l{sr'y3N阤|g=Tp򼷪a/7 o'p9 ,pԸު]#&.Ls^9cztnwUE4ix*!N&;ؤml"B(8Gu~Pи74;=: Q"'D=-iܫP"MeI̘&RM4(DH%-$EmA}9 S-"hL}-qN2VH~cdǦd!54s9VVڸ\yi7iU#%i(N hiə1)s0%22&1rrT_ZwL/qHۮ ;qoNI֡Œ8R VA=#*:qT9DJ9¬TeڧIUDmCWRѪA>TXzৈ[׼z)=qؿFT$|*b \ΉxQd/kرPx]1 ں2 HhM>6W7ؚ-8c,k6 r>h*w؁l'i]BwBi* f m,U N ϓm V{ūUdgd9|. O񮁭Bx"wׄVa[ n`lbG.Forx%}ySqQLHyRz52||,CsǧLZvrqXu:dS 1|+},75Tp6R8mSE/9RvPWAhtd:H Xh}X hrxw?qx&r +CfpVKV1m]ehk3;g{jkŅ6Agt:s>u,Df(HGUpulr귉U(X+0wt{dgJQ(Prw7E7WVhW5Y2EAظtp؅RQnCw60+`43NkVd|륏(MT~ȑ"kg'?e"hc.F?EcL=uB]*hfw{(DfizdK|uiL Qwow =ytxAyWvߘG8q=8@pS4!VP!ӈsWtrd]9hNZWĕtL o}g[td!e䨅T^v^HqO")V@D?zV)Eh]x9WF#R޹ѐŅ'J]uKf[D=7OTJ0ȧH$膐vI3;}ٙE8T6؀2G #7 *5b<3)V-U 6PIz$B@acsn$BSXT~]á4cC2H ($ɘ'hB7`;VS*?zR&[I:i$bl5FsjyBlJ7:^'|F5tGUŤz*8/yƨ5\: c:bCCk䡝J-=8W')ӪsbG$VSW<X)G_erwl7wSJɟcmWACZ_x%ƫ7#8Zaecv4ɖa_x2F 2jk8z c NְdwȪi foɥkה}?kX l'kاWq},y? jy|E{ I\pRi㓙JkQ CWYIag8-ze{jf_> Hkl'趼qkzR~FXRY1JT $fW5I fl7xgj%(6ȶ#ZX32;g뷨s[,_[{%ڢ]@ n'kW-IKK:"ʸ~[QXa[:E ~׻KA':kfh؆ T'V@B;X˾#&7  UyۿWvgdku35 !K7eG <11NEɀ=S$9){gcCk4ئ6p::-Y-+IHȋ(,8-,%%4UL4QeՆHSz6i=]`G\ȞuX{ Z$Z^stQLk!8#zZYrLvg[©Enթ | t"jK11kmIv|W#ld7Z:(ZwxA\̽Ќxj|JJi;ٛ:JflU׼C9ljI}7?ywIsSL,Q`̜t =dw[˖r$4h>I+&ks_bX|GYOq \umMκ{Jl Ѡzy˗H橨AM(s\Y.!%MRk͞YĽayM3Ģ'}pbz ؗI,y=vךcWO4*ӻeӋ*OpԁeS AjDIpGdzSȸ q}Kfm㞟\Md whgxSE)9;Ķ$0#(J;9Iadh֠?S=J ,WYvcwv);̰l³'geme}vU:I =fN^1.Î6+7Z6[ %j^dl,ˡWXF},?` +sʏÔnmgQ)kua;/gH}݇t2Bz||dX A59z})Asqhn?e=5>5X`/UR=7H|M2^x?b37FAӠ/ߍN$ua 3"PT]N1eֆ󤼀=*h0r7DZ^g~9Yㅐiܙ \'NgykIXKvC SI ')) X>ACEG +)1OR]U[Xbd%cw`yZu{{y}#d, îl;]ӉG`U߁2j8`A7oǛm62,fm:llM7v:ʌ7&ŕfl -ZG:Q3L<4`QEI%UB A#ʤ 7~:K(j( ϓ>šyI\&Ԫ[:n]w8+.~{7`7_byU60a5,*ɈCBxO͜A]r^GnzUi6_܇!#f^S5@XQ GPcC=@LTۢ}IU0Q4Ts8".\!~sǖdsNc K:Q數)|ģZb"xxZQ;HO 90hjSL\c.Fa2I4, #08͞2Ɠ2H$}4ŷЂi 4e&)SlUEdD@}44>IaSr2JTMRC~ &vD{9֨EÈYhe;?tsd(X , LN'EH1xJ2F/f}^VErv>}X^S_7\`(ч K6X5]NYxfA$vFc$a~SHyYi*uIwT@5쑟.5UElxRWa[Te+t{9 /L[foJi \3XFf)ϡ\C3bVt詏k<[]i%:Cb7UYgVO\K驯@{683]O_o?4DE߀?Ɇ~nסN!rMlӦ v*9CӰOY%4!o1œ'tBVn\ Ǩ␇롼2L\kVbe?teB)ORxzJDdb+zeE12 Sb4ˡ,itB9eo:ڑIB04$gD)CIԕQC‹dǺIn2t\K`~_Pkc9ɍw )UeFYΒLi#'Q2c.yZa/GeDȌ2 &b2մ5G41rcs&%}4|#@$ |#$>tB%+tEOj=BT*un+ӟ?s'.%ЭnxZrY*E'ةNg+F&R^AwvoQo >N{[)1%}ԓpVIat::vL-kҟ3.QC]*KԂ(N>PBwsގD,nA~Z.8 8_ BSl-]c J-+܄EBFtAGZsT5'.YRI!P3'O K!6Jt"r@O2+HӔ5 )s45k0 z5KAQ6#B6K<KSN0-m0T#EQ1U3<3Tf*b81۔rؤ  JIJ)PQLXD.D  .<?t\.\ ͵ A@Uq45`4[<9XO,oFN6 \>3^UJ1QPCSdL5F m^U-bLAQb3^ `/L;_5+vvjq[-151`SY3a V Ve Uц1mtdbPIܤOH?RKuO9ChvM,蕺nn3]$BVCMʊeĮ1Cc65 ghKv0._ǶW:VrZh|V0&gDJ@9oWfQcGrGm6d`q#MrPÜrFU)t^lwSt[UC@Sv{IukzlM*.\PU=7WkȄ#u nM'KA z;!Lp $ŴZ>1Lx(2"HX6 kKt~hCGLaVc~o1TeMYM R˒w_9]JƍpDVah)7d#pj '*p9]c ZM@ ;x{9Ng`Tu}a7c7Ȯ),_TI!UU@HS`WK gtWUY(9XxE1bc8REv 8j٠pfsMcj⑋ZVS:ͷ-ėVHYդm:s;ZcrbnNy֊Z0w=V.%LpfZH2o*: e ׆#`?~zM c̯90p'7ޗbvNQk7zP~P{Ѫuc29 c(ກH1U=G8ȚO4q/8EAsU"XDg,R6/o䴙ruqœUi'Tli#6L9 H50#{U: J#qoWihx!{AYoF!-DT-!N4{p~*v9;h7β]t簗7{mڛ7_wClj ӜYy<}yٺ$ ^sƏf!N+w)iLSGDF7#kyds-Evy6S-{o|Ϗ9\jGĮ]]5jϙϕqh_GuNwѷC+~`|e<UizF\fjyS}üH;ϑ2cȟK|۸gڶїwo4{\ۘ0 /D8\%hm3۷W E2cΩgkƭQW30q:3қƆ _ۚ"ѿ= W}Co,wB)~*9]|=Y{0~e~xi?tc39Y0\[~KjFNݽAp Y?Bzi|{}}=꥾>,NI*V=i+pkmjbW/[M5;܏K̬/^߽wйs,1S:UWku~]佲п,=Y԰ia^%z68ukitC)繬'(}<6s%X?O@?tMv)iIݙB+t>l2sxm_V%ѕ+_ >Ri/N p2#Y4)R#3@C }Vu)8$!)bc=/5d8\I+mb.cu㥈bj]/ߒ#` P!48Hu9D'FO"gJ8m*2\CNh-( RB'ͲPÄ4G i%X`c:ꜯ>F^Y)@ՖH&I_Tz"J;"?2zm'讼gZ-NGǒJ]kF $6Q{оK&bv.'HfpC:Kw670\Pf̜v.LZ%wʳv|1Q|$p& &nT(q)Rf$Q"OV_eBrp94Ѩ:Ihy޽dE-Yg40P8z5 n lwvqYZߍ,7bvz ^:KhrIw+֚ wޔ>Q'C[^h5qzޙyf d[_ 8X6.5{2ﱯSRy >?5fGE|7ڥ}^zEeAY׻ l ux *Tlv:, %+u =&PTgX̶$2\9T1F)fP*:LY2r4@]U>0f*6—Pf/a 9zgzP(@0S"g3C^#& oDK$A1Ғ8_#H= xJ4]{JH26Ôd'iAR*s0ay^._Sq3{2׶(R2e6qt<Xܭ s5t[23{kg0Cr|_')xfpw+n'8ӃsG- QZr0*B.ĝl$dCg&~'UMJb::}dڪLbӠ\K!Ӎr\$X8u$9|MG%$Z'PQUҊՙE=N$98#> k,q!7 úr3`:WLB'%J"75t_ b05l@SbUC2TjJ#q9904LZڶkqQ*ĦU4mr\ufW5i< bI@\E{}n{=GsZyRNmSb^A H3~g\WHg^iXiL(CLgM,|,V# /&L2ᚢu{s X|ixy-g6e|}G챏E\3VL JqLxYf&gdB좯19FSϔ4ӹ \3~];ж-|q[Dw~48Zf,n#Mo3WoXzivuҜ>5RmMR;؎6us_59}lvɱe3[ܰTmj.mתv`E1CN3!~7mC'7ow} -QO m3Vg q8O cʌ+8{ )rT7SvLc)ٝ5W#..ow`Tyn3JRhrʿ$7S;k j1]դm.B-7È^GEvtoNǷ[IJz-Tytm{-j>yO=/-_So05Kw碏o10.WWK"k˜4;a5nG<"P{ʺ>-:uBGӔ6ͥTx]+y/;<~;|*^)Wt[ar5V_z\kњ^ ȹ TeQsHN bZݞ C^Š`̇A ^u|Z y DIՍؘЍ!uV!U`$a ޡ!򋿕!9^""n"F$`=⻁Tb q؛6bh9`DYu@Ej\q`]ɣXU{] mH50a%hJa0^'Nx-,UPXPl /bЇ[L`c.U8Ř&K!#a`BS_ =SU8죆6O%\$~!R"C͞+ J"";߼`uFLVFbWQGRC!jU$5 'zQ*H^M$dN"%-!4E6OMES"]_@X 5oabSۯAeTiU"" 4PWZa._2$%.Uky/dS:aBद]dcM&IOZ!6ipfy;sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/images/sip-parser4.eps000066400000000000000000004552671223300710500245170ustar00rootroot00000000000000""7%!PS-Adobe-3.0 EPSF-3.0 %%Creator: ImageMark Software Labs %%For: () () %%Title: G:\Docs\Sofia\Graphics\sip-parser4.eps %%CreationDate: () () %%BoundingBox: 0 0 449 182 %%DocumentProcessColors: Black %%ColorUsage:Color %%DocumentFonts: Helvetica %%+Helvetica-Bold %%+Helvetica-Oblique %%+Helvetica-BoldOblique %%+Times-Roman %%+Times-Bold %%+Times-Italic %%+Times-BoldItalic %%+Courier %%+Courier-Bold %%+Courier-Oblique %%+Courier-BoldOblique %%+Symbol %%DocumentSuppliedResources: procset Adobe_level2_AI5 1.2 0 %%+ procset Adobe_screens_AI5 1.0 0 %%+ procset Adobe_typography_AI5 1.0 0 %%+ procset Adobe_ColorImage_AI6 1.1 0 %%+ procset Adobe_blend_AI5 1.0 0 %%+ procset Adobe_pattern_AI5 1.0 0 %%+ procset Adobe_Illustrator_AI5 1.0 0 %AI5_FileFormat 3.0 %AI3_ColorUsage: Color %AI3_TemplateBox: 0 0 449 182 %AI3_TileBox: 0 0 449 182 %AI3_DocumentPreview: None %%Template: %%PageOrigin:0.0000 0.0000 %AI7_GridSettings: 72 8 72 8 1 0 0.8 0.8 0.8 0.9 0.9 0.9 %%EndComments %%BeginProlog %%BeginResource: procset Adobe_level2_AI5 1.2 0 %%Title: (Adobe Illustrator (R) Version 5.0 Level 2 Emulation) %%Version: 1.2 0 %%CreationDate: (04/10/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /Adobe_level2_AI5 25 dict dup begin put /packedarray where not { userdict begin /packedarray { array astore readonly } bind def /setpacking /pop load def /currentpacking false def end 0 } if pop userdict /defaultpacking currentpacking put true setpacking /initialize { Adobe_level2_AI5 begin } bind def /terminate { currentdict Adobe_level2_AI5 eq { end } if } bind def mark /setcustomcolor where not { /findcmykcustomcolor { 0 6 packedarray } bind def /findrgbcustomcolor { 1 5 packedarray } bind def /setcustomcolor { exch aload pop 0 eq { pop 4 { 4 index mul 4 1 roll } repeat 5 -1 roll pop setcmykcolor } { pop 3 { 1 exch sub 3 index mul 1 exch sub 3 1 roll } repeat 4 -1 roll pop setrgbcolor } ifelse } def } if /gt38? mark {version cvr cvx exec} stopped {cleartomark true} {38 gt exch pop} ifelse def userdict /deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt put userdict /level2? systemdict /languagelevel known dup { pop systemdict /languagelevel get 2 ge } if put /level2ScreenFreq { begin 60 HalftoneType 1 eq { pop Frequency } if HalftoneType 2 eq { pop GrayFrequency } if HalftoneType 5 eq { pop Default level2ScreenFreq } if end } bind def userdict /currentScreenFreq level2? {currenthalftone level2ScreenFreq} {currentscreen pop pop} ifelse put level2? not { /setcmykcolor where not { /setcmykcolor { exch .11 mul add exch .59 mul add exch .3 mul add 1 exch sub setgray } def } if /currentcmykcolor where not { /currentcmykcolor { 0 0 0 1 currentgray sub } def } if /setoverprint where not { /setoverprint /pop load def } if /selectfont where not { /selectfont { exch findfont exch dup type /arraytype eq { makefont } { scalefont } ifelse setfont } bind def } if /cshow where not { /cshow { [ 0 0 5 -1 roll aload pop ] cvx bind forall } bind def } if } if cleartomark /anyColor? { add add add 0 ne } bind def /testColor { gsave setcmykcolor currentcmykcolor grestore } bind def /testCMYKColorThrough { testColor anyColor? } bind def userdict /composite? level2? { gsave 1 1 1 1 setcmykcolor currentcmykcolor grestore add add add 4 eq } { 1 0 0 0 testCMYKColorThrough 0 1 0 0 testCMYKColorThrough 0 0 1 0 testCMYKColorThrough 0 0 0 1 testCMYKColorThrough and and and } ifelse put composite? not { userdict begin gsave /cyan? 1 0 0 0 testCMYKColorThrough def /magenta? 0 1 0 0 testCMYKColorThrough def /yellow? 0 0 1 0 testCMYKColorThrough def /black? 0 0 0 1 testCMYKColorThrough def grestore /isCMYKSep? cyan? magenta? yellow? black? or or or def /customColor? isCMYKSep? not def end } if end defaultpacking setpacking %%EndResource %%BeginResource: procset Adobe_typography_AI5 1.0 1 %%Title: (Typography Operators) %%Version: 1.0 %%CreationDate:(03/26/93) () %%Copyright: ((C) 1987-1993 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_typography_AI5 54 dict dup begin put /initialize { begin begin Adobe_typography_AI5 begin Adobe_typography_AI5 { dup xcheck { bind } if pop pop } forall end end end Adobe_typography_AI5 begin } def /terminate { currentdict Adobe_typography_AI5 eq { end } if } def /modifyEncoding { /_tempEncode exch ddef /_pntr 0 ddef { counttomark -1 roll dup type dup /marktype eq { pop pop exit } { /nametype eq { _tempEncode /_pntr dup load dup 3 1 roll 1 add ddef 3 -1 roll put } { /_pntr exch ddef } ifelse } ifelse } loop _tempEncode } def /TE { StandardEncoding 256 array copy modifyEncoding /_nativeEncoding exch def } def % /TZ { dup type /arraytype eq { /_wv exch def } { /_wv 0 def } ifelse /_useNativeEncoding exch def pop pop findfont _wv type /arraytype eq { _wv makeblendedfont } if dup length 2 add dict begin mark exch { 1 index /FID ne { def } if cleartomark mark } forall pop /FontName exch def counttomark 0 eq { 1 _useNativeEncoding eq { /Encoding _nativeEncoding def } if cleartomark } { /Encoding load 256 array copy modifyEncoding /Encoding exch def } ifelse FontName currentdict end definefont pop } def /tr { _ax _ay 3 2 roll } def /trj { _cx _cy _sp _ax _ay 6 5 roll } def /a0 { /Tx { dup currentpoint 3 2 roll tr _psf newpath moveto tr _ctm _pss } ddef /Tj { dup currentpoint 3 2 roll trj _pjsf newpath moveto trj _ctm _pjss } ddef } def /a1 { /Tx { dup currentpoint 4 2 roll gsave dup currentpoint 3 2 roll tr _psf newpath moveto tr _ctm _pss grestore 3 1 roll moveto tr sp } ddef /Tj { dup currentpoint 4 2 roll gsave dup currentpoint 3 2 roll trj _pjsf newpath moveto trj _ctm _pjss grestore 3 1 roll moveto tr jsp } ddef } def /e0 { /Tx { tr _psf } ddef /Tj { trj _pjsf } ddef } def /e1 { /Tx { dup currentpoint 4 2 roll gsave tr _psf grestore 3 1 roll moveto tr sp } ddef /Tj { dup currentpoint 4 2 roll gsave trj _pjsf grestore 3 1 roll moveto tr jsp } ddef } def /i0 { /Tx { tr sp } ddef /Tj { trj jsp } ddef } def /i1 { W N } def /o0 { /Tx { tr sw rmoveto } ddef /Tj { trj swj rmoveto } ddef } def /r0 { /Tx { tr _ctm _pss } ddef /Tj { trj _ctm _pjss } ddef } def /r1 { /Tx { dup currentpoint 4 2 roll currentpoint gsave newpath moveto tr _ctm _pss grestore 3 1 roll moveto tr sp } ddef /Tj { dup currentpoint 4 2 roll currentpoint gsave newpath moveto trj _ctm _pjss grestore 3 1 roll moveto tr jsp } ddef } def /To { pop _ctm currentmatrix pop } def /TO { iTe _ctm setmatrix newpath } def /Tp { pop _tm astore pop _ctm setmatrix _tDict begin /W { } def /h { } def } def /TP { end iTm 0 0 moveto } def /Tr { _render 3 le { currentpoint newpath moveto } if dup 8 eq { pop 0 } { dup 9 eq { pop 1 } if } ifelse dup /_render exch ddef _renderStart exch get load exec } def /iTm { _ctm setmatrix _tm concat 0 _rise translate _hs 1 scale } def /Tm { _tm astore pop iTm 0 0 moveto } def /Td { _mtx translate _tm _tm concatmatrix pop iTm 0 0 moveto } def /iTe { _render -1 eq { } { _renderEnd _render get dup null ne { load exec } { pop } ifelse } ifelse /_render -1 ddef } def /Ta { pop } def /Tf { dup 1000 div /_fScl exch ddef % selectfont } def /Tl { pop 0 exch _leading astore pop } def /Tt { pop } def /TW { 3 npop } def /Tw { /_cx exch ddef } def /TC { 3 npop } def /Tc { /_ax exch ddef } def /Ts { /_rise exch ddef currentpoint iTm moveto } def /Ti { 3 npop } def /Tz { 100 div /_hs exch ddef iTm } def /TA { pop } def /Tq { pop } def /Th { pop pop pop pop pop } def /TX { pop } def /Tk { exch pop _fScl mul neg 0 rmoveto } def /TK { 2 npop } def /T* { _leading aload pop neg Td } def /T*- { _leading aload pop Td } def /T- { _hyphen Tx } def /T+ { } def /TR { _ctm currentmatrix pop _tm astore pop iTm 0 0 moveto } def /TS { currentfont 3 1 roll /_Symbol_ _fScl 1000 mul selectfont 0 eq { Tx } { Tj } ifelse setfont } def /Xb { pop pop } def /Tb /Xb load def /Xe { pop pop pop pop } def /Te /Xe load def /XB { } def /TB /XB load def currentdict readonly pop end setpacking %%EndResource %%BeginResource: procset Adobe_screens_AI5 1.2 0 %%Title: (Adobe Illustrator (R) Version 5.0 Custom Halftone Screens ProcSet) %%Version: 1.2 0 %%CreationDate: (03/24/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking systemdict begin userdict /Adobe_screens_AI5 15 dict dup begin put /initialize { Adobe_screens_AI5 begin /screenid deviceDPI 600 gt composite? not or { -1 } { deviceDPI currentScreenFreq dup dup 60 ge exch 150 le and deviceDPI 300 le and { pop 60 } if div 1.41421 div 0.5 add cvi } ifelse def 2 screenid eq { /customsize 16 def /customdata /customdata2 def setcustomscreen } if 3 screenid eq { /customsize 24 def /customdata /customdata3 def setcustomscreen } if 4 screenid eq { /customsize 16 def /customdata /customdata4 def setcustomscreen } if 5 screenid eq { /customsize 20 def /customdata /customdata5 def setcustomscreen } if 6 screenid eq { /customsize 24 def /customdata /customdata6 def setcustomscreen } if 7 screenid eq { /customsize 28 def /customdata /customdata7 def setcustomscreen } if 8 screenid eq { /customsize 16 def /customdata /customdata8 def setcustomscreen } if } def /terminate { currentdict Adobe_screens_AI5 eq { end } if } def /setcustomscreen { deviceDPI customsize div 0 { 1 add 2 div customsize mul cvi exch 1 add 2 div customsize mul cvi exch customsize mul add customdata load exch get 256 div } setscreen } def /customdata2 28 28 mul string def currentfile customdata2 readhexstring 4180E8694988E2634382EA6B4B8AE061A01939C8A81737C2A21B3BCAAA1636C0 F8795998F6775796FA7B5B9AF57656952ED8B80727D6B60F2FDABA0626D5B50E 4E8DE6674786EE6F4F8EE5664685ED6EAD1434C6A61F3FCEAE1232C5A51E3ECD F3745493FE7F5F9EF1725291FD7E5E9D24D3B30C2CDEBE0222D1B10A2ADDBD04 4483EB6C4C8BE1624281E96A4A89E364A31C3CCBAB1535C1A11A3AC9A91838C3 FB7C5C9BF4755594F97A5A99F778589730DBBB0525D4B40D2DD9B90828D7B710 508FE4654584EC6D4D8CE7684887EF70AF1131C4A41D3DCCAC1333C7A72040CF F0715190FC7D5D9CF2735392FF80609F21D0B00929DCBC0323D2B20B2BDFBF01 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata3 28 28 mul string def currentfile customdata3 readhexstring 011DC7F5E73D0421CBF3E43A021EC8F6E83E0522CCF2E43A2B648BC4A0762F68 8AC39E732C658CC5A177306989C29D72D5B6521A6192D9B55219608FD6B6531B 6193DAB451185F8FFCEE440C28D2FCED430B27D1FDEF450C29D3FBEC420A26D0 BEA77D366F83BCA77C356E87BFA87E377082BBA67B346D86145B99E0AE4A1259 98DFB14E155C9AE1AD4A115897DEB04D0623CDF4E63C0420CAF8EA400723CDF4 E53B031FC9F7E93F316988C19F752E678EC6A378326A88C09F742D668DC6A278 DBB350175E91D8B8551C6395DCB24F165D90D7B7541C6294FAEC420925CFFFF1 470E2BD5F9EB410824CEFEF0460D2AD4BAA57A336C85BEAA80397180B9A47933 6B84BDA97F387181105797DDAF4C145A9CE3AB480F5696DDAE4B13599BE2AC49 021EC8F6E83E0522CCF2E43A011DC7F5E73D0421CBF3E43A2C658CC5A1773069 89C29D722B648BC4A0762F688AC39E73D6B6531B6193DAB451185F8FD5B6521A 6192D9B55219608FFDEF450C29D3FBEC420A26D0FCEE440C28D2FCED430B27D1 BFA87E377082BBA67B346D86BEA77D366F83BCA77C356E87155C9AE1AD4A1158 97DEB04D145B99E0AE4A125998DFB14E0723CDF4E53B031FC9F7E93F0623CDF4 E63C0420CAF8EA40326A88C09F742D668DC6A278316988C19F752E678EC6A378 DCB24F165D90D7B7541C6294DBB350175E91D8B8551C6395F9EB410824CEFEF0 460D2AD4FAEC420925CFFFF1470E2BD5B9A479336B84BDA97F387181BAA57A33 6C85BEAA803971800F5696DDAE4B13599BE2AC49105797DDAF4C145A9CE3AB48 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata4 28 28 mul string def currentfile customdata4 readhexstring 1139B8E0FAD2531B133BBAE2F8D05119417180A6AE9A7B4B437382A5AD987949 C08867272F6F92CAC28A66262E6E90C8E8DE5F070F37B6F2EADD5E060E36B5F0 FED6571F173FBEE6FDD5561E163EBDE5AB9E7F4F477786A1A99D7E4E467685A3 2C6C96CEC68E62222A6A95CDC58D64240C34B3F6EED95A020A32B1F5EDDB5C04 143CBBE3F9D1521A123AB9E1FBD3541C447483A4AC997A4A427281A7AF9B7C4C C38B65252D6D91C9C1896828307093CBEBDC5D050D35B4F1E9DF60081038B7F3 FCD4551D153DBCE4FFD758201840BFE7A89C7D4D457584A2AA9F8050487887A0 296994CCC48C63232B6B97CFC78F61210931B0F4ECDA5B030B33B2F7EFD85901 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata5 28 28 mul string def currentfile customdata5 readhexstring 010B34C3EBFCF7CE3F16020C35C4EDFBF6CD3E15102552A4D6EADDB5632B1126 54A5D5EADCB3622A3958768499C19E8C7C5E3A59778498C19D8B7B5DC8A99370 47334C7587AFC9AA936F46324B7485AEF1E5BC6B1E0A2351A3D8F2E4BC6A1E09 2351A2D7FFF9D14219050F38C6EFFEF9D04118040E37C6EFE8E0B7662D142856 A8D3E7DFB7652D132856A7D4BF9C8E7F603D5B7A8195BE9A8E7E603C5B798297 314A7389B2CCAD906D442F497289B1CBAC926E4508214FA1DBF4E2B9671B0720 4EA0DAF4E3BA691C030D36C5EDFBF6CD3F16010C34C3ECFDF8CF4017122654A6 D4E9DDB4622A112553A5D6EBDEB5642C3B59788397C09C8B7C5D3A58778599C2 9E8C7D5FCAAB926E46314B7486AFC8AA947048334D7587B0F2E4BB691D082250 A1D8F1E6BD6B1F0A2452A3D9FDF8CF4118030E36C5EEFFFAD1421A050F38C7F0 E6DFB6642C132755A7D3E8E1B8662E152957A8D2BE9A8D7E5F3B5A798296BF9B 8F80613D5C7B80952F487188B1CAAC916D443049728AB3CCAE906C43061F4D9F DAF3E2BA681C07214FA0DBF5E1B8671A00000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata6 28 28 mul string def currentfile customdata6 readhexstring 081A44B6E0F2FDECC150250C091B45B6E1F3FCEBC04F240C1D336199C7D8DCD3 A56C37221E33619AC8D7DBD2A46B36214864798091AEB1958C7E694C49657A81 90ADB0948B7D684BB99D8475593C405C7888A1BEBA9E8574583B3F5B7888A0BD E4CBAA712E1215326098CFE8E4CCA9712D1114315F97CEE7F5F1C6552B040719 43B5DFFAF6F0C6542A03061842B4DEF9FFEDC352270E0B1C47B8E3F4FEECC251 260D0A1C46B7E2F4DAD5A76E39232035639CCAD5D9D4A66D38231F34629BC9D6 AF938E806A4E4A677C838FABAE928D7F694D4A667B828FAC3E5A778AA3BFBC9F 8772563A3D597689A2BEBB9F8673573A14305E97D1EAE6CDA76F2B0F132F5D96 D0E9E5CDA8702C10051742B3DDFCF8EEC4522801041641B2DDFBF7EFC5532902 091B45B6E1F3FCEBC04F240C081A44B6E0F2FDECC150250C1E33619AC8D7DBD2 A46B36211D336199C7D8DCD3A56C372249657A8190ADB0948B7D684B48647980 91AEB1958C7E694CBA9E8574583B3F5B7888A0BDB99D8475593C405C7888A1BE E4CCA9712D1114315F97CEE7E4CBAA712E1215326098CFE8F6F0C6542A030618 42B4DEF9F5F1C6552B04071943B5DFFAFEECC251260D0A1C46B7E2F4FFEDC352 270E0B1C47B8E3F4D9D4A66D38231F34629BC9D6DAD5A76E39232035639CCAD5 AE928D7F694D4A667B828FACAF938E806A4E4A677C838FAB3D597689A2BEBB9F 8673573A3E5A778AA3BFBC9F8772563A132F5D96D0E9E5CDA8702C1014305E97 D1EAE6CDA76F2B0F041641B2DDFBF7EFC5532902051742B3DDFCF8EEC4522801 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop /customdata7 28 28 mul string def currentfile customdata7 readhexstring 01061B44B7E1F5FEFBE6BD4A210C01071B45B8E1F6FDFBE6BC4A200B09132A54 A7D1EAF5EED9B05D331609142B55A8D2EAF4EED9AF5C32161D2D3D6993C1CBE0 CEC59B7140301E2E3D6A93C0CADFCDC49A713F3047576C7B828DA2B6A48F867E 6F5A48576C7C828CA1B6A38F867E6E59BAAA958A78634E4451667A8498ADBAAB 968977624E4350657A8398ADE3D4C99F7539251A273C6892C2D7E4D4C89E7539 241A273B6891C1D6F8F2DDB460371005122A53A7D0ECF9F2DDB360360F051229 53A6D0EBFFFDE8BE4C220D03081D46B9E3F7FFFCE7BD4B210D02071C46B8E2F7 F3F0DBB15E34180B152C56A9D3E8F3EFDAB05D34170A142C55A9D2E9DFCCC69C 7341321F2F3F6B94BFC9DECCC59C7241311F2E3E6A94BFCAB5A38E8780705B49 596D7D808BA0B4A28D877F6F5B48586D7C818BA043506479859AAFBCAC978876 614C424F64798499AEBBAB968977624D19263B6791C3D8E5D6C79D7337231825 3A6690C3D7E5D5C79E74382304112952A5CFEDFAF0DBB25E350E03102851A5CE ECF9F1DCB25F360E01071B45B8E1F6FDFBE6BC4A200B01061B44B7E1F5FEFBE6 BD4A210C09142B55A8D2EAF4EED9AF5C321609132A54A7D1EAF5EED9B05D3316 1E2E3D6A93C0CADFCDC49A713F301D2D3D6993C1CBE0CEC59B71403048576C7C 828CA1B6A38F867E6E5947576C7B828DA2B6A48F867E6F5ABAAB968977624E43 50657A8398ADBAAA958A78634E4451667A8498ADE4D4C89E7539241A273B6891 C1D6E3D4C99F7539251A273C6892C2D7F9F2DDB360360F05122953A6D0EBF8F2 DDB460371005122A53A7D0ECFFFCE7BD4B210D02071C46B8E2F7FFFDE8BE4C22 0D03081D46B9E3F7F3EFDAB05D34170A142C55A9D2E9F3F0DBB15E34180B152C 56A9D3E8DECCC59C7241311F2E3E6A94BFCADFCCC69C7341321F2F3F6B94BFC9 B4A28D877F6F5B48586D7C818BA0B5A38E8780705B49596D7D808BA0424F6479 8499AEBBAB968977624D43506479859AAFBCAC978876614C18253A6690C3D7E5 D5C79E74382319263B6791C3D8E5D6C79D73372303102851A5CEECF9F1DCB25F 360E04112952A5CFEDFAF0DBB25E350E pop pop /customdata8 28 28 mul string def currentfile customdata8 readhexstring 050F2747B6D6EEF8FEF4DCBC4D2D1507111D375F9EC6E0E9EBE6CCA4653D1F13 2939556F8EA8C1D1D3C3AE9475573B2B4961717D808999B1B39B8B867F73634B B8A090827A6A5A42445C6C7C8492A2BAD8C8AA97785232222434546E8DACCADA F0E2CFA768401A0A0C1C365E9DC5E4F2FAF7DFBF50301802040E2646B5D5EDFC FFF5DDBD4E2E160806102848B7D7EFF9EAE7CDA5663E2014121E38609FC7E1E8 D2C2AF9576583C2C2A3A56708FA9C0D0B29A8A878074644C4A62727E818898B0 435B6B7B8593A3BBB9A19183796959412333536D8CADCBDBD9C9AB9677513121 0B1B355D9CC4E5F3F1E3CEA6673F1909030D2545B4D4ECFDFBF6DEBE4F2F1701 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 pop pop end end defaultpacking setpacking %%EndResource %%BeginResource: procset AGM_Gradient_Sep 1.0 0 %%Title: (AGM Gradient Procset) %%Version: 1.0 0 %%CreationDate: (4/26/96) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /AGM_Gradient_Sep 5 dict dup begin put /AGM_Gradient_Sep_private 100 dict def /initialize{ AGM_Gradient_Sep begin AGM_Gradient_Sep_private begin _compositeJob{ initializeSinglePassSeps }{ initializeMultiPassSeps }ifelse initializeSeps AGM_Gradient_private begin /_fillSD newSpotDict def /_rampSD newSpotDict def /_nCustomColorSD nd end AGM_Gradient_Sep_private { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall AGM_Gradient_Sep { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall end currentdict readonly pop end }def /terminate{ currentdict AGM_Gradient_Sep eq{ end }if }def AGM_Gradient_Sep_private begin /initializeSeps{ _noImage not _level2PS not and{ /_whiteBytes 1 makeByte8 pt /knockOut{ 8 setImageParms _whiteBytes /_image load 5 execImage }def /linealFill{ mySave 8 setImageParms _color{ _nCustomColorSD begin cyan magenta yellow black _spotColor{ spot1 begin /tintImage tintValue 1 exch sub makeByte8 def end spot2 begin /tintImage tintValue 1 exch sub makeByte8 def end }if end 4{ makeByte8 4 1 roll }repeat true 4 _nCustomColorSD ncolorimage }{ _nCustomColorSD/black get 1 exch sub makeByte8 _nCustomColorSD bwImage }ifelse myRestore }def }{ /knockOut{ gsave false setoverprint 1 setgray 0 0 1 1 rectfill grestore }def }ifelse /newSpotDict{ 11 dict dup begin /nSpots 2 def /spot1 7 dict def /spot2 7 dict def end }def /initSpotData { begin /name nd /tintImage nd /tintValue nd /spot_C nd /spot_M nd /spot_Y nd /spot_K nd end }def /initSpotDict{ begin /cyanInk false def /magentaInk false def /yellowInk false def /blackInk false def /cyan nd /magenta nd /yellow nd /black nd spot1 initSpotData spot2 initSpotData end }def /copySpotDict{ /_dst xp begin cyanInk magentaInk yellowInk blackInk cyan magenta yellow black spot1 spot2 end _dst begin /spot1 spot1 maxlength dict def /spot2 spot2 maxlength dict def spot2 copy pop spot1 copy pop /black xd /yellow xd /magenta xd /cyan xd /blackInk xd /yellowInk xd /magentaInk xd /cyanInk xd end }def /setCustomColor { 1 index /Black eq{ 6 1 roll 5 npop 1 exch sub setgray }{ 6 1 roll _ccAry1 astore exch dup null eq{ pop 0 }if setcustomcolor }ifelse }def /setCStop{ /_colorStyle exch pt _colorStyle 0 eq{ 0 0 0 4 -1 roll 1 exch sub _spotColor{ /_colorStyle 3 pt /Black 1 index 1 exch sub }if }if _colorStyle 2 eq{ 3 npop }if _rampSD _fillSD copySpotDict _colorStyle 4 eq{ pop 9 2 roll 3 npop 6 -2 roll } if _colorStyle 3 eq _colorStyle 4 eq or{ _fillSD begin exch dup spot1/name get eq{ spot1 spot2 }{ spot2 spot1 }ifelse begin begin /name xd 1 exch sub /tintValue xd 4{ tintValue mul 4 1 roll }repeat _spotColor not{ /tintValue null def }if end /tintValue 0 def end end }if _fillSD nsetcustomcolor }def /renderCMYK{ spot1/name get null eq spot2/name get null eq and dup not{ pop spot1 spotConverted }if dup not{ pop spot2 spotConverted }if }def /fill_ /fill load def /fillOvp{ currentoverprint{ _inRipSep{ currentcolorspace 0 get dup /DeviceGray eq 1 index /DeviceCMYK eq or{ pop currentcmykcolor add add add 0 eq{ newpath }if }{ /Separation eq{ currentcolor 0 eq{ newpath }if }if }ifelse }{ currentgray 1 eq{ newpath }if }ifelse }if fill_ }def /fill{ _nCustomColorSD begin renderCMYK { fillOvp }{ spot1 begin gsave name null ne{ spot_C spot_M spot_Y spot_K name tintValue setCustomColor }{ 1 setgray }ifelse fillOvp grestore end spot2 begin name null ne{ gsave true setoverprint spot_C spot_M spot_Y spot_K name tintValue setCustomColor fillOvp grestore }if end newpath }ifelse end }def /expandSpot{ _spotColor{ /_len xp _rampSD begin spot1 begin tintImage null ne{ tintImage _len expandOne /tintImage xd }if end spot2 begin tintImage null ne{ tintImage _len expandOne /tintImage xd }if end end }{ pop }ifelse }def /rampImage{ _rampSD begin _color{ /cyanInk _cyanData 0 ne def /magentaInk _magentaData 0 ne def /yellowInk _yellowData 0 ne def /blackInk _blackData 0 ne def _nSamples setImageParms _nSamples expandSpot _cyanData _magentaData _yellowData _blackData _nSamples 4 expandColor true 4 _rampSD ncolorimage }{ /cyanInk false def /magentaInk false def /yellowInk false def /blackInk true def _nSamples setImageParms _blackData _rampSD bwImage }ifelse end }def /nsetcustomcolor where{ pop }{ /nsetcustomcolor { /_nCustomColorSD xp _nCustomColorSD begin 4 copy /black xd /yellow xd /magenta xd /cyan xd 4 copy 0 ne /blackInk xd 0 ne /yellowInk xd 0 ne /magentaInk xd 0 ne /cyanInk xd end setcmykcolor }def }ifelse /nsetcustomcolorend where{ pop }{ /nsetcustomcolorend { /_nCustomColorSD null pt }def }ifelse }def /initializeSinglePassSeps{ /_decodeNorm [0 1] pt /_decodeInvert [1 0] pt /spotConverted { begin name null eq{ false }{ tintValue null eq tintImage null eq and{ true }{ false currentpagedevice/SeparationOrder get{name eq or}forall not }ifelse }ifelse end }def /dictImage { 20 dict dup begin /Dict xd /Decode xd /DataSource xd /ImageMatrix xd /BitsPerComponent xd /Height xd /Width xd /ImageType 1 def Dict end /_image load 1 execImage }def /bwImage{ begin gsave currentoverprint{ blackInk{ [/Separation /Black /DeviceGray{}] setcolorspace _decodeInvert dictImage }{ 5 npop }ifelse }{ /DeviceGray setcolorspace _decodeNorm dictImage }ifelse grestore end }def /ncolorimage where{ pop }{ /ncolorimage{ begin renderCMYK { cyanInk magentaInk and yellowInk and blackInk and not currentoverprint and { pop pop gsave cyanInk{ 8 copy [/Separation /Cyan /DeviceGray{}] setcolorspace 3 npop _decodeNorm dictImage }if magentaInk{ 8 copy [/Separation /Magenta /DeviceGray{}] setcolorspace 4 -1 roll 3 npop _decodeNorm dictImage }if yellowInk{ 8 copy [/Separation /Yellow /DeviceGray{}] setcolorspace 4 -2 roll 3 npop _decodeNorm dictImage }if blackInk{ 4 -3 roll [/Separation /Black /DeviceGray{}] setcolorspace 3 npop _decodeNorm dictImage }{ 8 npop }ifelse grestore }{ /_colorimage load 10 execImage }ifelse }{ 6 npop gsave spot1 begin name null ne tintImage null ne and{ [/Separation name /DeviceGray{}] setcolorspace 4 copy tintImage name /Black eq{ _decodeNorm }{ _decodeInvert }ifelse dictImage }{ 1 setgray fill }ifelse end spot2 begin true setoverprint name null ne tintImage null ne and{ [/Separation name /DeviceGray{}] setcolorspace tintImage name /Black eq{ _decodeNorm }{ _decodeInvert }ifelse dictImage }{ 4 npop 1 setgray fill }ifelse end grestore }ifelse end }def }ifelse }def /initializeMultiPassSeps{ /_isCMYKSep _cyanPlate _magentaPlate or _yellowPlate or _blackPlate or pt /invertXfer{ [ { 1 exch sub }/exec load systemdict /currenttransfer get exec /exec load ] cvx systemdict /settransfer get exec }def /ccThrough{ gsave 1 setCustomColor currentcmykcolor grestore add add add 0 ne }def /spotConverted { begin _isCMYKSep not{ false }{ name null eq{ false }{ tintValue null eq tintImage null eq and{ true }{ spot_C spot_M spot_Y spot_K name ccThrough }ifelse }ifelse }ifelse end }def /spotChannel { _isCMYKSep{ pop false }{ begin name null eq{ false }{ spot_C spot_M spot_Y spot_K name ccThrough }ifelse end }ifelse }def /getChannelData { _isCMYKSep dup{ pop renderCMYK }if { _blackPlate{ 4 1 roll 3 npop blackInk }{ _yellowPlate{ 4 2 roll 3 npop yellowInk }{ _magentaPlate{ 4 3 roll 3 npop magentaInk }{ 3 npop cyanInk }ifelse }ifelse }ifelse { true /nonZeroData }{ true /zeroData }ifelse }{ 4 npop spot1/name get null ne spot1 spotChannel and{ spot1/tintImage get dup null ne{ false /nonZeroData }{ pop false /noData }ifelse }{ spot2/name get null ne spot2 spotChannel and{ spot2/tintImage get dup null ne{ false /nonZeroData }{ pop false /noData }ifelse }{ false /noData }ifelse }ifelse }ifelse }def /renderChannelData { /_tmp xp _tmp /nonZeroData ne currentoverprint and{ pop _tmp /zeroData eq{pop}if 4 npop }{ _tmp /nonZeroData eq{ { invertXfer }if systemdict/image get 5 execImage }{ pop _tmp /zeroData eq{pop}if 4 npop knockOut }ifelse }ifelse }def /bwImage{ begin gsave dup dup dup getChannelData exch pop false exch renderChannelData grestore end }def /ncolorimage{ begin pop pop gsave spot2/name get null ne spot2 spotChannel and{ true setoverprint }if getChannelData renderChannelData grestore end }def }def end end defaultpacking setpacking %%EndResource %%BeginResource: procset AGM_Gradient 1.0 0 %%Title: (AGM Gradient Procset) %%Version: 1.0 0 %%CreationDate: (4/26/96) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /AGM_Gradient 20 dict dup begin put /AGM_Gradient_private 200 dict def /initialize { AGM_Gradient begin AGM_Gradient_private begin initializeVars /bd systemdict/mark get def /ed _level2PS { (>>) }{ (counttomark 2 idiv dup dict begin {def} repeat pop currentdict end) } ifelse cvx def _level2PS{ initializeLev2 }{ initializeLev1 }ifelse queryDevice initializeShading initializeOps _producingSeps{ AGM_Gradient_Sep/initialize get exec }{ initializeComposite }ifelse _illustrator{ /f{}def /F{}def /s{}def /S{}def /b{}def /B{}def }if /image where{ /image get /_image xd }if /colorimage where{ /colorimage get /_colorimage xd }if /rectfill where dup{ exch pop not _producingSeps or }{ not }ifelse { /rectfill{ gsave newpath 4 2 roll moveto 1 index 0 rlineto 0 1 index rlineto 1 index neg 0 rlineto pop pop closepath fill grestore }def }if /linealImage _noImage{ /rectImage load }{ _producingSeps{ AGM_Gradient_Sep/AGM_Gradient_Sep_private get begin /rampImage load end }{ /rampImage load }ifelse }ifelse def AGM_Gradient_private { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall AGM_Gradient { dup xcheck 1 index type /arraytype eq and { bind }if pop pop }forall end currentdict readonly pop end }def /initializeAI { pop pop AGM_Gradient/AGM_Gradient_private get /_illustrator true put AGM_Gradient/initialize get exec AGM_Gradient begin }def /unload{ systemdict/languagelevel known{ systemdict/languagelevel get 2 ge{ userdict/AGM_Gradient_Sep 2 copy known{ undef }{ pop pop }ifelse userdict/AGM_Gradient 2 copy known{ undef }{ pop pop }ifelse }if }if }def /terminate{ currentdict AGM_Gradient eq{ end }if }def AGM_Gradient_private begin /initializeVars{ /_d255 256 array def 0 1 255{ _d255 exch dup 255 div put }bind for /_d255- 256 array def 0 1 255{ _d255- exch 1 _d255 2 index get sub put }bind for /_sSave nd /_dUserSpace matrix defaultmatrix def /_bUMatrix matrix def /_imageMatrix matrix def /_saveMatrix matrix def /_xm matrix def /_ccAry1 5 array def /_level2PS systemdict/languagelevel known dup{ pop systemdict/languagelevel get 2 ge }if def /_level3PS _level2PS systemdict/shfill known and def currentdict /_illustrator known not{ /_illustrator false def }if }def /initializeOps { AGM_Gradient begin currentdict/Bc known not{ /Bc{ _renderFlag 2 eq{ 6 npop }{ pushBSpace _rampIndex 0 eq{ pop pop setCStop }if linealFill popBSpace }ifelse }def }if currentdict/Bg known not{ /Bg{ 10 npop /_gradName xp /_renderFlag xp _renderFlag 2 ne{ _illustrator{ _of setoverprint }if _illustrator _eo and _renderFlag 3 eq or{ eoclip }{ clip }ifelse _gradNames _gradName 2 copy known{ get mark exch aload pop /_gradType xp 1 sub dup /_rampIndex xp /_maxRampIndex xp mark exch aload pop 0 0 }if pop pop getRampData }{ mark mark }ifelse }def }if currentdict/Bm known not{ /Bm{ _renderFlag 2 ne{ _gradType 0 eq{ linealRamp }{ radialGrad }ifelse }{ 6 npop }ifelse }def }if currentdict/Bh known not{ /Bh{ 2 npop /_yHi xp /_xHi xp /_radHilite _xHi 0 ne _yHi 0 ne or pt }def }if currentdict/Bn known not{ /Bn{ AGM_Gradient_private begin dict /_gradNames xp end }def }if currentdict/Bd known not{ /Bd{ AGM_Gradient begin AGM_Gradient_private begin /_nColorsBd xp /_gradType xp /_gradName xp }def }if currentdict/BD known not{ /BD{ currentdict/_gradNames known not{ /_gradNames 20 dict def }if ] _nColorsBd _gradType ] _gradName exch /_gradNames xput end end }def }if currentdict/Bb known not{ /Bb{ AGM_Gradient begin AGM_Gradient_private begin _producingSeps{ AGM_Gradient_Sep/AGM_Gradient_Sep_private get begin }if mySave }def }if currentdict/BB known not{ /BB{ /_tmp xp cleartomark cleartomark _tmp dup _renderFlag myRestore _producingSeps{ end }if _illustrator end end { 2 ne exch 0 gt and{ 2 eq{ s }{ S }ifelse }{ pop newpath }ifelse }{ pop newpath }ifelse }def }if currentdict/Xm known not{ /Xm{ _xm astore pop }def }if end }def /queryDevice{ /_inRipSep _level2PS{ currentpagedevice/Separations 2 copy known{ get }{ pop pop false }ifelse }{ false }ifelse def /_noImage /lv1Fix where{ pop lv1Fix }{ false }ifelse def /_useShells where{ pop }{ /_useShells true def }ifelse /_useSmoothShade where{ pop }{ /_useSmoothShade false def }ifelse /_cyanPlate 1 0 0 0 testCMYKColorThrough def /_magentaPlate 0 1 0 0 testCMYKColorThrough def /_yellowPlate 0 0 1 0 testCMYKColorThrough def /_blackPlate 0 0 0 1 testCMYKColorThrough def /_compositeJob _cyanPlate _magentaPlate and _yellowPlate and _blackPlate and def /_compositeSpotDevice where{ pop }{ /_compositeSpotDevice _compositeJob not _inRipSep or{ 1 }{ 0 }ifelse def }ifelse /_producingSeps _compositeSpotDevice 0 ne def /_deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt def /_dpiThreshold where{ pop }{ /_dpiThreshold 600 def }ifelse /_screenFreqThreshold where{ pop }{ /_screenFreqThreshold 150 def }ifelse /_contoneDevice where{ pop }{ /_contoneDevice false def }ifelse /_subSampleOK _deviceDPI _dpiThreshold le currentScreenFreq _screenFreqThreshold le and _contoneDevice not and _producingSeps not and def }def /initializeLev1{ /makeByte8{ /_tmp 0 pt 255 mul cvi 8 string 8{ dup _tmp 3 index put /_tmp _tmp 1 add pt }repeat exch pop }def /currentScreenFreq{ currentscreen pop pop }def /_byte 1 string def /colorimage where{ pop }{ /colorimage{ pop pop /_blackTmp xp /_yellowTmp xp /_magentaTmp xp /_cyanTmp xp /_cnt 0 pt [ _byte dup 0 _cyanTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .3 /mul cvx _magentaTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .59 /mul cvx _yellowTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx .11 /mul cvx _blackTmp /_cnt cvx /get cvx _d255 /exch cvx /get cvx /add cvx /add cvx /add cvx 1 /exch cvx /sub cvx /dup cvx 0 /lt cvx{ pop 0 }/if cvx /dup cvx 1 /gt cvx{ pop 1 }/if cvx 255 /mul cvx /cvi cvx 256 /mod cvx /dup cvx 0 /lt cvx{ pop 0 }/if cvx /put cvx /_cnt dup cvx 1 /add cvx /pt cvx ] cvx bind /_image load 5 execImage }def }ifelse }def /initializeLev2{ /level2ScreenFreq{ begin 60 HalftoneType 1 eq{ pop Frequency }if HalftoneType 2 eq{ pop GrayFrequency }if HalftoneType 5 eq{ pop Default level2ScreenFreq }if end }def /currentScreenFreq{ currenthalftone level2ScreenFreq }def }def /initializeShading{ _useSmoothShade _level3PS and{ /_usingSmoothShade true pt initializeLev3_Ops }{ /_usingSmoothShade false pt }ifelse }def /initializeLev3_Ops { /initShFill{ /_index _gradType 0 eq {0}{_maxRampIndex 1 sub} ifelse pt /_rampFuncsArray _maxRampIndex array pt /_boundsArray _maxRampIndex 1 sub array pt /_encodeArray _maxRampIndex 2 mul array pt /_beginCoord _rampPoint pt /_colorSpace null pt /_firstFill _rampIndex _maxRampIndex eq pt /_lastFill false pt }def /getRampColorSpace{ _nSamples 1 gt{ /_ndx 0 pt [blendColor] cvx exec }if /_C0 [currentcolor] pt /_C0_Space currentcolorspace pt _nSamples 1 gt{ /_ndx _nSamples 1 sub pt [blendColor] cvx exec }if /_C1 [currentcolor] pt /_C1_Space currentcolorspace pt _C0_Space _C1_Space eq{ /_rampColorSpace _C0_Space pt }{ (colorspace conflict!) == showpage stop }ifelse _spotColor{ nsetcustomcolorend }if }def /linealShFill{ popBSpace _xm aload pop pushBSpace /_size _index 1 add pt _size _maxRampIndex lt { /_rampFuncsArray _rampFuncsArray 0 _size getinterval pt /_boundsArray _boundsArray 0 _size 1 sub getinterval pt /_encodeArray _encodeArray 0 _size 2 mul getinterval pt }if bd /ShadingType 2 /ColorSpace _colorSpace /Function bd /FunctionType 3 /Domain [0 1] /Functions _rampFuncsArray /Bounds _boundsArray /Encode _encodeArray ed /Extend [_firstFill _lastFill] /Domain [0 1] /Coords [_beginCoord 0 _endCoord 0] ed shfill }def /radialShFill{ /_size _maxRampIndex _index sub pt _size _maxRampIndex lt { /_rampFuncsArray _rampFuncsArray _index _size getinterval pt /_boundsArray _boundsArray _index _size 1 sub getinterval pt /_encodeArray _encodeArray _index 2 mul _size 2 mul getinterval pt }if /_rampLen _beginCoord _endCoord sub pt bd /ShadingType 3 /ColorSpace _colorSpace /Function bd /FunctionType 3 /Domain [0 1] /Functions _rampFuncsArray /Bounds _boundsArray /Encode _encodeArray ed /Extend [_lastFill _firstFill] /Domain [0 1] /Coords [_xHi _rampLen mul _yHi _rampLen mul _endCoord 0 0 _beginCoord] ed shfill _radHilite{ _xHi _rampLen mul _yHi _rampLen mul translate }if }def /fillRamp{ /_invert _midPoint 0.5 lt pt _rampIndex _maxRampIndex eq { initShFill }if getRampColorSpace _colorSpace null eq{ /_colorSpace _rampColorSpace pt }{ _colorSpace _rampColorSpace ne{ /_index _index 1 _gradType 0 eq{ sub pt linealShFill }{ add pt radialShFill }ifelse initShFill /_colorSpace _rampColorSpace pt } if }ifelse /_endCoord _endPoint pt _rampFuncsArray _index bd /FunctionType 2 /Domain [0 1] /N 0.5 log _invert{1 _midPoint sub}{_midPoint}ifelse log div _gradType 0 eq{ _invert{/C1}{/C0}ifelse _C0 _invert{/C0}{/C1}ifelse _C1 }{ _invert{/C0}{/C1}ifelse _C1 _invert{/C1}{/C0}ifelse _C0 }ifelse ed put _rampIndex 1 ne{ _boundsArray _index _gradType 1 eq{1 sub}if _endCoord put } if 0 1 _invert {exch}if _encodeArray _index 2 mul 1 add 3 -1 roll put _encodeArray _index 2 mul 3 -1 roll put _rampIndex 1 eq { /_lastFill true pt _gradType 0 eq{ linealShFill }{ radialShFill }ifelse }if /_index _index 1 _gradType 0 eq{ add pt }{ sub pt }ifelse }def /radialRamp /fillRamp load def /rampImage /fillRamp load def AGM_Gradient begin /Bc{ 6 npop }def end }def /initializeComposite{ /bwImage{ pop /_image load 5 execImage }def currentdict/rampImage known not{ /rampImage{ _color{ _nSamples setImageParms _rgbRamp{ _redData _greenData _blueData _nSamples 3 expandColor true 3 null ncolorimage }{ _cyanData _magentaData _yellowData _blackData _nSamples 4 expandColor true 4 null ncolorimage }ifelse }{ _nSamples setImageParms _blackData null bwImage }ifelse }def }if /setCStop{ /_colorStyle exch pt _colorStyle 0 eq{ 1 exch sub 0 0 0 4 -1 roll }if _colorStyle 2 eq{ setrgbcolor 4 npop }if _colorStyle 3 eq{ 1 exch sub /_tmp xp pop 4{ _tmp mul 4 1 roll }repeat }if _colorStyle 4 eq{ 3 -1 roll pop pop 1 exch sub /_tmp xp 3{ 1 exch sub _tmp mul 1 exch sub 3 1 roll }repeat setrgbcolor 4 npop }if _colorStyle 2 ne _colorStyle 4 ne and{ null nsetcustomcolor }if }def /nsetcustomcolor { pop setcmykcolor }def /nsetcustomcolorend { }def /ncolorimage{ pop /_colorimage load 10 execImage }def _noImage not _level2PS not and{ /linealFill{ 8 setImageParms _color{ currentcmykcolor 4{ makeByte8 4 1 roll }repeat true 4 null ncolorimage }{ currentgray makeByte8 null bwImage }ifelse }def }if }def /npop{ {pop}repeat }def /xd{ exch def }def /nd{ null def }def /pt{ AGM_Gradient_private 3 1 roll put }def /xp{ exch pt }def /xput{ dup load dup length exch maxlength eq{ dup dup load dup length 2 mul dict copy def }if load begin def end }def /mySave{ save /_sSave xp }def /myRestore{ _sSave type /savetype eq{ _sSave restore }if }def /gMark{ counttomark 2 add -1 roll }def /execImage{ /_tmp xp { exec }stopped{ $error /errorname get /undefinedresult ne{ stop }{ _tmp npop }ifelse }if }def /pushBSpace{ newpath gsave _bUMatrix astore concat }def /popBSpace{ grestore }def /setImageParms{ 1 8 2 index 0 0 1 0 0 _imageMatrix astore }def /linealFill{ 0 0 1 1 rectfill }def /testCMYKColorThrough{ gsave setcmykcolor currentcmykcolor grestore add add add 0 ne }def /expandOne { /_tmp xp dup type /stringtype ne{ _tmp string exch dup 0 ne{ 255 mul cvi 0 1 _tmp 1 sub{ 3 copy exch put pop }for }if pop }if }def /expandColor{ /_channels xp /_len xp _channels{ _len expandOne _channels 1 roll }repeat }def /blendColor{ _color{ _rgbRamp _producingSeps not and{ _redData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _greenData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _blueData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if /setrgbcolor cvx }{ _cyanData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _magentaData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _yellowData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _blackData dup type /stringtype eq{ /_ndx cvx /get cvx _d255 /exch cvx /get cvx }if _spotColor{ _rampSD begin /_rampSD cvx /begin cvx spot1 begin tintImage dup type /stringtype eq{ /_ndx cvx /get cvx _d255- /exch cvx /get cvx }{ dup null ne{ name type /nametype ne{ 1 exch sub }if }if }ifelse end /spot1 cvx /tintValue 3 -1 /roll cvx /put cvx spot2 begin tintImage dup type /stringtype eq{ /_ndx cvx /get cvx _d255- /exch cvx /get cvx }{ dup null ne{ name type /nametype ne{ 1 exch sub }if }if }ifelse end /spot2 cvx /tintValue 3 -1 /roll cvx /put cvx /end cvx end /_rampSD cvx /nsetcustomcolor cvx }{ /setcmykcolor cvx }ifelse }ifelse }{ _blackData /_ndx cvx /get cvx _d255 /exch cvx /get cvx _usingSmoothShade{ 1 /exch cvx /sub cvx 0 0 0 4 -1 /roll cvx /setcmykcolor cvx }{ /setgray cvx }ifelse }ifelse }def /linealRamp{ pushBSpace _ramp{ linealImage }{ linealFill }ifelse popBSpace /_rampIndex _rampIndex 1 sub pt _rampIndex 0 gt{ getRampData }if }def /radialGrad{ /_firstShell true pt _usingSmoothShade not{ fill }if pushBSpace _radHilite{ _xHi _yHi _bUMatrix idtransform /_yHi xp /_xHi xp _rampPoint 1 lt{ 1 _rampPoint sub dup _xHi mul exch _yHi mul translate }if }if _rampIndex{ radialRamp /_rampIndex _rampIndex 1 sub pt _rampIndex 0 gt{ getRampData }if }repeat popBSpace }def /getNSamples{ 0 exch { dup type /stringtype eq{ length exch pop exit }if pop }forall dup 0 eq{ pop 1 }if }def /getRampData{ /_rampType gMark pt /_color _rampType 0 gt pt /_ccRGB _rampType 5 eq _rampType 6 eq or pt /_rgbRamp _rampType 4 eq _ccRGB or pt /_ccProcess _rampType 2 eq _rampType 3 eq or pt _producingSeps{ _rampSD initSpotDict /_spotColor _ccProcess _ccRGB or pt }{ /_spotColor false pt }ifelse /_ramp true pt 100 div /_rampPoint xp 100 div /_midPoint xp dup /_colorStyle xp _colorStyle 0 eq{ 2 }{ _colorStyle 1 eq{ 5 }{ _colorStyle 2 eq{ 8 }{ _colorStyle 3 eq{ _producingSeps{ _rampSD begin spot1 begin /name 3 index def /spot_K 4 index def /spot_Y 5 index def /spot_M 6 index def /spot_C 7 index def end end }if 7 }{ _producingSeps{ _rampSD begin spot1 begin /name 4 index def /spot_K 8 index def /spot_Y 9 index def /spot_M 10 index def /spot_C 11 index def end end }if 11 } ifelse }ifelse }ifelse }ifelse /_tmp xp _tmp index 100 div /_endPoint xp _gradType 1 eq{ _tmp 1 add index 100 div /_midPoint xp }if _producingSeps{ _tmp 2 add index /_nextColorStyle xp _nextColorStyle 3 eq{ /_tmp _tmp 4 add pt _tmp index dup _rampSD begin spot1 /name get ne{ spot2 begin /name xd /spot_K _tmp 2 add index def /spot_Y _tmp 3 add index def /spot_M _tmp 4 add index def /spot_C _tmp 5 add index def end }{ pop }ifelse end }if _nextColorStyle 4 eq{ /_tmp _tmp 5 add pt _tmp index dup _rampSD begin spot1 /name get ne{ spot2 begin /name xd /spot_K _tmp 5 add index def /spot_Y _tmp 6 add index def /spot_M _tmp 7 add index def /spot_C _tmp 8 add index def end }{ pop }ifelse end }if }if _rampType 3 eq _rampType 6 eq or{ /_tint2Data gMark pt }if _ccProcess _ccRGB or{ /_tint1Data gMark pt }if _rgbRamp{ /_blueData gMark pt /_greenData gMark pt /_redData gMark pt }if _producingSeps{ _rampSD begin _ccProcess _ccRGB or{ _rampType 3 eq _rampType 6 eq or{ spot2 begin /tintImage _gradType 0 eq{ _tint2Data }{ _tint1Data }ifelse def name null eq{ /name /Black def }if end }if spot1 begin /tintImage _gradType 0 eq _rampType 2 eq or _rampType 5 eq or{ _tint1Data }{ _tint2Data }ifelse def _rampType 2 eq _rampType 5 eq or{ name null eq{ /name spot2 /name get def spot2 /name null put }if }{ name null eq{ /name /Black def }if }ifelse end }if end }if /_blackData gMark pt _rampType 0 gt{ counttomark 4 add -3 roll /_yellowData xp /_magentaData xp /_cyanData xp }if _ramp{ /_nSamples [ _rampType 0 eq {_blackData}if _rampType 1 eq {_cyanData _magentaData _yellowData _blackData}if _rampType 2 eq {_cyanData _magentaData _yellowData _blackData _tint1Data}if _rampType 3 eq {_cyanData _magentaData _yellowData _blackData _tint1Data _tint2Data}if _rampType 4 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData}if _rampType 5 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData _tint1Data}if _rampType 6 eq {_cyanData _magentaData _yellowData _blackData _redData _greenData _blueData _tint1Data _tint2Data}if ] getNSamples pt _usingSmoothShade not {/_ramp _nSamples 1 gt pt} if } if setCStop }def /rectImage{ gsave /_sInc 1 pt /_bInc 1 _nSamples div pt /_uRampLen 1 0 dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt pt /_pChange _uRampLen 0 eq{0}{_nSamples _uRampLen div}ifelse pt 0 _nSamples [ /dup cvx /_ndx /exch cvx /pt cvx blendColor 0 0 _bInc 1 /rectfill cvx _bInc 0 /translate cvx _sInc /add cvx ] cvx bind repeat pop _spotColor{ nsetcustomcolorend }if grestore }def /radialInit{ /_nRadSamples _nSamples dup 0 eq{pop 1}if pt /_sInc -1 pt /_rampLen _rampPoint _endPoint sub pt /_bInc _rampLen _nSamples div neg pt /_optimize false pt _subSampleOK{ /_uRampLen _rampLen 0 dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt 0 _rampLen dtransform _dUserSpace idtransform dup mul exch dup mul add sqrt 2 copy lt{ exch }if pop pt /_pChange _uRampLen 0 eq{ 0 }{ _nSamples _uRampLen div }ifelse pt _pChange .5 gt dup /_optimize xp{ /_nRadSamples _uRampLen 2 div round cvi dup 1 le{pop 2}if pt /_bInc _rampLen _nRadSamples div neg pt /_sInc _nSamples 1 sub _nRadSamples 1 sub div neg pt }if }if _radHilite{ /_xBCInc _xHi _rampLen mul _nRadSamples div pt /_yBCInc _yHi _rampLen mul _nRadSamples div pt }if }def currentdict/radialRamp known not{ /radialRamp{ /_saveMatrix _saveMatrix currentmatrix def radialInit _rampPoint _nSamples 1 sub _nRadSamples [ /dup cvx _optimize{ /round cvx /cvi cvx }if /_ndx /exch cvx /pt cvx _useShells{ /_firstShell cvx{ /_firstShell false pt }{ 0 0 3 index 360 0 arcn fill }/ifelse cvx }if blendColor _useShells{ 0 0 3 /index cvx 0 360 /arc cvx }{ 0 0 3 /index cvx 0 360 /arc cvx /fill cvx }ifelse /exch cvx _bInc /add cvx /exch cvx _sInc /add cvx _radHilite{ _xBCInc _yBCInc /translate cvx }if ] cvx bind repeat pop pop _saveMatrix setmatrix _radHilite{ _xHi _rampLen mul _yHi _rampLen mul translate }if _useShells _rampIndex 1 eq and{ fill }if _spotColor{ nsetcustomcolorend }if }def }if end end defaultpacking setpacking %%EndResource %%BeginProcSet: Adobe_ColorImage_AI6 1.1 0 userdict /Adobe_ColorImage_AI6 known not { userdict /Adobe_ColorImage_AI6 24 dict put } if userdict /Adobe_ColorImage_AI6 get begin /initialize { Adobe_ColorImage_AI6 begin Adobe_ColorImage_AI6 { dup type /arraytype eq { dup xcheck { bind } if } if pop pop } forall } def /terminate { end } def currentdict /Adobe_ColorImage_AI6_Vars known not { /Adobe_ColorImage_AI6_Vars 15 dict def } if Adobe_ColorImage_AI6_Vars begin /channelcount 0 def /sourcecount 0 def /sourcearray 4 array def /plateindex -1 def /XIMask 0 def /XIBinary 0 def /XIChannelCount 0 def /XIBitsPerPixel 0 def /XIImageHeight 0 def /XIImageWidth 0 def /XIImageMatrix null def /XIBuffer null def /XIDataProc null def /XIVersion 6 def end /WalkRGBString null def /WalkCMYKString null def /StuffRGBIntoGrayString null def /RGBToGrayImageProc null def /StuffCMYKIntoGrayString null def /CMYKToGrayImageProc null def /ColorImageCompositeEmulator null def /SeparateCMYKImageProc null def /FourEqual null def /TestPlateIndex null def currentdict /_colorimage known not { /colorimage where { /colorimage get /_colorimage exch def } { /_colorimage null def } ifelse } if /_currenttransfer systemdict /currenttransfer get def /colorimage null def /XI null def /WalkRGBString { 0 3 index dup length 1 sub 0 3 3 -1 roll { 3 getinterval { } forall 5 index exec 3 index } for 5 { pop } repeat } def /WalkCMYKString { 0 3 index dup length 1 sub 0 4 3 -1 roll { 4 getinterval { } forall 6 index exec 3 index } for 5 { pop } repeat } def /StuffRGBIntoGrayString { .11 mul exch .59 mul add exch .3 mul add cvi 3 copy put pop 1 add } def /RGBToGrayImageProc { Adobe_ColorImage_AI6_Vars begin sourcearray 0 get exec dup length 3 idiv string dup 3 1 roll /StuffRGBIntoGrayString load exch WalkRGBString end } def /StuffCMYKIntoGrayString { exch .11 mul add exch .59 mul add exch .3 mul add dup 255 gt { pop 255 } if 255 exch sub cvi 3 copy put pop 1 add } def /CMYKToGrayImageProc { Adobe_ColorImage_AI6_Vars begin sourcearray 0 get exec dup length 4 idiv string dup 3 1 roll /StuffCMYKIntoGrayString load exch WalkCMYKString end } def /ColorImageCompositeEmulator { pop true eq { Adobe_ColorImage_AI6_Vars /sourcecount get 5 add { pop } repeat } { Adobe_ColorImage_AI6_Vars /channelcount get 1 ne { Adobe_ColorImage_AI6_Vars begin sourcearray 0 3 -1 roll put channelcount 3 eq { /RGBToGrayImageProc } { /CMYKToGrayImageProc } ifelse load end } if image } ifelse } def /SeparateCMYKImageProc { Adobe_ColorImage_AI6_Vars begin sourcecount 0 ne { sourcearray plateindex get exec } { sourcearray 0 get exec dup length 4 idiv string 0 2 index plateindex 4 2 index length 1 sub { get 255 exch sub 3 copy put pop 1 add 2 index } for pop pop exch pop } ifelse end } def /FourEqual { 4 index ne { pop pop pop false } { 4 index ne { pop pop false } { 4 index ne { pop false } { 4 index eq } ifelse } ifelse } ifelse } def /TestPlateIndex { Adobe_ColorImage_AI6_Vars begin /plateindex -1 def /setcmykcolor where { pop gsave 1 0 0 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 1 0 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 0 1 0 setcmykcolor systemdict /currentgray get exec 1 exch sub 0 0 0 1 setcmykcolor systemdict /currentgray get exec 1 exch sub grestore 1 0 0 0 FourEqual { /plateindex 0 def } { 0 1 0 0 FourEqual { /plateindex 1 def } { 0 0 1 0 FourEqual { /plateindex 2 def } { 0 0 0 1 FourEqual { /plateindex 3 def } { 0 0 0 0 FourEqual { /plateindex 5 def } if } ifelse } ifelse } ifelse } ifelse pop pop pop pop } if plateindex end } def /colorimage { Adobe_ColorImage_AI6_Vars begin /channelcount 1 index def /sourcecount 2 index 1 eq { channelcount 1 sub } { 0 } ifelse def 4 sourcecount add index dup 8 eq exch 1 eq or not end { /_colorimage load null ne { _colorimage } { Adobe_ColorImage_AI6_Vars /sourcecount get 7 add { pop } repeat } ifelse } { dup 3 eq TestPlateIndex dup -1 eq exch 5 eq or or { /_colorimage load null eq { ColorImageCompositeEmulator } { dup 1 eq { pop pop image } { Adobe_ColorImage_AI6_Vars /plateindex get 5 eq { gsave 0 _currenttransfer exec 1 _currenttransfer exec eq { 0 _currenttransfer exec 0.5 lt } { 0 _currenttransfer exec 1 _currenttransfer exec gt } ifelse { { pop 0 } } { { pop 1 } } ifelse systemdict /settransfer get exec } if _colorimage Adobe_ColorImage_AI6_Vars /plateindex get 5 eq { grestore } if } ifelse } ifelse } { dup 1 eq { pop pop image } { pop pop Adobe_ColorImage_AI6_Vars begin sourcecount -1 0 { exch sourcearray 3 1 roll put } for /SeparateCMYKImageProc load end systemdict /image get exec } ifelse } ifelse } ifelse } def /XG { pop pop } def /XF { 13 {pop} repeat } def /Xh { Adobe_ColorImage_AI6_Vars begin gsave /XIMask exch 0 ne def /XIImageHeight exch def /XIImageWidth exch def /XIImageMatrix exch def 0 0 moveto XIImageMatrix concat XIImageWidth XIImageHeight scale XIMask { /_lp /null ddef _fc /_lp /imagemask ddef } if /XIVersion 7 def end } def /XH { Adobe_ColorImage_AI6_Vars begin /XIVersion 6 def grestore end } def /XI { Adobe_ColorImage_AI6_Vars begin gsave /XIMask exch 0 ne def /XIBinary exch 0 ne def pop pop /XIChannelCount exch def /XIBitsPerPixel exch def /XIImageHeight exch def /XIImageWidth exch def pop pop pop pop /XIImageMatrix exch def XIBitsPerPixel 1 eq { XIImageWidth 8 div ceiling cvi } { XIImageWidth XIChannelCount mul } ifelse /XIBuffer exch string def XIBinary { /XIDataProc { currentfile XIBuffer readstring pop } def XIVersion 6 le { currentfile 128 string readline pop pop } if } { /XIDataProc { currentfile XIBuffer readhexstring pop } def } ifelse XIVersion 6 le { 0 0 moveto XIImageMatrix concat XIImageWidth XIImageHeight scale XIMask { /_lp /null ddef _fc /_lp /imagemask ddef } if } if XIMask { XIImageWidth XIImageHeight false [ XIImageWidth 0 0 XIImageHeight neg 0 0 ] /XIDataProc load imagemask } { XIImageWidth XIImageHeight XIBitsPerPixel [ XIImageWidth 0 0 XIImageHeight neg 0 0 ] /XIDataProc load XIChannelCount 1 eq { gsave 0 setgray image grestore } { false XIChannelCount colorimage } ifelse } ifelse grestore end } def end %%EndProcSet %%BeginResource: procset Adobe_Illustrator_AI5 1.1 0 %%Title: (Adobe Illustrator (R) Version 5.0 Full Prolog) %%Version: 1.1 0 %%CreationDate: (3/7/1994) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_Illustrator_AI5_vars 81 dict dup begin put /_eo false def /_lp /none def /_pf { } def /_ps { } def /_psf { } def /_pss { } def /_pjsf { } def /_pjss { } def /_pola 0 def /_doClip 0 def /cf currentflat def /_tm matrix def /_renderStart [ /e0 /r0 /a0 /o0 /e1 /r1 /a1 /i0 ] def /_renderEnd [ null null null null /i1 /i1 /i1 /i1 ] def /_render -1 def /_rise 0 def /_ax 0 def /_ay 0 def /_cx 0 def /_cy 0 def /_leading [ 0 0 ] def /_ctm matrix def /_mtx matrix def /_sp 16#020 def /_hyphen (-) def /_fScl 0 def /_cnt 0 def /_hs 1 def /_nativeEncoding 0 def /_useNativeEncoding 0 def /_tempEncode 0 def /_pntr 0 def /_tDict 2 dict def /_wv 0 def /Tx { } def /Tj { } def /CRender { } def /_AI3_savepage { } def /_gf null def /_cf 4 array def /_if null def /_of false def /_fc { } def /_gs null def /_cs 4 array def /_is null def /_os false def /_sc { } def /_pd 1 dict def /_ed 15 dict def /_pm matrix def /_fm null def /_fd null def /_fdd null def /_sm null def /_sd null def /_sdd null def /_i null def /discardSave null def /buffer 256 string def /beginString null def /endString null def /endStringLength null def /layerCnt 1 def /layerCount 1 def /perCent (%) 0 get def /perCentSeen? false def /newBuff null def /newBuffButFirst null def /newBuffLast null def /clipForward? false def end userdict /Adobe_Illustrator_AI5 known not { userdict /Adobe_Illustrator_AI5 91 dict put } if userdict /Adobe_Illustrator_AI5 get begin /initialize { Adobe_Illustrator_AI5 dup begin Adobe_Illustrator_AI5_vars begin discardDict { bind pop pop } forall dup /nc get begin { dup xcheck 1 index type /operatortype ne and { bind } if pop pop } forall end newpath } def /terminate { end end } def /_ null def /ddef { Adobe_Illustrator_AI5_vars 3 1 roll put } def /xput { dup load dup length exch maxlength eq { dup dup load dup length 2 mul dict copy def } if load begin def end } def /npop { { pop } repeat } def /sw { dup length exch stringwidth exch 5 -1 roll 3 index mul add 4 1 roll 3 1 roll mul add } def /swj { dup 4 1 roll dup length exch stringwidth exch 5 -1 roll 3 index mul add 4 1 roll 3 1 roll mul add 6 2 roll /_cnt 0 ddef { 1 index eq { /_cnt _cnt 1 add ddef } if } forall pop exch _cnt mul exch _cnt mul 2 index add 4 1 roll 2 index add 4 1 roll pop pop } def /ss { 4 1 roll { 2 npop (0) exch 2 copy 0 exch put pop gsave false charpath currentpoint 4 index setmatrix stroke grestore moveto 2 copy rmoveto } exch cshow 3 npop } def /jss { 4 1 roll { 2 npop (0) exch 2 copy 0 exch put gsave _sp eq { exch 6 index 6 index 6 index 5 -1 roll widthshow currentpoint } { false charpath currentpoint 4 index setmatrix stroke } ifelse grestore moveto 2 copy rmoveto } exch cshow 6 npop } def /sp { { 2 npop (0) exch 2 copy 0 exch put pop false charpath 2 copy rmoveto } exch cshow 2 npop } def /jsp { { 2 npop (0) exch 2 copy 0 exch put _sp eq { exch 5 index 5 index 5 index 5 -1 roll widthshow } { false charpath } ifelse 2 copy rmoveto } exch cshow 5 npop } def /pl { transform 0.25 sub round 0.25 add exch 0.25 sub round 0.25 add exch itransform } def /setstrokeadjust where { pop true setstrokeadjust /c { curveto } def /C /c load def /v { currentpoint 6 2 roll curveto } def /V /v load def /y { 2 copy curveto } def /Y /y load def /l { lineto } def /L /l load def /m { moveto } def } { /c { pl curveto } def /C /c load def /v { currentpoint 6 2 roll pl curveto } def /V /v load def /y { pl 2 copy curveto } def /Y /y load def /l { pl lineto } def /L /l load def /m { pl moveto } def } ifelse /d { setdash } def /cf { } def /i { dup 0 eq { pop cf } if setflat } def /j { setlinejoin } def /J { setlinecap } def /M { setmiterlimit } def /w { setlinewidth } def /XR { 0 ne /_eo exch ddef } def /H { } def /h { closepath } def /N { _pola 0 eq { _doClip 1 eq { _eo {eoclip} {clip} ifelse /_doClip 0 ddef } if newpath } { /CRender { N } ddef } ifelse } def /n { N } def /F { _pola 0 eq { _doClip 1 eq { gsave _pf grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _fc /_doClip 0 ddef } { _pf } ifelse } { /CRender { F } ddef } ifelse } def /f { closepath F } def /S { _pola 0 eq { _doClip 1 eq { gsave _ps grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _sc /_doClip 0 ddef } { _ps } ifelse } { /CRender { S } ddef } ifelse } def /s { closepath S } def /B { _pola 0 eq { _doClip 1 eq gsave F grestore { gsave S grestore _eo {eoclip} {clip} ifelse newpath /_lp /none ddef _sc /_doClip 0 ddef } { S } ifelse } { /CRender { B } ddef } ifelse } def /b { closepath B } def /W { /_doClip 1 ddef } def /* { count 0 ne { dup type /stringtype eq { pop } if } if newpath } def /u { } def /U { } def /q { _pola 0 eq { gsave } if } def /Q { _pola 0 eq { grestore } if } def /*u { _pola 1 add /_pola exch ddef } def /*U { _pola 1 sub /_pola exch ddef _pola 0 eq { CRender } if } def /D { pop } def /*w { } def /*W { } def /` { /_i save ddef clipForward? { nulldevice } if 6 1 roll 4 npop concat pop userdict begin /showpage { } def 0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit [] 0 setdash /setstrokeadjust where {pop false setstrokeadjust} if newpath 0 setgray false setoverprint } def /~ { end _i restore } def /O { 0 ne /_of exch ddef /_lp /none ddef } def /R { 0 ne /_os exch ddef /_lp /none ddef } def /g { /_gf exch ddef /_fc { _lp /fill ne { _of setoverprint _gf setgray /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /G { /_gs exch ddef /_sc { _lp /stroke ne { _os setoverprint _gs setgray /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /k { _cf astore pop /_fc { _lp /fill ne { _of setoverprint _cf aload pop setcmykcolor /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /K { _cs astore pop /_sc { _lp /stroke ne { _os setoverprint _cs aload pop setcmykcolor /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /x { /_gf exch ddef findcmykcustomcolor /_if exch ddef /_fc { _lp /fill ne { _of setoverprint _if _gf 1 exch sub setcustomcolor /_lp /fill ddef } if } ddef /_pf { _fc _eo {eofill} {fill} ifelse } ddef /_psf { _fc ashow } ddef /_pjsf { _fc awidthshow } ddef /_lp /none ddef } def /X { /_gs exch ddef findcmykcustomcolor /_is exch ddef /_sc { _lp /stroke ne { _os setoverprint _is _gs 1 exch sub setcustomcolor /_lp /stroke ddef } if } ddef /_ps { _sc stroke } ddef /_pss { _sc ss } ddef /_pjss { _sc jss } ddef /_lp /none ddef } def /A { pop } def /annotatepage { userdict /annotatepage 2 copy known {get exec} {pop pop} ifelse } def /XT { pop pop } def /discard { save /discardSave exch store discardDict begin /endString exch store gt38? { 2 add } if load stopped pop end discardSave restore } bind def userdict /discardDict 7 dict dup begin put /pre38Initialize { /endStringLength endString length store /newBuff buffer 0 endStringLength getinterval store /newBuffButFirst newBuff 1 endStringLength 1 sub getinterval store /newBuffLast newBuff endStringLength 1 sub 1 getinterval store } def /shiftBuffer { newBuff 0 newBuffButFirst putinterval newBuffLast 0 currentfile read not { stop } if put } def 0 { pre38Initialize mark currentfile newBuff readstring exch pop { { newBuff endString eq { cleartomark stop } if shiftBuffer } loop } { stop } ifelse } def 1 { pre38Initialize /beginString exch store mark currentfile newBuff readstring exch pop { { newBuff beginString eq { /layerCount dup load 1 add store } { newBuff endString eq { /layerCount dup load 1 sub store layerCount 0 eq { cleartomark stop } if } if } ifelse shiftBuffer } loop } if } def 2 { mark { currentfile buffer readline not { stop } if endString eq { cleartomark stop } if } loop } def 3 { /beginString exch store /layerCnt 1 store mark { currentfile buffer readline not { stop } if dup beginString eq { pop /layerCnt dup load 1 add store } { endString eq { layerCnt 1 eq { cleartomark stop } { /layerCnt dup load 1 sub store } ifelse } if } ifelse } loop } def end userdict /clipRenderOff 15 dict dup begin put { /n /N /s /S /f /F /b /B } { { _doClip 1 eq { /_doClip 0 ddef _eo {eoclip} {clip} ifelse } if newpath } def } forall /Tr /pop load def /Bb {} def /BB /pop load def /Bg {12 npop} def /Bm {6 npop} def /Bc /Bm load def /Bh {4 npop} def end /Lb { 4 npop 6 1 roll pop 4 1 roll pop pop pop 0 eq { 0 eq { (%AI5_BeginLayer) 1 (%AI5_EndLayer--) discard } { /clipForward? true def /Tx /pop load def /Tj /pop load def currentdict end clipRenderOff begin begin } ifelse } { 0 eq { save /discardSave exch store } if } ifelse } bind def /LB { discardSave dup null ne { restore } { pop clipForward? { currentdict end end begin /clipForward? false ddef } if } ifelse } bind def /Pb { pop pop 0 (%AI5_EndPalette) discard } bind def /Np { 0 (%AI5_End_NonPrinting--) discard } bind def /Ln /pop load def /Ap /pop load def /Ar { 72 exch div 0 dtransform dup mul exch dup mul add sqrt dup 1 lt { pop 1 } if setflat } def /Mb { q } def /Md { } def /MB { Q } def /nc 3 dict def nc begin /setgray { pop } bind def /setcmykcolor { 4 npop } bind def /setcustomcolor { 2 npop } bind def currentdict readonly pop end end setpacking %%EndResource %%BeginResource: procset Adobe_blend_AI5 1.4 0 %%Title: (Adobe Illustrator (R) Version 5.0 Blend ProcSet) %%Version: 1.4 0 %%CreationDate: (11/19/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) userdict /defaultpacking currentpacking put true setpacking userdict /Adobe_blend_AI5 70 dict dup begin put /bd { bind def } bind def /xs { exch store } bd /nullProc { { } } def /initialize { pop pop Adobe_blend_AI5 begin Adobe_blend_AI5_vars begin /_contoneDevice where { pop } { /_contoneDevice false def } ifelse /_dpiThreshold where { pop } { /_dpiThreshold 600 def } ifelse /_screenFreqThreshold where { pop } { /_screenFreqThreshold 150 def } ifelse /tRectOK? deviceDPI _dpiThreshold le currentScreenFreq _screenFreqThreshold le and _contoneDevice not and def /invertXfer { [ { 1 exch sub } /exec load systemdict/currenttransfer get exec /exec load ] cvx systemdict/settransfer get exec } bd /spotDict 3 dict dup begin /nSpots 2 def /spot1 7 dict def /spot2 7 dict def end def composite? { /_setgray_ /setgray load def /_fill_ /fill load def /_image_ /image load def } { /_setgray_ systemdict/setgray get def /_fill_ systemdict/fill get def /_image_ systemdict/image get def } ifelse } bd /terminate { currentdict Adobe_blend_AI5_vars eq { end currentdict Adobe_blend_AI5 eq { end } if } if } bd /_compositeSpotDevice where { begin _compositeSpotDevice 0 ne {userdict /composite? true put} if end } { /_compositeSpotDevice 0 def } ifelse /nullString () def /d255 256 array def 0 1 255 { d255 exch dup 255 div put } bind for /d255- 256 array def 0 1 255 { d255- exch 1 d255 2 index get sub put } bind for /dUserSpace matrix defaultmatrix def currentdict /Adobe_blend_AI5_vars 89 dict dup begin put { /f /F /s /S /b /B } { null def } bind forall /byte 1 string def /sSave null def /setSSave { save /sSave exch store } bind def /Bm null def /doBlend null def /startC? false def /endC? false def /fCMYK? null def /startTint 0 def /endTint 0 def /bSMatrix matrix def /bUMatrix matrix def /dMatrix matrix def /inLine? true def /pTState? false def /bHi? false def /yHi 0 def /xHi 0 def /noImg /lv1Fix where { pop lv1Fix } { false } ifelse def /ccAry1 5 array def /ccTint 0 def /spotColor? false def /colorimage? true def [ /tint1Data /tint2Data /spotDict /bAxis /ubAxis /pChange /optimize? /nSamples /sInc /blendProc /_bn /xBCInc /yBCInc /bInc /bRender /cBName /cBType /nColors /color? /blend? /colorType /cData /cDataLen /bDataLen /rampPoint /midPoint /endPoint /blendLength /blackData /yeData /mgData /cyData /cnt1 /ndx /_fill /tmp counttomark { null def } bind repeat pop currentdict end currentdict end exch begin begin /unitSq { 0 0 moveto 0 1 lineto 1 1 lineto 1 0 lineto closepath } bd /gMark { counttomark 2 add -1 roll } bd /setCustomColor { dup /ccTint exch store 1 exch sub 6 1 roll ccAry1 astore exch setcustomcolor } bd /currentCustomColor { ccAry1 aload pop ccTint } bd /nsetcustomcolor where { pop } { /nsetcustomcolor { pop setcmykcolor } bd } ifelse /nsetcustomcolorend where { pop } { /nsetcustomcolorend { } bd } ifelse /setBSpace { newpath bUMatrix astore concat unitSq } bd /setCStop { dup 0 eq { pop spotColor? { dup 1 exch sub /ccTint exch def ccAry1 4 /Black put } if setgray } { 1 eq { setcmykcolor } { composite? not colorType 2 lt and { forceCMYK } { setCustomColor } ifelse } ifelse } ifelse } bd /makeByte { /tmp 0 store 255 mul cvi 8 string 8 { dup tmp 3 index put /tmp tmp 1 add store } repeat exch pop } bd /setImgSpace { cDataLen 1 8 2 index 0 0 1 0 0 dMatrix astore } bd /bwImage { setImgSpace cData /_image_ load { exec } stopped { $error /errorname get /undefinedresult ne { stop } { pop pop pop pop pop } ifelse } if } bd level2? { /bFill { _fill } def /bCImg { /cDataLen bDataLen store setImgSpace setSSave expandSpot cyData mgData yeData cData expandCMYK true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd } if /expandOne { dup type /stringtype ne { cDataLen string exch dup 0 ne { 255 mul cvi 0 1 cDataLen 1 sub { 3 copy exch put pop } for } if pop } if } bd /expandSpot { spotColor? { spotDict begin spot1 begin tintImage type /nulltype ne { tintImage expandOne /tintImage exch def } if end spot2 begin tintImage type /nulltype ne { tintImage expandOne /tintImage exch def } if end end } if } bd /expandCMYK { 4 { expandOne 4 1 roll } repeat } bd /colorimage where dup { exch pop /ncolorimage where { pop } { /ncolorimage {pop colorimage} bd } ifelse } if not { /ncolorimage where { pop } { /colorimage? false store /ncolorimage { pop pop pop setSSave /blackData xs /yeData xs /mgData xs /cyData xs /cnt1 0 store [ byte dup 0 cyData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .3 /mul cvx } { .3 mul } ifelse mgData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .59 /mul cvx } { .59 mul } ifelse yeData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx .11 /mul cvx } { .11 mul } ifelse blackData dup type /stringtype eq { /cnt1 cvx /get cvx d255 /exch cvx /get cvx } if /add cvx /add cvx /add cvx 1 /exch cvx /sub cvx /dup cvx 0 /lt cvx { pop 0 } /if cvx /dup cvx 1 /gt cvx { pop 1 } /if cvx 255 /mul cvx /cvi cvx 256 /mod cvx /dup cvx 0 /lt cvx { pop 0 } /if cvx /put cvx /cnt1 dup cvx 1 /add cvx /store cvx ] cvx bind _image_ sSave restore } bd } ifelse } if level2? not { /bCImg { /cDataLen bDataLen store setImgSpace setSSave expandSpot cyData mgData yeData cData colorimage? { expandCMYK } if true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd /bwFill { setSSave /cDataLen 8 store /cData currentgray makeByte store bwImage sSave restore } bd /c1ImgFill { setSSave /cDataLen 8 store setImgSpace spotColor? { spotDict begin spot1 begin currentCustomColor makeByte /tintImage exch def /name exch def /spot_K exch def /spot_Y exch def /spot_M exch def /spot_C exch def end spot2 initSpotData end } if currentcmykcolor 4 { makeByte 4 1 roll } repeat true 4 spotDict { ncolorimage } stopped { $error /errorname get /undefinedresult ne { stop } { 10 { pop } repeat } ifelse } if sSave restore } bd /bFill noImg { { _fill } } { { color? { c1ImgFill } { bwFill } ifelse } } ifelse bd } if composite? { /bCFun { color? { cyData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if mgData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if yeData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if cData dup type /stringtype eq { /ndx cvx /get cvx d255 /exch cvx /get cvx } if spotColor? { spotDict begin /spotDict cvx /begin cvx spot1 begin tintImage dup type /stringtype eq { /ndx cvx /get cvx d255- /exch cvx /get cvx } { dup type /nulltype ne { name type /nametype ne {1 exch sub} if } if } ifelse end /spot1 cvx /tintValue 3 -1 /roll cvx /put cvx spot2 begin tintImage dup type /stringtype eq { /ndx cvx /get cvx d255- /exch cvx /get cvx } { dup type /nulltype ne { name type /nametype ne {1 exch sub} if } if } ifelse end /spot2 cvx /tintValue 3 -1 /roll cvx /put cvx /end cvx end /spotDict cvx /nsetcustomcolor cvx } { /setcmykcolor cvx } ifelse } { cData /ndx cvx /get cvx d255 /exch cvx /get cvx /setgray cvx } ifelse } bd /Bc { newpath gsave setBSpace nColors 1 eq { pop pop setCStop } if bFill grestore } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { linImg } { bFill } ifelse grestore nColors 1 gt { getRData } if } bd /rdBm { /nColors dup load 1 sub store _fill gsave bUMatrix astore concat bHi? { xHi yHi bUMatrix idtransform /yHi exch store /xHi exch store rampPoint 1 lt { 1 rampPoint sub dup xHi mul exch yHi mul translate } if } if nColors { 0 0 rampPoint 0 360 arc _fill blend? bHi? or { rdBlend } if nColors 1 gt { getRData } if /nColors dup load 1 sub store } repeat /nColors 1 store grestore } bd /cGetRData { setCStop /blend? cData type /stringtype eq dup not color? and { pop cyData type /stringtype eq mgData type /stringtype eq yeData type /stringtype eq or or } if store } def /cGetRData } if /eCStop { mark 1 index 3 mul 3 add dup 8 gt { pop 8 } if 1 roll cleartomark } bd composite? not { /knockOut level2? { { 0 0 0 0 setcmykcolor _fill } } { /bFill noImg { { _fill } } { { _of true eq { currentgray 1 ne { bwFill } if } { bwFill } ifelse } } ifelse def /whiteByte 1 makeByte def noImg { { 0 0 0 0 setcmykcolor _fill } } { { cBType 0 eq { setSSave /cData whiteByte store /cDataLen 8 store bwImage sSave restore } { _fill } ifelse } } ifelse } ifelse bd /bCFun { cData dup type /stringtype ne { color? { 1 exch sub } if } { /ndx cvx /get cvx color? customColor? not and { d255- } { d255 } ifelse /exch cvx /get cvx } ifelse /_setgray_ cvx } bd /eCCBlend { dup 3 eq { pop mark 7 1 roll 6 copy ccThrough? dup /blend? xs { /startC? true store setCustomColor customColor? { /cData tint1Data store setCDataLen } if /endC? 3 index 3 eq { 4 index 1 ne } { false } ifelse store } if cleartomark stop } if 1 eq { pop pop pop } if pop /startC? false store 6 { 8 index } repeat ccThrough? dup /blend? xs { /endC? true store blend? not { stop } if customColor? { /cData tint1Data store setCDataLen } if } if } bd /handleOP { _of not { knockOut } if } bd /handleROP { _of not { 0 0 0 0 setcmykcolor _fill } { newpath } ifelse } bd /rdBm { /nColors dup load 1 sub store blend? { _fill } { handleROP } ifelse gsave bUMatrix astore concat bHi? { xHi yHi bUMatrix idtransform /yHi exch store /xHi exch store rampPoint 1 lt { 1 rampPoint sub dup xHi mul exch yHi mul translate } if } if nColors { 0 0 rampPoint 0 360 arc blend? { cData type /stringtype ne bHi? not and { cData color? { 1 exch sub } if _setgray_ _fill_ } { cData type /stringtype ne { /cDataLen 1 store /bDataLen 1 store } if rdBlend } ifelse } { handleROP pTState? { /bAxis rampPoint endPoint sub store xHi bAxis mul yHi bAxis mul translate } if } ifelse nColors 1 gt { getRData } if /nColors dup load 1 sub store } repeat /nColors 1 store grestore } bd /ccThrough? { gsave pop 0 setCustomColor currentcmykcolor grestore anyColor? } bd /forceCMYK { exch pop 1 exch sub 5 1 roll 4 { 4 index mul 4 1 roll } repeat 0 cCMYKData dup /cData ne { dup /yeData eq { pop 1 add } { /mgData eq { 2 } { 3 } ifelse add } ifelse 0 } if pop index 0 eq { pop pop pop pop 0 0 0 0 } if setcmykcolor pop /fCMYK? true store } bd /endCapSepBc { pop pop dup 0 eq { pop setgray } { 1 eq { setcmykcolor } { colorType 1 eq { forceCMYK } { fCMYK? { forceCMYK } { setCustomColor } ifelse } ifelse } ifelse } ifelse currentcmykcolor anyColor? blend? and { bFill } { handleOP } ifelse } bd } if /cCMYKData 0 def composite? dup not { pop customColor? } if not { /cCMYKData /cyData /mgData /yeData /cData black? not { yellow? { exch } { magenta? { 3 } { 4 } ifelse -1 roll } ifelse } if 4 1 roll pop pop pop store /Bc { gsave setBSpace nColors 1 gt { blend? currentcmykcolor anyColor? and { bFill } { handleOP } ifelse } { endCapSepBc } ifelse grestore newpath } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { cCMYKData load dup type /stringtype eq { dup length /cDataLen xs /cData xs gsave colorType 0 ne noImg not and { invertXfer } if linImg grestore } { pop bFill } ifelse } { handleOP } ifelse grestore nColors 1 gt { getRData } if } bd /cmykGetRData { /fCMYK? false store blend? { { cmykDataProcs colorType get exec } stopped pop blend? { /cData cCMYKData load store setCDataLen } if } if } def /cmykDataProcs [ { pop black? dup /blend? xs { setgray 0 } if pop } { cCMYKData load dup type /stringtype ne { 0 0 0 cyan? not { 4 magenta? { 1 } { yellow? { 2 } { 3 } ifelse } ifelse roll } if 4 copy add add add 0 eq { /blend? false store } if setcmykcolor /startC? true store /endC? true store eCStop stop } if pop dup 0 eq { pop setgray } { 1 eq { setcmykcolor } { forceCMYK } ifelse } ifelse } bind /eCCBlend load { cBType 1 eq { tint1Data tint2Data /tint1Data xs /tint2Data xs } if 0 eq { black? { setgray } { 0 0 0 4 -1 roll 1 exch sub setcmykcolor } ifelse black? { /blend? true store } if 6 { 8 index } repeat ccThrough? { /blend? true store } { black? { /cData tint1Data store setCDataLen } { /blend? false store } ifelse } ifelse } { mark 7 1 roll 6 copy ccThrough? { forceCMYK pop stop } if 9 index 0 eq { black? dup /blend? xs { pop 1 setgray /cData tint2Data store setCDataLen 0 } if pop } { /blend? 6 { 16 index } repeat ccThrough? store blend? { forceCMYK } if } ifelse cleartomark } ifelse } bind ] def /cmykGetRData } if composite? dup not { pop isCMYKSep? } if not { /endCapSepBc { /white? false store pop pop dup 0 eq { pop /white? 1 index 1 eq store setgray } { 1 eq { setcmykcolor } { setCustomColor } ifelse } ifelse % currentcmykcolor anyColor? endC? or blend? and { bFill } { handleOP } ifelse } bd /Bc { gsave setBSpace nColors 1 gt { blend? startC? and { bFill } { handleOP } ifelse } { endCapSepBc } ifelse grestore newpath } bd /linealBm { /nColors dup load 1 sub store newpath gsave setBSpace blend? { cData type /stringtype eq { linImg } { bFill } ifelse } { handleOP } ifelse grestore nColors 1 gt { getRData } if } bd /discardCMY { counttomark 4 add -3 roll pop pop pop } bd /testTopCC { 6 copy ccThrough? } bd /getCRamp { { ccDataProcs colorType 2 sub get exec } stopped pop blend? cDataLen 0 eq and { /cDataLen bDataLen store } if } bd /ccGetRData { /fCMYK? false store /startC? false store /endC? false store colorType 2 lt { /blend? false def } if blend? { getCRamp } { setCStop } ifelse blend? { /blend? cData 1 ne store blend? { cData dup type /stringtype ne { 1 exch sub /cData xs 0 } if pop } if } if } def /ccDataProcs [ /eCCBlend load { cBType 1 eq { tint1Data tint2Data /tint1Data xs /tint2Data xs } if 0 eq { /blend? false store pop } { mark 7 1 roll testTopCC { /blend? 1 index 1 ne store /startC? blend? store /endC? false store blend? not { cleartomark stop } if /cData tint1Data store setCDataLen setCustomColor pop stop } if cleartomark } ifelse 2 index 0 eq { /blend? false store } { mark 6 { 9 index } repeat testTopCC dup /blend? xs { /blend? 1 index 1 ne store /endC? blend? store /startC? false store blend? not { cleartomark stop } if /cData tint2Data store setCDataLen } if cleartomark } ifelse } bind ] def /ccGetRData } if load Adobe_blend_AI5_vars /getData 3 -1 roll put /setCDataLen { /cDataLen 0 cData dup type /stringtype eq { length exch } if pop store } bd /initSpotData { begin /name null def /tintImage null def /tintValue null def /spot_C null def /spot_M null def /spot_Y null def /spot_K null def end } bd /getRData { /colorType gMark store _compositeSpotDevice 0 ne { spotDict begin spot1 initSpotData spot2 initSpotData end /spotColor? colorType 2 eq colorType 3 eq or def } { /spotColor? false store } ifelse /blend? true store 0 0 0 0 setcmykcolor 100 div /rampPoint xs % (between 13 and 87%) 100 div /midPoint xs dup 0 eq { 2 } { dup 1 eq { 5 } { _compositeSpotDevice 0 ne { spotDict begin spot1 begin /name 3 index def /spot_K 4 index def /spot_Y 5 index def /spot_M 6 index def /spot_C 7 index def end end } if 7 } ifelse } ifelse /tmp exch def tmp index 100 div /endPoint xs _compositeSpotDevice 0 ne { tmp 2 add index 3 eq { /tmp tmp 4 add def tmp index dup spotDict begin spot1/name get ne { spot2 begin /name exch def /spot_K tmp 2 add index def /spot_Y tmp 3 add index def /spot_M tmp 4 add index def /spot_C tmp 5 add index def end } { pop } ifelse end } if } if /color? colorType 0 gt store colorType 3 eq { /tint2Data gMark store } if colorType 2 ge { /tint1Data gMark store } if _compositeSpotDevice 0 ne { spotDict begin colorType 2 ge { colorType 3 eq { spot2 begin /tintImage cBType 0 eq {tint2Data} {tint1Data} ifelse def name null eq {/name /Black def} if end } if spot1 begin /tintImage cBType 0 eq colorType 2 eq or {tint1Data} {tint2Data} ifelse def colorType 2 eq { name null eq { /name spot2/name get def spot2/name null put } if } { name null eq {/name /Black def} if } ifelse end } if end } if /cData gMark store setCDataLen colorType 0 gt { counttomark 4 add -3 roll /yeData xs /mgData xs /cyData xs } if blend? { /bDataLen cDataLen dup 0 eq color? and { [ cyData mgData yeData ] { dup type /stringtype eq { length exch pop exit } if pop } forall } if store bDataLen 0 eq { /bDataLen 1 store } if getData blend? { composite? cDataLen 0 eq and { /cDataLen bDataLen store } if } if } { setCStop } ifelse } bd /Bg { 0 0 0 0 setcmykcolor 6 { pop } repeat /blendLength xs pop pop pop /cBName xs /bRender xs bRender 2 ne { composite? not { _of setoverprint } if _eo {eoclip} {clip} ifelse _bn cBName 2 copy known { get mark exch aload pop /cBType xs /nColors xs mark exch aload pop 0 0 } if pop pop getRData cBType 0 eq { /linealBm } { bHi? { /pTState? nColors 2 gt store } if /doBlend /rdBlend load store /rdBm } ifelse } { inLine? not { mark mark } if /Bc dup { cleartomark mark } bd /nullProc } ifelse load /Bm xs } bd /linImg noImg { { newpath doRctBlend } } { { /doBlend color? composite? and { /bCImg } { /bwImage } ifelse load store 0 0 moveto tRectOK? composite? and { { mark 0 1 dtransform atan cvi 90 mod 0 eq 1 0 dtransform atan cvi 90 mod 0 eq } stopped { cleartomark } { and exch pop { newpath doRctBlend } { doBlend } ifelse } ifelse } { doBlend } ifelse } } ifelse bd /doRctBlend { gsave /sInc 1 store /nSamples bDataLen store /bInc 1 bDataLen div store /ubAxis 1 0 dtransform dUserSpace idtransform dup mul exch dup mul add sqrt store /pChange ubAxis 0 eq { 0 } { bDataLen ubAxis div } ifelse store pChange .5 gt noImg not and dup /optimize? xs { /nSamples ubAxis 2 div round cvi dup 1 le { pop 2 } if store /bInc 1 nSamples div store /sInc bDataLen 1 sub nSamples 1 sub div store } if 0 nSamples [ /dup cvx optimize? { /round cvx /cvi cvx } if /ndx /exch cvx /store cvx bCFun /rectfill where dup { exch pop _compositeSpotDevice 1 ne and } if { 0 0 bInc 1 /rectfill cvx } { 0 0 /moveto cvx bInc 0 /lineto cvx bInc 1 /lineto cvx 0 1 /lineto cvx /closepath cvx /_fill_ cvx } ifelse bInc 0 /translate cvx sInc /add cvx ] cvx bind repeat pop spotColor? {nsetcustomcolorend} if grestore } bd /rdPrep { /nSamples bDataLen dup 0 eq { pop 1 } if store /sInc -1 store /bAxis rampPoint endPoint sub store /bInc bAxis bDataLen div neg store /optimize? false store tRectOK? { /ubAxis bAxis 0 dtransform dUserSpace idtransform dup mul exch dup mul add sqrt 0 bAxis dtransform dUserSpace idtransform dup mul exch dup mul add sqrt 2 copy lt { exch } if pop store /pChange ubAxis 0 eq { 0 } { bDataLen ubAxis div } ifelse store pChange .5 gt noImg not and dup /optimize? xs { /nSamples ubAxis 2 div round cvi dup 1 le { pop 2 } if store /bInc bAxis nSamples div neg store /sInc bDataLen 1 sub nSamples 1 sub div neg store } if } if bHi? { /xBCInc xHi bAxis mul nSamples div store /yBCInc yHi bAxis mul nSamples div store } if } bd /rdBlend { newpath gsave rdPrep rampPoint bDataLen 1 sub nSamples [ /dup cvx optimize? { /round cvx /cvi cvx } if /ndx /exch cvx /store cvx bCFun 0 0 3 /index cvx 0 360 /arc cvx /_fill_ cvx /exch cvx bInc /add cvx /exch cvx sInc /add cvx bHi? { xBCInc yBCInc /translate cvx } if ] cvx bind repeat pop pop spotColor? {nsetcustomcolorend} if grestore pTState? { xHi bAxis mul yHi bAxis mul translate } if } bd /Bh { pop pop /pTState? false store 2 copy 0 ne exch 0 ne or dup /bHi? xs { /yHi xs /xHi xs 0 0 } if pop pop } bd /BD { inLine? not { ] nColors cBType ] _bn cBName 3 -1 roll put end } if } bd /Bn { 1 add dict dup nullString null put /_bn xs } bd /Bd { Adobe_blend_AI5_vars begin 3 -1 roll dup nullString eq dup { setSSave } if /inLine? exch def /cBName exch def /nColors exch def /cBType exch def } bd /Bb { sSave null eq { Adobe_blend_AI5_vars begin setSSave } if composite? { /_fill /fill load store } { /__fill /fill load store /_fill { _of true eq { currentgray 1 ne { __fill } if } { __fill } ifelse } def } ifelse /fill { } def } bd /BB { /cBType xs cleartomark cleartomark cBType dup bRender sSave dup type /savetype eq { restore 0 } if pop currentdict Adobe_blend_AI5_vars eq { end } if 2 ne exch 0 gt and { 2 eq { s } { S } ifelse } { pop newpath } ifelse } bd currentdict readonly pop end end defaultpacking setpacking %%EndResource %%BeginResource: procset Adobe_pattern_AI5 1.1 0 %%Title: (Adobe Illustrator (R) Version 5.0 Pattern Operators) %%Version: 1.1 0 %%CreationDate: (03/26/93) () %%Copyright: ((C) 1987-1996 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_Illustrator_AI5 known not { userdict /Adobe_Illustrator_AI5 95 dict put } if userdict /Adobe_Illustrator_AI5 get begin /@ { } def /& { } def /dp { dup null eq { pop _dp 0 ne { 0 1 _dp 1 sub _dl mod { _da exch get 3 get } for _dp 1 sub _dl mod 1 add packedarray _da 0 get aload pop 8 -1 roll 5 -1 roll pop 4 1 roll definepattern pop } if } { _dp 0 ne _dp _dl mod 0 eq and { null dp } if 7 packedarray _da exch _dp _dl mod exch put _dp _dl mod _da 0 get 4 get 2 packedarray /_dp _dp 1 add def } ifelse } def /E { _ed begin dup 0 get type /arraytype ne { 0 { dup 1 add index type /arraytype eq { 1 add } { exit } ifelse } loop array astore } if /_dd exch def /_ury exch def /_urx exch def /_lly exch def /_llx exch def /_n exch def /_y 0 def /_dl 4 def /_dp 0 def /_da _dl array def 0 1 _dd length 1 sub { /_d exch _dd exch get def 0 2 _d length 2 sub { /_x exch def /_c _d _x get _ ne def /_r _d _x 1 add get cvlit def _r _ ne { _urx _llx sub _ury _lly sub [ 1 0 0 1 0 0 ] [ /save cvx _llx neg _lly neg /translate cvx _c { nc /begin cvx } if _r dup type /stringtype eq { cvx } { { exec } /forall cvx } ifelse _c { /end cvx } if /restore cvx ] cvx /_fn 12 _n length add string def _y _fn cvs pop /_y _y 1 add def _fn 12 _n putinterval _fn _c false dp _d exch _x 1 add exch put } if } for } for null dp _n _dd /_pd end xput } def /fc { _fm dup concatmatrix pop } def /p { /_fm exch ddef 9 -2 roll _pm translate fc 7 -2 roll _pm scale fc 5 -1 roll _pm rotate fc 4 -2 roll exch 0 ne { dup _pm rotate fc 1 -1 _pm scale fc neg _pm rotate fc } { pop } ifelse dup _pm rotate fc exch dup sin exch cos div 1 0 0 1 0 6 2 roll _pm astore fc neg _pm rotate fc _pd exch get /_fdd exch ddef /_pf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm patternfill } { pop fill } ifelse grestore pop } for pop } for restore newpath } ddef /_psf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm 9 copy 6 npop patternashow } { pop 6 copy 3 npop hvashow } ifelse grestore pop } for pop } for restore sw rmoveto } ddef /_pjsf { save /_doClip 0 ddef 0 1 _fdd length 1 sub { /_fd exch _fdd exch get ddef _fd 0 2 _fd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _fc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _fm 12 copy 6 npop patternawidthshow } { pop 9 copy 3 npop hvawidthshow } ifelse grestore pop } for pop } for restore swj rmoveto } ddef /_lp /none ddef } def /sc { _sm dup concatmatrix pop } def /P { /_sm exch ddef 9 -2 roll _pm translate sc 7 -2 roll _pm scale sc 5 -1 roll _pm rotate sc 4 -2 roll exch 0 ne { dup _pm rotate sc 1 -1 _pm scale sc neg _pm rotate sc } { pop } ifelse dup _pm rotate sc exch dup sin exch cos div 1 0 0 1 0 6 2 roll _pm astore sc neg _pm rotate sc _pd exch get /_sdd exch ddef /_ps { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm patternstroke } { pop stroke } ifelse grestore pop } for pop } for restore newpath } ddef /_pss { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm 10 copy 6 npop patternashowstroke } { pop 7 copy 3 npop ss } ifelse grestore pop } for pop } for restore pop sw rmoveto } ddef /_pjss { save /_doClip 0 ddef 0 1 _sdd length 1 sub { /_sd exch _sdd exch get ddef _sd 0 2 _sd length 2 sub { gsave 2 copy get dup _ ne { cvx exec _sc } { pop } ifelse 2 copy 1 add get dup _ ne { aload pop findfont _sm 13 copy 6 npop patternawidthshowstroke } { pop 10 copy 3 npop jss } ifelse grestore pop } for pop } for restore pop swj rmoveto } ddef /_lp /none ddef } def end userdict /Adobe_pattern_AI5 18 dict dup begin put /initialize { /definepattern where { pop } { begin begin Adobe_pattern_AI5 begin Adobe_pattern_AI5 { dup xcheck { bind } if pop pop } forall mark cachestatus 7 1 roll pop pop pop pop exch pop exch { { 10000 add dup 2 index gt { exit } if dup setcachelimit } loop } stopped cleartomark end end end Adobe_pattern_AI5 begin } ifelse } def /terminate { currentdict Adobe_pattern_AI5 eq { end } if } def errordict /nocurrentpoint { pop stop } put errordict /invalidaccess { pop stop } put /patternencoding 256 array def 0 1 255 { patternencoding exch ( ) 2 copy exch 0 exch put cvn put } for /definepattern { 17 dict begin /uniform exch def /cache exch def /key exch def /procarray exch def /mtx exch matrix invertmatrix def /height exch def /width exch def /ctm matrix currentmatrix def /ptm matrix def /str 32 string def /slice 9 dict def slice /s 1 put slice /q 256 procarray length div sqrt floor cvi put slice /b 0 put /FontBBox [ 0 0 0 0 ] def /FontMatrix mtx matrix copy def /Encoding patternencoding def /FontType 3 def /BuildChar { exch begin /setstrokeadjust where {pop true setstrokeadjust} if slice begin dup q dup mul mod s idiv /i exch def dup q dup mul mod s mod /j exch def q dup mul idiv procarray exch get /xl j width s div mul def /xg j 1 add width s div mul def /yl i height s div mul def /yg i 1 add height s div mul def uniform { 1 1 } { width 0 dtransform dup mul exch dup mul add sqrt dup 1 add exch div 0 height dtransform dup mul exch dup mul add sqrt dup 1 add exch div } ifelse width 0 cache { xl 4 index mul yl 4 index mul xg 6 index mul yg 6 index mul setcachedevice } { setcharwidth } ifelse gsave scale newpath xl yl moveto xg yl lineto xg yg lineto xl yg lineto closepath clip newpath end end exec grestore } def key currentdict definefont end } def /patterncachesize { gsave newpath 0 0 moveto width 0 lineto width height lineto 0 height lineto closepath patternmatrix setmatrix pathbbox exch ceiling 4 -1 roll floor sub 3 1 roll ceiling exch floor sub mul 1 add grestore } def /patterncachelimit { cachestatus 7 1 roll 6 npop 8 mul } def /patternpath { exch dup begin setfont ctm setmatrix concat slice exch /b exch slice /q get dup mul mul put FontMatrix concat uniform { width 0 dtransform round width div exch round width div exch 0 height dtransform round height div exch height div exch 0 0 transform round exch round exch ptm astore setmatrix } { ptm currentmatrix pop } ifelse { currentpoint } stopped not { 2 npop pathbbox true 4 index 3 index eq 4 index 3 index eq and { pop false { { 2 npop } { 3 npop true } { 7 npop true } { pop true } pathforall } stopped { 5 npop true } if } if { height div ceiling height mul 4 1 roll width div ceiling width mul 4 1 roll height div floor height mul 4 1 roll width div floor width mul 4 1 roll 2 index sub height div ceiling cvi exch 3 index sub width div ceiling cvi exch 4 2 roll moveto FontMatrix mtx invertmatrix dup dup 4 get exch 5 get rmoveto ptm ptm concatmatrix pop slice /s patterncachesize patterncachelimit div ceiling sqrt ceiling cvi dup slice /q get gt { pop slice /q get } if put 0 1 slice /s get dup mul 1 sub { slice /b get add gsave 0 1 str length 1 sub { str exch 2 index put } for pop dup { gsave ptm setmatrix 1 index str length idiv { str show } repeat 1 index str length mod str exch 0 exch getinterval show grestore 0 height rmoveto } repeat grestore } for 2 npop } { 4 npop } ifelse } if end } def /patternclip { _eo {eoclip} {clip} ifelse } def /patternstrokepath { strokepath } def /patternmatrix matrix def /patternfill { dup type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get } if gsave patternclip Adobe_pattern_AI5 /patternpath get exec grestore newpath } def /patternstroke { dup type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get } if gsave patternstrokepath true { { { newpath moveto } { lineto } { curveto } { closepath 3 copy Adobe_pattern_AI5 /patternfill get exec } pathforall 3 npop } stopped { 5 npop patternclip Adobe_pattern_AI5 /patternfill get exec } if } { patternclip Adobe_pattern_AI5 /patternfill get exec } ifelse grestore newpath } def /vpatternawidthshow { 6 1 roll /_hvay exch ddef /_hvax exch ddef /_hvwb exch ddef /_hvcy exch ddef /_hvcx exch ddef { dup cstring dup length 1 eq _charorientation 1 eq and { -90 rotate currentpoint _fontRotateAdjust add moveto gsave false charpath currentpoint 5 index 5 index 5 index Adobe_pattern_AI5 /patternfill get exec grestore _fontRotateAdjust sub moveto _hvwb eq { _hvcx _hvcy rmoveto } if _hvax _hvay rmoveto 90 rotate } { currentpoint _fontHeight sub _hvax sub 3 index _hvwb eq { _hvcx sub } if currentpoint exch 4 index stringwidth pop 2 div sub exch _fontAscent sub moveto gsave 2 index false charpath 6 index 6 index 6 index Adobe_pattern_AI5 /patternfill get exec grestore newpath moveto pop pop } ifelse } cforall 3 npop } def /hpatternawidthshow { { dup cstring exch gsave 3 index eq { 5 index 5 index rmoveto } if false charpath currentpoint 9 index 9 index 9 index Adobe_pattern_AI5 /patternfill get exec grestore newpath moveto 2 copy rmoveto } cforall 8 npop } def /patternashow { 0 0 0 6 3 roll patternawidthshow } def /patternawidthshow { 6 index type /dicttype eq { Adobe_pattern_AI5 /patternmatrix get 7 1 roll } if _lineorientation 0 eq { hpatternawidthshow } { vpatternawidthshow } ifelse } def /vpatternawidthshowstroke { 7 1 roll 6 1 roll /_hvay exch ddef /_hvax exch ddef /_hvwb exch ddef /_hvcy exch ddef /_hvcx exch ddef { dup cstring dup length 1 eq _charorientation 1 eq and { -90 rotate currentpoint _fontRotateAdjust add moveto gsave false charpath currentpoint 3 index setmatrix 6 index 6 index 6 index Adobe_pattern_AI5 /patternstroke get exec grestore _fontRotateAdjust sub moveto _hvwb eq { _hvcx _hvcy rmoveto } if _hvax _hvay rmoveto 90 rotate } { currentpoint _fontHeight sub _hvax sub 3 index _hvwb eq { _hvcx sub } if currentpoint exch 4 index stringwidth pop 2 div sub exch _fontAscent sub moveto gsave 2 index false charpath 4 index setmatrix 7 index 7 index 7 index Adobe_pattern_AI5 /patternstroke get exec grestore newpath moveto pop pop } ifelse } cforall 4 npop } def /hpatternawidthshowstroke { 7 1 roll { dup cstring exch gsave 3 index eq { 5 index 5 index rmoveto } if false charpath currentpoint 7 index setmatrix 10 index 10 index 10 index Adobe_pattern_AI5 /patternstroke get exec grestore newpath moveto 2 copy rmoveto } cforall 9 npop } def /patternashowstroke { 0 0 0 7 3 roll patternawidthshowstroke } def /patternawidthshowstroke { 7 index type /dicttype eq { patternmatrix /patternmatrix get 8 1 roll } if _lineorientation 0 eq { hpatternawidthshowstroke } { vpatternawidthshowstroke } ifelse } def end setpacking %%EndResource %%EndProlog %%BeginSetup Adobe_level2_AI5 /initialize get exec Adobe_screens_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_typography_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_blend_AI5 /initialize get exec Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5 Adobe_pattern_AI5 /initialize get exec Adobe_ColorImage_AI6 /initialize get exec Adobe_Illustrator_AI5 /initialize get exec [ 39/quotesingle 96/grave 130/quotesinglbase 131/florin 132/quotedblbase 133/ellipsis 134/dagger 135/daggerdbl 136/circumflex 137/perthousand 138/Scaron 139/guilsinglleft 140/OE 145/quoteleft 146/quoteright 147/quotedblleft 148/quotedblright 149/bullet 150/endash 151/emdash 152/tilde 153/trademark 154/scaron 155/guilsinglright 156/oe 157/dotlessi 159/Ydieresis 164/currency 166/brokenbar 168/dieresis 169/copyright 170/ordfeminine 172/logicalnot 174/registered 175/macron 176/ring 177/plusminus 178/twosuperior 179/threesuperior 180/acute 181/mu 183/periodcentered 184/cedilla 185/onesuperior 186/ordmasculine 188/onequarter 189/onehalf 190/threequarters 192/Agrave 193/Aacute 194/Acircumflex 195/Atilde 196/Adieresis 197/Aring 198/AE 199/Ccedilla 200/Egrave 201/Eacute 202/Ecircumflex 203/Edieresis 204/Igrave 205/Iacute 206/Icircumflex 207/Idieresis 208/Eth 209/Ntilde 210/Ograve 211/Oacute 212/Ocircumflex 213/Otilde 214/Odieresis 215/multiply 216/Oslash 217/Ugrave 218/Uacute 219/Ucircumflex 220/Udieresis 221/Yacute 222/Thorn 223/germandbls 224/agrave 225/aacute 226/acircumflex 227/atilde 228/adieresis 229/aring 230/ae 231/ccedilla 232/egrave 233/eacute 234/ecircumflex 235/edieresis 236/igrave 237/iacute 238/icircumflex 239/idieresis 240/eth 241/ntilde 242/ograve 243/oacute 244/ocircumflex 245/otilde 246/odieresis 247/divide 248/oslash 249/ugrave 250/uacute 251/ucircumflex 252/udieresis 253/yacute 254/thorn 255/ydieresis TE %AI3_BeginEncoding: _Helvetica Helvetica [ /_Helvetica/Helvetica 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-Bold Helvetica-Bold [ /_Helvetica-Bold/Helvetica-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-Oblique Helvetica-Oblique [ /_Helvetica-Oblique/Helvetica-Oblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Helvetica-BoldOblique Helvetica-BoldOblique [ /_Helvetica-BoldOblique/Helvetica-BoldOblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Roman Times-Roman [ /_Times-Roman/Times-Roman 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Bold Times-Bold [ /_Times-Bold/Times-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-Italic Times-Italic [ /_Times-Italic/Times-Italic 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Times-BoldItalic Times-BoldItalic [ /_Times-BoldItalic/Times-BoldItalic 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier Courier [ /_Courier/Courier 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-Bold Courier-Bold [ /_Courier-Bold/Courier-Bold 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-Oblique Courier-Oblique [ /_Courier-Oblique/Courier-Oblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Courier-BoldOblique Courier-BoldOblique [ /_Courier-BoldOblique/Courier-BoldOblique 0 0 1 TZ %AI3_EndEncoding AdobeType %AI3_BeginEncoding: _Symbol Symbol [ /_Symbol/Symbol 0 0 1 TZ %AI3_EndEncoding AdobeType %%EndSetup 1 XR u 0.000 0.000 0.000 0.247 k [] 0 d 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 85.5000 129.7500 m 92.2500 137.2500 L 92.2500 150.7500 L 85.5000 144.0000 L 85.5000 129.7500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 0.7500 144.0000 m 85.5000 144.0000 L 92.2500 150.7500 L 8.2500 150.7500 L 0.7500 144.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 0.7500 129.7500 m 85.5000 129.7500 L 85.5000 144.0000 L 0.7500 144.0000 L 0.7500 129.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 3.0000 135.0000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (url_type = urLsip\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 85.5000 116.2500 m 92.2500 123.0000 L 92.2500 137.2500 L 85.5000 129.7500 L 85.5000 116.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 0.7500 116.2500 m 85.5000 116.2500 L 85.5000 129.7500 L 0.7500 129.7500 L 0.7500 116.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 3.0000 120.7500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (url_scheme\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 85.5000 102.0000 m 92.2500 108.7500 L 92.2500 123.0000 L 85.5000 116.2500 L 85.5000 102.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 0.7500 102.0000 m 85.5000 102.0000 L 85.5000 116.2500 L 0.7500 116.2500 L 0.7500 102.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 3.0000 106.5000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (url_user\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 85.5000 87.7500 m 92.2500 95.2500 L 92.2500 108.7500 L 85.5000 102.0000 L 85.5000 87.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 0.7500 87.7500 m 85.5000 87.7500 L 85.5000 102.0000 L 0.7500 102.0000 L 0.7500 87.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 3.0000 92.2500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (url_password\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 85.5000 74.2500 m 92.2500 81.0000 L 92.2500 95.2500 L 85.5000 87.7500 L 85.5000 74.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 0.7500 74.2500 m 85.5000 74.2500 L 85.5000 87.7500 L 0.7500 87.7500 L 0.7500 74.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 3.0000 78.7500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (url_host\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 85.5000 60.0000 m 92.2500 66.7500 L 92.2500 81.0000 L 85.5000 74.2500 L 85.5000 60.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 0.7500 60.0000 m 85.5000 60.0000 L 85.5000 74.2500 L 0.7500 74.2500 L 0.7500 60.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 3.0000 64.5000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (url_port\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 85.5000 45.7500 m 92.2500 53.2500 L 92.2500 66.7500 L 85.5000 60.0000 L 85.5000 45.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 0.7500 45.7500 m 85.5000 45.7500 L 85.5000 60.0000 L 0.7500 60.0000 L 0.7500 45.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 3.0000 50.2500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (url_path\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 85.5000 31.5000 m 92.2500 39.0000 L 92.2500 53.2500 L 85.5000 45.7500 L 85.5000 31.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 0.7500 31.5000 m 85.5000 31.5000 L 85.5000 45.7500 L 0.7500 45.7500 L 0.7500 31.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 3.0000 36.7500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (url_params\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 85.5000 18.0000 m 92.2500 24.7500 L 92.2500 39.0000 L 85.5000 31.5000 L 85.5000 18.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 0.7500 18.0000 m 85.5000 18.0000 L 85.5000 31.5000 L 0.7500 31.5000 L 0.7500 18.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 3.0000 22.5000 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (url_headers\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 85.5000 3.7500 m 92.2500 10.5000 L 92.2500 24.7500 L 85.5000 18.0000 L 85.5000 3.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 0.7500 3.7500 m 85.5000 3.7500 L 85.5000 18.0000 L 0.7500 18.0000 L 0.7500 3.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 3.0000 8.2500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (url_fragment\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 435.7500 158.2500 m 443.2500 165.0000 L 443.2500 179.2500 L 435.7500 172.5000 L 435.7500 158.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 113.2500 172.5000 m 435.7500 172.5000 L 443.2500 179.2500 L 120.0000 179.2500 L 113.2500 172.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 113.2500 158.2500 m 435.7500 158.2500 L 435.7500 172.5000 L 113.2500 172.5000 L 113.2500 158.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 116.2500 162.7500 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sip:joe:secret@example.com:5060;user=ip?subject=Click-to-dial\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 131.2500 116.2500 m 138.7500 123.0000 L 138.7500 137.2500 L 131.2500 129.7500 L 131.2500 116.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 113.2500 129.7500 m 131.2500 129.7500 L 138.7500 137.2500 L 120.0000 137.2500 L 113.2500 129.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 113.2500 116.2500 m 131.2500 116.2500 L 131.2500 129.7500 L 113.2500 129.7500 L 113.2500 116.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 114.7500 120.7500 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (sip\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 150.7500 102.0000 m 157.5000 108.7500 L 157.5000 123.0000 L 150.7500 116.2500 L 150.7500 102.0000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 132.7500 116.2500 m 150.7500 116.2500 L 157.5000 123.0000 L 140.2500 123.0000 L 132.7500 116.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 132.7500 102.0000 m 150.7500 102.0000 L 150.7500 116.2500 L 132.7500 116.2500 L 132.7500 102.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 134.2500 106.5000 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (joe\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 185.2500 87.7500 m 192.0000 95.2500 L 192.0000 108.7500 L 185.2500 102.0000 L 185.2500 87.7500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 152.2500 102.0000 m 185.2500 102.0000 L 192.0000 108.7500 L 159.7500 108.7500 L 152.2500 102.0000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 152.2500 87.7500 m 185.2500 87.7500 L 185.2500 102.0000 L 152.2500 102.0000 L 152.2500 87.7500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 153.0000 92.2500 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (secret\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 253.5000 74.2500 m 260.2500 81.0000 L 260.2500 95.2500 L 253.5000 87.7500 L 253.5000 74.2500 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 186.0000 87.7500 m 253.5000 87.7500 L 260.2500 95.2500 L 193.5000 95.2500 L 186.0000 87.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 186.0000 74.2500 m 253.5000 74.2500 L 253.5000 87.7500 L 186.0000 87.7500 L 186.0000 74.2500 L B U 0 To 1.0000 0.0000 0.0000 1.0000 191.2500 78.7500 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (example.com\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 287.2500 60.0000 m 294.0000 66.7500 L 294.0000 81.0000 L 287.2500 74.2500 L 287.2500 60.0000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 253.5000 74.2500 m 287.2500 74.2500 L 294.0000 81.0000 L 260.2500 81.0000 L 253.5000 74.2500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 253.5000 60.0000 m 287.2500 60.0000 L 287.2500 74.2500 L 253.5000 74.2500 L 253.5000 60.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 260.2500 64.5000 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (5060\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 332.2500 31.5000 m 339.0000 39.0000 L 339.0000 53.2500 L 332.2500 45.7500 L 332.2500 31.5000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 287.2500 45.7500 m 332.2500 45.7500 L 339.0000 53.2500 L 294.0000 53.2500 L 287.2500 45.7500 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 287.2500 31.5000 m 332.2500 31.5000 L 332.2500 45.7500 L 287.2500 45.7500 L 287.2500 31.5000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 291.7500 36.7500 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (user=ip\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 0.247 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 435.7500 18.0000 m 443.2500 24.7500 L 443.2500 39.0000 L 435.7500 31.5000 L 435.7500 18.0000 L B U u 0.000 0.000 0.000 0.247 k 0.000 0.000 0.000 1.000 K 330.7500 31.5000 m 435.7500 31.5000 L 443.2500 39.0000 L 337.5000 39.0000 L 330.7500 31.5000 L B U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 330.7500 18.0000 m 435.7500 18.0000 L 435.7500 31.5000 L 330.7500 31.5000 L 330.7500 18.0000 L B U 0 To 1.0000 0.0000 0.0000 1.0000 339.0000 27.0000 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (subject=Click-to-\r) Tx TO 0.000 0.000 0.000 1.000 K 0 To 1.0000 0.0000 0.0000 1.0000 372.7500 18.0000 0 Tp TP /_Courier 7.2500 Tf 0.0000 Tc 0 Tr 0.000 0.000 0.000 1.000 K 0.000 0.000 0.000 1.000 k (dial\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 1.000 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 76.5000 123.0000 m 76.5000 123.7500 L 76.5000 124.5000 L 75.7500 124.5000 L 75.7500 125.2500 L 75.0000 125.2500 L 74.2500 125.2500 L 73.5000 125.2500 L 73.5000 124.5000 L 72.7500 124.5000 L 72.7500 123.7500 L 72.7500 123.0000 L 72.7500 122.2500 L 72.7500 122.2500 L 73.5000 121.5000 L 73.5000 121.5000 L 74.2500 120.7500 L 75.0000 120.7500 L 75.7500 121.5000 L 75.7500 121.5000 L 76.5000 122.2500 L 76.5000 122.2500 L 76.5000 123.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 108.0000 126.0000 m 113.2500 123.0000 L 108.0000 120.0000 L 108.0000 126.0000 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 248.2500 150.7500 m 248.2500 116.2500 L 234.0000 116.2500 L 261.7500 102.0000 L 290.2500 116.2500 L 276.0000 116.2500 L 276.0000 150.7500 L 248.2500 150.7500 L F U u 0.000 0.000 0.000 1.000 k 76.5000 108.7500 m 76.5000 109.5000 L 76.5000 110.2500 L 75.7500 110.2500 L 75.7500 111.0000 L 75.0000 111.0000 L 74.2500 111.0000 L 73.5000 111.0000 L 73.5000 110.2500 L 72.7500 110.2500 L 72.7500 109.5000 L 72.7500 108.7500 L 72.7500 108.7500 L 72.7500 108.0000 L 73.5000 107.2500 L 73.5000 107.2500 L 74.2500 107.2500 L 75.0000 107.2500 L 75.7500 107.2500 L 75.7500 107.2500 L 76.5000 108.0000 L 76.5000 108.7500 L 76.5000 108.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 127.5000 111.7500 m 132.7500 108.7500 L 127.5000 106.5000 L 127.5000 111.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 76.5000 95.2500 m 76.5000 95.2500 L 76.5000 96.0000 L 75.7500 96.7500 L 75.7500 96.7500 L 75.0000 96.7500 L 74.2500 96.7500 L 73.5000 96.7500 L 73.5000 96.7500 L 72.7500 96.0000 L 72.7500 95.2500 L 72.7500 95.2500 L 72.7500 94.5000 L 72.7500 93.7500 L 73.5000 93.7500 L 73.5000 93.0000 L 74.2500 93.0000 L 75.0000 93.0000 L 75.7500 93.0000 L 75.7500 93.7500 L 76.5000 93.7500 L 76.5000 94.5000 L 76.5000 95.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 147.0000 97.5000 m 152.2500 95.2500 L 147.0000 92.2500 L 147.0000 97.5000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 76.5000 81.0000 m 76.5000 81.7500 L 76.5000 81.7500 L 75.7500 82.5000 L 75.7500 82.5000 L 75.0000 83.2500 L 74.2500 83.2500 L 73.5000 82.5000 L 73.5000 82.5000 L 72.7500 81.7500 L 72.7500 81.7500 L 72.7500 81.0000 L 72.7500 80.2500 L 72.7500 79.5000 L 73.5000 79.5000 L 73.5000 78.7500 L 74.2500 78.7500 L 75.0000 78.7500 L 75.7500 78.7500 L 75.7500 79.5000 L 76.5000 79.5000 L 76.5000 80.2500 L 76.5000 81.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 180.7500 84.0000 m 186.0000 81.0000 L 180.7500 78.0000 L 180.7500 84.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 76.5000 66.7500 m 76.5000 67.5000 L 76.5000 68.2500 L 75.7500 68.2500 L 75.7500 69.0000 L 75.0000 69.0000 L 74.2500 69.0000 L 73.5000 69.0000 L 73.5000 68.2500 L 72.7500 68.2500 L 72.7500 67.5000 L 72.7500 66.7500 L 72.7500 66.0000 L 72.7500 66.0000 L 73.5000 65.2500 L 73.5000 65.2500 L 74.2500 65.2500 L 75.0000 65.2500 L 75.7500 65.2500 L 75.7500 65.2500 L 76.5000 66.0000 L 76.5000 66.0000 L 76.5000 66.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 248.2500 69.7500 m 253.5000 66.7500 L 248.2500 64.5000 L 248.2500 69.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 76.5000 39.0000 m 76.5000 39.7500 L 76.5000 39.7500 L 75.7500 40.5000 L 75.7500 40.5000 L 75.0000 41.2500 L 74.2500 41.2500 L 73.5000 40.5000 L 73.5000 40.5000 L 72.7500 39.7500 L 72.7500 39.7500 L 72.7500 39.0000 L 72.7500 38.2500 L 72.7500 37.5000 L 73.5000 37.5000 L 73.5000 36.7500 L 74.2500 36.7500 L 75.0000 36.7500 L 75.7500 36.7500 L 75.7500 37.5000 L 76.5000 37.5000 L 76.5000 38.2500 L 76.5000 39.0000 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 282.0000 41.2500 m 287.2500 39.0000 L 282.0000 36.0000 L 282.0000 41.2500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 76.5000 24.7500 m 76.5000 25.5000 L 76.5000 26.2500 L 75.7500 26.2500 L 75.7500 27.0000 L 75.0000 27.0000 L 74.2500 27.0000 L 73.5000 27.0000 L 73.5000 26.2500 L 72.7500 26.2500 L 72.7500 25.5000 L 72.7500 24.7500 L 72.7500 24.0000 L 72.7500 24.0000 L 73.5000 23.2500 L 73.5000 23.2500 L 74.2500 22.5000 L 75.0000 22.5000 L 75.7500 23.2500 L 75.7500 23.2500 L 76.5000 24.0000 L 76.5000 24.0000 L 76.5000 24.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 325.5000 27.7500 m 330.7500 24.7500 L 325.5000 21.7500 L 325.5000 27.7500 L F U u 0.000 0.000 0.000 1.000 k 0.000 0.000 0.000 1.000 K 76.5000 53.2500 m 75.7500 52.5000 L 75.7500 51.7500 L 75.7500 51.7500 L 75.0000 51.7500 L 75.0000 51.7500 L 74.2500 51.7500 L 74.2500 51.7500 L 73.5000 51.7500 L 73.5000 51.7500 L 73.5000 52.5000 L 73.5000 53.2500 L 73.5000 53.2500 L 73.5000 54.0000 L 73.5000 54.0000 L 74.2500 54.0000 L 74.2500 54.7500 L 75.0000 54.7500 L 75.0000 54.0000 L 75.7500 54.0000 L 75.7500 54.0000 L 75.7500 53.2500 L 76.5000 53.2500 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 98.2500 47.2500 m 120.0000 47.2500 L 120.0000 58.5000 L 98.2500 58.5000 L 98.2500 47.2500 L F U 0 To 1.0000 0.0000 0.0000 1.0000 99.7500 50.2500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (NULL\r) Tx TO 0.000 0.000 0.000 1.000 K u 0.000 0.000 0.000 1.000 k 0.7500 w 0.000 0.000 0.000 1.000 K 1 j 76.5000 10.5000 m 75.7500 10.5000 L 75.7500 9.7500 L 75.7500 9.7500 L 75.0000 9.7500 L 75.0000 9.0000 L 74.2500 9.0000 L 74.2500 9.7500 L 73.5000 9.7500 L 73.5000 9.7500 L 73.5000 10.5000 L 73.5000 10.5000 L 73.5000 11.2500 L 73.5000 11.2500 L 73.5000 12.0000 L 74.2500 12.0000 L 74.2500 12.0000 L 75.0000 12.0000 L 75.0000 12.0000 L 75.7500 12.0000 L 75.7500 11.2500 L 75.7500 11.2500 L 76.5000 10.5000 L F U u 0.000 0.000 0.000 0.000 k 0.000 0.000 0.000 1.000 K 98.2500 5.2500 m 120.0000 5.2500 L 120.0000 16.5000 L 98.2500 16.5000 L 98.2500 5.2500 L F U 0 To 1.0000 0.0000 0.0000 1.0000 99.7500 8.2500 0 Tp TP /_Helvetica 7.2500 Tf 0.0000 Tc 0 Tr 0.0000 w 0.000 0.000 0.000 1.000 K 0 j 0.000 0.000 0.000 1.000 k (NULL\r) Tx TO 0.000 0.000 0.000 1.000 K %%PageTrailer gsave annotatepage grestore showpage %%Trailer Adobe_Illustrator_AI5 /terminate get exec Adobe_pattern_AI5 /terminate get exec Adobe_blend_AI5 /terminate get exec Adobe_ColorImage_AI6 /terminate get exec Adobe_typography_AI5 /terminate get exec Adobe_screens_AI5 /terminate get exec Adobe_level2_AI5 /terminate get exec %%EOF II*V<(@nn}}""++33<A'0vQTxhw`iiQyչ Zjzڸ%;k5zkIkK,<{ uM8=GMm'mVll~^Ȍξ[^CLï/~lCW -|5nxfm`@D*M *"!jɥ43jڜQ B/r4bYПDiX[Fni33I<Yc̢5,%cHPaʅ˓\esruLº|dl$+_\]55ȉ'N͙,(>$:u Ӡ[ GL{qڵ$%qbIV<\n4UYmRt̶VwZԢk#k?JvD2MT`cw9H!T!RӜyR ~zc xwa2:!Dbh"Fm'`F¢ZJ.dN .GFb%#X)HwI"e*?4!j:bf~-Xlx mBfzԕ Ǟ[{Jh.9c.h>(m~8vܥVeJ yz.Ŗp&јVbQz%U}QavzauzTrZeCfYH pzRT*mQkm#6`q2͐/֊kK*pbvj-|T7W'o~ ?wgљ Z{/b{$Gh (e$ (kcwvDq[axE-CN8a׀HTU9f"(M$qw(aVg!RREl&]se7EwL6\e6;C^vx"‚tZVC,'q7T~\rwqc5Ds[5?K̗^1)x/A Q~QƆOZ'`xqMw+BaBgw]5؇QRw0XW^mR8XYX(88?2уB"/hcfi;(5TGaW؂'W=4='6j7Iwx>Ȅ0WWRsRGMdWKXk _%eB'f7\K]݈.8D щX^2Dx W[x^C6؎}is(cdvwcVaz!c5C'wpŘr-)"Iqs6VK8\,wg^{n$c5/u#>;6x'(<4+$0"%Plah8d1x!qY8ɇ*J@—}J27  j g/ȉ7h!HEZiUi9.y)3#|Tb77NaO4Iirsy/hc I7z4{dOI;6m+=)8f4Oט:Qz#{`MGI疋k EfsFjIc1Z5f "}e :iDhVVLG]AxA/ Oר}(*й%U8{!2@`[@9Gm$y|8|֝QPʼn8r\7Z b)YY^dE$>H {Qu꘵qݣKbxHЧ. `SW6w4x%醧N2U*6}evmnEG'JovVLvpLl츥rw9ڞrN ڥO,c~xJz3;Z9*7;Ί7ל{UrbsJ ϖ)\F=._m2(}pIwxvyʧtHꙘڋ@ʦ%֬ Izt .J!;cr Y(أ fémn$bzu{SSxwJi|a$)dPF>67R4&Ԫ;@V )Q`y#츫Cg8-jNIli&v[iV1;e۷~VIܢlnZ{2׸);{ UfARbAksF*+7銺~b: l8K򶴥XIɗ'XSrL 7Q4i+@Lk_znȇxºy_@5[zAk4sɰ\S\N W,%~y|=%}s*e |)JE [F= zP&fAe/J#L¼fn5S4U46còf:уABf\ILT;sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/run-tests000077500000000000000000000023571223300710500222460ustar00rootroot00000000000000#! /bin/sh # # Run the parser tests # # usage: run-tests [test_program] [test-case...] # # -------------------------------------------------------------------- # # This file is part of the Sofia-SIP package # # Copyright (C) 2005 Nokia Corporation. # # Contact: Pekka Pessi # # 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 # # -------------------------------------------------------------------- # msg_test="${1:-./msg_test}" shift rc=0 for n in "$@"; do if "$msg_test" < "$n" > /dev/null ; then true else echo "$n: ERROR"; rc=1 fi done exit $rcsofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/run_test_date000077500000000000000000000000661223300710500231350ustar00rootroot00000000000000#!/bin/sh ./test_date "Sun, 18 Mar 2001 23:01:00 GMT" sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/run_test_sip_msg000077500000000000000000000047571223300710500236740ustar00rootroot00000000000000#! /bin/sh # # Run the parser tests # # usage: env srcdir=dir run_sip_test_msg # # -------------------------------------------------------------------- # # This file is part of the Sofia-SIP package # # Copyright (C) 2005 Nokia Corporation. # # Contact: Pekka Pessi # # 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 # # -------------------------------------------------------------------- # rc=0 if test ! -d "${srcdir:=.}/tests" then echo Please set environment variable srcdir exit 77 fi test=./test_sip_msg # These are messages that the parser should pass good="-t test1.txt test2.txt test3.txt test4.txt -u test5.txt -t test6.txt test7.txt -u test8.txt -t test9.txt test14.txt test20.txt test23.txt test24.txt test31.txt own1.txt own2.txt own3.txt own4.txt own5.txt own6.txt" # These are messages that the parser should fail bad="test10.txt test11.txt test12.txt test13.txt test15.txt test16.txt test17.txt test18.txt test19.txt test21.txt test22.txt test26.txt test29.txt test33.txt test35.txt test40.txt" # These are ugly messages that parser should pass ugly="-t test25.txt -u test27.txt test28.txt -t test30.txt -u test32.txt test34.txt -t test36.txt -u test37.txt test38.txt test39.txt test41.txt test42.txt" # These are messages that parser should pass, but it does not goodish="" # These are messages that parser should not pass, but it does baddish="" flag=-t for n in $good $ugly; do if test $n = -t ; then flag=$n elif test $n = -u ; then flag= elif "$test" $flag < "$srcdir/tests/$n" > /dev/null ; then echo "PASS: $n" else echo "ERROR: $n"; rc=1 fi done for n in $bad; do if "$test" -t < "$srcdir/tests/$n" > /dev/null 2>/dev/null ; then echo "ERROR: $n (no error detected)"; rc=1 else echo "PASS: $n" fi done exit $rc sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sip.docs000066400000000000000000000552021223300710500220160ustar00rootroot00000000000000/* -*- c -*- */ /**@MODULEPAGE "sip" - SIP Parser Module * * @section sip_meta Module Meta Information * * The Sofia @b sip module contains interface to the SIP parser and the * header and message objects. * * @CONTACT Pekka Pessi * * @STATUS @SofiaSIP Core library * * @LICENSE LGPL * * @section sip_overview Overview * * The structure of each header is defined in @b . In addition to the * header structure, there is defined a @em header @em class structure and * some standard functions for each header in the include file @b * . For header @c X, there are types, functions, * macros and header class declared in and * . See @ref sip_header_x for detailed description * of these header-specific boilerplate declarations. * * In addition to this interface, the @ref sip_parser "SIP parser documentation" * contains description of the functionality required when a parser is * extended by a new header. It is possible to add new headers to the SIP * parser or extend the definition of existing ones. * * @section sip_parser_intro Parsing SIP Messages * * Sofia SIP parser follows @em recursive-descent principle. In other words, * it is a program that descends the SIP syntax tree top-down recursively. * (All syntax trees have root at top and they grow downwards.) * * In the case of SIP such a parser is very efficient. The parser can choose * between different forms based on each token, as SIP syntax is carefully * designed so that it requires only minimal scan-ahead. It is also easy to * extend a recursive-descent parser via a standard API, unlike, for * instance, a LALR parser generated by @em Bison. * * The abstract message module @b msg contains a high-level parser engine * that drives the parsing process and invokes the SIP parser for each * header. As there are no framing between SIP messages, the parser * considers any received data, be it a UDP datagram or a TCP stream, as a * @em message @em stream, which may consist of one or more SIP messages. * The parser works by first separating stream into fragments, then building * a complete message based on parsing result. After a message is completed, * it can be given to the message stream customer (typically a protocol * state machine). The parser continues processing the stream and feeding * the messages to protocol engine until the end of the stream is reached. * * For each message, the parser starts by separating the first fragment, * which is either a request or status line. After the first line has been * processed, the parser engine continues by separating the headers * one-by-one from the message. After the parser encounters an empty line * separating the headers and the message body (payload), it invokes a * function parsing the separator and payload fragment(s). When the message * is complete, the parser can hand the message over to the protocol engine. * Then it is ready to start again with first fragment of the next message. * * @image html sip-parser.gif Separating byte stream to messages * @image latex sip-parser.eps Separating byte stream to messages * * When the parsing process has completed, the request or status line, each * header, separator and the payload are all in their own fragment * structure. The fragments form a dual-linked list known as @e fragment @e * chain as shown in the above figure. The buffers for the message, the * fragment chain, and a whole other stuff is held by the generic message * type, #msg_t, defined in . The internal structure of #msg_t is * known only within @b msg module and it is hidden from other modules. * * The abstract message module @b msg also drives the reverse process, * invoking the encoding method of each fragment so that the whole outgoing * SIP message is encoded properly. * * @section sip_header_struct SIP Header as a C struct * * Just separating headers from each other and from the message body is not * usually enough. When a header contains structured data, the header * contents should be converted to a form that is convenient to use from C * programs. For that purpose, the message parser needs a special function * for each individual header. The header-specific parsing function divides * the contents of the header into semantically meaningful segments and * stores the result in a header-specific structure. * * The parser passes the fragment contents to a parsing function immediately * after it has separated a fragment from the message. The parsing function * is defined by the @e header @e class. The header class is either * determined by the fragment position (first line, separator line or * payload), or it is found from the hash table using the header name as * key. There is also a special header class for @e unknown headers, headers * with a name that is not regocnized by the parser. * * For instance, the @From header has following syntax: * * @code * from = ("From" | "f") ":" * ( name-addr | addr-spec ) *( ";" addr-params ) * name-addr = [ display-name ] "<" addr-spec ">" * addr-spec = SIP-URL | URI * display-name = *token | quoted-string * addr-params = *( tag-param | generic-param ) * tag-param = "tag" "=" ( token | quoted-string ) * @endcode * * When a @From header is parsed, the header parser function sip_from_d() * separates the @e display-name, @e addr-spec and each parameter in the @e * addr-params list. The parsing result is assigned to a #sip_from_t * structure, which is defined as follows: * * @code * typedef struct sip_addr_s { * sip_common_t a_common[1]; * sip_unknown_t *a_next; * char const *a_display; * url_t a_url[1]; * sip_param_t const *a_params; * char const *a_tag; * } sip_from_t; * @endcode * * The string containing the @e display-name is put into the @c a_display * field, the URL contents can be found in the @c a_url field, and the list * of @e addr-params parameters is put in the @c a_params array. If there * is a @e tag-param present, a pointer to the parameter value is assigned * to @c a_tag field. * * @section sip_msg_struct SIP Message as a C struct * * It is not enough to represent a SIP message as a collection of headers * following each other. The programmer also needs a convenient way to * access certain headers at the SIP message level, for example, accessing * directly the @From header instead of going through all headers and * examining their name. The structured view to the SIP message is provided * via a C struct with type #sip_t. * * In other words, a single message is represented by two types, first type * (#msg_t) is private to the msg module and inaccessable by an application * programmer, second (#sip_t) is a public structure containing the parsed * headers. * * The #sip_t structure is defined as follows: * @code * typedef struct sip_s { * msg_common_t sip_common[1]; // Used with recursive inclusion * msg_pub_t *sip_next; // Ditto * void *sip_user; // Application data * unsigned sip_size; * int sip_flags; * * sip_error_t *sip_error; // Erroneous headers * * sip_request_t *sip_request; // Request line * sip_status_t *sip_status; // Status line * * sip_via_t *sip_via; // @Via (v) * sip_route_t *sip_route; // @Route * sip_record_route_t *sip_record_route; // @RecordRoute * sip_max_forwards_t *sip_max_forwards; // @MaxForwards * ... * } sip_t; * @endcode * * As you can see above, the public #sip_t structure contains the common * header members that are also found in the beginning of a header * structure. The @e sip_size indicates the size of the structure - the * application can extend the parser and #sip_t structure beyond the * original size. The @e sip_flags contains various flags used during the * parsing and printing process. They are documented in the . These * boilerplate members are followed by the pointers to various message * elements and headers. * * @note Within the @b msg module, the public structure is known as * #msg_pub_t. The application programmer can cast a #msg_t pointer to * #sip_t with sip_object() function (or macro). * * * @section sip_parsing_example Result of Parsing Process * * Let us now show how a simple message is parsed and presented to the * applications. As an exampe, we choose a BYE message with only the * mandatory fields included: * @code * BYE sip:joe@example.com SIP/2.0 * Via: SIP/2.0/UDP sip.example.edu;branch=d7f2e89c.74a72681 * Via: SIP/2.0/UDP pc104.example.edu:1030;maddr=110.213.33.19 * From: Bobby Brown ;tag=77241a86 * To: Joe User ;tag=7c6276c1 * Call-ID: 4c4e911b@pc104.example.edu * CSeq: 2 * @endcode * * The figure below shows the layout of the BYE message above after parsing: * * @image html sip-parser2.gif BYE message and its representation in C * @image latex sip-parser2.eps BYE message and its representation in C * * The leftmost box represents the message of type #msg_t. Next box from * the left reprents the #sip_t structure, which contains pointers to a * header objects. The next column contains the header objects. There is * one header object for each message fragment. The rightmost box represents * the I/O buffer used when the message was received. Note that the I/O * buffer may be non-continous and composed of many separate memory areas. * * The message object has link to the public message structure (@a * m_object), to the dual-linked fragment chain (@a m_frags) and to the I/O * buffer (@a m_buffer). The public message header structure contains * pointers to the headers according to their type. If there are multiple * headers of the same type (like there are two @Via headers in the above * message), the headers are put into a single-linked list. * * Each fragment has pointers to successing and preceding fragment. It also * contains pointer to the corresponding data within the I/O buffer and its * length. * * The main purpose of the fragment chain is to preserve the original order * of the headers. If there were an third @Via header after @CSeq in the * message, the fragment representing it would be after the @CSeq header in * the fragment chain but after the second @Via in the header list. * */ /**@defgroup sip_headers SIP Headers * * SIP headers and other SIP message elements. * * For each SIP header recognized by the SIP module, there is a header * structure containing the parsed value. The header structure name is * generated from the header name by lowercasing the name, replacing the * non-alphanumeric characters (usually just minus "-") with underscore "_" * characters, and then adding prefix @c sip_ and suffix @c _t. For * instance, the contents of header "MIME-Version" is stored in a structure * called sip_mime_version_t. * */ /**@ingroup sip_headers * @defgroup sip_header_x SIP Header X - Conventions * * For a SIP header X, there are types, functions, macros and global data * declared in and as * follows: * - #sip_X_t is the structure used to store parsed header, * - SIP_X_INIT() initializes a static instance of #sip_X_t, * - sip_X_init() initializes a dynamic instance of #sip_X_t, * - sip_is_X() tests if header object is instance of header X, * - sip_X_make() creates a header X object by decoding given string, * - sip_X_format() creates a header X object by decoding given * printf() list, * - sip_X_dup() duplicates (deeply copies) the header X, * - sip_X_copy() copies the header X, * - #msg_hclass_t #sip_X_class[] contains the @em header @em class * for header X. * * All header structures contain the common part, a #sip_common_t structure * (@a X_common[]), a link to the next header in list (@a X_next), and * various fields describing the header value (in this case, @a X_value). * The header structure looks like this: * @code * typedef struct sip_X_s * { * struct msg_common_s { * msg_header_t *h_succ; // Pointer to succeeding fragment * msg_header_t **h_prev; // Pointer to preceeding fragment * msg_hclass_t *h_class; // Header class * void const *h_data; // Encoded data * usize_t h_len; // Encoding length (including CRLF) * } X_common[1]; * sip_X_t *X_next; // Link to next X header field * uint32_t X_value; // Value of X * msg_param_t *X_param; // List of parameters * } sip_X_t; * @endcode * * The common structure #msg_common_t (aka #sip_common_t) * can be considered as a base class for all * headers. The structure contains the pointers for dual-linked * fragment chain (@a h_succ, @a h_prev), a pointer to header class (@a * h_class), a pointer to the text encoding of header contents (@a h_data) * and the length of the encoding (@a h_len). (@a X_common is an array of size * 1, as it makes it easy to cast a header pointer to a pointer to * msg_common_t.) * * The @a X_next is a pointer to another header (usually a pointer to * structure of same type). If there are multiple headers with same name, * like the two "Via" headers in the example above, the @a X_next is used to * link the second header to the first. The fragment chain cannot be used * for this purpose as the headers with same name are not necessarily * adjacent in the parsed message. * * The rest of the fields contain the parsed or decoded representation of * the header. In this case, it is a 32-bit integer followed by a list of * parameters. The content of parameters is not parsed, they are just * separated from each other and then stored in an dynamically allocated * array of string pointers. Pointer to the array is stored to @a X_params. * * For more complex header structures, see #sip_contact_t or #sip_rack_t. * * @{ */ /**The structure #sip_X_t contains representation of a SIP * @ref sip_header_x "X" header. * * The #sip_X_t is defined as follows: * @code * typedef struct sip_X_s { * msg_common_t X_common[1]; // Common fragment info * sip_X_t *X_next; // Link to next X header field * uint32_t X_value; // Value of X * msg_param_t *X_param; // List of parameters * } sip_X_t; * @endcode */ typedef struct sip_X_s sip_X_t; /**@var msg_hclass_t sip_X_class[]; * @brief Header class for SIP X. * * The header class sip_X_class defines how a SIP * X is parsed and printed. It also * contains methods used by SIP parser and other functions * to manipulate the sip_X_t header structure. * */ SIP_DLL extern msg_hclass_t sip_X_class[]; enum { /** Hash of X. @internal */ sip_X_hash = hash }; /** Parse a X. @internal */ msg_parse_f sip_X_d; /** Print a X. @internal */ msg_print_f sip_X_e; /**Initializer for structure sip_X_t. * * A static sip_X_t structure must be initialized * with the SIP_X_INIT() macro. For instance, * @code * * sip_X_t sip_X = SIP_X_INIT; * * @endcode * @HI */ #define SIP_X_INIT() SIP_HDR_INIT(X) /**Initialize a structure sip_X_t. * * An sip_X_t structure can be initialized with the * sip_X_init() function/macro. For instance, * @code * * sip_X_t sip_X; * * sip_X_init(&sip_X); * * @endcode * @HI */ #if SU_HAVE_INLINE su_inline sip_X_t *sip_X_init(sip_X_t x[1]) { return SIP_HEADER_INIT(x, sip_X_class, sizeof(sip_X_t)); } #else #define sip_X_init(x) \ SIP_HEADER_INIT(x, sip_X_class, sizeof(sip_X_t)) #endif /**Test if header object is instance of sip_X_t. * * The function sip_is_X() returns true (nonzero) if * the header class is an instance of X * object and false (zero) otherwise. * * @param header pointer to the header structure to be tested * * @return * The function sip_is_X() returns true (nonzero) if * the header object is an instance of header X and * false (zero) otherwise. */ #if SU_HAVE_INLINE su_inline int sip_is_X(sip_header_t const *header) { return header && header->sh_class->hc_id == sip_hdr_X; } #else int sip_is_X(sip_header_t const *header); #endif #define sip_X_p(h) sip_is_X((h)) /**Duplicate (deep copy) @c sip_X_t. * * The function sip_X_dup() duplicates a header * structure @a hdr. If the header structure @a hdr * contains a reference (@c hdr->x_next) to a list of * headers, all the headers in the list are duplicated, too. * * @param home memory home used to allocate new structure * @param hdr header structure to be duplicated * * When duplicating, all parameter lists and non-constant * strings attached to the header are copied, too. The * function uses given memory @a home to allocate all the * memory areas used to copy the header. * * @par Example * @code * * X = sip_X_dup(home, sip->sip_X); * * @endcode * * @return * The function sip_X_dup() returns a pointer to the * newly duplicated sip_X_t header structure, or NULL * upon an error. */ sip_X_t *sip_X_dup(su_home_t *home, sip_X_t const *hdr); /**Copy a sip_X_t header structure. * * The function sip_X_copy() copies a header structure @a * hdr. If the header structure @a hdr contains a reference (@c * hdr->h_next) to a list of headers, all the headers in that * list are copied, too. The function uses given memory @a home * to allocate all the memory areas used to copy the header * structure @a hdr. * * @param home memory home used to allocate new structure * @param hdr pointer to the header structure to be duplicated * * When copying, only the header structure and parameter lists * attached to it are duplicated. The new header structure * retains all the references to the strings within the old @a * header, including the encoding of the old header, if present. * * @par Example * @code * * X = sip_X_copy(home, sip->sip_X); * * @endcode * * @return * The function sip_X_copy() returns a pointer to * newly copied header structure, or NULL upon an error. */ sip_X_t *sip_X_copy(su_home_t *home, sip_X_t const *hdr); /**Make a header structure sip_X_t. * * The function sip_X_make() makes a new * sip_X_t header structure. It allocates a new * header structure, and decodes the string @a s as the * value of the structure. * * @param home memory home used to allocate new header structure. * @param s string to be decoded as value of the new header structure * * @note This function is usually implemented as a macro calling * sip_header_make(). * * @return * The function sip_X_make() returns a pointer to * newly maked sip_X_t header structure, or NULL upon * an error. */ #if SU_HAVE_INLINE su_inline sip_X_t *sip_X_make(su_home_t *home, char const *s) { return sip_header_make(home, sip_X_class, s)->sh_X; } #else sip_X_t *sip_X_make(su_home_t *home, char const *s); #endif /**Make a X from formatting result. * * The function sip_X_format() makes a new * X object using formatting result as its * value. The function first prints the arguments according to * the format @a fmt specified. Then it allocates a new header * structure, and uses the formatting result as the header * value. * * @param home memory home used to allocate new header structure. * @param fmt string used as a printf()-style format * @param ... argument list for format * * @note This function is usually implemented as a macro calling * msg_header_format(). * * @return * The function sip_X_format() returns a pointer to newly * makes header structure, or NULL upon an error. * * @HIDE */ #if SU_HAVE_INLINE su_inline #endif sip_X_t *sip_X_format(su_home_t *home, char const *fmt, ...) __attribute__((format (printf, 2, 3))); #if SU_HAVE_INLINE su_inline sip_X_t *sip_X_format(su_home_t *home, char const *fmt, ...) { sip_header_t *h; va_list ap; va_start(ap, fmt); h = sip_header_vformat(home, sip_X_class, fmt, ap); va_end(ap); return h->sh_X; } #endif /**Decode a header X. * * The function sip_X_d() decodes value of the header X in the preallocated * header structure @a h. The string @a s to be decoded should not contain * the header name or colon. The decoding function also expects that the * leading and trailing whitespace has been removed from the string @a s. * * @param home memory home used to allocate new header structure. * @param h sip_X_t header structure * @param s string to be decoded * @param bsiz length of string @a s * * @return * The function sip_X_d() returns non-negative value when successful, or * -1 upon an error. */ int sip_X_d(su_home_t *home, sip_header_t *h, char *s, int bsiz); /**Encode a header X. * * The function sip_X_e() encodes a header structure @a h to the given * buffer @a buf. Even if the given buffer @a buf is NULL or its size @a * bufsiz is too small to fit the encoding result, the function returns the * number of characters required for the encoding. * * @param buf buffer to store the encoding result * @param bsiz size of the encoding buffer * @param h header to be encoded. * @param flags flags controlling the encoding * * @note * The encoding buffer size @b must be @b bigger than, not equal to, * the actual encoding result. * * @return * The function sip_X_e() returns the number of characters required for the * encoding. * */ int sip_X_e(char buf[], int bsiz, sip_header_t const *h, int flags); /** @} */ /**@defgroup sip_status_codes SIP Status Codes and Reason Phrases * * The macros and variables for the standard SIP status codes and reason * phrases are defined in . */ /**@defgroup sip_tag SIP Tags * * SIP headers in tag item lists and tagged argument lists. * * The include file defines tags and tag items for including SIP * headers in tag item lists or tagged argument lists. For each header, * there is a tag for pointer to header object and an another tag for string * containing header value. For example, @From header has tags * SIPTAG_FROM() and SIPTAG_FROM_STR(). * * It is also possible to include user-defined headers or non-standard * headers using SIPTAG_HEADER_STR(). * * A function taking SIP headers as arguments could be called like this: * @code * sip_payload_t *payload; * ... * sip_add_tl(msg, sip, * SIPTAG_CONTENT_TYPE_STR("text/plain"), * SIPTAG_USER_AGENT(agent->user_agent), * SIPTAG_PAYLOAD(payload), * SIPTAG_HEADER_STR("X-Header: contents\nP-Header: bar"), * TAG_END()); * ... * @endcode * * In the above fragment, the function sip_add_tl() will add @ContentType * and @UserAgent headers along with message payload to the SIP message. * The @ContentType header is made with value "text/plain". * */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sip.doxyaliases000066400000000000000000000076401223300710500234160ustar00rootroot00000000000000ALIASES += \ "AcceptContact=@ref sip_accept_contact \"Accept-Contact\"" \ "AcceptEncoding=@ref sip_accept_encoding \"Accept-Encoding\"" \ "AcceptLanguage=@ref sip_accept_language \"Accept-Language\"" \ "Accept=@ref sip_accept \"Accept\"" \ "AllowEvents=@ref sip_allow_events \"Allow-Events\"" \ "Allow=@ref sip_allow \"Allow\"" \ "AuthenticationInfo=@ref sip_authentication_info \"Authentication-Info\"" \ "Authorization=@ref sip_authorization \"Authorization\"" \ "CSeq=@ref sip_cseq \"CSeq\"" \ "CallID=@ref sip_call_id \"Call-ID\"" \ "CallInfo=@ref sip_call_info \"Call-Info\"" \ "Contact=@ref sip_contact \"Contact\"" \ "ContentDisposition=@ref sip_content_disposition \"Content-Disposition\"" \ "ContentEncoding=@ref sip_content_encoding \"Content-Encoding\"" \ "ContentLanguage=@ref sip_content_language \"Content-Language\"" \ "ContentLength=@ref sip_content_length \"Content-Length\"" \ "ContentType=@ref sip_content_type \"Content-Type\"" \ "Date=@ref sip_date \"Date\"" \ "ErrorInfo=@ref sip_error_info \"Error-Info\"" \ "Event=@ref sip_event \"Event\"" \ "Expires=@ref sip_expires \"Expires\"" \ "From=@ref sip_from \"From\"" \ "InReplyTo=@ref sip_in_reply_to \"In-Reply-To\"" \ "MIMEVersion=@ref sip_mime_version \"MIME-Version\"" \ "MaxForwards=@ref sip_max_forwards \"Max-Forwards\"" \ "MinExpires=@ref sip_min_expires \"Min-Expires\"" \ "MinSE=@ref sip_min_se \"Min-SE\"" \ "Organization=@ref sip_organization \"Organization\"" \ "Path=@ref sip_path \"Path\"" \ "Priority=@ref sip_priority \"Priority\"" \ "Privacy=@ref sip_privacy \"Privacy\"" \ "ProxyAuthenticate=@ref sip_proxy_authenticate \"Proxy-Authenticate\"" \ "ProxyAuthenticationInfo=@ref sip_proxy_authentication_info \"Proxy-Authentication-Info\"" \ "ProxyAuthorization=@ref sip_proxy_authorization \"Proxy-Authorization\"" \ "ProxyRequire=@ref sip_proxy_require \"Proxy-Require\"" \ "RAck=@ref sip_rack \"RAck\"" \ "RSeq=@ref sip_rseq \"RSeq\"" \ "Reason=@ref sip_reason \"Reason\"" \ "RecordRoute=@ref sip_record_route \"Record-Route\"" \ "ReferTo=@ref sip_refer_to \"Refer-To\"" \ "ReferredBy=@ref sip_referred_by \"Referred-By\"" \ "RejectContact=@ref sip_reject_contact \"Reject-Contact\"" \ "RemotePartyId=@ref sip_remote_party_id \"Remote-Party-Id\"" \ "Replaces=@ref sip_replaces \"Replaces\"" \ "RequestDisposition=@ref sip_request_disposition \"Request-Disposition\"" \ "Require=@ref sip_require \"Require\"" \ "RetryAfter=@ref sip_retry_after \"Retry-After\"" \ "Route=@ref sip_route \"Route\"" \ "SIPETag=@ref sip_etag \"SIP-ETag\"" \ "SIPIfMatch=@ref sip_if_match \"SIP-If-Match\"" \ "SecurityClient=@ref sip_security_client \"Security-Client\"" \ "SecurityServer=@ref sip_security_server \"Security-Server\"" \ "SecurityVerify=@ref sip_security_verify \"Security-Verify\"" \ "Server=@ref sip_server \"Server\"" \ "ServiceRoute=@ref sip_service_route \"Service-Route\"" \ "SessionExpires=@ref sip_session_expires \"Session-Expires\"" \ "Subject=@ref sip_subject \"Subject\"" \ "SubscriptionState=@ref sip_subscription_state \"Subscription-State\"" \ "Supported=@ref sip_supported \"Supported\"" \ "Timestamp=@ref sip_timestamp \"Timestamp\"" \ "To=@ref sip_to \"To\"" \ "Unsupported=@ref sip_unsupported \"Unsupported\"" \ "UserAgent=@ref sip_user_agent \"User-Agent\"" \ "Via=@ref sip_via \"Via\"" \ "WWWAuthenticate=@ref sip_www_authenticate \"WWW-Authenticate\"" \ "Warning=@ref sip_warning \"Warning\"" \ "ReferSub=@ref sip_refer_sub \"Refer-Sub\"" \ "AlertInfo=@ref sip_alert_info \"Alert-Info\"" \ "ReplyTo=@ref sip_reply_to \"Reply-To\"" \ "SuppressBodyIfMatch=@ref sip_suppress_body_if_match \"Suppress-Body-If-Match\"" \ "SuppressNotifyIfMatch=@ref sip_suppress_notify_if_match \"Suppress-Notify-If-Match\"" \ "RemotePartyID=@ref sip_remote_party_id \"Remote-Party-ID\"" \ "PAssertedIdentity=@ref sip_p_asserted_identity \"P-Asserted-Identity\"" \ "PPreferredIdentity=@ref sip_p_preferred_identity \"P-Preferred-Identity\"" \ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sip_bad_mask000066400000000000000000000045071223300710500227120ustar00rootroot00000000000000# # nta has an error mask specifying which headers cause nta to automatically # return 400 Bad Message if a critical header or pseudoheader in a request # has a parsing error. # # The parsing error can be later checked with msg_extract_errors(), too. # # See for definition of mask values. # # The error flags for a particular header can be set when header is added # with msg_mclass_insert_header_flags(). # # The flags of existing headers can be modified, if a copy of message class # is first made with msg_mclass_clone(). # # # When updating this file, please update # NTATAG_BAD_RESP_MASK()/NTATAG_BAD_REQ_MASK() documentation, too. # # # Headers that must be valid for all requests # request = sip_mask_request | sip_mask_response status = sip_mask_request | sip_mask_response From = sip_mask_request | sip_mask_response To = sip_mask_request | sip_mask_response CSeq = sip_mask_request | sip_mask_response Call-ID = sip_mask_request | sip_mask_response Content-Length = sip_mask_request | sip_mask_response Via = sip_mask_request | sip_mask_response # # User-Agent headers # Content-Type = sip_mask_ua Content-Disposition = sip_mask_ua Content-Encoding = sip_mask_ua # # Proxy heades # Route = sip_mask_proxy Max-Forwards = sip_mask_proxy Proxy-Require = sip_mask_proxy Proxy-Authorization = sip_mask_proxy # # Registrar headers # Min-Expires = sip_mask_registrar Authorization = sip_mask_registrar Path = sip_mask_registrar # # Headers that must be valid in UA, proxy or registrar # Contact = sip_mask_ua | sip_mask_proxy | sip_mask_registrar Require = sip_mask_ua | sip_mask_registrar | sip_mask_timer Record-Route = sip_mask_ua | sip_mask_proxy Expires = sip_mask_registrar | sip_mask_events # Nothing bad can happen if something looks like it is not Supported # Supported = sip_mask_ua | sip_mask_proxy | sip_mask_registrar # # 100rel headers # RAck = sip_mask_100rel RSeq = sip_mask_100rel # # Event headers # Event = sip_mask_events Subscription-State = sip_mask_events # # 'timer' headers # Session-Expires = sip_mask_timer Min-SE = sip_mask_timer # # Privacy headers # Privacy = sip_mask_privacy # # Headers used in caller preferences # Request-Disposition = sip_mask_pref Accept-Contact = sip_mask_pref Reject-Contact = sip_mask_pref # # PUBLISH headers (NOTE: No SIP- here!) # Etag = sip_mask_publish If-Match = sip_mask_publish sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sip_basic.c000066400000000000000000002307421223300710500224550ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE sip_basic.c * @brief Basic SIP headers. * * Implementation of header classes for basic SIP headers, like request and * status lines, payload, @CallID, @CSeq, @Contact, @ContentLength, @Date, * @Expires, @From, @Route, @RecordRoute, @To, and @Via. * * @author Pekka Pessi . * * @date Created: Tue Jun 13 02:57:51 2000 ppessi */ #include "config.h" /* Avoid casting sip_t to msg_pub_t and sip_header_t to msg_header_t */ #define MSG_PUB_T struct sip_s #define MSG_HDR_T union sip_header_u #include #include #include "sofia-sip/sip_parser.h" #include #include #include #include #include #include #include #include #include #include /* ====================================================================== */ /**@SIP_HEADER sip_request Request Line * * The request line is first line in a SIP request message. Its syntax defined * in @RFC3261 as follows: * * @code * Request-Line = Method SP Request-URI SP SIP-Version CRLF * Request-URI = SIP-URI / SIPS-URI / absoluteURI * absoluteURI = scheme ":" ( hier-part / opaque-part ) * hier-part = ( net-path / abs-path ) [ "?" query ] * net-path = "//" authority [ abs-path ] * abs-path = "/" path-segments * opaque-part = uric-no-slash *uric * uric = reserved / unreserved / escaped * uric-no-slash = unreserved / escaped / ";" / "?" / ":" / "@" * / "&" / "=" / "+" / "$" / "," * path-segments = segment *( "/" segment ) * segment = *pchar *( ";" param ) * param = *pchar * pchar = unreserved / escaped / * ":" / "@" / "&" / "=" / "+" / "$" / "," * scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) * authority = srvr / reg-name * srvr = [ [ userinfo "@" ] hostport ] * reg-name = 1*( unreserved / escaped / "$" / "," * / ";" / ":" / "@" / "&" / "=" / "+" ) * query = *uric * SIP-Version = "SIP" "/" 1*DIGIT "." 1*DIGIT * @endcode * * The parsed request-line is stored in #sip_request_t structure. */ /**@ingroup sip_request * @typedef typedef struct sip_request_s sip_request_t; * * The structure #sip_request_t contains representation of SIP request line. * * The #sip_request_t is defined as follows: * @code * typedef struct sip_request_s { * sip_common_t rq_common[1]; // Common fragment info * sip_unknown_t *rq_next; // Link to next (dummy) * sip_method_t rq_method; // Method enum * char const *rq_method_name; // Method name * url_t rq_url[1]; // RequestURI * char const *rq_version; // Protocol version * } sip_request_t; * @endcode */ #define sip_request_insert msg_request_insert static msg_xtra_f sip_request_dup_xtra; static msg_dup_f sip_request_dup_one; #define sip_request_update NULL msg_hclass_t sip_request_class[] = SIP_HEADER_CLASS(request, NULL, "", rq_common, single_critical, request); /**Parse @ref sip_request "request line" from a a SIP message. */ issize_t sip_request_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_request_t *rq = (sip_request_t *)h; char *uri, *version; if (msg_firstline_d(s, &uri, &version) < 0 || !uri || !version || (rq->rq_method = sip_method_d(&s, &rq->rq_method_name)) < 0 || *s || url_d(rq->rq_url, uri) < 0 || sip_version_d(&version, &rq->rq_version) < 0 || *version) return -1; return 0; } /**Encode @ref sip_request "request line" of a a SIP message. */ issize_t sip_request_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { sip_request_t const *rq = (sip_request_t *)h; return snprintf(b, bsiz, "%s " URL_FORMAT_STRING " %s" CRLF, rq->rq_method_name, URL_PRINT_ARGS(rq->rq_url), rq->rq_version); } isize_t sip_request_dup_xtra(sip_header_t const *h, isize_t offset) { sip_request_t const *rq = (sip_request_t *)h; offset += url_xtra(rq->rq_url); if (!rq->rq_method) offset += MSG_STRING_SIZE(rq->rq_method_name); offset += sip_version_xtra(rq->rq_version); return offset; } /** Duplicate one request header. */ char *sip_request_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { sip_request_t *rq = (sip_request_t *)dst; sip_request_t const *o = (sip_request_t *)src; char *end = b + xtra; URL_DUP(b, end, rq->rq_url, o->rq_url); if (!(rq->rq_method = o->rq_method)) MSG_STRING_DUP(b, rq->rq_method_name, o->rq_method_name); else rq->rq_method_name = o->rq_method_name; sip_version_dup(&b, &rq->rq_version, o->rq_version); assert(b <= end); return b; } /**@ingroup sip_request * * Create a @ref sip_request "request line" object. * * Create a request line object with * method enum @a method, method name @a name, request URI @a uri, and * protocol version @a version. The memory for the header object is * allocated from the memory home @a home. * * @param home memory home used to allocate #sip_request_t object * @param method method enum * @param name method name (required if method is not well-known) * @param uri request URI * @param version version string (defaults to "SIP/2.0" if NULL) * * @par Example * The following code fragment creates an OPTIONS request object: * @code * sip_request_t *rq; * rq = sip_request_create(home, SIP_METHOD_OPTIONS, requestURI, NULL); * @endcode * @note * If you provide an non-NULL @a version string, it is not copied. The * version string @b MUST remain constant. */ sip_request_t *sip_request_create(su_home_t *home, sip_method_t method, char const *name, url_string_t const *uri, char const *version) { size_t xtra; sip_request_t *rq; if (method) name = sip_method_name(method, name); if (!name) return NULL; if (!method) method = sip_method_code(name); xtra = url_xtra(uri->us_url) + (method ? 0 : strlen(name) + 1); rq = (sip_request_t *)sip_header_alloc(home, sip_request_class, xtra); if (rq) { char *b = (char *)(rq + 1), *end = b + xtra; rq->rq_method = method; rq->rq_method_name = name; if (!method) MSG_STRING_DUP(b, rq->rq_method_name, name); URL_DUP(b, end, rq->rq_url, uri->us_url); rq->rq_version = version ? version : SIP_VERSION_CURRENT; assert(b == end); } return rq; } /* ====================================================================== */ /**@SIP_HEADER sip_status Status Line * * The status line is first line in a response message. It is defined in * @RFC3261 as follows: * * @code * Status-Line = SIP-Version SP Status-Code SP Reason-Phrase CRLF * Status-Code = Informational * / Redirection * / Success * / Client-Error * / Server-Error * / Global-Failure * / extension-code * extension-code = 3DIGIT * Reason-Phrase = *(reserved / unreserved / escaped * / UTF8-NONASCII / UTF8-CONT / SP / HTAB) * @endcode * * The parsed status line is stored in #sip_status_t structure. */ /**@ingroup sip_status * @typedef typedef struct sip_status_s sip_status_t; * * The structure #sip_status_t contains representation of SIP * @ref sip_status "status line". * * The #sip_status_t is defined as follows: * @code * typedef struct sip_status_s { * sip_common_t st_common[1]; // Common fragment info * sip_unknown_t *st_next; // Link to next (dummy) * char const *st_version; // Protocol version * int st_status; // Status code * char const *st_phrase; // Status phrase * } sip_status_t; * @endcode */ static msg_xtra_f sip_status_dup_xtra; static msg_dup_f sip_status_dup_one; #define sip_status_insert msg_status_insert #define sip_status_update NULL msg_hclass_t sip_status_class[] = SIP_HEADER_CLASS(status, NULL, "", st_common, single_critical, status); /** Parse status line */ issize_t sip_status_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_status_t *st = (sip_status_t *)h; char *status, *phrase; unsigned long code; if (msg_firstline_d(s, &status, &phrase) < 0 || sip_version_d(&s, &st->st_version) < 0 || *s || (code = strtoul(status, &status, 10)) >= INT_MAX || *status) return -1; st->st_status = code; st->st_phrase = phrase; return 0; } issize_t sip_status_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { sip_status_t const *st = (sip_status_t *)h; int status; assert(sip_is_status(h)); status = st->st_status; if (status > 999 || status < 100) status = 0; return snprintf(b, bsiz, "%s %03u %s" CRLF, st->st_version, status, st->st_phrase); } /** Extra size of a #sip_status_t object. */ isize_t sip_status_dup_xtra(sip_header_t const *h, isize_t offset) { sip_status_t const *st = (sip_status_t *)h; offset += sip_version_xtra(st->st_version); offset += MSG_STRING_SIZE(st->st_phrase); return offset; } /** Duplicate one status header. */ char *sip_status_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { sip_status_t *st = (sip_status_t *)dst; sip_status_t const *o = (sip_status_t *)src; char *end = b + xtra; sip_version_dup(&b, &st->st_version, o->st_version); st->st_status = o->st_status; MSG_STRING_DUP(b, st->st_phrase, o->st_phrase); assert(b <= end); (void)end; return b; } /**@ingroup sip_status * * Create a @ref sip_status "status line" object. * * @param home memory home used to allocate #sip_status_t object * @param status status code (in range 100 - 699) * @param phrase status phrase (may be NULL) * @param version version string (defaults to "SIP/2.0" if NULL) * * @note * If you provide an non-NULL @a version string, it is not copied. The * string @b MUST remain constant. * * @return * A pointer to newly created @ref sip_status "status line" * structure when successful, or NULL upon an error. */ sip_status_t *sip_status_create(su_home_t *home, unsigned status, char const *phrase, char const *version) { sip_status_t *st; if (status < 100 || status > 699) return NULL; if (phrase == NULL && (phrase = sip_status_phrase(status)) == NULL) phrase = ""; if ((st = (sip_status_t *)sip_header_alloc(home, sip_status_class, 0))) { st->st_status = status; st->st_phrase = phrase; st->st_version = version ? version : SIP_VERSION_CURRENT; } return st; } /* ====================================================================== */ /**@SIP_HEADER sip_payload Message Body * * The payload structure contains the optional message body. The message * body stored in the #sip_payload_t structure has no internal structure, * but it is accessed as a byte array. Use @ref sdp_parser "SDP parser" to * parse SDP content, for instance. * * The message body is stored in a #sip_payload_t structure. */ /**@ingroup sip_payload * @typedef typedef struct sip_payload_s sip_payload_t; * * The structure #sip_payload_t contains representation of SIP message payload. * * The #sip_payload_t is defined as follows: * @code * typedef struct sip_payload_s { * msg_common_t pl_common[1]; // Common fragment info * msg_header_t *pl_next; // Next payload (if multipart message) * char *pl_data; // Data - may contain NUL * unsigned pl_len; // Length of message payload * } sip_payload_t; * @endcode */ #define sip_payload_d msg_payload_d #define sip_payload_e msg_payload_e #define sip_payload_dup_xtra msg_payload_dup_xtra #define sip_payload_dup_one msg_payload_dup_one #define sip_payload_update NULL msg_hclass_t sip_payload_class[] = SIP_HEADER_CLASS(payload, NULL, "", pl_common, single, payload); /**@ingroup sip_payload * * Create a @ref sip_payload "SIP payload" structure. * * Create a new SIP payload structure. it * copies the given data to the the payload data, and NUL terminates it (it * allocates one extra byte for NUL). If a NULL pointer is given as @a data, * sip_payload_create() allocates and zeroes a data buffer of @a len bytes. * * @param home memory home * @param data payload data * @param len payload length * * @return A pointer to newly created * payload structure, if successful, and NULL upon an error. */ sip_payload_t *sip_payload_create(su_home_t *home, void const *data, isize_t len) { msg_hclass_t *hc = sip_payload_class; sip_header_t *h = sip_header_alloc(home, hc, len + 1); sip_payload_t *pl = (sip_payload_t *)h; if (pl) { char *b = sip_header_data(h); if (data) { memcpy(b, data, len); b[len] = 0; } else { memset(b, 0, len + 1); } h->sh_data = pl->pl_data = b; h->sh_len = pl->pl_len = len; } return pl; } /* ====================================================================== */ /**@SIP_HEADER sip_separator Separator Line * * An empty line separates message headers from the message body (payload). * In order to avoid modifying messages with integrity protection, the * separator line has its own header structure which is included in the * #sip_t structure. * * The parsed separator line is stored in #sip_separator_t structure. */ /**@ingroup sip_separator * @typedef typedef struct sip_separator_s sip_separator_t; * * The structure #sip_separator_t contains representation of separator line * between message headers and body. * * The #sip_separator_t is defined as follows: * @code * typedef struct sip_separator_s { * msg_common_t sep_common[1]; // Common fragment info * msg_header_t *sep_next; // Pointer to next header * char sep_data[4]; // NUL-terminated separator * } sip_separator_t; * @endcode */ #define sip_separator_d msg_separator_d #define sip_separator_e msg_separator_e #define sip_separator_insert msg_separator_insert msg_hclass_t sip_separator_class[] = SIP_HEADER_CLASS(separator, NULL, "", sep_common, single, any); /**@ingroup sip_separator * * Create a @ref sip_separator "SIP separator line" structure. */ sip_separator_t *sip_separator_create(su_home_t *home) { sip_separator_t *sep = (sip_separator_t *) sip_header_alloc(home, sip_separator_class, 0); if (sep) strcpy(sep->sep_data, CRLF); return sep; } /* ====================================================================== */ /**@SIP_HEADER sip_unknown Unknown Headers * * The unknown headers are handled with #sip_unknown_t structure. The * unknown header name is stored in @a un_name field and the header field * following the colon is stored in @a un_value field. * * @note It is possible to speed up parsing process by creating a parser * which does understand only a minimum number of headers. If such a parser * is used, some well-known headers are regarded as unknown and put into * list of unknown headers. */ /**@ingroup sip_unknown * @typedef typedef struct sip_unknown_s sip_unknown_t; * * The structure #sip_unknown_t contains representation of unknown headers. * * The #sip_unknown_t is defined as follows: * @code * typedef struct msg_unknown_s { * msg_common_t un_common[1]; // Common fragment info * msg_unknown_t *un_next; // Link to next unknown header * char const *un_name; // Header name * char const *un_value; // Header field value * } sip_unknown_t; * @endcode */ #define sip_unknown_dup_xtra msg_unknown_dup_xtra #define sip_unknown_dup_one msg_unknown_dup_one #define sip_unknown_update NULL msg_hclass_t sip_unknown_class[] = SIP_HEADER_CLASS(unknown, "", "", un_common, append, unknown); issize_t sip_unknown_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return msg_unknown_d(home, h, s, slen); } issize_t sip_unknown_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { return msg_unknown_e(b, bsiz, h, flags); } /* ====================================================================== */ /**@SIP_HEADER sip_error Erroneous Headers * * The erroneous headers are stored in #sip_error_t structure. * * @note Other headers (like duplicate @ContentLength headers) may be put * into the list of erroneous headers (@c sip->sip_error). If the list of * erroneous headers is processed, the header type must be validated first * by calling sip_is_error() (or by other relevant tests). */ /**@ingroup sip_error * @typedef typedef msg_error_t sip_error_t; * The structure #sip_error_t contains representation of error headers. * * The #sip_error_t is defined as follows: * @code * typedef struct msg_error_s { * msg_common_t er_common[1]; // Common fragment info * msg_error_t *er_next; // Link to next header * char const *er_name; // Name of bad header (if any) * } sip_error_t; * @endcode */ msg_hclass_t sip_error_class[] = SIP_HEADER_CLASS(error, NULL, "", er_common, append, any); issize_t sip_error_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { return 0; } issize_t sip_error_e(char b[], isize_t bsiz, msg_header_t const *h, int flags) { /* There is no way to encode an erroneous header */ return 0; } /* ====================================================================== */ /* * addr = ("To" | "t" | "From" | "f") ":" * ( name-addr | addr-spec ) *( ";" addr-params ) * name-addr = [ display-name ] "<" addr-spec ">" * addr-spec = SIP-URL | URI * display-name = *token | quoted-string */ /**Parse @e name-addr. * * Parses ( name-addr | addr-spec ) construct on @Contact, @From, * @To, and other compatible headers. It splits the argument string in * four parts: * * @par * @e [display-name] @e addr-spec @e [parameters] @e [comment] @e [ss] * * @param home pointer to memory home * @param inout_s pointer to pointer to string to be parsed * @param return_display value-result parameter for @e display-name * @param return_url value-result parameter for @e addr-spec * @param return_params value-result paramater for @e parameters * @param return_comment value-result parameter for @e comment * * @note After succesful call to the function @c sip_name_addr_d(), *ss * contains pointer to the first character not beloging to @e name-addr, * most probably a comma. If that character is a separator, the last parameter * may not be NUL (zero) terminated. So, after examining value of @a **ss, * the calling function @b MUST set it to NUL. * * @retval 0 if successful * @retval -1 upon an error * * @sa @From, @To, @Contact */ issize_t sip_name_addr_d(su_home_t *home, char **inout_s, char const **return_display, url_t *return_url, msg_param_t const **return_params, char const **return_comment) { char c, *s = *inout_s; char *display = NULL, *addr_spec = NULL; size_t n; if (*s == '\0') /* Empty string */ return -1; if (return_display && *s == '"') { /* Quoted string */ if (msg_quoted_d(&s, &display) == -1) return -1; /* Now, we should have a '<' in s[0] */ if (s[0] != '<') return -1; s++[0] = '\0'; /* NUL terminate quoted string... */ n = strcspn(s, ">"); addr_spec = s; s += n; if (*s) *s++ = '\0'; else return -1; } else { if (return_display) n = span_token_lws(s); else n = 0; if (s[n] == '<') { /* OK, we got a display name */ display = s; s += n + 1; /* NUL terminate display name */ while (n > 0 && IS_LWS(display[n - 1])) n--; if (n > 0) display[n] = '\0'; else display = ""; n = strcspn(s, ">"); addr_spec = s; s += n; if (*s) *s++ = '\0'; else return -1; } else { /* addr-spec only */ addr_spec = s; /**@sa * Discussion about comma, semicolon and question mark in * @RFC3261 section 20.10. */ if (return_params) n = strcspn(s, " \t,;?"); /* DO NOT accept ,;? in URL */ else /* P-Asserted-Identity and friends */ n = strcspn(s, " ,"); /* DO NOT accept , in URL */ s += n; if (IS_LWS(*s)) *s++ = '\0'; } } skip_lws(&s); if (return_display) *return_display = display; /* Now, url may still not be NUL terminated, e.g., if * it is like "Contact: url:foo,sip:bar,sip:zunk" */ c = *s; *s = '\0'; /* terminate temporarily */ /* Do not accept an empty URL */ if (addr_spec[0] == '\0') return -1; if (url_d(return_url, addr_spec) == -1) return -1; *s = c; /* return terminator */ *inout_s = s; if (c == ';' && return_params) if (msg_params_d(home, inout_s, return_params) == -1) return -1; if (**inout_s == '(' && return_comment) if (msg_comment_d(inout_s, return_comment) == -1) return -1; return 0; } /**Encode @e name-addr and parameter list. * * Encodes @e name-addr headers, like @From, @To, @CallInfo, @ErrorInfo, * @Route, and @RecordRoute. * * @param b buffer to store the encoding result * @param bsiz size of the buffer @a b * @param flags encoding flags * @param display display name encoded before the @a url (may be NULL) * @param brackets if true, use always brackets around @a url * @param url pointer to URL structure * @param params pointer to parameter list (may be NULL) * @param comment comment string encoded after others (may be NULL) * * @return * Returns number of characters in encoding, excluding the * final NUL. * * @note * The encoding result may be incomplete if the buffer size is not large * enough to store the whole encoding result. */ issize_t sip_name_addr_e(char b[], isize_t bsiz, int flags, char const *display, int brackets, url_t const url[], msg_param_t const params[], char const *comment) { int const compact = MSG_IS_COMPACT(flags); char const *u; char *b0 = b, *end = b + bsiz; brackets = brackets || display || (url && (url->url_params || url->url_headers || ((u = url->url_user) && u[strcspn(u, ";,?")]) || ((u = url->url_password) && u[strcspn(u, ",")]))); if (display && display[0]) { MSG_STRING_E(b, end, display); if (!compact) MSG_CHAR_E(b, end, ' '); } if (url) { if (brackets) MSG_CHAR_E(b, end, '<'); URL_E(b, end, url); if (brackets) MSG_CHAR_E(b, end, '>'); } MSG_PARAMS_E(b, end, params, flags); if (comment) { if (!compact) MSG_CHAR_E(b, end, ' '); MSG_CHAR_E(b, end, '('); MSG_STRING_E(b, end, comment); MSG_CHAR_E(b, end, ')'); } MSG_TERM_E(b, end); return b - b0; } /** Calculate the extra size needed to duplicate a name-addr-params construct. * * @param display display name (may be NULL) * @param addr pointer to URL structure * @param params pointer to parameter list (may be NULL) * @param offset base offset * * @retval Size of duplicated name-addr-params construct, including base offset. * * @NEW_1_12_7. */ isize_t sip_name_addr_xtra(char const *display, url_t const *addr, msg_param_t const params[], isize_t offset) { SIP_PARAMS_SIZE(offset, params); offset += SIP_STRING_SIZE(display); offset += url_xtra(addr); return offset; } /**Duplicate a name-addr-params construct. * * @param d_display value-result parameter for copied @e name (may be NULL) * @param display display name (may be NULL) * @param d_addr value-result parameter for copied @e address * @param addr pointer to URL address structure * @param d_params value-result parameter for copied parameters (may be NULL) * @param params pointer to parameter list (may be NULL) * @param b pointer to memory pool * @param xtra size of the memory pool * * @retval End of the memory area used. * * @NEW_1_12_7. */ char *sip_name_addr_dup(char const **d_display, char const *display, url_t *d_addr, url_t const *addr, msg_param_t const **d_params, msg_param_t const params[], char *b, isize_t xtra) { char *end = b + xtra; if (d_params) b = msg_params_dup(d_params, params, b, xtra); URL_DUP(b, end, d_addr, addr); if (d_display) MSG_STRING_DUP(b, *d_display, display); assert(b <= end); return b; } /** Parse @To or @From headers */ static issize_t sip_addr_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_addr_t *a = (sip_addr_t *)h; char const *comment = NULL; if (sip_name_addr_d(home, &s, &a->a_display, a->a_url, &a->a_params, &comment) == -1 || *s /* XXX - something extra? */) return -1; a->a_tag = msg_params_find(a->a_params, "tag="); return 0; } static int sip_addr_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { sip_addr_t const *a = (sip_addr_t const *)h; return sip_name_addr_e(b, bsiz, flags, a->a_display, MSG_IS_CANONIC(flags), a->a_url, a->a_params, NULL); } /** * Extra dup size of a sip_addr_t object. * * This function calculates extra size required when duplicating a * sip_addr_t object. * * @param a pointer to a sip_addr_t object * * @return * Size of strings related to sip_addr_t object. */ static isize_t sip_addr_dup_xtra(sip_header_t const *h, isize_t offset) { sip_addr_t const *a = (sip_addr_t const *)h; return sip_name_addr_xtra(a->a_display, a->a_url, a->a_params, offset); } /**@internal * Duplicate one sip_addr_t object. */ static char *sip_addr_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { sip_addr_t *a = (sip_addr_t *)dst; sip_addr_t const *o = (sip_addr_t *)src; return sip_name_addr_dup(&a->a_display, o->a_display, a->a_url, o->a_url, &a->a_params, o->a_params, b, xtra); } /** Update parameters in sip_addr_t object */ static int sip_addr_update(msg_common_t *h, char const *name, isize_t namelen, char const *value) { sip_addr_t *a = (sip_addr_t *)h; if (name == NULL) { a->a_tag = NULL; } else if (namelen == strlen("tag") && su_casenmatch(name, "tag", namelen)) { a->a_tag = value; } return 0; } /** Create an address header object from URL */ static sip_addr_t * sip_addr_make_url(su_home_t *home, msg_hclass_t *hc, url_string_t const *us) { size_t n; sip_header_t *h; n = url_xtra(us->us_url); h = sip_header_alloc(home, hc, n); if (h) { sip_addr_t *a = (sip_to_t *)h; char *s2 = sip_header_data(h); if ((size_t)url_dup(s2, n, a->a_url, us->us_url) == n) return a; su_free(home, h); } return NULL; } /** Add a tag to address structure. */ static int sip_addr_tag(su_home_t *home, sip_addr_t *a, char const *tag) { if (a && tag) { msg_param_t value = strchr(tag, '='); if (value) value = strchr(value, '=') + 1; else value = tag; if (a->a_tag) { if (su_casematch(a->a_tag, value)) return 0; else return -1; } if (tag == value) tag = su_sprintf(home, "tag=%s", tag); else tag = su_strdup(home, tag); if (tag) if (msg_header_replace_param(home, a->a_common, tag) >= 0) return 0; } return -1; } /* ====================================================================== */ /**@SIP_HEADER sip_call_id Call-ID Header * * The @b Call-ID header uniquely identifies a particular invitation or all * registrations of a particular client. It is defined in @RFC3261 as * follows: * * @code * Call-ID = ( "Call-ID" / "i" ) HCOLON callid * callid = word [ "@" word ] * word = 1*(alphanum / "-" / "." / "!" / "%" / "*" / * "_" / "+" / "`" / "'" / "~" / "(" / ")" / "<" / ">" / * ":" / "\" / DQUOTE / "/" / "[" / "]" / "?" / "{" / "}" ) * @endcode * * The parsed Call-ID Header is stored in #sip_call_id_t structure. */ /**@ingroup sip_call_id * @typedef typedef struct sip_call_id_s sip_call_id_t; * * The structure #sip_call_id_t contains representation of SIP @CallID * header. * * The #sip_call_id_t is defined as follows: * @code * typedef struct sip_call_id_s { * sip_common_t i_common[1]; // Common fragment info * sip_call_id_t *i_next; // Link to next (dummy) * char const *i_id; // ID value * uint32_t i_hash; // Hash value (always nonzero) * } sip_call_id_t; * @endcode */ static msg_xtra_f sip_call_id_dup_xtra; static msg_dup_f sip_call_id_dup_one; #define sip_call_id_update NULL msg_hclass_t sip_call_id_class[] = SIP_HEADER_CLASS(call_id, "Call-ID", "i", i_common, single, call_id); issize_t sip_call_id_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_call_id_t *i = (sip_call_id_t *)h; i->i_id = s; /* XXX - why not sip_word_at_word_d(&s); */ i->i_hash = msg_hash_string(s); return 0; } issize_t sip_call_id_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { sip_call_id_t const *i = (sip_call_id_t *)h; size_t n = strlen(i->i_id); if (bsiz > n) strcpy(b, i->i_id); return (issize_t)n; } /** Extra size of a #sip_call_id_t object. */ isize_t sip_call_id_dup_xtra(sip_header_t const *h, isize_t offset) { sip_call_id_t const *i = (sip_call_id_t *)h; return offset + MSG_STRING_SIZE(i->i_id); } /**Duplicate a sip_call_id object. * * Duplicate (copy deeply) a single #sip_call_id_t header object. * * @param dst pointer to newly allocated header object * @param src pointer to a header object to be duplicated * @param b memory buffer used to copy external references * @param xtra number bytes in buffer @a b * * @return Pointer to the new copy of #sip_call_id_t object, or @c NULL * upon an error. */ char *sip_call_id_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { sip_call_id_t *i = (sip_call_id_t *)dst; sip_call_id_t const *o = (sip_call_id_t *)src; char *end = b + xtra; MSG_STRING_DUP(b, i->i_id, o->i_id); if (!(i->i_hash = o->i_hash)) i->i_hash = msg_hash_string(i->i_id); assert(b <= end); (void)end; return b; } /**@ingroup sip_call_id * * Create a @CallID header object. * * Create a Call-ID header object with a new unique value. It uses * su_guid_generate() function to generate the value. If the local host name * @a domain is specified, it is prepended to the generated value instead of * local MAC address. * @param home memory home * @param domain local domain name * * @return A pointer to newly created @CallID header object when * successful or NULL upon an error. * * @sa su_guid_generate(), su_guid_sprintf() */ sip_call_id_t *sip_call_id_create(su_home_t *home, char const *domain) { sip_call_id_t *i; size_t xtra = su_guid_strlen + 1 + (domain ? strlen(domain) + 1 : 0); i = (sip_call_id_t *)sip_header_alloc(home, sip_call_id_class, xtra); if (i) { char *b; su_guid_t guid[1]; i->i_id = b = (char *)(i + 1); su_guid_generate(guid); /* * Guid looks like "NNNNNNNN-NNNN-NNNN-NNNN-XXXXXXXXXXXX" * where NNNNNNNN-NNNN-NNNN-NNNN is timestamp and XX is MAC address * (but we use usually random ID for MAC because we do not have * guid generator available for all processes within node) */ su_guid_sprintf(b, su_guid_strlen + 1, guid); /* If we have a domain name don't include MAC address at the end of guid */ if (domain) { b[8 + 5 + 5 + 5] = '@'; strcpy(b + 8 + 5 + 5 + 5 + 1, domain); } i->i_hash = msg_hash_string(i->i_id); } return i; } /* ====================================================================== */ /**@SIP_HEADER sip_cseq CSeq Header * * The CSeq header (command sequence) uniquely identifies transactions * within a dialog. It is defined in @RFC3261 as follows: * * @code * CSeq = "CSeq" HCOLON 1*DIGIT LWS Method * Method = INVITEm / ACKm / OPTIONSm / BYEm * / CANCELm / REGISTERm * / extension-method * extension-method = token * @endcode * * The parsed CSeq header is stored in #sip_cseq_t structure. */ /**@ingroup sip_cseq * @typedef typedef struct sip_cseq_s sip_cseq_t; * * The structure #sip_cseq_t contains representation of SIP @CSeq header. * * The #sip_cseq_t is defined as follows: * @code * typedef struct sip_cseq_s { * sip_common_t cs_common[1]; // Common fragment info * sip_error_t *cs_next; // Link to next (dummy) * uint32_t cs_seq; // Sequence number * sip_method_t cs_method; // Method enum * char const *cs_method_name; // Method name * } sip_cseq_t; * @endcode */ static msg_xtra_f sip_cseq_dup_xtra; static msg_dup_f sip_cseq_dup_one; #define sip_cseq_update NULL msg_hclass_t sip_cseq_class[] = SIP_HEADER_CLASS(cseq, "CSeq", "", cs_common, single, cseq); issize_t sip_cseq_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_cseq_t *cs = (sip_cseq_t *)h; if (msg_uint32_d(&s, &cs->cs_seq) < 0) return -1; if (*s) { if ((cs->cs_method = sip_method_d(&s, &cs->cs_method_name)) >= 0) return 0; } return -1; } issize_t sip_cseq_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { sip_cseq_t const *cs = (sip_cseq_t *)h; assert(sip_is_cseq(h)); return snprintf(b, bsiz, "%u %s", cs->cs_seq, cs->cs_method_name); } isize_t sip_cseq_dup_xtra(sip_header_t const *h, isize_t offset) { sip_cseq_t const *cs = (sip_cseq_t *)h; if (!cs->cs_method) return offset + MSG_STRING_SIZE(cs->cs_method_name); else return offset; } char *sip_cseq_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { sip_cseq_t *cs = (sip_cseq_t *)dst; sip_cseq_t const *o = (sip_cseq_t *)src; char *end = b + xtra; if (!(cs->cs_method = o->cs_method)) MSG_STRING_DUP(b, cs->cs_method_name, o->cs_method_name); else cs->cs_method_name = o->cs_method_name; cs->cs_seq = o->cs_seq; assert(b <= end); (void)end; return b; } /**@ingroup sip_cseq * *Create a @CSeq header object. * * Create a @CSeq header object with the * sequence number @a seq, method enum @a method and method name @a * method_name. The memory for the header object is allocated from the * memory home @a home. * * @param home memory home * @param seq sequence number * @param method method enum * @param method_name method name (required if method is not well-known) * * @par Example * The following code fragment creates a cseq object for OPTIONS request: * @code * sip_cseq_t *cseq; * cseq = sip_cseq_create(home, agent->seq++, SIP_METHOD_OPTIONS); * @endcode * * @return * A pointer to newly created @CSeq * header object when successful or NULL upon an error. */ sip_cseq_t *sip_cseq_create(su_home_t *home, uint32_t seq, unsigned method, char const *method_name) { size_t xtra; sip_cseq_t *cs; if (method) method_name = sip_method_name((sip_method_t)method, method_name); if (method_name == NULL) return NULL; xtra = (method ? 0 : (strlen(method_name) + 1)); cs = (sip_cseq_t *)sip_header_alloc(home, sip_cseq_class, xtra); if (cs) { cs->cs_seq = seq; cs->cs_method = (sip_method_t)method; if (!method) method_name = strcpy((char *)(cs + 1), method_name); cs->cs_method_name = method_name; } return cs; } /* ====================================================================== */ /**@SIP_HEADER sip_contact Contact Header * * The Contact header contain a list of URLs used to redirect future * requests. Its syntax is defined in @RFC3261 as follows: * * @code * Contact = ("Contact" / "m" ) HCOLON * ( STAR / (contact-param *(COMMA contact-param))) * contact-param = (name-addr / addr-spec) *(SEMI contact-params) * name-addr = [ display-name ] LAQUOT addr-spec RAQUOT * addr-spec = SIP-URI / SIPS-URI / absoluteURI * display-name = *(token LWS)/ quoted-string * contact-params = c-p-q / c-p-expires * / contact-extension * c-p-q = "q" EQUAL qvalue * c-p-expires = "expires" EQUAL delta-seconds * contact-extension = generic-param * delta-seconds = 1*DIGIT * @endcode * * @note * The @RFC2543 syntax allowed . We accept it, but don't encode it. * * Each parsed Contact header field is stored in #sip_contact_t structure. */ /**@ingroup sip_contact * @typedef typedef struct sip_contact_s sip_contact_t; * * The structure #sip_contact_t contains representation of SIP @Contact * header. * * The #sip_contact_t is defined as follows: * @code * typedef struct sip_contact_s { * sip_common_t m_common[1]; // Common fragment info * sip_contact_t *m_next; // Link to next * char const *m_display; // Display name * url_t m_url[1]; // SIP URL * msg_param_t const *m_params; // List of contact-params * char const *m_comment; // Comment * * char const *m_q; // Priority * char const *m_expires; // Expiration time * } sip_contact_t; * @endcode * * @note The field @ref sip_contact_s::m_comment "m_comment" is * deprecated: it is parsed but not included in encoding. */ static msg_xtra_f sip_contact_dup_xtra; static msg_dup_f sip_contact_dup_one; static msg_update_f sip_contact_update; /** @showinitializer */ msg_hclass_t sip_contact_class[] = /* * Cut through the fog of macros * SIP_HEADER_CLASS(contact, "Contact", "m", m_params, append, contact); * and show here how the msg_hclass_t is initialized */ {{ /* hc_hash: */ sip_contact_hash, /* hc_parse: */ sip_contact_d, /* hc_print: */ sip_contact_e, /* hc_dxtra: */ sip_contact_dup_xtra, /* hc_dup_one: */ sip_contact_dup_one, /* hc_update: */ sip_contact_update, /* hc_name: */ "Contact", /* hc_len: */ sizeof("Contact") - 1, /* hc_short: */ "m", /* hc_size: */ MSG_ALIGN(sizeof(sip_contact_t), sizeof(void*)), /* hc_params: */ offsetof(sip_contact_t, m_params), /* hc_kind: */ msg_kind_append, /* hc_critical: */ 0 }}; issize_t sip_contact_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_contact_t *m = (sip_contact_t *)h; assert(h); while (*s == ',') /* Ignore empty entries (comma-whitespace) */ *s = '\0', s += span_lws(s + 1) + 1; if (sip_name_addr_d(home, &s, &m->m_display, m->m_url, &m->m_params, &m->m_comment) == -1) return -1; return msg_parse_next_field(home, h, s, slen); } issize_t sip_contact_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { sip_contact_t const *m = (sip_contact_t *)h; int always_lt_gt = MSG_IS_CANONIC(flags) && m->m_url->url_type != url_any; assert(sip_is_contact(h)); return sip_name_addr_e(b, bsiz, flags, m->m_display, always_lt_gt, m->m_url, m->m_params, NULL /* m->m_comment */); } isize_t sip_contact_dup_xtra(sip_header_t const *h, isize_t offset) { sip_contact_t const *m = (sip_contact_t *)h; return sip_name_addr_xtra(m->m_display, m->m_url, m->m_params, offset) + MSG_STRING_SIZE(m->m_comment); } char *sip_contact_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { sip_contact_t *m = (sip_contact_t *)dst; sip_contact_t const *o = (sip_contact_t *)src; b = sip_name_addr_dup(&m->m_display, o->m_display, m->m_url, o->m_url, &m->m_params, o->m_params, b, xtra); MSG_STRING_DUP(b, m->m_comment, o->m_comment); return b; } /** Update parameter in #sip_contact_t */ static int sip_contact_update(msg_common_t *h, char const *name, isize_t namelen, char const *value) { sip_contact_t *m = (sip_contact_t *)h; if (name == NULL) { m->m_q = NULL; m->m_expires = NULL; } else if (namelen == 1 && su_casenmatch(name, "q", 1)) { /* XXX - check for invalid value? */ m->m_q = value; } else if (namelen == strlen("expires") && su_casenmatch(name, "expires", namelen)) { m->m_expires = value; } return 0; } /**@ingroup sip_contact * * Add a parameter to a @Contact header object * * Add a parameter to a @Contact * object. It does not copy the contents of the string @c param. * * @note This function @b does @b not duplicate @p param. * * @param home memory home * @param m #sip_contact_t object * @param param parameter string * * @return 0 when successful, and -1 upon an error. * * @deprecated Use msg_header_replace_param() directly. */ int sip_contact_add_param(su_home_t *home, sip_contact_t *m, char const *param) { return msg_header_replace_param(home, m->m_common, param); } /* ====================================================================== */ /**@SIP_HEADER sip_content_length Content-Length Header * * The Content-Length header indicates the size of the message-body in * decimal number of octets. Its syntax is defined in @RFC3261 as * follows: * * @code * Content-Length = ( "Content-Length" / "l" ) HCOLON 1*DIGIT * @endcode * * The parsed Content-Length header is stored in #sip_content_length_t * structure. */ /**@ingroup sip_content_length * @typedef typedef struct sip_content_length_s sip_content_length_t; * * The structure #sip_content_length_t contains representation of SIP * @ContentLength header. * * The #sip_content_length_t is defined as follows: * @code * typedef struct sip_content_length_s { * sip_common_t l_common[1]; // Common fragment info * sip_error_t *l_next; // Dummy link to next * uint32_t l_length; // Message body length in bytes * } sip_content_length_t; * @endcode */ msg_hclass_t sip_content_length_class[] = SIP_HEADER_CLASS(content_length, "Content-Length", "l", l_common, single_critical, any); issize_t sip_content_length_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_content_length_t *l = (sip_content_length_t *)h; issize_t retval = msg_uint32_d(&s, &l->l_length); if (*s) retval = -1; return retval; } issize_t sip_content_length_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { sip_content_length_t const *l = (sip_content_length_t const *)h; assert(sip_is_content_length(h)); return snprintf(b, bsiz, "%lu", (unsigned long)l->l_length); } /**@ingroup sip_content_length * *Create a @ContentLength header object. * * Create a @ContentLength * header object with the value @a n. The memory for the header is * allocated from the memory home @a home. * * @param home memory home * @param n payload size in bytes * * @return * A pointer to newly created @ContentLength header object when successful * or NULL upon an error. */ sip_content_length_t *sip_content_length_create(su_home_t *home, uint32_t n) { sip_content_length_t *l = (sip_content_length_t *) sip_header_alloc(home, sip_content_length_class, 0); if (l) l->l_length = n; return l; } /* ====================================================================== */ /**@SIP_HEADER sip_date Date Header * * The Date header field reflects the time when the request or response was * first sent. Its syntax is defined in @RFC3261 and @RFC2616 section 14.18 as * follows: * * @code * Date = "Date" HCOLON SIP-date * SIP-date = rfc1123-date * rfc1123-date = wkday "," SP date1 SP time SP "GMT" * date1 = 2DIGIT SP month SP 4DIGIT * ; day month year (e.g., 02 Jun 1982) * time = 2DIGIT ":" 2DIGIT ":" 2DIGIT * ; 00:00:00 - 23:59:59 * wkday = "Mon" / "Tue" / "Wed" * / "Thu" / "Fri" / "Sat" / "Sun" * month = "Jan" / "Feb" / "Mar" / "Apr" * / "May" / "Jun" / "Jul" / "Aug" * / "Sep" / "Oct" / "Nov" / "Dec" * @endcode * * The parsed Date header is stored in #sip_date_t structure. */ /**@ingroup sip_date * @typedef typedef struct sip_date_s sip_date_t; * * The structure #sip_date_t contains representation of SIP @Date header. * * The #sip_date_t is defined as follows: * @code * typedef struct sip_date_s { * sip_common_t d_common[1]; // Common fragment info * sip_date_t *d_next; // Link to next (dummy) * sip_time_t d_time; // Seconds since Jan 1, 1900 * } sip_date_t; * @endcode */ msg_hclass_t sip_date_class[] = SIP_HEADER_CLASS(date, "Date", "", d_common, single, any); issize_t sip_date_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_date_t *date = (sip_date_t *)h; if (msg_date_d((char const **)&s, &date->d_time) < 0 || *s) return -1; else return 0; } issize_t sip_date_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { sip_date_t const *date = (sip_date_t *)h; return msg_date_e(b, bsiz, date->d_time); } /**@ingroup sip_date * @brief Create an @Date header object. * * Create a @Date header object with * the date @a date. If @date is 0, current time (as returned by sip_now()) * is used. * * @param home memory home * @param date date expressed as seconds since Mon, 01 Jan 1900 00:00:00 * * @return * A pointer to newly created @Date header object when successful, or NULL * upon an error. */ sip_date_t *sip_date_create(su_home_t *home, sip_time_t date) { sip_date_t *d = (sip_date_t *)sip_header_alloc(home, sip_date_class, 0); if (d) { if (date == 0) date = sip_now(); d->d_time = date; } return d; } /* ====================================================================== */ /**@SIP_HEADER sip_expires Expires Header * * The Expires header field gives the date and time after which the message * content expires. Its syntax is defined in @RFC3261 as follows: * * @code * Expires = "Expires" HCOLON delta-seconds * @endcode * * Note that the first SIP revision (@RFC2543) also allowed absolute time in * Expires. * * The parsed Expires header is stored in #sip_expires_t structure. */ /**@ingroup sip_expires * @typedef typedef struct sip_expires_s sip_expires_t; * * The structure #sip_expires_t contains representation of SIP @Expires * header. * * The #sip_expires_t is defined as follows: * @code * typedef struct sip_expires_s { * sip_common_t ex_common[1]; // Common fragment info * sip_error_t *ex_next; // Link to next (dummy) * sip_time_t ex_date; // Seconds since Jan 1, 1900 * sip_time_t ex_delta; // ...or delta seconds * } sip_expires_t; * @endcode */ msg_hclass_t sip_expires_class[] = SIP_HEADER_CLASS(expires, "Expires", "", ex_common, single, any); issize_t sip_expires_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_expires_t *expires = (sip_expires_t *)h; if (msg_date_delta_d((char const **)&s, &expires->ex_date, &expires->ex_delta) < 0 || *s) return -1; else return 0; } issize_t sip_expires_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { sip_expires_t const *expires = (sip_expires_t *)h; if (expires->ex_date) return msg_date_e(b, bsiz, expires->ex_date + expires->ex_delta); else return msg_delta_e(b, bsiz, expires->ex_delta); } /**@ingroup sip_expires * @brief Create an @Expires header object. * * Create an @Expires header object with the expiration time @a delta. * * @param home memory home used to allocate #sip_expires_t structure * @param delta relative expiration time in seconds * * @return * A pointer to newly created @Expires header object when successful or NULL * upon an error. */ sip_expires_t *sip_expires_create(su_home_t *home, sip_time_t delta) { sip_expires_t *ex = (sip_expires_t *) sip_header_alloc(home, sip_expires_class, 0); if (ex) ex->ex_delta = delta; return ex; } /* ====================================================================== */ /**@SIP_HEADER sip_from From Header * * The From header indicates the initiator of the request. It is defined in * @RFC3261 as follows: * * @code * From = ( "From" / "f" ) HCOLON from-spec * from-spec = ( name-addr / addr-spec ) * *( SEMI from-param ) * from-param = tag-param / generic-param * tag-param = "tag" EQUAL token * @endcode * * * The parsed From header is stored in #sip_from_t structure. */ /**@ingroup sip_from * @typedef typedef struct sip_addr_s sip_from_t; * * The structure #sip_from_t contains representation of @From header. * * The #sip_from_t is defined as follows: * @code * typedef struct sip_addr_s { * sip_common_t a_common[1]; // Common fragment info * sip_error_t *a_next; // Link to next * char const *a_display; // Display name * url_t a_url[1]; // URL * msg_param_t const *a_params; // List of from-param * char const *a_comment; // Comment * char const *a_tag; // Tag parameter * } sip_from_t; * @endcode * */ msg_hclass_t sip_from_class[] = SIP_HEADER_CLASS(from, "From", "f", a_params, single, addr); issize_t sip_from_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return sip_addr_d(home, h, s, slen); } issize_t sip_from_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { assert(sip_is_from(h)); return sip_addr_e(b, bsiz, h, flags); } /**@ingroup sip_from * * Create a @From header object with URL. * * @param home memory home used to allocate #sip_from_t structure * @param s pointer to the URL or a string * * @return * A pointer to newly created @From header object when successful or NULL * upon an error. */ sip_from_t * sip_from_create(su_home_t *home, url_string_t const *s) { return sip_addr_make_url(home, sip_from_class, s); } /**@ingroup sip_from * * Add a parameter to an #sip_from_t object. * * @param home memory home * @param from a pointer to #sip_from_t object * @param param parameter string * * @retval 0 when successful * @retval -1 upon an error * * @deprecated Use msg_header_replace_param() directly. */ int sip_from_add_param(su_home_t *home, sip_from_t *from, char const *param) { return msg_header_replace_param(home, from->a_common, param); } /**@ingroup sip_from * * Add a tag to a @From header. If @a tag is * identical with the existing one, nothing will be done. An error is * returned, if the header already contains a different tag. The @a tag can * be provided either as a single token ("deadbeer") or as in parameter form * ("tag=deadbeer"). In both cases the tag is duplicated using the memory * home @a home. * * @param home memory home used to allocate new tag * @param from @From header to modify * @param tag tag token or parameter to be added * * @retval 0 when successful * @retval -1 upon an error. */ int sip_from_tag(su_home_t *home, sip_from_t *from, char const *tag) { return sip_addr_tag(home, from, tag); } int sip_to_tag(su_home_t *home, sip_to_t *to, char const *tag) { return sip_addr_tag(home, to, tag); } /* ====================================================================== */ /**@SIP_HEADER sip_max_forwards Max-Forwards Header * * The Max-Forwards header is used to limit the number of proxies or * gateways that can forward the request. The Max-Forwards syntax is * defined in @RFC3261 as follows: * * @code * Max-Forwards = "Max-Forwards" HCOLON 1*DIGIT * @endcode * * * The parsed Max-Forwards header is stored in #sip_max_forwards_t structure. */ /**@ingroup sip_max_forwards * @typedef typedef struct sip_max_forwards_s sip_max_forwards_t; * * The structure #sip_max_forwards_t contains representation of SIP * @MaxForwards header. * * The #sip_max_forwards_t is defined as follows: * @code * typedef struct sip_max_forwards_s { * sip_common_t mf_common[1]; // Common fragment info * sip_error_t *mf_next; // Link to next (dummy) * unsigned long mf_count; // Digits * } sip_max_forwards_t; * @endcode */ msg_hclass_t sip_max_forwards_class[] = SIP_HEADER_CLASS(max_forwards, "Max-Forwards", "", mf_common, single, any); issize_t sip_max_forwards_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return sip_numeric_d(home, h, s, slen); } issize_t sip_max_forwards_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { assert(sip_is_max_forwards(h)); return sip_numeric_e(b, bsiz, h, f); } /* ====================================================================== */ /**@SIP_HEADER sip_min_expires Min-Expires Header * * The Min-Expires header is used to limit the number of proxies or * gateways that can forward the request. The Min-Expires syntax is * defined in @RFC3261 as follows: * * @code * Min-Expires = "Min-Expires" HCOLON delta-seconds * @endcode * * The parsed Min-Expires header is stored in #sip_min_expires_t structure. */ /**@ingroup sip_min_expires * @typedef typedef struct sip_min_expires_s sip_min_expires_t; * * The structure #sip_min_expires_t contains representation of SIP * @MinExpires header. * * The #sip_min_expires_t is defined as follows: * @code * typedef struct sip_min_expires_s { * sip_common_t me_common[1]; // Common fragment info * sip_error_t *me_next; // Link to next (dummy) * unsigned long me_delta; // Seconds * } sip_min_expires_t; * @endcode */ msg_hclass_t sip_min_expires_class[] = SIP_HEADER_CLASS(min_expires, "Min-Expires", "", me_common, single, any); issize_t sip_min_expires_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return sip_numeric_d(home, h, s, slen); } issize_t sip_min_expires_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { assert(sip_is_min_expires(h)); return sip_numeric_e(b, bsiz, h, f); } /* ====================================================================== */ /**@SIP_HEADER sip_retry_after Retry-After Header * * The Retry-After response-header field @RFC3261 section 20.33 can be used to * indicate how long the service is expected to be unavailable or when the * called party anticipates being available again. Its syntax is defined in * @RFC3261 as follows: * * @code * Retry-After = "Retry-After" HCOLON delta-seconds * [ comment ] *( SEMI retry-param ) * retry-param = ("duration" EQUAL delta-seconds) * / generic-param * @endcode * * The parsed Retry-After header is stored in #sip_retry_after_t structure. */ /**@ingroup sip_retry_after * @typedef struct sip_retry_after_s sip_retry_after_t; * * The structure #sip_retry_after_t contains representation of an * @RetryAfter header. * * The #sip_retry_after_t is defined as follows: * @code * typedef struct sip_retry_after_s { * sip_common_t af_common[1]; // Common fragment info * sip_error_t *af_next; // Link to next (dummy) * sip_time_t af_delta; // Seconds to before retry * char const *af_comment; // Comment string * msg_param_t const *af_params; // List of parameters * char const *af_duration; // Duration parameter * } sip_retry_after_t; * @endcode */ static msg_xtra_f sip_retry_after_dup_xtra; static msg_dup_f sip_retry_after_dup_one; static msg_update_f sip_retry_after_update; msg_hclass_t sip_retry_after_class[] = SIP_HEADER_CLASS(retry_after, "Retry-After", "", af_params, single, retry_after); issize_t sip_retry_after_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_retry_after_t *af = (sip_retry_after_t *)h; if ((msg_delta_d((char const **)&s, &af->af_delta) < 0) || (*s == '(' && msg_comment_d(&s, &af->af_comment) == -1) || (*s == ';' && msg_params_d(home, &s, &af->af_params) == -1) || (*s != '\0')) { if (af->af_params) su_free(home, (void *)af->af_params), af->af_params = NULL; return -1; } if (af->af_params) msg_header_update_params(h->sh_common, 0); return 0; } issize_t sip_retry_after_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { sip_retry_after_t const *af = (sip_retry_after_t *)h; int const compact = MSG_IS_COMPACT(f); char *b0 = b, *end = b + bsiz; b += snprintf(b, bsiz, "%lu", af->af_delta); if (af->af_comment) { if (!compact) MSG_CHAR_E(b, end, ' '); MSG_CHAR_E(b, end, '('); MSG_STRING_E(b, end, af->af_comment); MSG_CHAR_E(b, end, ')'); if (!compact && af->af_params && af->af_params[0]) MSG_CHAR_E(b, end, ' '); } if (af->af_params) MSG_PARAMS_E(b, end, af->af_params, f); MSG_TERM_E(b, end); return b - b0; } isize_t sip_retry_after_dup_xtra(sip_header_t const *h, isize_t offset) { sip_retry_after_t const *af = (sip_retry_after_t *)h; MSG_PARAMS_SIZE(offset, af->af_params); offset += MSG_STRING_SIZE(af->af_comment); return offset; } char *sip_retry_after_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { sip_retry_after_t *af = (sip_retry_after_t *)dst; sip_retry_after_t const *o = (sip_retry_after_t *)src; char *end = b + xtra; b = msg_params_dup(&af->af_params, o->af_params, b, xtra); MSG_STRING_DUP(b, af->af_comment, o->af_comment); af->af_delta = o->af_delta; assert(b <= end); (void)end; return b; } static int sip_retry_after_update(msg_common_t *h, char const *name, isize_t namelen, char const *value) { sip_retry_after_t *af = (sip_retry_after_t *)h; if (name == NULL) { af->af_duration = NULL; } else if (namelen == strlen("duration") && su_casenmatch(name, "duration", namelen)) { af->af_duration = value; } return 0; } /* ====================================================================== */ /**Parse a @Route or a @RecordRoute header. * * @retval 0 when successful, * @retval -1 upon an error. */ issize_t sip_any_route_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_route_t *r = (sip_route_t *)h; assert(h); while (*s == ',') /* Ignore empty entries (comma-whitespace) */ *s = '\0', s += span_lws(s + 1) + 1; if (sip_name_addr_d(home, &s, &r->r_display, r->r_url, &r->r_params, NULL) < 0) return -1; return msg_parse_next_field(home, h, s, slen); } issize_t sip_any_route_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { sip_route_t const *r = (sip_route_t *)h; return sip_name_addr_e(b, bsiz, flags, r->r_display, 1, r->r_url, r->r_params, NULL); } isize_t sip_any_route_dup_xtra(sip_header_t const *h, isize_t offset) { sip_route_t const *r = (sip_route_t *)h; return sip_name_addr_xtra(r->r_display, r->r_url, r->r_params, offset); } char *sip_any_route_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { sip_route_t *r = (sip_route_t *)dst; sip_route_t const *o = (sip_route_t *)src; return sip_name_addr_dup(&r->r_display, o->r_display, r->r_url, o->r_url, &r->r_params, o->r_params, b, xtra); } #define sip_any_route_update NULL /** Create a route. * * Create a route or record-route entry * from two URLs; first one provides the URL, second maddr parameter and * port. * * @param home memory home * @param rq_url route URL * @param maddr optional route address and port * */ static sip_route_t *sip_any_route_create(su_home_t *home, msg_hclass_t *hc, url_t const *rq_url, url_t const *maddr) { sip_header_t *h; sip_route_t *rr; url_t url[1]; size_t xtra, n, n_url, n_params, n_addr; char *b, *param; *url = *rq_url; if (maddr) { url->url_port = maddr->url_port; url->url_params = NULL; } n_url = url_xtra(url); n_params = maddr && maddr->url_params ? strlen(maddr->url_params) : 0; if (maddr && (!maddr->url_params || !url_param(maddr->url_params, "maddr", NULL, 0))) n_addr = (n_params != 0) + strlen("maddr=") + strlen(maddr->url_host); else n_addr = 0; xtra = n_url + n_params + n_addr + (n_params || n_addr); h = sip_header_alloc(home, hc, xtra); if ((rr = (sip_record_route_t *)h)) { b = sip_header_data(h); n = url_dup(b, n_url, rr->r_url, url); assert(n == n_url); if (n_params || n_addr) { param = b + n_url; if (n_params) { rr->r_url->url_params = strcpy(param, maddr->url_params); param += n_params; } if (n_addr) { if (n_params) *param++ = ';'; strcpy(param, "maddr="), param += strlen("maddr="); strcpy(param, maddr->url_host), param += strlen(maddr->url_host); } assert(b + xtra == param + 1); } } return rr; } /* ====================================================================== */ /**@SIP_HEADER sip_route Route Header * * The Route headers is used to store the route set of a transaction. * The Route header is defined in @RFC3261 as follows: * * @code * Route = "Route" HCOLON route-param *(COMMA route-param) * route-param = name-addr *( SEMI rr-param ) * @endcode * * The parsed Route header is stored in #sip_route_t structure. */ /**@ingroup sip_route * @typedef typedef struct sip_route_s sip_route_t; * * The structure #sip_route_t contains representation of SIP @Route header. * * The #sip_route_t is defined as follows: * @code * typedef struct sip_route_s { * sip_common_t r_common[1]; // Common fragment info * sip_route_t *r_next; // Link to next @Route * char const *r_display; // Display name * url_t r_url[1]; // @Route URL * msg_param_t const *r_params; // List of route parameters * } sip_route_t; * @endcode */ msg_hclass_t sip_route_class[] = SIP_HEADER_CLASS(route, "Route", "", r_params, append, any_route); issize_t sip_route_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return sip_any_route_d(home, h, s, slen); } issize_t sip_route_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { assert(sip_is_route(h)); return sip_any_route_e(b, bsiz, h, flags); } /**@ingroup sip_route * @brief Create a @Route header object. * * Creates a route entry from two URLs; first one provides the URL, second * maddr parameter and port. * * @param home memory home * @param url route URL * @param maddr optional route address and port * * @return * Returns a pointer to newly created @Route header object when successful, * or NULL upon an error. */ sip_route_t *sip_route_create(su_home_t *home, url_t const *url, url_t const *maddr) { return sip_any_route_create(home, sip_route_class, url, maddr); } /* ====================================================================== */ /**@SIP_HEADER sip_record_route Record-Route Header * * The Record-Route headers are used to establish a route for transactions * belonging to a session. The Record-Route header is defined in @RFC3261 * as follows: * * @code * Record-Route = "Record-Route" HCOLON rec-route *(COMMA rec-route) * rec-route = name-addr *( SEMI rr-param ) * rr-param = generic-param * @endcode * * The parsed Record-Route header is stored in #sip_record_route_t structure. */ /**@ingroup sip_record_route * @typedef typedef struct sip_record_route_s sip_record_route_t; * * The structure #sip_record_route_t contains representation of SIP * @RecordRoute header. * * The #sip_record_route_t is defined as follows: * @code * typedef struct sip_route_s { * sip_common_t r_common[1]; // Common fragment info * sip_record_route_t *r_next; // Link to next * char const *r_display; // Display name * url_t r_url[1]; // @RecordRoute URL * msg_param_t const *r_params; // List of route parameters * } sip_record_route_t; * @endcode */ msg_hclass_t sip_record_route_class[] = SIP_HEADER_CLASS(record_route, "Record-Route", "", r_params, prepend, any_route); issize_t sip_record_route_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return sip_any_route_d(home, h, s, slen); } issize_t sip_record_route_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { assert(sip_is_record_route(h)); return sip_any_route_e(b, bsiz, h, flags); } /** @ingroup sip_record_route * * Create a record-route. * * Create a record-route entry from two URLs; first one provides the URL, * second maddr parameter and port. * * @param home memory home * @param rq_url route URL * @param maddr optional route address and port * * @return * A pointer to newly created @RecordRoute header object when successful or * NULL upon an error. */ sip_record_route_t *sip_record_route_create(su_home_t *home, url_t const *rq_url, url_t const *maddr) { return sip_any_route_create(home, sip_record_route_class, rq_url, maddr); } /* ====================================================================== */ /**@SIP_HEADER sip_to To Header * * The To header field specifies the "logical" recipient of the * request. It is defined in @RFC3261 as follows: * * @code * To = ( "To" / "t" ) HCOLON ( name-addr * / addr-spec ) *( SEMI to-param ) * to-param = tag-param / generic-param * @endcode * * The parsed To header is stored in #sip_to_t structure. */ /**@ingroup sip_to * @typedef typedef struct sip_addr_s sip_to_t; * * The structure #sip_to_t contains representation of @To header. * * The #sip_to_t is defined as follows: * @code * typedef struct { * sip_common_t a_common[1]; // Common fragment info * sip_error_t *a_next; // Link to next (dummy) * char const *a_display; // Display name * url_t a_url[1]; // URL * msg_param_t const *a_params; // List of to-params * char const *a_comment; // Comment * char const *a_tag; // Tag parameter * } sip_to_t; * @endcode * */ msg_hclass_t sip_to_class[] = SIP_HEADER_CLASS(to, "To", "t", a_params, single, addr); issize_t sip_to_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return sip_addr_d(home, h, s, slen); } issize_t sip_to_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { assert(sip_is_to(h)); return sip_addr_e(b, bsiz, h, flags); } /**@ingroup sip_to * * Create a @To header object with URL. * * @param home memory home * @param url URL (string or pointer to url_t) * * @return * A pointer to newly created @To header object when successful or NULL upon * an error. */ sip_to_t * sip_to_create(su_home_t *home, url_string_t const *url) { return sip_addr_make_url(home, sip_to_class, url); } /**@ingroup sip_to * * Add a parameter to a #sip_to_t object. * * @note This function @b does @b not duplicate @p param. * * @param home memory home * @param to #sip_to_t structure * @param param parameter string * * @retval 0 when successful * @retval -1 upon an error * * @deprecated Use msg_header_replace_param() directly. */ int sip_to_add_param(su_home_t *home, sip_to_t *to, char const *param) { return msg_header_replace_param(home, to->a_common, param); } /* ====================================================================== */ /**@SIP_HEADER sip_via Via Header * * The Via header indicates the path taken by the request so far. Via * headers can be used to prevent request looping and ensure replies take * the same path as the requests. The Via syntax is defined in @RFC3261 * as follows: * * @code * Via = ( "Via" / "v" ) HCOLON via-parm *(COMMA via-parm) * via-parm = sent-protocol LWS sent-by *( SEMI via-params ) * via-params = via-ttl / via-maddr * / via-received / via-branch * / via-extension * via-ttl = "ttl" EQUAL ttl * via-maddr = "maddr" EQUAL host * via-received = "received" EQUAL (IPv4address / IPv6address) * via-branch = "branch" EQUAL token * via-extension = generic-param * sent-protocol = protocol-name SLASH protocol-version * SLASH transport * protocol-name = "SIP" / token * protocol-version = token * transport = "UDP" / "TCP" / "TLS" / "SCTP" * / other-transport * sent-by = host [ COLON port ] * ttl = 1*3DIGIT ; 0 to 255 * @endcode * * @note * The @RFC2543 syntax allowed . We accept it, but don't encode it. * * In addition to the parameters defined in @RFC3261, @RFC3486 defines a * parameter "comp": * @code * via-compression = "comp" EQUAL ("sigcomp" / other-compression) * via-params /= via-compression * @endcode * * @RFC3581 defines a parameter "rport": * @code * response-port = "rport" [EQUAL 1*DIGIT] * via-params /= response-port * @endcode * * The parsed Via header is stored in #sip_via_t structure. */ /**@ingroup sip_via * @typedef typedef struct sip_via_s sip_via_t; * * The structure #sip_via_t contains representation of SIP @Via header. * * The #sip_via_t is defined as follows: * @code * typedef struct sip_via_s { * sip_common_t v_common[1]; // Common fragment info * sip_via_t *v_next; // Link to next @Via header * char const *v_protocol; // Application and transport protocol * char const *v_host; // Hostname * char const *v_port; // Port number * msg_param_t const *v_params; // List of via-params * char const *v_comment; // Comment * * char const *v_ttl; // "ttl" parameter * char const *v_maddr; // "maddr" parameter * char const *v_received; // "received" parameter * char const *v_branch; // "branch" parameter * char const *v_comp; // "comp" parameter * char const *v_rport; // "rport" parameter * } sip_via_t; * @endcode */ static msg_xtra_f sip_via_dup_xtra; static msg_dup_f sip_via_dup_one; static msg_update_f sip_via_update; msg_hclass_t sip_via_class[] = SIP_HEADER_CLASS(via, "Via", "v", v_params, prepend, via); issize_t sip_via_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_via_t *v = (sip_via_t *)h; assert(h); while (*s == ',') /* Ignore empty entries (comma-whitespace) */ *s = '\0', s += span_lws(s + 1) + 1; /* sent-protocol sent-by *( ";" via-params ) [ comment ] */ /* Parse protocol */ if (sip_transport_d(&s, &v->v_protocol) == -1) return -1; /* Host (and port) */ if (msg_hostport_d(&s, &v->v_host, &v->v_port) == -1) return -1; /* Parameters */ if (*s == ';' && msg_params_d(home, &s, &v->v_params) == -1) return -1; /* Comment */ if (*s == '(' && msg_comment_d(&s, &v->v_comment) == -1) return -1; return msg_parse_next_field(home, h, s, slen); } issize_t sip_via_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { char *b0 = b, *end = b + bsiz; sip_via_t const *v = (sip_via_t *)h; assert(sip_is_via(h)); MSG_STRING_E(b, end, v->v_protocol); MSG_CHAR_E(b, end, ' '); MSG_STRING_E(b, end, v->v_host); if (v->v_port) { MSG_CHAR_E(b, end, ':'); MSG_STRING_E(b, end, v->v_port); } MSG_PARAMS_E(b, end, v->v_params, flags); #if 0 /* Comment is deprecated in @RFC3265 - accept it, but do not send */ if (v->v_comment) { if (!MSG_IS_COMPACT(flags)) MSG_CHAR_E(b, end, ' '); MSG_CHAR_E(b, end, '('); MSG_STRING_E(b, end, v->v_comment); MSG_CHAR_E(b, end, ')'); } #endif MSG_TERM_E(b, end); return b - b0; } isize_t sip_via_dup_xtra(sip_header_t const *h, isize_t offset) { sip_via_t const *v = (sip_via_t *)h; MSG_PARAMS_SIZE(offset, v->v_params); offset += sip_transport_xtra(v->v_protocol); offset += MSG_STRING_SIZE(v->v_host); offset += MSG_STRING_SIZE(v->v_port); offset += MSG_STRING_SIZE(v->v_comment); return offset; } /** Duplicate one #sip_via_t object */ char *sip_via_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { sip_via_t *v = (sip_via_t *)dst; sip_via_t const *o = (sip_via_t *)src; char *end = b + xtra; b = msg_params_dup(&v->v_params, o->v_params, b, xtra); sip_transport_dup(&b, &v->v_protocol, o->v_protocol); MSG_STRING_DUP(b, v->v_host, o->v_host); MSG_STRING_DUP(b, v->v_port, o->v_port); MSG_STRING_DUP(b, v->v_comment, o->v_comment); assert(b <= end); (void)end; return b; } static int sip_via_update(msg_common_t *h, char const *name, isize_t namelen, char const *value) { sip_via_t *v = (sip_via_t *)h; if (name == NULL) { v->v_ttl = NULL; v->v_maddr = NULL; v->v_received = NULL; v->v_branch = NULL; v->v_rport = NULL; v->v_comp = NULL; } #define MATCH(s) (namelen == strlen(#s) && su_casenmatch(name, #s, strlen(#s))) else if (MATCH(ttl)) { v->v_ttl = value; } else if (MATCH(maddr)) { v->v_maddr = value; } else if (MATCH(received)) { v->v_received = value; } else if (MATCH(branch)) { v->v_branch = value; } else if (MATCH(rport)) { v->v_rport = value; } else if (MATCH(comp)) { v->v_comp = value; } #undef MATCH return 0; } /**@ingroup sip_via * * Add a parameter to a @Via object. * * @note This function @b does @b not duplicate @p param. * * @param home memory home * @param v #sip_via_t object * @param param parameter string * * @retval 0 when successful * @retval -1 upon an error. * * @deprecated Use msg_header_replace_param() directly. */ int sip_via_add_param(su_home_t *home, sip_via_t *v, char const *param) { return msg_header_replace_param(home, v->v_common, param); } /**@ingroup sip_via * * Create a @Via object. * * Create a new @Via header object with * given parameters. If @a transport is NULL, the default transport * "SIP/2.0/UDP" is used. A NULL-terminated list of parameters can be * specified after transport. * * @param home memory home * @param host host name * @param port protocol port number * @param transport transport protocol (default is "SIP/2.0/UDP") * @param ... NULL-terminated list of parameters * * @return * A pointer to newly created * @Via header object when successful or NULL upon an error. */ sip_via_t *sip_via_create(su_home_t *home, char const *host, char const *port, char const *transport, /* char const *params */ ...) { sip_via_t *v, via[1] = {{{{ NULL }}}}; va_list params; via->v_common->h_class = sip_via_class; if (transport) via->v_protocol = transport; else via->v_protocol = sip_transport_udp; via->v_host = host; via->v_port = port; v = (sip_via_t *)msg_header_dup_as(home, sip_via_class, (sip_header_t *)via); if (v) { char const *param; va_start(params, transport); for (param = va_arg(params, char const *); param; param = va_arg(params, char const *)) { if ((param = su_strdup(home, param))) { if (msg_header_replace_param(home, v->v_common, param) < 0) break; } } va_end(params); } return v; } /**@ingroup sip_via * * Get port number corresponding to a @Via line. * * If @a using_rport is non-null, try rport. * If *using_rport is non-zero, try rport even if is not UDP. * If is UDP, set *using_rport to zero. */ char const *sip_via_port(sip_via_t const *v, int *using_rport) { if (v == NULL) return NULL; if (using_rport) { char const *port; if (v->v_rport && !v->v_maddr /* multicast */) { if (v->v_protocol == sip_transport_udp || su_casematch(v->v_protocol, sip_transport_udp)) port = v->v_rport, *using_rport = 0; else if (*using_rport) port = v->v_rport; else port = NULL; if (port && port[0]) return port; } *using_rport = 0; /* No, we don't... */ } if (v->v_port) return v->v_port; if (sip_transport_has_tls(v->v_protocol)) return SIPS_DEFAULT_SERV; /* 5061 */ else return SIP_DEFAULT_SERV; /* 5060 */ } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sip_caller_prefs.c000066400000000000000000000304331223300710500240300ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE sip_caller_prefs.c * @brief SIP headers related to Caller Preferences * * Implementation of header classes for Caller-Preferences-related SIP * headers @AcceptContact, @RejectContact, and @RequestDisposition. * * @author Remeres Jacobs * @author Pekka Pessi * * @date Created: Th 23.01.2003 */ #include "config.h" /* Avoid casting sip_t to msg_pub_t and sip_header_t to msg_header_t */ #define MSG_PUB_T struct sip_s #define MSG_HDR_T union sip_header_u #include "sofia-sip/sip_parser.h" #include #include #include #include #include /* ====================================================================== */ /**@SIP_HEADER sip_request_disposition Request-Disposition Header * * The Request-Disposition header syntax is defined in * @RFC3841 section 10 as follows: * * @code * Request-Disposition = ( "Request-Disposition" | "d" ) HCOLON * directive *(COMMA directive) * directive = proxy-directive / cancel-directive / * fork-directive / recurse-directive / * parallel-directive / queue-directive) * proxy-directive = "proxy" / "redirect" * cancel-directive = "cancel" / "no-cancel" * fork-directive = "fork" / "no-fork" * recurse-directive = "recurse" / "no-recurse" * parallel-directive = "parallel" / "sequential" * queue-directive = "queue" / "no-queue" * @endcode * * * The parsed Request-Disposition header * is stored in #sip_request_disposition_t structure. */ /**@ingroup sip_request_disposition * @typedef typedef struct sip_request_disposition_s sip_request_disposition_t; * * The structure #sip_request_disposition_t contains representation of * @RequestDisposition header. * * The #sip_request_disposition_t is defined as follows: * @code * typedef struct sip_request_disposition_s * { * sip_common_t rd_common[1]; // Common fragment info * sip_unknown_t *rd_next; // Link to next (dummy) * msg_param_t *rd_items; // List of directives * } sip_request_disposition_t; * @endcode */ static msg_xtra_f sip_request_disposition_dup_xtra; static msg_dup_f sip_request_disposition_dup_one; #define sip_request_disposition_update NULL msg_hclass_t sip_request_disposition_class[] = SIP_HEADER_CLASS(request_disposition, "Request-Disposition", "d", rd_items, list, request_disposition); issize_t sip_request_disposition_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_request_disposition_t *rd = h->sh_request_disposition; return msg_commalist_d(home, &s, &rd->rd_items, msg_token_scan); } issize_t sip_request_disposition_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { char *end = b + bsiz, *b0 = b; sip_request_disposition_t const *o = h->sh_request_disposition; assert(sip_is_request_disposition(h)); MSG_COMMALIST_E(b, end, o->rd_items, flags); return b - b0; } isize_t sip_request_disposition_dup_xtra(sip_header_t const *h, isize_t offset) { sip_request_disposition_t const *o = h->sh_request_disposition; MSG_PARAMS_SIZE(offset, o->rd_items); return offset; } /** Duplicate one #sip_request_disposition_t object */ char *sip_request_disposition_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { char *end = b + xtra; sip_request_disposition_t *o_dst = dst->sh_request_disposition; sip_request_disposition_t const *o_src = src->sh_request_disposition; msg_param_t const **dst_items = (msg_param_t const **)&o_dst->rd_items; b = msg_params_dup(dst_items, o_src->rd_items, b, xtra); assert(b <= end); (void)end; return b; } /* ====================================================================== */ /**@ingroup sip_caller_prefs * * Add a parameter to a @AcceptContact or @RejectContact header object. * * @note This function does not duplicate @p param. * * @param home memory home * @param cp pointer to #sip_accept_contact_t or #sip_reject_contact_t * @param param parameter string * * @retval 0 when successful * @retval -1 upon an error * * @deprecated Use msg_header_replace_param() instead. */ int sip_caller_prefs_add_param(su_home_t *home, sip_caller_prefs_t *cp, char const *param) { return msg_header_replace_param(home, cp->cp_common, param); } static size_t span_attribute_value(char *s) { size_t n; n = span_token_lws(s); if (n > 0 && s[n] == '=') { n += 1 + span_lws(s + n + 1); if (s[n] == '"') n += span_quoted(s + n); else n += span_token(s + n); n += span_lws(s + n); } return n; } static issize_t sip_caller_prefs_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_caller_prefs_t *cp = (sip_caller_prefs_t *)h; url_t url[1]; char const *ignore = NULL; int kludge = 0; assert(h); while (*s == ',') /* Ignore empty entries (comma-whitespace) */ *s = '\0', s += span_lws(s + 1) + 1; /* Kludge: support PoC IS spec with a typo... */ if (su_casenmatch(s, "*,", 2)) s[1] = ';', kludge = 0; else if (s[0] != '*' && s[0] != '<') { /* Kludge: missing URL - */ size_t n = span_attribute_value(s); kludge = n > 0 && (s[n] == '\0' || s[n] == ',' || s[n] == ';'); } if (kludge) { if (msg_any_list_d(home, &s, (msg_param_t **)&cp->cp_params, msg_attribute_value_scanner, ';') == -1) return -1; } /* Parse params (and ignore display name and url) */ else if (sip_name_addr_d(home, &s, &ignore, url, &cp->cp_params, NULL) == -1) return -1; /* Be liberal... */ /* if (url->url_type != url_any) return -1; */ return msg_parse_next_field(home, h, s, slen); } static issize_t sip_caller_prefs_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { sip_caller_prefs_t const *cp = h->sh_caller_prefs; char *b0 = b, *end = b + bsiz; MSG_CHAR_E(b, end, '*'); MSG_PARAMS_E(b, end, cp->cp_params, flags); MSG_TERM_E(b, end); return b - b0; } static isize_t sip_caller_prefs_dup_xtra(sip_header_t const *h, isize_t offset) { sip_caller_prefs_t const *cp = h->sh_caller_prefs; MSG_PARAMS_SIZE(offset, cp->cp_params); return offset; } static char *sip_caller_prefs_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { char *end = b + xtra; sip_caller_prefs_t *cp = dst->sh_caller_prefs; sip_caller_prefs_t const *o = src->sh_caller_prefs; b = msg_params_dup(&cp->cp_params, o->cp_params, b, xtra); assert(b <= end); (void)end; return b; } /**@SIP_HEADER sip_accept_contact Accept-Contact Header * * The Accept-Contact syntax is defined in @RFC3841 section 10 as follows: * * @code * Accept-Contact = ("Accept-Contact" / "a") HCOLON ac-value * *(COMMA ac-value) * ac-value = "*" *(SEMI ac-params) * ac-params = feature-param / req-param * / explicit-param / generic-param * ;;feature param from RFC 3840 * ;;generic-param from RFC 3261 * req-param = "require" * explicit-param = "explicit" * @endcode * * Despite the BNF, there MUST NOT be more than one req-param or * explicit-param in an ac-params. Furthermore, there can only be one * instance of any feature tag in feature-param. * * @sa @RFC3840, @RFC3841, sip_contact_accept(), sip_contact_score(). * * The parsed Accept-Contact header * is stored in #sip_accept_contact_t structure. */ /**@ingroup sip_accept_contact * @typedef struct sip_caller_prefs_s sip_accept_contact_t; * * The structure #sip_accept_contact_t contains representation of SIP * @AcceptContact header. * * The #sip_accept_contact_t is defined as follows: * @code * typedef struct caller_prefs_s { * sip_common_t cp_common[1]; // Common fragment info * sip_caller_prefs_t *cp_next; // Link to next ac-value * msg_param_t const *cp_params; // List of parameters * char const *cp_q; // Priority * unsigned cp_require :1; // Shortcut to "require" parameter * unsigned cp_explicit :1; // Shortcut to "explicit" parameter * } sip_accept_contact_t; * @endcode */ #define sip_accept_contact_dup_xtra sip_caller_prefs_dup_xtra #define sip_accept_contact_dup_one sip_caller_prefs_dup_one static int sip_accept_contact_update(msg_common_t *h, char const *name, isize_t namelen, char const *value); msg_hclass_t sip_accept_contact_class[] = SIP_HEADER_CLASS(accept_contact, "Accept-Contact", "a", cp_params, append, accept_contact); issize_t sip_accept_contact_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return sip_caller_prefs_d(home, h, s, slen); } issize_t sip_accept_contact_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { return sip_caller_prefs_e(b, bsiz, h, flags); } static int sip_accept_contact_update(msg_common_t *h, char const *name, isize_t namelen, char const *value) { sip_caller_prefs_t *cp = (sip_caller_prefs_t *)h; if (name == NULL) { cp->cp_q = NULL; cp->cp_require = 0; cp->cp_explicit = 0; } #define MATCH(s) (namelen == strlen(#s) && su_casenmatch(name, #s, strlen(#s))) #if nomore else if (MATCH(q)) { cp->cp_q = value; } #endif else if (MATCH(require)) { cp->cp_require = value != NULL; } else if (MATCH(explicit)) { cp->cp_explicit = value != NULL; } #undef MATCH return 0; } /**@SIP_HEADER sip_reject_contact Reject-Contact Header * * The Reject-Contact syntax is defined in @RFC3841 section 10 as follows: * * @code * Reject-Contact = ("Reject-Contact" / "j") HCOLON rc-value * *(COMMA rc-value) * rc-value = "*" *(SEMI rc-params) * rc-params = feature-param / generic-param * ;;feature param from RFC 3840 * ;;generic-param from RFC 3261 * @endcode * * Despite the BNF, there MUST NOT be more than one instance of any feature * tag in feature-param. * * @sa @RFC3840, @RFC3841, sip_contact_reject(), sip_contact_score(). * * The parsed Reject-Contact header * is stored in #sip_reject_contact_t structure. */ /**@ingroup sip_reject_contact * @typedef struct sip_caller_prefs_s sip_reject_contact_t; * * The structure #sip_reject_contact_t contains representation of SIP * @RejectContact header. * * The #sip_reject_contact_t is defined as follows: * @code * typedef struct caller_prefs_s { * sip_common_t cp_common[1]; // Common fragment info * sip_caller_prefs_t *cp_next; // Link to next rc-value * msg_param_t const *cp_params; // List of parameters * } sip_reject_contact_t; * @endcode * * @note Fields @c cp_q, @c cp_require and @c cp_explicit are ignored for * @RejectContact header. */ #define sip_reject_contact_dup_xtra sip_caller_prefs_dup_xtra #define sip_reject_contact_dup_one sip_caller_prefs_dup_one #define sip_reject_contact_update NULL msg_hclass_t sip_reject_contact_class[] = SIP_HEADER_CLASS(reject_contact, "Reject-Contact", "j", cp_params, append, reject_contact); issize_t sip_reject_contact_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return sip_caller_prefs_d(home, h, s, slen); } issize_t sip_reject_contact_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { return sip_caller_prefs_e(b, bsiz, h, flags); } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sip_event.c000066400000000000000000000402211223300710500225040ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE sip_event.c * @brief Event SIP headers. * * Implementation of header classes for event-related SIP headers @Event, * @AllowEvents, and @SubscriptionState. * * @author Pekka Pessi . * * @date Created: Thu Sep 13 21:24:15 EEST 2001 ppessi */ #include "config.h" /* Avoid casting sip_t to msg_pub_t and sip_header_t to msg_header_t */ #define MSG_PUB_T struct sip_s #define MSG_HDR_T union sip_header_u #include "sofia-sip/sip_parser.h" #include #include #include #include #include #include /* ====================================================================== */ /**@SIP_HEADER sip_event Event Header * * The Event header is used to indicate the which event or class of events * the message contains or subscribes. Its syntax is defined in @RFC3265 as * follows: * * @code * Event = ( "Event" / "o" ) HCOLON event-type * *( SEMI event-param ) * event-type = event-package *( "." event-template ) * event-package = token-nodot * event-template = token-nodot * token-nodot = 1*( alphanum / "-" / "!" / "%" / "*" * / "_" / "+" / "`" / "'" / "~" ) * event-param = generic-param / ( "id" EQUAL token ) * @endcode * * The parsed Event header is stored in #sip_event_t structure. */ /**@ingroup sip_event * @typedef struct sip_event_s sip_event_t; * * The structure #sip_event_t contains representation of an @Event header. * * The #sip_event_t is defined as follows: * @code * typedef struct sip_event_s * { * sip_common_t o_common; // Common fragment info * sip_error_t *o_next; // Link to next (dummy) * char const * o_type; // Event type * msg_param_t const *o_params; // List of parameters * char const *o_id; // Event ID * } sip_event_t; * @endcode */ static msg_xtra_f sip_event_dup_xtra; static msg_dup_f sip_event_dup_one; static msg_update_f sip_event_update; msg_hclass_t sip_event_class[] = SIP_HEADER_CLASS(event, "Event", "o", o_params, single, event); issize_t sip_event_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_event_t *o = h->sh_event; size_t n; n = span_token(s); if (n == 0) return -1; o->o_type = s; s += n; while (IS_LWS(*s)) { *s++ = '\0'; } if (*s == ';') { if (msg_params_d(home, &s, &o->o_params) < 0 || *s) return -1; msg_header_update_params(o->o_common, 0); } return 0; } issize_t sip_event_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { char *end = b + bsiz, *b0 = b; sip_event_t const *o = h->sh_event; assert(sip_is_event(h)); MSG_STRING_E(b, end, o->o_type); MSG_PARAMS_E(b, end, o->o_params, flags); return b - b0; } isize_t sip_event_dup_xtra(sip_header_t const *h, isize_t offset) { sip_event_t const *o = h->sh_event; MSG_PARAMS_SIZE(offset, o->o_params); offset += MSG_STRING_SIZE(o->o_type); return offset; } /** Duplicate one #sip_event_t object */ char *sip_event_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { sip_event_t *o_dst = dst->sh_event; sip_event_t const *o_src = src->sh_event; char *end = b + xtra; b = msg_params_dup(&o_dst->o_params, o_src->o_params, b, xtra); MSG_STRING_DUP(b, o_dst->o_type, o_src->o_type); assert(b <= end); (void)end; return b; } /** Update parameters in @Event header. */ static int sip_event_update(msg_common_t *h, char const *name, isize_t namelen, char const *value) { sip_event_t *o = (sip_event_t *)h; if (name == NULL) { o->o_id = NULL; } else if (namelen == strlen("id") && su_casenmatch(name, "id", namelen)) { o->o_id = value; } return 0; } /* ====================================================================== */ /**@SIP_HEADER sip_allow_events Allow-Events Header * * The Allow-Events header is used to indicate which events or classes of * events the notifier supports. Its syntax is defined in @RFC3265 as * follows: * * @code * Allow-Events = ( "Allow-Events" / "u" ) HCOLON event-type * *(COMMA event-type) * @endcode * * The parsed Allow-Events header is stored in #sip_allow_events_t structure. * * Note that the event name is case-sensitive. The event "Presence" is * different from "presence". However, it is very unwise to use such event * names. * * @sa @Event, @RFC3265, msg_header_find_item(), msg_header_replace_item(), * msg_header_remove_item() */ /**@ingroup sip_allow_events * @typedef struct msg_list_s sip_allow_events_t; * * The structure #sip_allow_events_t contains representation of an * @AllowEvents header. * * The #sip_allow_events_t is defined as follows: * @code * typedef struct msg_list_s * { * msg_common_t k_common[1]; // Common fragment info * msg_list_t *k_next; // Link to next header * msg_param_t *k_items; // List of items * } sip_allow_events_t; * @endcode */ msg_hclass_t sip_allow_events_class[] = SIP_HEADER_CLASS_LIST(allow_events, "Allow-Events", "u", list); issize_t sip_allow_events_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return msg_list_d(home, h, s, slen); } issize_t sip_allow_events_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { assert(sip_is_allow_events(h)); return msg_list_e(b, bsiz, h, f); } /** Append an event to a @AllowEvents header. * * @note This function @b does @b duplicate @p event. * * @deprecated Use msg_header_replace_item() directly. */ int sip_allow_events_add(su_home_t *home, sip_allow_events_t *ae, char const *event) { event = su_strdup(home, event); if (!event) return -1; return msg_header_replace_item(home, ae->k_common, event); } /* ====================================================================== */ /**@SIP_HEADER sip_subscription_state Subscription-State Header * * The Subscription-State header is used to indicate in which state a * subscription is. Its syntax is defined in @RFC3265 section 4.2.4 as * follows: * * @code * Subscription-State = "Subscription-State" HCOLON substate-value * *( SEMI subexp-params ) * substate-value = "active" / "pending" / "terminated" * / extension-substate * extension-substate = token * subexp-params = ("reason" EQUAL event-reason-value) * / ("expires" EQUAL delta-seconds) * / ("retry-after" EQUAL delta-seconds) * / generic-param * event-reason-value = "deactivated" * / "probation" * / "rejected" * / "timeout" * / "giveup" * / "noresource" * / event-reason-extension * event-reason-extension = token * @endcode * * The parsed Subscription-State header * is stored in #sip_subscription_state_t structure. */ /**@ingroup sip_subscription_state * @typedef struct sip_subscription_state_s sip_subscription_state_t; * * The structure #sip_subscription_state_t contains representation of an * @SubscriptionState header. * * The #sip_subscription_state_t is defined as follows: * @code * typedef struct sip_subscription_state_s * { * sip_common_t ss_common[1]; * sip_unknown_t *ss_next; * // Subscription state: "pending", "active" or "terminated" * char const *ss_substate; * msg_param_t const *ss_params; // List of parameters * char const *ss_reason; // Reason of terminating * char const *ss_expires; // Subscription lifetime in seconds * char const *ss_retry_after; // Value of retry-after parameter * } sip_subscription_state_t; * @endcode */ static msg_xtra_f sip_subscription_state_dup_xtra; static msg_dup_f sip_subscription_state_dup_one; static msg_update_f sip_subscription_state_update; msg_hclass_t sip_subscription_state_class[] = SIP_HEADER_CLASS(subscription_state, "Subscription-State", "", ss_params, single, subscription_state); issize_t sip_subscription_state_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_subscription_state_t *ss = h->sh_subscription_state; ss->ss_substate = s; s += span_token(s); /* forwards the pointer to the end of substate-value */ if (s == ss->ss_substate) return -1; if (IS_LWS(*s)) { *s = '\0'; s += span_lws(s + 1) + 1; } /* check if parameters are present and if so parse them */ if (*s == ';') { if ( msg_params_d(home, &s, &ss->ss_params) < 0) return -1; if (msg_header_update_params(ss->ss_common, 0) < 0) return -1; } return 0; } issize_t sip_subscription_state_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { char *end = b + bsiz, *b0 = b; sip_subscription_state_t const *ss = h->sh_subscription_state; assert(sip_is_subscription_state(h)); MSG_STRING_E(b, end, ss->ss_substate); MSG_PARAMS_E(b, end, ss->ss_params, flags); return b - b0; } isize_t sip_subscription_state_dup_xtra(sip_header_t const *h, isize_t offset) { sip_subscription_state_t const *ss = h->sh_subscription_state; /* Calculates memory size occupied */ MSG_PARAMS_SIZE(offset, ss->ss_params); offset += MSG_STRING_SIZE(ss->ss_substate); return offset; } /** Duplicate one #sip_subscription_state_t object */ char *sip_subscription_state_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { sip_subscription_state_t *ss_dst = dst->sh_subscription_state; sip_subscription_state_t const *ss_src = src->sh_subscription_state; char *end = b + xtra; b = msg_params_dup(&ss_dst->ss_params, ss_src->ss_params, b, xtra); MSG_STRING_DUP(b, ss_dst->ss_substate, ss_src->ss_substate); assert(b <= end); (void)end; return b; } static int sip_subscription_state_update(msg_common_t *h, char const *name, isize_t namelen, char const *value) { sip_subscription_state_t *ss = (sip_subscription_state_t *)h; if (name == NULL) { ss->ss_reason = NULL; ss->ss_retry_after = NULL; ss->ss_expires = NULL; } #define MATCH(s) (namelen == strlen(#s) && su_casenmatch(name, #s, strlen(#s))) else if (MATCH(reason)) { ss->ss_reason = value; } else if (MATCH(retry-after)) { ss->ss_retry_after = value; } else if (MATCH(expires)) { ss->ss_expires = value; } #undef MATCH return 0; } #if 0 /* More dead headers */ /* ====================================================================== */ /**@SIP_HEADER sip_publication Publication Header * * The Publication header is used to indicate the which publication or class * of publications the message contains. Its syntax is defined * in (draft-niemi-simple-publish-00.txt) as follows: * * @code * Publication = ( "Publication") HCOLON publish-package * *( SEMI publish-param ) * publish-package = token-nodot * token-nodot = 1*( alphanum / "-" / "!" / "%" / "*" * / "_" / "+" / "`" / "'" / "~" ) * publish-param = generic-param / pstream / ptype * pstream = "stream" EQUAL token * ptype = "type" EQUAL token * @endcode * * * The parsed Publication header is stored in #sip_publication_t structure. */ /**@ingroup sip_publication * @brief Structure for Publication header. */ struct sip_publication_s { sip_common_t pub_common; /**< Common fragment info */ sip_error_t *pub_next; /**< Link to next (dummy) */ char const * pub_package; /**< Publication packaage */ msg_param_t const *pub_params; /**< List of parameters */ msg_param_t pub_type; /**< Publication type */ msg_param_t pub_stream; /**< Publication stream */ }; static msg_xtra_f sip_publication_dup_xtra; static msg_dup_f sip_publication_dup_one; msg_hclass_t sip_publication_class[] = SIP_HEADER_CLASS(publication, "Publication", "", pub_params, single, publication); su_inline void sip_publication_update(sip_publication_t *pub); issize_t sip_publication_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_publication_t *pub = h->sh_publication; size_t n; n = span_token(s); if (n == 0) return -1; pub->pub_package = s; s += n; while (IS_LWS(*s)) { *s++ = '\0'; } if (*s == ';') { if (msg_params_d(home, &s, &pub->pub_params) < 0 || *s) return -1; sip_publication_update(pub); } return 0; } issize_t sip_publication_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { char *end = b + bsiz, *b0 = b; sip_publication_t const *pub = h->sh_publication; assert(sip_is_publication(h)); MSG_STRING_E(b, end, pub->pub_package); MSG_PARAMS_E(b, end, pub->pub_params, flags); return b - b0; } isize_t sip_publication_dup_xtra(sip_header_t const *h, isize_t offset) { sip_publication_t const *pub = h->sh_publication; MSG_PARAMS_SIZE(offset, pub->pub_params); offset += MSG_STRING_SIZE(pub->pub_package); return offset; } /** Duplicate one #sip_publication_t object */ char *sip_publication_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { sip_publication_t *pub_dst = dst->sh_publication; sip_publication_t const *pub_src = src->sh_publication; char *end = b + xtra; b = msg_params_dup(&pub_dst->pub_params, pub_src->pub_params, b, xtra); MSG_STRING_DUP(b, pub_dst->pub_package, pub_src->pub_package); if (pub_dst->pub_params) sip_publication_update(pub_dst); assert(b <= end); return b; } su_inline void sip_publication_update(sip_publication_t *pub) { size_t i; if (pub->pub_params) for (i = 0; pub->pub_params[i]; i++) { if (su_casenmatch(pub->pub_params[i], "stream=", strlen("stream="))) pub->pub_stream = pub->pub_params[i] + strlen("stream="); else if (su_casenmatch(pub->pub_params[i], "type=", strlen("type="))) pub->pub_type = pub->pub_params[i] + strlen("type="); } } /* ====================================================================== */ /**@SIP_HEADER sip_allow_publications Allow-Publication Header * * The Allow-Publication header is used to indicate which publications or classes of * publications the server supports. Its syntax is defined in [niemi] * (draft-niemi-simple-publish-00.txt) as follows: * * @code * Allow-Publications = "Allow-Publications" HCOLON publish-type * * ( COMMA publish-type ) * @endcode * * * The parsed Allow-Publication Header * is stored in #sip_allow_publications_t structure. */ msg_hclass_t sip_allow_publications_class[] = SIP_HEADER_CLASS_LIST(allow_publications, "Allow-Publications", "", list); issize_t sip_allow_publications_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return msg_list_d(home, h, s, slen); } issize_t sip_allow_publications_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { assert(sip_is_allow_publications(h)); return msg_list_e(b, bsiz, h, f); } /** Append an publication to a Allow-Publications header. */ int sip_allow_publications_add(su_home_t *home, sip_allow_publications_t *ae, char const *e) { e = su_strdup(home, e); if (!e) return -1; return msg_params_replace(home, (msg_param_t **)&ae->k_items, e); } #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sip_extra.c000066400000000000000000001215621223300710500225160ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE sip_extra.c * @brief Non-critical SIP headers * * This file contains implementation of @CallInfo, @ErrorInfo, * @Organization, @Priority, @RetryAfter, @Server, @Subject, * @Timestamp, and @UserAgent headers. * * @author Pekka Pessi . * * @date Created: Tue Jun 13 02:57:51 2000 ppessi */ #include "config.h" /* Avoid casting sip_t to msg_pub_t and sip_header_t to msg_header_t */ #define MSG_PUB_T struct sip_s #define MSG_HDR_T union sip_header_u #include "sofia-sip/sip_parser.h" #include "sofia-sip/sip_extra.h" #include #include #include #include #include #include /* ====================================================================== */ static issize_t sip_info_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen); static isize_t sip_info_dup_xtra(sip_header_t const *h, isize_t offset); static char *sip_info_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra); #define sip_info_update NULL /* ====================================================================== */ /**@SIP_HEADER sip_call_info Call-Info Header * * The Call-Info header provides additional information about the caller or * callee. Its syntax is defined in @RFC3261 as follows: * * @code * Call-Info = "Call-Info" HCOLON info *(COMMA info) * info = LAQUOT absoluteURI RAQUOT *( SEMI info-param) * info-param = ( "purpose" EQUAL ( "icon" / "info" * / "card" / token ) ) / generic-param * @endcode * * * The parsed Call-Info header is stored in #sip_call_info_t structure. */ /**@ingroup sip_call_info * @typedef struct sip_call_info_s sip_call_info_t; * * The structure #sip_call_info_t contains representation of an * @CallInfo header. * * The #sip_call_info_t is defined as follows: * @code * struct sip_call_info_s * { * sip_common_t ci_common[1]; // Common fragment info * sip_call_info_t *ci_next; // Link to next @CallInfo * url_t ci_url[1]; // URI to call info * msg_param_t const *ci_params; // List of parameters * char const *ci_purpose; // Value of @b purpose parameter * }; * @endcode */ #define sip_call_info_dup_xtra sip_info_dup_xtra #define sip_call_info_dup_one sip_info_dup_one static msg_update_f sip_call_info_update; msg_hclass_t sip_call_info_class[] = SIP_HEADER_CLASS(call_info, "Call-Info", "", ci_params, append, call_info); issize_t sip_call_info_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { issize_t retval = sip_info_d(home, h, s, slen); if (retval == 0) for (;h; h = h->sh_next) msg_header_update_params(h->sh_common, 0); return retval; } issize_t sip_call_info_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { sip_call_info_t *ci = (sip_call_info_t *)h; assert(sip_call_info_p(h)); return sip_name_addr_e(b, bsiz, f, NULL, 1, ci->ci_url, ci->ci_params, NULL); } /** @internal * Update parameter in a @CallInfo object. * */ static int sip_call_info_update(msg_common_t *h, char const *name, isize_t namelen, char const *value) { sip_call_info_t *ci = (sip_call_info_t *)h; if (name == NULL) { ci->ci_purpose = NULL; } else if (namelen == strlen("purpose") && su_casenmatch(name, "purpose", namelen)) { ci->ci_purpose = value; } return 0; } /* ====================================================================== */ /**@SIP_HEADER sip_error_info Error-Info Header * * The Error-Info header provides a pointer to additional information about * the error status response. Its syntax is defined in @RFC3261 as follows: * * @code * Error-Info = "Error-Info" HCOLON error-uri *(COMMA error-uri) * error-uri = LAQUOT absoluteURI RAQUOT *( SEMI generic-param ) * @endcode * * * The parsed Error-Info header is stored in #sip_error_info_t structure. */ /**@ingroup sip_error_info * @typedef struct sip_error_info_s sip_error_info_t; * * The structure #sip_error_info_t contains representation of an * @ErrorInfo header. * * The #sip_error_info_t is defined as follows: * @code * struct sip_error_info_s * { * sip_common_t ei_common[1]; // Common fragment info * sip_error_info_t *ei_next; // Link to next @ErrorInfo * url_t ei_url[1]; // URI to error info * msg_param_t const *ei_params; // List of parameters * }; * @endcode */ msg_hclass_t sip_error_info_class[] = SIP_HEADER_CLASS(error_info, "Error-Info", "", ei_params, append, info); issize_t sip_error_info_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return sip_info_d(home, h, s, slen); } issize_t sip_error_info_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { sip_error_info_t const *ei = h->sh_error_info; assert(sip_error_info_p(h)); return sip_name_addr_e(b, bsiz, f, NULL, 1, ei->ei_url, ei->ei_params, NULL); } /* ====================================================================== */ /**@SIP_HEADER sip_alert_info Alert-Info Header * * When present in an INVITE request, the Alert-Info header field * specifies an alternative ring tone to the UAS. When present in a 180 * (Ringing) response, the Alert-Info header field specifies an * alternative ringback tone to the UAC. A typical usage is for a proxy * to insert this header field to provide a distinctive ring feature. * * @code * Alert-Info = "Alert-Info" HCOLON alert-param *(COMMA alert-param) * alert-param = LAQUOT absoluteURI RAQUOT *(SEMI generic-param) * @endcode * * The parsed Alert-Info header is stored in #sip_alert_info_t structure. * * @NEW_1_12_7. In order to use @b Alert-Info header, initialize the SIP * parser before calling nta_agent_create() or nua_create() with, e.g., * sip_update_default_mclass(sip_extend_mclass(NULL)). * * The #sip_t structure does not contain a @a sip_alert_info field, but * sip_alert_info() function should be used for accessing the @b Alert-Info * header structure. */ /**@ingroup sip_alert_info * @typedef struct sip_alert_info_s sip_alert_info_t; * * The structure #sip_alert_info_t contains representation of an * @AlertInfo header. * * The #sip_alert_info_t is defined as follows: * @code * struct sip_alert_info_s * { * sip_common_t ai_common[1]; // Common fragment info * sip_alert_info_t *ai_next; // Link to next @AlertInfo * url_t ai_url[1]; // URI to alert info * msg_param_t const *ai_params; // List of optional parameters * }; * @endcode * * @NEW_1_12_7. */ msg_hclass_t sip_alert_info_class[] = SIP_HEADER_CLASS(alert_info, "Alert-Info", "", ai_params, append, info); issize_t sip_alert_info_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return sip_info_d(home, h, s, slen); } issize_t sip_alert_info_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { sip_alert_info_t *ai = (sip_alert_info_t *)h; return sip_name_addr_e(b, bsiz, f, NULL, 1, ai->ai_url, ai->ai_params, NULL); } /* ====================================================================== */ /**@SIP_HEADER sip_reply_to Reply-To Header * * The @b Reply-To header field contains a logical return URI that may be * different from the @From header field. For example, the URI MAY be used to * return missed calls or unestablished sessions. If the user wished to * remain anonymous, the header field SHOULD either be omitted from the * request or populated in such a way that does not reveal any private * information. Its syntax is defined in @RFC3261 as follows: * * @code * Reply-To = "Reply-To" HCOLON rplyto-spec * rplyto-spec = ( name-addr / addr-spec ) * *( SEMI rplyto-param ) * rplyto-param = generic-param * @endcode * * The parsed Reply-To header is stored in #sip_reply_to_t structure. * * @sa sip_update_default_mclass() * * @NEW_1_12_7. In order to use @b Reply-To header, * initialize the SIP parser before calling nta_agent_create() or * nua_create() with, e.g., * sip_update_default_mclass(sip_extend_mclass(NULL)). * * @note * The #sip_t structure does not contain a @a sip_reply_to field, but * sip_reply_to() function should be used for accessing the @b Reply-To * header structure. */ /**@ingroup sip_reply_to * @typedef struct msg_list_s sip_reply_to_t; * * The structure #sip_reply_to_t contains representation of SIP * @ReplyTo header. * * The #sip_reply_to_t is defined as follows: * @code * struct sip_reply_to_s * { * sip_common_t rplyto_common[1]; // Common fragment info * sip_error_t *rplyto_next; // Dummy link to next header * char const *rplyto_display; // Display name * url_t rplyto_url[1]; // Return URI * msg_param_t const *rplyto_params; // List of optional parameters * }; * @endcode */ static isize_t sip_reply_to_dup_xtra(sip_header_t const *h, isize_t offset); static char *sip_reply_to_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra); #define sip_reply_to_update NULL msg_hclass_t sip_reply_to_class[] = SIP_HEADER_CLASS(reply_to, "Reply-To", "", rplyto_params, single, reply_to); issize_t sip_reply_to_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_reply_to_t *rplyto = (sip_reply_to_t *)h; return sip_name_addr_d(home, &s, &rplyto->rplyto_display, rplyto->rplyto_url, &rplyto->rplyto_params, NULL); } issize_t sip_reply_to_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { sip_reply_to_t *rplyto = (sip_reply_to_t *)h; return sip_name_addr_e(b, bsiz, flags, rplyto->rplyto_display, MSG_IS_CANONIC(flags), rplyto->rplyto_url, rplyto->rplyto_params, NULL); } static isize_t sip_reply_to_dup_xtra(sip_header_t const *h, isize_t offset) { sip_reply_to_t const *rplyto = (sip_reply_to_t const *)h; return sip_name_addr_xtra(rplyto->rplyto_display, rplyto->rplyto_url, rplyto->rplyto_params, offset); } /**@internal Duplicate one sip_reply_to_t object. */ static char *sip_reply_to_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { sip_reply_to_t *rplyto = (sip_reply_to_t *)dst; sip_reply_to_t const *o = (sip_reply_to_t *)src; return sip_name_addr_dup(&rplyto->rplyto_display, o->rplyto_display, rplyto->rplyto_url, o->rplyto_url, &rplyto->rplyto_params, o->rplyto_params, b, xtra); } /* ====================================================================== */ /**@SIP_HEADER sip_in_reply_to In-Reply-To Header * * The @b In-Reply-To request header field enumerates the * @ref sip_call_id "Call-IDs" that this call references or returns. * Its syntax is defined in @RFC3261 as follows: * * @code * In-Reply-To = "In-Reply-To" HCOLON callid *(COMMA callid) * @endcode * * The parsed In-Reply-To header is stored in #sip_in_reply_to_t structure. */ /**@ingroup sip_in_reply_to * @typedef struct msg_list_s sip_in_reply_to_t; * * The structure #sip_in_reply_to_t contains representation of SIP * @InReplyTo header. * * The #sip_in_reply_to_t is defined as follows: * @code * typedef struct msg_list_s * { * msg_common_t k_common[1]; // Common fragment info * msg_list_t *k_next; // Link to next header * msg_param_t *k_items; // List of call ids * } sip_in_reply_to_t; * @endcode */ msg_hclass_t sip_in_reply_to_class[] = SIP_HEADER_CLASS_LIST(in_reply_to, "In-Reply-To", "", list); issize_t sip_in_reply_to_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return msg_list_d(home, h, s, slen); } issize_t sip_in_reply_to_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { assert(sip_in_reply_to_p(h)); return msg_list_e(b, bsiz, h, f); } /* ====================================================================== */ /**@SIP_HEADER sip_organization Organization Header * * The Organization header field conveys the name of the organization to * which the entity issuing the request or response belongs. Its syntax is * defined in @RFC3261 as follows: * * @code * Organization = "Organization" HCOLON [TEXT-UTF8-TRIM] * @endcode * * * The parsed Organization header is stored in #sip_organization_t structure. */ /**@ingroup sip_organization * @typedef struct msg_generic_s sip_organization_t; * * The structure #sip_organization_t contains representation of a SIP * @Organization header. * * The #sip_organization_t is defined as follows: * @code * typedef struct msg_generic_s * { * msg_common_t g_common[1]; // Common fragment info * msg_generic_t *g_next; // Link to next header * char const *g_string; // Organization text * } sip_organization_t; * @endcode */ msg_hclass_t sip_organization_class[] = SIP_HEADER_CLASS_G(organization, "Organization", "", single); issize_t sip_organization_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return sip_generic_d(home, h, s, slen); } issize_t sip_organization_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { assert(sip_organization_p(h)); return sip_generic_e(b, bsiz, h, f); } /* ====================================================================== */ /**@SIP_HEADER sip_priority Priority Header * * The Priority request-header field indicates the urgency of the request as * perceived by the client. Its syntax is defined in @RFC3261 as follows: * * @code * Priority = "Priority" HCOLON priority-value * priority-value = "emergency" / "urgent" / "normal" * / "non-urgent" / other-priority * other-priority = token * @endcode * * * The parsed Priority header is stored in #sip_priority_t structure. */ /**@ingroup sip_priority * @typedef struct msg_generic_s sip_priority_t; * * The structure #sip_priority_t contains representation of a SIP * @Priority header. * * The #sip_priority_t is defined as follows: * @code * typedef struct msg_generic_s * { * msg_common_t g_common[1]; // Common fragment info * msg_generic_t *g_next; // Dummy link to next header * char const *g_string; // Priority token * } sip_priority_t; * @endcode */ msg_hclass_t sip_priority_class[] = SIP_HEADER_CLASS_G(priority, "Priority", "", single); issize_t sip_priority_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_priority_t *priority = (sip_priority_t *)h; if (msg_token_d(&s, &priority->g_string) < 0) return -1; if (*s && !IS_LWS(*s)) /* Something extra after priority token? */ return -1; return 0; } issize_t sip_priority_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { assert(sip_priority_p(h)); return sip_generic_e(b, bsiz, h, f); } /* ====================================================================== */ /**@SIP_HEADER sip_server Server Header * * The Server response-header field contains information about the software * used by the user agent server to handle the request. Its syntax is * defined in @RFC2616 section 14.38 and @RFC3261 as follows: * * @code * Server = "Server" HCOLON server-val *(LWS server-val) * server-val = product / comment * product = token [SLASH product-version] * product-version = token * @endcode * * The parsed Server header is stored in #sip_server_t structure. */ /**@ingroup sip_server * @typedef struct msg_generic_s sip_server_t; * * The structure #sip_server_t contains representation of a SIP * @Server header. * * The #sip_server_t is defined as follows: * @code * typedef struct msg_generic_s * { * msg_common_t g_common[1]; // Common fragment info * msg_generic_t *g_next; // Link to next header * char const *g_string; // Server tokens * } sip_server_t; * @endcode */ msg_hclass_t sip_server_class[] = SIP_HEADER_CLASS_G(server, "Server", "", single); issize_t sip_server_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return sip_generic_d(home, h, s, slen); } issize_t sip_server_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { assert(sip_server_p(h)); return sip_generic_e(b, bsiz, h, f); } /* ====================================================================== */ /**@SIP_HEADER sip_subject Subject Header * * The Subject header provides a summary or indicates the nature of the * request. Its syntax is defined in @RFC3261 as follows: * * @code * Subject = ( "Subject" / "s" ) HCOLON [TEXT-UTF8-TRIM] * @endcode * * The parsed Subject header is stored in #sip_subject_t structure. */ /**@ingroup sip_subject * @typedef struct msg_generic_s sip_subject_t; * * The structure #sip_subject_t contains representation of a SIP * @Subject header. * * The #sip_subject_t is defined as follows: * @code * typedef struct msg_generic_s * { * msg_common_t g_common[1]; // Common fragment info * msg_generic_t *g_next; // Link to next header * char const *g_string; // Subject text * } sip_subject_t; * @endcode */ msg_hclass_t sip_subject_class[] = SIP_HEADER_CLASS_G(subject, "Subject", "s", single); issize_t sip_subject_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return sip_generic_d(home, h, s, slen); } issize_t sip_subject_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { assert(sip_subject_p(h)); return sip_generic_e(b, bsiz, h, f); } /* ====================================================================== */ /**@SIP_HEADER sip_timestamp Timestamp Header * * The @b Timestamp header describes when the client sent the request to the * server, and it is used by the client to adjust its retransmission * intervals. Its syntax is defined in @RFC3261 as follows: * * @code * Timestamp = "Timestamp" HCOLON 1*(DIGIT) * [ "." *(DIGIT) ] [ LWS delay ] * delay = *(DIGIT) [ "." *(DIGIT) ] * @endcode * * The parsed Timestamp header is stored in #sip_timestamp_t structure. */ /**@ingroup sip_timestamp * @typedef struct sip_timestamp_s sip_timestamp_t; * * The structure #sip_timestamp_t contains representation of a SIP * @Timestamp header. * * The #sip_timestamp_t is defined as follows: * @code * typedef struct sip_timestamp_s * { * sip_common_t ts_common[1]; // Common fragment info * sip_error_t *ts_next; // Dummy link * char const *ts_stamp; // Original timestamp * char const *ts_delay; // Delay at UAS * } sip_timestamp_t; * @endcode */ static isize_t sip_timestamp_dup_xtra(sip_header_t const *h, isize_t offset); static char *sip_timestamp_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra); #define sip_timestamp_update NULL msg_hclass_t sip_timestamp_class[] = SIP_HEADER_CLASS(timestamp, "Timestamp", "", ts_common, single, timestamp); issize_t sip_timestamp_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_timestamp_t *ts = (sip_timestamp_t*)h; ts->ts_stamp = s; s += span_digit(s); if (s == ts->ts_stamp) return -1; if (*s == '.') { s += span_digit(s + 1) + 1; } if (IS_LWS(*s)) { *s = '\0'; s += span_lws(s + 1) + 1; ts->ts_delay = s; s += span_digit(s); if (*s == '.') { s += span_digit(s + 1) + 1; } } if (!*s || IS_LWS(*s)) *s++ = '\0'; else return -1; return 0; } issize_t sip_timestamp_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { sip_timestamp_t const *ts = h->sh_timestamp; char *end = b + bsiz, *b0 = b; assert(sip_timestamp_p(h)); MSG_STRING_E(b, end, ts->ts_stamp); if (ts->ts_delay) { MSG_CHAR_E(b, end, ' '); MSG_STRING_E(b, end, ts->ts_delay); } MSG_TERM_E(b, end); return b - b0; } static isize_t sip_timestamp_dup_xtra(sip_header_t const *h, isize_t offset) { sip_timestamp_t const *ts = h->sh_timestamp; offset += MSG_STRING_SIZE(ts->ts_stamp); offset += MSG_STRING_SIZE(ts->ts_delay); return offset; } static char *sip_timestamp_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { sip_timestamp_t *ts = dst->sh_timestamp; sip_timestamp_t const *o = src->sh_timestamp; char *end = b + xtra; MSG_STRING_DUP(b, ts->ts_stamp, o->ts_stamp); MSG_STRING_DUP(b, ts->ts_delay, o->ts_delay); assert(b <= end); (void)end; return b; } /* ====================================================================== */ /**@SIP_HEADER sip_user_agent User-Agent Header * * The User-Agent header contains information about the client user agent * originating the request. Its syntax is defined in [H14.43, S10.45] as * follows: * * @code * User-Agent = "User-Agent" HCOLON server-val *(LWS server-val) * server-val = product / comment * product = token [SLASH product-version] * product-version = token * @endcode * * The parsed User-Agent header is stored in #sip_user_agent_t structure. */ /**@ingroup sip_user_agent * @typedef struct msg_generic_s sip_user_agent_t; * * The structure #sip_user_agent_t contains representation of a SIP * @UserAgent header. * * The #sip_user_agent_t is defined as follows: * @code * typedef struct msg_generic_s * { * msg_common_t g_common[1]; // Common fragment info * msg_generic_t *g_next; // Link to next header * char const *g_string; // User-Agent components * } sip_user_agent_t; * @endcode */ msg_hclass_t sip_user_agent_class[] = SIP_HEADER_CLASS_G(user_agent, "User-Agent", "", single); issize_t sip_user_agent_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return sip_generic_d(home, h, s, slen); } issize_t sip_user_agent_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { assert(sip_user_agent_p(h)); return sip_generic_e(b, bsiz, h, f); } /* ====================================================================== */ /**@SIP_HEADER sip_etag SIP-ETag Header * * The @b SIP-ETag header field identifies the published event state. Its * syntax is defined in @RFC3903 as follows: * * @code * SIP-ETag = "SIP-ETag" HCOLON entity-tag * entity-tag = token * @endcode * * The parsed SIP-ETag header is stored in #sip_etag_t structure. */ /**@ingroup sip_etag * @typedef struct msg_generic_s sip_etag_t; * * The structure #sip_etag_t contains representation of a SIP * @SIPETag header. * * The #sip_etag_t is defined as follows: * @code * typedef struct msg_generic_s * { * msg_common_t g_common[1]; // Common fragment info * msg_generic_t *g_next; // Link to next header * char const *g_string; // entity-tag * } sip_etag_t; * @endcode */ msg_hclass_t sip_etag_class[] = SIP_HEADER_CLASS_G(etag, "SIP-ETag", "", single); issize_t sip_etag_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_etag_t *etag = (sip_etag_t *)h; return msg_token_d(&s, &etag->g_value); } issize_t sip_etag_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { return msg_generic_e(b, bsiz, h, f); } /* ====================================================================== */ /**@SIP_HEADER sip_if_match SIP-If-Match Header * * The @b SIP-If-Match header field identifies the specific entity of event * state that the request is refreshing, modifying or removing. Its syntax * is defined in @RFC3903 as follows: * * @code * SIP-If-Match = "SIP-If-Match" HCOLON entity-tag * entity-tag = token * @endcode * * The parsed SIP-If-Match header is stored in #sip_if_match_t structure. */ /**@ingroup sip_if_match * @typedef struct msg_generic_s sip_if_match_t; * * The structure #sip_if_match_t contains representation of a SIP * @SIPIfMatch header. * * The #sip_if_match_t is defined as follows: * @code * typedef struct msg_generic_s * { * msg_common_t g_common[1]; // Common fragment info * msg_generic_t *g_next; // Link to next header * char const *g_string; // entity-tag * } sip_if_match_t; * @endcode */ msg_hclass_t sip_if_match_class[] = SIP_HEADER_CLASS_G(if_match, "SIP-If-Match", "", single); issize_t sip_if_match_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return sip_etag_d(home, h, s, slen); } issize_t sip_if_match_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { return sip_etag_e(b, bsiz, h, f); } /* ====================================================================== */ /** Parsing @CallInfo, @ErrorInfo. */ static issize_t sip_info_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_call_info_t *ci = h->sh_call_info; char *end = s + slen; assert(h); while (*s == ',') s += span_lws(s + 1) + 1; if (sip_name_addr_d(home, &s, NULL, ci->ci_url, &ci->ci_params, NULL) < 0) return -1; /* Recurse */ return msg_parse_next_field(home, h, s, end - s); } isize_t sip_info_dup_xtra(sip_header_t const *h, isize_t offset) { sip_call_info_t const *ci = h->sh_call_info; return sip_name_addr_xtra(NULL, ci->ci_url, ci->ci_params, offset); } char *sip_info_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { sip_call_info_t *ci = dst->sh_call_info; sip_call_info_t const *o = src->sh_call_info; return sip_name_addr_dup(NULL, NULL, ci->ci_url, o->ci_url, &ci->ci_params, o->ci_params, b, xtra); } /* ====================================================================== */ #if SU_HAVE_EXPERIMENTAL /**@SIP_HEADER sip_suppress_body_if_match Suppress-Body-If-Match Header * * The @b Suppress-Body-If-Match header field identifies a SIP event content * already known by the watcher. Its syntax is defined in * draft-niemi-sip-subnot-etags-01 as follows: * * @code * Suppress-Body-If-Match = "Suppress-Body-If-Match" HCOLON entity-tag * entity-tag = token * @endcode * * The parsed Suppress-Body-If-Match header is stored in * #sip_suppress_body_if_match_t structure. * * @sa @RFC3265, draft-niemi-sip-subnot-etags-01.txt * * @EXP_1_12_5. * In order to use @b Suppress-Body-If-Match header, * initialize the SIP parser with, e.g., * sip_update_default_mclass(sip_extend_mclass(NULL)). * * @note * The #sip_t structure does not contain a @a * sip_suppress_body_if_match field, but sip_suppress_body_if_match() * function should be used for accessing the @b Suppress-Body-If-Match * header structure. */ /**@ingroup sip_suppress_body_if_match * @typedef struct sip_suppress_body_if_match_s sip_suppress_body_if_match_t; * * The structure #sip_suppress_body_if_match_t contains representation of a * SIP @SuppressBodyIfMatch header. * * The #sip_suppress_body_if_match_t is defined as follows: * @code * typedef struct sip_suppress_body_if_match_s * { * sip_common_t sbim_common[1]; // Common fragment info * sip_error_t *sbim_next; // Dummy link to next header * char const *sbim_tag; // entity-tag * } sip_suppress_body_if_match_t; * @endcode */ #define sip_suppress_body_if_match_dup_xtra msg_generic_dup_xtra #define sip_suppress_body_if_match_dup_one msg_generic_dup_one #define sip_suppress_body_if_match_update NULL msg_hclass_t sip_suppress_body_if_match_class[] = SIP_HEADER_CLASS(suppress_body_if_match, "Suppress-Body-If-Match", "", sbim_common, single, suppress_body_if_match); issize_t sip_suppress_body_if_match_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_suppress_body_if_match_t *sbim = (void *)h; return msg_token_d(&s, &sbim->sbim_tag); } issize_t sip_suppress_body_if_match_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { return sip_etag_e(b, bsiz, h, f); } /* ====================================================================== */ /**@SIP_HEADER sip_suppress_notify_if_match Suppress-Notify-If-Match Header * * The @b Suppress-Notify-If-Match header is used to suppress * superfluous NOTIFY transactions. Its syntax is defined in * draft-niemi-sip-subnot-etags-01 as follows: * * @code * Suppress-Notify-If-Match = "Suppress-Notify-If-Match" HCOLON entity-tag * entity-tag = token * @endcode * * The parsed Suppress-Notify-If-Match header is stored in * #sip_suppress_notify_if_match_t structure. * * @sa @RFC3265, draft-niemi-sip-subnot-etag-01 * * @EXP_1_12_5. * In order to use @b Suppress-Notify-If-Match header, * initialize the SIP parser with, e.g., * sip_update_default_mclass(sip_extend_mclass(NULL)). * * @note * The #sip_t struct does not contain @a sip_suppress_notify_if_match field, * but sip_suppress_notify_if_match() function should be used for accessing * the @b Suppress-Notify-If-Match header structure. */ /**@ingroup sip_suppress_notify_if_match * @typedef struct sip_suppress_notify_if_match_s \ * sip_suppress_notify_if_match_t; * * The structure #sip_suppress_notify_if_match_t contains representation of a * SIP @SuppressNotifyIfMatch header. * * The #sip_suppress_notify_if_match_t is defined as follows: * @code * typedef struct sip_suppress_notify_if_match_s * { * sip_common_t snim_common[1]; // Common fragment info * sip_error_t *snim_next; // Dummy link to next header * char const *snim_tag; // entity-tag * } sip_suppress_notify_if_match_t; * @endcode */ #define sip_suppress_notify_if_match_dup_xtra msg_generic_dup_xtra #define sip_suppress_notify_if_match_dup_one msg_generic_dup_one #define sip_suppress_notify_if_match_update NULL msg_hclass_t sip_suppress_notify_if_match_class[] = SIP_HEADER_CLASS(suppress_notify_if_match, "Suppress-Notify-If-Match", "", snim_common, single, suppress_notify_if_match); issize_t sip_suppress_notify_if_match_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_suppress_notify_if_match_t *snim = (void *)h; return msg_token_d(&s, &snim->snim_tag); } issize_t sip_suppress_notify_if_match_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { return msg_generic_e(b, bsiz, h, f); } #endif #if SIP_HAVE_REMOTE_PARTY_ID /**@SIP_HEADER sip_remote_party_id Remote-Party-ID Header * * The syntax of the Remote-Party-ID header is described as follows: * @code * Remote-Party-ID = "Remote-Party-ID" HCOLON rpid *(COMMA rpid) * * rpid = [display-name] LAQUOT addr-spec RAQUOT * *(SEMI rpi-token) * * rpi-token = rpi-screen / rpi-pty-type / * rpi-id-type / rpi-privacy / other-rpi-token * * rpi-screen = "screen" EQUAL ("no" / "yes") * * rpi-pty-type = "party" EQUAL ("calling" / "called" / token) * * rpi-id-type = "id-type" EQUAL ("subscriber" / "user" / * "term" / token) * * rpi-privacy = "privacy" EQUAL * ( rpi-priv-element * / (LDQUOT rpi-priv-element * *(COMMA rpi-priv-element) RDQUOT) ) * * rpi-priv-element = ("full" / "name" / "uri" / "off" / token) * ["-" ( "network" / token )] * * other-rpi-token = ["-"] token [EQUAL (token / quoted-string)] * * @endcode * * @sa sip_update_default_mclass(), draft-ietf-sip-privacy-04.txt, @RFC3325 * * @NEW_1_12_7. In order to use @b Remote-Party-ID header, * initialize the SIP parser before calling nta_agent_create() or * nua_create() with, e.g., * sip_update_default_mclass(sip_extend_mclass(NULL)). * * @note * The #sip_t structure does not contain @a sip_remote_party_id field, but * sip_remote_party_id() function should be used for accessing the @b * Remote-Party-ID header structure. */ /**@ingroup sip_remote_party_id * @typedef typedef struct sip_remote_party_id_s sip_remote_party_id_t; * * The structure #sip_remote_party_id_t contains representation of SIP * @RemotePartyID header. * * The #sip_remote_party_id_t is defined as follows: * @code * typedef struct sip_remote_party_id_s { * sip_common_t rpid_common[1]; // Common fragment info * sip_remote_party_id_t *rpid_next; // Link to next * char const *rpid_display; // Display name * url_t rpid_url[1]; // URL * sip_param_t const *rpid_params; // Parameters * // Shortcuts to screen, party, id-type and privacy parameters * char const *rpid_screen, *rpid_party, *rpid_id_type, *rpid_privacy; * } sip_remote_party_id_t; * @endcode */ extern msg_xtra_f sip_remote_party_id_dup_xtra; extern msg_dup_f sip_remote_party_id_dup_one; static msg_update_f sip_remote_party_id_update; msg_hclass_t sip_remote_party_id_class[] = SIP_HEADER_CLASS(remote_party_id, "Remote-Party-ID", "", rpid_params, append, remote_party_id); issize_t sip_remote_party_id_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_remote_party_id_t *rpid = (sip_remote_party_id_t *)h; while (*s == ',') /* Ignore empty entries (comma-whitespace) */ *s = '\0', s += span_lws(s + 1) + 1; if (sip_name_addr_d(home, &s, &rpid->rpid_display, rpid->rpid_url, &rpid->rpid_params, NULL) == -1) return -1; return msg_parse_next_field(home, h, s, slen); } issize_t sip_remote_party_id_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { sip_remote_party_id_t const *rpid = (sip_remote_party_id_t *)h; return sip_name_addr_e(b, bsiz, f, rpid->rpid_display, 1, rpid->rpid_url, rpid->rpid_params, NULL); } /** Calculate size of extra data required for duplicating one * sip_remote_party_id_t header. */ isize_t sip_remote_party_id_dup_xtra(sip_header_t const *h, isize_t offset) { sip_remote_party_id_t const *rpid = (sip_remote_party_id_t *)h; return sip_name_addr_xtra(rpid->rpid_display, rpid->rpid_url, rpid->rpid_params, offset); } /** Duplicate one sip_remote_party_id_t object */ char *sip_remote_party_id_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { sip_remote_party_id_t *rpid = (sip_remote_party_id_t *)dst; sip_remote_party_id_t const *o = (sip_remote_party_id_t const *)src; return sip_name_addr_dup(&rpid->rpid_display, o->rpid_display, rpid->rpid_url, o->rpid_url, &rpid->rpid_params, o->rpid_params, b, xtra); } static int sip_remote_party_id_update(msg_common_t *h, char const *name, isize_t namelen, char const *value) { sip_remote_party_id_t *rpid = (sip_remote_party_id_t *)h; if (name == NULL) { rpid->rpid_screen = NULL; rpid->rpid_party = NULL; rpid->rpid_id_type = NULL; rpid->rpid_privacy = NULL; } #define MATCH(s) (namelen == strlen(#s) && su_casenmatch(name, #s, strlen(#s))) else if (MATCH(screen)) rpid->rpid_screen = value; else if (MATCH(party)) rpid->rpid_party = value; else if (MATCH(id-type)) rpid->rpid_id_type = value; else if (MATCH(privacy)) rpid->rpid_privacy = value; #undef MATCH return 0; } #endif #if SIP_HAVE_P_ASSERTED_IDENTITY /**@SIP_HEADER sip_p_asserted_identity P-Asserted-Identity Header * * The P-Asserted-Identity header is used used among trusted SIP entities * (typically intermediaries) to carry the identity of the user sending a * SIP message as it was verified by authentication. It is "defined" in * @RFC3325 section 9.1 as follows: * * @code * PAssertedID = "P-Asserted-Identity" HCOLON PAssertedID-value * *(COMMA PAssertedID-value) * PAssertedID-value = name-addr / addr-spec * @endcode * * @sa @RFC3325, @PPreferredIdentity * * @NEW_1_12_7. In order to use @b P-Asserted-Identity header, * initialize the SIP parser before calling nta_agent_create() or * nua_create() with, e.g., * sip_update_default_mclass(sip_extend_mclass(NULL)). * * @note * The #sip_t structure does not contain @a sip_p_asserted_identity field, * but sip_p_asserted_identity() function should be used for accessing the * @b P-Asserted-Identity header structure. */ /**@ingroup sip_p_asserted_identity * @typedef typedef struct sip_p_asserted_identity_s sip_p_asserted_identity_t; * * The structure #sip_p_asserted_identity_t contains representation of SIP * @PAssertedIdentity header. * * The #sip_p_asserted_identity_t is defined as follows: * @code * typedef struct sip_p_asserted_identity_s { * sip_common_t paid_common[1]; // Common fragment info * sip_p_asserted_identity_t *paid_next; // Link to next * char const *paid_display; // Display name * url_t paid_url[1]; // URL * } sip_p_asserted_identity_t; * @endcode */ static msg_xtra_f sip_p_asserted_identity_dup_xtra; static msg_dup_f sip_p_asserted_identity_dup_one; #define sip_p_asserted_identity_update NULL msg_hclass_t sip_p_asserted_identity_class[] = SIP_HEADER_CLASS(p_asserted_identity, "P-Asserted-Identity", "", paid_common, append, p_asserted_identity); issize_t sip_p_asserted_identity_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_p_asserted_identity_t *paid = (sip_p_asserted_identity_t *)h; while (*s == ',') /* Ignore empty entries (comma-whitespace) */ *s = '\0', s += span_lws(s + 1) + 1; if (sip_name_addr_d(home, &s, &paid->paid_display, paid->paid_url, NULL, NULL) == -1) return -1; return msg_parse_next_field(home, h, s, slen); } issize_t sip_p_asserted_identity_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { sip_p_asserted_identity_t const *paid = (sip_p_asserted_identity_t *)h; return sip_name_addr_e(b, bsiz, f, paid->paid_display, MSG_IS_CANONIC(f), paid->paid_url, NULL, NULL); } isize_t sip_p_asserted_identity_dup_xtra(sip_header_t const *h, isize_t offset) { sip_p_asserted_identity_t const *paid = (sip_p_asserted_identity_t *)h; return sip_name_addr_xtra(paid->paid_display, paid->paid_url, NULL, offset); } /** Duplicate one sip_p_asserted_identity_t object */ char *sip_p_asserted_identity_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { sip_p_asserted_identity_t *paid = (sip_p_asserted_identity_t *)dst; sip_p_asserted_identity_t const *o = (sip_p_asserted_identity_t *)src; return sip_name_addr_dup(&paid->paid_display, o->paid_display, paid->paid_url, o->paid_url, NULL, NULL, b, xtra); } #endif #if SIP_HAVE_P_PREFERRED_IDENTITY /**@SIP_HEADER sip_p_preferred_identity P-Preferred-Identity Header * * The P-Preferred-Identity header is used used among trusted SIP entities * (typically intermediaries) to carry the identity of the user sending a * SIP message as it was verified by authentication. It is "defined" in * @RFC3325 section 9.1 as follows: * * @code * PPreferredID = "P-Preferred-Identity" HCOLON PPreferredID-value * *(COMMA PPreferredID-value) * PPreferredID-value = name-addr / addr-spec * @endcode * * @sa @RFC3325, @PAssertedIdentity * * @NEW_1_12_7. In order to use @b P-Preferred-Identity header, * initialize the SIP parser before calling nta_agent_create() or * nua_create() with, e.g., * sip_update_default_mclass(sip_extend_mclass(NULL)). * * @note * The #sip_t structure does not contain @a sip_p_preferred_identity field, * but sip_p_preferred_identity() function should be used for accessing the * @b P-Preferred-Identity header structure. */ /**@ingroup sip_p_preferred_identity * @typedef typedef struct sip_p_preferred_identity_s sip_p_preferred_identity_t; * * The structure #sip_p_preferred_identity_t contains representation of SIP * @PPreferredIdentity header. * * The #sip_p_preferred_identity_t is defined as follows: * @code * typedef struct sip_p_preferred_identity_s { * sip_common_t ppid_common[1]; // Common fragment info * sip_p_preferred_identity_t *ppid_next; // Link to next * char const *ppid_display; // Display name * url_t ppid_url[1]; // URL * } sip_p_preferred_identity_t; * @endcode */ msg_hclass_t sip_p_preferred_identity_class[] = SIP_HEADER_CLASS(p_preferred_identity, "P-Preferred-Identity", "", ppid_common, append, p_asserted_identity); issize_t sip_p_preferred_identity_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return sip_p_asserted_identity_d(home, h, s, slen); } issize_t sip_p_preferred_identity_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { return sip_p_asserted_identity_e(b, bsiz, h, f); } #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sip_extra_headers.txt000066400000000000000000000021161223300710500245770ustar00rootroot00000000000000# # This file specifies extra SIP headers not included in sip_t structure # # The parsed headers are accessed with function (or macro) like sip_refer_sub() # e.g., sip_refer_sub_t *rsub = sip_refer_sub(sip); # # The line format is: # C-name @SINCE sip_t-like-comment # # Put all experimental things after EXPERIMENTAL HEADER LIST STARTS HERE... # #### EXTRA HEADER LIST STARTS HERE #### refer_sub @NEW_1_12_5 /**< Refer-Sub header */ #### DEFAULT HEADER LIST ENDS HERE #### # # These headers are added to the extended parser, installed # as default with sip_update_default_mclass(NULL) # alert_info @NEW_1_12_7 /**< Alert-Info header */ reply_to @NEW_1_12_7 /**< Reply-To header */ remote_party_id @NEW_1_12_7 /**< Remote-Party-ID header */ p_asserted_identity @NEW_1_12_7 /** * * 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 * */ /**@CFILE sip_feature.c * * @brief Feature-related SIP header handling * * @author Pekka Pessi . * * @date Created: Tue Jun 13 02:57:51 2000 ppessi */ #include "config.h" /* Avoid casting sip_t to msg_pub_t and sip_header_t to msg_header_t */ #define MSG_PUB_T struct sip_s #define MSG_HDR_T union sip_header_u #include "sofia-sip/sip_parser.h" #include #include #include #include #include /* ====================================================================== */ /**@SIP_HEADER sip_allow Allow Header * * The Allow header lists the set of methods supported by the user agent * generating the message. Its syntax is defined in @RFC3261 as * follows: * * @code * Allow = "Allow" HCOLON [Method *(COMMA Method)] * @endcode * * The parsed Allow header is stored in #sip_allow_t structure. * * Note that SIP methods are case-sensitive: "INVITE" method is different from * "Invite". * * @sa msg_header_find_item(), msg_header_replace_item(), * msg_header_remove_item() */ /**@ingroup sip_allow * @typedef struct msg_list_s sip_allow_t; * * The structure #sip_allow_t contains representation of an @Allow header. * * The #sip_allow_t is defined as follows: * @code * typedef struct msg_allow_s * { * msg_common_t k_common[1]; // Common fragment info * msg_list_t *k_next; // Link to next header * msg_param_t *k_items; // List of items * uint32_t k_bitmap; // Bitmap of allowed methods * } sip_allow_t; * @endcode * * @note The field @a k_bitmap was added in @VERSION_1_12_5. */ #define sip_allow_dup_xtra msg_list_dup_xtra #define sip_allow_dup_one msg_list_dup_one static msg_update_f sip_allow_update; msg_hclass_t sip_allow_class[] = SIP_HEADER_CLASS(allow, "Allow", "", k_items, list, allow); issize_t sip_allow_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_allow_t *k = (sip_allow_t *)h; issize_t retval = msg_commalist_d(home, &s, &k->k_items, msg_token_scan); msg_header_update_params(k->k_common, 0); return retval; } issize_t sip_allow_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { assert(sip_is_allow(h)); return msg_list_e(b, bsiz, h, f); } static int sip_allow_update(msg_common_t *h, char const *name, isize_t namelen, char const *value) { sip_allow_t *k = (sip_allow_t *)h; if (name == NULL) { k->k_bitmap = 0; } else { sip_method_t method = sip_method_code(name); if (method >= 0 && method < 32) k->k_bitmap |= 1 << method; } return 0; } /** Return true if the method is listed in @Allow header. */ int sip_is_allowed(sip_allow_t const *allow, sip_method_t method, char const *name) { if (method < sip_method_unknown || !allow) return 0; if (sip_method_unknown < method && method < 32) /* Well-known method */ return (allow->k_bitmap & (1 << method)) != 0; if (method == sip_method_unknown && (allow->k_bitmap & (1 << sip_method_unknown)) == 0) return 0; return msg_header_find_item(allow->k_common, name) != NULL; } /* ====================================================================== */ /**@SIP_HEADER sip_proxy_require Proxy-Require Header * * The Proxy-Require header is used to indicate proxy-sensitive features * that @b MUST be supported by the proxy. Its syntax is defined in @RFC3261 * as follows: * * @code * Proxy-Require = "Proxy-Require" HCOLON option-tag *(COMMA option-tag) * @endcode * * * The parsed Proxy-Require header is stored in #sip_proxy_require_t structure. */ /**@ingroup sip_proxy_require * @typedef struct msg_list_s sip_proxy_require_t; * * The structure #sip_proxy_require_t contains representation of an * @ProxyRequire header. * * The #sip_proxy_require_t is defined as follows: * @code * typedef struct msg_list_s * { * msg_common_t k_common[1]; // Common fragment info * msg_list_t *k_next; // Dummy link * msg_param_t *k_items; // List of items * } sip_proxy_require_t; * @endcode */ msg_hclass_t sip_proxy_require_class[] = SIP_HEADER_CLASS_LIST(proxy_require, "Proxy-Require", "", list); issize_t sip_proxy_require_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_proxy_require_t *k = (sip_proxy_require_t *)h; return msg_commalist_d(home, &s, &k->k_items, msg_token_scan); } issize_t sip_proxy_require_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { assert(sip_is_proxy_require(h)); return msg_list_e(b, bsiz, h, f); } /* ====================================================================== */ /**@SIP_HEADER sip_require Require Header * * The Require header is used by clients to tell user agent servers about * options that the client expects the server to support in order to * properly process the request. Its syntax is defined in @RFC3261 * as follows: * * @code * Require = "Require" HCOLON option-tag *(COMMA option-tag) * @endcode * * The parsed Require header is stored in #sip_require_t structure. */ /**@ingroup sip_require * @typedef struct msg_list_s sip_require_t; * * The structure #sip_require_t contains representation of an * @Require header. * * The #sip_require_t is defined as follows: * @code * typedef struct msg_list_s * { * msg_common_t k_common[1]; // Common fragment info * msg_list_t *k_next; // Link to next header * msg_param_t *k_items; // List of items * } sip_require_t; * @endcode */ msg_hclass_t sip_require_class[] = SIP_HEADER_CLASS_LIST(require, "Require", "", list); issize_t sip_require_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_require_t *k = (sip_require_t *)h; return msg_commalist_d(home, &s, &k->k_items, msg_token_scan); } issize_t sip_require_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { assert(sip_is_require(h)); return msg_list_e(b, bsiz, h, f); } /* ====================================================================== */ /**@SIP_HEADER sip_supported Supported Header * * The Supported header enumerates all the capabilities of the client or * server. Its syntax is defined in @RFC3261 as follows: * * @code * Supported = ( "Supported" / "k" ) HCOLON * [option-tag *(COMMA option-tag)] * @endcode * * The parsed option-tags of Supported header * are stored in #sip_supported_t structure. */ /**@ingroup sip_supported * @typedef struct msg_list_s sip_supported_t; * * The structure #sip_supported_t contains representation of an * @Supported header. * * The #sip_supported_t is defined as follows: * @code * typedef struct msg_list_s * { * msg_common_t k_common[1]; // Common fragment info * msg_list_t *k_next; // Link to next header * msg_param_t *k_items; // List of items * } sip_supported_t; * @endcode */ msg_hclass_t sip_supported_class[] = SIP_HEADER_CLASS_LIST(supported, "Supported", "k", list); issize_t sip_supported_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_supported_t *k = (sip_supported_t *)h; return msg_commalist_d(home, &s, &k->k_items, msg_token_scan); } issize_t sip_supported_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { assert(sip_is_supported(h)); return msg_list_e(b, bsiz, h, f); } /* ====================================================================== */ /**@SIP_HEADER sip_unsupported Unsupported Header * * The Unsupported header lists the features not supported by the server. * Its syntax is defined in @RFC3261 as follows: * * @code * Unsupported = "Unsupported" HCOLON [option-tag *(COMMA option-tag)] * @endcode * * * The parsed Unsupported header is stored in #sip_unsupported_t structure. */ /**@ingroup sip_unsupported * @typedef struct msg_list_s sip_unsupported_t; * * The structure #sip_unsupported_t contains representation of an * @Unsupported header. * * The #sip_unsupported_t is defined as follows: * @code * typedef struct msg_list_s * { * msg_common_t k_common[1]; // Common fragment info * msg_list_t *k_next; // Link to next header * msg_param_t *k_items; // List of items * } sip_unsupported_t; * @endcode */ msg_hclass_t sip_unsupported_class[] = SIP_HEADER_CLASS_LIST(unsupported, "Unsupported", "", list); issize_t sip_unsupported_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_unsupported_t *k = (sip_unsupported_t *)h; return msg_commalist_d(home, &s, &k->k_items, msg_token_scan); } issize_t sip_unsupported_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { assert(sip_is_unsupported(h)); return msg_list_e(b, bsiz, h, f); } /** Check if required feature is not supported. * * @retval NULL if all the required features are supported * @retval pointer to a @Unsupported header or * #SIP_NONE if @a home is NULL */ sip_unsupported_t *sip_has_unsupported(su_home_t *home, sip_supported_t const *support, sip_require_t const *require) { return sip_has_unsupported_any(home, support, NULL, NULL, require, NULL, NULL); } /** Check if required feature is not supported. * * @retval NULL if all the required features are supported * @retval pointer to a @Unsupported header or * #SIP_NONE if @a home is NULL */ sip_unsupported_t * sip_has_unsupported2(su_home_t *home, sip_supported_t const *support, sip_require_t const *support_by_require, sip_require_t const *require) { return sip_has_unsupported_any(home, support, support_by_require, NULL, require, NULL, NULL); } /** Check if required features are not supported. * * The supported features can be listed in @Supported, @Require or * @ProxyRequire headers (in @a supported, @a by_require, or @a * by_proxy_require parameters, respectively) * * @param home (optional) home pointer for allocating @Unsupported header * @param supported @Supported features (may be NULL) [IN] * @param by_require supported features listed by * @Require (may be NULL) [IN] * @param by_proxy_require supported features listed * by @ProxyRequire (may be NULL) [IN] * * @param require list of required features (may be NULL) [IN] * @param require2 2nd list of required features (may be NULL) [IN] * @param require3 3rd list of required features (may be NULL) [IN] * * @retval NULL if all the required features are supported * @retval pointer to a @Unsupported header or * #SIP_NONE if @a home is NULL */ sip_unsupported_t * sip_has_unsupported_any(su_home_t *home, sip_supported_t const *supported, sip_require_t const *by_require, sip_proxy_require_t const *by_proxy_require, sip_require_t const *require, sip_require_t const *require2, sip_require_t const *require3) { size_t i, j; sip_unsupported_t *unsupported = NULL; msg_param_t const empty[1] = { NULL }; msg_param_t const *slist = empty; msg_param_t const *rlist = empty; msg_param_t const *prlist = empty; if (require2 == NULL) require2 = require3, require3 = NULL; if (require == NULL) require = require2, require2 = NULL; if (require && require->k_items) { if (supported && supported->k_items) slist = supported->k_items; if (by_require && by_require->k_items) rlist = by_require->k_items; if (by_proxy_require && by_proxy_require->k_items) prlist = by_proxy_require->k_items; for (i = 0; require->k_items && require->k_items[i];) { msg_param_t feature = require->k_items[i++]; for (j = 0; slist[j]; j++) if (su_casematch(feature, slist[j])) { feature = NULL; break; } if (feature) for (j = 0; rlist[j]; j++) if (su_casematch(feature, rlist[j])) { feature = NULL; break; } if (feature) for (j = 0; prlist[j]; j++) if (su_casematch(feature, prlist[j])) { feature = NULL; break; } if (feature) { if (home) { if (unsupported == NULL) unsupported = sip_unsupported_make(home, feature); else msg_params_add(home, (msg_param_t **)&unsupported->k_items, feature); } else { return (sip_unsupported_t *)SIP_NONE; } } if (require->k_items[i] == NULL && require2 && require2->k_items) { i = 0, require = require2, require2 = require3, require3 = NULL; } } } return unsupported; } int sip_has_feature(msg_list_t const *supported, char const *feature) { size_t i; if (!feature || !feature[0]) return 1; /* Empty feature is always supported */ for (; supported; supported = supported->k_next) if (supported->k_items) for (i = 0; supported->k_items[i]; i++) if (su_casematch(feature, supported->k_items[i])) return 1; return 0; } /** Check that a feature is supported. */ int sip_has_supported(sip_supported_t const *supported, char const *feature) { return sip_has_feature(supported, feature); } /* ====================================================================== */ /**@SIP_HEADER sip_path Path Header * * The Path header field is a SIP extension header field (@RFC3327) with * syntax very similar to the @RecordRoute header field. It is used in * conjunction with SIP REGISTER requests and with 200 class messages in * response to REGISTER (REGISTER responses). * * @code * Path = "Path" HCOLON path-value *(COMMA path-value) * path-value = name-addr *( SEMI rr-param ) * @endcode * * * The parsed Path header is stored in #sip_path_t structure. */ /**@ingroup sip_path * @typedef typedef struct sip_route_s sip_path_t; * * The structure #sip_path_t contains representation of SIP @Path header. * * The #sip_path_t is defined as follows: * @code * typedef struct sip_route_s { * sip_common_t r_common[1]; // Common fragment info * sip_path_t *r_next; // Link to next @Path * char const *r_display; // Display name * url_t r_url[1]; // @Path URL * msg_param_t const *r_params; // List of parameters * } sip_path_t; * @endcode */ msg_hclass_t sip_path_class[] = SIP_HEADER_CLASS(path, "Path", "", r_params, prepend, any_route); issize_t sip_path_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return sip_any_route_d(home, h, s, slen); } issize_t sip_path_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { assert(sip_is_path(h)); return sip_any_route_e(b, bsiz, h, flags); } /* ====================================================================== */ /**@SIP_HEADER sip_service_route Service-Route Header * * The "Service-Route" is a SIP extension header field (@RFC3608), which can * contain a route vector that will direct requests through a specific * sequence of proxies. A registrar may use a Service-Route header field to * inform a UA of a service route that, if used by the UA, will provide * services from a proxy or set of proxies associated with that registrar. * The Service-Route header field may be included by a registrar in the * response to a REGISTER request. The syntax for the Service-Route header * field is: * * @code * Service-Route = "Service-Route" HCOLON sr-value *(COMMA sr-value) * sr-value = name-addr *( SEMI rr-param ) * @endcode * * The parsed Service-Route header is stored in #sip_service_route_t structure. * * @sa @RFC3608, @Path, @Route, @RecordRoute */ /**@ingroup sip_service_route * @typedef typedef struct sip_route_s sip_service_route_t; * * The structure #sip_service_route_t contains representation of SIP * @ServiceRoute header. * * The #sip_service_route_t is defined as follows: * @code * typedef struct sip_route_s { * sip_common_t r_common[1]; // Common fragment info * sip_service_route_t*r_next; // Link to next @ServiceRoute * char const *r_display; // Display name * url_t r_url[1]; // Service-Route URL * msg_param_t const *r_params; // List of parameters * } sip_service_route_t; * @endcode */ msg_hclass_t sip_service_route_class[] = SIP_HEADER_CLASS(service_route, "Service-Route", "", r_params, append, any_route); issize_t sip_service_route_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return sip_any_route_d(home, h, s, slen); } issize_t sip_service_route_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { assert(sip_is_service_route(h)); return sip_any_route_e(b, bsiz, h, flags); } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sip_header.c000066400000000000000000000061771223300710500226270ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE sip_header.c * * SIP header handling. * * @author Pekka Pessi . * * @date Created: Tue Jun 13 02:57:51 2000 ppessi */ #include "config.h" /* Avoid casting sip_t to msg_pub_t and sip_header_t to msg_header_t */ #define MSG_PUB_T struct sip_s #define MSG_HDR_T union sip_header_u /* Get bodies of inlined functions included in library */ #define SIP_STATIC_INLINE #include #include "sofia-sip/sip_parser.h" #include #include #include #include #include #include #include #include /** Copy a SIP header. * * @deprecated Use msg_header_copy() instead. */ sip_header_t *sip_header_copy(su_home_t *home, sip_header_t const *h) { if (h == NULL || h == SIP_NONE) return NULL; return msg_header_copy_as(home, h->sh_class, h); } /** Duplicate a SIP header. * * @deprecated Use msg_header_dup() instead. */ sip_header_t *sip_header_dup(su_home_t *home, sip_header_t const *h) { if (h == NULL || h == SIP_NONE) return NULL; return msg_header_dup_as(home, h->sh_class, h); } /** Decode a SIP header. * * @deprecated Use msg_header_d() instead. */ sip_header_t *sip_header_d(su_home_t *home, msg_t const *msg, char const *b) { return msg_header_d(home, msg, b); } /** Encode a SIP header. * * @deprecated Use msg_header_e() instead. */ issize_t sip_header_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { return msg_header_e(b, bsiz, (msg_header_t const *)h, flags); } sip_header_t *sip_header_format(su_home_t *home, msg_hclass_t *hc, char const *fmt, ...) { sip_header_t *h; va_list ap; va_start(ap, fmt); h = msg_header_vformat(home, hc, fmt, ap); va_end(ap); return h; } /** Add a duplicate of header object to a SIP message. */ int sip_add_dup(msg_t *msg, sip_t *sip, sip_header_t const *o) { return msg_header_add_dup(msg, (msg_pub_t *)sip, o); } int sip_add_dup_as(msg_t *msg, sip_t *sip, msg_hclass_t *hc, sip_header_t const *o) { return msg_header_add_dup_as(msg, (msg_pub_t *)sip, hc, o); } int sip_add_make(msg_t *msg, sip_t *sip, msg_hclass_t *hc, char const *s) { return msg_header_add_make(msg, sip, hc, s); } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sip_inlined.c000066400000000000000000000024151223300710500230100ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2007 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE sip_inlined.c * * Expand inlined sip functions non-inline. * */ #include "config.h" #include #if SU_HAVE_INLINE extern int xyzzy; #else #include "sofia-sip/msg_header.h" #include "sofia-sip/su_tag.h" #undef SU_HAVE_INLINE #undef su_inline #define SU_HAVE_INLINE 1 #define su_inline #include "sofia-sip/sip_protos.h" #include "sofia-sip/sip_extra.h" #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sip_mime.c000066400000000000000000000541151223300710500223210ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE sip_mime.c * * MIME-related SIP headers * * @author Pekka Pessi . * * @date Created: Tue Jun 13 02:57:51 2000 ppessi */ #include "config.h" /* Avoid casting sip_t to msg_pub_t and sip_header_t to msg_header_t */ #define MSG_PUB_T struct sip_s #define MSG_HDR_T union sip_header_u #include "sofia-sip/sip_parser.h" #include "sofia-sip/msg_mime_protos.h" #include #include #include #include #include #include /* ====================================================================== */ /**@SIP_HEADER sip_accept Accept Header * * The @b Accept request-header field can be used to specify certain media * types which are acceptable for the response. Its syntax is defined in * [H14.1, S10.6] as follows: * * @code * Accept = "Accept" HCOLON * [ accept-range *(COMMA accept-range) ] * accept-range = media-range *(SEMI accept-param) * media-range = ( "*" "/" "*" * / ( m-type SLASH "*" ) * / ( m-type SLASH m-subtype ) * ) *( SEMI m-parameter ) * accept-param = ("q" EQUAL qvalue) / generic-param * qvalue = ( "0" [ "." 0*3DIGIT ] ) * / ( "1" [ "." 0*3("0") ] ) * generic-param = token [ EQUAL gen-value ] * gen-value = token / host / quoted-string * @endcode * * * The parsed Accept header is stored in #sip_accept_t structure. */ /**@ingroup sip_accept * @typedef typedef struct sip_accept_s sip_accept_t; * * The structure #sip_accept_t contains representation of SIP * @Accept header. * * The #sip_accept_t is defined as follows: * @code * typedef struct sip_accept_s { * sip_common_t ac_common[1]; // Common fragment info * sip_accept_t *ac_next; // Pointer to next @Acceptheader * char const *ac_type; // Pointer to type/subtype * char const *ac_subtype; // Points after first slash in type * msg_param_t const *ac_params; // List of parameters * char const *ac_q; // Value of q parameter * } sip_accept_t; * @endcode */ #define sip_accept_dup_xtra msg_accept_dup_xtra #define sip_accept_dup_one msg_accept_dup_one #define sip_accept_update msg_accept_update msg_hclass_t sip_accept_class[] = SIP_HEADER_CLASS(accept, "Accept", "", ac_params, apndlist, accept); issize_t sip_accept_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return msg_accept_d(home, h, s, slen); } issize_t sip_accept_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { return msg_accept_e(b, bsiz, h, flags); } #if SIP_HAVE_ACCEPT_DISPOSITION /* ====================================================================== */ /**@SIP_HEADER sip_accept_disposition Accept-Disposition Header * * The Accept-Disposition header field is used to indicate what content * disposition types are acceptable to a client or server. Its syntax is * defined in draft-lennox-sip-reg-payload-01.txt section 3.2 as follows: * * @code * Accept-Disposition = "Accept-Disposition" ":" * #( (disposition-type | "*") *( ";" generic-param ) ) * @endcode * * * The parsed Accept-Disposition header * is stored in #sip_accept_disposition_t structure. */ msg_hclass_t sip_accept_disposition_class[] = SIP_HEADER_CLASS(accept_disposition, "Accept-Disposition", "", ad_params, apndlist, accept_disposition); issize_t sip_accept_disposition_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_accept_disposition_t *ad = (sip_accept_disposition_t *)h; assert(h); /* Ignore empty entries (comma-whitespace) */ while (*s == ',') s += span_lws(s + 1) + 1; /* "Accept:" #(type/subtyp ; *(parameters))) */ if (/* Parse protocol */ sip_version_d(&s, &ad->ad_type) == -1 || (ad->ad_subtype = strchr(ad->ad_type, '/')) == NULL || (*s == ';' && msg_params_d(home, &s, &ad->ad_params) == -1)) return -1; if (ad->ad_subtype) ad->ad_subtype++; return msg_parse_next_field(home, h, s, slen); } issize_t sip_accept_disposition_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { char *b0 = b, *end = b + bsiz; sip_accept_disposition_t const *ad = h->sh_accept_disposition; MSG_STRING_E(b, end, ad->ad_type); MSG_PARAMS_E(b, end, ad->ad_params, flags); MSG_TERM_E(b, end); return b - b0; } #endif /* ====================================================================== */ /**@SIP_HEADER sip_accept_encoding Accept-Encoding Header * * The Accept-Encoding header is similar to Accept, but restricts the * content-codings that are acceptable in the response. Its syntax is * defined in [H14.3, S10.7] as follows: * * @code * Accept-Encoding = "Accept-Encoding" HCOLON * [ encoding *(COMMA encoding) ] * encoding = codings *(SEMI accept-param) * codings = content-coding / "*" * content-coding = token * @endcode * * * The parsed Accept-Encoding header * is stored in #sip_accept_encoding_t structure. */ /**@ingroup sip_accept_encoding * @typedef typedef struct msg_accept_any_s sip_accept_encoding_t; * * The structure #sip_accept_encoding_t contains representation of SIP * @AcceptEncoding header. * * The #sip_accept_encoding_t is defined as follows: * @code * typedef struct { * msg_common_t aa_common[1]; // Common fragment info * sip_accept_encoding_t *aa_next; // Pointer to next @AcceptEncoding header * char const *aa_value; // Encoding token * msg_param_t const *aa_params; // List of parameters * char const *aa_q; // Value of q parameter * } sip_accept_encoding_t; * @endcode */ #define sip_accept_encoding_dup_xtra msg_accept_any_dup_xtra #define sip_accept_encoding_dup_one msg_accept_any_dup_one #define sip_accept_encoding_update msg_accept_any_update msg_hclass_t sip_accept_encoding_class[] = SIP_HEADER_CLASS(accept_encoding, "Accept-Encoding", "", aa_params, apndlist, accept_encoding); issize_t sip_accept_encoding_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { issize_t retval = msg_accept_encoding_d(home, h, s, slen); if (retval == -2) { /* Empty Accept-Encoding list is not an error */ sip_accept_encoding_t *aa = (sip_accept_encoding_t *)h; aa->aa_value = ""; retval = 0; } return retval; } issize_t sip_accept_encoding_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { return msg_accept_encoding_e(b, bsiz, h, f); } /* ====================================================================== */ /**@SIP_HEADER sip_accept_language Accept-Language Header * * The Accept-Language header can be used to allow the client to indicate to * the server in which language it would prefer to receive reason phrases, * session descriptions or status responses carried as message bodies. Its * syntax is defined in [H14.4, S10.8] as follows: * * @code * Accept-Language = "Accept-Language" HCOLON * [ language *(COMMA language) ] * language = language-range *(SEMI accept-param) * language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) / "*" ) * @endcode * * * The parsed Accept-Language header * is stored in #sip_accept_language_t structure. */ /**@ingroup sip_accept_language * @typedef typedef struct msg_accept_any_s sip_accept_language_t; * * The structure #sip_accept_language_t contains representation of SIP * @AcceptLanguage header. * * The #sip_accept_language_t is defined as follows: * @code * typedef struct { * msg_common_t aa_common[1]; // Common fragment info * sip_accept_language_t *aa_next; // Pointer to next * char const *aa_value; // Language-range * msg_param_t const *aa_params; // List of accept-parameters * char const *aa_q; // Value of q parameter * } sip_accept_language_t; * @endcode */ #define sip_accept_language_dup_xtra msg_accept_any_dup_xtra #define sip_accept_language_dup_one msg_accept_any_dup_one #define sip_accept_language_update msg_accept_any_update msg_hclass_t sip_accept_language_class[] = SIP_HEADER_CLASS(accept_language, "Accept-Language", "", aa_params, apndlist, accept_language); issize_t sip_accept_language_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { int retval = msg_accept_language_d(home, h, s, slen); if (retval == -2) { /* Empty Accept-Language list is not an error */ ((sip_accept_language_t *)h)->aa_value = ""; retval = 0; } return retval; } issize_t sip_accept_language_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { return msg_accept_language_e(b, bsiz, h, f); } /* ====================================================================== */ /**@SIP_HEADER sip_content_disposition Content-Disposition Header * * The Content-Disposition header field describes how the message body or, * in the case of multipart messages, a message body part is to be * interpreted by the UAC or UAS. Its syntax is defined in @RFC3261 * as follows: * * @code * Content-Disposition = "Content-Disposition" HCOLON * disp-type *( SEMI disp-param ) * disp-type = "render" / "session" / "icon" / "alert" * / disp-extension-token * disp-param = handling-param / generic-param * handling-param = "handling" EQUAL * ( "optional" / "required" * / other-handling ) * other-handling = token * disp-extension-token = token * @endcode * * The Content-Disposition header was extended by * draft-lennox-sip-reg-payload-01.txt section 3.1 as follows: * * @code * Content-Disposition = "Content-Disposition" ":" * disposition-type *( ";" disposition-param ) * disposition-type = "script" | "sip-cgi" | token * disposition-param = action-param * | modification-date-param * | generic-param * action-param = "action" "=" action-value * action-value = "store" | "remove" | token * modification-date-param = "modification-date" "=" quoted-date-time * quoted-date-time = <"> SIP-date <"> * @endcode * * The parsed Content-Disposition header * is stored in #sip_content_disposition_t structure. */ /**@ingroup sip_content_disposition * @typedef struct msg_content_disposition_s sip_content_disposition_t; * * The structure #sip_content_disposition_t contains representation of an * @ContentDisposition header. * * The #sip_content_disposition_t is defined as follows: * @code * typedef struct msg_content_disposition_s * { * msg_common_t cd_common[1]; // Common fragment info * msg_error_t *cd_next; // Link to next (dummy) * char const *cd_type; // Disposition type * msg_param_t const *cd_params; // List of parameters * char const *cd_handling; // Value of @b handling parameter * unsigned cd_required:1; // True if handling=required * unsigned cd_optional:1; // True if handling=optional * } sip_content_disposition_t; * @endcode */ static msg_xtra_f sip_content_disposition_dup_xtra; static msg_dup_f sip_content_disposition_dup_one; #define sip_content_disposition_update msg_content_disposition_update msg_hclass_t sip_content_disposition_class[] = SIP_HEADER_CLASS(content_disposition, "Content-Disposition", "", cd_params, single, content_disposition); issize_t sip_content_disposition_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return msg_content_disposition_d(home, h, s, slen); } issize_t sip_content_disposition_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { return msg_content_disposition_e(b, bsiz, h, f); } static isize_t sip_content_disposition_dup_xtra(sip_header_t const *h, isize_t offset) { return msg_content_disposition_dup_xtra(h, offset); } /** Duplicate one #sip_content_disposition_t object */ static char *sip_content_disposition_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { return msg_content_disposition_dup_one(dst, src, b, xtra); } /* ====================================================================== */ /**@SIP_HEADER sip_content_encoding Content-Encoding Header * * The Content-Encoding header indicates what additional content codings * have been applied to the entity-body. Its syntax is defined in @RFC3261 * as follows: * * @code * Content-Encoding = ( "Content-Encoding" / "e" ) HCOLON * content-coding *(COMMA content-coding) * content-coding = token * @endcode * * The parsed Content-Encoding header * is stored in #sip_content_encoding_t structure. */ /**@ingroup sip_content_encoding * @typedef struct msg_list_s sip_content_encoding_t; * * The structure #sip_content_encoding_t contains representation of an * @ContentEncoding header. * * The #sip_content_encoding_t is defined as follows: * @code * typedef struct msg_list_s * { * msg_common_t k_common[1]; // Common fragment info * msg_list_t *k_next; // Link to next header * msg_param_t *k_items; // List of items * } sip_content_encoding_t; * @endcode */ msg_hclass_t sip_content_encoding_class[] = SIP_HEADER_CLASS_LIST(content_encoding, "Content-Encoding", "e", list); issize_t sip_content_encoding_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return msg_list_d(home, h, s, slen); } issize_t sip_content_encoding_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { return msg_list_e(b, bsiz, h, f); } /* ====================================================================== */ /**@SIP_HEADER sip_content_language Content-Language Header * * The Content-Language header @RFC2616 section 14.12 describes the natural language(s) of * the intended audience for the enclosed entity. Note that this might not * be equivalent to all the languages used within the entity-body. Its * syntax is defined in @RFC3261 as follows: * * @code * Content-Language = "Content-Language" HCOLON * language-tag *(COMMA language-tag) * language-tag = primary-tag *( "-" subtag ) * primary-tag = 1*8ALPHA * subtag = 1*8ALPHA * @endcode * * The parsed Content-Language header * is stored in #sip_content_language_t structure. */ /**@ingroup sip_content_language * @typedef typedef struct msg_content_language_s sip_content_language_t; * * The structure #sip_content_language_t contains representation of * @ContentLanguage header. * * The #sip_content_language_t is defined as follows: * @code * typedef struct { * msg_common_t k_common[1]; // Common fragment info * msg_content_language_t *k_next; // (Content-Encoding header) * msg_param_t *k_items; // List of languages * } sip_content_language_t; * @endcode */ msg_hclass_t sip_content_language_class[] = SIP_HEADER_CLASS_LIST(content_language, "Content-Language", "", list); issize_t sip_content_language_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return msg_list_d(home, h, s, slen); } issize_t sip_content_language_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { return msg_list_e(b, bsiz, h, f); } /* ====================================================================== */ /**@SIP_HEADER sip_content_type Content-Type Header * * The Content-Type header indicates the media type of the message-body sent * to the recipient. Its syntax is defined in [H3.7, S] as * follows: * * @code * Content-Type = ( "Content-Type" / "c" ) HCOLON media-type * media-type = m-type SLASH m-subtype *(SEMI m-parameter) * m-type = discrete-type / composite-type * discrete-type = "text" / "image" / "audio" / "video" * / "application" / extension-token * composite-type = "message" / "multipart" / extension-token * extension-token = ietf-token / x-token * ietf-token = token * x-token = "x-" token * m-subtype = extension-token / iana-token * iana-token = token * m-parameter = m-attribute EQUAL m-value * m-attribute = token * m-value = token / quoted-string * @endcode * * The parsed Content-Type header is stored in #sip_content_type_t structure. */ /**@ingroup sip_content_type * @typedef typedef struct sip_content_type_s sip_content_type_t; * * The structure #sip_content_type_t contains representation of SIP * @ContentType header. * * The #sip_content_type_t is defined as follows: * @code * typedef struct sip_content_type_s { * sip_common_t c_common[1]; // Common fragment info * sip_unknown_t *c_next; // Dummy link to next * char const *c_type; // Pointer to type/subtype * char const *c_subtype; // Points after first slash in type * msg_param_t const *c_params; // List of parameters * } sip_content_type_t; * @endcode * * The whitespace in the @a c_type is always removed when parsing. */ static msg_xtra_f sip_content_type_dup_xtra; static msg_dup_f sip_content_type_dup_one; #define sip_content_type_update NULL msg_hclass_t sip_content_type_class[] = SIP_HEADER_CLASS(content_type, "Content-Type", "c", c_params, single, content_type); issize_t sip_content_type_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return msg_content_type_d(home, (msg_header_t *)h, s, slen); } issize_t sip_content_type_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { return msg_content_type_e(b, bsiz, (msg_header_t const *)h, flags); } static isize_t sip_content_type_dup_xtra(sip_header_t const *h, isize_t offset) { return msg_content_type_dup_xtra((msg_header_t *)h, offset); } /** Duplicate one #sip_content_type_t object */ static char *sip_content_type_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { return msg_content_type_dup_one((msg_header_t *)dst, (msg_header_t const *)src, b, xtra); } /* ====================================================================== */ /**@SIP_HEADER sip_mime_version MIME-Version Header * * MIME-Version header indicates what version of the MIME protocol was used * to construct the message. Its syntax is defined in [H19.4.1, S10.28] * as follows: * * @code * MIME-Version = "MIME-Version" HCOLON 1*DIGIT "." 1*DIGIT * @endcode * * The parsed MIME-Version header is stored in #sip_mime_version_t structure. */ /**@ingroup sip_mime_version * @typedef struct msg_generic_s sip_mime_version_t; * * The structure #sip_mime_version_t contains representation of an * @MIMEVersion header. * * The #sip_mime_version_t is defined as follows: * @code * typedef struct msg_generic_s * { * msg_common_t g_common[1]; // Common fragment info * msg_generic_t *g_next; // Link to next header * char const *g_string; // Header value * } sip_mime_version_t; * @endcode */ msg_hclass_t sip_mime_version_class[] = SIP_HEADER_CLASS_G(mime_version, "MIME-Version", "", single); issize_t sip_mime_version_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return sip_generic_d(home, h, s, slen); } issize_t sip_mime_version_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { return sip_generic_e(b, bsiz, h, f); } /* ====================================================================== */ /**@SIP_HEADER sip_warning Warning Header * * The Warning response-header field is used to carry additional information * about the status of a response. Its syntax is defined in @RFC3261 as * follows: * * @code * Warning = "Warning" HCOLON warning-value *(COMMA warning-value) * warning-value = warn-code SP warn-agent SP warn-text * warn-code = 3DIGIT * warn-agent = hostport / pseudonym * ; the name or pseudonym of the server adding * ; the Warning header, for use in debugging * warn-text = quoted-string * pseudonym = token * @endcode * * The parsed Warning header is stored in #sip_warning_t structure. */ /**@ingroup sip_warning * @typedef struct msg_warning_s sip_warning_t; * * The structure #sip_warning_t contains representation of an * @Warning header. * * The #sip_warning_t is defined as follows: * @code * typedef struct msg_warning_s * { * msg_common_t w_common[1]; // Common fragment info * msg_warning_t *w_next; // Link to next @Warning header * unsigned w_code; // Warning code * char const *w_host; // Hostname or pseudonym * char const *w_port; // Port number * char const *w_text; // Warning text * } sip_warning_t; * @endcode */ #define sip_warning_dup_xtra msg_warning_dup_xtra #define sip_warning_dup_one msg_warning_dup_one #define sip_warning_update NULL msg_hclass_t sip_warning_class[] = SIP_HEADER_CLASS(warning, "Warning", "", w_common, append, warning); issize_t sip_warning_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return msg_warning_d(home, h, s, slen); } issize_t sip_warning_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { return msg_warning_e(b, bsiz, h, f); } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sip_parser.c000066400000000000000000000410301223300710500226560ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@ingroup sip_parser * @CFILE sip_parser.c * * SIP parser. * * @author Pekka Pessi . * * @date Created: Thu Oct 5 14:01:24 2000 ppessi */ #include "config.h" /* Avoid casting sip_t to msg_pub_t and sip_header_t to msg_header_t */ #define MSG_PUB_T struct sip_s #define MSG_HDR_T union sip_header_u #include #include #include "sofia-sip/sip_parser.h" #include #include #include #include #include #include #include #ifndef UINT32_MAX #define UINT32_MAX (0xffffffffU) #endif /** Version of the SIP module */ char const sip_parser_version[] = VERSION; /** SIP version 2.0. */ char const sip_version_2_0[] = "SIP/2.0"; /** Default message class */ extern msg_mclass_t sip_mclass[]; static msg_mclass_t const *_default = sip_mclass; /** Return a built-in SIP parser object. */ msg_mclass_t const *sip_default_mclass(void) { return _default; } /** Update the default SIP parser. * * Use the extended SIP parser as default one. * * If the applications want to use headers added after @VERSION_1_12_5, * they should call this function before doing any other initialization, e.g., * @code * su_init(); * if (sip_update_default_mclass(sip_extend_mclass(NULL)) < 0) { * su_deinit(); * exit(2); * } * @endcode * * The default parser is not extended because it may break the old * applications looking for extension headers from sip_unknown list. * * @retval 0 when successful * @retval -1 upon an error * * @sa sip_extend_mclass() * * @NEW_1_12_7. */ int sip_update_default_mclass(msg_mclass_t const *mclass) { if (mclass == NULL) return -1; _default = mclass; return 0; } /**Extend SIP parser class with extension headers. * * Extend given SIP parser class with extension headers. If the given parser * (message class) is the default one or NULL, make a clone of default * parser before extending it. * * @param input pointer to a SIP message class (may be NULL) * * @return Pointer to extended mclass, or NULL upon an error. * * @sa * @AlertInfo, * @ReplyTo, * @RemotePartyId, * @PAssertedIdentity, * @PPreferredIdentity, * @SuppressBodyIfMatch, * @SuppressNotifyIfMatch * * @NEW_1_12_7. */ msg_mclass_t *sip_extend_mclass(msg_mclass_t *input) { msg_mclass_t *mclass; if (input == NULL || input == _default) mclass = msg_mclass_clone(_default, 0, 0); else mclass = input; if (mclass) { extern msg_hclass_t * const sip_extensions[]; int i; for (i = 0; sip_extensions[i]; i++) { msg_hclass_t *hclass = sip_extensions[i]; if (mclass->mc_unknown != msg_find_hclass(mclass, hclass->hc_name, NULL)) continue; if (msg_mclass_insert_header(mclass, hclass, 0) < 0) { if (input != mclass) free(mclass); return mclass = NULL; } } } return mclass; } /** Extract the SIP message body, including separator line. * * @param msg message object [IN] * @param sip public SIP message structure [IN/OUT] * @param b buffer containing unparsed data [IN] * @param bsiz buffer size [IN] * @param eos true if buffer contains whole message [IN] * * @retval -1 error * @retval 0 cannot proceed * @retval m */ issize_t sip_extract_body(msg_t *msg, sip_t *sip, char b[], isize_t bsiz, int eos) { ssize_t m = 0; size_t body_len; if (!(sip->sip_flags & MSG_FLG_BODY)) { /* We are looking at a potential empty line */ m = msg_extract_separator(msg, (msg_pub_t *)sip, b, bsiz, eos); if (m <= 0) return m; sip->sip_flags |= MSG_FLG_BODY; b += m; bsiz -= m; } if (sip->sip_content_length) body_len = sip->sip_content_length->l_length; else if (MSG_IS_MAILBOX(sip->sip_flags)) /* message fragments */ body_len = 0; else if (eos) body_len = bsiz; else if (bsiz == 0) return m; else return -1; if (body_len == 0) { sip->sip_flags |= MSG_FLG_COMPLETE; return m; } if (m) return m; if (eos && body_len > bsiz) { sip->sip_flags |= MSG_FLG_TRUNC | MSG_FLG_ERROR; return bsiz; } if ((m = msg_extract_payload(msg, (msg_pub_t *)sip, NULL, body_len, b, bsiz, eos)) == -1) return -1; sip->sip_flags |= MSG_FLG_FRAGS; if (bsiz >= body_len) sip->sip_flags |= MSG_FLG_COMPLETE; return m; } /** Parse SIP version. * * Parse a SIP version string. Update the * pointer at @a ss to first non-LWS character after the version string. * * @param ss string to be parsed [IN/OUT] * @param ver value result for version [OUT] * * @retval 0 when successful, * @retval -1 upon an error. */ int sip_version_d(char **ss, char const **ver) { char *s = *ss; char const *result; size_t const version_size = sizeof(sip_version_2_0) - 1; if (su_casenmatch(s, sip_version_2_0, version_size) && !IS_TOKEN(s[version_size])) { result = sip_version_2_0; s += version_size; } else { /* Version consists of two tokens, separated by / */ size_t l1 = 0, l2 = 0, n; result = s; l1 = span_token(s); for (n = l1; IS_LWS(s[n]); n++) {} if (s[n] == '/') { for (n++; IS_LWS(s[n]); n++) {} l2 = span_token(s + n); n += l2; } if (l1 == 0 || l2 == 0) return -1; /* If there is extra ws between tokens, compact version */ if (n > l1 + 1 + l2) { s[l1] = '/'; memmove(s + l1 + 1, s + n - l2, l2); s[l1 + 1 + l2] = 0; /* Compare again with compacted version */ if (su_casematch(s, sip_version_2_0)) result = sip_version_2_0; } s += n; } while (IS_WS(*s)) *s++ = '\0'; *ss = s; if (ver) *ver = result; return 0; } /** Calculate extra space required by version string */ isize_t sip_version_xtra(char const *version) { if (version == SIP_VERSION_CURRENT) return 0; return MSG_STRING_SIZE(version); } /** Duplicate a transport string */ void sip_version_dup(char **pp, char const **dd, char const *s) { if (s == SIP_VERSION_CURRENT) *dd = s; else MSG_STRING_DUP(*pp, *dd, s); } char const sip_method_name_invite[] = "INVITE"; char const sip_method_name_ack[] = "ACK"; char const sip_method_name_cancel[] = "CANCEL"; char const sip_method_name_bye[] = "BYE"; char const sip_method_name_options[] = "OPTIONS"; char const sip_method_name_register[] = "REGISTER"; char const sip_method_name_info[] = "INFO"; char const sip_method_name_prack[] = "PRACK"; char const sip_method_name_update[] = "UPDATE"; char const sip_method_name_message[] = "MESSAGE"; char const sip_method_name_subscribe[] = "SUBSCRIBE"; char const sip_method_name_notify[] = "NOTIFY"; char const sip_method_name_refer[] = "REFER"; char const sip_method_name_publish[] = "PUBLISH"; /** Well-known SIP method names. */ char const * const sip_method_names[] = { "", sip_method_name_invite, sip_method_name_ack, sip_method_name_cancel, sip_method_name_bye, sip_method_name_options, sip_method_name_register, sip_method_name_info, sip_method_name_prack, sip_method_name_update, sip_method_name_message, sip_method_name_subscribe, sip_method_name_notify, sip_method_name_refer, sip_method_name_publish, /* If you add something here, add also them to sip_method_d! */ NULL }; /** Get canonic method name. */ char const *sip_method_name(sip_method_t method, char const *name) { const size_t N = sizeof(sip_method_names)/sizeof(sip_method_names[0]); if (method > 0 && (size_t)method < N) return sip_method_names[method]; else if (method == 0) return name; else return NULL; } /**Parse a SIP method name. * * Parse a SIP method name and return a code corresponding to the method. * The address of the first non-LWS character after method name is stored in * @a *ss. * * @param ss pointer to pointer to string to be parsed * @param return_name value-result parameter for method name * * @note * If there is no whitespace after method name, the value in @a *return_name * may not be NUL-terminated. The calling function @b must NUL terminate * the value by setting the @a **ss to NUL after first examining its value. * * @return The method code if method * was identified, 0 (sip_method_unknown()) if method is not known, or @c -1 * (sip_method_invalid()) if an error occurred. * * If the value-result argument @a return_name is not @c NULL, * a pointer to the method name is stored to it. */ sip_method_t sip_method_d(char **ss, char const **return_name) { char *s = *ss, c = *s; char const *name; int code = sip_method_unknown; size_t n = 0; #define MATCH(s, m) (strncmp(s, m, n = sizeof(m) - 1) == 0) switch (c) { case 'A': if (MATCH(s, "ACK")) code = sip_method_ack; break; case 'B': if (MATCH(s, "BYE")) code = sip_method_bye; break; case 'C': if (MATCH(s, "CANCEL")) code = sip_method_cancel; break; case 'I': if (MATCH(s, "INVITE")) code = sip_method_invite; else if (MATCH(s, "INFO")) code = sip_method_info; break; case 'M': if (MATCH(s, "MESSAGE")) code = sip_method_message; break; case 'N': if (MATCH(s, "NOTIFY")) code = sip_method_notify; break; case 'O': if (MATCH(s, "OPTIONS")) code = sip_method_options; break; case 'P': if (MATCH(s, "PRACK")) code = sip_method_prack; else if (MATCH(s, "PUBLISH")) code = sip_method_publish; break; case 'R': if (MATCH(s, "REGISTER")) code = sip_method_register; else if (MATCH(s, "REFER")) code = sip_method_refer; break; case 'S': if (MATCH(s, "SUBSCRIBE")) code = sip_method_subscribe; break; case 'U': if (MATCH(s, "UPDATE")) code = sip_method_update; break; } #undef MATCH if (IS_NON_WS(s[n])) /* Unknown method */ code = sip_method_unknown; if (code == sip_method_unknown) { name = s; for (n = 0; IS_UNRESERVED(s[n]); n++) ; if (s[n]) { if (!IS_LWS(s[n])) return sip_method_invalid; if (return_name) s[n++] = '\0'; } } else { name = sip_method_names[code]; } while (IS_LWS(s[n])) n++; *ss = (s + n); if (return_name) *return_name = name; return (sip_method_t)code; } /** Get method enum corresponding to method name */ sip_method_t sip_method_code(char const *name) { /* Note that sip_method_d() does not change string if return_name is NULL */ return sip_method_d((char **)&name, NULL); } char const sip_transport_udp[] = "SIP/2.0/UDP"; char const sip_transport_tcp[] = "SIP/2.0/TCP"; char const sip_transport_sctp[] = "SIP/2.0/SCTP"; char const sip_transport_tls[] = "SIP/2.0/TLS"; /** Decode transport */ issize_t sip_transport_d(char **ss, char const **ttransport) { char const *transport; char *pn, *pv, *pt; size_t pn_len, pv_len, pt_len; char *s = *ss; #define TRANSPORT_MATCH(t) \ (su_casenmatch(s + 7, t + 7, (sizeof t) - 8) && \ (!s[sizeof(t) - 1] || IS_LWS(s[sizeof(t) - 1])) \ && (transport = t, s += sizeof(t) - 1)) if (!su_casenmatch(s, "SIP/2.0", 7) || (!TRANSPORT_MATCH(sip_transport_udp) && !TRANSPORT_MATCH(sip_transport_tcp) && !TRANSPORT_MATCH(sip_transport_sctp) && !TRANSPORT_MATCH(sip_transport_tls))) { /* Protocol name */ transport = pn = s; skip_token(&s); pn_len = s - pn; skip_lws(&s); if (pn_len == 0 || *s++ != '/') return -1; skip_lws(&s); /* Protocol version */ pv = s; skip_token(&s); pv_len = s - pv; skip_lws(&s); if (pv_len == 0 || *s++ != '/') return -1; skip_lws(&s); /* Transport protocol */ pt = s; skip_token(&s); pt_len = s - pt; if (pt_len == 0) return -1; /* Remove whitespace between protocol name and version */ if (pn + pn_len + 1 != pv) { pn[pn_len] = '/'; pv = memmove(pn + pn_len + 1, pv, pv_len); } /* Remove whitespace between protocol version and transport */ if (pv + pv_len + 1 != pt) { pv[pv_len] = '/'; pt = memmove(pv + pv_len + 1, pt, pt_len); pt[pt_len] = '\0'; /* extra whitespace? */ if (su_casematch(transport, sip_transport_udp)) transport = sip_transport_udp; else if (su_casematch(transport, sip_transport_tcp)) transport = sip_transport_tcp; else if (su_casematch(transport, sip_transport_sctp)) transport = sip_transport_sctp; else if (su_casematch(transport, sip_transport_tls)) transport = sip_transport_tls; } } if (IS_LWS(*s)) { *s++ = '\0'; skip_lws(&s); } *ss = s; *ttransport = transport; return 0; } /** Calculate extra space required by sip_transport_dup() */ isize_t sip_transport_xtra(char const *transport) { if (transport == sip_transport_udp || transport == sip_transport_tcp || transport == sip_transport_sctp || transport == sip_transport_tls || su_casematch(transport, sip_transport_udp) || su_casematch(transport, sip_transport_tcp) || su_casematch(transport, sip_transport_sctp) || su_casematch(transport, sip_transport_tls)) return 0; return MSG_STRING_SIZE(transport); } /** Duplicate a transport string */ void sip_transport_dup(char **pp, char const **dd, char const *s) { if (s == sip_transport_udp) *dd = s; else if (s == sip_transport_tcp) *dd = s; else if (s == sip_transport_sctp) *dd = s; else if (s == sip_transport_tls) *dd = s; else if (su_casematch(s, sip_transport_udp)) *dd = sip_transport_udp; else if (su_casematch(s, sip_transport_tcp)) *dd = sip_transport_tcp; else if (su_casematch(s, sip_transport_sctp)) *dd = sip_transport_sctp; else if (su_casematch(s, sip_transport_tls)) *dd = sip_transport_tls; else MSG_STRING_DUP(*pp, *dd, s); } /** Parse SIP construct used in @CallID. */ char *sip_word_at_word_d(char **ss) { char *rv = *ss, *s0 = *ss; skip_word(ss); if (s0 == *ss) return NULL; if (**ss == '@') { (*ss)++; s0 = *ss; skip_word(ss); if (s0 == *ss) return NULL; } if (IS_LWS(**ss)) (*ss)++; skip_lws(ss); return rv; } /**Add message separator, then test if message is complete. * * Add sip_content_length and sip_separator if they are missing. * The test that all necessary message components ( @From, @To, * @CSeq, @CallID, @ContentLength and message separator are present. * * @retval 0 when successful * @retval -1 upon an error: headers are missing and they could not be added */ int sip_complete_message(msg_t *msg) { sip_t *sip = sip_object(msg); su_home_t *home = msg_home(msg); size_t len = 0; ssize_t mplen; if (sip == NULL) return -1; if (!sip->sip_separator) sip->sip_separator = sip_separator_create(msg_home(msg)); if (sip->sip_multipart) { sip_content_type_t *c = sip->sip_content_type; msg_multipart_t *mp = sip->sip_multipart; sip_common_t *head; if (!c || msg_multipart_complete(msg_home(msg), c, mp) < 0) return -1; if (sip->sip_payload) head = sip->sip_payload->pl_common; else head = sip->sip_separator->sep_common; if (!head || !msg_multipart_serialize(&head->h_succ, mp)) return -1; mplen = msg_multipart_prepare(msg, mp, sip->sip_flags); if (mplen == -1) return -1; len = (size_t)mplen; } if (sip->sip_payload) len += sip->sip_payload->pl_len; if (len > UINT32_MAX) return -1; if (!sip->sip_content_length) { msg_header_insert(msg, (msg_pub_t *)sip, (msg_header_t*) sip_content_length_create(home, (uint32_t)len)); } else { if (sip->sip_content_length->l_length != len) { sip->sip_content_length->l_length = (uint32_t)len; msg_fragment_clear(sip->sip_content_length->l_common); } } if (!sip->sip_cseq || !sip->sip_call_id || !sip->sip_to || !sip->sip_from || !sip->sip_separator || !sip->sip_content_length) return -1; return 0; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sip_parser.docs000066400000000000000000000057101223300710500233710ustar00rootroot00000000000000/* -*- c -*- */ /**@page sip_parser SIP Parser * * This part of the Sofia documentation describes the internal working of * SIP parser. It documents the internal functions and macros used when a * new parser is added. * * The @b sip module contains interface to the SIP headers and message * objects. The interface is abstracted using objects known as * @ref msg_hclass_s "header classes" and @ref msg_mclass_s "message classes". * * The @ref msg_mclass_s "message class" defines how a message is handled: * parsed and encoded. It contains a parser table with references to header * classes. It also contains function pointers used by the parser to handle * message body and other details that vary between protocols. * * A @ref msg_hclass_s "header class" defines how a single header is parsed. * Each header has its own header class. There are also header classes for * message elements that are not really headers, like @ref sip_request * "request" and @ref sip_status "status line", * @ref sip_separator "separator between headers" and * @ref sip_payload "message body" * (which is also known as payload). There is also a header classes * for @ref sip_unknown "unknown headers" and * @ref sip_error "headers that contained parsing errors". * * * @section sip_add_headers Adding Headers to Parser * * Sofia SIP Parser can be extended easily, either by application or by * internally extending the sofia-sip library itself. * * Create a header template for your header just like sip_rfc2543.h.in, * e.g, sip_example.h.in: * *@code /**@file sip_example.h.in * * Template for . */ #ifndef SIP_EXAMPLE_H /** Defined when has been included. */ #define SIP_EXAMPLE_H /**@file sofia-sip/sip_example.h * * @brief Example header. * * #AUTO# * * @author Pekka Pessi . * * @date Created: Fri May 27 18:40:38 EEST 2005 ppessi */ #ifndef SIP_H #include #endif /**@ingroup sip_also * @brief Structure for @b Also header. */ struct sip_also_s { sip_common_t also_common[1]; /**< Common fragment info */ sip_also_t *also_next; /**< Link to next Also header */ char const *also_display; /**< Display name */ url_t also_url[1]; /**< URL */ }; typedef struct sip_also_s sip_also_t; typedef sip_generic_t sip_hide_t; typedef sip_auth_t sip_encryption_t; typedef sip_auth_t sip_response_key_t; struct sip_example_dummy_structure { /* === Headers start here */ sip_also_t *sip_also; /**< Also */ sip_hide_t *sip_hide; /**< Hide */ sip_encryption_t *sip_encryption; /**< Encryption */ sip_response_key_t *sip_response_key; /**< Response-Key */ /* === Headers end here */ }; #endif /** !defined(SIP_EXAMPLE_H) */ --->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8--- * @endcode */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sip_parser_table.c.in000066400000000000000000000027631223300710500244440ustar00rootroot00000000000000/**@IFILE sip_parser_table.c.in * * Template for . * * @date Created: Wed Feb 21 11:01:45 2001 ppessi */ /* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE sip_parser_table.c * @brief SIP parser table * * #AUTO# * * @author Pekka Pessi . * * @date Created: Tue Oct 1 20:28:59 2002 ppessi */ #include "config.h" #include #include /* Avoid casting sip_t to msg_pub_t and sip_header_t to msg_header_t */ #define MSG_PUB_T struct sip_s #define MSG_HDR_T union sip_header_u #include #include #include sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sip_prack.c000066400000000000000000000131241223300710500224650ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE sip_prack.c * @brief SIP headers for Prack. * * The file @b sip_prack.c contains implementation of header classes for * PRACK-related SIP headers @RAck and @RSeq. * * @author Pekka Pessi . * * @date Created: Thu Sep 13 21:24:15 EEST 2001 ppessi */ #include "config.h" /* Avoid casting sip_t to msg_pub_t and sip_header_t to msg_header_t */ #define MSG_PUB_T struct sip_s #define MSG_HDR_T union sip_header_u #include "sofia-sip/sip_parser.h" #include #include #include #include #include #include /* ====================================================================== */ /**@SIP_HEADER sip_rack RAck Header * * The RAck header indicates the sequence number of the provisional response * which is being acknowledged. Its syntax is defined in * @RFC3262 section 10 as follows: * * @code * RAck = "RAck" HCOLON response-num LWS CSeq-num LWS Method * response-num = 1*DIGIT * CSeq-num = 1*DIGIT * @endcode * * @sa @RFC3262, nta_outgoing_prack(), nta_reliable_treply(), * nta_reliable_mreply(). * * The parsed RAck header is stored in #sip_rack_t structure. */ /**@ingroup sip_rack * @typedef struct sip_rack_s sip_rack_t; * * The structure #sip_rack_t contains representation of an @RAck header. * * The #sip_rack_t is defined as follows: * @code * typedef struct sip_rack_s * { * sip_common_t ra_common; // Common fragment info * sip_error_t *ra_next; // Dummy link to next * uint32_t ra_response; // Sequence number of response * uint32_t ra_cseq; // Sequence number of request * sip_method_t ra_method; // Original request method * char const *ra_method_name; // Original request method name * } sip_rack_t; * @endcode */ static msg_xtra_f sip_rack_dup_xtra; static msg_dup_f sip_rack_dup_one; #define sip_rack_update NULL msg_hclass_t sip_rack_class[] = SIP_HEADER_CLASS(rack, "RAck", "", ra_common, single, rack); issize_t sip_rack_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_rack_t *ra = h->sh_rack; ra->ra_response = strtoul(s, &s, 10); if (IS_LWS(*s)) { skip_lws(&s); ra->ra_cseq = strtoul(s, &s, 10); if (IS_LWS(*s)) { skip_lws(&s); if ((ra->ra_method = sip_method_d(&s, &ra->ra_method_name)) >= 0) { return 0; } } } return -1; } issize_t sip_rack_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { sip_rack_t const *ra = h->sh_rack; assert(sip_is_rack(h)); return snprintf(b, bsiz, "%u %u %s", ra->ra_response, ra->ra_cseq, ra->ra_method_name); } isize_t sip_rack_dup_xtra(sip_header_t const *h, isize_t offset) { sip_rack_t const *ra = h->sh_rack; if (ra->ra_method == sip_method_unknown) return offset + MSG_STRING_SIZE(ra->ra_method_name); else return offset; } /** Duplicate one #sip_rack_t object */ char *sip_rack_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { sip_rack_t *ra_dst = dst->sh_rack; sip_rack_t const *ra_src = src->sh_rack; char *end = b + xtra; ra_dst->ra_response = ra_src->ra_response; ra_dst->ra_cseq = ra_src->ra_cseq; ra_dst->ra_method = ra_src->ra_method; if (ra_src->ra_method == sip_method_unknown) MSG_STRING_DUP(b, ra_dst->ra_method_name, ra_src->ra_method_name); else ra_dst->ra_method_name = ra_src->ra_method_name; assert(b <= end); (void)end; return b; } /* ====================================================================== */ /**@SIP_HEADER sip_rseq RSeq Header * * The RSeq header identifies provisional responses within a transaction. * Its syntax is defined in @RFC3262 section 10 as follows: * * @code * RSeq = "RSeq" HCOLON response-num * response-num = 1*DIGIT * @endcode * * The parsed RSeq header is stored in #sip_rseq_t structure. */ /**@ingroup sip_rseq * @typedef struct sip_rseq_s sip_rseq_t; * * The structure #sip_rseq_t contains representation of an @RSeq header. * * The #sip_rseq_t is defined as follows: * @code * typedef struct sip_rseq_s * { * sip_common_t rs_common; // Common fragment info * sip_error_t *rs_next; // Dummy link to next * uint32_t rs_response; // Sequence number of response * } sip_rseq_t; * @endcode */ msg_hclass_t sip_rseq_class[] = SIP_HEADER_CLASS(rseq, "RSeq", "", rs_common, single, any); issize_t sip_rseq_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return msg_numeric_d(home, h, s, slen); } issize_t sip_rseq_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { assert(sip_is_rseq(h)); return msg_numeric_e(b, bsiz, h, f); } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sip_pref_util.c000066400000000000000000000361171223300710500233650ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE sip_pref_util.c * * SIP callercaps and callerprefs utility functions. * * @author Pekka Pessi . * * @date Created: Tue Nov 2 16:39:33 EET 2004 ppessi */ #include "config.h" #include #include #include #include #include #include #include "sofia-sip/sip_parser.h" #include #include #include static double parse_number(char const *str, char **return_end); /** Parse a single preference */ int sip_prefs_parse(union sip_pref *sp, char const **in_out_s, int *return_negation) { char const *s; size_t n; enum sp_type old_type; assert(sp && in_out_s && *in_out_s && return_negation); old_type = sp->sp_type; sp->sp_type = sp_error; s = *in_out_s; if (!s) return 0; if (old_type == sp_init) { if (s[0] == '\0' || su_casematch(s, "TRUE") || su_casematch(s, "\"TRUE\"")) { /* Boolean */ sp->sp_type = sp_literal; sp->sp_literal.spl_value = "TRUE"; sp->sp_literal.spl_length = 4; *return_negation = 0; *in_out_s = s + strlen(s); return 1; } else if (su_casematch(s, "FALSE") || su_casematch(s, "\"FALSE\"")) { /* Boolean */ sp->sp_type = sp_literal; sp->sp_literal.spl_value = "FALSE"; sp->sp_literal.spl_length = 5; *return_negation = 0; *in_out_s = s + strlen(s); return 1; } else if (s[0] == '"' && s[1] != '\0') { for (s++; IS_LWS(s[0]); s++) {} } else old_type = sp_error; } else if (!s[0]) { sp->sp_type = sp_init; return 0; } if (old_type == sp_error) return 0; if ((*return_negation = s[0] == '!')) for (s++; IS_LWS(s[0]); s++) {} if (*s == '#') { /* Numeric */ double n1, n2; char s0, *e; for (s++; IS_LWS(s[0]); s++) {} s0 = s[0]; if (s0 == '=') sp->sp_type = sp_range, n1 = n2 = parse_number(s = s + 1, &e); else if (s0 == '<' && s[1] == '=') sp->sp_type = sp_range, n1 = -DBL_MAX, n2 = parse_number(s = s + 2, &e); else if (s0 == '>' && s[1] == '=') sp->sp_type = sp_range, n1 = parse_number(s = s + 2, &e), n2 = DBL_MAX; else if (((n1 = parse_number(s, &e)) != 0.0 || s != e) && e[0] == ':') sp->sp_type = sp_range, n2 = parse_number(s = e + 1, &e); else /* Error in conversion */ sp->sp_type = sp_error, n1 = DBL_MAX, n2 = -DBL_MAX; if (s == e && (n1 == 0.0 || n2 == 0.0)) sp->sp_type = sp_error; /* Error in conversion */ sp->sp_range.spr_lower = n1; sp->sp_range.spr_upper = n2; s = e; } else if (*s == '<') { /* Quoted string */ n = strcspn(++s, ">"); sp->sp_type = sp_string; sp->sp_string.sps_value = s; sp->sp_string.sps_length = n; s += n + 1; } else if ((n = span_token(s))) { /* Literal */ sp->sp_type = sp_literal; sp->sp_literal.spl_value = s; sp->sp_literal.spl_length = n; s += n; } for (; IS_LWS(s[0]); s++) {} if (s[0] == ',' || (s[0] == '"' && s[1] == '\0')) for (s++; IS_LWS(s[0]); s++) {} else old_type = sp_error; if (old_type != sp_init && old_type != sp->sp_type) sp->sp_type = sp_error; *in_out_s = s; return sp->sp_type != sp_error; } /** Parse number: * number = [ "+" / "-" ] 1*DIGIT ["." 0*DIGIT] */ static double parse_number(char const *str, char **return_end) { double value = 0.0; double decimal = 0.1; char d, sign = '+'; if (return_end) *return_end = (char *)str; d = *str; if (d == '+' || d == '-') sign = d, d = *++str; if (!('0' <= d && d <= '9')) return value; for (; '0' <= d && d <= '9'; d = *++str) value = value * 10 + (d - '0'); if (d == '.') for (d = *++str; '0' <= d && d <= '9'; d = *++str) { value += (d - '0') * decimal; decimal *= 0.1; } if (value > DBL_MAX) value = DBL_MAX; if (sign == '-') value = -value; if (return_end) *return_end = (char *)str; return value; } /** Return true if preferences match */ int sip_prefs_match(union sip_pref const *a, union sip_pref const *b) { if (!a || !b) return 0; if (a->sp_type != b->sp_type) return 0; switch (a->sp_type) { default: case sp_error: return 0; case sp_literal: return a->sp_literal.spl_length == b->sp_literal.spl_length && su_casenmatch(a->sp_literal.spl_value, b->sp_literal.spl_value, a->sp_literal.spl_length); case sp_string: return a->sp_string.sps_length == b->sp_string.sps_length && strncmp(a->sp_string.sps_value, b->sp_string.sps_value, a->sp_string.sps_length) == 0; case sp_range: return a->sp_range.spr_lower <= b->sp_range.spr_upper && a->sp_range.spr_upper >= b->sp_range.spr_lower; } } /**Find a matching parameter-value pair from a parameter list. * * Check if the given feature values match with each other. * * @param pvalue first feature parameter * @param nvalue second feature parameter * @param return_parse_error return-value parameter for error (may be NULL) * * @retval 1 if given feature parameters match * @retval 0 if there is no match or a parse or type error occurred. * * If there is a parsing or type error, 0 is returned and @a * *return_parse_error is set to -1. * * @sa sip_prefs_parse(), sip_prefs_match(), union #sip_pref. */ int sip_prefs_matching(char const *pvalue, char const *nvalue, int *return_parse_error) { int error; char const *p; union sip_pref np[1], pp[1]; int n_negated, p_negated; if (!return_parse_error) return_parse_error = &error; if (!pvalue || !nvalue) return 0; memset(np, 0, sizeof np); /* Usually nvalue is from Accept/Reject-Contact, pvalue is from Contact */ while (sip_prefs_parse(np, &nvalue, &n_negated)) { memset(pp, 0, sizeof pp); p = pvalue; while (sip_prefs_parse(pp, &p, &p_negated)) { if (pp->sp_type != np->sp_type) /* Types do not match */ return 0; if (sip_prefs_match(np, pp) /* We found matching value */ ? !p_negated /* without negative */ : p_negated) /* Negative did not match */ break; } if (pp->sp_type == sp_error) return *return_parse_error = -1, 0; if (pp->sp_type != sp_init /* We found matching value */ ? !n_negated /* and we expected one */ : n_negated) /* We found none and expected none */ return 1; } if (np->sp_type == sp_error) *return_parse_error = -1; return 0; } /** Check if the parameter is a valid feature tag. * * A feature tag is a parameter starting with a single plus, or a well-known * feature tag listed in @RFC3841: "audio", "automata", "application", * "class", "control", "duplex", "data", "description", "events", "isfocus", * "language", "mobility", "methods", "priority", "schemes", "type", or * "video". However, well-known feature tag can not start with plus. So, * "+alarm" or "audio" is a feature tag, "alarm", "++alarm", or "+audio" are * not. * * @retval 1 if string is a feature tag parameter * @retval 0 otherwise */ int sip_is_callerpref(char const *param) { #define MATCH(s) \ (su_casenmatch(param + 1, s + 1, strlen(s) - 1) && \ (param[strlen(s)] == '=' || param[strlen(s)] == '\0')) int xor = 0, base = 0; if (!param || !param[0]) return 0; if (param[0] == '+') param++, xor = 1; switch (param[0]) { case 'a': case 'A': base = MATCH("audio") || MATCH("automata") || MATCH("application") || MATCH("actor"); break; case 'c': case 'C': base = MATCH("class") || MATCH("control"); break; case 'd': case 'D': base = MATCH("duplex") || MATCH("data") || MATCH("description"); break; case 'e': case 'E': base = MATCH("events"); break; case 'i': case 'I': base = MATCH("isfocus"); break; case 'l': case 'L': base = MATCH("language"); break; case 'm': case 'M': base = MATCH("mobility") || MATCH("methods"); break; case 'p': case 'P': base = MATCH("priority"); break; case 's': case 'S': base = MATCH("schemes"); break; case 't': case 'T': base = MATCH("type"); break; case 'v': case 'V': base = MATCH("video"); break; default: base = 0; break; } #undef MATCH return base ^ xor; } /** Check if @Contact is immune to callerprefs. */ int sip_contact_is_immune(sip_contact_t const *m) { unsigned i; if (m->m_params) for (i = 0; m->m_params[i]; i++) { if (sip_is_callerpref(m->m_params[i])) return 0; } return 1; } /**Check if @Contact matches by @AcceptContact. * * Matching @AcceptContact and @Contact headers is done as explained in * @RFC3841 section 7.2.4. The caller score can be calculated from the * returned S and N values. * * @par Matching * The @AcceptContact header contains number of feature tag parameters. The * count of feature tags is returned in @a return_N. For each feature tag in * @AcceptContact, the feature tag with same name is searched from the * @Contact header. If both headers contain the feature tag with same name, * their values are compared. If the value in @AcceptContact does not match * with the value in @Contact, there is mismatch and 0 is returned. If they * match, S is increased by 1. * * @param m pointer to @Contact header structure * @param cp pointer to @AcceptContact header structure * @param return_N return-value parameter for number of * feature tags in @AcceptContact * @param return_S return-value parameter for number of * matching feature tags * @param return_error return-value parameter for parsing error * * For example, * @code * if (sip_contact_accept(contact, accept_contact, &S, &N, &error)) { * if (N == 0) * score == 1.0; * else * score = (double)S / (double)N; * if (accept_contact->cp_explicit) { * if (accept_contact->cp_require) * goto drop; * else * score = 0.0; * } * } * else if (!error) { * score = 0.0; * } * @endcode * * @retval 1 if @Contact matches * @return @a return_S contains number of matching feature tags * @return @a return_N contains number of feature tags in @AcceptContact * @retval 0 if @Contact does not match * @return @a return_error contains -1 if feature tag value was malformed * * @sa @RFC3841 section 7.2.4, sip_contact_score(), sip_contact_reject(), * sip_contact_is_immune(), sip_contact_immunize(), sip_is_callerpref(), * sip_prefs_matching(). */ int sip_contact_accept(sip_contact_t const *m, sip_accept_contact_t const *cp, unsigned *return_S, unsigned *return_N, int *return_error) { char const *cap, *acc; unsigned i, S, N; size_t eq; if (!return_N) return_N = &N; if (!return_S) return_S = &S; *return_S = 0, *return_N = 0; if (!m || !cp || !m->m_params || !cp->cp_params) return 1; for (i = 0, S = 0, N = 0; cp->cp_params[i]; i++) { acc = cp->cp_params[i]; if (!sip_is_callerpref(acc)) continue; N++; cap = msg_params_find(m->m_params, acc); if (cap) { eq = strcspn(acc, "="); acc += eq + (acc[eq] == '='); if (!sip_prefs_matching(cap, acc, return_error)) return 0; S++; } } *return_S = S; /* Matched feature tags */ *return_N = N; /* Number of feature tags in @AcceptContact */ return 1; } /** Check if @Contact is rejected by @RejectContact. * * @param m pointer to @Contact header * @param reject pointer to @RejectContact header * * @retval 1 when rejecting * @retval 0 when @Contact does not match with @RejectContact * * @sa sip_contact_score(), sip_contact_accept(), sip_contact_immunize(), * sip_contact_is_immune(), @RFC3841, @RejectContact, @Contact */ int sip_contact_reject(sip_contact_t const *m, sip_reject_contact_t const *reject) { unsigned S, N; int error; if (!m || !m->m_params || !reject || !reject->cp_params) return 0; return sip_contact_accept(m, reject, &S, &N, &error) && S == N && N > 0; } /**Immunize @Contact to callerprefs. * * Make a copy of @Contact header @a m and remove all parameters which * affect caller preferences. * * @param home home object used when allocating copy * @param m pointer to @Contact header structure to immunize * * @retval pointer to immunized copy if successful * @retval NULL upon an error * * @sa @RFC3841, sip_is_callerpref(), sip_contact_score(), * sip_contact_accept(), sip_contact_reject(), @Contact */ sip_contact_t *sip_contact_immunize(su_home_t *home, sip_contact_t const *m) { unsigned i, j; sip_contact_t m0[1], *m1; msg_param_t *params; if (!m) return NULL; *m0 = *m, m0->m_next = NULL; m1 = sip_contact_copy(home, m0); if (m1 == NULL || !m1->m_params) return m1; params = (msg_param_t *)m1->m_params; for (i = 0, j = 0; params[i]; i++) { if (!sip_is_callerpref(params[i])) params[j++] = params[i]; } params[j] = NULL; return m1; } /** Calculate score for contact. * * The caller preference score is an integer in range of 0 to 1000. * * @retval -1 if the contact is rejected * @retval 1000 if contact is immune to caller preferences * @retval 0..1000 reflecting @RFC3841 score in 0.000 - 1.000. * * @sa msg_q_value(), * sip_contact_accept(), sip_contact_reject(), sip_contact_is_immune(), * sip_contact_immunize(), sip_is_callerpref(), sip_prefs_matching(), * @RFC3841, @AcceptContact, @RejectContact, @Contact */ int sip_contact_score(sip_contact_t const *m, sip_accept_contact_t const *ac, sip_reject_contact_t const *rc) { unsigned long S_total = 0; unsigned M = 0, scale = 1000; int error = 0; if (sip_contact_is_immune(m)) return 1000; /* Immune */ for (; rc; rc = rc->cp_next) if (sip_contact_reject(m, rc)) break; if (rc) return -1; /* Rejected */ for (; ac; ac = ac->cp_next) { unsigned S, N; if (!sip_contact_accept(m, ac, &S, &N, &error)) { if (ac->cp_require) return 0; /* Discarded */ continue; } M++; /* Apply score */ if (S < N && ac->cp_explicit) { S = 0; if (ac->cp_require) return 0; /* Dropped */ } if (S > 0 && N > 0) S_total += msg_q_value(ac->cp_q) * (scale * S / N + (2 * S >= N)); } if (!M) return 0; S_total /= M; if (S_total < scale * 1000) return S_total / scale; else return 1000; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sip_reason.c000066400000000000000000000116541223300710500226620ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE sip_reason.c * @brief @Reason header. * * The file @b sip_reason.c contains implementation of header class for * SIP header @Reason. * * @author Pekka Pessi . */ #include "config.h" /* Avoid casting sip_t to msg_pub_t and sip_header_t to msg_header_t */ #define MSG_PUB_T struct sip_s #define MSG_HDR_T union sip_header_u #include "sofia-sip/sip_parser.h" #include #include #include #include #include #include /**@SIP_HEADER sip_reason Reason Header * * The Reason header is used to indicate why a SIP request was issued or why * a provisional response was sent. It can be used with HRPF scenarios. It * is defined in @RFC3326 as follows: * * @code * Reason = "Reason" HCOLON reason-value *(COMMA reason-value) * reason-value = protocol *(SEMI reason-params) * protocol = "SIP" / "Q.850" / token * reason-params = protocol-cause / reason-text * / reason-extension * protocol-cause = "cause" EQUAL cause * cause = 1*DIGIT * reason-text = "text" EQUAL quoted-string * reason-extension = generic-param * @endcode * * The parsed Reason header is stored in #sip_reason_t structure. */ /**@ingroup sip_reason * @typedef typedef struct sip_reason_s sip_reason_t; * * The structure #sip_reason_t contains representation of SIP @Reason header. * * The #sip_reason_t is defined as follows: * @code * typedef struct sip_reason_s * { * sip_common_t re_common[1]; // Common fragment info * sip_reason_t *re_next; // Link to next * char const *re_protocol; // Protocol * msg_param_t const *re_params; // List of reason parameters * char const *re_cause; // Value of cause parameter * char const *re_text; // Value of text parameter * } sip_reason_t; * @endcode */ static msg_xtra_f sip_reason_dup_xtra; static msg_dup_f sip_reason_dup_one; static msg_update_f sip_reason_update; msg_hclass_t sip_reason_class[] = SIP_HEADER_CLASS(reason, "Reason", "", re_params, append, reason); issize_t sip_reason_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_reason_t *re = (sip_reason_t *)h; size_t n; while (*s == ',') /* Ignore empty entries (comma-whitespace) */ *s = '\0', s += span_lws(s + 1) + 1; re->re_protocol = s; if ((n = span_token(s)) == 0) return -1; s += n; while (IS_LWS(*s)) *s++ = '\0'; if (*s == ';' && msg_params_d(home, &s, &re->re_params) < 0) return -1; return msg_parse_next_field(home, h, s, slen); } issize_t sip_reason_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { char *end = b + bsiz, *b0 = b; sip_reason_t const *re = h->sh_reason; assert(sip_is_reason(h)); MSG_STRING_E(b, end, re->re_protocol); MSG_PARAMS_E(b, end, re->re_params, flags); return b - b0; } isize_t sip_reason_dup_xtra(sip_header_t const *h, isize_t offset) { sip_reason_t const *re = h->sh_reason; MSG_PARAMS_SIZE(offset, re->re_params); offset += MSG_STRING_SIZE(re->re_protocol); return offset; } /** Duplicate one #sip_reason_t object */ char *sip_reason_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { sip_reason_t *re_dst = dst->sh_reason; sip_reason_t const *re_src = src->sh_reason; char *end = b + xtra; b = msg_params_dup(&re_dst->re_params, re_src->re_params, b, xtra); MSG_STRING_DUP(b, re_dst->re_protocol, re_src->re_protocol); assert(b <= end); (void)end; return b; } /** Update parameter values for @Reason header */ static int sip_reason_update(msg_common_t *h, char const *name, isize_t namelen, char const *value) { sip_reason_t *re = (sip_reason_t *)h; if (name == NULL) { re->re_cause = NULL; re->re_text = NULL; } #define MATCH(s) (namelen == strlen(#s) && su_casenmatch(name, #s, strlen(#s))) else if (MATCH(cause)) { re->re_cause = value; } else if (MATCH(text)) { re->re_text = value; } #undef MATCH return 0; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sip_refer.c000066400000000000000000000363501223300710500224760ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE sip_refer.c * @brief SIP REFER-related headers. * * The file @b sip_refer.c contains implementation of header classes for * REFER-related SIP headers @ReferTo and @ReferredBy. * * @author Pekka Pessi * * @date Created: Wed Jan 23 13:23:45 EET 2002 ppessi */ #include "config.h" /* Avoid casting sip_t to msg_pub_t and sip_header_t to msg_header_t */ #define MSG_PUB_T struct sip_s #define MSG_HDR_T union sip_header_u #include "sofia-sip/sip_parser.h" #include "sofia-sip/sip_extra.h" #include #include #include #include #include #include /* ====================================================================== */ /**@SIP_HEADER sip_refer_to Refer-To Header * * The Refer-To header provides a URI to reference. Its syntax is defined in * @RFC3515 section 2.1 as follows: * * @code * Refer-To = ("Refer-To" / "r") HCOLON ( name-addr / addr-spec ) * *(SEMI generic-param) * @endcode * * * The parsed Refer-To header is stored in #sip_refer_to_t structure. */ /**@ingroup sip_refer_to * * @typedef typedef struct sip_refer_to_s sip_refer_to_t; * * The structure #sip_refer_to_t contains representation of @ReferTo * header. * * The #sip_refer_to_t is defined as follows: * @code * typedef struct sip_refer_to_s * { * sip_common_t r_common[1]; // Common fragment info * sip_error_t *r_next; // Link to next (dummy) * char const r_display; // Display name * url_t r_url[1]; // URI to reference * msg_param_t const *r_params; // List of generic parameters * } sip_refer_to_t; * @endcode */ static msg_xtra_f sip_refer_to_dup_xtra; static msg_dup_f sip_refer_to_dup_one; #define sip_refer_to_update NULL msg_hclass_t sip_refer_to_class[] = SIP_HEADER_CLASS(refer_to, "Refer-To", "r", r_params, single, refer_to); issize_t sip_refer_to_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { issize_t retval; sip_refer_to_t *r = (sip_refer_to_t *)h; retval = sip_name_addr_d(home, &s, &r->r_display, r->r_url, &r->r_params, NULL); if (retval < 0) return retval; if (*s == '?' && !r->r_display && !r->r_url->url_headers) { /* Missing <> around URL */ *s++ = '\0'; r->r_url->url_headers = s; s += strcspn(s, " \t;,"); if (IS_LWS(*s)) *s++ = '\0', skip_lws(&s); if (*s) return -1; r->r_display = s; /* Put empty string in display so that we encode using <> */ } else if (*s) return -1; return retval; } issize_t sip_refer_to_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { sip_refer_to_t const *r = h->sh_refer_to; assert(sip_is_refer_to(h)); return sip_name_addr_e(b, bsiz, flags, r->r_display, MSG_IS_CANONIC(flags), r->r_url, r->r_params, NULL); } isize_t sip_refer_to_dup_xtra(sip_header_t const *h, isize_t offset) { sip_refer_to_t const *r = h->sh_refer_to; MSG_PARAMS_SIZE(offset, r->r_params); offset += MSG_STRING_SIZE(r->r_display); offset += url_xtra(r->r_url); return offset; } /** Duplicate one #sip_refer_to_t object */ char *sip_refer_to_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { sip_refer_to_t *r_dst = dst->sh_refer_to; sip_refer_to_t const *r_src = src->sh_refer_to; char *end = b + xtra; b = msg_params_dup(&r_dst->r_params, r_src->r_params, b, xtra); MSG_STRING_DUP(b, r_dst->r_display, r_src->r_display); URL_DUP(b, end, r_dst->r_url, r_src->r_url); assert(b <= end); return b; } /* ====================================================================== */ /**@SIP_HEADER sip_referred_by Referred-By Header * * The Referred-By header conveys the identity of the original referrer to * the referred-to party. Its syntax is defined in * @RFC3892 section 3 as follows: * * @code * Referred-By = ("Referred-By" / "b") HCOLON referrer-uri * *( SEMI (referredby-id-param / generic-param) ) * * referrer-uri = ( name-addr / addr-spec ) * * referredby-id-param = "cid" EQUAL sip-clean-msg-id * * sip-clean-msg-id = LDQUOT dot-atom "@" (dot-atom / host) RDQUOT * * dot-atom = atom *( "." atom ) * * atom = 1*( alphanum / "-" / "!" / "%" / "*" / * "_" / "+" / "'" / "`" / "~" ) * @endcode * * * The parsed Referred-By header is stored in #sip_referred_by_t structure. */ /**@ingroup sip_referred_by * * @typedef typedef struct sip_referred_by_s sip_referred_by_t; * * The structure #sip_referred_by_t contains representation of @ReferredBy * header. * * The #sip_referred_by_t is defined as follows: * @code * typedef struct sip_referred_by_s * { * sip_common_t b_common[1]; // Common fragment info * sip_error_t *b_next; // Link to next (dummy) * char const b_display, * url_t b_url[1]; // Referrer-URI * msg_param_t const *b_params; // List of parameters * char const *b_cid; * } sip_referred_by_t; * @endcode */ static msg_xtra_f sip_referred_by_dup_xtra; static msg_dup_f sip_referred_by_dup_one; static msg_update_f sip_referred_by_update; msg_hclass_t sip_referred_by_class[] = SIP_HEADER_CLASS(referred_by, "Referred-By", "b", b_params, single, referred_by); issize_t sip_referred_by_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_referred_by_t *b = h->sh_referred_by; if (sip_name_addr_d(home, &s, &b->b_display, b->b_url, &b->b_params, NULL) < 0 || *s /* Extra stuff? */) return -1; if (b->b_params) msg_header_update_params(b->b_common, 0); return 0; } issize_t sip_referred_by_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { assert(sip_is_referred_by(h)); return sip_name_addr_e(b, bsiz, flags, h->sh_referred_by->b_display, MSG_IS_CANONIC(flags), h->sh_referred_by->b_url, h->sh_referred_by->b_params, NULL); } isize_t sip_referred_by_dup_xtra(sip_header_t const *h, isize_t offset) { sip_referred_by_t const *b = h->sh_referred_by; MSG_PARAMS_SIZE(offset, b->b_params); offset += MSG_STRING_SIZE(b->b_display); offset += url_xtra(b->b_url); return offset; } char *sip_referred_by_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { sip_referred_by_t *nb = dst->sh_referred_by; sip_referred_by_t const *o = src->sh_referred_by; char *end = b + xtra; b = msg_params_dup(&nb->b_params, o->b_params, b, xtra); MSG_STRING_DUP(b, nb->b_display, o->b_display); URL_DUP(b, end, nb->b_url, o->b_url); nb->b_cid = msg_params_find(nb->b_params, "cid="); assert(b <= end); return b; } static int sip_referred_by_update(msg_common_t *h, char const *name, isize_t namelen, char const *value) { sip_referred_by_t *b = (sip_referred_by_t *)h; if (name == NULL) { b->b_cid = NULL; } else if (namelen == strlen("cid") && su_casenmatch(name, "cid", namelen)) { b->b_cid = value; } return 0; } /* ====================================================================== */ /**@SIP_HEADER sip_replaces Replaces Header * * The Replaces header indicates that a single dialog identified by the * header field is to be shut down and logically replaced by the incoming * INVITE in which it is contained. Its syntax is defined in * @RFC3891 section 6.1 as follows: * * @code * Replaces = "Replaces" HCOLON callid *(SEMI replaces-param) * replaces-param = to-tag / from-tag / early-flag / generic-param * to-tag = "to-tag" EQUAL token * from-tag = "from-tag" EQUAL token * early-flag = "early-only" * @endcode * * A Replaces header field MUST contain exactly one and exactly * one , as they are required for unique dialog matching. For * compatibility with dialogs initiated by @RFC2543 compliant UAs, a * tag of zero ("0") matches both tags of zero and null. A Replaces header * field MAY contain the flag. * * The parsed Replaces header is stored in #sip_replaces_t structure. * * @sa @RFC3891, nta_leg_by_replaces(), nta_leg_make_replaces() */ /**@ingroup sip_replaces * * @typedef typedef struct sip_replaces_s sip_replaces_t; * * The structure #sip_replaces_t contains representation of @Replaces * header. * * The #sip_replaces_t is defined as follows: * @code * typedef struct sip_replaces_s * { * sip_common_t rp_common[1]; // Common fragment info * sip_error_t *rp_next; // Dummy link to next * char const *rp_call_id; // @CallID of dialog to replace * msg_param_t const *rp_params; // List of parameters * char const *rp_to_tag; // Value of "to-tag" parameter * char const *rp_from_tag; // Value of "from-tag" parameter * unsigned rp_early_only; // early-only parameter * } sip_replaces_t; * @endcode */ static msg_xtra_f sip_replaces_dup_xtra; static msg_dup_f sip_replaces_dup_one; static msg_update_f sip_replaces_update; msg_hclass_t sip_replaces_class[] = SIP_HEADER_CLASS(replaces, "Replaces", "", rp_params, single, replaces); /** Decode (parse) @Replaces header */ issize_t sip_replaces_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_replaces_t *rp = h->sh_replaces; rp->rp_call_id = sip_word_at_word_d(&s); if (!rp->rp_call_id) return -1; if (*s) { if (msg_params_d(home, &s, &rp->rp_params) == -1) return -1; msg_header_update_params(rp->rp_common, 0); } return s - rp->rp_call_id; } /** Encode (print) @Replaces header */ issize_t sip_replaces_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { char *b0 = b, *end = b + bsiz; sip_replaces_t const *rp = h->sh_replaces; assert(sip_is_replaces(h)); MSG_STRING_E(b, end, rp->rp_call_id); MSG_PARAMS_E(b, end, rp->rp_params, flags); MSG_TERM_E(b, end); return b - b0; } /** Calculate extra storage used by @Replaces header field */ isize_t sip_replaces_dup_xtra(sip_header_t const *h, isize_t offset) { sip_replaces_t const *rp = h->sh_replaces; MSG_PARAMS_SIZE(offset, rp->rp_params); offset += MSG_STRING_SIZE(rp->rp_call_id); return offset; } /** Duplicate a @Replaces header field */ char *sip_replaces_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { sip_replaces_t *rp_dst = dst->sh_replaces; sip_replaces_t const *rp_src = src->sh_replaces; char *end = b + xtra; b = msg_params_dup(&rp_dst->rp_params, rp_src->rp_params, b, xtra); MSG_STRING_DUP(b, rp_dst->rp_call_id, rp_src->rp_call_id); assert(b <= end); (void)end; return b; } /** Update parameters in @Replaces header. */ static int sip_replaces_update(msg_common_t *h, char const *name, isize_t namelen, char const *value) { sip_replaces_t *rp = (sip_replaces_t *)h; if (name == NULL) { rp->rp_to_tag = NULL; rp->rp_from_tag = NULL; rp->rp_early_only = 0; } #define MATCH(s) (namelen == strlen(#s) && su_casenmatch(name, #s, strlen(#s))) else if (MATCH(to-tag)) { rp->rp_to_tag = value; } else if (MATCH(from-tag)) { rp->rp_from_tag = value; } else if (MATCH(early-only)) { rp->rp_early_only = value != NULL; } #undef MATCH return 0; } /* ====================================================================== */ /**@SIP_HEADER sip_refer_sub Refer-Sub Header * * SIP header field @b Refer-Sub is meaningful and MAY be used with a REFER * request and the corresponding 2XX response only. This header field set to * "false" specifies that a REFER-Issuer requests that the REFER-Recipient * doesn't establish an implicit subscription and the resultant dialog. * * Refer-Sub = "Refer-Sub" HCOLON refer-sub-value *(SEMI exten) * refer-sub-value = "true" / "false" * exten = generic-param * * The parsed Refer-Sub header is stored in #sip_refer_sub_t structure. * * @NEW_1_12_5. Note that #sip_t does not contain @a sip_refer_sub field, * but sip_refer_sub() accessor function should be used for accessing @b * Refer-Sub header structure. * * @sa @RFC4488, nua_refer(), #nua_i_refer */ /**@ingroup sip_refer_sub * * @typedef typedef struct sip_refer_sub_s sip_refer_sub_t; * * The structure #sip_refer_sub_t contains representation of @ReferSub * header. * * The #sip_refer_sub_t is defined as follows: * @code * typedef struct sip_refer_sub_s * { * sip_common_t rs_common[1]; // Common fragment info * sip_error_t *rs_next; // Dummy link to next * char const *rs_value; // "true" or "false" * msg_param_t const *rs_params; // List of extension parameters * } sip_refer_sub_t; * @endcode * * @NEW_1_12_5. */ static msg_xtra_f sip_refer_sub_dup_xtra; static msg_dup_f sip_refer_sub_dup_one; #define sip_refer_sub_update NULL msg_hclass_t sip_refer_sub_class[] = SIP_HEADER_CLASS(refer_sub, "Refer-Sub", "", rs_params, single, refer_sub); /** Decode (parse) @ReferSub header */ issize_t sip_refer_sub_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_refer_sub_t *rs = (sip_refer_sub_t *)h; if (msg_token_d(&s, &rs->rs_value) < 0) return -1; if (!su_casematch(rs->rs_value, "false") && !su_casematch(rs->rs_value, "true")) return -1; if (*s) if (msg_params_d(home, &s, &rs->rs_params) == -1) return -1; return s - rs->rs_value; } /** Encode (print) @ReferSub header */ issize_t sip_refer_sub_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { char *b0 = b, *end = b + bsiz; sip_refer_sub_t const *rs = (sip_refer_sub_t *)h; assert(sip_is_refer_sub(h)); MSG_STRING_E(b, end, rs->rs_value); MSG_PARAMS_E(b, end, rs->rs_params, flags); MSG_TERM_E(b, end); return b - b0; } /** Calculate extra storage used by @ReferSub header field */ isize_t sip_refer_sub_dup_xtra(sip_header_t const *h, isize_t offset) { sip_refer_sub_t const *rs = (sip_refer_sub_t *)h; MSG_PARAMS_SIZE(offset, rs->rs_params); offset += MSG_STRING_SIZE(rs->rs_value); return offset; } /** Duplicate a @ReferSub header field */ char *sip_refer_sub_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { sip_refer_sub_t *rs_dst = (sip_refer_sub_t *)dst; sip_refer_sub_t const *rs_src = (sip_refer_sub_t *)src; char *end = b + xtra; b = msg_params_dup(&rs_dst->rs_params, rs_src->rs_params, b, xtra); MSG_STRING_DUP(b, rs_dst->rs_value, rs_src->rs_value); assert(b <= end); (void)end; return b; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sip_security.c000066400000000000000000000656641223300710500232540ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE sip_security.c * * Security-related SIP header handling. * * This file contains implementation of headers related to HTTP authentication * (@RFC2617): * @ref sip_authorization "Authorization", * @ref sip_authentication_info "Authentication-Info", * @ref sip_proxy_authenticate "Proxy-Authenticate", * @ref sip_proxy_authentication_info "Proxy-Authentication-Info", * @ref sip_proxy_authorization "Proxy-Authorization", and * @ref sip_www_authenticate "WWW-Authenticate". * * There is also implementation of headers related to security agreement * (@RFC3329): * @ref sip_security_client "Security-Client", * @ref sip_security_server "Security-Server", and * @ref sip_security_verify "Security-Verify" headers. * * The implementation of @ref sip_privacy "Privacy" header (@RFC3323) is * also here. * * @author Pekka Pessi . * * @date Created: Tue Jun 13 02:57:51 2000 ppessi */ #include "config.h" /* Avoid casting sip_t to msg_pub_t and sip_header_t to msg_header_t */ #define MSG_PUB_T struct sip_s #define MSG_HDR_T union sip_header_u #include "sofia-sip/sip_parser.h" #include #include #include #include #include #include /* ====================================================================== */ /**@SIP_HEADER sip_authorization Authorization Header * * The Authorization header consists of credentials containing the * authentication information of the user agent for the realm of the * resource being requested. Its syntax is defined in @RFC2617 and @RFC3261 * as follows: * * @code * Authorization = "Authorization" HCOLON credentials * credentials = ("Digest" LWS digest-response) * / other-response * digest-response = dig-resp *(COMMA dig-resp) * dig-resp = username / realm / nonce / digest-uri * / dresponse / algorithm / cnonce * / opaque / message-qop * / nonce-count / auth-param * username = "username" EQUAL username-value * username-value = quoted-string * digest-uri = "uri" EQUAL LDQUOT digest-uri-value RDQUOT * digest-uri-value = rquest-uri ; Equal to request-uri as specified * by HTTP/1.1 * message-qop = "qop" EQUAL qop-value * cnonce = "cnonce" EQUAL cnonce-value * cnonce-value = nonce-value * nonce-count = "nc" EQUAL nc-value * nc-value = 8LHEX * dresponse = "response" EQUAL request-digest * request-digest = LDQUOT 32LHEX RDQUOT * auth-param = auth-param-name EQUAL * ( token / quoted-string ) * auth-param-name = token * other-response = auth-scheme LWS auth-param * *(COMMA auth-param) * auth-scheme = token * @endcode * * The parsed Authorization header * is stored in #sip_authorization_t structure. * * @sa @RFC2617, auth_mod_verify(), auth_mod_check(), auth_get_params(), * auth_digest_response_get(). */ /**@ingroup sip_authorization * @typedef typedef struct sip_authorization_s sip_authorization_t; * * The structure #sip_authorization_t contains representation of SIP * @Authorization header. * * The #sip_authorization_t is defined as follows: * @code * typedef struct msg_auth_s { * msg_common_t au_common[1]; // Common fragment info * msg_auth_t *au_next; // Link to next header * char const *au_scheme; // Auth-scheme like "Basic" or "Digest" * msg_param_t const *au_params; // Comma-separated parameters * } sip_authorization_t; * @endcode * */ msg_hclass_t sip_authorization_class[] = SIP_HEADER_CLASS_AUTH(authorization, "Authorization", append); issize_t sip_authorization_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return msg_auth_d(home, h, s, slen); } issize_t sip_authorization_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { assert(sip_is_authorization(h)); return msg_auth_e(b, bsiz, h, f); } /* ====================================================================== */ /**@SIP_HEADER sip_proxy_authenticate Proxy-Authenticate Header * * The Proxy-Authenticate header consists of a challenge that indicates the * authentication scheme and parameters applicable to the proxy. Its syntax * is defined in [H14.33, S10.31] as follows: * * @code * Proxy-Authenticate = "Proxy-Authenticate" HCOLON challenge * challenge = ("Digest" LWS digest-cln *(COMMA digest-cln)) * / other-challenge * other-challenge = auth-scheme LWS auth-param * *(COMMA auth-param) * digest-cln = realm / domain / nonce * / opaque / stale / algorithm * / qop-options / auth-param * realm = "realm" EQUAL realm-value * realm-value = quoted-string * domain = "domain" EQUAL LDQUOT URI * *( 1*SP URI ) RDQUOT * URI = absoluteURI / abs-path * nonce = "nonce" EQUAL nonce-value * nonce-value = quoted-string * opaque = "opaque" EQUAL quoted-string * stale = "stale" EQUAL ( "true" / "false" ) * algorithm = "algorithm" EQUAL ( "MD5" / "MD5-sess" * / token ) * qop-options = "qop" EQUAL LDQUOT qop-value * *("," qop-value) RDQUOT * qop-value = "auth" / "auth-int" / token * @endcode * * * The parsed Proxy-Authenticate header * is stored in #sip_proxy_authenticate_t structure. */ /**@ingroup sip_proxy_authenticate * @typedef typedef struct sip_proxy_authenticate_s sip_proxy_authenticate_t; * * The structure #sip_proxy_authenticate_t contains representation of SIP * @ProxyAuthenticate header. * * The #sip_proxy_authenticate_t is defined as follows: * @code * typedef struct msg_auth_s { * msg_common_t au_common[1]; // Common fragment info * msg_auth_t *au_next; // Link to next header * char const *au_scheme; // Auth-scheme like "Basic" or "Digest" * msg_param_t const *au_params; // Comma-separated parameters * } sip_proxy_authenticate_t; * @endcode * */ msg_hclass_t sip_proxy_authenticate_class[] = SIP_HEADER_CLASS_AUTH(proxy_authenticate, "Proxy-Authenticate", append); issize_t sip_proxy_authenticate_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return msg_auth_d(home, h, s, slen); } issize_t sip_proxy_authenticate_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { assert(sip_is_proxy_authenticate(h)); return msg_auth_e(b, bsiz, h, f); } /* ====================================================================== */ /**@SIP_HEADER sip_proxy_authorization Proxy-Authorization Header * * The Proxy-Authorization header consists of credentials containing the * authentication information of the user agent for the proxy and/or realm * of the resource being requested. Its syntax is defined in @RFC3261 * as follows: * * @code * Proxy-Authorization = "Proxy-Authorization" ":" credentials * credentials = ("Digest" LWS digest-response) * / other-response * @endcode * * @sa auth_mod_verify(), auth_mod_check(), auth_get_params(), * auth_digest_response_get(). * * The parsed Proxy-Authorization header * is stored in #sip_proxy_authorization_t structure. */ /**@ingroup sip_proxy_authorization * @typedef typedef struct sip_proxy_authorization_s sip_proxy_authorization_t; * * The structure #sip_proxy_authorization_t contains representation of SIP * @ProxyAuthorization header. * * The #sip_proxy_authorization_t is defined as follows: * @code * typedef struct msg_auth_s { * msg_common_t au_common[1]; // Common fragment info * msg_auth_t *au_next; // Link to next header * char const *au_scheme; // Auth-scheme like "Basic" or "Digest" * msg_param_t const *au_params; // Comma-separated parameters * } sip_proxy_authorization_t; * @endcode * */ msg_hclass_t sip_proxy_authorization_class[] = SIP_HEADER_CLASS_AUTH(proxy_authorization, "Proxy-Authorization", append); issize_t sip_proxy_authorization_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return msg_auth_d(home, h, s, slen); } issize_t sip_proxy_authorization_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { assert(sip_is_proxy_authorization(h)); return msg_auth_e(b, bsiz, h, f); } /* ====================================================================== */ /**@SIP_HEADER sip_www_authenticate WWW-Authenticate Header * * The WWW-Authenticate header consists of at least one challenge that * indicates the authentication scheme(s) and parameters applicable to the * Request-URI. Its syntax is defined in @RFC3261 as * follows: * * @code * WWW-Authenticate = "WWW-Authenticate" HCOLON challenge * challenge = ("Digest" LWS digest-cln *(COMMA digest-cln)) * / other-challenge * other-challenge = auth-scheme LWS auth-param *(COMMA auth-param) * @endcode * * See @ProxyAuthenticate for the definition of \. * * The parsed WWW-Authenticate header * is stored in #sip_www_authenticate_t structure. */ /**@ingroup sip_www_authenticate * @typedef typedef struct sip_www_authenticate_s sip_www_authenticate_t; * * The structure #sip_www_authenticate_t contains representation of SIP * @WWWAuthenticate header. * * The #sip_www_authenticate_t is defined as follows: * @code * typedef struct msg_auth_s { * msg_common_t au_common[1]; // Common fragment info * msg_auth_t *au_next; // Link to next header * char const *au_scheme; // Auth-scheme like "Basic" or "Digest" * msg_param_t const *au_params; // Comma-separated parameters * } sip_www_authenticate_t; * @endcode * */ msg_hclass_t sip_www_authenticate_class[] = SIP_HEADER_CLASS_AUTH(www_authenticate, "WWW-Authenticate", append); issize_t sip_www_authenticate_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return msg_auth_d(home, h, s, slen); } issize_t sip_www_authenticate_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { assert(sip_is_www_authenticate(h)); return msg_auth_e(b, bsiz, h, f); } /**@SIP_HEADER sip_authentication_info Authentication-Info Header * * The @b Authentication-Info header contains either a next-nonce used by * next request and/or authentication from server used in mutual * authentication. The syntax of @b Authentication-Info header is defined in * @RFC2617 and @RFC3261 as follows: * * @code * Authentication-Info = "Authentication-Info" HCOLON ainfo * *(COMMA ainfo) * ainfo = nextnonce / message-qop * / response-auth / cnonce * / nonce-count * nextnonce = "nextnonce" EQUAL nonce-value * response-auth = "rspauth" EQUAL response-digest * response-digest = LDQUOT *LHEX RDQUOT * @endcode * * The parsed Authentication-Info header * is stored in #sip_authentication_info_t structure. */ /**@ingroup sip_authentication_info * @typedef typedef struct sip_authentication_info_s sip_authentication_info_t; * * The structure #sip_authentication_info_t contains representation of SIP * @AuthenticationInfo header. * * The #sip_authentication_info_t is defined as follows: * @code * typedef struct msg_auth_info_s * { * msg_common_t ai_common[1]; // Common fragment info * msg_error_t *ai_next; // Dummy link to next header * msg_param_t *ai_items; // List of ainfo * } sip_authentication_info_t; * @endcode */ #define sip_authentication_info_dup_xtra msg_list_dup_xtra #define sip_authentication_info_dup_one msg_list_dup_one #define sip_authentication_info_update NULL msg_hclass_t sip_authentication_info_class[] = SIP_HEADER_CLASS(authentication_info, "Authentication-Info", "", ai_params, append, authentication_info); issize_t sip_authentication_info_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return msg_list_d(home, (msg_header_t *)h, s, slen); } issize_t sip_authentication_info_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { assert(sip_is_authentication_info(h)); return msg_list_e(b, bsiz, h, f); } /* ====================================================================== */ /**@SIP_HEADER sip_proxy_authentication_info Proxy-Authentication-Info Header * * The @b Proxy-Authentication-Info header contains either a next-nonce used * by next request and/or authentication from proxy used in mutual * authentication. The syntax of @b Proxy-Authentication-Info header is defined * in @RFC2617 as follows: * * @code * Proxy-Authentication-Info = "Proxy-Authentication-Info" HCOLON ainfo * *(COMMA ainfo) * ainfo = nextnonce / message-qop * / response-auth / cnonce * / nonce-count * nextnonce = "nextnonce" EQUAL nonce-value * response-auth = "rspauth" EQUAL response-digest * response-digest = LDQUOT *LHEX RDQUOT * @endcode * * @note @b Proxy-Authentication-Info is not specified @RFC3261 and it is * mentioned by @RFC2617 but in passage. * * The parsed Proxy-Authentication-Info header * is stored in #sip_proxy_authentication_info_t structure. */ /**@ingroup sip_proxy_authentication_info * @typedef typedef struct msg_authentication_info_s sip_proxy_authentication_info_t; * * The structure #sip_proxy_authentication_info_t contains representation of SIP * @ProxyAuthenticationInfo header. * * The #sip_proxy_authentication_info_t is defined as follows: * @code * typedef struct msg_auth_info_s * { * msg_common_t ai_common[1]; // Common fragment info * msg_error_t *ai_next; // Dummy link to next header * msg_param_t *ai_items; // List of ainfo * } sip_proxy_authentication_info_t; * @endcode * */ #define sip_proxy_authentication_info_dup_xtra msg_list_dup_xtra #define sip_proxy_authentication_info_dup_one msg_list_dup_one #define sip_proxy_authentication_info_update NULL msg_hclass_t sip_proxy_authentication_info_class[] = SIP_HEADER_CLASS(proxy_authentication_info, "Proxy-Authentication-Info", "", ai_params, append, proxy_authentication_info); issize_t sip_proxy_authentication_info_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return msg_list_d(home, (msg_header_t *)h, s, slen); } issize_t sip_proxy_authentication_info_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { assert(sip_is_proxy_authentication_info(h)); /* This is soo popular */ return msg_list_e(b, bsiz, h, f); } /* ====================================================================== */ /* Functions parsing @RFC3329 SIP Security Agreement headers */ typedef struct sip_security_agree_s sip_security_agree_t; #define sh_security_agree sh_security_client static issize_t sip_security_agree_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_security_agree_t *sa = (sip_security_agree_t *)h; isize_t n; while (*s == ',') /* Ignore empty entries (comma-whitespace) */ *s = '\0', s += span_lws(s + 1) + 1; if ((n = span_token(s)) == 0) return -1; sa->sa_mec = s; s += n; while (IS_LWS(*s)) *s++ = '\0'; if (*s == ';' && msg_params_d(home, &s, &sa->sa_params) < 0) return -1; return msg_parse_next_field(home, h, s, slen); } static issize_t sip_security_agree_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { char *end = b + bsiz, *b0 = b; sip_security_agree_t const *sa = (sip_security_agree_t const *)h; MSG_STRING_E(b, end, sa->sa_mec); MSG_PARAMS_E(b, end, sa->sa_params, flags); return b - b0; } static isize_t sip_security_agree_dup_xtra(sip_header_t const *h, isize_t offset) { sip_security_agree_t const *sa = h->sh_security_agree; MSG_PARAMS_SIZE(offset, sa->sa_params); offset += MSG_STRING_SIZE(sa->sa_mec); return offset; } /** Duplicate one sip_security_agree_t object */ static char *sip_security_agree_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { sip_security_agree_t *sa_dst = dst->sh_security_agree; sip_security_agree_t const *sa_src = src->sh_security_agree; char *end = b + xtra; b = msg_params_dup(&sa_dst->sa_params, sa_src->sa_params, b, xtra); MSG_STRING_DUP(b, sa_dst->sa_mec, sa_src->sa_mec); assert(b <= end); (void)end; return b; } static int sip_security_agree_update(msg_common_t *h, char const *name, isize_t namelen, char const *value) { sip_security_agree_t *sa = (sip_security_agree_t *)h; if (name == NULL) { sa->sa_q = NULL; sa->sa_d_alg = NULL; sa->sa_d_qop = NULL; sa->sa_d_ver = NULL; } #define MATCH(s) (namelen == strlen(#s) && su_casenmatch(name, #s, strlen(#s))) else if (MATCH(q)) { sa->sa_q = value; } else if (MATCH(d-alg)) { sa->sa_d_alg = value; } else if (MATCH(d-qop)) { sa->sa_d_qop = value; } else if (MATCH(d-ver)) { sa->sa_d_ver = value; } #undef MATCH return 0; } /**@SIP_HEADER sip_security_client Security-Client Header * * The Security-Client header is defined by @RFC3329, "Security Mechanism * Agreement for the Session Initiation Protocol (SIP)". * * @code * security-client = "Security-Client" HCOLON * sec-mechanism *(COMMA sec-mechanism) * security-server = "Security-Server" HCOLON * sec-mechanism *(COMMA sec-mechanism) * security-verify = "Security-Verify" HCOLON * sec-mechanism *(COMMA sec-mechanism) * sec-mechanism = mechanism-name *(SEMI mech-parameters) * mechanism-name = ( "digest" / "tls" / "ipsec-ike" / * "ipsec-man" / token ) * mech-parameters = ( preference / digest-algorithm / * digest-qop / digest-verify / extension ) * preference = "q" EQUAL qvalue * qvalue = ( "0" [ "." 0*3DIGIT ] ) * / ( "1" [ "." 0*3("0") ] ) * digest-algorithm = "d-alg" EQUAL token * digest-qop = "d-qop" EQUAL token * digest-verify = "d-ver" EQUAL LDQUOT 32LHEX RDQUOT * extension = generic-param * @endcode * * @sa @SecurityServer, @SecurityVerify, sip_security_verify_compare(), * sip_security_client_select(), @RFC3329 * * The parsed Security-Client header * is stored in #sip_security_client_t structure. */ /**@ingroup sip_security_client * @typedef typedef struct sip_security_client_s sip_security_client_t; * * The structure #sip_security_client_t contains representation of SIP * @SecurityClient header. * * The #sip_security_client_t is defined as follows: * @code * typedef struct sip_security_agree_s * { * sip_common_t sa_common[1]; // Common fragment info * sip_security_client_t *sa_next; // Link to next mechanism * char const *sa_mec; // Security mechanism * msg_param_t const *sa_params; // List of mechanism parameters * char const *sa_q; // Value of q (preference) parameter * char const *sa_d_alg; // Value of d-alg parameter * char const *sa_d_qop; // Value of d-qop parameter * char const *sa_d_ver; // Value of d-ver parameter * } sip_security_client_t; * @endcode */ msg_hclass_t sip_security_client_class[] = SIP_HEADER_CLASS(security_client, "Security-Client", "", sa_params, append, security_agree); issize_t sip_security_client_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return sip_security_agree_d(home, h, s, slen); } issize_t sip_security_client_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { return sip_security_agree_e(b, bsiz, h, f); } /**@SIP_HEADER sip_security_server Security-Server Header * * The Security-Server header is defined by @RFC3329, "Security Mechanism * Agreement for the Session Initiation Protocol (SIP)". * * @sa @SecurityClient, @SecurityVerify, sip_security_verify_compare(), * sip_security_client_select(), @RFC3329. * * The parsed Security-Server header * is stored in #sip_security_server_t structure. */ /**@ingroup sip_security_server * @typedef typedef struct sip_security_server_s sip_security_server_t; * * The structure #sip_security_server_t contains representation of SIP * @SecurityServer header. * * The #sip_security_server_t is defined as follows: * @code * typedef struct sip_security_agree_s * { * sip_common_t sa_common[1]; // Common fragment info * sip_security_server_t *sa_next; // Link to next mechanism * char const *sa_mec; // Security mechanism * msg_param_t const *sa_params; // List of mechanism parameters * char const *sa_q; // Value of q (preference) parameter * char const *sa_d_alg; // Value of d-alg parameter * char const *sa_d_qop; // Value of d-qop parameter * char const *sa_d_ver; // Value of d-ver parameter * } sip_security_server_t; * @endcode */ msg_hclass_t sip_security_server_class[] = SIP_HEADER_CLASS(security_server, "Security-Server", "", sa_params, append, security_agree); issize_t sip_security_server_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return sip_security_agree_d(home, h, s, slen); } issize_t sip_security_server_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { return sip_security_agree_e(b, bsiz, h, f); } /**@SIP_HEADER sip_security_verify Security-Verify Header * * The Security-Verify header is defined by @RFC3329, "Security Mechanism * Agreement for the Session Initiation Protocol (SIP)". * * @sa @SecurityClient, @SecurityServer, sip_security_verify_compare(), * sip_security_client_select(), @RFC3329. * * The parsed Security-Verify header * is stored in #sip_security_verify_t structure. */ /**@ingroup sip_security_verify * @typedef typedef struct sip_security_verify_s sip_security_verify_t; * * The structure #sip_security_verify_t contains representation of SIP * @SecurityVerify header. * * The #sip_security_verify_t is defined as follows: * @code * typedef struct sip_security_agree_s * { * sip_common_t sa_common[1]; // Common fragment info * sip_security_verify_t *sa_next; // Link to next mechanism * char const *sa_mec; // Security mechanism * msg_param_t const *sa_params; // List of mechanism parameters * char const *sa_q; // Value of q (preference) parameter * char const *sa_d_alg; // Value of d-alg parameter * char const *sa_d_qop; // Value of d-qop parameter * char const *sa_d_ver; // Value of d-ver parameter * } sip_security_verify_t; * @endcode */ msg_hclass_t sip_security_verify_class[] = SIP_HEADER_CLASS(security_verify, "Security-Verify", "", sa_params, append, security_agree); issize_t sip_security_verify_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { return sip_security_agree_d(home, h, s, slen); } issize_t sip_security_verify_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { return sip_security_agree_e(b, bsiz, h, f); } /* ====================================================================== */ /* RFC 3323 */ /**@SIP_HEADER sip_privacy Privacy Header * * The Privacy header is used by User-Agent to request privacy services from * the network. Its syntax is defined in @RFC3323 as follows: * * @code * Privacy-hdr = "Privacy" HCOLON priv-value *(";" priv-value) * priv-value = "header" / "session" / "user" / "none" / "critical" * / token * @endcode * * The parsed Privacy header is stored in #sip_privacy_t structure. */ /**@ingroup sip_privacy * @typedef typedef struct sip_privacy_s sip_privacy_t; * * The structure #sip_privacy_t contains representation of a SIP @Privacy * header. * * The #sip_privacy_t is defined as follows: * @code * typedef struct sip_privacy_s { * sip_common_t priv_common[1]; // Common fragment info * sip_error_t *priv_next; // Dummy link * msg_param_t const *priv_values; // List of privacy values * } sip_privacy_t; * @endcode */ msg_xtra_f sip_privacy_dup_xtra; msg_dup_f sip_privacy_dup_one; #define sip_privacy_update NULL msg_hclass_t sip_privacy_class[] = SIP_HEADER_CLASS(privacy, "Privacy", "", priv_values, single, privacy); static issize_t sip_privacy_token_scan(char *start) { char *s = start; skip_token(&s); if (s == start) return -1; if (IS_LWS(*s)) *s++ = '\0'; skip_lws(&s); return s - start; } issize_t sip_privacy_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_privacy_t *priv = (sip_privacy_t *)h; while (*s == ';' || *s == ',') { s++; skip_lws(&s); } for (;;) { if (msg_any_list_d(home, &s, (msg_param_t **)&priv->priv_values, sip_privacy_token_scan, ';') < 0) return -1; if (*s == '\0') return 0; /* Success! */ if (*s == ',') *s++ = '\0'; /* We accept comma-separated list, too */ else if (IS_TOKEN(*s)) ; /* LWS separated list... */ else return -1; } } issize_t sip_privacy_e(char b[], isize_t bsiz, sip_header_t const *h, int f) { sip_privacy_t const *priv = h->sh_privacy; char *b0 = b, *end = b + bsiz; size_t i; if (priv->priv_values) { for (i = 0; priv->priv_values[i]; i++) { if (i > 0) MSG_CHAR_E(b, end, ';'); MSG_STRING_E(b, end, priv->priv_values[i]); } } MSG_TERM_E(b, end); return b - b0; } isize_t sip_privacy_dup_xtra(sip_header_t const *h, isize_t offset) { sip_privacy_t const *priv = h->sh_privacy; MSG_PARAMS_SIZE(offset, priv->priv_values); return offset; } char *sip_privacy_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { sip_privacy_t *priv = dst->sh_privacy; sip_privacy_t const *o = src->sh_privacy; char *end = b + xtra; b = msg_params_dup(&priv->priv_values, o->priv_values, b, xtra); assert(b <= end); (void)end; return b; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sip_session.c000066400000000000000000000156241223300710500230570ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE sip_session.c * @brief Session Timer SIP headers. * * The file @b sip_session.c contains implementation of header classes for * session-timer-related SIP headers @SessionExpires and @MinSE. * * @author Pekka Pessi . * * @date Created: Thu Sep 13 21:24:15 EEST 2001 ppessi */ #include "config.h" /* Avoid casting sip_t to msg_pub_t and sip_header_t to msg_header_t */ #define MSG_PUB_T struct sip_s #define MSG_HDR_T union sip_header_u #include "sofia-sip/sip_parser.h" #include #include #include #include #include #include /* ====================================================================== */ /**@SIP_HEADER sip_session_expires Session-Expires Header * * The Session-Expires header is used to convey the lifetime of the session. * Its syntax is defined in @RFC4028 as follows: * * @code * Session-Expires = ("Session-Expires" | "x") HCOLON delta-seconds * *(SEMI se-params) * se-params = refresher-param / generic-param * refresher-param = "refresher" EQUAL ("uas" / "uac") * @endcode * * The parsed Session-Expires header is stored in #sip_session_expires_t structure. */ /**@ingroup sip_session_expires * @typedef typedef struct sip_session_expires_s sip_session_expires_t; * * The structure #sip_session_expires_t contains representation of the SIP * @SessionExpires header. * * The #sip_session_expires_t is defined as follows: * @code * typedef struct sip_session_expires_s * { * sip_common_t x_common[1]; * sip_unknown_t *x_next; * unsigned long x_delta; //Delta Seconds * msg_param_t *x_params; * char const *x_refresher; //Who will send the refresh UAS or UAC * } sip_session_expires_t; * @endcode */ static msg_xtra_f sip_session_expires_dup_xtra; static msg_dup_f sip_session_expires_dup_one; static msg_update_f sip_session_expires_update; msg_hclass_t sip_session_expires_class[] = SIP_HEADER_CLASS(session_expires, "Session-Expires", "x", x_params, single, session_expires); issize_t sip_session_expires_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_session_expires_t *x = h->sh_session_expires; if (msg_delta_d((char const **) &s, &x->x_delta) < 0) return -1; if (*s == ';') { if (msg_params_d(home, &s, &x->x_params) < 0 || *s) return -1; x->x_refresher = msg_params_find(x->x_params, "refresher"); } return 0; } issize_t sip_session_expires_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { char *end = b + bsiz, *b0 = b; int n = 0; sip_session_expires_t const *o = h->sh_session_expires; n = snprintf(b, bsiz, "%lu", o->x_delta); b += n; MSG_PARAMS_E(b, end, o->x_params, flags); return b - b0; } isize_t sip_session_expires_dup_xtra(sip_header_t const *h, isize_t offset) { sip_session_expires_t const *o = h->sh_session_expires; MSG_PARAMS_SIZE(offset, o->x_params); return offset; } /** Duplicate one #sip_session_expires_t object */ char *sip_session_expires_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { sip_session_expires_t *o_dst = dst->sh_session_expires; sip_session_expires_t const *o_src = src->sh_session_expires; char *end = b + xtra; b = msg_params_dup(&o_dst->x_params, o_src->x_params, b, xtra); o_dst->x_delta = o_src->x_delta; assert(b <= end); (void)end; return b; } /** Update parameters in @SessionExpires header. */ static int sip_session_expires_update(msg_common_t *h, char const *name, isize_t namelen, char const *value) { sip_session_expires_t *x = (sip_session_expires_t *)h; if (name == NULL) { x->x_refresher = NULL; } else if (namelen == strlen("refresher") && su_casenmatch(name, "refresher", namelen)) { x->x_refresher = value; } return 0; } /**@SIP_HEADER sip_min_se Min-SE Header * * The Min-SE header is used to indicate the minimum value for the session * interval. Its syntax is defined in @RFC4028 as follows: * * @code * MMin-SE = "Min-SE" HCOLON delta-seconds *(SEMI generic-param) * @endcode * * The parsed Min-SE header is stored in #sip_min_se_t structure. */ /**@ingroup sip_min_se * @typedef typedef struct sip_min_se_s sip_min_se_t; * * The structure #sip_min_se_t contains representation of the SIP * @MinSE header. * * The #sip_min_se_t is defined as follows: * @code * typedef struct sip_min_se_s * { * sip_common_t min_common[1]; * sip_unknown_t *min_next; * unsigned long min_delta; // Delta seconds * sip_params_t *min_params; // List of extension parameters * } sip_min_se_t; * @endcode */ static msg_xtra_f sip_min_se_dup_xtra; static msg_dup_f sip_min_se_dup_one; #define sip_min_se_update NULL msg_hclass_t sip_min_se_class[] = SIP_HEADER_CLASS(min_se, "Min-SE", "", min_params, single, min_se); issize_t sip_min_se_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { sip_min_se_t *min = h->sh_min_se; if (msg_delta_d((char const **) &s, &min->min_delta) < 0) return -1; if (*s == ';') { if (msg_params_d(home, &s, &min->min_params) < 0 || *s) return -1; } return 0; } issize_t sip_min_se_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) { char *end = b + bsiz, *b0 = b; int n = 0; sip_min_se_t const *o = (sip_min_se_t *)h; n = snprintf(b, bsiz, "%lu", o->min_delta); b += n; MSG_PARAMS_E(b, end, o->min_params, flags); return b - b0; } isize_t sip_min_se_dup_xtra(sip_header_t const *h, isize_t offset) { sip_min_se_t const *o = (sip_min_se_t *)h; MSG_PARAMS_SIZE(offset, o->min_params); return offset; } /** Duplicate one #sip_min_se_t object */ char *sip_min_se_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra) { sip_min_se_t *o_dst = (sip_min_se_t *)dst; sip_min_se_t const *o_src = (sip_min_se_t *)src; char *end = b + xtra; b = msg_params_dup(&o_dst->min_params, o_src->min_params, b, xtra); o_dst->min_delta = o_src->min_delta; assert(b <= end); (void)end; return b; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sip_status.c000066400000000000000000000174261223300710500227210ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@ingroup sip_status_codes * @CFILE sip_status.c * * SIP status codes and standard phrases. * * @author Pekka Pessi . * * @date Created: Fri Aug 11 18:03:33 2000 ppessi */ #include "config.h" #include #include char const sip_100_Trying[] = "Trying", sip_180_Ringing[] = "Ringing", sip_181_Call_is_being_forwarded[] = "Call Is Being Forwarded", sip_182_Queued[] = "Queued", sip_183_Session_progress[] = "Session Progress", sip_200_OK[] = "OK", sip_202_Accepted[] = "Accepted", sip_300_Multiple_choices[] = "Multiple Choices", sip_301_Moved_permanently[] = "Moved Permanently", sip_302_Moved_temporarily[] = "Moved Temporarily", sip_305_Use_proxy[] = "Use Proxy", sip_380_Alternative_service[] = "Alternative Service", sip_400_Bad_request[] = "Bad Request", sip_401_Unauthorized[] = "Unauthorized", sip_402_Payment_required[] = "Payment Required", sip_403_Forbidden[] = "Forbidden", sip_404_Not_found[] = "Not Found", sip_405_Method_not_allowed[] = "Method Not Allowed", sip_406_Not_acceptable[] = "Not Acceptable", sip_407_Proxy_auth_required[] = "Proxy Authentication Required", sip_408_Request_timeout[] = "Request Timeout", sip_409_Conflict[] = "Conflict", sip_410_Gone[] = "Gone", sip_411_Length_required[] = "Length Required", sip_412_Precondition_failed[] = "Precondition Failed", sip_413_Request_too_large[] = "Request Entity Too Large", sip_414_Request_uri_too_long[] = "Request-URI Too Long", sip_415_Unsupported_media[] = "Unsupported Media Type", sip_416_Unsupported_uri[] = "Unsupported URI Scheme", sip_417_Resource_priority[]= "Unknown Resource-Priority", sip_420_Bad_extension[] = "Bad Extension", sip_421_Extension_required[] = "Extension Required", sip_422_Session_timer[] = "Session Interval Too Small", sip_423_Interval_too_brief[] = "Interval Too Brief", sip_480_Temporarily_unavailable[] = "Temporarily Unavailable", sip_481_No_transaction[] = "Call/Transaction Does Not Exist", sip_482_Loop_detected[] = "Loop Detected", sip_483_Too_many_hops[] = "Too Many Hops", sip_484_Address_incomplete[] = "Address Incomplete", sip_485_Ambiguous[] = "Ambiguous", sip_486_Busy_here[] = "Busy Here", sip_487_Request_terminated[] = "Request Terminated", sip_488_Not_acceptable[] = "Not Acceptable Here", sip_489_Bad_event[] = "Bad Event", sip_490_Request_updated[] = "Request Updated", sip_491_Request_pending[] = "Request Pending", sip_493_Undecipherable[] = "Undecipherable", sip_494_Secagree_required [] = "Security Agreement Required", sip_500_Internal_server_error[] = "Internal Server Error", sip_501_Not_implemented[] = "Not Implemented", sip_502_Bad_gateway[] = "Bad Gateway", sip_503_Service_unavailable[] = "Service Unavailable", sip_504_Gateway_time_out[] = "Gateway Time-out", sip_505_Version_not_supported[] = "Version Not Supported", sip_513_Message_too_large[] = "Message Too Large", sip_580_Precondition[] = "Precondition Failure", sip_600_Busy_everywhere[] = "Busy Everywhere", sip_603_Decline[] = "Decline", sip_604_Does_not_exist_anywhere[] = "Does Not Exist Anywhere", sip_606_Not_acceptable[] = "Not Acceptable", sip_687_Dialog_terminated[] = "Dialog Terminated" ; /** Convert a SIP status code to a status phrase. * * Convert a SIP status code to a status phrase. If the status code is not * in the range 100..699, NULL is returned. If the status code is not known, * empty string "" is returned. * * @param status well-known status code in range 100..699 * * @return * A response message corresponding to status code, or NULL upon an error. */ char const *sip_status_phrase(int status) { if (status < 100 || status > 699) return NULL; switch (status) { case 100: return sip_100_Trying; case 180: return sip_180_Ringing; case 181: return sip_181_Call_is_being_forwarded; case 182: return sip_182_Queued; case 183: return sip_183_Session_progress; case 200: return sip_200_OK; case 202: return sip_202_Accepted; case 300: return sip_300_Multiple_choices; case 301: return sip_301_Moved_permanently; case 302: return sip_302_Moved_temporarily; case 305: return sip_305_Use_proxy; case 380: return sip_380_Alternative_service; case 400: return sip_400_Bad_request; case 401: return sip_401_Unauthorized; case 402: return sip_402_Payment_required; case 403: return sip_403_Forbidden; case 404: return sip_404_Not_found; case 405: return sip_405_Method_not_allowed; case 406: return sip_406_Not_acceptable; case 407: return sip_407_Proxy_auth_required; case 408: return sip_408_Request_timeout; case 409: return sip_409_Conflict; case 410: return sip_410_Gone; case 411: return sip_411_Length_required; case 412: return sip_412_Precondition_failed; case 413: return sip_413_Request_too_large; case 414: return sip_414_Request_uri_too_long; case 415: return sip_415_Unsupported_media; case 416: return sip_416_Unsupported_uri; case 417: return sip_417_Resource_priority; case 420: return sip_420_Bad_extension; case 421: return sip_421_Extension_required; case 422: return sip_422_Session_timer; case 423: return sip_423_Interval_too_brief; case 480: return sip_480_Temporarily_unavailable; case 481: return sip_481_No_transaction; case 482: return sip_482_Loop_detected; case 483: return sip_483_Too_many_hops; case 484: return sip_484_Address_incomplete; case 485: return sip_485_Ambiguous; case 486: return sip_486_Busy_here; case 487: return sip_487_Request_terminated; case 488: return sip_488_Not_acceptable; case 489: return sip_489_Bad_event; case 490: return sip_490_Request_updated; case 491: return sip_491_Request_pending; case 493: return sip_493_Undecipherable; case 494: return sip_494_Secagree_required; case 500: return sip_500_Internal_server_error; case 501: return sip_501_Not_implemented; case 502: return sip_502_Bad_gateway; case 503: return sip_503_Service_unavailable; case 504: return sip_504_Gateway_time_out; case 505: return sip_505_Version_not_supported; case 513: return sip_513_Message_too_large; case 580: return sip_580_Precondition; case 600: return sip_600_Busy_everywhere; case 603: return sip_603_Decline; case 604: return sip_604_Does_not_exist_anywhere; case 606: return sip_606_Not_acceptable; case 687: return sip_687_Dialog_terminated; } return ""; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sip_tag.c.in000066400000000000000000000045011223300710500225440ustar00rootroot00000000000000/**@IFILE sip_tag.c.in * * Template for . * * @date Created: Wed Feb 21 11:01:45 2001 ppessi */ /* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE sip_tag.c SIP Tags. * * #AUTO# * * @author Pekka Pessi . * * @date Created: Fri Feb 23 12:46:42 2001 ppessi */ #include "config.h" #include #include #include #include #define TAG_NAMESPACE "sip" #include "sofia-sip/sip_parser.h" #include #include #include #include #include tag_typedef_t siptag_any = NSTAG_TYPEDEF(*); tag_typedef_t siptag_sip = SIPMSGTAG_TYPEDEF(sip); tag_typedef_t siptag_header = {{ "sip", "header", siphdrtag_class, 0 }}; tag_typedef_t siptag_header_str = STRTAG_TYPEDEF(header_str); tag_typedef_t siptag_end = TAG_TYPEDEF(tag_end, end); extern msg_hclass_t sip_#xxxxxx#_class[]; /**@ingroup sip_#xxxxxx# * Tag for @ref sip_#xxxxxx# "#xxxxxxx_xxxxxxx#" object. */ tag_typedef_t siptag_#xxxxxx# = SIPHDRTAG_TYPEDEF(#xxxxxx#); /**@ingroup sip_#xxxxxx# * Tag for string with @ref sip_#xxxxxx# "#xxxxxxx_xxxxxxx#" value. */ tag_typedef_t siptag_#xxxxxx#_str = SIPSTRTAG_TYPEDEF(#xxxxxx#); /** List of all tags for SIP headers */ tag_type_t sip_tag_list[] = { siptag_#xxxxxx#, NULL }; /** List of all string tags for SIP headers */ tag_type_t sip_tag_str_list[] = { siptag_#xxxxxx#_str, NULL }; sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sip_tag_class.c000066400000000000000000000306041223300710500233270ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@SIP_TAG * * @CFILE sip_tag_class.c SIP Tag classes * * @author Pekka Pessi . * * @date Created: Fri Feb 23 12:46:42 2001 ppessi */ #include "config.h" #include "sofia-sip/sip_parser.h" #include #include #include #include #include #include #include #include #include #include #include #include /** Tag class for tags containing SIP headers. @HIDE * * Tags in this class are not automatically added to the message with * sip_add_tl() or sip_add_tagis(). */ tag_class_t sipexthdrtag_class[1] = {{ sizeof(siphdrtag_class), /* tc_next */ NULL, /* tc_len */ NULL, /* tc_move */ NULL, /* tc_xtra */ msghdrtag_xtra, /* tc_dup */ msghdrtag_dup, /* tc_free */ NULL, /* tc_find */ NULL, /* tc_snprintf */ msghdrtag_snprintf, /* tc_filter */ siptag_filter, /* tc_ref_set */ t_ptr_ref_set, /* tc_scan */ msghdrtag_scan, }}; /** Tag class for SIP header tags. @HIDE */ tag_class_t siphdrtag_class[1] = {{ sizeof(siphdrtag_class), /* tc_next */ NULL, /* tc_len */ NULL, /* tc_move */ NULL, /* tc_xtra */ msghdrtag_xtra, /* tc_dup */ msghdrtag_dup, /* tc_free */ NULL, /* tc_find */ NULL, /* tc_snprintf */ msghdrtag_snprintf, /* tc_filter */ siptag_filter, /* tc_ref_set */ t_ptr_ref_set, /* tc_scan */ msghdrtag_scan, }}; /** Tag class for SIP header string tags. @HIDE */ tag_class_t sipstrtag_class[1] = {{ sizeof(sipstrtag_class), /* tc_next */ NULL, /* tc_len */ NULL, /* tc_move */ NULL, /* tc_xtra */ t_str_xtra, /* tc_dup */ t_str_dup, /* tc_free */ NULL, /* tc_find */ NULL, /* tc_snprintf */ t_str_snprintf, /* tc_filter */ NULL /* msgtag_str_filter */, /* tc_ref_set */ t_ptr_ref_set, /* tc_scan */ t_str_scan }}; /** Tag class for SIP message tags. @HIDE */ tag_class_t sipmsgtag_class[1] = {{ sizeof(sipmsgtag_class), /* tc_next */ NULL, /* tc_len */ NULL, /* tc_move */ NULL, /* tc_xtra */ msgobjtag_xtra, /* tc_dup */ msgobjtag_dup, /* tc_free */ NULL, /* tc_find */ NULL, /* tc_snprintf */ msgobjtag_snprintf, /* tc_filter */ NULL /* siptag_sip_filter */, /* tc_ref_set */ t_ptr_ref_set, }}; /** Filter a for SIP header tag. * * @param[in] dst tag list for filtering result. May be NULL. * @param[in] f filter tag * @param[in] src tag item from source list. * @param[in,out] bb pointer to pointer of mempory area used to dup * the filtering result * * This function is also used to calculate size for filtering result. */ tagi_t *siptag_filter(tagi_t *dst, tagi_t const f[], tagi_t const *src, void **bb) { tagi_t stub[2] = {{ NULL }}; tag_type_t srctt, tt = f->t_tag; msg_hclass_t *hc = (msg_hclass_t *)tt->tt_magic; assert(src); srctt = src->t_tag; /* Match filtered header with a header from a SIP message */ if (srctt && srctt->tt_class == sipmsgtag_class) { sip_t const *sip = (sip_t const *)src->t_value; sip_header_t const **hh, *h; if (sip == NULL) return dst; hh = (sip_header_t const **) msg_hclass_offset((msg_mclass_t *)sip->sip_common->h_class, (msg_pub_t *)sip, hc); /* Is header present in the SIP message? */ if (hh == NULL || (char *)hh >= ((char *)sip + sip->sip_size) || (char *)hh < (char *)&sip->sip_request) return dst; h = *hh; if (h == NULL) return dst; stub[0].t_tag = tt; stub[0].t_value = (tag_value_t)h; src = stub; srctt = tt; } if (tt != srctt) return dst; if (!src->t_value) return dst; else if (dst) { return t_dup(dst, src, bb); } else { *bb = (char *)*bb + t_xtra(src, (size_t)*bb); return dst + 1; } } /** Duplicate headers from taglist and add them to the SIP message. */ int sip_add_tl(msg_t *msg, sip_t *sip, tag_type_t tag, tag_value_t value, ...) { tagi_t const *t; ta_list ta; int retval; ta_start(ta, tag, value); t = ta_args(ta); retval = sip_add_tagis(msg, sip, &t); ta_end(ta); return retval; } /** Add duplicates of headers from taglist to the SIP message. */ int sip_add_tagis(msg_t *msg, sip_t *sip, tagi_t const **inout_list) { tagi_t const *t; tag_type_t tag; tag_value_t value; if (!msg || !inout_list) return -1; if (sip == NULL) sip = sip_object(msg); for (t = *inout_list; t; t = t_next(t)) { tag = t->t_tag, value = t->t_value; if (tag == NULL || tag == siptag_end) { t = t_next(t); break; } if (!value) continue; if (SIPTAG_P(tag)) { msg_hclass_t *hc = (msg_hclass_t *)tag->tt_magic; msg_header_t *h = (msg_header_t *)value, **hh; if (h == SIP_NONE) { /* Remove header */ hh = msg_hclass_offset(msg_mclass(msg), (msg_pub_t *)sip, hc); if (hh != NULL && (char *)hh < ((char *)sip + sip->sip_size) && (char *)hh >= (char *)&sip->sip_request) { while (*hh) msg_header_remove(msg, (msg_pub_t *)sip, *hh); } continue; } if (tag == siptag_header) hc = h->sh_class; if (msg_header_add_dup_as(msg, (msg_pub_t *)sip, hc, h) < 0) break; } else if (SIPTAG_STR_P(tag)) { msg_hclass_t *hc = (msg_hclass_t *)tag->tt_magic; char const *s = (char const *)value; if (s && msg_header_add_make(msg, (msg_pub_t *)sip, hc, s) < 0) return -1; } else if (tag == siptag_header_str) { if (msg_header_add_str(msg, (msg_pub_t *)sip, (char const *)value) < 0) return -1; } } *inout_list = t; return 0; } static char const *append_escaped(su_strlst_t *l, msg_hclass_t *hc, char const *s); /** Convert tagged SIP headers to a URL-encoded headers list. * * The SIP URI can contain a query part separated with the "?", which * specifies SIP headers that are included in the request constructed * from the URI. For example, using URI @code * would include @Subject header with value "test" in the request. * * @param home memory home used to allocate query string (if NULL, use malloc) * @param tag, value, ... list of tagged arguments * * @bug This function returns NULL if SIPTAG_REQUEST(), SIPTAG_STATUS(), * SIPTAG_HEADER(), SIPTAG_UNKNOWN(), SIPTAG_ERROR(), SIPTAG_SEPARATOR(), or * any corresponding string tag is included in the tag list. It ignores * SIPTAG_SIP(). * * @par Example * @code * url->url_headers = * sip_headers_as_url_query(home, SIPTAG_REPLACES(replaces), TAG_END()); * @endcode * * @since New in @VERSION_1_12_4. * * @sa * url_query_as_header_string(), sip_url_query_as_taglist(), * nta_msg_request_complete(), * @RFC3261 section 19.1.1 "Headers", #url_t, url_s#url_headers */ char *sip_headers_as_url_query(su_home_t *home, tag_type_t tag, tag_value_t value, ...) { ta_list ta; tagi_t const *t; su_strlst_t *l = su_strlst_create(home); su_home_t *lhome = su_strlst_home(l); char const *retval = ""; if (!l) return NULL; ta_start(ta, tag, value); for (t = ta_args(ta); t && retval; t = t_next(t)) { msg_hclass_t *hc; if (t->t_value == 0 || t->t_value == -1) continue; hc = (msg_hclass_t *)t->t_tag->tt_magic; if (SIPTAG_P(t->t_tag)) { sip_header_t const *h = (sip_header_t const *)t->t_value; char *s = sip_header_as_string(lhome, h); retval = append_escaped(l, hc, s); if (retval != s) su_free(lhome, s); } else if (SIPTAG_STR_P(t->t_tag)) { retval = append_escaped(l, hc, (char const *)t->t_value); } } ta_end(ta); if (retval) retval = su_strlst_join(l, home, ""); su_strlst_destroy(l); return (char *)retval; } /* "[" / "]" / "/" / "?" / ":" / "+" / "$" */ #define HNV_UNRESERVED "[]/?+$" #define HNV_RESERVED ":=,;" /* Append a string to list and url-escape it if needed */ static char const *append_escaped(su_strlst_t *l, msg_hclass_t *hc, char const *s) { char const *name; if (hc == NULL) return NULL; if (hc->hc_hash == sip_payload_hash) name = "body"; else /* XXX - could we use short form? */ name = hc->hc_name; if (name == NULL) return NULL; if (s) { su_home_t *lhome = su_strlst_home(l); size_t slen; isize_t elen; char *n, *escaped; char *sep = su_strlst_len(l) > 0 ? "&" : ""; n = su_sprintf(lhome, "%s%s=", sep, name); if (!su_strlst_append(l, n)) return NULL; for (;*n; n++) if (isupper(*n)) *n = tolower(*n); slen = strlen(s); elen = url_esclen(s, HNV_RESERVED); if ((size_t)elen == slen) return su_strlst_append(l, s); escaped = su_alloc(lhome, elen + 1); if (escaped) return su_strlst_append(l, url_escape(escaped, s, HNV_RESERVED)); } return NULL; } /** Convert URL query to a tag list. * * SIP headers encoded as URL @a query is parsed returned as a tag list. * Unknown headers are encoded as SIPTAG_HEADER_STR(). * * @param home memory home used to alloate string (if NULL, malloc() it) * @param query query part from SIP URL * @param parser optional SIP parser used * * @sa sip_add_tl(), sip_add_tagis(), SIPTAG_HEADER_STR(), * sip_headers_as_url_query(), url_query_as_header_string(), * @RFC3261 section 19.1.1 "Headers", #url_t, url_s#url_headers * * @NEW_1_12_4. * * @bug Extension headers are ignored. The @a parser parameter is not used * at the moment. */ tagi_t *sip_url_query_as_taglist(su_home_t *home, char const *query, msg_mclass_t const *parser) { tagi_t *retval = NULL; char *s; su_strlst_t *l; isize_t N; size_t i, j, n; if (query == NULL || query[0] == '\0' || query[0] == '&') return NULL; s = su_strdup(home, query); if (!s) return NULL; l = su_strlst_split(home, s, "&"); N = su_strlst_len(l); if (N == 0) goto error; retval = su_zalloc(home, (N + 1) * sizeof (*retval)); if (retval == NULL) goto error; for (i = 0; i < N; i++) { char const *hnv; char *value; tag_type_t t; tag_value_t v; msg_hclass_t *hc = NULL; hnv = su_strlst_item(l, i); n = hnv ? strcspn(hnv, "=") : 0; if (n == 0) break; if (n == 4 && su_casenmatch(hnv, "body", 4)) t = siptag_payload, hc = sip_payload_class; else { for (j = 0; (t = sip_tag_list[j]); j++) { hc = (msg_hclass_t *)sip_tag_list[j]->tt_magic; if (n == 1 && su_casenmatch(hnv, hc->hc_short, 1)) break; else if (n == (size_t)hc->hc_len && su_casenmatch(hnv, hc->hc_name, n)) break; } } value = (char *)hnv + n; *value++ = ':'; n = url_unescape_to(value, value, SIZE_MAX); value[n] = '\0'; if (t) { msg_header_t *h = msg_header_make(home, hc, value); if (!h) break; v = (tag_value_t)h; } else { char *s; s = su_alloc(home, n + 1); if (!s) break; memcpy(s, value, n + 1); t = siptag_header_str; v = (tag_value_t)s; } retval[i].t_tag = t, retval[i].t_value = v; } retval[i].t_tag = NULL, retval[i].t_value = (tag_value_t)0; if (i < N) { for (j = 0; j < i; j++) { if (retval[i].t_tag == siptag_header_str) su_free(home, (void *)retval[i].t_value); else msg_header_free_all(home, (msg_header_t *)retval[i].t_value); } su_free(home, retval); retval = NULL; } error: su_free(home, s); su_strlst_destroy(l); return retval; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sip_time.c000066400000000000000000000051561223300710500223310ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE sip_time.c * @brief SIP time handling * * Functions for handling time and dates in SIP. * * @author Pekka Pessi . * * @date Created: Wed Apr 11 18:57:06 2001 ppessi */ #include "config.h" #include #include #include #include #include #include "sofia-sip/sip_parser.h" #include #include #include /** Return current time as seconds since Epoch. */ sip_time_t sip_now(void) { return su_now().tv_sec; } /**@ingroup sip_expires * * Calculate the expiration time for a SIP @Contact. * * @param m @Contact header * @param ex @Expires header * @param date @Date header * @param def default expiration time * @param now current time. * * @note If @a m is NULL, the function calculates the expiration time * based on the @Expires and @Date headers. * * @note If @a now is 0, the function gets the current time using sip_now(). * * @return * The expiration time in seconds. */ sip_time_t sip_contact_expires(sip_contact_t const *m, sip_expires_t const *ex, sip_date_t const *date, sip_time_t def, sip_time_t now) { sip_time_t time = 0, delta = def; /* "Contact: *" */ if (m && m->m_url->url_type == url_any) return 0; if (m && m->m_expires) { msg_param_t expires = m->m_expires; if (msg_date_delta_d(&expires, &time, &delta) < 0) return def; } else if (ex) { time = ex->ex_date; delta = ex->ex_delta; } if (time) { if (date) now = date->d_time; else if (now == 0) now = sip_now(); if (time > now) delta = time - now; else delta = 0; } return delta; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sip_util.c000066400000000000000000001216261223300710500223510ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@CFILE sip_util.c * * SIP utility functions. * * @author Pekka Pessi . * * @date Created: Tue Jun 13 02:57:51 2000 ppessi */ #include "config.h" /* Avoid casting sip_t to msg_pub_t and sip_header_t to msg_header_t */ #define MSG_PUB_T struct sip_s #define MSG_HDR_T union sip_header_u #include #include #include #include "sofia-sip/sip_parser.h" #include #include #include #include #include #include #include #include #include #include #include #include #include /**Compare two SIP addresses ( @From or @To headers). * * @retval nonzero if matching. * @retval zero if not matching. */ int sip_addr_match(sip_addr_t const *a, sip_addr_t const *b) { return (a->a_tag == NULL || b->a_tag == NULL || su_casematch(a->a_tag, b->a_tag)) && su_casematch(a->a_host, b->a_host) && su_strmatch(a->a_user, b->a_user) && su_strmatch(a->a_url->url_scheme, b->a_url->url_scheme); } /**@ingroup sip_contact * * Create a contact header. * * Create a @Contact header object with the given URL and list of parameters. * * @param home memory home * @param url URL (string or pointer to url_t) * @param p,... NULL-terminated list of @Contact parameters * * @return * A pointer to newly created @Contact header object when successful or NULL * upon an error. * */ sip_contact_t * sip_contact_create(su_home_t *home, url_string_t const *url, char const *p, ...) { su_strlst_t *l; su_home_t *lhome; sip_contact_t *m; if (url == NULL) return NULL; l = su_strlst_create_with(NULL, "<", NULL), lhome = su_strlst_home(l); if (l == NULL) return NULL; if (url_is_string(url)) su_strlst_append(l, (char const *)url); else su_strlst_append(l, url_as_string(lhome, url->us_url)); su_strlst_append(l, ">"); if (p) { va_list ap; va_start(ap, p); for (; p; p = va_arg(ap, char const *)) { su_strlst_append(l, ";"); su_strlst_append(l, p); } va_end(ap); } m = sip_contact_make(home, su_strlst_join(l, lhome, "")); su_strlst_destroy(l); return m; } /** Convert a @Via header to @Contact header. * * The @Contact URI will contain the port number if needed. If transport * protocol name starts with "TLS", "SIPS:" URI schema is used. Transport * parameter is included in the URI unless the transport protocol is UDP. * * @param home memory home * @param v @Via header field structure * (with and parameters) * @param user username for @Contact URI (may be NULL) * * @retval contact header structure * @retval NULL upon an error * * @sa sip_contact_create_from_via_with_transport(), * sip_contact_string_from_via() */ sip_contact_t * sip_contact_create_from_via(su_home_t *home, sip_via_t const *v, char const *user) { const char *tp; if (!v) return NULL; tp = v->v_protocol; if (tp == sip_transport_udp || su_casematch(tp, sip_transport_udp)) /* Default is UDP */ tp = NULL; return sip_contact_create_from_via_with_transport(home, v, user, tp); } /** Convert a @Via header to @Contact header. * * The @Contact URI will contain the port number and transport parameters if * needed. If transport protocol name starts with "TLS", "SIPS:" URI schema * is used. * * @param home memory home * @param v @Via header field structure * (with parameter containing host and port) * @param user username for @Contact URI (may be NULL) * @param transport transport name for @Contact URI (may be NULL) * * @retval contact header structure * @retval NULL upon an error * * @sa sip_contact_create_from_via(), sip_contact_string_from_via() */ sip_contact_t * sip_contact_create_from_via_with_transport(su_home_t *home, sip_via_t const *v, char const *user, char const *transport) { char *s = sip_contact_string_from_via(NULL, v, user, transport); sip_contact_t *m = sip_contact_make(home, s); su_free(NULL, s); return m; } /** Convert a @Via header to @Contact URL string. * * The @Contact URI will contain the port number and transport parameters if * needed. If transport protocol name starts with "TLS", "SIPS:" URI schema * is used. * * The contact URI string returned will always have angle brackets ("<" and * ">") around it. * * @param home memory home * @param v @Via header field structure * (with parameter containing host and port) * @param user username for @Contact URI (may be NULL) * @param transport transport name for @Contact URI (may be NULL) * * @retval string containing Contact URI with angle brackets * @retval NULL upon an error */ char * sip_contact_string_from_via(su_home_t *home, sip_via_t const *v, char const *user, char const *transport) { const char *host, *port, *maddr, *comp; char const *scheme = "sip:"; int one = 1; char _transport[16]; if (!v) return NULL; host = v->v_host; if (v->v_received) host = v->v_received; port = sip_via_port(v, &one); maddr = v->v_maddr; comp = v->v_comp; if (host == NULL) return NULL; if (sip_transport_has_tls(v->v_protocol) || sip_transport_has_tls(transport)) { scheme = "sips:"; if (port && strcmp(port, SIPS_DEFAULT_SERV) == 0) port = NULL; if (port || host_is_ip_address(host)) transport = NULL; } else if (port && strcmp(port, SIP_DEFAULT_SERV) == 0 && (host_is_ip_address(host) || host_has_domain_invalid(host))) { port = NULL; } if (su_casenmatch(transport, "SIP/2.0/", 8)) transport += 8; /* Make transport parameter lowercase */ if (transport && strlen(transport) < (sizeof _transport)) { char *s = strcpy(_transport, transport); short c; for (; (c = *s) && c != ';'; s++) if (isupper(c)) *s = tolower(c); transport = _transport; } return su_strcat_all(home, "<", scheme, user ? user : "", user ? "@" : "", host, SIP_STRLOG(":", port), SIP_STRLOG(";transport=", transport), SIP_STRLOG(";maddr=", maddr), SIP_STRLOG(";comp=", comp), ">", NULL); } /** Check if tranport name refers to TLS */ int sip_transport_has_tls(char const *transport_name) { if (!transport_name) return 0; if (transport_name == sip_transport_tls) return 1; /* transport name starts with TLS or SIP/2.0/TLS */ return su_casenmatch(transport_name, "TLS", 3) || su_casenmatch(transport_name, sip_transport_tls, 11); } /**Perform sanity check on a SIP message * * Check that the SIP message has all the mandatory fields. * * @param sip SIP message to be checked * * @return * When the SIP message fulfills the minimum requirements, return zero, * otherwise a negative status code. */ int sip_sanity_check(sip_t const *sip) { if (!sip || !((sip->sip_request != NULL) ^ (sip->sip_status != NULL)) || !sip->sip_to || !sip->sip_from || !sip->sip_call_id || !sip->sip_cseq || !sip->sip_via || (sip->sip_flags & MSG_FLG_TRUNC)) return -1; /* Bad request */ if (sip->sip_request) { url_t const *ruri = sip->sip_request->rq_url; switch (ruri->url_type) { case url_invalid: return -1; case url_sip: case url_sips: case url_im: case url_pres: if (!ruri->url_host || strlen(ruri->url_host) == 0) return -1; break; case url_tel: if (!ruri->url_user || strlen(ruri->url_user) == 0) return -1; break; } if (sip->sip_request->rq_method != sip->sip_cseq->cs_method) return -1; if (sip->sip_request->rq_method == sip_method_unknown && !su_strmatch(sip->sip_request->rq_method_name, sip->sip_cseq->cs_method_name)) return -1; } return 0; } /** Decode a string containg header field. * * The header object is initialized with the contents of the string. The * string is modified when parsing. The home is used to allocate extra * memory required when parsing, e.g., for parameter list or when there * string contains multiple header fields. * * @deprecated * Use msg_header_make() or header-specific make functions, e.g., * sip_via_make(). * * @retval 0 when successful * @retval -1 upon an error. */ issize_t sip_header_field_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { if (h && s && s[slen] == '\0') { size_t n = span_lws(s); s += n; slen -= n; for (n = slen; n >= 1 && IS_LWS(s[n - 1]); n--) ; s[n] = '\0'; assert(SIP_HDR_TEST(h)); return h->sh_class->hc_parse(home, h, s, slen); } else return -1; } /** Encode a SIP header contents. * * @deprecated Use msg_header_field_e() instead. */ issize_t sip_header_field_e(char *b, isize_t bsiz, sip_header_t const *h, int flags) { return msg_header_field_e(b, bsiz, h, flags); } /** Convert the header @a h to a string allocated from @a home. */ char *sip_header_as_string(su_home_t *home, sip_header_t const *h) { ssize_t len; char *rv, s[128]; if (h == NULL) return NULL; len = sip_header_field_e(s, sizeof(s), h, 0); if (len >= 0 && (size_t)len < sizeof(s)) return su_strdup(home, s); if (len == -1) len = 2 * sizeof(s); else len += 1; for (rv = su_alloc(home, len); rv; rv = su_realloc(home, rv, len)) { ssize_t n = sip_header_field_e(rv, len, h, 0); if (n > -1 && n + 1 <= len) break; if (n > -1) /* glibc >2.1 */ len = n + 1; else /* glibc 2.0 */ len *= 2; } return rv; } /** Calculate size of a SIP header. */ isize_t sip_header_size(sip_header_t const *h) { assert(h == NULL || h == SIP_NONE || h->sh_class); if (h == NULL || h == SIP_NONE) return 0; else return h->sh_class->hc_dxtra(h, h->sh_class->hc_size); } /** Duplicate a url or make a url out of string. * @deprecated Use url_hdup() instead. */ url_t *sip_url_dup(su_home_t *home, url_t const *o) { return url_hdup(home, o); } /**Calculate Q value. * * Convert q-value string @a q to numeric value * in range (0..1000). Q values are used, for instance, to describe * relative priorities of registered contacts. * * @param q q-value string ("1" | "." 1,3DIGIT) * * @return An integer in range 0 .. 1000. * * @deprecated Use msg_q_value() instead. */ unsigned sip_q_value(char const *q) { return msg_q_value(q); } /**@ingroup sip_route * * Get first route header and remove it from its fragment chain. * */ sip_route_t *sip_route_remove(msg_t *msg, sip_t *sip) { sip_route_t *r; if ((r = sip->sip_route)) msg_header_remove(msg, (msg_pub_t *)sip, (msg_header_t *)r); return r; } /**@ingroup sip_route * * Get last route header and remove it from its fragment chain. * */ sip_route_t *sip_route_pop(msg_t *msg, sip_t *sip) { sip_route_t *r; for (r = sip->sip_route; r; r = r->r_next) if (r->r_next == NULL) { msg_header_remove(msg, (msg_pub_t *)sip, (msg_header_t *)r); return r; } return NULL; } /**@ingroup sip_route * * Get first route header and rewrite the RequestURI. */ sip_route_t *sip_route_follow(msg_t *msg, sip_t *sip) { if (sip->sip_route) { /* XXX - in case of outbound proxy, route may contain our address */ sip_route_t *r = sip_route_remove(msg, sip); sip_request_t *rq = sip->sip_request; rq = sip_request_create(msg_home(msg), rq->rq_method, rq->rq_method_name, (url_string_t const *)r->r_url, rq->rq_version); url_strip_transport(rq->rq_url); msg_header_insert(msg, (msg_pub_t *)sip, (msg_header_t *)rq); return r; } return NULL; } /**@ingroup sip_route * * Check if route header has lr param. * * "lr" param can be either URL or header parameter. */ int sip_route_is_loose(sip_route_t const *r) { if (!r) return 0; if (r->r_url->url_params) return url_has_param(r->r_url, "lr"); else return r->r_params && msg_params_find(r->r_params, "lr") != NULL; } /**@ingroup sip_route * * Reverse a route header (@Route, @RecordRoute, @Path, @ServiceRoute). */ sip_route_t *sip_route_reverse_as(su_home_t *home, msg_hclass_t *hc, sip_route_t const *route) { sip_route_t *reverse = NULL; sip_route_t r[1], *tmp; sip_route_init(r); r->r_common->h_class = hc; for (reverse = NULL; route; route = route->r_next) { *r->r_url = *route->r_url; /* Fix broken (Record-)Routes without <> */ if (r->r_url->url_params == NULL && r->r_params && r->r_params[0] && (r->r_params[0][0] == 'l' || r->r_params[0][0] == 'L') && (r->r_params[0][1] == 'r' || r->r_params[0][1] == 'R') && (r->r_params[0][2] == '=' || r->r_params[0][2] == 0)) r->r_url->url_params = route->r_params[0], r->r_params = route->r_params + 1; else r->r_params = route->r_params; tmp = (sip_route_t *)msg_header_dup_as(home, hc, (msg_header_t *)r); if (!tmp) goto error; tmp->r_next = reverse; reverse = tmp; } return reverse; error: msg_header_free_all(home, (msg_header_t *)reverse); return NULL; } /**@ingroup sip_route * * Reverse a @Route header. * * Reverse A route header like @RecordRoute or @Path. */ sip_route_t *sip_route_reverse(su_home_t *home, sip_route_t const *route) { return sip_route_reverse_as(home, sip_route_class, route); } /**@ingroup sip_route * * Fix and duplicate a route header (@Route, @RecordRoute, @Path, @ServiceRoute). * */ sip_route_t *sip_route_fixdup_as(su_home_t *home, msg_hclass_t *hc, sip_route_t const *route) { sip_route_t *copy = NULL; sip_route_t r[1], **rr; sip_route_init(r); /* Copy the record route as route */ for (rr = © route; route = route->r_next) { *r->r_url = *route->r_url; /* Fix broken (Record-)Routes without <> */ if (r->r_url->url_params == NULL && r->r_params && r->r_params[0] && (r->r_params[0][0] == 'l' || r->r_params[0][0] == 'L') && (r->r_params[0][1] == 'r' || r->r_params[0][1] == 'R') && (r->r_params[0][2] == '=' || r->r_params[0][2] == 0)) r->r_url->url_params = route->r_params[0], r->r_params = route->r_params + 1; else r->r_params = route->r_params; *rr = (sip_route_t *)msg_header_dup_as(home, hc, (msg_header_t *)r); if (!*rr) goto error; rr = &(*rr)->r_next; } return copy; error: msg_header_free_all(home, (msg_header_t *)copy); return NULL; } /**@ingroup sip_route * * Fix and duplicate a @Route header. * * Copy a route header like @RecordRoute or @Path as @Route. * */ sip_route_t *sip_route_fixdup(su_home_t *home, sip_route_t const *route) { return sip_route_fixdup_as(home, sip_route_class, route); } /**@ingroup sip_route * * Fix @Route header. * * If URI has no parameters and the header contains a single @c ;lr header * parameter, the "lr" is moved as URI parameter. */ sip_route_t *sip_route_fix(sip_route_t *route) { sip_route_t *r; sip_header_t *h = NULL; size_t i; for (r = route; r; r = r->r_next) { /* Keep track of first header structure on this header line */ if (!h || (char *)h->sh_data + h->sh_len != r->r_common->h_data || r->r_common->h_len) h = (sip_header_t *)r; if (r->r_url->url_params == NULL && r->r_params && r->r_params[0] && (r->r_params[0][0] == 'l' || r->r_params[0][0] == 'L') && (r->r_params[0][1] == 'r' || r->r_params[0][1] == 'R') && (r->r_params[0][2] == '=' || r->r_params[0][2] == 0)) { r->r_url->url_params = r->r_params[0]; for (i = 0; r->r_params[i]; i++) ((char const **)r->r_params)[i] = r->r_params[i + 1]; msg_fragment_clear_chain((msg_header_t *)h); } } return route; } /**@ingroup sip_via * * Get first via header and remove it from its fragment chain. */ sip_via_t *sip_via_remove(msg_t *msg, sip_t *sip) { sip_via_t *v; if (sip == NULL) return NULL; v = sip->sip_via; if (v) msg_header_remove(msg, (msg_pub_t *)sip, (msg_header_t *)v); return v; } /** Serialize payload. * * The sip_payload_serialize() adds missing headers to MIME multiparty payload, * encodes them and orders them in header chain. It also calculates the total * length of the payload. */ unsigned long sip_payload_serialize(msg_t *msg, sip_payload_t *pl) { unsigned long total; for (total = 0; pl; pl = (sip_payload_t *)pl->pl_next) { total += (unsigned)pl->pl_common->h_len; } return total; } /** * Remove extra parameters from an AOR URL. * * The extra parameters listed in the @RFC3261 table 1 include port number, * method, maddr, ttl, transport, lr and headers. * * @note The funtion modifies the @a url and the strings attached to it. * * @retval 0 when successful * @retval -1 upon an error */ int sip_aor_strip(url_t *url) { if (url == NULL) return -1; url->url_port = NULL; url->url_headers = NULL; if (url->url_params) url_strip_transport(url); if (url->url_params) url->url_params = url_strip_param_string((char *)url->url_params, "lr"); return 0; } /** Compare @SecurityVerify header with @SecurityServer header. */ int sip_security_verify_compare(sip_security_server_t const *s, sip_security_verify_t const *v, msg_param_t *return_d_ver) { size_t i, j; int retval, digest; msg_param_t const *s_params, *v_params, empty[] = { NULL }; if (return_d_ver) *return_d_ver = NULL; if (s == NULL) return 0; for (;;s = s->sa_next, v = v->sa_next) { if (s == NULL || v == NULL) return (s == NULL) - (v == NULL); if ((retval = su_strcmp(s->sa_mec, v->sa_mec))) return retval; digest = su_casematch(s->sa_mec, "Digest"); s_params = s->sa_params, v_params = v->sa_params; if (digest && s_params == NULL && v_params != NULL) s_params = empty; if (s_params == NULL || v_params == NULL) { if ((retval = (s_params == NULL) - (v_params == NULL))) return retval; continue; } for (i = 0, j = 0;; i++, j++) { if (digest && v_params[j] && su_casenmatch(v_params[j], "d-ver=", 6)) { if (return_d_ver) *return_d_ver = v_params[j] + strlen("d-ver="); j++; } retval = su_strcmp(s_params[i], v_params[j]); if (retval || s_params[i] == NULL || v_params[j] == NULL) break; } if (retval) return retval; } } /** Select best mechanism from @SecurityClient header. * * @note We assume that @SecurityServer header in @a s is sorted by * preference. */ sip_security_client_t const * sip_security_client_select(sip_security_client_t const *client, sip_security_server_t const *server) { sip_security_server_t const *c, *s; if (server == NULL || client == NULL) return NULL; for (s = server; s; s = s->sa_next) { for (c = client; c; c = c->sa_next) { if (su_strmatch(s->sa_mec, c->sa_mec)) return c; } } return NULL; } /**Checks if the response with given response code terminates dialog or * dialog usage. * * @return -1 if the response with given code terminates whole dialog. * @return 1 if the response terminates the dialog usage. * @return 0 if the response does not terminate dialog or dialog usage. * * @return * The @a *return_graceful_terminate_usage is set to 1, if application * should gracefully terminate its dialog usage. It is set to 0, if no * graceful terminate is required. If it is up to application policy to * decide whether to gracefully terminate or not, the * @a *return_graceful_terminate_usage is left unmodified. * * @RFC5057 */ int sip_response_terminates_dialog(int response_code, sip_method_t method, int *return_graceful_terminate_usage) { enum { no_effect, terminate_usage = 1, terminate_dialog = -1 }; int dummy; if (!return_graceful_terminate_usage) return_graceful_terminate_usage = &dummy; if (response_code < 300) return *return_graceful_terminate_usage = 0; /* 3xx responses: Redirection mid-dialog is not well understood in SIP, but whatever effect it has impacts the entire dialog and all of its usages equally. In our example scenario, both the subscription and the invite usage would be redirected by this single response. */ if (response_code < 400) return *return_graceful_terminate_usage = 0; if (response_code < 500) switch (response_code) { default: case 400: /** @par 400 and unrecognized 4xx responses These responses affect only the NOTIFY transaction, not the subscription, the dialog it resides in (beyond affecting the local CSeq), or any other usage of that dialog. In general, the response is a complaint about this transaction, not the usage or dialog the transaction occurs in. */ *return_graceful_terminate_usage = 0; return 0; case 401: case 407: /** @par 401 Unauthorized and 407 Proxy Authentication Required This request, not the subscription or dialog, is being challenged. The usages and dialog are not terminated. */ *return_graceful_terminate_usage = 0; return 0; case 402: /** @par 402 Payment Required This is a reserved response code. If encountered, it should be treated as an unrecognized 4xx. */ *return_graceful_terminate_usage = 0; return 0; case 403: /** @par 403 Forbidden This response terminates the subscription, but has no effect on any other usages of the dialog. In our example scenario, the invite usage continues to exist. Similarly, if the 403 came in response to a re-INVITE, the invite usage would be terminated, but not the subscription. */ *return_graceful_terminate_usage = 0; return 0; case 404: /** @par 404 Not Found This response destroys the dialog and all usages sharing it. The Request-URI that is being 404ed is the remote target set by the @Contact provided by the peer. Getting this response means something has gone fundamentally wrong with the dialog state. */ return terminate_dialog; case 405: /** @par 405 Method Not Allowed In our example scenario, this response destroys the subscription, but not the invite usage or the dialog. It's an aberrant case for NOTIFYs to receive a 405 since they only come as a result to something that creates subscription. In general, a 405 within a given usage affects only that usage, but does not affect other usages of the dialog. */ switch (method) { case sip_method_notify: case sip_method_subscribe: case sip_method_invite: return terminate_usage; default: *return_graceful_terminate_usage = 0; return 0; } case 406: /** @par 406 Not Acceptable These responses concern details of the message in the transaction. Subsequent requests in this same usage may succeed. Neither the usage nor dialog is terminated, other usages sharing this dialog are unaffected. */ *return_graceful_terminate_usage = 0; return 0; case 408: /** @par 408 Request Timeout Receiving a 408 will have the same effect on usages and dialogs as a real transaction timeout as described in Section 3.2. */ return terminate_usage; case 410: /** @par 410 Gone This response destroys the dialog and all usages sharing it. The Request-URI that is being rejected is the remote target set by the @Contact provided by the peer. Similar to 404, getting this response means something has gone fundamentally wrong with the dialog state, its slightly less aberrant in that the other endpoint recognizes that this was once a valid URI that it isn't willing to respond to anymore. */ return terminate_dialog; case 412: /* Conditional Request Failed: */ case 413: /* Request Entity Too Large: */ case 414: /* Request-URI Too Long: */ case 415: /* Unsupported Media Type: */ /** @par 412, 413, 414 and 415 These responses concern details of the message in the transaction. Subsequent requests in this same usage may succeed. Neither the usage nor dialog is terminated, other usages sharing this dialog are unaffected. */ *return_graceful_terminate_usage = 0; return 0; case 416: /** @par 416 Unsupported URI Scheme Similar to 404 and 410, this response came to a request whose Request-URI was provided by the peer in a @Contact header field. Something has gone fundamentally wrong, and the dialog and all of its usages are destroyed. */ return terminate_dialog; case 417: /** @par 417 Uknown Resource-Priority The effect of this response on usages and dialogs is analgous to that for 420 and 488. The usage is not affected. The dialog is only affected by a change in its local @CSeq. No other usages of the dialog are affected. */ case 420: /* Bad Extension */ case 421: /* Extension Required */ /** @par 420 Bad Extension and 421 Extension Required These responses are objecting to the request, not the usage. The usage is not affected. The dialog is only affected by a change in its local @CSeq. No other usages of the dialog are affected. */ case 422: /** @par 422 Session Interval Too Small This response will not be returned to a NOTIFY in our example scenario. This response is non-sensical for any mid-usage request. If it is received, an element in the path of the request is violating protocol, and the recipient should treat this as it would an unknown 4xx response. If the response came to a request that was attempting to establish a new usage in an existing dialog, no new usage is created and existing usages are unaffected. */ case 423: /** @par 423 Interval Too Brief This response won't happen in our example scenario, but if it came in response to a re-SUBSCRIBE, the subscribe usage is not destroyed (or otherwise affected). No other usages of the dialog are affected. */ case 428: /** @par 428 Use Identity Header This response objects to the request, not the usage. The usage is not affected. The dialog is only affected by a change in its local @CSeq. No other usages of the dialog are affected. */ case 429: /** @par 429 Provide Referrer Identity This response won't be returned to a NOTIFY as in our example scenario, but when it is returned to a REFER, it is objecting to the REFER request itself, not any usage the REFER occurs within. The usage is unaffected. Any other usages sharing this dialog are unaffected. The dialog is only affected by a change in its local @CSeq. */ case 436: case 437: case 438: /** @par 436 Bad Identity-Info, 437 Unsupported Certificate, 438 Invalid \ * Identity Header * * These responses object to the request, not the usage. * The usage is not affected. The dialog is only affected by a * change in its local @CSeq. No other usages of the dialog are * affected. */ *return_graceful_terminate_usage = 0; return 0; case 480: /** @par 480 Temporarily Unavailable @RFC3261 is unclear on what this response means for mid-usage requests. Clarifications will be made to show that this response affects only the usage in which the request occurs. No other usages are affected. If the response included a @RetryAfter header field, further requests in that usage should not be sent until the indicated time has past. Requests in other usages may still be sent at any time. */ return terminate_usage; case 481: /** @par 481 Call/Transaction Does Not Exist This response indicates that the peer has lost its copy of the dialog state. The dialog and any usages sharing it are destroyed. The dialog itself should not be destroyed unless this was the last usage. The effects of a 481 on a dialog and its usages are the most ambiguous of any final response. There are implementations that have chosen the meaning recommended here, and others that destroy the entire dialog without regard to the number of outstanding usages. Going forward with this clarification will allow those deployed implementations that assumed only the usage was destroyed to work with a wider number of implementations. Those that made the other choice will continue to function as they do now, suffering at most the same extra messages needed for a peer to discover that that other usages have gone away that they currently do. However, the necessary clarification to @RFC3261 needs to make it very clear that the ability to terminate usages independently from the overall dialog using a 481 is not justification for designing new applications that count on multiple usages in a dialog. */ return terminate_usage; case 482: /** @par 482 Loop Detected This response is aberrant mid-dialog. It will only occur if the @RecordRoute header field was improperly constructed by the proxies involved in setting up the dialog's initial usage, or if a mid-dialog request forks and merges (which should never happen). Future requests using this dialog state will also fail. The dialog and any usages sharing it are destroyed. */ return terminate_dialog; case 483: /** @par 483 Too Many Hops Similar to 482, receiving this mid-dialog is aberrant. Unlike 482, recovery may be possible by increasing @MaxForwards (assuming that the requester did something strange like using a smaller value for @MaxForwards in mid-dialog requests than it used for an initial request). If the request isn't tried with an increased @MaxForwards, then the agent should attempt to gracefully terminate this usage and all other usages that share its dialog. */ *return_graceful_terminate_usage = 1; return 0; case 484: /* Address Incomplete */ /** @par 484 Address Incomplete and 485 Ambiguous Similar to 404 and 410, these responses came to a request whose Request-URI was provided by the peer in a @Contact header field. Something has gone fundamentally wrong, and the dialog and all of its usages are destroyed. Asterisk (v 1.2.7.1) does response with 484 if a client does send a refer with a @ReferTo header to an unknown number. This is therefore not fundamentally wrong and the dialog should not be destroyed! */ if (method == sip_method_refer) { *return_graceful_terminate_usage = 0; return 0; } case 485: /* Ambiguous */ return terminate_dialog; case 486: /** @par 486 Busy Here This response is non-sensical in our example scenario, or in any scenario where this response comes inside an established usage. If it occurs in that context, it should be treated as an unknown 4xx response. The usage, and any other usages sharing its dialog are unaffected. The dialog is only affected by the change in its local @CSeq. If this response is to a request that is attempting to establish a new usage within an existing dialog (such as an INVITE sent within a dialog established by a subscription), the request fails, no new usage is created, and no other usages are affected. */ *return_graceful_terminate_usage = 0; return 0; case 487: /** @par 487 Request Terminated This response speaks to the disposition of a particular request (transaction). The usage in which that request occurs is not affected by this response (it may be affected by another associated request within that usage). No other usages sharing this dialog are affected. */ *return_graceful_terminate_usage = 0; return 0; case 488: /** @par 488 Not Acceptable Here This response is objecting to the request, not the usage. The usage is not affected. The dialog is only affected by a change in its local @CSeq. No other usages of the dialog are affected. */ *return_graceful_terminate_usage = 0; return 0; case 489: /** @par 489 Bad Event In our example scenario, @RFC3265 declares that the subscription usage in which the NOTIFY is sent is terminated. The invite usage is unaffected and the dialog continues to exist. This response is only valid in the context of SUBSCRIBE and NOTIFY. UAC behavior for receiving this response to other methods is not specified, but treating it as an unknown 4xx is a reasonable practice. */ *return_graceful_terminate_usage = 0; return method == sip_method_notify ? terminate_usage : no_effect; case 491: /** @par 491 Request Pending This response addresses in-dialog request glare. Its affect is scoped to the request. The usage in which the request occurs is not affected. The dialog is only affected by the change in its local @CSeq. No other usages sharing this dialog are affected. */ *return_graceful_terminate_usage = 0; return 0; case 493: /** @par 493 Undecipherable This response objects to the request, not the usage. The usage is not affected. The dialog is only affected by a change in its local @CSeq. No other usages of the dialog are affected. */ *return_graceful_terminate_usage = 0; return 0; case 494: /** @par 494 Security Agreement Required This response is objecting to the request, not the usage. The usage is not affected. The dialog is only affected by a change in its local @CSeq. No other usages of the dialog are affected. */ *return_graceful_terminate_usage = 0; return 0; } if (response_code < 600) switch (response_code) { case 500: /* 500 and 5xx unrecognized responses */ default: /** @par 500 and 5xx unrecognized responses These responses are complaints against the request (transaction), not the usage. If the response contains a @RetryAfter header field value, the server thinks the condition is temporary and the request can be retried after the indicated interval. This usage, and any other usages sharing the dialog are unaffected. If the response does not contain a @RetryAfter header field value, the UA may decide to retry after an interval of its choosing or attempt to gracefully terminate the usage. Whether or not to terminate other usages depends on the application. If the UA receives a 500 (or unrecognized 5xx) in response to an attempt to gracefully terminate this usage, it can treat this usage as terminated. If this is the last usage sharing the dialog, the dialog is also terminated. */ /* Do not change *return_graceful_terminate_usage */ return 0; case 501: /** @par 501 Not Implemented This would be a degenerate response in our example scenario since the NOTIFY is being sent as part of an established subscribe usage. In this case, the UA knows the condition is unrecoverable and should stop attempting to send NOTIFYs on this usage. (It may or may not destroy the usage. If it remembers the bad behavior, it can reject any refresh subscription). In general, this response may or may not affect the usage (a 501 to an unknown method or an INFO will not end an invite usage). It will never affect other usages sharing this usage's dialog. */ /* Do not change *return_graceful_terminate_usage */ return 0; case 502: /** @par 502 Bad Gateway This response is aberrant mid-dialog. It will only occur if the @RecordRoute header field was improperly constructed by the proxies involved in setting up the dialog's initial usage. Future requests using this dialog state will also fail. The dialog and any usages sharing it are destroyed. */ return terminate_dialog; case 503: /** @par 503 Service Unavailable As per @RFC3263, the logic handling locating SIP servers for transactions may handle 503 requests (effectively sequentially forking at the endpoint based on DNS results). If this process does not yield a better response, a 503 may be returned to the transaction user. Like a 500 response, the error is a complaint about this transaction, not the usage. Because this response occurred in the context of an established usage (hence an existing dialog), the route-set has already been formed and any opportunity to try alternate servers (as recommended in @RFC3261) has been exhausted by the @RFC3263 logic. The response should be handled as described for 500 earlier in this memo. */ /* Do not change *return_graceful_terminate_usage */ return 0; case 504: /** @par 504 Server Time-out It is not obvious under what circumstances this response would be returned to a request in an existing dialog. If it occurs it should have the same affect on the dialog and its usages as described for unknown 5xx responses. */ /* Do not change *return_graceful_terminate_usage */ return 0; case 505: /* Version Not Supported */ case 513: /* Message Too Large */ /** @par 505 Version Not Supported and 513 Message Too Large These responses are objecting to the request, not the usage. The usage is not affected. The dialog is only affected by a change in its local @CSeq. No other usages of the dialog are affected. */ *return_graceful_terminate_usage = 0; return 0; case 580: /** @par 580 Precondition Failure This response is objecting to the request, not the usage. The usage is not affected. The dialog is only affected by a change in its local @CSeq. No other usages of the dialog are affected. */ *return_graceful_terminate_usage = 0; return 0; } if (response_code < 700) switch (response_code) { case 600: /* 600 and 6xx unrecognized responses */ default: /** @par 600 and 6xx unrecognized responses Unlike 400 Bad Request, a 600 response code says something about the recipient user, not the request that was made. This end user is stating an unwillingness to communicate. If the response contains a @RetryAfter header field value, the user is indicating willingness to communicate later and the request can be retried after the indicated interval. This usage, and any other usages sharing the dialog are unaffected. If the response does not contain a @RetryAfter header field value, the UA may decide to retry after an interval of its choosing or attempt to gracefully terminate the usage. Whether or not to terminate other usages depends on the application. If the UA receives a 600 (or unrecognized 6xx) in response to an attempt to gracefully terminate this usage, it can treat this usage as terminated. If this is the last usage sharing the dialog, the dialog is also terminated. */ /* Do not change graceful_terminate */ return 0; case 603: /** @par 603 Decline This response declines the action indicated by the associated request. It can be used, for example, to decline a hold or transfer attempt. Receiving this response does NOT terminate the usage it occurs in. Other usages sharing the dialog are unaffected. */ *return_graceful_terminate_usage = 0; return 0; case 604: /** @par 604 Does Not Exist Anywhere Like 404, this response destroys the dialog and all usages sharing it. The Request-URI that is being 604ed is the remote target set by the @Contact provided by the peer. Getting this response means something has gone fundamentally wrong with the dialog state. */ return terminate_dialog; case 606: /** @par 606 Not Acceptable This response is objecting to aspects of the associated request, not the usage the request appears in. The usage is unaffected. Any other usages sharing the dialog are unaffected. The only affect on the dialog is the change in the local @CSeq. */ *return_graceful_terminate_usage = 0; return 0; } /* Do not change graceful_terminate */ return 0; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sofia-sip/000077500000000000000000000000001223300710500222375ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sofia-sip/sip.h000066400000000000000000001020711223300710500232040ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef SIP_H /** Defined when has been included. */ #define SIP_H /**@file sofia-sip/sip.h * * SIP objects. * * @author Pekka Pessi . * * @date Created : Thu Jun 8 19:28:55 2000 ppessi */ #ifndef MSG_TYPES_H #include #endif #ifndef MSG_MIME_H #include #endif SOFIA_BEGIN_DECLS /** IDs for well-known SIP methods. */ typedef enum { sip_method_invalid = -1, /**< Invalid method name */ sip_method_unknown = 0, /**< Unknown method, use @c method_name */ sip_method_invite, /**< INVITE */ sip_method_ack, /**< ACK */ sip_method_cancel, /**< CANCEL */ sip_method_bye, /**< BYE */ sip_method_options, /**< OPTIONS */ sip_method_register, /**< REGISTER */ sip_method_info, /**< INFO */ sip_method_prack, /**< PRACK */ sip_method_update, /**< UPDATE */ sip_method_message, /**< MESSAGE */ sip_method_subscribe, /**< SUBSCRIBE */ sip_method_notify, /**< NOTIFY */ sip_method_refer, /**< REFER */ sip_method_publish /**< PUBLISH */ } sip_method_t; #define SIP_METHOD(s) sip_method_unknown, #s #define SIP_METHOD_ACK sip_method_ack, "ACK" #define SIP_METHOD_CANCEL sip_method_cancel, "CANCEL" #define SIP_METHOD_BYE sip_method_bye, "BYE" #define SIP_METHOD_INVITE sip_method_invite, "INVITE" #define SIP_METHOD_OPTIONS sip_method_options, "OPTIONS" #define SIP_METHOD_REGISTER sip_method_register, "REGISTER" #define SIP_METHOD_INFO sip_method_info, "INFO" #define SIP_METHOD_PRACK sip_method_prack, "PRACK" #define SIP_METHOD_UPDATE sip_method_update, "UPDATE" #define SIP_METHOD_MESSAGE sip_method_message, "MESSAGE" #define SIP_METHOD_SUBSCRIBE sip_method_subscribe, "SUBSCRIBE" #define SIP_METHOD_NOTIFY sip_method_notify, "NOTIFY" #define SIP_METHOD_REFER sip_method_refer, "REFER" #define SIP_METHOD_PUBLISH sip_method_publish, "PUBLISH" /** Magic pointer value - never valid for SIP headers. @HI */ #define SIP_NONE ((void const *)(intptr_t)-1) /** SIP protocol identifier @HIDE */ #define SIP_PROTOCOL_TAG ((void *)(uintptr_t)0x53495020) /* 'SIP ' */ enum { /** Default port for SIP as integer */ SIP_DEFAULT_PORT = 5060, #define SIP_DEFAULT_PORT SIP_DEFAULT_PORT /** Default port for SIP as string */ #define SIP_DEFAULT_SERV "5060" /** Default port for SIPS as integer */ SIPS_DEFAULT_PORT = 5061 #define SIPS_DEFAULT_PORT SIPS_DEFAULT_PORT /** Default port for SIPS as string */ #define SIPS_DEFAULT_SERV "5061" }; /** Time in seconds since Jan 01 1900. */ typedef msg_time_t sip_time_t; /** Latest time that can be expressed with #sip_time_t. @HIDE */ #define SIP_TIME_MAX ((sip_time_t)MSG_TIME_MAX) /** Structure for accessing parsed SIP headers. */ typedef struct sip_s sip_t; /** Any SIP header - union of all possible SIP headers. */ typedef union sip_header_u sip_header_t; /** Type of a generic SIP header. */ typedef struct msg_generic_s sip_generic_t; #define g_value g_string /** Common part of all the header structures. */ typedef msg_common_t sip_common_t; /** SIP parameter string. */ typedef msg_param_t sip_param_t; /** @To or @From header. */ typedef struct sip_addr_s sip_addr_t; /** @Authorization, @ProxyAuthenticate, @WWWAuthenticate */ typedef msg_auth_t sip_auth_t; typedef struct sip_request_s sip_request_t; typedef struct sip_status_s sip_status_t; typedef msg_error_t sip_error_t; typedef msg_unknown_t sip_unknown_t; typedef msg_separator_t sip_separator_t; typedef msg_payload_t sip_payload_t; typedef struct sip_accept_s sip_accept_t; typedef msg_accept_any_t sip_accept_encoding_t; typedef msg_accept_any_t sip_accept_language_t; typedef struct sip_allow_s sip_allow_t; typedef struct msg_auth_info_s sip_authentication_info_t; typedef struct msg_auth_s sip_authorization_t; typedef struct sip_call_id_s sip_call_id_t; typedef struct sip_call_info_s sip_call_info_t; typedef struct sip_contact_s sip_contact_t; typedef struct sip_cseq_s sip_cseq_t; typedef struct msg_generic_s sip_etag_t; typedef struct msg_generic_s sip_if_match_t; typedef msg_content_disposition_t sip_content_disposition_t; typedef msg_list_t sip_content_encoding_t; typedef msg_list_t sip_content_language_t; typedef struct sip_content_length_s sip_content_length_t; typedef struct msg_content_type_s sip_content_type_t; typedef struct msg_generic_s sip_mime_version_t; typedef struct sip_date_s sip_date_t; typedef struct sip_error_info_s sip_error_info_t; typedef struct sip_expires_s sip_expires_t; typedef struct sip_addr_s sip_from_t; typedef msg_list_t sip_in_reply_to_t; typedef struct sip_max_forwards_s sip_max_forwards_t; typedef struct sip_min_expires_s sip_min_expires_t; typedef struct sip_min_se_s sip_min_se_t; typedef struct msg_generic_s sip_organization_t; typedef struct msg_generic_s sip_priority_t; typedef struct msg_auth_s sip_proxy_authenticate_t; typedef struct msg_auth_info_s sip_proxy_authentication_info_t; typedef struct msg_auth_s sip_proxy_authorization_t; typedef msg_list_t sip_proxy_require_t; typedef struct sip_rack_s sip_rack_t; typedef struct sip_reason_s sip_reason_t; typedef struct sip_route_s sip_record_route_t; typedef struct sip_refer_to_s sip_refer_to_t; typedef struct sip_referred_by_s sip_referred_by_t; typedef struct sip_replaces_s sip_replaces_t; typedef struct sip_request_disposition_s sip_request_disposition_t; typedef struct sip_caller_prefs_s sip_caller_prefs_t; typedef struct sip_caller_prefs_s sip_accept_contact_t; typedef struct sip_caller_prefs_s sip_reject_contact_t; typedef msg_list_t sip_require_t; typedef struct sip_retry_after_s sip_retry_after_t; typedef struct sip_route_s sip_route_t; typedef struct sip_rseq_s sip_rseq_t; typedef struct msg_generic_s sip_server_t; typedef struct sip_session_expires_s sip_session_expires_t; typedef struct msg_generic_s sip_subject_t; typedef struct sip_subscription_state_s sip_subscription_state_t; typedef msg_list_t sip_supported_t; typedef struct sip_timestamp_s sip_timestamp_t; typedef struct sip_addr_s sip_to_t; typedef msg_list_t sip_unsupported_t; typedef struct msg_generic_s sip_user_agent_t; typedef struct sip_via_s sip_via_t; typedef msg_warning_t sip_warning_t; typedef struct msg_auth_s sip_www_authenticate_t; typedef struct sip_event_s sip_event_t; typedef msg_list_t sip_allow_events_t; /* RFC 3323 - @Privacy */ typedef struct sip_privacy_s sip_privacy_t; /* RFC 3327 - @Path */ typedef struct sip_route_s sip_path_t; /* RFC 3329 - Security Mechanism Agreement */ typedef struct sip_security_agree_s sip_security_client_t; typedef struct sip_security_agree_s sip_security_server_t; typedef struct sip_security_agree_s sip_security_verify_t; /* RFC 3608 - Service Route */ typedef struct sip_route_s sip_service_route_t; /**SIP message object. * * This structure contains a parsed SIP message. The struct is usually * referred with typedef #sip_t. It is used to access the headers and * payload within the SIP message. The generic transport aspects of the * message, like network address, is accessed using the #msg_t object * directly. */ struct sip_s { msg_common_t sip_common[1]; /**< For recursive inclusion */ msg_pub_t *sip_next; /**< Dummy link to msgfrag */ void *sip_user; /**< Application data */ unsigned sip_size; /**< Size of structure */ int sip_flags; /**< Parser flags */ sip_error_t *sip_error; /**< Erroneous headers */ /* Pseudoheaders */ sip_request_t *sip_request; /**< Request line */ sip_status_t *sip_status; /**< Status line */ /* === Headers start here */ sip_via_t *sip_via; /**< Via (v) */ sip_route_t *sip_route; /**< Route */ sip_record_route_t *sip_record_route; /**< Record-Route */ sip_max_forwards_t *sip_max_forwards; /**< Max-Forwards */ sip_proxy_require_t *sip_proxy_require; /**< Proxy-Require */ sip_from_t *sip_from; /**< From (f) */ sip_to_t *sip_to; /**< To (t) */ sip_call_id_t *sip_call_id; /**< Call-ID (i) */ sip_cseq_t *sip_cseq; /**< CSeq */ sip_contact_t *sip_contact; /**< Contact (m) */ sip_rseq_t *sip_rseq; /**< RSeq */ sip_rack_t *sip_rack; /**< RAck */ /* Caller Preferences */ sip_request_disposition_t *sip_request_disposition; /**< Request-Disposition (d) */ sip_accept_contact_t *sip_accept_contact;/**< Accept-Contact (a) */ sip_reject_contact_t *sip_reject_contact;/**< Reject-Contact (j) */ sip_expires_t *sip_expires; /**< Expires */ sip_date_t *sip_date; /**< Date */ sip_retry_after_t *sip_retry_after; /**< Retry-After */ sip_timestamp_t *sip_timestamp; /**< Timestamp */ sip_min_expires_t *sip_min_expires; /**< Min-Expires */ sip_subject_t *sip_subject; /**< Subject (s) */ sip_priority_t *sip_priority; /**< Priority */ sip_call_info_t *sip_call_info; /**< Call-Info */ sip_organization_t *sip_organization; /**< Organization */ sip_server_t *sip_server; /**< Server */ sip_user_agent_t *sip_user_agent; /**< User-Agent */ sip_in_reply_to_t *sip_in_reply_to; /**< In-Reply-To */ sip_accept_t *sip_accept; /**< Accept */ sip_accept_encoding_t *sip_accept_encoding; /**< Accept-Encoding */ sip_accept_language_t *sip_accept_language; /**< Accept-Language */ sip_allow_t *sip_allow; /**< Allow */ sip_require_t *sip_require; /**< Require */ sip_supported_t *sip_supported; /**< Supported (k) */ sip_unsupported_t *sip_unsupported; /**< Unsupported */ /* RFC 3265 */ sip_event_t *sip_event; /**< Event (o) */ sip_allow_events_t *sip_allow_events; /**< Allow-Events (u) */ sip_subscription_state_t *sip_subscription_state; /**< Subscription-State */ sip_proxy_authenticate_t *sip_proxy_authenticate; /**< Proxy-Authenticate */ sip_proxy_authentication_info_t *sip_proxy_authentication_info; /**< Proxy-Authentication-Info */ sip_proxy_authorization_t *sip_proxy_authorization; /**< Proxy-Authorization */ sip_authorization_t *sip_authorization; /**< Authorization */ sip_www_authenticate_t *sip_www_authenticate; /**< WWW-Authenticate */ sip_authentication_info_t *sip_authentication_info; /**< Authentication-Info */ sip_error_info_t *sip_error_info; /**< Error-Info */ sip_warning_t *sip_warning; /**< Warning */ /* RFC 3515 */ sip_refer_to_t *sip_refer_to; /**< Refer-To (r) */ sip_referred_by_t *sip_referred_by; /**< Referred-By (b) */ sip_replaces_t *sip_replaces; /**< Replaces */ /* draft-ietf-sip-session-timer */ sip_session_expires_t *sip_session_expires; /**< Session-Expires (x) */ sip_min_se_t *sip_min_se; /**< Min-SE */ sip_path_t *sip_path; /**< Path */ sip_service_route_t *sip_service_route; /**< Service-Route */ sip_reason_t *sip_reason; /**< Reason */ sip_security_client_t *sip_security_client; /**< Security-Client */ sip_security_server_t *sip_security_server; /**< Security-Server */ sip_security_verify_t *sip_security_verify; /**< Security-Verify */ sip_privacy_t *sip_privacy; /**< Privacy */ sip_etag_t *sip_etag; /**< SIP-ETag */ sip_if_match_t *sip_if_match; /**< SIP-If-Match */ /* Entity headers */ sip_mime_version_t *sip_mime_version; /**< MIME-Version */ sip_content_type_t *sip_content_type; /**< Content-Type (c) */ sip_content_encoding_t *sip_content_encoding; /**< Content-Encoding (e) */ sip_content_language_t *sip_content_language; /**< Content-Language */ sip_content_disposition_t *sip_content_disposition; /**< Content-Disposition */ sip_content_length_t *sip_content_length;/**< Content-Length (l) */ /* === Headers end here */ sip_unknown_t *sip_unknown; /**< Unknown headers */ sip_separator_t *sip_separator; /**< Separator between headers and payload */ sip_payload_t *sip_payload; /**< Message payload */ msg_multipart_t *sip_multipart; /**< Multipart MIME payload */ }; /** @ingroup sip_request * @brief Structure for @ref sip_request "SIP request line". */ struct sip_request_s { sip_common_t rq_common[1]; /**< Common fragment info */ sip_error_t *rq_next; /**< Link to next (dummy) */ sip_method_t rq_method; /**< Method enum */ char const *rq_method_name; /**< Method name */ url_t rq_url[1]; /**< RequestURI */ char const *rq_version; /**< Protocol version */ }; /**@ingroup sip_status * @brief Structure for @ref sip_status "SIP status line". */ struct sip_status_s { sip_common_t st_common[1]; /**< Common fragment info */ sip_error_t *st_next; /**< Link to next (dummy) */ char const *st_version; /**< Protocol version */ int st_status; /**< Status code */ char const *st_phrase; /**< Status phrase */ }; /**@ingroup sip_from * @brief Structure for @From and @To headers. */ struct sip_addr_s { sip_common_t a_common[1]; /**< Common fragment info */ sip_error_t *a_next; char const *a_display; /**< Display name */ url_t a_url[1]; /**< URL */ msg_param_t const *a_params; /**< Parameter table */ char const *a_comment; /**< Comment */ char const *a_tag; /**< Tag parameter */ }; #define a_user a_url->url_user #define a_host a_url->url_host /**@ingroup sip_accept * @brief Structure for @Accept header field. */ struct sip_accept_s { sip_common_t ac_common[1]; /**< Common fragment info */ sip_accept_t *ac_next; /**< Pointer to next @Accept value */ char const *ac_type; /**< Pointer to type/subtype */ char const *ac_subtype; /**< Points after first slash in type */ msg_param_t const *ac_params; /**< List of parameters */ char const *ac_q; /**< Value of q parameter */ }; /**@ingroup sip_allow * @brief Structure for @Allow header field. * * @NEW_1_12_5. (Before used struct msg_list_s with @Allow). */ struct sip_allow_s { msg_common_t k_common[1]; /**< Common fragment info */ msg_list_t *k_next; /**< Link to next */ msg_param_t *k_items; /**< List of allowed items */ uint32_t k_bitmap; /**< Bitmap of allowed methods. @NEW_1_12_5. */ }; /**@ingroup sip_authentication_info * @brief Structure for @AuthenticationInfo header. * * @deprecated Use struct msg_auth_info_s instead. */ struct sip_authentication_info_s { sip_common_t ai_common[1]; /**< Common fragment info */ sip_error_t *ai_next; /**< Dummy link to next */ msg_param_t const *ai_params; /**< List of authentication info */ }; /**@ingroup sip_call_id * @brief Structure for @CallID (and @InReplyTo) header fields. */ struct sip_call_id_s { sip_common_t i_common[1]; /**< Common fragment info */ sip_call_id_t *i_next; /**< Link to next (In-Reply-To) */ char const *i_id; /**< ID value */ uint32_t i_hash; /**< Hash value (always nonzero) */ }; /**@ingroup sip_call_info * @brief Structure for @CallInfo header. */ struct sip_call_info_s { sip_common_t ci_common[1]; /**< Common fragment info */ sip_call_info_t *ci_next; /**< Link to next @CallInfo */ url_t ci_url[1]; /**< URI to call info */ msg_param_t const *ci_params; /**< List of parameters */ char const *ci_purpose; /**< Value of @b purpose parameter */ }; /**@ingroup sip_cseq * @brief Structure for @CSeq header. */ struct sip_cseq_s { sip_common_t cs_common[1]; /**< Common fragment info */ sip_error_t *cs_next; /**< Link to next (dummy) */ uint32_t cs_seq; /**< Sequence number */ sip_method_t cs_method; /**< Method enum */ char const *cs_method_name; /**< Method name */ }; /**@ingroup sip_contact * @brief Structure for @Contact header field. */ struct sip_contact_s { sip_common_t m_common[1]; /**< Common fragment info */ sip_contact_t *m_next; /**< Link to next @Contact header */ char const *m_display; /**< Display name */ url_t m_url[1]; /**< SIP URL */ msg_param_t const *m_params; /**< List of contact-params */ char const *m_comment; /**< Comment */ char const *m_q; /**< @Priority */ char const *m_expires; /**< Expiration time */ }; /**@ingroup sip_content_length * @brief Structure for @ContentLength header. */ struct sip_content_length_s { sip_common_t l_common[1]; /**< Common fragment info */ sip_error_t *l_next; /**< Link to next (dummy) */ uint32_t l_length; /**< Length in bytes */ }; #if DOCUMENTATION_ONLY /**@ingroup sip_content_type * * @brief Structure for @ContentType header. */ struct sip_content_type_s { sip_common_t c_common[1]; /**< Common fragment info */ sip_error_t *c_next; /**< Dummy link to next */ char const *c_type; /**< Pointer to type/subtype */ char const *c_subtype; /**< Points after first slash in type */ msg_param_t const *c_params; /**< List of parameters */ }; #endif /**@ingroup sip_date * @brief Structure for @Date header. */ struct sip_date_s { sip_common_t d_common[1]; /**< Common fragment info */ sip_date_t *d_next; /**< Link to next (dummy) */ sip_time_t d_time; /**< Seconds since Jan 1, 1900 */ }; /**@ingroup sip_error_info * @brief Structure for @ErrorInfo header. */ struct sip_error_info_s { sip_common_t ei_common[1]; /**< Common fragment info */ sip_call_info_t *ei_next; /**< Link to next @ErrorInfo */ url_t ei_url[1]; /**< URI to error description */ msg_param_t const *ei_params; /**< List of parameters */ }; /**@ingroup sip_event * @brief Structure for @Event header. */ struct sip_event_s { sip_common_t o_common[1]; /**< Common fragment info */ sip_error_t *o_next; /**< Link to next (dummy) */ char const * o_type; /**< @Event type */ msg_param_t const *o_params; /**< List of parameters */ char const *o_id; /**< @Event ID */ }; /**@ingroup sip_expires * @brief Structure for @Expires header. */ struct sip_expires_s { sip_common_t ex_common[1]; /**< Common fragment info */ sip_error_t *ex_next; /**< Link to next (dummy) */ sip_time_t ex_date; /**< Seconds since Jan 1, 1900 */ # define ex_time ex_date sip_time_t ex_delta; /**< Delta seconds */ }; /**@ingroup sip_max_forwards * @brief Structure for @MaxForwards header. */ struct sip_max_forwards_s { sip_common_t mf_common[1]; /**< Common fragment info */ sip_error_t *mf_next; /**< Link to next (dummy) */ unsigned long mf_count; /**< Forwarding count */ }; /**@ingroup sip_min_expires * @brief Structure for @MinExpires header. */ struct sip_min_expires_s { sip_common_t me_common[1]; /**< Common fragment info */ sip_error_t *me_next; /**< Link to next (dummy) */ unsigned long me_delta; /**< Seconds */ }; /**@ingroup sip_rack * @brief Structure for @RAck header. */ struct sip_rack_s { sip_common_t ra_common; /**< Common fragment info */ sip_error_t *ra_next; /**< Dummy link to next */ uint32_t ra_response; /**< Sequence number of response */ uint32_t ra_cseq; /**< Sequence number of request */ sip_method_t ra_method; /**< Original request method */ char const *ra_method_name; /**< Original request method name */ }; /**@ingroup sip_refer_to * @brief Structure for @ReferTo header. */ struct sip_refer_to_s { sip_common_t r_common[1]; /**< Common fragment info */ sip_error_t *r_next; /**< Link to next (dummy) */ char const *r_display; url_t r_url[1]; /**< URI to reference */ msg_param_t const *r_params; /**< List of parameters */ }; /**@ingroup sip_referred_by * @brief Structure for @ReferredBy header. */ struct sip_referred_by_s { sip_common_t b_common[1]; /**< Common fragment info */ sip_error_t *b_next; /**< Link to next (dummy) */ char const *b_display; url_t b_url[1]; /**< Referrer-URI */ msg_param_t const *b_params; /**< List of parameters */ char const *b_cid; /**< The cid parameter */ }; /**@ingroup sip_replaces * @brief Structure for @Replaces header. */ struct sip_replaces_s { sip_common_t rp_common[1]; /**< Common fragment info */ sip_error_t *rp_next; /**< Link to next (dummy) */ char const *rp_call_id; /**< @CallID of dialog to replace */ msg_param_t const *rp_params; /**< List of parameters */ char const *rp_to_tag; /**< Value of "to-tag" parameter */ char const *rp_from_tag; /**< Value of "from-tag" parameter */ unsigned rp_early_only; /**< early-only parameter */ }; /**@ingroup sip_retry_after * @brief Structure for @RetryAfter header. */ struct sip_retry_after_s { sip_common_t af_common[1]; /**< Common fragment info */ sip_error_t *af_next; /**< Link to next (dummy) */ sip_time_t af_delta; /**< Seconds to before retry */ char const *af_comment; /**< Comment string */ msg_param_t const *af_params; /**< List of parameters */ char const *af_duration; /**< Value of "duration" parameter */ }; /**@ingroup sip_request_disposition * @brief Structure for @RequestDisposition header. */ struct sip_request_disposition_s { sip_common_t rd_common[1]; /**< Common fragment info */ sip_error_t *rd_next; /**< Link to next (dummy) */ msg_param_t *rd_items; /**< List of directives */ }; /**@ingroup sip_caller_preferences * @brief Structure for @AcceptContact and @RejectContact header fields. */ struct sip_caller_prefs_s { sip_common_t cp_common[1]; /**< Common fragment info */ sip_caller_prefs_t *cp_next; /**< Link to next (dummy) */ msg_param_t const *cp_params; /**< List of parameters */ char const *cp_q; /**< @Priority */ unsigned cp_require :1; /**< Value of "require" parameter */ unsigned cp_explicit :1; /**< Value of "explicit" parameter */ }; /**@ingroup sip_reason * @brief Structure for @Reason header field. */ struct sip_reason_s { sip_common_t re_common[1]; /**< Common fragment info */ sip_reason_t *re_next; /**< Link to next */ char const *re_protocol; /**< Protocol */ msg_param_t const *re_params; /**< List of reason parameters */ char const *re_cause; /**< Value of cause parameter */ char const *re_text; /**< Value of text parameter */ }; /**@ingroup sip_route * @brief Structure for @Route and @RecordRoute header fields. */ struct sip_route_s { sip_common_t r_common[1]; /**< Common fragment info */ sip_route_t *r_next; /**< Link to next */ char const *r_display; /**< Display name */ url_t r_url[1]; /**< @Route URL */ msg_param_t const *r_params; /**< List of route parameters */ }; /**@ingroup sip_rseq * @brief Structure for @RSeq header. */ struct sip_rseq_s { sip_common_t rs_common[1]; /**< Common fragment info */ sip_error_t *rs_next; /**< Dummy link to next */ unsigned long rs_response; /**< Sequence number of response */ }; /**@ingroup sip_session_expires * @brief Structure for @SessionExpires header. */ struct sip_session_expires_s { sip_common_t x_common[1]; /**< Common fragment info */ sip_error_t *x_next; /**< Dummy link to next */ unsigned long x_delta; /**< Delta-seconds */ msg_param_t const *x_params; /**< List of parameters */ char const *x_refresher; /**< Value of "refresher" * parameter: UAS or UAC */ }; /**@ingroup sip_min_se * @brief Structure for @MinSE header. */ struct sip_min_se_s { sip_common_t min_common[1]; /**< Common fragment info */ sip_error_t *min_next; /**< Dummy link to next */ unsigned long min_delta; /**< Delta-seconds */ msg_param_t const *min_params; /**< List of extension parameters */ }; /**@ingroup sip_subscription_state * @brief Structure for @SubscriptionState header. */ struct sip_subscription_state_s { sip_common_t ss_common[1]; /**< Common fragment info */ sip_error_t *ss_next; /**< Dummy link to next */ /** Subscription state: "pending", "active" or "terminated" */ char const *ss_substate; msg_param_t const *ss_params; /**< List of parameters */ char const *ss_reason; /**< Reason for termination */ char const *ss_expires; /**< Subscription lifetime */ char const *ss_retry_after; /**< Value of retry-after parameter */ }; /**@ingroup sip_timestamp * @brief Structure for @Timestamp header. */ struct sip_timestamp_s { sip_common_t ts_common[1]; /**< Common fragment info */ sip_error_t *ts_next; /**< Dummy link to next */ char const *ts_stamp; /**< Original timestamp */ char const *ts_delay; /**< Delay at UAS */ }; /**@ingroup sip_via * @brief Structure for @Via header field. */ struct sip_via_s { sip_common_t v_common[1]; /**< Common fragment info */ sip_via_t *v_next; /**< Link to next @Via header */ char const *v_protocol; /**< Application and transport protocol */ char const *v_host; /**< Hostname */ char const *v_port; /**< Port number */ msg_param_t const *v_params; /**< List of via-params */ char const *v_comment; /**< Comment */ char const *v_ttl; /**< Value of "ttl" parameter */ char const *v_maddr; /**< Value of "maddr" parameter */ char const *v_received; /**< Value of "received" parameter*/ char const *v_branch; /**< Value of "branch" parameter */ char const *v_rport; /**< Value of "rport" parameter */ char const *v_comp; /**< Value of "comp" parameter */ }; /**@ingroup sip_security_client * @brief Structure for @SecurityClient, @SecurityServer, and * @SecurityVerify headers. */ struct sip_security_agree_s { sip_common_t sa_common[1]; /**< Common fragment info */ struct sip_security_agree_s *sa_next; /**< Link to next mechanism */ char const *sa_mec; /**< Security mechanism */ msg_param_t const *sa_params; /**< List of mechanism parameters */ char const *sa_q; /**< Value of q (preference) parameter */ char const *sa_d_alg; /**< Value of d-alg parameter */ char const *sa_d_qop; /**< Value of d-qop parameter */ char const *sa_d_ver; /**< Value of d-ver parameter */ }; /**@ingroup sip_privacy * @brief Structure for @Privacy header. */ struct sip_privacy_s { sip_common_t priv_common[1];/**< Common fragment info */ sip_error_t *priv_next; /**< Dummy link */ msg_param_t const *priv_values; /**< @Privacy values */ }; /* union representing any SIP header * these are arrays of size 1 for easy casting */ union sip_header_u { sip_common_t sh_common[1]; struct { sip_common_t shn_common; sip_header_t *shn_next; } sh_header_next[1]; #define sh_next sh_header_next->shn_next #define sh_class sh_common->h_class #define sh_succ sh_common->h_succ #define sh_prev sh_common->h_prev #define sh_data sh_common->h_data #define sh_len sh_common->h_len sip_addr_t sh_addr[1]; sip_auth_t sh_auth[1]; sip_generic_t sh_generic[1]; sip_request_t sh_request[1]; sip_status_t sh_status[1]; sip_error_t sh_error[1]; sip_via_t sh_via[1]; sip_route_t sh_route[1]; sip_record_route_t sh_record_route[1]; sip_max_forwards_t sh_max_forwards[1]; sip_from_t sh_from[1]; sip_to_t sh_to[1]; sip_contact_t sh_contact[1]; sip_call_id_t sh_call_id[1]; sip_cseq_t sh_cseq[1]; sip_rseq_t sh_rseq[1]; sip_rack_t sh_rack[1]; sip_subject_t sh_subject[1]; sip_priority_t sh_priority[1]; sip_date_t sh_date[1]; sip_retry_after_t sh_retry_after[1]; sip_timestamp_t sh_timestamp[1]; sip_expires_t sh_expires[1]; sip_min_expires_t sh_min_expires[1]; sip_call_info_t sh_call_info[1]; sip_organization_t sh_organization[1]; sip_server_t sh_server[1]; sip_user_agent_t sh_user_agent[1]; sip_in_reply_to_t sh_in_reply_to[1]; sip_accept_t sh_accept[1]; sip_accept_encoding_t sh_accept_encoding[1]; sip_accept_language_t sh_accept_language[1]; sip_allow_t sh_allow[1]; sip_require_t sh_require[1]; sip_proxy_require_t sh_proxy_require[1]; sip_supported_t sh_supported[1]; sip_unsupported_t sh_unsupported[1]; sip_event_t sh_event[1]; sip_allow_events_t sh_allow_events[1]; sip_subscription_state_t sh_subscription_state[1]; sip_proxy_authenticate_t sh_proxy_authenticate[1]; sip_proxy_authentication_info_t sh_proxy_authentication_info[1]; sip_proxy_authorization_t sh_proxy_authorization[1]; sip_authorization_t sh_authorization[1]; sip_www_authenticate_t sh_www_authenticate[1]; sip_authentication_info_t sh_authentication_info[1]; sip_error_info_t sh_error_info[1]; sip_warning_t sh_warning[1]; sip_refer_to_t sh_refer_to[1]; sip_referred_by_t sh_referred_by[1]; sip_replaces_t sh_replaces[1]; /* Caller-Preferences */ sip_caller_prefs_t sh_caller_prefs[1]; sip_request_disposition_t sh_request_disposition[1]; sip_accept_contact_t sh_accept_contact[1]; sip_reject_contact_t sh_reject_contact[1]; sip_session_expires_t sh_session_expires[1]; sip_min_se_t sh_min_se[1]; sip_path_t sh_path[1]; sip_service_route_t sh_service_route[1]; sip_reason_t sh_reason[1]; sip_security_client_t sh_security_client[1]; sip_security_server_t sh_security_server[1]; sip_security_verify_t sh_security_verify[1]; sip_privacy_t sh_privacy[1]; sip_etag_t sh_etag[1]; sip_if_match_t sh_if_match[1]; /* Entity headers */ sip_mime_version_t sh_mime_version[1]; sip_content_type_t sh_content_type[1]; sip_content_encoding_t sh_content_encoding[1]; sip_content_language_t sh_content_language[1]; sip_content_length_t sh_content_length[1]; sip_content_disposition_t sh_content_disposition[1]; sip_unknown_t sh_unknown[1]; sip_separator_t sh_separator[1]; sip_payload_t sh_payload[1]; }; SOFIA_END_DECLS #endif /* !defined(SIP_H) */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sofia-sip/sip_extra.h.in000066400000000000000000000123631223300710500250200ustar00rootroot00000000000000`/**@file sofia-sip/sip_extra.h.in * -*- C -*- * Template for . * * @date Created: Thu Oct 5 19:10:58 EEST 2006 */ /* -*- C -*- * * This file is part of the Sofia-SIP package * * Copyright (C) 2006 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef SIP_EXTRA_H /** Defined when has been included. */ #define SIP_EXTRA_H /**@file sofia-sip/sip_extra.h * * @brief Extension headers for SIP. * * #AUTO# * * @author Pekka Pessi . */ #ifndef SIP_H #include #endif #ifndef SIP_HEADER_H #include #endif SOFIA_BEGIN_DECLS typedef struct sip_refer_sub_s sip_refer_sub_t; /**@ingroup sip_refer_sub * @brief Structure for @ReferSub header. */ struct sip_refer_sub_s { sip_common_t rs_common[1]; /**< Common fragment info */ sip_error_t *rs_next; /**< Dummy link to next */ char const *rs_value; /**< "true" or "false" */ msg_param_t const *rs_params; /**< List of extension parameters */ }; typedef struct sip_alert_info_s sip_alert_info_t; /**@ingroup sip_alert_info * @brief Structure for @AlertInfo header. */ struct sip_alert_info_s { sip_common_t ai_common[1]; /**< Common fragment info */ sip_alert_info_t *ai_next; /**< Link to next @AlertInfo */ url_t ai_url[1]; /**< URI to alert info */ msg_param_t const *ai_params; /**< List of optional parameters */ }; typedef struct sip_reply_to_s sip_reply_to_t; /**@ingroup sip_reply_to * @brief Structure for @ReplyTo header. */ struct sip_reply_to_s { sip_common_t rplyto_common[1]; /**< Common fragment info */ sip_error_t *rplyto_next; /**< Dummy link to next header */ char const *rplyto_display; /**< Display name */ url_t rplyto_url[1]; /**< Return URI */ msg_param_t const *rplyto_params; /**< List of optional parameters */ }; typedef struct sip_suppress_body_if_match_s sip_suppress_body_if_match_t; /**@ingroup sip_suppress_body_if_match * @brief Structure for @SuppressBodyIfMatch header. */ struct sip_suppress_body_if_match_s { sip_common_t sbim_common[1]; /**< Common fragment info */ sip_error_t *sbim_next; /**< Dummy link to next header */ char const *sbim_tag; /**< Entity-tag */ }; typedef struct sip_suppress_notify_if_match_s sip_suppress_notify_if_match_t; /**@ingroup sip_suppress_notify_if_match * @brief Structure for @SuppressNotifyIfMatch header. */ struct sip_suppress_notify_if_match_s { sip_common_t snim_common[1]; /**< Common fragment info */ sip_error_t *snim_next; /**< Dummy link to next header */ char const *snim_tag; /**< Entity-tag */ }; typedef struct sip_p_asserted_identity_s sip_p_asserted_identity_t; /**@ingroup sip_p_asserted_identity * @brief Structure for @PAssertedIdentity header. */ struct sip_p_asserted_identity_s { sip_common_t paid_common[1];/**< Common fragment info */ sip_p_asserted_identity_t *paid_next; /**< Link to next identity */ char const *paid_display; /**< Display name */ url_t paid_url[1]; /**< SIP, SIPS or TEL URL */ }; typedef struct sip_p_preferred_identity_s sip_p_preferred_identity_t; /**@ingroup sip_p_preferred_identity * @brief Structure for @PPreferredIdentity header. */ struct sip_p_preferred_identity_s { sip_common_t ppid_common[1];/**< Common fragment info */ sip_p_preferred_identity_t *ppid_next; /**< Link to next identity */ char const *ppid_display; /**< Display name */ url_t ppid_url[1]; /**< SIP, SIPS or TEL URL */ }; int sip_p_initialize_remote_party_id_headers(msg_mclass_t *mclass); typedef struct sip_remote_party_id_s sip_remote_party_id_t; /**@ingroup sip_remote_party_id * @brief Structure for @RemotePartyID header. */ struct sip_remote_party_id_s { sip_common_t rpid_common[1];/**< Common fragment info */ sip_remote_party_id_t *rpid_next; /**< Link to next identity */ char const *rpid_display; /**< Display name */ url_t rpid_url[1]; /**< URL */ sip_param_t const *rpid_params; /**< Parameters */ /** Shortcuts to screen, party, id-type and privacy parameters */ char const *rpid_screen, *rpid_party, *rpid_id_type, *rpid_privacy; }; /** Defined as 1 if the @ref sip_#xxxxxx# "#xxxxxxx_xxxxxxx#" is supported */ #define SIP_HAVE_#XXXXXX# 1 SOFIA_END_DECLS #endif /** !defined(SIP_EXTRA_H) */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sofia-sip/sip_hclasses.h.in000066400000000000000000000037621223300710500255050ustar00rootroot00000000000000/** -*- C -*- * * @file sofia-sip/sip_hclasses.h.in * * Template for . */ /* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef SIP_HCLASSES_H /** Defined when has been included. */ #define SIP_HCLASSES_H /**@file sofia-sip/sip_hclasses.h * @brief Declarations of SIP header classes. * * #AUTO# * * @author Pekka Pessi * * @date Created: Thu Jan 23 19:26:31 2003 ppessi */ #ifndef MSG_TYPES_H #include #endif SOFIA_BEGIN_DECLS enum { /**@ingroup sip_#xxxxxx# @internal * * Hash of @ref sip_#xxxxxx# "#xxxxxxx_xxxxxxx#". * * @since New in #version#. */ sip_#xxxxxx#_hash = #hash# }; /**Header class for @ref sip_#xxxxxx# "#xxxxxxx_xxxxxxx#". * * The header class sip_#xxxxxx#_class defines how a SIP * @ref sip_#xxxxxx# "#xxxxxxx_xxxxxxx#" is parsed and printed. * It also contains methods used by SIP parser and other functions to * manipulate the #sip_#xxxxxx#_t header structure. * * @ingroup sip_#xxxxxx# * * @since New in #version#. */ SIP_DLL extern msg_hclass_t sip_#xxxxxx#_class[]; SOFIA_END_DECLS #endif /* !defined SIP_HCLASSES_H */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sofia-sip/sip_header.h000066400000000000000000000374371223300710500245310ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef SIP_HEADER_H /**Defined when has been included.*/ #define SIP_HEADER_H /**@file sofia-sip/sip_header.h * * SIP parser library prototypes. * * @author Pekka Pessi . * * @date Created: Tue Jun 13 02:58:26 2000 ppessi */ #ifndef SU_ALLOC_H #include #endif #ifndef SU_TAG_H #include #endif #ifndef SIP_H #include #endif #ifndef MSG_HEADER_H #include #endif #ifndef _STRING_H #include #endif SOFIA_BEGIN_DECLS /** Return a built-in SIP parser object. */ SOFIAPUBFUN msg_mclass_t const *sip_default_mclass(void); SOFIAPUBFUN int sip_update_default_mclass(msg_mclass_t const *mclass); SOFIAPUBFUN msg_mclass_t *sip_extend_mclass(msg_mclass_t *input); /** Check that sip_t is a SIP header structure (not MIME or HTTP). @HIDE */ #define sip_is_sip(sip) ((sip) && (sip)->sip_ident == SIP_PROTOCOL_TAG) /** Initializer for a SIP header structure. @HIDE */ #define SIP_HDR_INIT(name) {{{ 0, 0, sip_##name##_class }}} /** Initialize a SIP header structure. @HIDE */ #define SIP_HEADER_INIT(h, sip_class, size) \ ((void)memset((h), 0, (size)), \ (void)(((sip_common_t *)(h))->h_class = (sip_class)), \ (h)) /** Serialize headers into the fragment chain. */ SOFIAPUBFUN int sip_serialize(msg_t *msg, sip_t *sip); /** Encode a SIP message. */ SOFIAPUBFUN issize_t sip_e(sip_t const *sip, int flags, char b[], isize_t size); /** Test if @a header is a pointer to a SIP header object. */ SOFIAPUBFUN int sip_is_header(sip_header_t const *header); /** Convert the header @a h to a string allocated from @a home. */ SOFIAPUBFUN char *sip_header_as_string(su_home_t *home, sip_header_t const *h); /** Add a duplicate of header object to a SIP message. */ SOFIAPUBFUN int sip_add_dup(msg_t *, sip_t *, sip_header_t const *); /** Add a duplicate of header object to the SIP message. */ SOFIAPUBFUN int sip_add_dup_as(msg_t *msg, sip_t *sip, msg_hclass_t *hc, sip_header_t const *o); /** Add duplicates of headers to the SIP message. */ SOFIAPUBFUN int sip_add_headers(msg_t *msg, sip_t *sip, void const *extra, va_list headers); /** Add duplicates of headers from taglist to the SIP message. */ SOFIAPUBFUN int sip_add_tl(msg_t *msg, sip_t *sip, tag_type_t tag, tag_value_t value, ...); /** Add duplicates of headers from taglist to the SIP message. */ SOFIAPUBFUN int sip_add_tagis(msg_t *, sip_t *, tagi_t const **inout_list); /** Parse a string as a header and add it to the SIP message. */ SOFIAPUBFUN int sip_add_make(msg_t *, sip_t *, msg_hclass_t *hc, char const *s); /** Convert headers from taglist as URL query. */ SOFIAPUBFUN char *sip_headers_as_url_query(su_home_t *home, tag_type_t tag, tag_value_t value, ...); /** Convert URL query to a tag list. */ SOFIAPUBFUN tagi_t *sip_url_query_as_taglist(su_home_t *home, char const *query, msg_mclass_t const *parser); /** Complete SIP message. */ SOFIAPUBFUN int sip_complete_message(msg_t *msg); /** Clear encoded data. @HIDE */ #define sip_fragment_clear(a) ((a)->h_data = NULL, (a)->h_len = 0) /* Use __attribute__ to allow argument checking for sip_header_format() */ #if !defined(__GNUC__) && !defined(__attribute__) #define __attribute__(x) #endif /** Make a SIP header with formatting provided. */ SOFIAPUBFUN sip_header_t *sip_header_format(su_home_t *home, msg_hclass_t *hc, char const *fmt, ...) __attribute__((__format__ (printf, 3, 4))); /** Return current time */ SOFIAPUBFUN sip_time_t sip_now(void); SOFIAPUBVAR char const sip_method_name_ack[]; SOFIAPUBVAR char const sip_method_name_bye[]; SOFIAPUBVAR char const sip_method_name_cancel[]; SOFIAPUBVAR char const sip_method_name_invite[]; SOFIAPUBVAR char const sip_method_name_options[]; SOFIAPUBVAR char const sip_method_name_register[]; SOFIAPUBVAR char const sip_method_name_info[]; SOFIAPUBVAR char const sip_method_name_prack[]; SOFIAPUBVAR char const sip_method_name_comet[]; SOFIAPUBVAR char const sip_method_name_message[]; SOFIAPUBVAR char const sip_method_name_subscribe[]; SOFIAPUBVAR char const sip_method_name_notify[]; SOFIAPUBVAR char const sip_method_name_refer[]; /** @internal UDP transport version string. */ SOFIAPUBVAR char const sip_transport_udp[]; /** @internal TCP transport version string. */ SOFIAPUBVAR char const sip_transport_tcp[]; /** @internal SCTP transport version string. */ SOFIAPUBVAR char const sip_transport_sctp[]; /** @internal TLS transport version string. */ SOFIAPUBVAR char const sip_transport_tls[]; /** @internal SIP version string. */ SOFIAPUBVAR char const sip_version_2_0[]; #define SIP_VERSION_CURRENT sip_version_2_0 /** SIP parser version */ SOFIAPUBVAR char const sip_parser_version[]; /** Get SIP service name */ #define SIP_PORT(s) ((s) ? (s) : "5060") /** Get SIPS service name */ #define SIPS_PORT(s) ((s) ? (s) : "5061") /** Return string corresponding to the method. */ SOFIAPUBFUN char const *sip_method_name(sip_method_t method, char const *name); /** Return code corresponding to the method code */ SOFIAPUBFUN sip_method_t sip_method_code(char const *name); SOFIAPUBVAR char const * const sip_method_names[]; #define SIP_METHOD_NAME(method, name) \ ((method) == sip_method_unknown ? (name) : sip_method_name(method, name)) #define sip_header_make(h, c, s) \ ((sip_header_t *)msg_header_make((h), (c), (s))) #define sip_header_vformat(h, c, f, a) \ ((sip_header_t *)msg_header_vformat((h), (c), (f), (a))) SOFIA_END_DECLS #ifndef SIP_PROTOS_H #include #endif SOFIA_BEGIN_DECLS /** Create a request line object. */ SOFIAPUBFUN sip_request_t *sip_request_create(su_home_t *home, sip_method_t method, const char *name, url_string_t const *url, char const *version); /** Create a status line object. */ SOFIAPUBFUN sip_status_t *sip_status_create(su_home_t *home, unsigned status, char const *phrase, char const *version); /** Create a @CallID header object. */ SOFIAPUBFUN sip_call_id_t *sip_call_id_create(su_home_t *home, char const *domain); /** Create a @CSeq header object. */ SOFIAPUBFUN sip_cseq_t *sip_cseq_create(su_home_t *, uint32_t seq, unsigned method, char const *name); /** Create a @Contact header object. */ SOFIAPUBFUN sip_contact_t * sip_contact_create(su_home_t *, url_string_t const *url, char const *param, /* char const *params, */ ...); /** Calculate expiration time of a @Contact header. */ SOFIAPUBFUN sip_time_t sip_contact_expires(sip_contact_t const *m, sip_expires_t const *ex, sip_date_t const *date, sip_time_t def, sip_time_t now); /** Create a @ContentLength header object. */ SOFIAPUBFUN sip_content_length_t *sip_content_length_create(su_home_t *, uint32_t n); /** Create an @Date header object. */ SOFIAPUBFUN sip_date_t *sip_date_create(su_home_t *, sip_time_t t); /** Create an @Expires header object. */ SOFIAPUBFUN sip_expires_t *sip_expires_create(su_home_t *, sip_time_t delta); /** Create a @Route header object. */ SOFIAPUBFUN sip_route_t *sip_route_create(su_home_t *home, url_t const *url, url_t const *maddr); /** Create a @RecordRoute header object. */ SOFIAPUBFUN sip_record_route_t *sip_record_route_create(su_home_t *, url_t const *rq_url, url_t const *m_url); /** Create a @From header object. */ SOFIAPUBFUN sip_from_t *sip_from_create(su_home_t *, url_string_t const *url); SOFIAPUBFUN int sip_from_tag(su_home_t *, sip_from_t *from, char const *tag); /** Create a @To header object. */ SOFIAPUBFUN sip_to_t *sip_to_create(su_home_t *, url_string_t const *url); SOFIAPUBFUN int sip_to_tag(su_home_t *, sip_to_t *to, char const *tag); /** Create a @Via object. */ SOFIAPUBFUN sip_via_t *sip_via_create(su_home_t *h, char const *host, char const *port, char const *transport, /* char const *params */ ...); /** Get transport protocol name. */ #if SU_HAVE_INLINE su_inline char const *sip_via_transport(sip_via_t const *v) { char const *tp = v->v_protocol; if (tp) { tp = strchr(tp, '/'); if (tp) { tp = strchr(tp + 1, '/'); if (tp) return tp + 1; } } return NULL; } #else char const *sip_via_transport(sip_via_t const *v); #endif SOFIAPUBFUN char const *sip_via_port(sip_via_t const *v, int *using_rport); SOFIAPUBFUN sip_payload_t *sip_payload_create(su_home_t *, void const *data, isize_t len); /**@ingroup sip_payload * * Initialize a SIP payload structure with pointer to data and its length. * * The SIP_PAYLOAD_INIT2() macro initializes a #sip_payload_t header * structure with a pointer to data and its length in octets. For * instance, * @code * sip_payload_t txt_payload = SIP_PAYLOAD_INIT2(txt, strlen(txt)); * @endcode * * The SIP_PAYLOAD_INIT2() macro can be used when creating a new payload * from heap is not required, for instance, when the resulting payload * structure is immediately copied. * * @HIDE */ #define SIP_PAYLOAD_INIT2(data, length) \ {{{ 0, 0, sip_payload_class, data, length }, NULL, data, length }} /** Create a SIP separator line structure. */ SOFIAPUBFUN sip_separator_t *sip_separator_create(su_home_t *home); /** Check that a required feature is supported. */ SOFIAPUBFUN sip_unsupported_t *sip_has_unsupported(su_home_t *, sip_supported_t const *support, sip_require_t const *require); SOFIAPUBFUN sip_unsupported_t *sip_has_unsupported2(su_home_t *, sip_supported_t const *support, sip_require_t const *by_require, sip_require_t const *require); SOFIAPUBFUN sip_unsupported_t * sip_has_unsupported_any(su_home_t *, sip_supported_t const *support, sip_require_t const *by_require, sip_proxy_require_t const *by_proxy_require, sip_require_t const *require, sip_require_t const *require2, sip_require_t const *require3); /** Check that a feature is supported. */ SOFIAPUBFUN int sip_has_supported(sip_supported_t const *support, char const *feature); /** Check that a feature is in the list. */ SOFIAPUBFUN int sip_has_feature(msg_list_t const *supported, char const *feature); /** Return true if the method is listed in @Allow header. */ SOFIAPUBFUN int sip_is_allowed(sip_allow_t const *allow, sip_method_t method, char const *name); /** Check if the well-known method is listed in @Allow header. @NEW_1_12_6. */ #define SIP_IS_ALLOWED(allow, method) \ (sip_method_unknown < (method) && (method) < 32 && \ (allow) && ((allow)->k_bitmap & (1 << (method))) != 0) /** * Bitmasks for header classifications. * * If parsing of a particular header fails, the error bits in #msg_t are * updated. The error bits can be obtained via msg_extract_errors() after * parsing. The header-specific bits are stored along with the * @ref msg_hclass_t "header class" in the #msg_href_t structure, found in * the parser tables of the #msg_mclass_t object. * * @sa NTATAG_BAD_REQ_MASK(), NTATAG_BAD_RESP_MASK(), * #msg_mclass_t, struct #msg_mclass_s, msg_mclass_clone(), * msg_mclass_insert_with_mask(), * #msg_href_t, struct #msg_href_s, msg_mclass_insert(). */ enum sip_bad_mask { /** Bit marking essential headers in a request message. * * @ref sip_request \"request line\"", @From, @To, @CSeq, @CallID, * @ContentLength, @Via */ sip_mask_request = (1 << 0), /** Bit marking essential headers in a response message. * * @ref sip_status \"status line\"", @From, @To, @CSeq, @CallID, * @ContentLength, @Via */ sip_mask_response = (1 << 1), /** Bit marking essential headers for User-Agent. * * @ContentType, @ContentDisposition, @ContentEncoding, @Supported, * @Contact, @Require, and @RecordRoute. */ sip_mask_ua = (1 << 2), /** Bit marking essential headers for proxy server. * * @Route, @MaxForwards, @ProxyRequire, @ProxyAuthorization, @Supported, * @Contact, and @RecordRoute. */ sip_mask_proxy = (1 << 3), /** Bit marking essential headers for registrar server. * * @MinExpires, @Authorization, @Path, @Supported, @Contact, @Require, and * @Expires. * */ sip_mask_registrar = (1 << 4), /** Bit marking essential headers for 100rel extension. * * @RAck and @RSeq. * * @sa @RFC3262. */ sip_mask_100rel = (1 << 5), /** Bit marking essential headers for SIP events. * * @Event, @Expires, and @SubscriptionState. * * @sa @RFC3265. */ sip_mask_events = (1 << 6), /** Bit marking essential headers for session timer extension. * * @SessionExpires, and @MinSE. * * @RFC4028 */ sip_mask_timer = (1 << 7), /** Bit marking essential headers for privacy extension. * * @Privacy. * * @sa @RFC3323 */ sip_mask_privacy = (1 << 8), /** Bit marking essential headers for caller preference extension. * * @RequestDisposition, @AcceptContact, and @RejectContact. * * @sa @RFC3841. */ sip_mask_pref = (1 << 9), /** Bit marking essential headers for PUBLISH servers and clients. * * @SIPETag, and @SIPIfMatch. * * @sa @RFC3903. */ sip_mask_publish = (1 << 10) /* NOTE: * When adding bits, please update nta_agent_create() and * NTATAG_BAD_RESP_MASK()/NTATAG_BAD_REQ_MASK() documentation. */ }; /* ------------------------------------------------------------------------- */ /* Here are @deprecated functions and names for compatibility */ /** Encode a SIP header field (name: contents CRLF). */ SOFIAPUBFUN issize_t sip_header_e(char[], isize_t, sip_header_t const *, int); /** Decode a SIP header string (name: contents CRLF?). */ SOFIAPUBFUN sip_header_t *sip_header_d(su_home_t *, msg_t const *, char const *); /** Encode contents of a SIP header field. */ SOFIAPUBFUN issize_t sip_header_field_e(char[], isize_t, sip_header_t const *, int); /** Decode the string containing header field */ SOFIAPUBFUN issize_t sip_header_field_d(su_home_t *, sip_header_t *, char *, isize_t); /** Calculate the size of a SIP header and associated memory areas. */ SOFIAPUBFUN isize_t sip_header_size(sip_header_t const *h); /** Duplicate (deep copy) a SIP header or whole list. */ SOFIAPUBFUN sip_header_t *sip_header_dup(su_home_t *, sip_header_t const *); /** Copy a SIP header or whole list. */ SOFIAPUBFUN sip_header_t *sip_header_copy(su_home_t *, sip_header_t const *o); /** Add an event to @AllowEvents header. */ SOFIAPUBFUN int sip_allow_events_add(su_home_t *, sip_allow_events_t *ae, char const *e); /** Add a parameter to a @Contact header object. */ SOFIAPUBFUN int sip_contact_add_param(su_home_t *, sip_contact_t *, char const *param); SOFIAPUBFUN int sip_to_add_param(su_home_t *, sip_to_t *, char const *); SOFIAPUBFUN int sip_from_add_param(su_home_t *, sip_from_t *, char const *); /** Add a parameter to a @Via header object. */ SOFIAPUBFUN int sip_via_add_param(su_home_t *, sip_via_t *, char const *); #define sip_from_make_url sip_from_create #define sip_to_make_url sip_to_create #define sip_params_find msg_params_find SOFIA_END_DECLS #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sofia-sip/sip_parser.h000066400000000000000000000160311223300710500245600ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef SIP_PARSER_H /** Defined when has been included.*/ #define SIP_PARSER_H /**@ingroup sip_parser * @file sofia-sip/sip_parser.h * * SIP parser provider interface. * * This file contains functions and macros used to create a SIP parser using * generic text message parser, and to define new SIP header classes. * * @author Pekka Pessi . * * @date Created: Thu Mar 8 15:13:11 2001 ppessi */ #ifndef SU_ALLOC_H #include #endif #ifndef MSG_H #include #endif #ifndef MSG_PARSER_H #include #endif #ifndef SIP_H #include #endif #ifndef SIP_HEADER_H #include #endif #ifndef SOFIA_SIP_SU_STRING_H #include #endif SOFIA_BEGIN_DECLS /* --------------------------------------------------------------------------- * 1) Macros for defining boilerplate functions and structures for each header */ #define SIP_HDR_TEST(x) ((x)->sh_class) /** Define a header class for a SIP header. @HIDE */ #define SIP_HEADER_CLASS(c, l, s, params, kind, dup) \ MSG_HEADER_CLASS(sip_, c, l, s, params, kind, sip_ ## dup, sip_ ## dup) /** Define a header class for a critical SIP header. @HIDE */ #define SIP_HEADER_CLASS_C(c, l, s, params, kind, dup) \ MSG_HEADER_CLASS_C(sip_, c, l, s, params, kind, sip_ ## dup, sip_ ## dup) /** Define a header class for headers without any extra data to copy. @HIDE */ #define SIP_HEADER_CLASS_G(c, l, s, kind) \ MSG_HEADER_CLASS(sip_, c, l, s, g_common, kind, msg_generic, sip_null) /** Define a header class for a msg_list_t kind of header. @HIDE */ #define SIP_HEADER_CLASS_LIST(c, l, s, kind) \ MSG_HEADER_CLASS(sip_, c, l, s, k_items, kind, msg_list, sip_null) /** Define a authorization header class. @HIDE */ #define SIP_HEADER_CLASS_AUTH(c, l, kind) \ MSG_HEADER_CLASS(sip_, c, l, "", au_params, kind, msg_auth, sip_null) #define sip_null_update NULL #define sip_any_update NULL /* --------------------------------------------------------------------------- * 2) Prototypes for internal decoding/encoding functions */ /* Version string */ SOFIAPUBFUN int sip_version_d(char **ss, char const **ver); SOFIAPUBFUN isize_t sip_version_xtra(char const *version); SOFIAPUBFUN void sip_version_dup(char **pp, char const **dd, char const *s); /* Transport identifiers */ #define SIP_TRANSPORT_LEN(s) SIP_STRING_SIZE((s)) SOFIAPUBFUN issize_t sip_transport_d(char **ss, char const **ttransport); SOFIAPUBFUN isize_t sip_transport_xtra(char const *transport); SOFIAPUBFUN void sip_transport_dup(char **pp, char const **dd, char const *s); /* Method */ SOFIAPUBFUN sip_method_t sip_method_d(char **ss, char const **nname); /* Call-ID */ SOFIAPUBFUN char *sip_word_at_word_d(char **ss); /** Extract SIP message body, including separator line. */ SOFIAPUBFUN issize_t sip_extract_body(msg_t *, sip_t *, char b[], isize_t bsiz, int eos); SOFIAPUBFUN issize_t sip_any_route_d(su_home_t *, sip_header_t *, char *s, isize_t slen); SOFIAPUBFUN issize_t sip_any_route_e(char [], isize_t, sip_header_t const *, int flags); SOFIAPUBFUN isize_t sip_any_route_dup_xtra(sip_header_t const *h, isize_t offset); SOFIAPUBFUN char *sip_any_route_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra); #define sip_any_route_update NULL SOFIAPUBFUN issize_t sip_name_addr_d(su_home_t *home, char **inout_s, char const **return_display, url_t *out_url, msg_param_t const **return_params, char const **return_comment); SOFIAPUBFUN issize_t sip_name_addr_e(char b[], isize_t bsiz, int flags, char const *display, int always_ltgt, url_t const url[], msg_param_t const params[], char const *comment); SOFIAPUBFUN isize_t sip_name_addr_xtra(char const *display, url_t const *addr, msg_param_t const params[], isize_t offset); SOFIAPUBFUN char *sip_name_addr_dup(char const **d_display, char const *display, url_t *d_addr, url_t const *addr, msg_param_t const **d_params, msg_param_t const params[], char *b, isize_t xtra); /* --------------------------------------------------------------------------- * 3) Compatibility macros and functions */ #define sip_generic_d msg_generic_d #define sip_generic_e msg_generic_e #define sip_numeric_d msg_numeric_d #define sip_numeric_e msg_numeric_e #define sip_any_copy_xtra msg_default_copy_xtra #define sip_any_copy_one msg_default_copy_one #define sip_any_dup_xtra msg_default_dup_xtra #define sip_any_dup_one msg_default_dup_one #define sip_generic_dup_xtra msg_generic_dup_xtra #define sip_generic_dup_one msg_generic_dup_one #define sip_auth_d msg_auth_d #define sip_auth_e msg_auth_e #define sip_header_dup_as msg_header_dup_as #define sip_header_alloc msg_header_alloc #define sip_header_copy_as msg_header_copy_as #define SIP_ALIGN MSG_ALIGN #define SIP_STRUCT_SIZE_ALIGN MSG_STRUCT_SIZE_ALIGN #define SIP_STRUCT_ALIGN MSG_STRUCT_ALIGN #define sip_comment_d msg_comment_d #define sip_quoted_d(ss, qq) msg_quoted_d(ss, qq) #define SIP_CHAR_E MSG_CHAR_E #define SIP_STRING_LEN MSG_STRING_LEN #define SIP_STRING_E MSG_STRING_E #define SIP_STRING_DUP MSG_STRING_DUP #define SIP_STRING_SIZE MSG_STRING_SIZE #define SIP_NAME_E MSG_NAME_E /* Parameters */ #define SIP_PARAM_MATCH MSG_PARAM_MATCH #define SIP_PARAM_MATCH_P MSG_PARAM_MATCH_P /* Parameter lists */ #define SIP_N_PARAMS MSG_N_PARAMS #define sip_params_d msg_params_d #define sip_params_dup msg_params_dup #define SIP_PARAMS_NUM MSG_PARAMS_NUM #define SIP_PARAMS_E MSG_PARAMS_E #define SIP_PARAMS_SIZE MSG_PARAMS_SIZE #define sip_params_count msg_params_count #define sip_params_copy_xtra msg_params_copy_xtra #define sip_params_copy msg_params_copy SOFIAPUBFUN int sip_generic_xtra(sip_generic_t const *g); SOFIAPUBFUN sip_generic_t *sip_generic_dup(su_home_t *home, msg_hclass_t *hc, sip_generic_t const *u); SOFIAPUBFUN sip_generic_t *sip_generic_copy(su_home_t *home, msg_hclass_t *hc, sip_generic_t const *o); SOFIA_END_DECLS #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sofia-sip/sip_protos.h.in000066400000000000000000000242211223300710500252170ustar00rootroot00000000000000/**@file sofia-sip/sip_protos.h.in * * Template for . */ /* -*- C -*- * * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef SIP_PROTOS_H /** Defined when has been included. */ #define SIP_PROTOS_H /**@file sofia-sip/sip_protos.h * * SIP prototypes and macros for each header. * * #AUTO# * * @author Pekka Pessi . * */ #include #ifndef SIP_HEADER_H #include #endif #ifndef SIP_HCLASSES_H #include #endif SOFIA_BEGIN_DECLS #if SU_HAVE_INLINE /** Get SIP structure from msg. */ su_inline sip_t *sip_object(msg_t const *msg) { return (sip_t *)msg_public(msg, SIP_PROTOCOL_TAG); } /** Insert a (list of) header(s) to the header structure and fragment chain. * * The function @c sip_header_insert() inserts header or list of headers * into a SIP message. It also inserts them into the the message fragment * chain, if it exists. * * When inserting headers into the fragment chain, a request (or status) is * inserted first and replaces the existing request (or status). The Via * headers are inserted after the request or status, and rest of the headers * after request, status, or Via headers. * * If the header is a singleton, existing headers with the same class are * removed. * * @param msg message owning the fragment chain * @param sip SIP message structure to which header is added * @param h list of header(s) to be added */ su_inline int sip_header_insert(msg_t *msg, sip_t *sip, sip_header_t *h) { return msg_header_insert(msg, (msg_pub_t *)sip, (msg_header_t *)h); } /** Remove a header from a SIP message. */ su_inline int sip_header_remove(msg_t *msg, sip_t *sip, sip_header_t *h) { return msg_header_remove(msg, (msg_pub_t *)sip, (msg_header_t *)h); } /** Return name of the header. */ su_inline char const *sip_header_name(sip_header_t const *h, int compact) { if (compact && h->sh_class->hc_short[0]) return h->sh_class->hc_short; else return h->sh_class->hc_name; } /** Return data after header structure. */ su_inline void *sip_header_data(sip_header_t *h) { return h && h != SIP_NONE ? h->sh_class->hc_size + (char *)h : NULL; } #else sip_t *sip_object(msg_t *msg); int sip_header_insert(msg_t *msg, sip_t *sip, sip_header_t *h); int sip_header_remove(msg_t *msg, sip_t *sip, sip_header_t *h); char const *sip_header_name(sip_header_t const *h, int compact); void *sip_header_data(sip_header_t *h); #endif /**@addtogroup sip_#xxxxxx# * @{ */ /** Parse a SIP @ref sip_#xxxxxx# "#xxxxxxx_xxxxxxx#". @internal */ SOFIAPUBFUN issize_t sip_#xxxxxx#_d(su_home_t *, msg_header_t *, char *s, isize_t slen); /** Print a SIP @ref sip_#xxxxxx# "#xxxxxxx_xxxxxxx#". @internal */ SOFIAPUBFUN issize_t sip_#xxxxxx#_e(char b[], isize_t bsiz, msg_header_t const *h, int flags); /**Access a SIP @ref sip_#xxxxxx# "#xxxxxxx_xxxxxxx#" * structure #sip_#xxxxxx#_t from #sip_t. * * @since New in #version#. */ #define sip_#xxxxxx#(sip) \ ((sip_#xxxxxx#_t *)msg_header_access((msg_pub_t*)(sip), sip_#xxxxxx#_class)) /**Initializer for structure #sip_#xxxxxx#_t. * * A static #sip_#xxxxxx#_t structure for * @ref sip_#xxxxxx# "#xxxxxxx_xxxxxxx#" must be initialized with * the SIP_#XXXXXX#_INIT() macro. * For instance, * @code * * sip_#xxxxxx#_t sip_#xxxxxx# = SIP_#XXXXXX#_INIT; * * @endcode * @HI * * @since New in #version#. */ #define SIP_#XXXXXX#_INIT() SIP_HDR_INIT(#xxxxxx#) /**Initialize a structure #sip_#xxxxxx#_t. * * An #sip_#xxxxxx#_t structure for * @ref sip_#xxxxxx# "#xxxxxxx_xxxxxxx#" can be initialized with the * sip_#xxxxxx#_init() function/macro. For instance, * @code * * sip_#xxxxxx#_t sip_#xxxxxx#; * * sip_#xxxxxx#_init(&sip_#xxxxxx#); * * @endcode * @HI * * @since New in #version#. */ #if SU_HAVE_INLINE su_inline sip_#xxxxxx#_t *sip_#xxxxxx#_init(sip_#xxxxxx#_t x[1]) { return SIP_HEADER_INIT(x, sip_#xxxxxx#_class, sizeof(sip_#xxxxxx#_t)); } #else #define sip_#xxxxxx#_init(x) \ SIP_HEADER_INIT(x, sip_#xxxxxx#_class, sizeof(sip_#xxxxxx#_t)) #endif /**Test if header object is instance of #sip_#xxxxxx#_t. * * Check if the header class is an instance of * @ref sip_#xxxxxx# "#xxxxxxx_xxxxxxx#" object and return true (nonzero), * otherwise return false (zero). * * @param header pointer to the header structure to be tested * * @retval 1 (true) if the @a header is an instance of header #xxxxxx# * @retval 0 (false) otherwise * * @since New in #version#. */ #if SU_HAVE_INLINE su_inline int sip_is_#xxxxxx#(sip_header_t const *header) { return header && header->sh_class->hc_hash == sip_#xxxxxx#_hash; } #else int sip_is_#xxxxxx#(sip_header_t const *header); #endif #define sip_#xxxxxx#_p(h) sip_is_#xxxxxx#((h)) /**Duplicate a list of @ref sip_#xxxxxx# "#xxxxxxx_xxxxxxx#" header structures #sip_#xxxxxx#_t. * * Duplicate a header * structure @a hdr. If the header structure @a hdr * contains a reference (@c hdr->x_next) to a list of * headers, all the headers in the list are duplicated, too. * * @param home memory home used to allocate new structure * @param hdr header structure to be duplicated * * When duplicating, all parameter lists and non-constant * strings attached to the header are copied, too. The * function uses given memory @a home to allocate all the * memory areas used to copy the header. * * @par Example * @code * * #xxxxxx# = sip_#xxxxxx#_dup(home, sip->sip_#xxxxxx#); * * @endcode * * @return * A pointer to the * newly duplicated #sip_#xxxxxx#_t header structure, or NULL * upon an error. * * @since New in #version#. */ #if SU_HAVE_INLINE su_inline #endif sip_#xxxxxx#_t *sip_#xxxxxx#_dup(su_home_t *home, sip_#xxxxxx#_t const *hdr) __attribute__((__malloc__)); #if SU_HAVE_INLINE su_inline sip_#xxxxxx#_t *sip_#xxxxxx#_dup(su_home_t *home, sip_#xxxxxx#_t const *hdr) { return (sip_#xxxxxx#_t *) msg_header_dup_as(home, sip_#xxxxxx#_class, (msg_header_t const *)hdr); } #endif /**Copy a list of @ref sip_#xxxxxx# "#xxxxxxx_xxxxxxx#" header structures #sip_#xxxxxx#_t. * * The function sip_#xxxxxx#_copy() copies a header structure @a * hdr. If the header structure @a hdr contains a reference (@c * hdr->h_next) to a list of headers, all the headers in that * list are copied, too. The function uses given memory @a home * to allocate all the memory areas used to copy the list of header * structure @a hdr. * * @param home memory home used to allocate new structure * @param hdr pointer to the header structure to be copied * * When copying, only the header structure and parameter lists attached to * it are duplicated. The new header structure retains all the references to * the strings within the old @a hdr header, including the encoding of the * old header, if present. * * @par Example * @code * * #xxxxxx# = sip_#xxxxxx#_copy(home, sip->sip_#xxxxxx#); * * @endcode * * @return * A pointer to newly copied header structure, or NULL upon an error. * * @since New in #version#. */ #if SU_HAVE_INLINE su_inline #endif sip_#xxxxxx#_t *sip_#xxxxxx#_copy(su_home_t *home, sip_#xxxxxx#_t const *hdr) __attribute__((__malloc__)); #if SU_HAVE_INLINE su_inline sip_#xxxxxx#_t *sip_#xxxxxx#_copy(su_home_t *home, sip_#xxxxxx#_t const *hdr) { return (sip_#xxxxxx#_t *) msg_header_copy_as(home, sip_#xxxxxx#_class, (msg_header_t const *)hdr); } #endif /**Make a @ref sip_#xxxxxx# "#xxxxxxx_xxxxxxx#" structure #sip_#xxxxxx#_t. * * The function sip_#xxxxxx#_make() makes a new * #sip_#xxxxxx#_t header structure. It allocates a new * header structure, and decodes the string @a s as the * value of the structure. * * @param home memory home used to allocate new header structure. * @param s string to be decoded as value of the new header structure * * @return * A pointer to newly maked #sip_#xxxxxx#_t header structure, or NULL upon an * error. * * @since New in #version#. */ #if SU_HAVE_INLINE su_inline #endif sip_#xxxxxx#_t *sip_#xxxxxx#_make(su_home_t *home, char const *s) __attribute__((__malloc__)); #if SU_HAVE_INLINE su_inline sip_#xxxxxx#_t *sip_#xxxxxx#_make(su_home_t *home, char const *s) { return (sip_#xxxxxx#_t *)sip_header_make(home, sip_#xxxxxx#_class, s); } #endif /**Make a @ref sip_#xxxxxx# "#xxxxxxx_xxxxxxx#" from formatting result. * * Make a new #sip_#xxxxxx#_t object using formatting result as its value. * The function first prints the arguments according to the format @a fmt * specified. Then it allocates a new header structure, and parses the * formatting result to the structure #sip_#xxxxxx#_t. * * @param home memory home used to allocate new header structure. * @param fmt string used as a printf()-style format * @param ... argument list for format * * @return * A pointer to newly * makes header structure, or NULL upon an error. * * @HIDE * * @since New in #version#. */ #if SU_HAVE_INLINE su_inline #endif sip_#xxxxxx#_t *sip_#xxxxxx#_format(su_home_t *home, char const *fmt, ...) __attribute__((__malloc__, __format__ (printf, 2, 3))); #if SU_HAVE_INLINE su_inline sip_#xxxxxx#_t *sip_#xxxxxx#_format(su_home_t *home, char const *fmt, ...) { sip_header_t *h; va_list ap; va_start(ap, fmt); h = sip_header_vformat(home, sip_#xxxxxx#_class, fmt, ap); va_end(ap); return (sip_#xxxxxx#_t *)h; } #endif /** @} */ SOFIA_END_DECLS #endif /* !defined(SIP_PROTOS_H) */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sofia-sip/sip_status.h000066400000000000000000000251351223300710500246140ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef SIP_STATUS_H /** Defined when has been included. */ #define SIP_STATUS_H /**@addtogroup sip_status_codes * @{ */ /**@file sofia-sip/sip_status.h * * SIP status codes and standard phrases. * * @author Pekka Pessi . * * @date Created: Tue Jun 6 17:43:46 2000 ppessi */ #include SOFIA_BEGIN_DECLS SOFIAPUBFUN char const *sip_status_phrase(int status); /** 100 Trying @HIDE */ #define SIP_100_TRYING 100, sip_100_Trying /** 180 Ringing @HIDE */ #define SIP_180_RINGING 180, sip_180_Ringing /** 181 Call Is Being Forwarded @HIDE */ #define SIP_181_CALL_IS_BEING_FORWARDED 181, sip_181_Call_is_being_forwarded /** 182 Queued @HIDE */ #define SIP_182_QUEUED 182, sip_182_Queued /** 183 Session Progress @HIDE */ #define SIP_183_SESSION_PROGRESS 183, sip_183_Session_progress /** 200 OK @HIDE */ #define SIP_200_OK 200, sip_200_OK /** 202 Accepted @HIDE */ #define SIP_202_ACCEPTED 202, sip_202_Accepted /** 300 Multiple Choices @HIDE */ #define SIP_300_MULTIPLE_CHOICES 300, sip_300_Multiple_choices /** 301 Moved Permanently @HIDE */ #define SIP_301_MOVED_PERMANENTLY 301, sip_301_Moved_permanently /** 302 Moved Temporarily @HIDE */ #define SIP_302_MOVED_TEMPORARILY 302, sip_302_Moved_temporarily /** 305 Use Proxy @HIDE */ #define SIP_305_USE_PROXY 305, sip_305_Use_proxy /** 380 Alternative Service @HIDE */ #define SIP_380_ALTERNATIVE_SERVICE 380, sip_380_Alternative_service /** 400 Bad Request @HIDE */ #define SIP_400_BAD_REQUEST 400, sip_400_Bad_request /** 401 Unauthorized @HIDE */ #define SIP_401_UNAUTHORIZED 401, sip_401_Unauthorized /** 402 Payment Required @HIDE */ #define SIP_402_PAYMENT_REQUIRED 402, sip_402_Payment_required /** 403 Forbidden @HIDE */ #define SIP_403_FORBIDDEN 403, sip_403_Forbidden /** 404 Not Found @HIDE */ #define SIP_404_NOT_FOUND 404, sip_404_Not_found /** 405 Method Not Allowed @HIDE */ #define SIP_405_METHOD_NOT_ALLOWED 405, sip_405_Method_not_allowed /** 406 Not Acceptable @HIDE */ #define SIP_406_NOT_ACCEPTABLE 406, sip_406_Not_acceptable /** 407 Proxy Authentication Required @HIDE */ #define SIP_407_PROXY_AUTH_REQUIRED 407, sip_407_Proxy_auth_required /** 408 Request Timeout @HIDE */ #define SIP_408_REQUEST_TIMEOUT 408, sip_408_Request_timeout /** 409 Conflict @HIDE */ #define SIP_409_CONFLICT 409, sip_409_Conflict /** 410 Gone @HIDE */ #define SIP_410_GONE 410, sip_410_Gone /** 411 Length Required @HIDE */ #define SIP_411_LENGTH_REQUIRED 411, sip_411_Length_required /** 412 Precondition Failed @HIDE */ #define SIP_412_PRECONDITION_FAILED 412, sip_412_Precondition_failed /** 413 Request Entity Too Large @HIDE */ #define SIP_413_REQUEST_TOO_LARGE 413, sip_413_Request_too_large /** 414 Request-URI Too Long @HIDE */ #define SIP_414_REQUEST_URI_TOO_LONG 414, sip_414_Request_uri_too_long /** 415 Unsupported Media Type @HIDE */ #define SIP_415_UNSUPPORTED_MEDIA 415, sip_415_Unsupported_media /** 416 Unsupported URI Scheme @HIDE */ #define SIP_416_UNSUPPORTED_URI 416, sip_416_Unsupported_uri /** 417 Unknown Resource-Priority @HIDE */ #define SIP_417_RESOURCE_PRIORITY 417, sip_417_Resource_priority /** 420 Bad Extension @HIDE */ #define SIP_420_BAD_EXTENSION 420, sip_420_Bad_extension /** 421 Extension Required @HIDE */ #define SIP_421_EXTENSION_REQUIRED 421, sip_421_Extension_required /** 422 Session Timer Too Small @HIDE */ #define SIP_422_SESSION_TIMER_TOO_SMALL 422, sip_422_Session_timer /** 423 Interval Too Brief @HIDE */ #define SIP_423_INTERVAL_TOO_BRIEF 423, sip_423_Interval_too_brief #define SIP_423_REGISTRATION_TOO_BRIEF 423, sip_423_Interval_too_brief /** 480 Temporarily Unavailable @HIDE */ #define SIP_480_TEMPORARILY_UNAVAILABLE 480, sip_480_Temporarily_unavailable /** 481 Call/Transaction Does Not Exist @HIDE */ #define SIP_481_NO_TRANSACTION 481, sip_481_No_transaction #define SIP_481_NO_CALL 481, sip_481_No_transaction /** 482 Loop Detected @HIDE */ #define SIP_482_LOOP_DETECTED 482, sip_482_Loop_detected /** 483 Too Many Hops @HIDE */ #define SIP_483_TOO_MANY_HOPS 483, sip_483_Too_many_hops /** 484 Address Incomplete @HIDE */ #define SIP_484_ADDRESS_INCOMPLETE 484, sip_484_Address_incomplete /** 485 Ambiguous @HIDE */ #define SIP_485_AMBIGUOUS 485, sip_485_Ambiguous /** 486 Busy Here @HIDE */ #define SIP_486_BUSY_HERE 486, sip_486_Busy_here /** 487 Request Terminated @HIDE */ #define SIP_487_REQUEST_TERMINATED 487, sip_487_Request_terminated #define SIP_487_REQUEST_CANCELLED 487, sip_487_Request_terminated /** 488 Not acceptable here @HIDE */ #define SIP_488_NOT_ACCEPTABLE 488, sip_488_Not_acceptable /** 489 Bad Event @HIDE */ #define SIP_489_BAD_EVENT 489, sip_489_Bad_event /** 490 Request Updated @HIDE */ #define SIP_490_REQUEST_UPDATED 490, sip_490_Request_updated /** 491 Request Pending @HIDE */ #define SIP_491_REQUEST_PENDING 491, sip_491_Request_pending /** 493 Undecipherable @HIDE */ #define SIP_493_UNDECIPHERABLE 493, sip_493_Undecipherable /** 494 Security Agreement Required @HIDE */ #define SIP_494_SECAGREE_REQUIRED 494, sip_494_Secagree_required /** 500 Internal Server Error @HIDE */ #define SIP_500_INTERNAL_SERVER_ERROR 500, sip_500_Internal_server_error /** 501 Not Implemented @HIDE */ #define SIP_501_NOT_IMPLEMENTED 501, sip_501_Not_implemented /** 502 Bad Gateway @HIDE */ #define SIP_502_BAD_GATEWAY 502, sip_502_Bad_gateway /** 503 Service Unavailable @HIDE */ #define SIP_503_SERVICE_UNAVAILABLE 503, sip_503_Service_unavailable /** 504 Gateway Time-out @HIDE */ #define SIP_504_GATEWAY_TIME_OUT 504, sip_504_Gateway_time_out /** 505 Version Not Supported @HIDE */ #define SIP_505_VERSION_NOT_SUPPORTED 505, sip_505_Version_not_supported /** 513 Message Too Large @HIDE */ #define SIP_513_MESSAGE_TOO_LARGE 513, sip_513_Message_too_large /** 580 Precondition Failure @HIDE */ #define SIP_580_PRECONDITION 580, sip_580_Precondition /** 600 Busy Everywhere @HIDE */ #define SIP_600_BUSY_EVERYWHERE 600, sip_600_Busy_everywhere /** 603 Decline @HIDE */ #define SIP_603_DECLINE 603, sip_603_Decline /** 604 Does Not Exist Anywhere @HIDE */ #define SIP_604_DOES_NOT_EXIST_ANYWHERE 604, sip_604_Does_not_exist_anywhere /** 606 Not Acceptable @HIDE */ #define SIP_606_NOT_ACCEPTABLE 606, sip_606_Not_acceptable /** 687 Dialog terminated @HIDE */ #define SIP_687_DIALOG_TERMINATED 687, sip_687_Dialog_terminated SOFIAPUBVAR char const sip_100_Trying[]; SOFIAPUBVAR char const sip_180_Ringing[]; SOFIAPUBVAR char const sip_181_Call_is_being_forwarded[]; SOFIAPUBVAR char const sip_182_Queued[]; SOFIAPUBVAR char const sip_183_Session_progress[]; SOFIAPUBVAR char const sip_200_OK[]; SOFIAPUBVAR char const sip_202_Accepted[]; SOFIAPUBVAR char const sip_300_Multiple_choices[]; SOFIAPUBVAR char const sip_301_Moved_permanently[]; SOFIAPUBVAR char const sip_302_Moved_temporarily[]; SOFIAPUBVAR char const sip_305_Use_proxy[]; SOFIAPUBVAR char const sip_380_Alternative_service[]; SOFIAPUBVAR char const sip_400_Bad_request[]; SOFIAPUBVAR char const sip_401_Unauthorized[]; SOFIAPUBVAR char const sip_402_Payment_required[]; SOFIAPUBVAR char const sip_403_Forbidden[]; SOFIAPUBVAR char const sip_404_Not_found[]; SOFIAPUBVAR char const sip_405_Method_not_allowed[]; SOFIAPUBVAR char const sip_406_Not_acceptable[]; SOFIAPUBVAR char const sip_407_Proxy_auth_required[]; SOFIAPUBVAR char const sip_408_Request_timeout[]; SOFIAPUBVAR char const sip_409_Conflict[]; SOFIAPUBVAR char const sip_410_Gone[]; SOFIAPUBVAR char const sip_411_Length_required[]; SOFIAPUBVAR char const sip_412_Precondition_failed[]; SOFIAPUBVAR char const sip_413_Request_too_large[]; SOFIAPUBVAR char const sip_414_Request_uri_too_long[]; SOFIAPUBVAR char const sip_415_Unsupported_media[]; SOFIAPUBVAR char const sip_416_Unsupported_uri[]; SOFIAPUBVAR char const sip_417_Resource_priority[]; SOFIAPUBVAR char const sip_420_Bad_extension[]; SOFIAPUBVAR char const sip_421_Extension_required[]; SOFIAPUBVAR char const sip_422_Session_timer[]; SOFIAPUBVAR char const sip_423_Interval_too_brief[]; SOFIAPUBVAR char const sip_480_Temporarily_unavailable[]; SOFIAPUBVAR char const sip_481_No_transaction[]; SOFIAPUBVAR char const sip_482_Loop_detected[]; SOFIAPUBVAR char const sip_483_Too_many_hops[]; SOFIAPUBVAR char const sip_484_Address_incomplete[]; SOFIAPUBVAR char const sip_485_Ambiguous[]; SOFIAPUBVAR char const sip_486_Busy_here[]; SOFIAPUBVAR char const sip_487_Request_terminated[]; SOFIAPUBVAR char const sip_488_Not_acceptable[]; SOFIAPUBVAR char const sip_489_Bad_event[]; SOFIAPUBVAR char const sip_490_Request_updated[]; SOFIAPUBVAR char const sip_491_Request_pending[]; SOFIAPUBVAR char const sip_493_Undecipherable[]; SOFIAPUBVAR char const sip_494_Secagree_required[]; SOFIAPUBVAR char const sip_500_Internal_server_error[]; SOFIAPUBVAR char const sip_501_Not_implemented[]; SOFIAPUBVAR char const sip_502_Bad_gateway[]; SOFIAPUBVAR char const sip_503_Service_unavailable[]; SOFIAPUBVAR char const sip_504_Gateway_time_out[]; SOFIAPUBVAR char const sip_505_Version_not_supported[]; SOFIAPUBVAR char const sip_513_Message_too_large[]; SOFIAPUBVAR char const sip_580_Precondition[]; SOFIAPUBVAR char const sip_600_Busy_everywhere[]; SOFIAPUBVAR char const sip_603_Decline[]; SOFIAPUBVAR char const sip_604_Does_not_exist_anywhere[]; SOFIAPUBVAR char const sip_606_Not_acceptable[]; SOFIAPUBVAR char const sip_687_Dialog_terminated[]; SOFIA_END_DECLS #endif /** @} !defined(SIP_STATUS_H) */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sofia-sip/sip_tag.h.in000066400000000000000000000164551223300710500244560ustar00rootroot00000000000000/**@file sofia-sip/sip_tag.h.in * * Template for . * * @date Created: Wed Feb 21 11:01:45 2001 ppessi */ /* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef SIP_TAG_H /** Defined when has been included. */ #define SIP_TAG_H /**@file sofia-sip/sip_tag.h * @brief Tag class for SIP headers * * #AUTO# * * @author Pekka Pessi . * */ #ifndef SU_TAG_H #include #endif #ifndef SU_TAG_CLASS_H #include #endif #ifndef SIP_H #include #endif SOFIA_BEGIN_DECLS /** Test if tag type marks a sip_t structure. @HIDE */ #define SIPTAG_P(tt) ((tt)->tt_class == siphdrtag_class) /** Test if tag type marks a SIP header string. @HIDE */ #define SIPTAG_STR_P(tt) ((tt)->tt_class == sipstrtag_class) /** Test if tag type marks a SIP header structure. @HIDE */ #define SIPTAG_SIP_P(tt) ((tt)->tt_class == sipmsgtag_class) /** Test if tag item contains sip_t structure. @HIDE */ #define SIPTAGI_P(t) (SIPTAG_P((t)->t_tag)) /** Test if tag item contains a SIP header string. @HIDE */ #define SIPTAGI_STR_P(t) (SIPTAG_STR_P((t)->t_tag)) /** Test if tag item contains a SIP header structure. @HIDE */ #define SIPTAGI_SIP_P(t) (SIPTAG_SIP_P((t)->t_tag)) /** Tag class for SIP headers */ SOFIAPUBVAR tag_class_t siphdrtag_class[1]; /** Tag class for string values of SIP headers */ SOFIAPUBVAR tag_class_t sipstrtag_class[1]; /** Tag class for SIP message */ SOFIAPUBVAR tag_class_t sipmsgtag_class[1]; /** Lists of SIP tags. */ SOFIAPUBVAR tag_type_t sip_tag_list[], sip_tag_str_list[]; /** Filter tag matching any sip tag. */ #define SIPTAG_ANY() siptag_any, ((tag_value_t)0) SOFIAPUBVAR tag_typedef_t siptag_any; /** End of SIP headers */ #define SIPTAG_END() siptag_end, (tag_value_t)0 SOFIAPUBVAR tag_typedef_t siptag_end; /**Tag list item for #sip_t object. * * The SIPTAG_SIP() macro is used to include a tag item for a #sip_t struct * in the tag list. * * @param x pointer to a #sip_t message structure, or NULL. * * @HIDE */ #define SIPTAG_SIP(x) siptag_sip, siptag_sip_v((x)) /** Tag for @c sip_t */ SOFIAPUBVAR tag_typedef_t siptag_sip; #define SIPTAG_SIP_REF(x) siptag_sip_ref, siptag_sip_vr(&(x)) SOFIAPUBVAR tag_typedef_t siptag_sip_ref; #if SU_INLINE_TAG_CAST su_inline tag_value_t siptag_sip_v(sip_t const *v) { return (tag_value_t)v; } su_inline tag_value_t siptag_sip_vr(sip_t const **vp) { return (tag_value_t)vp; } #else #define siptag_sip_v(v) (tag_value_t)(v) #define siptag_sip_vr(vp) (tag_value_t)(vp) #endif /**Tag list item for header string. * * The SIPTAG_HEADER() macro is used to include a tag item containing an * unknown SIP header in the tag list, e.g., * @code * sip_header_t *hdr; * * SIPTAG_HEADER(hdr). * @endcode * * @param x pointer to a header structure, or NULL. * * @HIDE */ #define SIPTAG_HEADER(x) siptag_header, siptag_header_v((x)) /** Tag for header string */ SOFIAPUBVAR tag_typedef_t siptag_header; #define SIPTAG_HEADER_REF(x) siptag_header_ref, siptag_header_vr(&(x)) SOFIAPUBVAR tag_typedef_t siptag_header_ref; #if SU_INLINE_TAG_CAST su_inline tag_value_t siptag_header_v(sip_header_t const *v) { return (tag_value_t)v; } su_inline tag_value_t siptag_header_vr(sip_header_t const **vp) { return (tag_value_t)vp; } #else #define siptag_header_v(v) (tag_value_t)(v) #define siptag_header_vr(vp) (tag_value_t)(vp) #endif /**Tag list item for header string. * * Macro is used to include a tag item containing an unknown extension * header in the tag list, e.g., * @code * SIPTAG_HEADER_STR("P-Alternative-URL: <+358718008000>") * @endcode * * It is also possible to include multiple headers at once * @code * SIPTAG_HEADER_STR("P-Access-Network-Info: IEEE-802.11g;" * " access-point-id=00:11:5C:34:E5:C0\r\n" " "P-Visited-Network-ID: other.net\r\n") * @endcode * * (See @RFC3455 for more information about these headers.) * * @param s pointer to a string, or NULL. * * The corresponding tag item taking reference parameter is * SIPTAG_HEADER_STR_REF(). * * @HIDE */ #define SIPTAG_HEADER_STR(s) siptag_header_str, tag_str_v((s)) /** Tag for header string */ SOFIAPUBVAR tag_typedef_t siptag_header_str; #define SIPTAG_HEADER_STR_REF(s) siptag_header_str_ref, tag_str_vr(&(s)) SOFIAPUBVAR tag_typedef_t siptag_header_str_ref; /**@ingroup sip_#xxxxxx# * * Tag list item for pointer to a @ref sip_#xxxxxx# "#xxxxxxx_xxxxxxx#" * structure #sip_#xxxxxx#_t. * * The SIPTAG_#XXXXXX#() macro is used to include a tag item with a * pointer to a #sip_#xxxxxx#_t structure in a tag list. * * @param x pointer to a #sip_#xxxxxx#_t structure, or NULL. * * The corresponding tag taking reference parameter is * SIPTAG_#XXXXXX#_REF(). * * @since New in #version#. * * @HIDE */ #define SIPTAG_#XXXXXX#(x) siptag_#xxxxxx#, siptag_#xxxxxx#_v(x) SOFIAPUBVAR tag_typedef_t siptag_#xxxxxx#; /**@ingroup sip_#xxxxxx# * Tag list item for reference to a * @ref sip_#xxxxxx# "#xxxxxxx_xxxxxxx#" pointer. */ #define SIPTAG_#XXXXXX#_REF(x) siptag_#xxxxxx#_ref, siptag_#xxxxxx#_vr(&(x)) SOFIAPUBVAR tag_typedef_t siptag_#xxxxxx#_ref; /**@ingroup sip_#xxxxxx# * * Tag list item for string with @ref sip_#xxxxxx# "#xxxxxxx_xxxxxxx#" value. * * The SIPTAG_#XXXXXX#_STR() macro is used to include a tag item with a * string containing value of a #sip_#xxxxxx#_t header in a tag list. * * @param s pointer to a string containing * @ref sip_#xxxxxx# "#xxxxxxx_xxxxxxx#" value, or NULL. * * The string in SIPTAG_#XXXXXX#_STR() can be converted to a * #sip_#xxxxxx#_t header structure by giving the string @a s has * second argument to function sip_#xxxxxx#_make(). * * The corresponding tag taking reference parameter is * SIPTAG_#XXXXXX#_STR_REF(). * * @since New in #version#. * * @HIDE */ #define SIPTAG_#XXXXXX#_STR(s) siptag_#xxxxxx#_str, tag_str_v(s) SOFIAPUBVAR tag_typedef_t siptag_#xxxxxx#_str; /**@ingroup sip_#xxxxxx# * Tag list item for reference to a * @ref sip_#xxxxxx# "#xxxxxxx_xxxxxxx#" string. */ #define SIPTAG_#XXXXXX#_STR_REF(x) siptag_#xxxxxx#_str_ref, tag_str_vr(&(x)) SOFIAPUBVAR tag_typedef_t siptag_#xxxxxx#_str_ref; #if SU_INLINE_TAG_CAST su_inline tag_value_t siptag_#xxxxxx#_v(sip_#xxxxxx#_t const *v) { return (tag_value_t)v; } su_inline tag_value_t siptag_#xxxxxx#_vr(sip_#xxxxxx#_t const **vp) { return (tag_value_t)vp; } #else #define siptag_#xxxxxx#_v(v) (tag_value_t)(v) #define siptag_#xxxxxx#_vr(vp) (tag_value_t)(vp) #endif SOFIA_END_DECLS #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sofia-sip/sip_tag_class.h000066400000000000000000000051701223300710500252260ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef SIP_TAG_CLASS_H /** Defined when have been included */ #define SIP_TAG_CLASS_H /**@SIP_TAG @{ */ /**@file sofia-sip/sip_tag_class.h * * @brief Tag classes for SIP headers. * * @author Pekka Pessi . * * @date Created: Wed Feb 21 11:01:45 2001 ppessi */ #ifndef SU_TAG_CLASS_H #include #endif #ifndef MSG_TAG_CLASS_H #include #endif SOFIA_BEGIN_DECLS /** Define a named tag type for SIP header @a t. */ #define SIPHDRTAG_NAMED_TYPEDEF(n, t) \ {{ TAG_NAMESPACE, #n, siphdrtag_class, \ (tag_value_t)sip_##t##_class }} /** Define a tag type for SIP header @a t. @HIDE */ #define SIPHDRTAG_TYPEDEF(t) SIPHDRTAG_NAMED_TYPEDEF(t, t) /** Define a string tag type for SIP header @a t. @HIDE */ #define SIPSTRTAG_TYPEDEF(t) \ {{ TAG_NAMESPACE, #t "_str", sipstrtag_class, \ (tag_value_t)sip_##t##_class }} /** Define a tag type for SIP message @a t. @HIDE */ #define SIPMSGTAG_TYPEDEF(t) \ {{ TAG_NAMESPACE, #t, sipmsgtag_class, \ (tag_value_t)SIP_PROTOCOL_TAG }} /** Tag class for SIP headers */ SOFIAPUBVAR tag_class_t siphdrtag_class[1]; /** Tag class for string values of SIP headers */ SOFIAPUBVAR tag_class_t sipstrtag_class[1]; /** Tag class for SIP message */ SOFIAPUBVAR tag_class_t sipmsgtag_class[1]; /** Define a named tag type using structure of SIP header @a t. */ #define SIPEXTHDRTAG_TYPEDEF(n, t) \ {{ TAG_NAMESPACE, #n, sipexthdrtag_class, \ (tag_value_t)sip_##t##_class }} /** Tag class using SIP header structure */ SOFIAPUBVAR tag_class_t sipexthdrtag_class[1]; /**@internal Filter SIP header tag items. */ SOFIAPUBFUN tagi_t *siptag_filter(tagi_t *dst, tagi_t const f[], tagi_t const *src, void **bb); SOFIA_END_DECLS #endif sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/sofia-sip/sip_util.h000066400000000000000000000136721223300710500242510ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ #ifndef SIP_UTIL_H /** Defined when has been included. */ #define SIP_UTIL_H /**@file sofia-sip/sip_util.h * @brief SIP utility functions * * @author Pekka Pessi . * * @date Created: Thu Jun 8 19:28:55 2000 ppessi */ #ifndef SIP_H #include #endif #ifndef STRING0_H #include #endif #ifndef MSG_HEADER_H #include #endif SOFIA_BEGIN_DECLS SOFIAPUBFUN sip_contact_t * sip_contact_create_from_via_with_transport(su_home_t *home, sip_via_t const *v, char const *user, char const *transport); SOFIAPUBFUN sip_contact_t *sip_contact_create_from_via(su_home_t *, sip_via_t const *, char const *user); SOFIAPUBFUN char * sip_contact_string_from_via(su_home_t *home, sip_via_t const *v, char const *user, char const *transport); SOFIAPUBFUN int sip_transport_has_tls(char const *transport_name); SOFIAPUBFUN int sip_response_terminates_dialog(int response_code, sip_method_t method, int *return_graceful_terminate); SOFIAPUBFUN int sip_sanity_check(sip_t const *sip); SOFIAPUBFUN unsigned sip_q_value(char const * q); SOFIAPUBFUN url_t *sip_url_dup(su_home_t *sh, url_t const *o); /**Add optional prefix and string to argument list if @a s is non-NULL. * @HIDE */ #define SIP_STRLOG(prefix, s) ((s) ? (prefix) : ""), ((s) ? (s) : "") SOFIAPUBFUN int sip_addr_match(sip_addr_t const *a, sip_addr_t const *b); /* ---------------------------------------------------------------------- * Header-specific functions below */ SOFIAPUBFUN int sip_route_is_loose(sip_route_t const *r); SOFIAPUBFUN sip_route_t *sip_route_remove(msg_t *msg, sip_t *sip); SOFIAPUBFUN sip_route_t *sip_route_pop(msg_t *msg, sip_t *sip); SOFIAPUBFUN sip_route_t *sip_route_follow(msg_t *msg, sip_t *sip); SOFIAPUBFUN sip_route_t *sip_route_reverse(su_home_t *, sip_route_t const *); SOFIAPUBFUN sip_route_t *sip_route_fixdup(su_home_t *, sip_route_t const *); SOFIAPUBFUN sip_route_t *sip_route_fix(sip_route_t *route); SOFIAPUBFUN sip_route_t *sip_route_fixdup_as(su_home_t *, msg_hclass_t *, sip_route_t const *); SOFIAPUBFUN sip_route_t *sip_route_reverse_as(su_home_t *, msg_hclass_t *, sip_route_t const *); SOFIAPUBFUN sip_via_t *sip_via_remove(msg_t *msg, sip_t *sip); /* ---------------------------------------------------------------------- */ /* Caller preferences */ /** Check callerprefs. */ SOFIAPUBFUN int sip_prefs_matching(char const *pvalue, char const *nvalue, int *return_parse_error); SOFIAPUBFUN int sip_is_callerpref(char const *param); /** Type of the SIP media tag */ enum sp_type { sp_error = -1, sp_init, sp_literal, sp_string, sp_range, }; /** Possible values for SIP media tags */ union sip_pref { /** Type of the media tag */ enum sp_type sp_type; /** Literal (tag="foo"). */ struct sp_literal { enum sp_type spl_type; char const *spl_value; usize_t spl_length; } sp_literal; /** String (tag="<foo>"). */ /* (tag="") */ struct sp_string { enum sp_type sps_type; char const *sps_value; usize_t sps_length; } sp_string; /** Numeric value or range (tag="#=1"; tag="#<=3"; tag="#>=-2"; tag="#1:6"). */ struct sp_range { enum sp_type spr_type; double spr_lower; /**< Lower limit. Lowest value is -DBL_MAX. */ double spr_upper; /**< Upper limit. Highest value is DBL_MAX. */ } sp_range; }; /** Parse a single preference */ SOFIAPUBFUN int sip_prefs_parse(union sip_pref *sp, char const **in_out_s, int *return_negation); /** Match preferences */ SOFIAPUBFUN int sip_prefs_match(union sip_pref const *, union sip_pref const *); SOFIAPUBFUN int sip_contact_is_immune(sip_contact_t const *m); /**@internal * Check if contact is immune to calleprefs. * @deprecated Use sip_contact_is_immune() instead. */ #define sip_contact_immune(m) sip_contact_is_immune(m) SOFIAPUBFUN sip_contact_t *sip_contact_immunize(su_home_t *home, sip_contact_t const *m); SOFIAPUBFUN int sip_contact_reject(sip_contact_t const *m, sip_reject_contact_t const *rc); SOFIAPUBFUN int sip_contact_accept(sip_contact_t const *m, sip_accept_contact_t const *cp, unsigned *return_S, unsigned *return_N, int *return_error); SOFIAPUBFUN int sip_contact_score(sip_contact_t const *m, sip_accept_contact_t const *ac, sip_reject_contact_t const *rc); SOFIAPUBFUN int sip_aor_strip(url_t *url); /* sec-agree utility functions. */ SOFIAPUBFUN int sip_security_verify_compare(sip_security_server_t const *s, sip_security_verify_t const *v, char const **return_d_ver); SOFIAPUBFUN sip_security_client_t const * sip_security_client_select(sip_security_client_t const *client, sip_security_server_t const *server); /* Compatibility stuff */ #define sip_params_add msg_params_add #define sip_params_cmp msg_params_cmp #define sip_params_replace msg_params_replace #define sip_params_find msg_params_find SOFIA_END_DECLS #endif /** !defined(SIP_UTIL_H) */ sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/test_date.c000066400000000000000000000052531223300710500224720ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@internal * * @CFILE test_date.c * * Tester for SIP date parser * * @author Pekka Pessi . * * @date Wed Mar 21 19:12:13 2001 ppessi */ #include "config.h" #include #include #include #include #include #include #include void usage(int exitcode) { fprintf(stderr, "usage: test_date [SIP-date] " "[YYYYy][DDd][HHh][MMm][SS[s]]\n"); exit(exitcode); } int main(int ac, char *av[]) { int i; sip_time_t t, delta, t2; char const *s; int verbatim = 0, retval = 0; t = ((31 + 27) * 24) * 60 * 60; delta = (365 * 24 + 6) * 60 * 60; if (su_strmatch(av[1], "-v")) verbatim = 1, av++; if ((s = av[1])) { if (msg_date_d(&s, &t) < 0) { fprintf(stderr, "test_date: %s is not valid time\n", s); exit(1); } if ((s = av[2])) { for (delta = 0; *s; ) { t2 = 0; msg_delta_d(&s, &t2); switch (*s++) { case 'y': delta += t2 * (365 * 24 + 6) * 60 * 60; break; case 'd': delta += t2 * 24 * 60 * 60; break; case 'h': delta += t2 * 60 * 60; break; case 'm': delta += t2 * 60; break; case '\0': --s; /* FALLTHROUGH */ case 's': delta += t2; break; default: fprintf(stderr, "test_date: %s is not valid time offset\n" , av[2]); usage(1); break; } } } } for (i = 0; i < 20; i++) { char buf[80]; msg_date_e(buf, sizeof(buf), t); if (verbatim) printf("%08lx is %s\n", t, buf); s = buf, t2 = 0; if (msg_date_d(&s, &t2) < 0) { fprintf(stderr, "test_date: decoding %s failed\n", buf); retval = 1; break; } else if (t2 != t) { fprintf(stderr, "test_date: %lu != %lu\n", t, t2); retval = 1; break; } t += delta; } return retval; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/test_sip_msg.c000066400000000000000000000155411223300710500232170ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@SIP_PARSER * * @file test_sip_msg.c Simple SIP message parser/printer tester. * * @author Pekka Pessi . * * @date Created: Fri Feb 18 10:25:08 2000 ppessi */ #include "config.h" /* Avoid casting sip_t to msg_pub_t and sip_header_t to msg_header_t */ #define MSG_PUB_T struct sip_s #define MSG_HDR_T union sip_header_u #include "sofia-sip/sip_parser.h" #include "sofia-sip/msg_mclass.h" #include "sofia-sip/msg_mclass_hash.h" #include #include #include #include #include #include #include #include int diff(const char *olds, const char *news, int *linep, int *pos) { const char *o, *n; *linep = 0; for (o = olds, n = news; *o && *n && *o == *n ; o++, n++) { if (*o == '\n') ++*linep; } *pos = o - olds; return *o != *n; } int test_msg_class(msg_mclass_t const *mc) { int i, j, N; N = mc->mc_hash_size; /* Check parser table sanity */ for (i = 0; i < N; i++) { /* Verify each header entry */ msg_hclass_t *hc = mc->mc_hash[i].hr_class; if (hc == NULL) continue; /* Short form */ if (hc->hc_short[0]) assert(mc->mc_short[hc->hc_short[0] - 'a'].hr_class == hc); /* Long form */ for (j = MC_HASH(hc->hc_name, N); j != i; j = (j + 1) % N) assert(mc->mc_hash[j].hr_class); } return 0; } char * url_print(url_t *url, char buf[1024]) { url_e(buf, 1024, url); return buf; } void print_contact(FILE *f, sip_contact_t *m) { char const * const *p; char buf[1024]; const char *sep = "\tContact: "; for (;m; m = m->m_next) { int quoted_url = 0; fputs(sep, f); sep = ", "; if (m->m_display) { quoted_url = 1; fprintf(f, "\"%s\" <", m->m_display); } url_print(m->m_url, buf); if (!quoted_url && strpbrk(buf, ",;?")) { fputs("<", f); } fputs(buf, f); if (quoted_url) fputs(">", f); if (m->m_params) for (p = m->m_params; *p; p++) fprintf(f, " ;%s", *p); if (m->m_comment) fprintf(f, " (%s)", m->m_comment); } fputs("\n", f); } void print_via(FILE *f, sip_via_t *v) { char const * const *p; char const * sep = "\tVia: "; for (;v; v = v->v_next) { fputs(sep, f); sep = ", "; fprintf(f, "%s %s", v->v_protocol, v->v_host); if (v->v_port) fprintf(f, ":%s", v->v_port); if (v->v_params) for (p = v->v_params; *p; p++) fprintf(f, " ;%s", *p); if (v->v_comment) fprintf(f, " (%s)", v->v_comment); } fputs("\n", f); } int main(int argc, char *argv[]) { char urlbuf[1024]; size_t n; int m, tcp; sip_t *sip; int exitcode = 0; msg_mclass_t const *sip_mclass = sip_default_mclass(); msg_t *msg = msg_create(sip_mclass, MSG_FLG_EXTRACT_COPY); msg_iovec_t iovec[1]; tcp = argv[1] && strcmp(argv[1], "-t") == 0; test_msg_class(sip_mclass); for (n = 0, m = 0;;) { if (msg_recv_iovec(msg, iovec, 1, 1, 0) < 0) { perror("msg_recv_iovec"); exit(1); } assert(iovec->mv_len >= 1); n = read(0, iovec->mv_base, 1); if (n < 0) { perror("test_sip_msg read"); exit(1); } msg_recv_commit(msg, n, n == 0); if (tcp) m = msg_extract(msg); if (n == 0 || m < 0) break; } if (!tcp) m = msg_extract(msg); sip = msg_object(msg); if (sip) fprintf(stdout, "sip flags = %x\n", sip->sip_flags); if (m < 0) { fprintf(stderr, "test_sip_msg: parsing error ("MOD_ZD")\n", n); exit(1); } if (sip->sip_flags & MSG_FLG_TRUNC) { fprintf(stderr, "test_sip_msg: message truncated\n"); exit(1); } if (msg_next(msg)) { fprintf(stderr, "test_sip_msg: stuff after message\n"); exit(1); } #if 0 fprintf(stderr, "test_sip_msg: %d headers (%d short ones), %d unknown\n", msg->mh_n_headers, msg->mh_n_short, msg->mh_n_unknown); if (msg->mh_payload) { fprintf(stderr, "\twith payload of %d bytes\n", msg->mh_payload->pl_len); } #endif if (MSG_HAS_ERROR(sip->sip_flags) || sip->sip_error) { fprintf(stderr, "test_sip_msg: parsing error\n"); exit(1); } else if (sip_sanity_check(sip) < 0) { fprintf(stderr, "test_sip_msg: message failed sanity check\n"); exit(1); } if (sip->sip_request) { fprintf(stdout, "\trequest %s (%d) %s %s\n", sip->sip_request->rq_method_name, sip->sip_request->rq_method, url_print(sip->sip_request->rq_url, urlbuf), sip->sip_request->rq_version); if (sip->sip_request->rq_url->url_type == url_unknown) { exitcode = 1; fprintf(stderr, "test_sip_msg: invalid request URI\n"); } } if (sip->sip_status) fprintf(stdout, "\tstatus %s %03d %s\n", sip->sip_status->st_version, sip->sip_status->st_status, sip->sip_status->st_phrase); if (sip->sip_cseq) fprintf(stdout, "\tCSeq: %u %s (%d)\n", sip->sip_cseq->cs_seq, sip->sip_cseq->cs_method_name, sip->sip_cseq->cs_method); if (sip->sip_call_id) fprintf(stdout, "\tCall-ID: %s (%x)\n", sip->sip_call_id->i_id, sip->sip_call_id->i_hash); if (sip->sip_from) fprintf(stdout, "\tFrom: %s@%s%s%s\n", sip->sip_from->a_user ? sip->sip_from->a_user : "[nobody]", sip->sip_from->a_host ? sip->sip_from->a_host : "[nowhere]", sip->sip_from->a_tag ? " ;tag=" : "", sip->sip_from->a_tag ? sip->sip_from->a_tag : ""); if (sip->sip_to) fprintf(stdout, "\tTo: %s@%s%s%s\n", sip->sip_to->a_user ? sip->sip_to->a_user : "[nobody]", sip->sip_to->a_host ? sip->sip_to->a_host : "[nowhere]", sip->sip_to->a_tag ? " ;tag=" : "", sip->sip_to->a_tag ? sip->sip_to->a_tag : ""); if (sip->sip_contact) print_contact(stdout, sip->sip_contact); if (sip->sip_via) print_via(stdout, sip->sip_via); if (sip->sip_content_length) { fprintf(stdout, "\tcontent length %u\n", sip->sip_content_length->l_length); } if (msg_next(msg)) { fprintf(stderr, "test_sip_msg: extra stuff after valid message\n"); exit(1); } return exitcode; } sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/000077500000000000000000000000001223300710500215075ustar00rootroot00000000000000sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/own0.txt000066400000000000000000000036301223300710500231350ustar00rootroot00000000000000REGISTER sip:garage.sr.ntc.nokia.com SIP/2.0 Via: SIP/2.0/UDP srlab.sr.ntc.nokia.com:5060;maddr=192.168.102.5 Via: SIP/2.0/TCP srlab.sr.ntc.nokia.com:5060;maddr=192.168.102.5 (NTA 1.0) Via: SIP/2.0/UDP 192.2.2.1:5060;received=[ffe0::FAB1] Route: ;foo=bar Record-Route: Hide: route Max-Forwards: 15 From: sip:digest@garage.sr.ntc.nokia.com To: sip:digest@garage.sr.ntc.nokia.com Contact: sip:digest@172.21.9.155 Call-ID: 982773899-reg@172.21.9.155 CSeq: 2 REGISTER Subject: Barfoo Priority: emergency Date: Wed, 04 Apr 2001 17:38:38 GMT Retry-After: Wed, 04 Apr 2001 19:00:00 GMT (wake-up) ;duration=1800 Timestamp: 986395257.13924321 3 Expires: 180 Also: sip:digestify@garage.sr.ntc.nokia.com Call-Info: ;purpose=icon Organization: Fuzzy Felines, Inc. Server: please User-Agent: Nokia Universal Killer Internet Application/2.0 (NUUKIA) In-Reply-To: 982773898-reg@172.21.9.155 Accept: text/plain Accept-Encoding: identity, deflate (???) Accept-Language: en Allow: any Require: all Proxy-Require: kinky, things Supported: sip-cc, sip-cc-01, timer Unsupported: everything Error-Info: Warning: 300 garage.sr.ntc.nokia.com IPv6 global addresses not available Warning: 330 garage.sr.ntc.nokia.com No IPv6 multicast, 330 garage.sr.ntc.nokia.com Only local IPv4 multicast available Authorization: Digest USERNAME="digest", REALM="garage.sr.ntc.nokia.com", NONCE="MjAwMS0wMS0yMSAxNTowODo1OA==", RESPONSE="d9d7f1ae99a013cb05f319f0f678251d", URI="sip:garage.sr.ntc.nokia.com" Via: SIP/2.0/UDP 172.21.9.155 MIME-Version: 1.0 Content-Type: text/plain;charset=US-ASCII Content-Encoding: identity Content-Disposition: render;handling=optional Content-Length: 31 xxxxxxxxxxxxxxxxxxxxxxxxxxxxx sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/own1.txt000066400000000000000000000010371223300710500231350ustar00rootroot00000000000000INVITE sip:John_Smith@tct.hut.fi SIP/2.0 To: John Smith ; tag = deadbeef From: http://www.cs.columbia.edu Call-ID: 0ha0isndaksdj@10.1.2.3 CSeq : 8 INVITE Via: SIP/2.0/UDP 135.180.130.133 Content-Type: application/sdp Contact: Joe Bob Briggs ; bar="foo baa", sip:kuik@foo.invalid Via: SIP/2.0/UDP [aa:bb::1]:5061 l: 138 v=0 o=mhandley 29739 7272939 IN IP4 126.5.4.3 c=IN IP4 135.180.130.88 m=audio 492170 RTP/AVP 0 12 m=video 3227 RTP/AVP 31 a=rtpmap:31 LPC sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/own2.txt000066400000000000000000000007331223300710500231400ustar00rootroot00000000000000SIP/2.0 401 Unauthorized Via: SIP/2.0/UDP srlab.sr.ntc.nokia.com:5060;maddr=192.168.102.5 Via: SIP/2.0/UDP 172.21.9.155 Record-Route: From: sip:digest@garage.sr.ntc.nokia.com To: sip:digest@garage.sr.ntc.nokia.com Call-ID: 982773899-reg@172.21.9.155 CSeq: 1 REGISTER WWW-Authenticate: Digest realm="garage.sr.ntc.nokia.com", nonce="MjAwMS0wMS0yMSAxNTowODo1OA==", algorithm=MD5, qop="auth" Content-Length: 0 sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/own3.txt000066400000000000000000000012771223300710500231450ustar00rootroot00000000000000REGISTER sip:garage.sr.ntc.nokia.com SIP/2.0 Via: SIP/2.0/UDP srlab.sr.ntc.nokia.com:5060;maddr=192.168.102.5 Record-Route: From: sip:digest@garage.sr.ntc.nokia.com To: sip:digest@garage.sr.ntc.nokia.com Call-Id: 982773899-reg@172.21.9.155 Cseq: 2 REGISTER Contact: sip:digest@172.21.9.155 Expires: 180 Content-Length: 0 Accept-Language: en Supported: sip-cc, sip-cc-01, timer User-Agent: Pingtel/0.8.0 (WinNT) Authorization: DIGEST USERNAME="digest", REALM="garage.sr.ntc.nokia.com", NONCE="MjAwMS0wMS0yMSAxNTowODo1OA==", RESPONSE="d9d7f1ae99a013cb05f319f0f678251d", URI="sip:garage.sr.ntc.nokia.com" Via: SIP/2.0/UDP 172.21.9.155 sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/own4.txt000066400000000000000000000012771223300710500231460ustar00rootroot00000000000000REGISTER sip:garage.sr.ntc.nokia.com SIP/2.0 Via: SIP/2.0/UDP srlab.sr.ntc.nokia.com:5060;maddr=192.168.102.5 Record-Route: From: sip:digest@garage.sr.ntc.nokia.com To: sip:digest@garage.sr.ntc.nokia.com Call-Id: 982773899-reg@172.21.9.155 Cseq: 2 REGISTER Contact: sip:digest@172.21.9.155 Expires: 180 Content-Length: 0 Accept-Language: en Supported: sip-cc, sip-cc-01, timer User-Agent: Pingtel/0.8.0 (WinNT) Authorization: Digest USERNAME="digest", REALM="garage.sr.ntc.nokia.com", NONCE="MjAwMS0wMS0yMSAxNTowODo1OA==", RESPONSE="d9d7f1ae99a013cb05f319f0f678251d", URI="sip:garage.sr.ntc.nokia.com" Via: SIP/2.0/UDP 172.21.9.155 sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/own5.txt000066400000000000000000000020771223300710500231460ustar00rootroot00000000000000INVITE sip:bob@[3ffe:1200:3012:c006:206:5bff:fe55:462f] SIP/2.0 Via: SIP/2.0/UDP [3ffe:1200:3012:c000:0030:e0ff:fe40:6297]:5062 ;branch=z9hG4bKuNCTHs8Lumv ;received=3ffe:1200:3012:c006:0030:e0ff:fe40:6297 Via: SIP/2.0/UDP [3ffe:1200:3012:c000:210:a4ff:fe8d:6a46]:5062 ;branch=z9hG4bKuNCTHs8Lumv ;received=[3ffe:1200:3012:c006:210:a4ff:fe8d:6a46] From: ;tag=ud6a29947 To: Call-ID: f89fa68e-5109-11d6-0581-0010A48D6A46 CSeq: 2 INVITE Contact: Call-Info: ;purpose=icon;g-param=[3ffe:1200:3012:c000:210:a4ff:fe8d:6a46] Content-Type: application/sdp Content-Length: 239 v=0 o=alice 1804289383 2 IN IP6 3ffe:1200:3012:c000:210:a4ff:fe8d:6a46 s=- c=IN IP6 3ffe:1200:3012:c000:210:a4ff:fe8d:6a46 t=0 0 m=audio 5004 RTP/AVP 96 97 98 a=rtpmap:96 AMR/8000 a=rtpmap:97 AMR-WB/16000 a=rtpmap:98 GSM-EFR/8000 sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/own6.txt000066400000000000000000000011351223300710500231410ustar00rootroot00000000000000OPTIONS sip:bob@example.com SIP/2.0 Via: SIP/2.0/UDP 172.21.40.44;branch=z9hG4bKitIIzAialKS Via: SIP/2.0/UDP [3ffe:1200:3012:c000:210:a4ff:fe8d:6a46]:5062 ;branch=z9hG4bKJv+PsUQdfOb ;received=172.21.40.24 Record-Route: Record-Route: From: ;tag=ud6a29947 To: Call-ID: f3359e42-5109-11d6-998d-0010a47e1c0f CSeq: 1 OPTIONS Contact: Content-Length: 0 Accept: Allow: sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/own8.txt000066400000000000000000000000221223300710500231350ustar00rootroot00000000000000JUNK * SIP/1.0 sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test-ack-1.txt000066400000000000000000000003361223300710500241230ustar00rootroot00000000000000ACK sip:company.com SIP/2.0 To: sip:j.user@company.com From: sip:j.user@company.com Call-ID: 0ha0isndaksdj@10.0.2.2 Contact: sip:j.user@host.company.com CSeq: 8 NEWMETHOD Via: SIP/2.0/UDP 135.180.130.133 Content-Length: 0 sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test1.txt000066400000000000000000000012561223300710500233140ustar00rootroot00000000000000INVITE sip:vivekg@chair.dnrc.bell-labs.com SIP/2.0 To : sip:vivekg@chair.dnrc.bell-labs.com ; tag = 1a1b1f1H33n From : "J Rosenberg \\\"" ; tag = 98asjd8 CaLl-Id : 0ha0isndaksdj@10.1.1.1 cseq: 8 INVITE Via : SIP / 2.0/ UDP 135.180.130.133 Subject : NewFangledHeader: newfangled value more newfangled value Content-Type: application/sdp v: SIP / 2.0 / TCP 12.3.4.5 ; branch = 9ikj8 , SIP / 2.0 / UDP 1.2.3.4 ; hidden m:"Quoted string \"\"" ; newparam = newvalue ; secondparam = secondvalue ; q = 0.33 (((nested comments) and (more))) , tel:4443322 sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test10.txt000066400000000000000000000011031223300710500233630ustar00rootroot00000000000000REGISTER sip:company.com SIP/2.0 To: sip:j.user@company.com From: sip:j.user@company.com Call-ID: 0ha0isndaksdj@10.0.2.2 Contact: sip:j.user@host.company.com CSeq: 8 REGISTER Via: SIP/2.0/UDP 135.180.130.133 Content-Length: 0 INVITE sip:joe@company.com SIP/3.0 To: sip:joe@company.com From: sip:caller@university.edu Call-ID: 0ha0isnda977644900765@10.0.0.1 CSeq: 8 INVITE Via: SIP/2.0/UDP 135.180.130.133 Content-Type: application/sdp v=0 o=mhandley 29739 7272939 IN IP4 126.5.4.3 c=IN IP4 135.180.130.88 m=audio 492170 RTP/AVP 0 12 m=video 3227 RTP/AVP 31 a=rtpmap:31 LPC sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test10b.txt000066400000000000000000000005241223300710500235330ustar00rootroot00000000000000REGISTER sip:company.com SIP/2.0 To: sip:j.user@COMPANY.COM;maddr=135.180.130.133;tag=foo From: sip:j.user@COMPANY.COM;x-param-0=0;x-param-1=1;x-param-2=2;x-param-3=3;x-param-4=4;x-param-5=5;x-param-6=6;x-param-7=7;x-param-8=8 Call-ID: 0ha0isndaksdj@10.0.2.2 Contact: * CSeq: 9 REGISTER Via: SIP/2.0/UDP 135.180.130.133 Content-Length: 0 sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test10c.txt000066400000000000000000000004311223300710500235310ustar00rootroot00000000000000REGISTER sip:company.com SIP/2.0 Via: SIP/2.0/UDP rama.research.nokia.com Via: SIP/2.0/UDP 135.180.130.133 To: sip:j.user@COMPANY.COM;maddr=135.180.130.133;tag=foo From: sip:j.user@COMPANY.COM;tag=bar Call-ID: 0ha0isndaksdj@10.0.2.2 Contact: * CSeq: 9 REGISTER Content-Length: 0 sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test11.txt000066400000000000000000000003751223300710500233760ustar00rootroot00000000000000INVITE sip:user@company.com SIP/2.0 CSeq: 0 INVITE Via: SIP/2.0/UDP 135.180.130.133 Content-Type: application/sdp v=0 o=mhandley 29739 7272939 IN IP4 126.5.4.3 c=IN IP4 135.180.130.88 m=audio 492170 RTP/AVP 0 12 m=video 3227 RTP/AVP 31 a=rtpmap:31 LPC sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test12.txt000066400000000000000000000006601223300710500233740ustar00rootroot00000000000000INVITE sip:user@company.com SIP/2.0 Via: SIP/2.0/UDP 135.180.130.133 CSeq: 0 INVITE Call-ID: 98asdh@10.1.1.1 Call-ID: 98asdh@10.1.1.2 From: sip:caller@university.edu From: sip:caller@organization.org To: sip:user@company.com Content-Type: application/sdp v=0 o=mhandley 29739 7272939 IN IP4 126.5.4.3 c=IN IP4 135.180.130.88 m=audio 492170 RTP/AVP 0 12 m=video 3227 RTP/AVP 31 s=My sesion t=2873397496 2873404696 a=rtpmap:31 LPC sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test13.txt000066400000000000000000000005671223300710500234030ustar00rootroot00000000000000INVITE sip:user@company.com SIP/2.0 Via: SIP/2.0/UDP 135.180.130.133 CSeq: 0 INVITE Call-ID: 98asdh@10.1.1.2 Expires: Thu, 44 Dec 19999 16:00:00 EDT From: sip:caller@university.edu To: sip:user@company.com Content-Type: application/sdp v=0 o=mhandley 29739 7272939 IN IP4 126.5.4.3 c=IN IP4 135.180.130.88 m=audio 492170 RTP/AVP 0 12 m=video 3227 RTP/AVP 31 a=rtpmap:31 LPC sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test14-req.txt000066400000000000000000000006171223300710500241650ustar00rootroot00000000000000INVITE sip:user@company.com SIP/2.0 Via: SIP/2.0/UDP 255.255.255.255;branch=0 Via: SIP/2.0/UDP 135.180.130.57;branch=0 Call-ID: 0384840201@10.1.1.1 CSeq: 0 INVITE To: sip:user@company.com From: sip:user@university.edu;tag=2229 Content-Type: application/sdp v=0 o=mhandley 29739 7272939 IN IP4 126.5.4.3 c=IN IP4 224.2.17.12/127 m=audio 492170 RTP/AVP 0 4 12 m=video 3227 RTP/AVP 31 a=rtpmap:31 LPC sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test14.txt000066400000000000000000000006141223300710500233750ustar00rootroot00000000000000SIP/2.0 200 OK Via: SIP/2.0/UDP 135.180.130.57;branch=0 Via: SIP/2.0/UDP 255.255.255.255;branch=0 Call-ID: 0384840201@10.1.1.1 CSeq: 0 INVITE From: sip:user@company.com To: sip:user@university.edu;tag=2229 Content-Type: application/sdp Content-Length: 139 v=0 o=mhandley 29739 7272939 IN IP4 126.5.4.3 c=IN IP4 224.2.17.12/127 m=audio 492170 RTP/AVP 0 12 m=video 3227 RTP/AVP 31 a=rtpmap:31 LPC sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test15.txt000066400000000000000000000006301223300710500233740ustar00rootroot00000000000000INVITE sip:user@company.com SIP/2.0 To: ;tag=23444 From: sip:caller@university.edu Call-ID: 0ha0isndaksdj@10.0.0.1 CSeq: 8 INVITE Via: SIP/2.0/UDP 135.180.130.133;;,; Contact: "" <> ;,"Joe" ;;,,;; Content-Type: application/sdp v=0 o=mhandley 29739 7272939 IN IP4 126.5.4.3 c=IN IP4 135.180.130.88 m=audio 492170 RTP/AVP 0 12 m=video 3227 RTP/AVP 31 a=rtpmap:31 LPC sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test16.txt000066400000000000000000000005551223300710500234030ustar00rootroot00000000000000INVITE sip:user@company.com SIP/2.0 To: sip:j.user@company.com From: sip:caller@university.edu Call-ID: 0ha0isndaksdj@10.0.0.1 CSeq: 8 INVITE Via: SIP/2.0/UDP 135.180.130.133 Content-Type: application/sdp Content-Length: 9999 v=0 o=mhandley 29739 7272939 IN IP4 126.5.4.3 c=IN IP4 135.180.130.88 m=audio 492170 RTP/AVP 0 12 m=video 3227 RTP/AVP 31 a=rtpmap:31 LPC sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test17.txt000066400000000000000000000005551223300710500234040ustar00rootroot00000000000000INVITE sip:user@company.com SIP/2.0 To: sip:j.user@company.com From: sip:caller@university.edu Call-ID: 0ha0isndaksdj@10.0.0.1 CSeq: 8 INVITE Via: SIP/2.0/UDP 135.180.130.133 Content-Type: application/sdp Content-Length: -999 v=0 o=mhandley 29739 7272939 IN IP4 126.5.4.3 c=IN IP4 135.180.130.88 m=audio 492170 RTP/AVP 0 12 m=video 3227 RTP/AVP 31 a=rtpmap:31 LPC sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test18.txt000066400000000000000000000006331223300710500234020ustar00rootroot00000000000000INVITE sip:user@company.com SIP/2.0 To: sip:j.user@company.com From: sip:caller@university.edu Call-ID: 0ha0isndaksdj@10.0.0.1 CSeq: 8 INVITE Via: SIP/2.0/UDP 135.180.130.133 Content-Type: application/sdp Content-Length: 138 v=0 o=mhandley 29739 7272939 IN IP4 126.5.4.3 c=IN IP4 135.180.130.88 m=audio 492170 RTP/AVP 0 12 m=video 3227 RTP/AVP 31 a=rtpmap:31 LPC asdpasd08asdsdk:;;asd a0sdjhg8a0''...'';;;; sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test19.txt000066400000000000000000000006241223300710500234030ustar00rootroot00000000000000INVITE sip:user@company.com SIP/2.0 To: "Mr. J. User From: sip:caller@university.edu Call-ID: 0ha0isndaksdj@10.0.0.1 CSeq: 8 INVITE Via: SIP/2.0/UDP 135.180.130.133:5050;branch=z9hG4bKkdjuw Content-Type: application/sdp Content-Length: 138 v=0 o=mhandley 29739 7272939 IN IP4 126.5.4.3 c=IN IP4 135.180.130.88 m=audio 492170 RTP/AVP 0 12 m=video 3227 RTP/AVP 31 a=rtpmap:31 LPC sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test1a.txt000066400000000000000000000011611223300710500234500ustar00rootroot00000000000000INVITE sip:vivekg@chair.dnrc.bell-labs.com SIP/2.0 To : sip:vivekg@chair.dnrc.bell-labs.com ; tag = 1a1b1f1H33n From : "J Rosenberg \\\"" ; tag = 98asjd8 CaLl-Id : 0ha0isndaksdj@10.1.1.1 cseq: 8 INVITE Via : SIP / 2.0/ UDP 135.180.130.133 Subject : Content-Type: application/sdp v: SIP / 2.0 / TCP 12.3.4.5 ; branch = 9ikj8 , SIP / 2.0 / UDP 1.2.3.4 ; hidden m:"Quoted string \"\"" ; newparam = newvalue ; secondparam = secondvalue ; q = 0.33 (((nested comments) and (more))) , tel:4443322 sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test2.txt000066400000000000000000000004501223300710500233100ustar00rootroot00000000000000INVITE sip:user@company.com SIP/2.0 To: sip:j_user@company.com From: sip:caller@university.edu;tag=242etr Max-Forward: 6 Call-ID: 0ha0isndaksdj@10.1.1.1 Require: newfeature1, newfeature2 Proxy-Require: newfeature3, newfeature4 CSeq: 8 INVITE Via: SIP/2.0/UDP 135.180.130.133;branch=z9hG4bKkdjuw sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test20.txt000066400000000000000000000004051223300710500233700ustar00rootroot00000000000000INVITE sip:user;par=u%40h.com@company.com SIP/2.0 To: sip:j_user@company.com From: sip:caller@university.edu;tag=33242 Max-Forwards: 3 Call-ID: 0ha0isndaksdj@10.1.1.1 CSeq: 8 INVITE Via: SIP/2.0/UDP 135.180.130.133;branch=z9hG4bKkdjuw Content-Length: 0 sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test21.txt000066400000000000000000000006021223300710500233700ustar00rootroot00000000000000INVITE SIP/2.0 To: sip:user@company.com From: sip:caller@university.edu Call-ID: 1@10.0.0.1 CSeq: 1 INVITE Via: SIP/2.0/UDP 135.180.130.133 Content-Type: application/sdp Content-Length: 163 v=0 o=mhandley 29739 7272939 IN IP4 126.5.4.3 s=SIP Call t=0 0 c=IN IP4 135.180.130.88 m=audio 492170 RTP/AVP 0 12 m=video 3227 RTP/AVP 31 a=rtpmap:31 LPC sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test22.txt000066400000000000000000000006171223300710500233770ustar00rootroot00000000000000INVITE sip:user@company.com; transport=udp SIP/2.0 To: sip:user@company.com From: sip:caller@university.edu Call-ID: 2@10.0.0.1 CSeq: 1 INVITE Via: SIP/2.0/UDP 135.180.130.133 Content-Type: application/sdp Content-Length: 163 v=0 o=mhandley 29739 7272939 IN IP4 126.5.4.3 s=SIP Call t=0 0 c=IN IP4 135.180.130.88 m=audio 492170 RTP/AVP 0 12 m=video 3227 RTP/AVP 31 a=rtpmap:31 LPC sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test23.txt000066400000000000000000000006011223300710500233710ustar00rootroot00000000000000INVITE sip:user@company.com SIP/2.0 To: sip:user@company.com From: sip:caller@university.edu Call-ID: 3@10.0.0.1 CSeq: 1 INVITE Via: SIP/2.0/UDP 135.180.130.133 Content-Type: application/sdp Content-Length: 163 v=0 o=mhandley 29739 7272939 IN IP4 126.5.4.3 s=SIP Call t=0 0 c=IN IP4 135.180.130.88 m=audio 492170 RTP/AVP 0 12 m=video 3227 RTP/AVP 31 a=rtpmap:31 LPC sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test24.txt000066400000000000000000000006471223300710500234040ustar00rootroot00000000000000INVITE sip:sip%3Auser%40example.com@company.com;other-param=summit SIP/2.0 To: sip:user@company.com From: sip:caller@university.edu Call-ID: 4@10.0.0.1 CSeq: 1 INVITE Via: SIP/2.0/UDP 135.180.130.133 Content-Type: application/sdp Content-Length: 163 v=0 o=mhandley 29739 7272939 IN IP4 126.5.4.3 s=SIP Call t=0 0 c=IN IP4 135.180.130.88 m=audio 492170 RTP/AVP 0 12 m=video 3227 RTP/AVP 31 a=rtpmap:31 LPC sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test25.txt000066400000000000000000000006401223300710500233760ustar00rootroot00000000000000INVITE sip:user@company.com?Route=%3Csip:sip.example.com%3E SIP/2.0 To: sip:user@company.com From: sip:caller@university.edu Call-ID: 5@10.0.0.1 CSeq: 1 INVITE Via: SIP/2.0/UDP 135.180.130.133 Content-Type: application/sdp Content-Length: 163 v=0 o=mhandley 29739 7272939 IN IP4 126.5.4.3 s=SIP Call t=0 0 c=IN IP4 135.180.130.88 m=audio 492170 RTP/AVP 0 12 m=video 3227 RTP/AVP 31 a=rtpmap:31 LPC sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test26.txt000066400000000000000000000005651223300710500234050ustar00rootroot00000000000000INVITE name:user SIP/2.0 To: sip:user@company.com From: sip:caller@university.edu Call-ID: 6@10.0.0.1 CSeq: 1 INVITE Via: SIP/2.0/UDP 135.180.130.133 Content-Type: application/sdp Content-Length: 163 v=0 o=mhandley 29739 7272939 IN IP4 126.5.4.3 s=SIP Call t=0 0 c=IN IP4 135.180.130.88 m=audio 492170 RTP/AVP 0 12 m=video 3227 RTP/AVP 31 a=rtpmap:31 LPC sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test27.txt000066400000000000000000000002731223300710500234020ustar00rootroot00000000000000OPTIONS sip:user@company.com SIP/2.0 To: sip:user@company.com From: "caller" Call-ID: 1234abcd@10.0.0.1 CSeq: 1 OPTIONS Via: SIP/2.0/UDP 135.180.130.133 sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test28.txt000066400000000000000000000002771223300710500234070ustar00rootroot00000000000000OPTIONS sip:user@company.com SIP/2.0 To: sip:user@company.com From: "caller" Call-ID: 1234abcd@10.0.0.1 CSeq: 2 OPTIONS Via: SIP/2.0/UDP 135.180.130.133 sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test29.txt000066400000000000000000000006501223300710500234030ustar00rootroot00000000000000INVITE sip:user@company.com SIP/2.0 To: sip:user@company.com From: sip:caller@university.edu Call-ID: 7@10.0.0.1 CSeq: 1 INVITE Via: SIP/2.0/UDP 135.180.130.133 Expires: Fri, 01 Jan 2010 16:00:00 EST Content-Type: application/sdp Content-Length: 163 v=0 o=mhandley 29739 7272939 IN IP4 126.5.4.3 s=SIP Call t=0 0 c=IN IP4 135.180.130.88 m=audio 492170 RTP/AVP 0 12 m=video 3227 RTP/AVP 31 a=rtpmap:31 LPC sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test3.txt000066400000000000000000000006441223300710500233160ustar00rootroot00000000000000INVITE sip:John_Smith@tct.hut.fi SIP/2.0 To: isbn:2983792873 From: http://www.cs.columbia.edu Call-ID: 0ha0isndaksdj@10.1.2.3 CSeq : 8 INVITE Via: SIP/2.0/UDP 135.180.130.133 Content-Type: application/sdp Contact: Joe Bob Briggs Content-Length: 138 v=0 o=mhandley 29739 7272939 IN IP4 126.5.4.3 c=IN IP4 135.180.130.88 m=audio 492170 RTP/AVP 0 12 m=video 3227 RTP/AVP 31 a=rtpmap:31 LPC sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test30.txt000066400000000000000000000006501223300710500233730ustar00rootroot00000000000000INVITE sip:user@company.com SIP/2.0 To: sip:user@company.com From: sip:caller@university.edu Call-ID: 8@10.0.0.1 CSeq: 1 INVITE Via: SIP/2.0/UDP 135.180.130.133 Expires: Thu, 01 Dec 1994 16:00:00 GMT Content-Type: application/sdp Content-Length: 163 v=0 o=mhandley 29739 7272939 IN IP4 126.5.4.3 s=SIP Call t=0 0 c=IN IP4 135.180.130.88 m=audio 492170 RTP/AVP 0 12 m=video 3227 RTP/AVP 31 a=rtpmap:31 LPC sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test31.txt000066400000000000000000000006211223300710500233720ustar00rootroot00000000000000INVITE sip:user@company.com SIP/2.0 To: sip:user@company.com From: sip:caller@university.edu Call-ID: 9@10.0.0.1 CSeq: 1 INVITE Via: SIP/2.0/UDP 135.180.130.133 Max-Forwards: 0 Content-Type: application/sdp Content-Length: 163 v=0 o=mhandley 29739 7272939 IN IP4 126.5.4.3 s=SIP Call t=0 0 c=IN IP4 135.180.130.88 m=audio 492170 RTP/AVP 0 12 m=video 3227 RTP/AVP 31 a=rtpmap:31 LPC sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test32.txt000066400000000000000000000004261223300710500233760ustar00rootroot00000000000000REGISTER sip:company.com SIP/2.0 To: sip:user@company.com From: sip:user@company.com Contact: sip:user@host.company.com Call-ID: k345asrl3fdbv@10.0.0.1 CSeq: 1 REGISTER Via: SIP/2.0/UDP 135.180.130.133 Contact: sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test33.txt000066400000000000000000000004241223300710500233750ustar00rootroot00000000000000REGISTER sip:company.com SIP/2.0 To: sip:user@company.com From: sip:user@company.com Contact: sip:user@host.company.com Call-ID: k345asrl3fdbv@10.0.0.1 CSeq: 1 REGISTER Via: SIP/2.0/UDP 135.180.130.133 Contact: sip:user@example.com?Route=%3Csip:sip.example.com%3E sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test34.txt000066400000000000000000000035411223300710500234010ustar00rootroot00000000000000INVITE sip:user@company.com SIP/2.0 To: "I have a user name of extreme proportion" From: sip:caller@university.edu Call-ID: kl24ahsd546folnyt2vbak9sad98u23naodiunzds09a3bqw0sdfbsk34poouymnae0043nsed09mfkvc74bd0cuwnms05dknw87hjpobd76f CSeq: 1 INVITE My-State: sldkjflzdsfaret0803adgaasd0afds0asdaasd Via: SIP/2.0/UDP sip33.example.com Via: SIP/2.0/UDP sip32.example.com Via: SIP/2.0/UDP sip31.example.com Via: SIP/2.0/UDP sip30.example.com Via: SIP/2.0/UDP sip29.example.com Via: SIP/2.0/UDP sip28.example.com Via: SIP/2.0/UDP sip27.example.com Via: SIP/2.0/UDP sip26.example.com Via: SIP/2.0/UDP sip25.example.com Via: SIP/2.0/UDP sip24.example.com Via: SIP/2.0/UDP sip23.example.com Via: SIP/2.0/UDP sip22.example.com Via: SIP/2.0/UDP sip21.example.com Via: SIP/2.0/UDP sip20.example.com Via: SIP/2.0/UDP sip19.example.com Via: SIP/2.0/UDP sip18.example.com Via: SIP/2.0/UDP sip17.example.com Via: SIP/2.0/UDP sip16.example.com Via: SIP/2.0/UDP sip15.example.com Via: SIP/2.0/UDP sip14.example.com Via: SIP/2.0/UDP sip13.example.com Via: SIP/2.0/UDP sip12.example.com Via: SIP/2.0/UDP sip11.example.com Via: SIP/2.0/UDP sip10.example.com Via: SIP/2.0/UDP sip9.example.com Via: SIP/2.0/UDP sip8.example.com Via: SIP/2.0/UDP sip7.example.com Via: SIP/2.0/UDP sip6.example.com Via: SIP/2.0/UDP sip5.example.com Via: SIP/2.0/UDP sip4.example.com Via: SIP/2.0/UDP sip3.example.com Via: SIP/2.0/UDP sip2.example.com Via: SIP/2.0/UDP sip1.example.com Via: SIP/2.0/UDP host.example.com;received=135.180.130.133;branch=C1C3344E2710000000E299E568E7potato10potato0potato0 Content-Type: application/sdp v=0 o=mhandley 29739 7272939 IN IP4 126.5.4.3 s=SIP Call t=3149328700 0 c=IN IP4 135.180.130.88 m=audio 492170 RTP/AVP 0 12 m=video 3227 RTP/AVP 31 a=rtpmap:31 LPC sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test35.txt000066400000000000000000000006271223300710500234040ustar00rootroot00000000000000OPTIONS sip:135.180.130.133 SIP/2.0 Via: SIP/2.0/UDP company.com:5604 From: sip:iuser@company.com To: sip:user@135.180.130.133 Call-ID: 1804928587@company.com CSeq: 1 OPTIONS Expires: 0 0l@company.com To: sip:user@135.180.130.133 Call-ID: 1804928587@company.com CSeq: 1 OPTIONS Contact: sip:host.company.com Expires: 0xpires: 0sip:host.company.com Expires: 0 Contact: sip:host.company.com sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test36.txt000066400000000000000000000013101223300710500233730ustar00rootroot00000000000000INVITE sip:+1-972-555-2222;phone-context=name%40domain;new=user?%22Route%3a%20X%40Y%3bZ=W%22@gw1.wcom.com;user=phone SIP/2.0 Via: SIP/2.0/UDP iftgw.there.com:5060 From: sip:+1-303-555-1111@ift.here.com;user=phone To: sip:+1-650-555-2222@ss1.wcom.com;user=phone Call-ID: 1717@ift.here.com CSeq: 56 INVITE Content-Type: application/sdp Content-Length: 348 v=0 o=faxgw1 2890844527 2890844527 IN IP4 iftgw.there.com s=Session SDP c=IN IP4 iftmg.there.com t=0 0 m=image 49172 udptl t38 a=T38FaxVersion:0 a=T38maxBitRate:14400 a=T38FaxFillBitRemoval:0 a=T38FaxTranscodingMMR:0 a=T38FaxTranscodingJBIG:0 a=T38FaxRateManagement:transferredTCF a=T38FaxMaxBuffer:260 a=T38FaxUdpEC:t38UDPRedundancy sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test37.txt000066400000000000000000000003651223300710500234050ustar00rootroot00000000000000REGISTER sip:bell-tel.com SIP/2.0 Via: SIP/2.0/UDP saturn.bell-tel.com From: sip:watson@bell-tel.com To: sip:watson@bell-tel.com Call-ID: 70710@saturn.bell-tel.com CSeq: 2 REGISTER Contact: sip:+1-972-555-2222@gw1.wcom.com;user=phone sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test38.txt000066400000000000000000000003671223300710500234100ustar00rootroot00000000000000REGISTER sip:bell-tel.com SIP/2.0 Via: SIP/2.0/UDP saturn.bell-tel.com From: sip:watson@bell-tel.com To: sip:watson@bell-tel.com Call-ID: 70710@saturn.bell-tel.com CSeq: 3 REGISTER Contact: sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test39.txt000066400000000000000000000003331223300710500234020ustar00rootroot00000000000000INVITE sip:t.watson@ieee.org SIP/2.0 Via: SIP/2.0/UDP c.bell-tel.com From: A. Bell To: T. Watson Call-ID: 31414@c.bell-tel.com CSeq: 1 INVITE sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test4.txt000066400000000000000000000003621223300710500233140ustar00rootroot00000000000000REGISTER sip:company.com SIP/2.0 To: sip:user@company.com From: sip:user@company.com Contact: sip:user@host.company.com Call-ID: 0ha0isndaksdj@10.0.0.1 CSeq: 8 REGISTER Via: SIP/2.0/UDP 135.180.130.133 Expires: Thu, 01 Dec 2040 16:00:00 GMT sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test40.txt000066400000000000000000000003501223300710500233710ustar00rootroot00000000000000INVITE sip:t.watson@ieee.org SIP/2.0 Via: SIP/2.0/UDP c.bell-tel.com From: Bell, Alexander To: Watson, Thomas Call-ID: 31415@c.bell-tel.com CSeq: 1 INVITE sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test41.txt000066400000000000000000000003571223300710500234010ustar00rootroot00000000000000INVITE sip:t.watson@ieee.org SIP/7.0 Max-Forwards: 70 Via: SIP/2.0/UDP c.bell-tel.com From: A. Bell To: T. Watson Call-ID: 31416@c.bell-tel.com CSeq: 1 INVITE sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test42.txt000066400000000000000000000003411223300710500233730ustar00rootroot00000000000000INVITE sip:t.watson@ieee.org SIP/7.0 Via: SIP/2.0/UDP c.bell-tel.com From: A. Bell To: T. Watson Call-ID: 31417@c.bell-tel.com CSeq: 1 INVITE sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test5.txt000066400000000000000000000006151223300710500233160ustar00rootroot00000000000000INVITE sip:user@company.com SIP/2.0 To: sip:j_user@company.com From: sip:caller@university.edu Call-ID: 0ha0isndaksdj@10.0.0.1 Accept: text/newformat CSeq: 8 INVITE Via: SIP/2.0/UDP 135.180.130.133 Content-Type: application/sdp v=0 o=mhandley 29739 7272939 IN IP4 126.5.4.3 c=IN IP4 135.180.130.88/127 m=audio 492170 RTP/AVP 0 12 m=video 3227 RTP/AVP 31 b=CT:3455 a=rtpmap:31 LPC sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test6.txt000066400000000000000000000004141223300710500233140ustar00rootroot00000000000000INVITE sip:user@comapny.com SIP/2.0 To: sip:j.user@company.com From: sip:caller@university.edu Call-ID: 0ha0isndaksdj@10.0.0.1 CSeq: 8 INVITE Via: SIP/2.0/UDP 135.180.130.133 Content-Type: application/newformat Content-Length: 37 sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test7.txt000066400000000000000000000005621223300710500233210ustar00rootroot00000000000000NEWMETHOD sip:user@comapny.com SIP/2.0 To: sip:j.user@company.com From: sip:caller@university.edu Call-ID: 0ha0isndaksdj@10.0.0.1 CSeq: 8 NEWMETHOD Via: SIP/2.0/UDP 135.180.130.133 Content-Type: application/sdp Content-Length: 138 v=0 o=mhandley 29739 7272939 IN IP4 126.5.4.3 c=IN IP4 135.180.130.88 m=audio 492170 RTP/AVP 0 12 m=video 3227 RTP/AVP 31 a=rtpmap:31 LPC sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test8.txt000066400000000000000000000006331223300710500233210ustar00rootroot00000000000000NEWMETHOD sip:user@comapny.com SIP/2.0 To: sip:j.user@company.com From: sip:caller@university.edu;tag=34525 Max-Forwards: 6 Call-ID: 0ha0isndaksdj@10.0.1.1 CSeq: 8 NEWMETHOD Via: SIP/2.0/UDP 135.180.130.133;branch=z9hG4bKkdjuw Content-Type: application/sdp v=0 o=mhandley 29739 7272939 IN IP4 126.5.4.3 c=IN IP4 135.180.130.88 m=audio 492170 RTP/AVP 0 12 m=video 3227 RTP/AVP 31 a=rtpmap:31 LPC sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/tests/test9.txt000066400000000000000000000003611223300710500233200ustar00rootroot00000000000000REGISTER sip:company.com SIP/2.0 To: sip:j.user@company.com From: sip:j.user@company.com Call-ID: 0ha0isndaksdj@10.0.1.1 CSeq: 8 REGISTER Via: SIP/2.0/UDP 135.180.130.133 Authorization: Super-PGP ajsohdaosdh0asyhdaind08yasdknasd09asidhas0d8 sofia-sip-1.12.11+20110422.1/libsofia-sip-ua/sip/torture_sip.c000066400000000000000000003351371223300710500231040ustar00rootroot00000000000000/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * */ /**@ingroup sip_test @internal * * @CFILE torture_sip.c * * Unit-testing functions for SIP. * * @author Pekka Pessi . * * @date Created: Tue Mar 6 18:33:42 2001 ppessi */ #include "config.h" #include #include #include #include /* Avoid casting sip_t to msg_pub_t and sip_header_t to msg_header_t */ #define MSG_PUB_T struct sip_s #define MSG_HDR_T union sip_header_u #include #include #include #include #include "sofia-sip/sip_parser.h" #include #include #include #include #include #include #include #include int tstflags; #define TSTFLAGS tstflags #include char const *name = "torture_sip.c"; msg_mclass_t *test_mclass = NULL; static msg_t *read_message(int flags, char const string[]); static int test_identity(void) { su_home_t *home; sip_alert_info_t *ai; sip_reply_to_t *rplyto; sip_remote_party_id_t *rpid; sip_p_asserted_identity_t *paid; sip_p_preferred_identity_t *ppid; msg_t *msg; sip_t *sip; BEGIN(); msg_href_t const *href; msg_mclass_t const *def0, *def1, *ext; def0 = sip_default_mclass(); /* Check that Refer-Sub has been added to our parser */ TEST_1(href = msg_find_hclass(def0, "Refer-Sub", NULL)); TEST_P(href->hr_class, sip_refer_sub_class); /* Check that Reply-To is not there */ TEST_P(msg_find_hclass(def0, "Reply-To", NULL), def0->mc_unknown); TEST_1(ext = sip_extend_mclass(NULL)); /* Update default parser */ TEST_1(sip_update_default_mclass(ext) == 0); def1 = sip_default_mclass(); TEST_1(def0 != def1); TEST_1(ext == def1); TEST_1(href = msg_find_hclass(def1, "Reply-To", NULL)); TEST_P(href->hr_class, sip_reply_to_class); TEST_1(test_mclass = msg_mclass_clone(def0, 0, 0)); msg = read_message(MSG_DO_EXTRACT_COPY, "BYE sip:foo@bar SIP/2.0\r\n" "To: ;tag=deadbeef\r\n" "From: ;\r\n" "Call-ID: 0ha0isndaksdj@10.1.2.3\r\n" "CSeq: 8 SUBSCRIBE\r\n" "Via: SIP/2.0/UDP 135.180.130.133\r\n" "Alert-Info: ;walz, \r\n" "Reply-To: Arska ;humppa\r\n" "P-Asserted-Identity: \r\n" "P-Preferred-Identity: , \r\n" "Remote-Party-ID: \r\n" "Content-Length: 0\r\n" "\r\n"); sip = sip_object(msg); TEST_1(sip); TEST_1(!sip_alert_info(sip)); TEST_1(!sip_reply_to(sip)); TEST_1(!sip_p_asserted_identity(sip)); TEST_1(!sip_p_preferred_identity(sip)); TEST_1(!sip_remote_party_id(sip)); msg_destroy(msg); TEST_1(msg_mclass_insert_header(test_mclass, sip_p_asserted_identity_class, 0) > 0); TEST_1(msg_mclass_insert_header(test_mclass, sip_p_preferred_identity_class, 0) > 0); msg = read_message(MSG_DO_EXTRACT_COPY, "BYE sip:foo@bar SIP/2.0\r\n" "To: ;tag=deadbeef\r\n" "From: ;\r\n" "Call-ID: 0ha0isndaksdj@10.1.2.3\r\n" "CSeq: 8 SUBSCRIBE\r\n" "Via: SIP/2.0/UDP 135.180.130.133\r\n" "Alert-Info: ;walz, \r\n" "Reply-To: Arska ;humppa\r\n" "P-Asserted-Identity: \r\n" "P-Preferred-Identity: , \r\n" "Remote-Party-ID: \r\n" "Content-Length: 0\r\n" "\r\n"); sip = sip_object(msg); TEST_1(!sip_alert_info(sip)); TEST_1(!sip_reply_to(sip)); TEST_1(sip_p_asserted_identity(sip)); TEST_1(sip_p_preferred_identity(sip)); TEST_1(!sip_remote_party_id(sip)); TEST_1(home = msg_home(msg)); TEST_1((paid = sip_p_asserted_identity_make(home, "sip:joe@example.com"))); TEST_1((paid = sip_p_asserted_identity_make (home, "Jaska , Helmi "))); TEST_1(paid->paid_next); TEST_1((ppid = sip_p_preferred_identity_make(home, "sip:joe@example.com"))); TEST_1((ppid = sip_p_preferred_identity_make (home, "Jaska , Helmi "))); msg_destroy(msg); /* Now with extensions */ TEST_1(test_mclass = msg_mclass_clone(def1, 0, 0)); msg = read_message(MSG_DO_EXTRACT_COPY, "BYE sip:foo@bar SIP/2.0\r\n" "To: ;tag=deadbeef\r\n" "From: ;\r\n" "Call-ID: 0ha0isndaksdj@10.1.2.3\r\n" "CSeq: 8 SUBSCRIBE\r\n" "Via: SIP/2.0/UDP 135.180.130.133\r\n" "Alert-Info: ;walz, \r\n" "Reply-To: Arska ;humppa\r\n" "P-Asserted-Identity: \r\n" "P-Preferred-Identity: , \r\n" "Remote-Party-ID: \r\n" "Content-Length: 0\r\n" "\r\n"); sip = sip_object(msg); TEST_1(ai = sip_alert_info(sip)); TEST_S(ai->ai_url->url_host, "test.com"); TEST_1(rplyto = sip_reply_to(sip)); TEST_S(rplyto->rplyto_url->url_host, "gov.ca.us"); TEST_1(paid = sip_p_asserted_identity(sip)); TEST_1(ppid = sip_p_preferred_identity(sip)); TEST_1(rpid = sip_remote_party_id(sip)); TEST_S(rpid->rpid_url->url_host, "test.domain.com"); msg_destroy(msg); { su_home_t *home = su_home_clone(NULL, sizeof *home); char *s; char const canonic[] = "\"Jaska Jokunen\" ;" "screen=yes;party=called;id-type=user;privacy=\"name,uri-network\""; char const canonic2[] = "Jaska Jokunen ;" "screen=yes;party=called;id-type=user;privacy=\"name,uri-network\""; sip_remote_party_id_t *rpid, *d; TEST_1(rpid = sip_remote_party_id_make(home, canonic)); TEST_S(rpid->rpid_display, "\"Jaska Jokunen\""); TEST_S(rpid->rpid_url->url_user, "jaska.jokunen"); TEST_S(rpid->rpid_params[0], "screen=yes"); TEST_S(rpid->rpid_screen, "yes"); TEST_S(rpid->rpid_party, "called"); TEST_S(rpid->rpid_id_type, "user"); TEST_S(rpid->rpid_privacy, "\"name,uri-network\""); TEST_1(s = sip_header_as_string(home, (void*)rpid)); TEST_S(s, canonic); TEST_1(d = sip_remote_party_id_dup(home, rpid)); TEST_S(d->rpid_display, rpid->rpid_display); TEST_S(d->rpid_params[0], rpid->rpid_params[0]); TEST_1(rpid = sip_remote_party_id_make(home, canonic2)); TEST_S(rpid->rpid_display, "Jaska Jokunen"); TEST_1(s = sip_header_as_string(home, (void*)rpid)); TEST_S(s, canonic2); TEST_1(d = sip_remote_party_id_dup(home, rpid)); TEST_S(d->rpid_display, rpid->rpid_display); su_home_check(home); su_home_zap(home); } END(); } int test_url_headers(void) { BEGIN(); su_home_t *home; char *s, *d; tagi_t *t; url_t *url; sip_from_t const *f; sip_accept_t const *ac; sip_payload_t const *body; sip_refer_sub_t rs[1]; TEST_1(home = su_home_new(sizeof *home)); sip_refer_sub_init(rs)->rs_value = "false"; s = sip_headers_as_url_query (home, SIPTAG_SUBJECT_STR("kuik"), SIPTAG_REFER_SUB(rs), TAG_END()); TEST_1(s); TEST_S(s, "subject=kuik&refer-sub=false"); s = sip_headers_as_url_query (home, SIPTAG_TO_STR("\"Joe\" ;tag=foofaa"), SIPTAG_SUBJECT_STR("foo"), TAG_END()); TEST_1(s); TEST_S(s, "to=%22Joe%22%20%3Csip%3Ajoe@example.com%3E%3Btag%3Dfoofaa" "&subject=foo"); url = url_format(home, "sip:test@example.net?%s", s); TEST_1(url); TEST_S(url->url_headers, s); s = sip_headers_as_url_query (home, SIPTAG_FROM_STR(""), SIPTAG_ACCEPT_STR(""), SIPTAG_PAYLOAD_STR("hello"), SIPTAG_ACCEPT_STR(""), TAG_END()); TEST_S(s, "from=%3Csip%3Ajoe@example.com%3Buser%3Dip%3E" "&accept=" "&body=hello" "&accept="); d = url_query_as_header_string(home, s); TEST_S(d, "from:\n" "accept:\n" "accept:\n" "\n" "hello"); t = sip_url_query_as_taglist(home, s, NULL); TEST_1(t); TEST_P(t[0].t_tag, siptag_from); TEST_1(f = (void *)t[0].t_value); TEST_P(t[1].t_tag, siptag_accept); TEST_1(ac = (void *)t[1].t_value); TEST_P(t[2].t_tag, siptag_payload); TEST_1(body = (void *)t[2].t_value); TEST_P(t[3].t_tag, siptag_accept); s = "xyzzy=foo"; t = sip_url_query_as_taglist(home, s, NULL); TEST_1(t); TEST_P(t[0].t_tag, siptag_header_str); TEST_1(d = (void *)t[0].t_value); TEST_S(d, "foo"); TEST_1(!sip_headers_as_url_query(home, SIPTAG_SEPARATOR_STR(""), TAG_END())); TEST_VOID(su_home_unref(home)); END(); } int test_manipulation(void) { BEGIN(); sip_content_length_t *l; sip_payload_t *pl; msg_t *msg, *msg0; sip_t *sip; msg0 = read_message(MSG_DO_EXTRACT_COPY, "MESSAGE sip:foo@bar SIP/2.0\r\n" "To: Joe User \r\n" "From: \"Bar Owner\" ;tag=foobar\r\n" "Call-ID: 0ha0isndaksdj@10.1.2.3\r\n" "CSeq: 8 MESSAGE\r\n" "Via: SIP/2.0/UDP 135.180.130.133\r\n" "Content-Length: 7\r\n" "Content-Type: text/plain\r\n" "\r\n" "Heippa!"); TEST_1(msg0); TEST_1(msg = msg_copy(msg0)); TEST_1(sip = sip_object(msg)); TEST_1(l = sip_content_length_make(msg_home(msg), "6")); TEST_1(pl = sip_payload_make(msg_home(msg), "hello!")); TEST_1(msg_header_replace(msg, NULL, (void *)sip->sip_content_length, (void *)l) >= 0); TEST_1(msg_header_replace(msg, NULL, (void *)sip->sip_payload, (void *)pl) >= 0); TEST(msg_serialize(msg, NULL), 0); TEST_1(msg_prepare(msg) > 0); msg_destroy(msg); msg_destroy(msg0); END(); } int test_methods(void) { int i; char name[32]; BEGIN(); for (i = 1; sip_method_names[i]; i++) { TEST_S(sip_method_names[i], sip_method_name(i, "foo")); } { char version[] = "protocol / version "; char *end = version + strlen(version); char *s = version; char const *result = NULL; TEST(sip_version_d(&s, &result), 0); TEST_P(s, end); TEST_S(result, "protocol/version"); } { char udp[] = "SIP/ 2.0 / udp"; char tcp[] = "SIP / 2.0 / tcp"; char tls[] = "SIP / 2.0 / tls"; char sctp[] = "SIP / 2.0 / scTp"; char dtls[] = "SIP/2.0/TLS-UDP"; char tls_sctp[] = "SIP/2.0/TLS-SCTP"; char *s, *end; char const *result = NULL; s = udp; end = s + strlen(s); TEST_SIZE(sip_transport_d(&s, &result), 0); TEST_P(s, end); TEST_S(result, sip_transport_udp); s = tcp; end = s + strlen(s); TEST_SIZE(sip_transport_d(&s, &result), 0); TEST_P(s, end); TEST_S(result, sip_transport_tcp); s = tls; end = s + strlen(s); TEST_SIZE(sip_transport_d(&s, &result), 0); TEST_P(s, end); TEST_S(result, sip_transport_tls); s = sctp; end = s + strlen(s); TEST_SIZE(sip_transport_d(&s, &result), 0); TEST_P(s, end); TEST_S(result, sip_transport_sctp); s = dtls; end = s + strlen(s); TEST_SIZE(sip_transport_d(&s, &result), 0); TEST_P(s, end); TEST_S(result, "SIP/2.0/TLS-UDP"); s = tls_sctp; end = s + strlen(s); TEST_SIZE(sip_transport_d(&s, &result), 0); TEST_P(s, end); TEST_S(result, "SIP/2.0/TLS-SCTP"); } END(); } /* Test functions. */ int test_basic(void) { su_home_t *home = su_home_new(sizeof *home); BEGIN(); TEST_1(home); { sip_request_t *rq, *rq1; rq = sip_request_make(home, "INVITE sip:joe@example.com SIP/2.1"); TEST_1(rq); TEST(rq->rq_method, sip_method_invite); TEST_S(rq->rq_method_name, "INVITE"); TEST_1(rq1 = sip_request_dup(home, rq)); su_free(home, rq); su_free(home, rq1); rq = sip_request_make(home, "invite sip:joe@example.com SIP/2.0"); TEST_1(rq); TEST(rq->rq_method, sip_method_unknown); TEST_S(rq->rq_method_name, "invite"); TEST_1(rq1 = sip_request_dup(home, rq)); su_free(home, rq); su_free(home, rq1); TEST_1(!sip_request_create(home, sip_method_unknown, NULL, (void *)"sip:joe@example.com", NULL)); TEST_1(rq = sip_request_create(home, sip_method_unknown, "invite", (void *)"sip:joe@example.com", NULL)); TEST(rq->rq_method, sip_method_unknown); TEST_S(rq->rq_method_name, "invite"); su_free(home, rq); TEST_1(rq = sip_request_create(home, sip_method_unknown, "INVITE", (void *)"sip:joe@example.com", NULL)); TEST(rq->rq_method, sip_method_invite); TEST_S(rq->rq_method_name, "INVITE"); su_free(home, rq); TEST_1(rq = sip_request_create(home, sip_method_invite, "foobar", (void *)"sip:joe@example.com", NULL)); TEST(rq->rq_method, sip_method_invite); TEST_S(rq->rq_method_name, "INVITE"); su_free(home, rq); } { sip_status_t *st; TEST_1(st = sip_status_make(home, "SIP/2.0 200 OK")); su_free(home, st); TEST_1(st = sip_status_make(home, "SIP/2.0 200")); su_free(home, st); TEST_1(!sip_status_make(home, "SIP2.0 200 OK")); TEST_1(!sip_status_create(home, 99, NULL, "SIP/2.1")); TEST_1(!sip_status_create(home, 700, NULL, "SIP/2.1")); TEST_1(st = sip_status_create(home, 200, "Ok", "SIP/2.2")); su_free(home, st); TEST_1(st = sip_status_create(home, 200, NULL, "SIP/2.0")); su_free(home, st); TEST_1(st = sip_status_create(home, 200, NULL, NULL)); su_free(home, st); TEST_1(st = sip_status_create(home, 699, NULL, NULL)); su_free(home, st); } { sip_payload_t *pl; TEST_1(pl = sip_payload_create(home, "foo", 3)); su_free(home, pl); TEST_1(pl = sip_payload_create(home, NULL, 3)); su_free(home, pl); } { sip_separator_t *sep; TEST_1(!sip_separator_make(home, "foo")); TEST_1(sep = sip_separator_create(home)); su_free(home, sep); } /* Test name-addr things */ { su_home_t home[1] = { SU_HOME_INIT(home) }; char const *display; url_t url[1]; msg_param_t const *params; char const *comment; char const na[] = "Raaka Arska ;param=1;humppa (test) "; char const na2[] = "tel:+358501970;param=1;humppa (test) "; char *s, buf[sizeof(na)], ebuf[sizeof(na) + 32]; s = strcpy(buf, na); TEST_1(sip_name_addr_d(home, &s, &display, url, ¶ms, &comment) >= 0); TEST_P(s, buf + strlen(na)); TEST_1(display); TEST(url->url_type, url_tel); TEST_1(params); TEST_1(comment); TEST_SIZE(sip_name_addr_e(ebuf, sizeof(ebuf), 0, display, 0, url, params, comment), strlen(na) - 1); TEST_1(strncmp(na, ebuf, strlen(na) - 1) == 0); s = strcpy(buf, na2); TEST_1(sip_name_addr_d(home, &s, &display, url, ¶ms, &comment) >= 0); TEST_S(s, ""); TEST_P(s, buf + strlen(na2)); TEST_1(!display); TEST(url->url_type, url_tel); TEST_1(params); TEST_1(comment); su_home_deinit(home); } { sip_from_t *f; sip_to_t *t, *t2; TEST_1(f = sip_from_create(home, (void *)"sip:joe@bar")); TEST_1(sip_from_add_param(home, f, NULL) == -1); TEST_1(sip_from_add_param(home, f, "tag=tagged") == 0); TEST_S(f->a_tag, "tagged"); TEST_1(sip_from_tag(home, f, "jxahudsf") == -1); while (f->a_params && f->a_params[0]) msg_header_remove_param(f->a_common, f->a_params[0]); TEST_P(f->a_tag, NULL); TEST_1(sip_from_add_param(home, f, "test=1") == 0); TEST_1(sip_from_tag(home, f, "jxahudsf") == 0); TEST_S(f->a_tag, "jxahudsf"); su_free(home, f); TEST_1(!sip_from_create(home, (void *)"sip:joe@[baa")); TEST_1(!sip_from_make(home, (void *)"tester <>;tag=fasjfuios")); TEST_1(f = sip_from_make(home, (void *)"sip:joe@bar (foo)")); su_free(home, f); TEST_1(f = sip_from_make(home, (void *)" (joe)")); TEST_1(sip_from_tag(home, f, "tag=jxahudsf") == 0); su_free(home, f); TEST_1(f = sip_from_create(home, (void *)" (joe)")); TEST_1(sip_is_from((sip_header_t*)f)); su_free(home, f); TEST_1(t = sip_to_create(home, (void *)" (joe)")); TEST_1(sip_is_to((sip_header_t*)t)); TEST_1(sip_to_tag(home, t, "tag=jxahudsf") == 0); TEST_S(t->a_tag, "jxahudsf"); TEST(msg_header_replace_param(home, t->a_common, "tag=bar"), 1); TEST_S(t->a_tag, "bar"); TEST_1(t2 = sip_to_dup(home, t)); TEST_S(t2->a_tag, "bar"); TEST(msg_header_remove_param(t->a_common, "tag"), 1); TEST_P(t->a_tag, NULL); TEST_1(sip_to_add_param(home, t, "tst=1") == 0); TEST_P(t->a_tag, NULL); su_free(home, t); } { sip_call_id_t *i, *i0; TEST_1(i = sip_call_id_create(home, "example.com")); i->i_hash = 0; TEST_1(i0 = sip_call_id_dup(home, i)); su_free(home, i); TEST_1(i = sip_call_id_make(home, i0->i_id)); TEST(i->i_hash, i0->i_hash); su_free(home, i); su_free(home, i0); } { sip_cseq_t *cs, *cs0; TEST_1(cs = sip_cseq_create(home, 123456789, sip_method_invite, "1nvite")); TEST(cs->cs_seq, 123456789); TEST(cs->cs_method, sip_method_invite); TEST_S(cs->cs_method_name, "INVITE"); su_free(home, cs); TEST_1(cs = sip_cseq_create(home, 123456789, sip_method_invite, NULL)); TEST(cs->cs_seq, 123456789); TEST(cs->cs_method, sip_method_invite); TEST_S(cs->cs_method_name, "INVITE"); TEST_1(cs0 = sip_cseq_dup(home, cs)); su_free(home, cs); su_free(home, cs0); TEST_1(!sip_cseq_create(home, 123456789, sip_method_unknown, NULL)); TEST_1(cs = sip_cseq_create(home, 123456789, sip_method_unknown, "invite")); TEST(cs->cs_seq, 123456789); TEST(cs->cs_method, sip_method_unknown); TEST_S(cs->cs_method_name, "invite"); TEST_1(cs0 = sip_cseq_dup(home, cs)); su_free(home, cs); su_free(home, cs0); } { sip_contact_t *m, *m0; TEST_1(!sip_contact_make(home, ",,")); TEST_1(m = sip_contact_create(home, (void *)"sip:joe@bar", "q=0.2", "+message", NULL)); TEST_S(m->m_q, "0.2"); TEST_1(m0 = sip_contact_dup(home, m)); TEST_1(sip_contact_add_param(home, m, "q=0.5") >= 0); TEST_1(sip_contact_add_param(home, m, "video=FALSE") >= 0); TEST_1(sip_contact_add_param(home, m, NULL) == -1); TEST_1(sip_contact_add_param(home, NULL, "video=FALSE") == -1); TEST_1(sip_contact_add_param(home, m, "audio=FALSE") == 0); TEST_1(sip_contact_add_param(home, m, "expires=0") == 0); TEST_S(m->m_q, "0.5"); TEST_S(m->m_expires, "0"); TEST_1(!sip_contact_create(home, (void *)"sip:joe@[baa", "audio", "video", NULL)); TEST_1(sip_header_format(home, sip_contact_class, "*")); su_free(home, m); su_free(home, m0); } { sip_via_t *v; char *s; v = sip_via_make(home, "SIP/2.0/UDP domain.invalid:5060"); TEST_1(v); s = sip_contact_string_from_via(home, v, NULL, v->v_protocol); TEST_S(s, ""); su_free(home, v), su_free(home, s); TEST_1(sip_transport_has_tls("SIP/2.0/TLS-SCTP")); TEST_1(sip_transport_has_tls("TLS-UDP")); v = sip_via_make(home, "SIP/2.0/TLS-SCTP domain.invalid"); TEST_1(v); s = sip_contact_string_from_via(home, v, NULL, v->v_protocol); TEST_S(s, ""); su_free(home, v), su_free(home, s); } { char *input; char const *output = NULL; char udp[] = "sip/2.0/udp"; char tcp[] = "sip/2.0/tCp "; char sctp[] = "sip/2.0/sctp\t"; char tls[] = "sip/2.0/tls\r"; input = udp; TEST(sip_transport_d(&input, &output), 0); TEST_S(output, "SIP/2.0/UDP"); input = tcp; TEST(sip_transport_d(&input, &output), 0); TEST_S(output, "SIP/2.0/TCP"); input = sctp; TEST(sip_transport_d(&input, &output), 0); TEST_S(output, "SIP/2.0/SCTP"); input = tls; TEST(sip_transport_d(&input, &output), 0); TEST_S(output, "SIP/2.0/TLS"); } { sip_expires_t *ex; TEST_1(!sip_expires_make(home, "-12+1")); TEST_1(ex = sip_expires_make(home, "4294967297")); /* XXX */ su_free(home, ex); TEST_1(ex = sip_expires_make(home, "Wed, 25 Mar 2004 14:49:29 GMT")); su_free(home, ex); TEST_1(ex = sip_expires_create(home, 3600)); su_free(home, ex); } { sip_retry_after_t *ra; char const *s; TEST_1(!(ra = sip_retry_after_make(home, "50 (foo"))); TEST_1(ra = sip_retry_after_make(home, "50 (foo) ; duration = 13")); TEST_S(ra->af_duration, "13"); TEST_S(ra->af_comment, "foo"); TEST(msg_header_remove_param(ra->af_common, "duration"), 1); TEST_P(ra->af_duration, NULL); s = sip_header_as_string(home, (void*)ra); TEST_S(s, "50 (foo)"); TEST(msg_header_add_param(home, ra->af_common, "x=z"), 0); s = sip_header_as_string(home, (void*)ra); TEST_S(s, "50 (foo) ;x=z"); su_free(home, ra); } { sip_date_t *d; TEST_1(!(d = sip_date_make(home, "Mon, 30 Feb 1896 23:59:59 GMT"))); su_free(home, d); TEST_1(d = sip_date_create(home, (1<<30))); su_free(home, d); TEST_1(d = sip_date_create(home, 0)); TEST_1(d->d_time != 0); su_free(home, d); } { sip_route_t *r, *r0; TEST_1(!sip_route_make(home, ";lr")); TEST_1(r = sip_route_make(home, ";lr")); TEST_1(r0 = sip_route_dup(home, r)); TEST_1(sip_route_fix(r)); TEST_1(url_has_param(r->r_url, "lr")); su_free(home, r); TEST_1(r = sip_route_create(home, r0->r_url, r0->r_url)); su_free(home, r); su_free(home, r0); } { sip_record_route_t *r, *r0; TEST_1(!sip_record_route_make(home, ";lr")); TEST_1(!sip_record_route_make(home, ";lr bar, sip:foo")); TEST_1(r = sip_record_route_make(home, ";lr")); TEST_1(r0 = sip_record_route_dup(home, r)); su_free(home, r); TEST_1(r = sip_route_create(home, r0->r_url, r0->r_url)); su_free(home, r), su_free(home, r0); } { sip_via_t *v, *v0; TEST_1(!sip_via_make(home, ",,")); TEST_1(!sip_via_make(home, "SIP// host:5060 (foo),")); TEST_1(!sip_via_make(home, "SIP/2.0/TCP host:5060 (foo) bar,")); TEST_1(!sip_via_make(home, "SIP/2.0/TCP [3ffe::1:5060 (foo),")); TEST_1(v = sip_via_create(home, "bar.com", "50600", "SIP/2.0/UDP", "hidden", "rport=50601", "comp=sigcomp", "branch=1", "q=0.2", NULL)); TEST_S(v->v_branch, "1"); TEST_S(v->v_rport, "50601"); TEST_S(v->v_comp, "sigcomp"); TEST_1(v = sip_via_make(home, "SIP/2.0/UDP bar.com:50600" " ;hidden;rport=50601;comp=sigcomp;branch=1;ttl=15" " ; maddr=[::227.0.0.1]" " (This is a comment) ")); TEST_S(v->v_ttl, "15"); TEST_S(v->v_maddr, "[::227.0.0.1]"); TEST_S(v->v_branch, "1"); TEST_S(v->v_rport, "50601"); TEST_S(v->v_comp, "sigcomp"); TEST_1(v0 = sip_via_dup(home, v)); TEST(msg_header_add_param(home, v->v_common, "rport"), 0); TEST_S(v->v_rport, ""); TEST(msg_header_remove_param(v->v_common, "comp"), 1); TEST_P(v->v_comp, NULL); TEST(msg_header_remove_param(v->v_common, "ttl"), 1); TEST_P(v->v_ttl, NULL); TEST(msg_header_remove_param(v->v_common, "maddr"), 1); TEST_P(v->v_maddr, NULL); TEST(msg_header_remove_param(v->v_common, "rport"), 1); TEST_P(v->v_rport, NULL); TEST(msg_header_remove_param(v->v_common, "branch"), 1); TEST_P(v->v_branch, NULL); TEST_1(sip_via_add_param(home, v, "video=FALSE") == 0); TEST_1(sip_via_add_param(home, v, NULL) == -1); TEST_1(sip_via_add_param(home, NULL, "video=FALSE") == -1); TEST_1(sip_via_add_param(home, v, "audio=FALSE") == 0); TEST_1(sip_via_add_param(home, v, "branch=0") == 0); su_free(home, v); su_free(home, v0); TEST_1(v = sip_via_create(home, "bar.com", "50600", NULL, "rport=50601", "branch=1", "q=0.2", NULL)); TEST_S(v->v_protocol, "SIP/2.0/UDP"); su_free(home, v); } { sip_call_info_t *ci, *ci0; TEST_1(ci = sip_call_info_make(home, ";purpose=info")); TEST_S(ci->ci_purpose, "info"); TEST_1(ci0 = sip_call_info_dup(home, ci)); TEST_S(ci0->ci_purpose, "info"); TEST_1(ci->ci_purpose != ci0->ci_purpose); TEST(msg_header_remove_param(ci->ci_common, "purpose"), 1); TEST_P(ci->ci_purpose, NULL); su_free(home, ci); su_free(home, ci0); } { sip_alert_info_t *ai, *ai0; TEST_1(ai = sip_alert_info_make(home, ";x-format=mp3")); TEST_1(ai0 = sip_alert_info_dup(home, ai)); TEST(msg_header_remove_param(ai->ai_common, "x-format"), 1); TEST(msg_header_remove_param(ai0->ai_common, "x-format"), 1); su_free(home, ai); su_free(home, ai0); } { sip_reply_to_t *rplyto, *rplyto0; TEST_1(rplyto = sip_reply_to_make(home, "sip:joe@bar")); TEST_1(msg_header_add_param(home, (msg_common_t *)rplyto, "x-extra=extra") == 0); while (rplyto->rplyto_params && rplyto->rplyto_params[0]) msg_header_remove_param(rplyto->rplyto_common, rplyto->rplyto_params[0]); su_free(home, rplyto); TEST_1(!sip_reply_to_make(home, (void *)"sip:joe@[baa")); TEST_1(rplyto = sip_reply_to_make(home, (void *)"sip:joe@bar")); su_free(home, rplyto); TEST_1(rplyto = sip_reply_to_make(home, (void *)"Joe ;x-extra=extra")); TEST_1(rplyto0 = sip_reply_to_dup(home, rplyto)); su_free(home, rplyto); su_free(home, rplyto0); } su_home_check(home); su_home_zap(home); END(); } int test_sip_msg_class(msg_mclass_t const *mc) { int i, j, N; msg_hclass_t *hc; BEGIN(); N = mc->mc_hash_size; /* check hashes */ for (i = 0; i < N; i++) { if (!(hc = mc->mc_hash[i].hr_class)) continue; for (j = i + 1; j < N; j++) { if (!mc->mc_hash[j].hr_class) continue; if (hc->hc_hash == mc->mc_hash[j].hr_class->hc_hash) { fprintf(stderr, "\t%s and %s have same hash\n", hc->hc_name, mc->mc_hash[j].hr_class->hc_name); return 1; } } } /* Check parser table sanity */ for (i = 0; i < N; i++) { /* Verify each header entry */ hc = mc->mc_hash[i].hr_class; if (hc == NULL) continue; /* Short form */ if (hc->hc_short[0]) TEST_P(mc->mc_short[hc->hc_short[0] - 'a'].hr_class, hc); /* Long form */ j = msg_header_name_hash(hc->hc_name, NULL); TEST(j, hc->hc_hash); for (j = MC_HASH(hc->hc_name, N); j != i; j = (j + 1) % N) TEST_1(mc->mc_hash[j].hr_class); } END(); } msg_t *read_message(int flags, char const buffer[]) { size_t n; int m; msg_t *msg; msg_iovec_t iovec[2]; n = strlen(buffer); if (n == 0) return NULL; msg = msg_create(test_mclass, flags); if (msg_recv_iovec(msg, iovec, 2, n, 1) < 0) { perror("msg_recv_iovec"); } memcpy(iovec->mv_base, buffer, n); msg_recv_commit(msg, n, 1); m = msg_extract(msg); return msg; } static int test_encoding(void) { msg_header_t *h, *h1; msg_common_t *c; msg_t *msg; sip_t *sip; su_home_t *home; BEGIN(); TEST_1(home = su_home_new(sizeof *home)); msg = read_message(MSG_DO_EXTRACT_COPY, "SUBSCRIBE sip:foo@bar SIP/2.0\r\n" "To: Joe User \r\n" "From: \"Bar Owner\" ;tag=foobar\r\n" "P-Asserted-Identity: \r\n" "P-Preferred-Identity: \r\n" "Call-ID: 0ha0isndaksdj@10.1.2.3\r\n" "CSeq: 8 SUBSCRIBE\r\n" "Via: SIP/2.0/UDP 135.180.130.133\r\n" "Extension-Header: extended, more\r\n" "Reason: Q.850;cause=16;text=\"Terminated\"\r\n" "Contact: \r\n" "Date: Wed, 25 Mar 2004 14:49:29 GMT\r\n" "Max-Forwards: 80\r\n" "Min-Expires: 30\r\n" "Retry-After: 48 (this is a comment) ;duration=321\r\n" "Route: \r\n" "Request-Disposition: proxy\r\n" "Accept-Contact: *;audio\r\n" "Reject-Contact: *;video\r\n" "Expires: 1200\r\n" "Event: presence;id=1\r\n" "In-Reply-To: {0h!a0i\"sndaksdj}@[kjsafi3], {0h!a0i\"snj}@[kjsfi3]\r\n" "Organization: Nuoret Banaani-Kotkat y.r.\r\n" "Priority: urgent\r\n" "Subject: ynk\r\n" "Timestamp: 3289129810.798259\r\n" "SIP-If-Match: foobar\r\n" "Proxy-Requires: prefs\r\n" "Supported: vnd.nokia\r\n" "User-Agent: Unknown Subscriber (1.0) Tonto (2.0)\r\n" "Accept: application/pidf+xml;version=1.0\r\n" "Accept-Encoding: gzip\r\n" /* Test loop below cannot encode multiple Accept-Language on one line */ "Accept-Language: "/* "fi, "*/"en;q=0.2\r\n" "RAck: 421413 214214 INVITE\r\n" "Referred-By: \r\n" "Replaces: 12345601@atlanta.example.com;from-tag=314159;to-tag=1234567\r\n" "Authorization: Digest realm=\"foo\"\r\n" "Proxy-Authorization: Digest realm=\"foo\"\r\n" "Security-Client: tls\r\n" "Security-Verify: tls;q=0.2\r\n" "Privacy: none\r\n" "Content-Length: 7\r\n" "Content-Encoding: gzip, deflate, identity\r\n" "Content-Disposition: filter\r\n" "Content-Language: fi\r\n" "MIME-Version: 1.0\r\n" "Min-SE: 123\r\n" "Session-Expires: 1200\r\n" "Content-Type: text/plain\r\n" "Refer-Sub: true\r\n" "Suppress-Body-If-Match: humppa\r\n" "Suppress-Notify-If-Match: zumppa\r\n" "\r\n" "Heippa!"); sip = sip_object(msg); TEST_1(msg); TEST_1(sip); TEST_1(!sip->sip_error); for (h = (msg_header_t *)sip->sip_request; h; h = h->sh_succ) { char b[80]; size_t n; if (h == (msg_header_t*)sip->sip_payload) break; TEST_1(h1 = msg_header_dup(home, h)); n = msg_header_e(b, sizeof b, h1, 0); TEST_SIZE(n, h->sh_len); TEST_M(b, h->sh_data, n); su_free(home, h1); } msg_destroy(msg), msg = NULL; /* Note: this should be canonic! */ msg = read_message(MSG_DO_EXTRACT_COPY, "SIP/2.0 200 Ok\r\n" "To: Joe User ;tag=deadbeef\r\n" "From: sip:bar@foo;tag=foobar\r\n" "Call-ID: {0h!a0i\"sndaksdj}@[kjsafi3]\r\n" "CSeq: 8912734 SUBSCRIBE\r\n" "Via: SIP/2.0/UDP 135.180.130.133\r\n" "Extension-Header: extended, more\r\n" "Reason: SIP;cause=400;text=\"Bad Message\"\r\n" "Contact: ;audio\r\n" "Date: Wed, 25 Mar 2004 14:49:29 GMT\r\n" "Max-Forwards: 80\r\n" "Min-Expires: 30\r\n" "Expires: Wed, 25 Mar 2004 15:49:29 GMT\r\n" "Retry-After: 48;duration=321\r\n" "Record-Route: \r\n" "Event: presence;id=1\r\n" "Allow-Events: presence, presence.winfo\r\n" "Subscription-State: active;expires=1800\r\n" "Call-Info: ;purpose=xcap\r\n" "Error-Info: ;param=xcap\r\n" "Server: None\r\n" "Timestamp: 3289129810.798259 0.084054\r\n" "SIP-ETag: foobar\r\n" "SIP-If-Match: foobar\r\n" "Requires: vnd.nokia\r\n" "Unsupported: vnd.nokia.pic\r\n" "Accept-Disposition: filter\r\n" "Warning: 399 presence.bar:5060 \"Unimplemented filter\"\r\n" "RSeq: 421414\r\n" "Refer-To: \r\n" "Alert-Info: \r\n" "Reply-To: Bob \r\n" "WWW-Authenticate: Digest realm=\"foo\"\r\n" "Proxy-Authenticate: Digest realm=\"foo\"\r\n" "Security-Server: tls;q=0.2\r\n" "Session-Expires: 1200;refresher=uac\r\n" "Content-Length: 7\r\n" "Content-Type: text/plain;charset=iso8859-1\r\n" "\r\n" "Heippa!"); sip = sip_object(msg); TEST_1(msg); TEST_1(sip); TEST_1(!sip->sip_error); for (h = (msg_header_t *)sip->sip_status; h; h = h->sh_succ) { char b[80]; size_t n; if (h == (sip_header_t*)sip->sip_payload) break; TEST_1(h1 = sip_header_dup(home, h)); n = sip_header_e(b, sizeof b, h1, 0); TEST_SIZE(n, h->sh_len); TEST_M(b, h->sh_data, n); su_free(home, h1); } TEST_1(sip->sip_etag); TEST_S(sip->sip_etag->g_value, "foobar"); TEST_1(sip->sip_if_match); msg_destroy(msg), msg = NULL; su_home_check(home); su_home_zap(home); msg = read_message(0, "SIP/2.0 200 Ok\r\n" "Via: SIP/2.0/UDP 135.180.130.133\r\n" "Via: SIP/2.0/UDP 135.180.130.130:5060\r\n" "To: Joe User ;tag=deadbeef\r\n" "From: sip:bar@foo;tag=foobar\r\n" "Call-ID: {0h!a0i\"sndaksdj}@[kjsafi3]\r\n" "CSeq: 8912734 SUBSCRIBE\r\n" "Record-Route: \r\n" "Record-Route: \r\n" "Content-Length: 0\r\n" "\r\n"); sip = sip_object(msg); TEST_1(msg); TEST_1(sip); TEST_1(!sip->sip_error); sip->sip_flags |= MSG_FLG_COMPACT; TEST_1(msg_prepare(msg) != 0); TEST_1(c = sip->sip_status->st_common); TEST_M(c->h_data, "SIP/2.0 200 Ok\r\n", c->h_len); TEST_1(c = sip->sip_to->a_common); TEST_M(c->h_data, "t:Joe User;tag=deadbeef\r\n", c->h_len); TEST_1(c = sip->sip_from->a_common); TEST_M(c->h_data, "f:sip:bar@foo;tag=foobar\r\n", c->h_len); TEST_1(c = sip->sip_call_id->i_common); TEST_M(c->h_data, "i:{0h!a0i\"sndaksdj}@[kjsafi3]\r\n", c->h_len); TEST_1(c = sip->sip_cseq->cs_common); TEST_M(c->h_data, "CSeq:8912734 SUBSCRIBE\r\n", c->h_len); TEST_1(c = sip->sip_via->v_common); TEST_M(c->h_data, "v:SIP/2.0/UDP 135.180.130.133,SIP/2.0/UDP 135.180.130.130:5060\r\n", c->h_len); TEST_1(c = sip->sip_via->v_next->v_common); TEST_SIZE(c->h_len, 0); TEST_1(c->h_data); TEST_1(c = sip->sip_record_route->r_common); TEST_M(c->h_data, "Record-Route:,\r\n", c->h_len); TEST_1(c = sip->sip_record_route->r_next->r_common); TEST_SIZE(c->h_len, 0); TEST_1(c->h_data); TEST_1(c = sip->sip_content_length->l_common); TEST_M(c->h_data, "l:0\r\n", c->h_len); END(); } #define XTRA(xtra, h) SU_ALIGN(xtra) + sip_header_size((sip_header_t*)h) /** Test header filtering and duplicating */ int tag_test(void) { su_home_t *home = su_home_new(sizeof(*home)); sip_request_t *request = sip_request_make(home, "INVITE sip:joe@example.com SIP/2.0"); sip_to_t *to = sip_to_make(home, "Joe User " ";tag=12345678"); sip_via_t *via = sip_via_make(home, "SIP/2.0/UDP sip.example.com" ";maddr=128.12.9.254" ";branch=289412978y641.321312"); url_t *url = url_hdup(home, (url_t *)"sip:test:pass@example.com;baz=1?foo&bar"); tagi_t *lst, *dup; size_t xtra; tag_value_t v; BEGIN(); su_home_check(home); TEST_1(home && request && to && via); lst = tl_list(SIPTAG_REQUEST(request), SIPTAG_TO(to), SIPTAG_VIA(via), URLTAG_URL(url), TAG_NULL()); xtra = 0; xtra += XTRA(xtra, request); xtra += XTRA(xtra, to); xtra += XTRA(xtra, via); xtra += SU_ALIGN(xtra) + sizeof(*url) + url_xtra(url); TEST_SIZE(tl_len(lst), 5 * sizeof(tagi_t)); TEST_SIZE(tl_xtra(lst, 0), xtra); dup = tl_adup(NULL, lst); TEST(dup != NULL, 1); TEST_SIZE(tl_len(dup), 5 * sizeof(tagi_t)); TEST_SIZE(tl_xtra(dup, 0), xtra); if (tstflags & tst_verbatim) tl_print(stdout, "dup:\n", dup); su_free(NULL, dup); tl_vfree(lst); TEST_1(t_scan(siptag_request, home, "INVITE sip:example.org SIP/2.0", &v)); TEST_1(request = (void *)v); TEST_1(request->rq_common->h_class == sip_request_class); TEST_S(request->rq_method_name, "INVITE"); TEST_S(request->rq_version, "SIP/2.0"); TEST_1(t_scan(siptag_to, home, "Example ;tag=foo", &v)); TEST_1(to = (void *)v); TEST_1(to->a_common->h_class == sip_to_class); TEST_S(to->a_display, "Example"); TEST_S(to->a_tag, "foo"); su_home_check(home); su_home_zap(home); END(); } /** Test advanced tag features */ static int parser_tag_test(void) { tagi_t *lst, *dup, *filter1, *filter2, *filter3, *filter4; tagi_t *b1, *b2, *b3, *b4; msg_t *msg; sip_t *sip; su_home_t *home; size_t xtra; BEGIN(); home = su_home_new(sizeof *home); msg = read_message(MSG_DO_EXTRACT_COPY, "SIP/2.0 401 Unauthorized\r\n" "Via: SIP/2.0/UDP srlab.sr.ntc.nokia.com:5060;maddr=192.168.102.5\r\n" "Via: SIP/2.0/UDP 172.21.9.155\r\n" "Record-Route: \r\n" "From: sip:digest@garage.sr.ntc.nokia.com\r\n" "To: sip:digest@garage.sr.ntc.nokia.com\r\n" "Call-ID: 982773899-reg@172.21.9.155\r\n" "CSeq: 1 REGISTER\r\n" "WWW-Authenticate: Digest realm=\"garage.sr.ntc.nokia.com\",\r\n" " nonce=\"MjAwMS0wMS0yMSAxNTowODo1OA==\", algorithm=MD5, qop=\"auth\"\r\n" "Proxy-Authenticate: Digest realm=\"IndigoSw\", domain=\"sip:indigosw.com\", " "nonce=\"V2VkIEF1ZyAxNSAxODoxMzozMiBCU1QgMjAwMVtCQDJkYjE5ZA==\", " "opaque=\"NzA3ZjJhYzU4MGY3MzU0MQ==\", stale=false, " "algorithm=md5, algorithm=sha1, qop=\"auth\"\r\n" /* , qop=\"auth, auth-int\"\r */ "\r\n"); sip = sip_object(msg); TEST_1(home && msg && sip); TEST_1(sip->sip_size >= sizeof *sip); TEST_1(sip_is_status((sip_header_t *)sip->sip_status)); TEST_1(sip_is_via((sip_header_t *)sip->sip_via)); TEST_1(sip_is_via((sip_header_t *)sip->sip_via->v_next)); TEST_1(sip_is_record_route((sip_header_t *)sip->sip_record_route)); TEST_1(sip_is_from((sip_header_t *)sip->sip_from)); TEST_1(sip_is_to((sip_header_t *)sip->sip_to)); TEST_1(sip_is_call_id((sip_header_t *)sip->sip_call_id)); TEST_1(sip_is_cseq((sip_header_t *)sip->sip_cseq)); TEST_1(sip_is_www_authenticate( (sip_header_t *)sip->sip_www_authenticate)); TEST_1(sip_complete_message(msg) == 0); TEST_1(sip_is_content_length((sip_header_t *)sip->sip_content_length)); TEST_P(sip->sip_content_length->l_common->h_succ, sip->sip_separator); lst = tl_list(SIPTAG_VIA(sip->sip_via), SIPTAG_RECORD_ROUTE(sip->sip_record_route), TAG_SKIP(2), SIPTAG_CSEQ(sip->sip_cseq), SIPTAG_PAYLOAD(sip->sip_payload), TAG_NULL()); filter1 = tl_list(SIPTAG_VIA(0), TAG_NULL()); filter2 = tl_list(SIPTAG_CALL_ID(0), SIPTAG_FROM(0), SIPTAG_ROUTE(0), SIPTAG_CSEQ(0), TAG_NULL()); filter3 = tl_list(SIPTAG_CSEQ(0), SIPTAG_CONTENT_LENGTH(0), TAG_NULL()); filter4 = tl_list(SIPTAG_STATUS(0), SIPTAG_VIA(0), SIPTAG_RECORD_ROUTE(0), SIPTAG_FROM(0), SIPTAG_TO(0), SIPTAG_CALL_ID(0), SIPTAG_CSEQ(0), SIPTAG_WWW_AUTHENTICATE(0), SIPTAG_PROXY_AUTHENTICATE(0), SIPTAG_CONTENT_LENGTH(0), TAG_NULL()); TEST_1(lst && filter1 && filter2 && filter3 && filter4); b1 = tl_afilter(home, filter1, lst); TEST_SIZE(tl_len(b1), 2 * sizeof(tagi_t)); TEST_1(((sip_via_t *)b1->t_value)->v_next); xtra = sip_header_size((sip_header_t *)sip->sip_via); xtra += SU_ALIGN(xtra); xtra += sip_header_size((sip_header_t *)sip->sip_via->v_next); TEST_SIZE(tl_xtra(b1, 0), xtra); dup = tl_adup(home, lst); TEST_SIZE(tl_len(dup), tl_len(lst)); TEST_SIZE(tl_xtra(dup, 0), tl_xtra(lst, 0)); tl_vfree(lst); lst = tl_list(SIPTAG_SIP(sip), TAG_NULL()); b2 = tl_afilter(home, filter2, lst); TEST_SIZE(tl_len(b2), 4 * sizeof(tagi_t)); xtra = 0; xtra += XTRA(xtra, sip->sip_call_id); xtra += XTRA(xtra, sip->sip_from); xtra += XTRA(xtra, sip->sip_cseq); TEST_SIZE(tl_xtra(b2, 0), xtra); b3 = tl_afilter(home, filter3, lst); TEST_SIZE(tl_len(b3), 3 * sizeof(tagi_t)); TEST_SIZE(tl_xtra(b3, 0), sizeof(sip_content_length_t) + sizeof(sip_cseq_t)); b4 = tl_afilter(home, filter4, lst); TEST_SIZE(tl_len(b4), 11 * sizeof(tagi_t)); xtra = 0; xtra += XTRA(xtra, sip->sip_status); xtra += XTRA(xtra, sip->sip_via); xtra += XTRA(xtra, sip->sip_via->v_next); xtra += XTRA(xtra, sip->sip_record_route); xtra += XTRA(xtra, sip->sip_from); xtra += XTRA(xtra, sip->sip_to); xtra += XTRA(xtra, sip->sip_call_id); xtra += XTRA(xtra, sip->sip_cseq); xtra += XTRA(xtra, sip->sip_www_authenticate); xtra += XTRA(xtra, sip->sip_proxy_authenticate); xtra += XTRA(xtra, sip->sip_content_length); TEST_SIZE(tl_xtra(b4, 0), xtra); tl_vfree(filter1); tl_vfree(filter2); tl_vfree(filter3); tl_vfree(filter4); tl_vfree(lst); su_home_check(home); su_free(home, b4); su_free(home, b3); su_free(home, b2); su_free(home, dup); su_free(home, b1); su_home_check(home); su_home_unref(home); msg_destroy(msg); END(); } /** Test error messages */ static int response_phrase_test(void) { BEGIN(); { struct { int status; char const *phrase; } const errors[] = { { SIP_100_TRYING }, { SIP_180_RINGING }, { SIP_181_CALL_IS_BEING_FORWARDED }, { SIP_182_QUEUED }, { SIP_183_SESSION_PROGRESS }, { SIP_200_OK }, { SIP_202_ACCEPTED }, { SIP_300_MULTIPLE_CHOICES }, { SIP_301_MOVED_PERMANENTLY }, { SIP_302_MOVED_TEMPORARILY }, { SIP_305_USE_PROXY }, { SIP_380_ALTERNATIVE_SERVICE }, { SIP_400_BAD_REQUEST }, { SIP_401_UNAUTHORIZED }, { SIP_402_PAYMENT_REQUIRED }, { SIP_403_FORBIDDEN }, { SIP_404_NOT_FOUND }, { SIP_405_METHOD_NOT_ALLOWED }, { SIP_406_NOT_ACCEPTABLE }, { SIP_407_PROXY_AUTH_REQUIRED }, { SIP_408_REQUEST_TIMEOUT }, { SIP_409_CONFLICT }, { SIP_410_GONE }, { SIP_411_LENGTH_REQUIRED }, { SIP_413_REQUEST_TOO_LARGE }, { SIP_414_REQUEST_URI_TOO_LONG }, { SIP_415_UNSUPPORTED_MEDIA }, { SIP_416_UNSUPPORTED_URI }, { SIP_420_BAD_EXTENSION }, { SIP_421_EXTENSION_REQUIRED }, { SIP_422_SESSION_TIMER_TOO_SMALL }, { SIP_423_INTERVAL_TOO_BRIEF }, { SIP_423_REGISTRATION_TOO_BRIEF }, { SIP_480_TEMPORARILY_UNAVAILABLE }, { SIP_481_NO_TRANSACTION }, { SIP_481_NO_CALL }, { SIP_482_LOOP_DETECTED }, { SIP_483_TOO_MANY_HOPS }, { SIP_484_ADDRESS_INCOMPLETE }, { SIP_485_AMBIGUOUS }, { SIP_486_BUSY_HERE }, { SIP_487_REQUEST_TERMINATED }, { SIP_487_REQUEST_CANCELLED }, { SIP_488_NOT_ACCEPTABLE }, { SIP_489_BAD_EVENT }, { SIP_491_REQUEST_PENDING }, { SIP_493_UNDECIPHERABLE }, { SIP_500_INTERNAL_SERVER_ERROR }, { SIP_501_NOT_IMPLEMENTED }, { SIP_502_BAD_GATEWAY }, { SIP_503_SERVICE_UNAVAILABLE }, { SIP_504_GATEWAY_TIME_OUT }, { SIP_505_VERSION_NOT_SUPPORTED }, { SIP_513_MESSAGE_TOO_LARGE }, { SIP_600_BUSY_EVERYWHERE }, { SIP_603_DECLINE }, { SIP_604_DOES_NOT_EXIST_ANYWHERE }, { SIP_606_NOT_ACCEPTABLE }, { 0, NULL } }; int i; for (i = 0; errors[i].status; i++) TEST_S(errors[i].phrase, sip_status_phrase(errors[i].status)); } END(); } /** Test parser and header manipulation */ static int parser_test(void) { msg_t *msg; sip_t *sip; su_home_t *home; sip_route_t *r; sip_request_t sip_request[1] = { SIP_REQUEST_INIT() }; sip_status_t sip_status[1] = { SIP_STATUS_INIT() }; sip_header_t sip_unknown[1] = { SIP_UNKNOWN_INIT() }; sip_separator_t sip_separator[1] = { SIP_SEPARATOR_INIT() }; sip_payload_t sip_payload[1] = { SIP_PAYLOAD_INIT() }; sip_via_t sip_via[1] = { SIP_VIA_INIT() }; sip_route_t sip_route[1] = { SIP_ROUTE_INIT() }; sip_record_route_t sip_record_route[1] = { SIP_RECORD_ROUTE_INIT() }; sip_max_forwards_t sip_max_forwards[1] = { SIP_MAX_FORWARDS_INIT() }; sip_from_t sip_from[1] = { SIP_FROM_INIT() }; sip_to_t sip_to[1] = { SIP_TO_INIT() }; sip_call_id_t sip_call_id[1] = { SIP_CALL_ID_INIT() }; sip_cseq_t sip_cseq[1] = { SIP_CSEQ_INIT() }; sip_contact_t sip_contact[1] = { SIP_CONTACT_INIT() }; sip_expires_t sip_expires[1] = { SIP_EXPIRES_INIT() }; sip_date_t sip_date[1] = { SIP_DATE_INIT() }; sip_retry_after_t sip_retry_after[1] = { SIP_RETRY_AFTER_INIT() }; sip_timestamp_t sip_timestamp[1] = { SIP_TIMESTAMP_INIT() }; sip_subject_t sip_subject[1] = { SIP_SUBJECT_INIT() }; sip_priority_t sip_priority[1] = { SIP_PRIORITY_INIT() }; sip_call_info_t sip_call_info[1] = { SIP_CALL_INFO_INIT() }; sip_organization_t sip_organization[1] = { SIP_ORGANIZATION_INIT() }; sip_server_t sip_server[1] = { SIP_SERVER_INIT() }; sip_user_agent_t sip_user_agent[1] = { SIP_USER_AGENT_INIT() }; sip_in_reply_to_t sip_in_reply_to[1] = { SIP_IN_REPLY_TO_INIT() }; sip_accept_t sip_accept[1] = { SIP_ACCEPT_INIT() }; sip_accept_encoding_t sip_accept_encoding[1] = { SIP_ACCEPT_ENCODING_INIT() }; sip_accept_language_t sip_accept_language[1] = { SIP_ACCEPT_LANGUAGE_INIT() }; sip_session_expires_t sip_session_expires[1] = { SIP_SESSION_EXPIRES_INIT() }; sip_min_se_t sip_min_se[1] = { SIP_MIN_SE_INIT() }; sip_allow_t sip_allow[1] = { SIP_ALLOW_INIT() }; sip_require_t sip_require[1] = { SIP_REQUIRE_INIT() }; sip_proxy_require_t sip_proxy_require[1] = { SIP_PROXY_REQUIRE_INIT() }; sip_supported_t sip_supported[1] = { SIP_SUPPORTED_INIT() }; sip_unsupported_t sip_unsupported[1] = { SIP_UNSUPPORTED_INIT() }; #if SIP_HAVE_ENCRYPTION sip_encryption_t sip_encryption[1] = { SIP_ENCRYPTION_INIT() }; #endif #if SIP_HAVE_RESPONSE_KEY sip_response_key_t sip_response_key[1] = { SIP_RESPONSE_KEY_INIT() }; #endif sip_proxy_authenticate_t sip_proxy_authenticate[1] = { SIP_PROXY_AUTHENTICATE_INIT() }; sip_proxy_authorization_t sip_proxy_authorization[1] = { SIP_PROXY_AUTHORIZATION_INIT() }; sip_authorization_t sip_authorization[1] = { SIP_AUTHORIZATION_INIT() }; sip_www_authenticate_t sip_www_authenticate[1] = { SIP_WWW_AUTHENTICATE_INIT() }; sip_error_info_t sip_error_info[1] = { SIP_ERROR_INFO_INIT() }; sip_warning_t sip_warning[1] = { SIP_WARNING_INIT() }; sip_mime_version_t sip_mime_version[1] = { SIP_MIME_VERSION_INIT() }; sip_content_type_t sip_content_type[1] = { SIP_CONTENT_TYPE_INIT() }; sip_content_encoding_t sip_content_encoding[1] = { SIP_CONTENT_ENCODING_INIT() }; sip_content_disposition_t sip_content_disposition[1] = { SIP_CONTENT_DISPOSITION_INIT() }; sip_content_length_t sip_content_length[1] = { SIP_CONTENT_LENGTH_INIT() }; BEGIN(); home = su_home_new(sizeof *home); msg = read_message(MSG_DO_EXTRACT_COPY, "INVITE sip:John_Smith@tct.hut.fi SIP/2.0\r\n" "To: John Smith \r\n" " ; tag = deadbeef\r\n" "From: http://www.cs.columbia.edu\r\n" "Call-ID: 0ha0isndaksdj@10.1.2.3\r\n" "CSeq : 8 INVITE\r\n" "Via: SIP/2.0/UDP 135.180.130.133\r\n" "Route: , sip:2@b;lr=2, \r\n" "Route: \r\n" "Route: sip:2@e;lr=5, \r\n" "Route: , ;lr=8\r\n" "Content-Type: application/sdp\r\n" "Contact: Joe Bob Briggs ; bar=\"foo baa\", sip:kuik@foo.invalid\r\n" "Via: SIP/2.0/UDP [aa:bb::1]:5061\r\n" "\r\n" "v=0\r\n" "o=mhandley 29739 7272939 IN IP4 126.5.4.3\r\n" "c=IN IP4 135.180.130.88\r\n" "m=audio 492170 RTP/AVP 0 12\r\n" "m=video 3227 RTP/AVP 31\r\n" "a=rtpmap:31 LPC\r\n"); sip = sip_object(msg); TEST_1(home && msg && sip); TEST_1(sip_is_request((sip_header_t *)sip->sip_request)); TEST_1(sip->sip_via); TEST_1(sip->sip_via->v_next); TEST_1(sip->sip_via->v_next->v_next == NULL); TEST_1(sip_sanity_check(sip) == 0); TEST_1(r = sip->sip_route); TEST_1(r->r_common->h_data); TEST_1(r = r->r_next); TEST_1(r->r_common->h_data); TEST_1(r = r->r_next); TEST_1(r->r_common->h_data); TEST_1(r = r->r_next); TEST_1(r->r_common->h_data); TEST_1(r = r->r_next); TEST_1(r->r_common->h_data); TEST_1(r = r->r_next); TEST_1(r->r_common->h_data); TEST_1(r = r->r_next); TEST_1(r->r_common->h_data); TEST_1(r = r->r_next); TEST_1(r->r_common->h_data); TEST_1(!r->r_next); TEST_1(r = sip_route_fix(sip->sip_route)); TEST_1(!r->r_common->h_data); TEST_1(r = r->r_next); TEST_1(!r->r_common->h_data); TEST_1(r = r->r_next); TEST_1(!r->r_common->h_data); TEST_1(r = r->r_next); TEST_1(r->r_common->h_data); TEST_1(r = r->r_next); TEST_1(!r->r_common->h_data); TEST_1(r = r->r_next); TEST_1(!r->r_common->h_data); TEST_1(r = r->r_next); TEST_1(!r->r_common->h_data); TEST_1(r = r->r_next); TEST_1(!r->r_common->h_data); TEST_1(!r->r_next); /* Quiet lots of warnings */ #define _msg_header_offset msg_header_offset #define msg_header_offset(msg, sip, h) \ _msg_header_offset(msg, (msg_pub_t *)sip, (msg_header_t *)h) TEST_P(msg_header_offset(msg, sip, sip_request), &sip->sip_request); TEST_P(msg_header_offset(msg, sip, sip_status), &sip->sip_status); TEST_P(msg_header_offset(msg, sip, sip_unknown), &sip->sip_unknown); TEST_P(msg_header_offset(msg, sip, sip_separator), &sip->sip_separator); TEST_P(msg_header_offset(msg, sip, sip_payload), &sip->sip_payload); TEST_P(msg_header_offset(msg, sip, sip_via), &sip->sip_via); TEST_P(msg_header_offset(msg, sip, sip_route), &sip->sip_route); TEST_P(msg_header_offset(msg, sip, sip_record_route), &sip->sip_record_route); TEST_P(msg_header_offset(msg, sip, sip_max_forwards), &sip->sip_max_forwards); TEST_P(msg_header_offset(msg, sip, sip_from), &sip->sip_from); TEST_P(msg_header_offset(msg, sip, sip_to), &sip->sip_to); TEST_P(msg_header_offset(msg, sip, sip_call_id), &sip->sip_call_id); TEST_P(msg_header_offset(msg, sip, sip_cseq), &sip->sip_cseq); TEST_P(msg_header_offset(msg, sip, sip_contact), &sip->sip_contact); TEST_P(msg_header_offset(msg, sip, sip_expires), &sip->sip_expires); TEST_P(msg_header_offset(msg, sip, sip_date), &sip->sip_date); TEST_P(msg_header_offset(msg, sip, sip_retry_after), &sip->sip_retry_after); TEST_P(msg_header_offset(msg, sip, sip_timestamp), &sip->sip_timestamp); TEST_P(msg_header_offset(msg, sip, sip_subject), &sip->sip_subject); TEST_P(msg_header_offset(msg, sip, sip_priority), &sip->sip_priority); TEST_P(msg_header_offset(msg, sip, sip_call_info), &sip->sip_call_info); TEST_P(msg_header_offset(msg, sip, sip_organization), &sip->sip_organization); TEST_P(msg_header_offset(msg, sip, sip_server), &sip->sip_server); TEST_P(msg_header_offset(msg, sip, sip_user_agent), &sip->sip_user_agent); TEST_P(msg_header_offset(msg, sip, sip_in_reply_to), &sip->sip_in_reply_to); TEST_P(msg_header_offset(msg, sip, sip_accept), &sip->sip_accept); TEST_P(msg_header_offset(msg, sip, sip_accept_encoding), &sip->sip_accept_encoding); TEST_P(msg_header_offset(msg, sip, sip_accept_language), &sip->sip_accept_language); TEST_P(msg_header_offset(msg, sip, sip_session_expires), &sip->sip_session_expires); TEST_P(msg_header_offset(msg, sip, sip_min_se), &sip->sip_min_se); TEST_P(msg_header_offset(msg, sip, sip_allow), &sip->sip_allow); TEST_P(msg_header_offset(msg, sip, sip_require), &sip->sip_require); TEST_P(msg_header_offset(msg, sip, sip_proxy_require), &sip->sip_proxy_require); TEST_P(msg_header_offset(msg, sip, sip_supported), &sip->sip_supported); TEST_P(msg_header_offset(msg, sip, sip_unsupported), &sip->sip_unsupported); #if SIP_HAVE_ENCRYPTION TEST(msg_header_offset(msg, sip, sip_encryption), &sip->sip_encryption); #endif #if SIP_HAVE_RESPONSE_KEY TEST(msg_header_offset(msg, sip, sip_response_key), &sip->sip_response_key); #endif TEST_P(msg_header_offset(msg, sip, sip_proxy_authenticate), &sip->sip_proxy_authenticate); TEST_P(msg_header_offset(msg, sip, sip_proxy_authorization), &sip->sip_proxy_authorization); TEST_P(msg_header_offset(msg, sip, sip_authorization), &sip->sip_authorization); TEST_P(msg_header_offset(msg, sip, sip_www_authenticate), &sip->sip_www_authenticate); TEST_P(msg_header_offset(msg, sip, sip_error_info), &sip->sip_error_info); TEST_P(msg_header_offset(msg, sip, sip_warning), &sip->sip_warning); TEST_P(msg_header_offset(msg, sip, sip_mime_version), &sip->sip_mime_version); TEST_P(msg_header_offset(msg, sip, sip_content_type), &sip->sip_content_type); TEST_P(msg_header_offset(msg, sip, sip_content_encoding), &sip->sip_content_encoding); TEST_P(msg_header_offset(msg, sip, sip_content_disposition), &sip->sip_content_disposition); TEST_P(msg_header_offset(msg, sip, sip_content_length), &sip->sip_content_length); TEST_SIZE(sip_request_class->hc_params, 0); TEST_SIZE(sip_status_class->hc_params, 0); TEST_SIZE(sip_unknown_class->hc_params, 0); TEST_SIZE(sip_separator_class->hc_params, 0); TEST_SIZE(sip_payload_class->hc_params, 0); TEST_SIZE(sip_via_class->hc_params, offsetof(sip_via_t, v_params)); TEST_SIZE(sip_route_class->hc_params, offsetof(sip_route_t, r_params)); TEST_SIZE(sip_record_route_class->hc_params, offsetof(sip_record_route_t, r_params)); TEST_SIZE(sip_max_forwards_class->hc_params, 0); TEST_SIZE(sip_from_class->hc_params, offsetof(sip_from_t, a_params)); TEST_SIZE(sip_to_class->hc_params, offsetof(sip_to_t, a_params)); TEST_SIZE(sip_call_id_class->hc_params, 0); TEST_SIZE(sip_cseq_class->hc_params, 0); TEST_SIZE(sip_contact_class->hc_params, offsetof(sip_contact_t, m_params)); TEST_SIZE(sip_expires_class->hc_params, 0); TEST_SIZE(sip_date_class->hc_params, 0); TEST_SIZE(sip_retry_after_class->hc_params, offsetof(sip_retry_after_t, af_params)); TEST_SIZE(sip_timestamp_class->hc_params, 0); TEST_SIZE(sip_subject_class->hc_params, 0); TEST_SIZE(sip_priority_class->hc_params, 0); TEST_SIZE(sip_call_info_class->hc_params, offsetof(sip_call_info_t, ci_params)); TEST_SIZE(sip_organization_class->hc_params, 0); TEST_SIZE(sip_server_class->hc_params, 0); TEST_SIZE(sip_user_agent_class->hc_params, 0); TEST_SIZE(sip_in_reply_to_class->hc_params, offsetof(sip_in_reply_to_t, k_items)); TEST_SIZE(sip_accept_class->hc_params, offsetof(sip_accept_t, ac_params)); TEST_SIZE(sip_accept_encoding_class->hc_params, offsetof(sip_accept_encoding_t, aa_params)); TEST_SIZE(sip_accept_language_class->hc_params, offsetof(sip_accept_language_t, aa_params)); TEST_SIZE(sip_session_expires_class->hc_params, offsetof(sip_session_expires_t, x_params)); TEST_SIZE(sip_min_se_class->hc_params, offsetof(sip_min_se_t, min_params)); TEST_SIZE(sip_allow_class->hc_params, offsetof(sip_allow_t, k_items)); TEST_SIZE(sip_require_class->hc_params, offsetof(sip_require_t, k_items)); TEST_SIZE(sip_proxy_require_class->hc_params, offsetof(sip_proxy_require_t, k_items)); TEST_SIZE(sip_supported_class->hc_params, offsetof(sip_supported_t, k_items)); TEST_SIZE(sip_unsupported_class->hc_params, offsetof(sip_unsupported_t, k_items)); #if SIP_HAVE_ENCRYPTION TEST_SIZE(sip_encryption_class->hc_params, offsetof(sip_encryption_t, au_params)); #endif #if SIP_HAVE_RESPONSE_KEY TEST_SIZE(sip_response_key_class->hc_params, offsetof(sip_response_key_t, au_params)); #endif TEST_SIZE(sip_proxy_authenticate_class->hc_params, offsetof(sip_proxy_authenticate_t, au_params)); TEST_SIZE(sip_proxy_authorization_class->hc_params, offsetof(sip_proxy_authorization_t, au_params)); TEST_SIZE(sip_authorization_class->hc_params, offsetof(sip_authorization_t, au_params)); TEST_SIZE(sip_www_authenticate_class->hc_params, offsetof(sip_www_authenticate_t, au_params)); TEST_SIZE(sip_error_info_class->hc_params, offsetof(sip_error_info_t, ei_params)); TEST_SIZE(sip_alert_info_class->hc_params, offsetof(sip_alert_info_t, ai_params)); TEST_SIZE(sip_reply_to_class->hc_params, offsetof(sip_reply_to_t, rplyto_params)); TEST_SIZE(sip_warning_class->hc_params, 0); TEST_SIZE(sip_mime_version_class->hc_params, 0); TEST_SIZE(sip_content_type_class->hc_params, offsetof(sip_content_type_t, c_params)); TEST_SIZE(sip_content_encoding_class->hc_params, offsetof(sip_content_encoding_t, k_items)); TEST_SIZE(sip_content_disposition_class->hc_params, offsetof(sip_content_disposition_t, cd_params)); TEST_SIZE(sip_content_length_class->hc_params, 0); msg_destroy(msg); su_home_unref(home); END(); } static int count(sip_common_t *h) { sip_header_t *sh = (sip_header_t *)h; unsigned n; for (n = 0; sh; sh = sh->sh_next) n++; return n; } static int len(sip_common_t *h) { sip_header_t *sh = (sip_header_t *)h; unsigned n; for (n = 0; sh; sh = sh->sh_next) { if (n) n +=2; n += sip_header_field_e(NULL, 0, sh, 0); } return n; } static int sip_header_test(void) { msg_t *msg; sip_t *sip; su_home_t *home; void const *x; sip_via_t *v, *v0; tagi_t const *tl; tagi_t *tl0; BEGIN(); home = su_home_new(sizeof *home); TEST_1(msg = read_message(MSG_DO_EXTRACT_COPY, "MESSAGE sip:John_Smith@tct.hut.fi SIP/2.0\r\n" "To: John Smith \r\n" " ; tag = deadbeef\r\n" "From:h\r\n" "Call-ID: 0ha0isndaksdj@10.1.2.3\r\n" "CSeq : 8 MESSAGE\r\n" "Via: SIP/2.0/UDP 135.180.130.133;received=defa:daf::00:12\r\n" "Via: SIP/2.0/TCP 135.180.130.131;branch=deadbeef.barf;ttl=3;hidden,," "SIP/2.0/UDP\r\n 135.180.130.131:5061;received=[defa::00:12]\r\n" "Contact: Joe Bob Briggs ; bar=\042foo baa\042, , sip:barf\r\n" "Via: SIP/2.0/UDP [aa:bb::1]:5061\r\n" "Record-Route: Test Element ;param=12+1\r\n" "Record-Route: sip:135.180.130.133,,\r\n" "\t,Test Element ;param=12+1\r\n" "Path: Test \r\n" "Service-Route: Test \r\n" "Route: ,\r\n" "Unknown-Extension: hip\r\n" "Hide: hop\r\n" "Max-Forwards: 12\r\n" "Min-Expires: 150\r\n" "Timestamp: 10.010 0.000100\r\n" "Suppress-Body-If-Match: humppa \t\r\n" "Suppress-Notify-If-Match: zumppa\r\n" " \r\n" "Content-Type: application/sdp\r\n" "\r\n" "v=0\r\n" "o=mhandley 29739 7272939 IN IP4 126.5.4.3\r\n" "c=IN IP4 135.180.130.88\r\n" "m=audio 492170 RTP/AVP 0 12\r\n" "m=video 3227 RTP/AVP 31\r\n" "a=rtpmap:31 LPC\r\n")); TEST_1(sip = sip_object(msg)); TEST(count(sip->sip_request->rq_common), 1); TEST(count(sip->sip_to->a_common), 1); TEST(count(sip->sip_from->a_common), 1); TEST(count(sip->sip_cseq->cs_common), 1); TEST(count(sip->sip_call_id->i_common), 1); TEST(count(sip->sip_via->v_common), 4); TEST(count(sip->sip_contact->m_common), 3); TEST(count(sip->sip_content_type->c_common), 1); TEST(count(sip->sip_route->r_common), 0); TEST(count(sip->sip_record_route->r_common), 4); #if SU_HAVE_EXPERIMENTAL TEST(count(sip->sip_unknown->un_common), 2); #else TEST(count(sip->sip_unknown->un_common), 4); #endif TEST(count(sip->sip_error->er_common), 1); TEST(count(sip->sip_max_forwards->mf_common), 1); TEST(count(sip->sip_min_expires->me_common), 1); TEST(count(sip->sip_timestamp->ts_common), 1); TEST_S(sip->sip_contact->m_display, "Joe Bob Briggs"); TEST_1(sip->sip_contact->m_next->m_display != NULL); TEST_S(sip->sip_contact->m_next->m_display, ""); TEST_1(sip->sip_contact->m_next->m_next->m_display == NULL); TEST(sip->sip_max_forwards->mf_count, 12); TEST(sip->sip_min_expires->me_delta, 150); #if SU_HAVE_EXPERIMENTAL { sip_suppress_body_if_match_t *sbim; sip_suppress_notify_if_match_t *snim; TEST_1(sbim = sip_suppress_body_if_match(sip)); TEST_S(sbim->sbim_tag, "humppa"); TEST_SIZE(offsetof(msg_generic_t, g_value), offsetof(sip_suppress_body_if_match_t, sbim_tag)); TEST_1(snim = sip_suppress_notify_if_match(sip)); TEST_S(snim->snim_tag, "zumppa"); TEST_SIZE(offsetof(msg_generic_t, g_value), offsetof(sip_suppress_notify_if_match_t, snim_tag)); } #endif TEST_1(sip->sip_from->a_display); TEST_S(sip->sip_from->a_display, "h"); v0 = sip->sip_via; TEST_1(v = sip_via_copy(home, v0)); TEST(len(v->v_common), len(v0->v_common)); for (; v && v0; v = v->v_next, v0 = v0->v_next) { if (v->v_params) TEST_1(v->v_params != v0->v_params); if (v->v_branch) TEST_1(v->v_branch == v0->v_branch); } TEST_1(v == NULL && v0 == NULL); v0 = sip->sip_via; TEST_1(v = sip_via_dup(home, v0)); TEST(len(v->v_common), len(v0->v_common)); for (; v && v0; v = v->v_next, v0 = v0->v_next) { if (v->v_params) TEST_1(v->v_params != v0->v_params); if (v->v_branch) TEST_1(v->v_branch != v0->v_branch); } TEST_1(v == NULL && v0 == NULL); TEST(sip_add_dup(msg, sip, (sip_header_t *)sip->sip_max_forwards), 0); /* Max-Forwards is last header? */ TEST_P(sip->sip_max_forwards, sip->sip_content_type->c_common->h_succ); TEST(sip_to_tag(home, sip->sip_to, sip->sip_to->a_tag), 0); TEST(sip_to_tag(home, sip->sip_to, "tag=deadbeef"), 0); TEST(sip_to_tag(home, sip->sip_to, "foofaa"), -1); msg_header_remove(msg, (msg_pub_t *)sip, (msg_header_t *)sip->sip_payload); TEST(sip_add_tl(msg, sip, SIPTAG_FROM(SIP_NONE), SIPTAG_VIA(SIP_NONE), SIPTAG_VIA_STR("SIP/2.0/SCTP foo.bar.com:5060;branch=foo"), SIPTAG_TO_STR(""), SIPTAG_HEADER_STR("Authorization: Basic foobar\n" "Priority:\n urgent"), SIPTAG_HEADER_STR("Accept: foo/bar\n" "\n" "test payload\n"), SIPTAG_TIMESTAMP(sip->sip_timestamp), SIPTAG_END(), SIPTAG_REFER_TO_STR(""), TAG_END()), 0); TEST_1(sip->sip_from == NULL); TEST_1(sip->sip_via); TEST_1(sip->sip_via->v_next == NULL); TEST_S(sip->sip_via->v_protocol, "SIP/2.0/SCTP"); TEST_1(sip->sip_authorization); TEST_1(sip->sip_priority); TEST_1(sip->sip_payload); TEST_S(sip->sip_payload->pl_data, "test payload\n"); TEST_1(sip->sip_timestamp); TEST_S(sip->sip_timestamp->ts_stamp, "10.010"); TEST_S(sip->sip_timestamp->ts_delay, "0.000100"); TEST_1(!sip->sip_refer_to); TEST_1(tl = tl0 = tl_list(SIPTAG_TO_STR(""), SIPTAG_END(), SIPTAG_REFER_TO_STR(""), TAG_END())); /* sip_add_tagis should stop after SIPTAG_END() */ TEST(sip_add_tagis(msg, sip, &tl), 0); TEST_P(tl, tl0 + 2); tl_free(tl0); TEST_P(sip_timestamp_make(home, "+1"), NULL); TEST_P(sip_timestamp_make(home, "1.0e6 13.0"), NULL); TEST_1(sip_timestamp_make(home, "1.0 .001")); TEST_P(sip_timestamp_make(home, ".0001 13.0"), NULL); TEST_1(x = sip->sip_path); TEST_1(sip_add_make(msg, sip, sip_path_class, "") == 0); TEST_P(x, sip->sip_path->r_next); TEST_1(x = sip->sip_service_route); TEST_1(sip_add_make(msg, sip, sip_service_route_class, "") == 0); TEST_P(x, sip->sip_service_route); TEST_1(sip->sip_service_route->r_next); /* Detect parsing errors */ TEST_1(!sip_cseq_make(home, "21874624876976 INVITE")); TEST_1(!sip_cseq_make(home, "218746INVITE")); msg_destroy(msg), msg = NULL; su_home_unref(home), home = NULL; END(); } static int test_bad_packet(void) { msg_t *msg; sip_t *sip; su_home_t *home; BEGIN(); home = su_home_new(sizeof *home); TEST_1(msg = read_message(MSG_DO_EXTRACT_COPY, "MESSAGE SIP/2.0\r\n" "To: John Smith \r\n" " ; tag = deadbeef\r\n" "From:h\r\n" "Call-ID: 0ha0isndaksdj@10.1.2.3\r\n" "CSeq : 8 MESSAGE\r\n" "Via: SIP/2.0/UDP 135.180.130.133;received=defa:daf::00:12\r\n" "Via: SIP/2.0/TCP 135.180.130.131;branch=deadbeef.barf;ttl=3;hidden,," "SIP/2.0/UDP\r\n 135.180.130.131:5061;received=[defa::00:12]\r\n" "Contact: Joe Bob Briggs ; bar=\042foo baa\042, sip:kuik@foo.invalid\r\n" "Via: SIP/2.0/UDP [aa:bb::1]:5061\0\0")); TEST_1(sip = sip_object(msg)); TEST(count(sip->sip_request->rq_common), 1); TEST(count(sip->sip_to->a_common), 1); TEST(count(sip->sip_from->a_common), 1); TEST(count(sip->sip_cseq->cs_common), 1); TEST(count(sip->sip_call_id->i_common), 1); TEST(count(sip->sip_via->v_common), 4); TEST(count(sip->sip_route->r_common), 0); TEST(sip->sip_request->rq_url->url_type, url_invalid); su_home_unref(home), home = NULL; msg_destroy(msg), msg = NULL; END(); } static int test_sip_list_header(void) { msg_t *msg; sip_t *sip; su_home_t *home; sip_allow_t *a; BEGIN(); home = su_home_new(sizeof *home); TEST_1(msg = read_message(0, "MESSAGE sip:John_Smith@tct.hut.fi SIP/2.0\r\n" "To: John Smith \r\n" "From: ;tag=foobar\r\n" "Call-ID: 0ha0isndaksdj@10.1.2.3\r\n" "CSeq : 8 MESSAGE\r\n" "Via: SIP/2.0/UDP 135.180.130.133;received=defa:daf::00:12\r\n" "Via: SIP/2.0/TCP 135.180.130.131;branch=deadbeef.barf;ttl=3;hidden,," "SIP/2.0/UDP\r\n 135.180.130.131:5061;received=[defa::00:12]\r\n" "Contact: Joe Bob Briggs ; bar=\042foo baa\042, , sip:barf\r\n" "Allow: INVITE\r\n" "Allow: ACK\r\n" "Allow: CANCEL\r\n" "Allow: BYE\r\n" "Allow: OPTIONS\r\n" "Allow: MESSAGE\r\n" "Allow: KUIK\r\n" "Max-Forwards: 12\r\n" "Content-Type: text/plain\r\n" "\r\n" "hello\r\n")); TEST_1(sip = sip_object(msg)); TEST_1(a = sip->sip_allow); TEST_1(a->k_items); TEST_1(a->k_next == NULL); TEST_1(sip_is_allowed(a, SIP_METHOD_INVITE)); TEST_1(!sip_is_allowed(a, SIP_METHOD_PUBLISH)); TEST_1(sip_is_allowed(a, SIP_METHOD(KUIK))); TEST_1(!sip_is_allowed(a, SIP_METHOD(kuik))); TEST_1(a = sip_allow_make(home, "")); TEST_S(sip_header_as_string(home, (void *)a), ""); TEST_1(a = sip_allow_make(home, "INVITE, PUBLISH")); TEST_1(sip_is_allowed(a, SIP_METHOD_INVITE)); /* Test with list header */ TEST_1(msg_header_add_dup(msg, NULL, (msg_header_t *)a) == 0); TEST_1(a = sip_allow_make(home, "MESSAGE, SUBSCRIBE")); TEST_1(msg_header_add_dup(msg, NULL, (msg_header_t *)a) == 0); TEST_1(msg_header_add_make(msg, NULL, sip_allow_class, "kuik") == 0); TEST_1(a = sip->sip_allow); TEST_1(a->k_items); TEST_S(a->k_items[0], "INVITE"); TEST_S(a->k_items[1], "ACK"); TEST_S(a->k_items[2], "CANCEL"); TEST_S(a->k_items[3], "BYE"); TEST_S(a->k_items[4], "OPTIONS"); TEST_S(a->k_items[5], "MESSAGE"); TEST_S(a->k_items[6], "KUIK"); TEST_S(a->k_items[7], "PUBLISH"); TEST_S(a->k_items[8], "SUBSCRIBE"); TEST_S(a->k_items[9], "kuik"); TEST_P(a->k_items[10], NULL); msg_destroy(msg), msg = NULL; su_home_unref(home), home = NULL; END(); } static int test_prack(void) { /* Test RAck and RSeq */ su_home_t *home; sip_rack_t *rack, *rack0; sip_rseq_t *rseq, *rseq0; BEGIN(); TEST_1(home = su_home_new(sizeof *home)); TEST_1(rack = sip_rack_make(home, "1 2 INVITE")); TEST(rack->ra_response, 1); TEST(rack->ra_cseq, 2); TEST(rack->ra_method, sip_method_invite); TEST_S(rack->ra_method_name, "INVITE"); TEST_1(rseq = sip_rseq_make(home, "3")); TEST(rseq->rs_response, 3); TEST_1(rack0 = sip_rack_dup(home, rack)); TEST_P(rack0->ra_method_name, rack->ra_method_name); TEST_1(rseq0 = sip_rseq_dup(home, rseq)); TEST_1(rack = sip_rack_make(home, "4\r\n\t5\r\n\tEXTRA")); TEST(rack->ra_response, 4); TEST(rack->ra_cseq, 5); TEST(rack->ra_method, sip_method_unknown); TEST_S(rack->ra_method_name, "EXTRA"); TEST_1(rseq = sip_rseq_make(home, " 6 ")); TEST(rseq->rs_response, 6); TEST_1(rack0 = sip_rack_dup(home, rack)); TEST_1(rack0->ra_method_name != rack->ra_method_name); TEST_1(rseq0 = sip_rseq_dup(home, rseq)); su_home_unref(home); END(); } /* Test MIME headers */ static int test_accept(void) { /* Test Accept header */ sip_accept_t *ac, *ac0; sip_accept_encoding_t *aa; su_home_t *home; BEGIN(); TEST_1(home = su_home_new(sizeof *home)); TEST_1(ac = ac0 = sip_accept_make(home, "image / jpeg ; q = 0.6,, image/png, image/*, */* ")); TEST_S(ac->ac_type, "image/jpeg"); TEST_S(ac->ac_subtype, "jpeg"); TEST_1(ac->ac_params && ac->ac_params[0]); TEST_S(ac->ac_params[0], "q=0.6"); TEST_S(ac->ac_q, "0.6"); TEST_1(ac = ac->ac_next); TEST_S(ac->ac_type, "image/png"); TEST_S(ac->ac_subtype, "png"); TEST_1(ac = ac->ac_next); TEST_S(ac->ac_type, "image/*"); TEST_S(ac->ac_subtype, "*"); TEST_1(aa = sip_accept_encoding_make(home, "gzip")); TEST_1(aa = sip_accept_encoding_make(home, "gzip;q=1.0,deflate;q=1.0")); TEST_S(aa->aa_value, "gzip"); TEST_S(aa->aa_q, "1.0"); TEST_1(aa->aa_next); TEST_S(aa->aa_next->aa_value, "deflate"); TEST_1(aa = sip_accept_encoding_make(home, ",")); TEST_S(aa->aa_value, ""); TEST_1(!aa->aa_next); TEST_1(aa = sip_accept_encoding_make(home, "")); TEST_S(aa->aa_value, ""); TEST_1(!aa->aa_next); TEST_1(aa = sip_accept_language_make(home, "fi")); TEST_1(aa = sip_accept_language_make(home, "fi;q=1.0,sv;q=1.0")); TEST_S(aa->aa_value, "fi"); TEST_S(aa->aa_q, "1.0"); TEST_1(aa->aa_next); TEST_S(aa->aa_next->aa_value, "sv"); TEST_1(aa = sip_accept_language_make(home, ",")); TEST_S(aa->aa_value, ""); TEST_1(!aa->aa_next); TEST_1(aa = sip_accept_language_make(home, "")); TEST_S(aa->aa_value, ""); TEST_1(!aa->aa_next); su_home_unref(home); END(); } static int test_content_disposition(void) { sip_content_disposition_t *cd, *cd0; su_home_t *home; BEGIN(); TEST_1(home = su_home_new(sizeof *home)); TEST_1(cd = cd0 = sip_content_disposition_make(home, "sip-cgi ; action = store;handling=required ")); TEST_S(cd->cd_type, "sip-cgi"); TEST_1(cd->cd_params && cd->cd_params[0] && cd->cd_params[1] && !cd->cd_params[2]); TEST_S(cd->cd_params[0], "action=store"); TEST_S(cd->cd_params[1], "handling=required"); TEST_S(cd->cd_handling, "required"); TEST_1(cd->cd_required); TEST_1(!cd->cd_optional); su_home_unref(home); END(); } static int test_content_type(void) { sip_content_type_t *c; sip_content_type_t c0[1]; su_home_t *home; BEGIN(); TEST_1(home = su_home_new(sizeof *home)); TEST_1(c = sip_content_type_make(home, "application/sdp ; charset = utf-8")); TEST_S(c->c_type, "application/sdp"); TEST_S(c->c_subtype, "sdp"); TEST_1(c->c_params && c->c_params[0] && !c->c_params[1]); TEST_S(c->c_params[0], "charset=utf-8"); TEST_P(c->c_params[1], NULL); sip_content_type_init(c0); c = sip_content_type_dup(home, c0); TEST_P(c->c_type, NULL); TEST_P(c->c_subtype, NULL); c0->c_type = "text"; c = sip_content_type_dup(home, c0); TEST_S(c->c_type, "text"); TEST_P(c->c_subtype, NULL); su_home_unref(home); END(); } static int test_www_authenticate(void) { sip_www_authenticate_t *www; su_home_t *home; char const *s; msg_t *msg; sip_t *sip; BEGIN(); TEST_1(home = su_home_new(sizeof *home)); TEST_1(www = sip_www_authenticate_make (home, "Digest realm=\"Registered_Subscribers\",\n" "domain=\"sip:206.229.26.61\",\n" "nonce=\"20dfb7e5a77abee7a02dbe53efe42cdd\", " "opaque=\"423767123y723742376423762376423784623782a794e58\",\n" "stale=FALSE,algorithm=MD5")); TEST_S(www->au_scheme, "Digest"); TEST_1(www->au_params && www->au_params[0] && www->au_params[1] && www->au_params[2] && www->au_params[3] && www->au_params[4] && www->au_params[5] && !www->au_params[6]); TEST_1(s = sip_header_as_string(home, (sip_header_t *)www)); TEST_1(strlen(s) >= 128); su_home_unref(home); TEST_1( msg = read_message( MSG_DO_EXTRACT_COPY, "SIP/2.0 401 Unauthorized" "\r\n" "Date: Wed, 07 Jan 2009 22:24:39 GMT" "\r\n" "WWW-Authenticate: Kerberos realm=\"SIP Communications Service\", targetname=\"sip/OCS1.flux.local\", version=3" "\r\n" "WWW-Authenticate: NTLM realm=\"SIP Communications Service\", targetname=\"OCS1.flux.local\", version=3" "\r\n" "From: ;epid=1234567890;tag=48BXgr379e85j" "\r\n" "To: ;transport=tls;tag=B57737091022903031FF204696B79CC4" "\r\n" "Call-ID: cf12f708-57ac-122c-ad90-6f23d7babf4f" "\r\n" "CSeq: 109565202 REGISTER" "\r\n" "Via: SIP/2.0/TLS 192.168.43.1:5069;branch=z9hG4bK47ZUrFK0v5eQa;received=192.168.43.1;ms-received-port=54059;ms-received-cid=E500" "\r\n" "Content-Length: 0" "\r\n")); TEST_1(sip = sip_object(msg)); TEST_1(www = sip->sip_www_authenticate); TEST_S(www->au_scheme, "Kerberos"); TEST_1(www = www->au_next); TEST_S(www->au_scheme, "NTLM"); msg_destroy(msg); END(); } int test_retry_after(void) { /* Test Session-Expires header */ sip_retry_after_t *af, *af0; su_home_t *home; char buf[64]; BEGIN(); TEST_1(home = su_home_new(sizeof *home)); TEST_1(af = sip_retry_after_make(home, "1800")); TEST(af->af_delta, 1800); TEST_1(af = sip_retry_after_make(home, "1800(foo); duration = 3600")); TEST_1(af->af_params && af->af_params[0]); TEST_S(af->af_comment, "foo"); TEST_S(af->af_params[0], "duration=3600"); TEST_S(af->af_duration, "3600"); TEST_1(af0 = sip_retry_after_dup(home, af)); TEST_1(af0->af_params && af0->af_params[0]); TEST_S(af0->af_comment, "foo"); TEST_S(af0->af_params[0], "duration=3600"); TEST_S(af0->af_duration, "3600"); TEST_1(sip_retry_after_e(buf, sizeof(buf), (sip_header_t *)af0, 0)); TEST_S(buf, "1800 (foo) ;duration=3600"); su_home_unref(home); END(); } int test_session_expires(void) { /* Test Session-Expires header */ sip_session_expires_t *x, *x0; su_home_t *home; BEGIN(); TEST_1(home = su_home_new(sizeof *home)); TEST_1(x = x0 = sip_session_expires_make(home, "1800")); TEST(x->x_delta, 1800); TEST_1(x = x0 = sip_session_expires_make(home, "1800 ; refresher = uas")); TEST_1(x->x_params && x->x_params[0]); TEST_S(x->x_params[0], "refresher=uas"); TEST_S(x->x_refresher, "uas"); su_home_unref(home); END(); } int test_min_se(void) { /* Test Min-SE header */ sip_min_se_t *min, *min0; su_home_t *home; BEGIN(); TEST_1(home = su_home_new(sizeof *home)); TEST_1(min = min0 = sip_min_se_make(home, "1800")); TEST(min->min_delta, 1800); TEST_1(min = sip_min_se_dup(home, min0)); TEST(min->min_delta, 1800); TEST_1(min = sip_min_se_copy(home, min0)); TEST(min->min_delta, 1800); TEST_1(min = sip_min_se_make(home, "1999 ; foo = bar")); TEST(min->min_delta, 1999); TEST_1(min->min_params); TEST_S(min->min_params[0], "foo=bar"); TEST_1(min0 = sip_min_se_dup(home, min)); TEST(min0->min_delta, 1999); TEST_1(min0->min_params); TEST_S(min0->min_params[0], "foo=bar"); su_home_unref(home); END(); } int test_refer(void) { sip_refer_to_t *r, *r0; sip_referred_by_t *b, *b0; sip_replaces_t *rp, *rp0; char const *s0; su_home_t *home; BEGIN(); char const m[] = "REFER sip:10.3.3.104 SIP/2.0\r\n" "Via: SIP/2.0/UDP 10.3.3.8;branch=z9hG4bKb8389b4c1BA8899\r\n" "From: \"Anthony Minessale\" ;tag=5AA04E0-66CFC37F\r\n" "To: ;user=phone;tag=j6Fg9y7t8KNrF\r\n" "CSeq: 4 REFER\r\n" "Call-ID: a14822a4-5932e3ea-d7f37191@10.3.3.8\r\n" "Contact: \r\n" "User-Agent: PolycomSoundPointIP-SPIP_500-UA/1.4.1\r\n" "Refer-To: \r\n" "Referred-By: \"Anthony Minessale\" \r\n" "Refer-Sub: true\r\n" "Max-Forwards: 70\r\n" "Content-Length: 0\r\n" "\r\n"; msg_t *msg; sip_t *sip; msg_iovec_t *iovec; isize_t veclen, i, size; char *back; sip_refer_sub_t *rs; TEST_1(home = su_home_new(sizeof *home)); /* Check that Refer-Sub has now been added to our parser */ TEST_1(msg_mclass_insert_with_mask(test_mclass, sip_refer_sub_class, 0, 0) == -1); msg = read_message(0, m); TEST_1(msg); TEST_1(sip = sip_object(msg)); TEST_1(sip->sip_refer_to); TEST_S(sip->sip_refer_to->r_url->url_headers, "Replaces=7d84c014-321368da-efa90f41%40" "10.3.3.8%3Bto-tag%3DpaNKgBB9vQe3D%3Bfrom-tag%3D93AC8D50-7CF6DAAF"); TEST_1(rs = sip_refer_sub(sip)); TEST_S(rs->rs_value, "true"); TEST_SIZE(msg_prepare(msg), strlen(m)); TEST_1(veclen = msg_iovec(msg, NULL, ISIZE_MAX)); TEST_1(iovec = su_zalloc(msg_home(home), veclen * (sizeof iovec[0]))); TEST_SIZE(msg_iovec(msg, iovec, veclen), veclen); for (i = 0, size = 0; i < veclen; i++) size += iovec[i].mv_len; TEST_1(back = su_zalloc(msg_home(msg), size + 1)); for (i = 0, size = 0; i < veclen; i++) { memcpy(back + size, iovec[i].mv_base, iovec[i].mv_len); size += iovec[i].mv_len; } back[size] = '\0'; TEST_S(back, m); TEST_1(r = r0 = sip_refer_to_make(home, "http://example.com;foo=bar")); TEST(r->r_url->url_type, url_http); TEST_1(r->r_params); TEST_S(r->r_params[0], "foo=bar"); r = sip_refer_to_dup(home, r0); TEST(r->r_url->url_type, url_http); TEST_1(r->r_params); TEST_S(r->r_params[0], "foo=bar"); TEST_1(r = r0 = sip_refer_to_make(home, s0 = "")); TEST_S(r->r_display, ""); TEST(r->r_url->url_type, url_http); TEST_P(r->r_params, NULL); r = sip_refer_to_dup(home, r0); TEST_S(r->r_display, ""); TEST(r->r_url->url_type, url_http); TEST_P(r->r_params, NULL); TEST_S(sip_header_as_string(home, (sip_header_t*)r), s0); TEST_1(r = r0 = sip_refer_to_make(home, "Web Site ;foo=bar")); TEST_S(r->r_display, "Web Site"); TEST(r->r_url->url_type, url_http); TEST_1(r->r_params); TEST_S(r->r_params[0], "foo=bar"); TEST_P(r->r_params[1], NULL); r = sip_refer_to_dup(home, r0); TEST(r->r_url->url_type, url_http); TEST_1(r->r_params); TEST_S(r->r_params[0], "foo=bar"); TEST_P(r->r_params[1], NULL); /* Test bad replaces without <> */ { char const s[] = "sip:2000@10.3.3.104?Replaces=7d84c014-321368da-efa90f41%4010.3.3.8" "%3Bto-tag%3DpaNKgBB9vQe3D%3Bfrom-tag%3D93AC8D50-7CF6DAAF" "\r\n"; char *str; TEST_1(r = r0 = sip_refer_to_make(home, s)); msg_fragment_clear(r->r_common); TEST_1(str = sip_header_as_string(home, (void *)r)); TEST_S(str, "<" "sip:2000@10.3.3.104?Replaces=7d84c014-321368da-efa90f41%4010.3.3.8" "%3Bto-tag%3DpaNKgBB9vQe3D%3Bfrom-tag%3D93AC8D50-7CF6DAAF" ">"); } su_home_unref(home); TEST_1(home = su_home_new(sizeof *home)); TEST_1(b = b0 = sip_referred_by_make(home, "sip:joe@example.edu;param=value")); TEST_P(b->b_display, NULL); TEST_1(b->b_params); TEST_P(b->b_cid, NULL); TEST_1(b = sip_referred_by_make(home, "John Doe " ";cid=\"foo@bar\"")); TEST_S(b->b_display, "John Doe"); TEST_1(b->b_params); TEST_1(b->b_cid); TEST_S(b->b_params[0] + 4, b->b_cid); b = sip_referred_by_dup(home, b0 = b); TEST_1(b); TEST_S(b->b_display, "John Doe"); TEST_1(b->b_cid); TEST_S(b->b_params[0] + 4, b->b_cid); TEST_S(b->b_cid, b0->b_cid); TEST(msg_header_replace_param(home, b->b_common, "cid=cid:8u432658725"), 1); TEST_S(b->b_cid, "cid:8u432658725"); TEST(msg_header_remove_param(b->b_common, "cid"), 1); TEST_P(b->b_cid, NULL); /* XXX */ #define WORD ALPHA DIGIT "-.!%*_+`'~()<>:\\\"/[]?{}" rp = sip_replaces_make(home, WORD "@" WORD ";to-tag=foo;from-tag=bar" ";early-only = yes-please "); TEST_1(rp); TEST_S(rp->rp_call_id, WORD "@" WORD); TEST_S(rp->rp_to_tag, "foo"); TEST_S(rp->rp_from_tag, "bar"); TEST(rp->rp_early_only, 1); rp = sip_replaces_dup(home, rp0 = rp); TEST_1(rp); TEST_S(rp->rp_call_id, WORD "@" WORD); TEST_S(rp->rp_to_tag, "foo"); TEST_S(rp->rp_from_tag, "bar"); TEST(rp->rp_early_only, 1); TEST(msg_header_replace_param(home, rp->rp_common, "early-only"), 1); TEST(rp->rp_early_only, 1); TEST(msg_header_remove_param(rp->rp_common, "from-tag"), 1); TEST_P(rp->rp_from_tag, NULL); TEST(msg_header_remove_param(rp->rp_common, "to-tag"), 1); TEST_P(rp->rp_to_tag, NULL); su_home_unref(home); END(); } static int test_features(void) { /* Test Proxy-Required, Require, Supported, and Unsupported headers */ sip_proxy_require_t *pr; sip_require_t *r; sip_supported_t *s; sip_unsupported_t *u, *u1; su_home_t *home; BEGIN(); TEST_1(home = su_home_new(sizeof *home)); TEST_1(pr = sip_proxy_require_make(home, "foo, bar, baz, dig, dug")); TEST_1(r = sip_require_make(home, "dig, dug")); TEST_1(s = sip_supported_make(home, "foo, baz, dug")); TEST_1(pr->k_items); TEST_S(pr->k_items[0], "foo"); TEST_1(r->k_items); TEST_S(r->k_items[0], "dig"); TEST_1(s->k_items); TEST_S(s->k_items[0], "foo"); TEST_1(u = sip_has_unsupported(home, s, pr)); TEST_1(u->k_items); TEST_S(u->k_items[0], "bar"); TEST_S(u->k_items[1], "dig"); TEST_P(u->k_items[2], NULL); TEST_1(u1 = sip_has_unsupported(home, s, r)); TEST_1(u1->k_items); TEST_S(u1->k_items[0], "dig"); TEST_1(!u1->k_items[1]); TEST_1(sip_has_supported(s, "foo")); TEST_1(sip_has_supported(s, "baz")); TEST_1(sip_has_supported(s, "dug")); TEST_1(!sip_has_supported(s, "dig")); TEST_1(!sip_has_supported(s, "dag.2")); TEST_1(sip_has_supported(s, NULL)); TEST_1(sip_has_supported(NULL, NULL)); TEST_1(!sip_has_supported(NULL, "foo")); su_home_unref(home); END(); } #if 0 static int sip_time_test(void) { sip_contact_t *m; sip_expires_t *ex; sip_date_t *date = NULL; sip_time_t default = 3600; BEGIN(); sip_time_t sip_contact_expires(sip_contact_t const *m, sip_expires_t const *ex, sip_date_t const *date, sip_time_t def, sip_time_t now); END(); } #endif static int test_events(void) { sip_event_t *o; sip_allow_events_t *ae; sip_subscription_state_t *ss; su_home_t *home; msg_t *msg; sip_t *sip; BEGIN(); TEST_1(home = su_home_new(sizeof *home)); TEST_1((o = sip_event_make(home, "presence;id=1"))); TEST_S(o->o_type, "presence"); TEST_S(o->o_id, "1"); TEST(msg_header_remove_param(o->o_common, "ix=0"), 0); TEST_S(o->o_id, "1"); TEST(msg_header_remove_param(o->o_common, "id"), 1); TEST_P(o->o_id, NULL); TEST(msg_header_replace_param(home, o->o_common, "id=32"), 0); TEST_S(o->o_id, "32"); TEST_1((ae = sip_allow_events_make(home, "presence, presence.winfo, foo"))); TEST_1(ae->k_items); TEST_S(ae->k_items[0], "presence"); TEST_S(ae->k_items[1], "presence.winfo"); TEST_S(ae->k_items[2], "foo"); TEST_P(ae->k_items[3], 0); TEST(sip_allow_events_add(home, ae, "event3"), 0); TEST_S(ae->k_items[3], "event3"); TEST(sip_allow_events_add(home, ae, "event4"), 0); TEST_S(ae->k_items[4], "event4"); TEST(sip_allow_events_add(home, ae, "event5"), 0); TEST_S(ae->k_items[5], "event5"); TEST(sip_allow_events_add(home, ae, "event6"), 0); TEST_S(ae->k_items[6], "event6"); TEST(sip_allow_events_add(home, ae, "event7"), 0); TEST_S(ae->k_items[7], "event7"); TEST(sip_allow_events_add(home, ae, "event8"), 0); TEST_S(ae->k_items[8], "event8"); TEST_1((ss = sip_subscription_state_make(home, "terminated ; reason=timeout"))); TEST_S(ss->ss_substate, "terminated"); TEST_S(ss->ss_reason, "timeout"); TEST(msg_header_replace_param(home, ss->ss_common, "reason=TimeOut"), 1); TEST_S(ss->ss_reason, "TimeOut"); TEST(msg_header_remove_param(ss->ss_common, "reasom"), 0); TEST_S(ss->ss_reason, "TimeOut"); TEST(msg_header_remove_param(ss->ss_common, "reason"), 1); TEST_P(ss->ss_reason, NULL); TEST(msg_header_replace_param(home, ss->ss_common, "expires=200"), 0); TEST(msg_header_replace_param(home, ss->ss_common, "retry-after=10"), 0); TEST_S(ss->ss_expires, "200"); TEST_S(ss->ss_retry_after, "10"); TEST_1((ss = sip_subscription_state_make(home, "active;expires=2"))); TEST_S(ss->ss_substate, "active"); TEST_S(ss->ss_expires, "2"); TEST_1((ss = sip_subscription_state_make(home, "terminated;retry-after=3600"))); TEST_S(ss->ss_substate, "terminated"); TEST_P(ss->ss_expires, NULL); TEST_S(ss->ss_retry_after, "3600"); TEST_1((ss = sip_subscription_state_dup(home, ss))); TEST_S(ss->ss_substate, "terminated"); TEST_P(ss->ss_expires, NULL); TEST_S(ss->ss_retry_after, "3600"); msg = read_message(MSG_DO_EXTRACT_COPY, "SIP/2.0 202 Accepted\r\n" "To: ;tag=deadbeef\r\n" "From: ;\r\n" "Call-ID: 0ha0isndaksdj@10.1.2.3\r\n" "CSeq: 8 SUBSCRIBE\r\n" "Via: SIP/2.0/UDP 135.180.130.133\r\n" "Event: foo;id=1\r\n" "Allow-Events: bar, foo, zap\r\n" "Subscription-State: terminated;reason=probation;retry-after=100000\r\n" "Content-Length: 0\r\n" "\r\n"); sip = sip_object(msg); TEST_1(msg); TEST_1(sip); TEST_1(sip->sip_event); TEST_1(sip->sip_allow_events); TEST_1(sip->sip_event->o_type); TEST_S(sip->sip_event->o_type, "foo"); TEST_1(sip->sip_event->o_id); TEST_S(sip->sip_event->o_id, "1"); TEST_1(sip->sip_allow_events); su_home_unref(home); msg_destroy(msg), msg = NULL; END(); } static int test_route(void) { sip_record_route_t *r0, *r1; sip_record_route_t *rr; sip_path_t *p, *p0; sip_service_route_t *sr, *sr0; su_home_t *home; BEGIN(); TEST_1(home = su_home_new(sizeof *home)); TEST_1((rr = sip_record_route_make(home, "sip:foo.bar;lr"))); TEST_1(rr->r_params); TEST_1((r0 = sip_record_route_make(home, ""))); TEST_P(r0->r_params, NULL); TEST_1(r0->r_url->url_params); TEST_1((r1 = sip_record_route_make(home, ""))); TEST_P(r1->r_params, NULL); TEST_1(r1->r_url->url_params); TEST_1((rr = sip_record_route_create(home, r0->r_url, r1->r_url))); TEST_S(rr->r_url->url_user, "0"); TEST_S(rr->r_url->url_port, "666"); TEST_S(rr->r_url->url_params, "maddr=127.0.0.1"); TEST_1((rr = sip_record_route_create(home, r1->r_url, r0->r_url))); TEST_S(rr->r_url->url_user, "1"); TEST_S(rr->r_url->url_port, "555"); TEST_S(rr->r_url->url_params, "lr;maddr=foo.bar"); TEST_1(!sip_path_make(home, ";lr")); TEST_1(p = sip_path_make(home, ";lr")); TEST_1(p0 = sip_path_dup(home, p)); su_free(home, p); su_free(home, p0); TEST_1(!sip_service_route_make(home, ";lr")); TEST_1(!sip_service_route_make(home, ";lr bar, sip:foo")); TEST_1(sr = sip_service_route_make(home, ";lr")); TEST_1(sr0 = sip_service_route_dup(home, sr)); su_free(home, sr); TEST_1(sr = sip_service_route_make(home, "sip:foo@[baa::1]:5060;lr")); su_free(home, sr); su_free(home, sr0); su_home_unref(home); END(); } /* Test Request-Disposition header */ int test_request_disposition(void) { sip_request_disposition_t *rd; su_home_t *home; BEGIN(); TEST_1(home = su_home_new(sizeof *home)); TEST_1(rd = sip_request_disposition_make(home, "proxy, recurse, parallel")); TEST_S(rd->rd_items[1], "recurse"); su_home_unref(home); END(); } #include #include int test_caller_prefs(void) { sip_accept_contact_t *ac; sip_accept_contact_t *cp; sip_reject_contact_t *rejc; su_home_t *home; char const *s; int negate, error; unsigned S, N; union sip_pref sp[1], a[1]; sip_contact_t *m, *m0, *m1, *m2; BEGIN(); TEST_1(home = su_home_new(sizeof *home)); TEST_1(!sip_is_callerpref("attendant")); TEST_1(sip_is_callerpref("audio")); TEST_1(sip_is_callerpref("automata")); TEST_1(sip_is_callerpref("class")); TEST_1(sip_is_callerpref("duplex")); TEST_1(sip_is_callerpref("data")); TEST_1(sip_is_callerpref("control")); TEST_1(sip_is_callerpref("mobility")); TEST_1(sip_is_callerpref("description")); TEST_1(sip_is_callerpref("events")); TEST_1(sip_is_callerpref("priority")); TEST_1(sip_is_callerpref("methods")); TEST_1(sip_is_callerpref("schemes")); TEST_1(sip_is_callerpref("application")); TEST_1(sip_is_callerpref("video")); TEST_1(sip_is_callerpref("actor")); TEST_1(!sip_is_callerpref("+actor")); TEST_1(!sip_is_callerpref("msgserver")); TEST_1(sip_is_callerpref("language")); TEST_1(sip_is_callerpref("isfocus")); TEST_1(sip_is_callerpref("type")); TEST_1(!sip_is_callerpref("uri-user")); TEST_1(!sip_is_callerpref("uri-domain")); TEST_1(!sip_is_callerpref(NULL)); TEST_1(sip_is_callerpref("+")); TEST_1(sip_is_callerpref("+foo")); /* Booleans (treated as literals) */ s = "TRUE"; negate = 2; memset(sp, 0, sizeof sp); TEST_1(sip_prefs_parse(sp, &s, &negate)); TEST(sp->sp_type, sp_literal); TEST_S(sp->sp_literal.spl_value, "TRUE"); TEST_1(!negate); TEST_1(sip_prefs_match(sp, sp)); TEST_1(!sip_prefs_parse(sp, &s, &negate)); TEST(sp->sp_type, sp_init); s = "FALSE"; negate = 2; memset(sp, 0, sizeof sp); TEST_1(sip_prefs_parse(sp, &s, &negate)); TEST(sp->sp_type, sp_literal); TEST_S(sp->sp_literal.spl_value, "FALSE"); TEST_1(!negate); TEST_1(sip_prefs_match(sp, sp)); TEST_1(!sip_prefs_parse(sp, &s, &negate)); TEST(sp->sp_type, sp_init); s = "\"!TRUE,!FALSE\""; negate = 0; TEST_1(sip_prefs_parse(sp, &s, &negate)); TEST(sp->sp_type, sp_literal); TEST_1(negate); /* Literal */ s = "\" !oukki , doukki \""; negate = 0; memset(sp, 0, sizeof sp); TEST_1(sip_prefs_parse(sp, &s, &negate)); TEST(sp->sp_type, sp_literal); TEST_SIZE(sp->sp_literal.spl_length, 5); TEST_M(sp->sp_literal.spl_value, "oukki", 5); TEST_1(negate); TEST_1(sip_prefs_parse(sp, &s, &negate)); TEST(sp->sp_type, sp_literal); TEST_SIZE(sp->sp_literal.spl_length, 6); TEST_M(sp->sp_literal.spl_value, "doukki", 6); TEST_1(!negate); TEST_1(!sip_prefs_parse(sp, &s, &negate)); TEST(sp->sp_type, sp_init); /* Strings */ s = "\" ! , \""; negate = 0; memset(sp, 0, sizeof sp); TEST_1(sip_prefs_parse(sp, &s, &negate)); TEST(sp->sp_type, sp_string); TEST_SIZE(sp->sp_string.sps_length, 5); TEST_M(sp->sp_string.sps_value, "oukki", 5); TEST_1(negate); TEST_1(sip_prefs_parse(sp, &s, &negate)); TEST(sp->sp_type, sp_string); TEST_SIZE(sp->sp_string.sps_length, 10); TEST_M(sp->sp_string.sps_value, "douK\\\"ki ", 10); TEST_1(!negate); TEST_1(!sip_prefs_parse(sp, &s, &negate)); TEST(sp->sp_type, sp_init); /* Numeric */ s = "\" !#=6, #<=3, #>=6, !#<=6, #1:6.5\""; negate = 0; memset(sp, 0, sizeof sp); TEST_1(sip_prefs_parse(sp, &s, &negate)); TEST(sp->sp_type, sp_range); TEST_D(sp->sp_range.spr_lower, 6.0); TEST_D(sp->sp_range.spr_upper, 6.0); TEST_1(sip_prefs_match(sp, sp)); TEST_1(negate); *a = *sp; TEST_1(sip_prefs_parse(sp, &s, &negate)); TEST(sp->sp_type, sp_range); TEST_D(sp->sp_range.spr_lower, -DBL_MAX); TEST_D(sp->sp_range.spr_upper, 3.0); TEST_1(sip_prefs_match(sp, sp)); TEST_1(!negate); TEST_1(!sip_prefs_match(a, sp)); TEST_1(sip_prefs_parse(sp, &s, &negate)); TEST(sp->sp_type, sp_range); TEST_D(sp->sp_range.spr_lower, 6.0); TEST_D(sp->sp_range.spr_upper, DBL_MAX); TEST_1(sip_prefs_match(sp, sp)); TEST_1(!negate); TEST_1(sip_prefs_match(a, sp)); TEST_1(sip_prefs_parse(sp, &s, &negate)); TEST(sp->sp_type, sp_range); TEST_D(sp->sp_range.spr_lower, -DBL_MAX); TEST_D(sp->sp_range.spr_upper, 6.0); TEST_1(sip_prefs_match(sp, sp)); TEST_1(negate); TEST_1(sip_prefs_match(a, sp)); TEST_1(sip_prefs_parse(sp, &s, &negate)); TEST(sp->sp_type, sp_range); TEST_D(sp->sp_range.spr_lower, 1.0); TEST_D(sp->sp_range.spr_upper, 6.5); TEST_1(sip_prefs_match(sp, sp)); TEST_1(!negate); TEST_1(sip_prefs_match(a, sp)); TEST_1(!sip_prefs_parse(sp, &s, &negate)); TEST(sp->sp_type, sp_init); /* Numeric */ s = "\" !#=" "1111111111111111111111111111111111111111" "1111111111111111111111111111111111111111" "1111111111111111111111111111111111111111" "1111111111111111111111111111111111111111" "1111111111111111111111111111111111111111" "1111111111111111111111111111111111111111" "1111111111111111111111111111111111111111" "1111111111111111111111111111111111111111." "1111111111111111111111111111111111111111" "1111111111111111111111111111111111111111" "1111111111111111111111111111111111111111" "1111111111111111111111111111111111111111" "1111111111111111111111111111111111111111" "1111111111111111111111111111111111111111" "1111111111111111111111111111111111111111" "1111111111111111111111111111111111111111," " #<=-16" "\""; negate = 0; memset(sp, 0, sizeof sp); TEST_1(sip_prefs_parse(sp, &s, &negate)); TEST(sp->sp_type, sp_range); TEST_D(sp->sp_range.spr_lower, DBL_MAX); TEST_D(sp->sp_range.spr_upper, DBL_MAX); TEST_1(sip_prefs_match(sp, sp)); TEST_1(negate); TEST_1(sip_prefs_parse(sp, &s, &negate)); TEST(sp->sp_type, sp_range); TEST_D(sp->sp_range.spr_lower, -DBL_MAX); TEST_D(sp->sp_range.spr_upper, -16.0); TEST_1(sip_prefs_match(sp, sp)); TEST_1(!negate); error = 12; TEST_1(sip_prefs_matching("\"INVITE,MESSAGE,SUBSCRIBE\"", "\"INVITE\"", &error)); TEST_1(!sip_prefs_matching("\"INVITE,MESSAGE,SUBSCRIBE\"", "\"BYE\"", &error)); TEST(error, 12); TEST_1(sip_prefs_matching("\"INVITE,MESSAGE,SUBSCRIBE\"", "\"invite\"", &error)); TEST_1(sip_prefs_matching("\"!INVITE,MESSAGE,SUBSCRIBE\"", "\"foo\"", &error)); TEST_1(sip_prefs_matching("TRUE", "", &error)); TEST_1(sip_prefs_matching("", "", &error)); TEST_1(!sip_prefs_matching("FALSE", "", &error)); TEST(error, 12); TEST_1(sip_prefs_matching("FALSE", "FALSE", &error)); /* Lax when receiving... */ TEST_1(sip_prefs_matching("\"FALSE\"", "FALSE", &error)); /* XXX */ TEST_1(sip_prefs_matching("\"TRUE\"", "TRUE", &error)); /* XXX */ TEST_1(!sip_prefs_matching("\"!INVITE\"", "\"INVITE\"", &error)); TEST_1(!sip_prefs_matching("\"!INVITE\"", "\"invite\"", &error)); TEST_1(sip_prefs_matching("\"!\"", "\"\"", &error)); TEST_1(!sip_prefs_matching("\"INVITE\"", "\"!INVITE\"", &error)); TEST_1(sip_prefs_matching("\"!INVITE\"", "\"INVITE,MESSAGE\"", &error)); TEST_1(sip_prefs_matching("\"!INVITE,!MESSAGE\"", "\"INVITE,MESSAGE\"", &error)); TEST_1(sip_prefs_matching("\"!MESSAGE\"", "\"INVITE,MESSAGE\"", &error)); TEST_1(!sip_prefs_matching("\",\"", "\",\"", &error)); TEST_1(!sip_prefs_matching("\",\"", "\"foo,bar\"", &error)); TEST_1(sip_prefs_matching("\"#=1\"", "\"#<=2\"", &error)); TEST_1(sip_prefs_matching("\"#1:2\"", "\"#<=2\"", &error)); TEST_1(!sip_prefs_matching("\"#1:2\"", "\"!#>=1,!#<=2\"", &error)); TEST_1(!sip_prefs_matching("\"#=0,#=1\"", "\",\"", &error)); TEST(error, 12); error = 12; TEST_1(!sip_prefs_matching("\",#=1\"", "\",\"", &error)); TEST(error, -1); error = 12; TEST_1(!sip_prefs_matching("\",\"", "\",#=1\"", &error)); TEST(error, -1); error = 12; TEST_1(!sip_prefs_matching("\",bar\"", "\",\"", &error)); TEST(error, -1); error = 12; TEST_1(!sip_prefs_matching("\",\"", "\",#12:12\"", &error)); TEST(error, -1); { char const *params[] = { "methods=\"INVITE,MESSAGE,SUBSCRIBE\"", "events=\"presence,presence.winfo\"", "description=\"\"", "language=\"!en,de\"", "schemes=\"sip\"", "+res-x=\"#=640\"", "+res-y=\"#=480\"", NULL }; TEST_1(sip_is_callerpref(params[0])); TEST_1(sip_is_callerpref(params[1])); TEST_1(sip_is_callerpref(params[2])); TEST_1(sip_is_callerpref(params[3])); TEST_1(sip_is_callerpref(params[4])); TEST_1(sip_is_callerpref(params[5])); TEST_1(sip_is_callerpref(params[6])); TEST_1(!sip_is_callerpref(params[7])); /* NULL */ TEST_1(!sip_is_callerpref("method=\"foo\"")); TEST_1(!sip_is_callerpref("+methods=\"foo\"")); } TEST_1(m = sip_contact_make(home, ";video;audio;type=\"