pax_global_header00006660000000000000000000000064135651401440014515gustar00rootroot0000000000000052 comment=899473199b9c9a947c9cb4981cdbfd4cf1c3d23d php-amqplib-2.11.0/000077500000000000000000000000001356514014400140105ustar00rootroot00000000000000php-amqplib-2.11.0/.editorconfig000066400000000000000000000006261356514014400164710ustar00rootroot00000000000000; This file is for unifying the coding style for different editors and IDEs. ; More information at http://editorconfig.org root = true [*] charset = utf-8 end_of_line = lf indent_size = 4 indent_style = space insert_final_newline = true trim_trailing_whitespace = true ; Works with some editors only quote_type = single max_line_length = 120 spaces_around_brackets = true spaces_around_operators = true php-amqplib-2.11.0/.github/000077500000000000000000000000001356514014400153505ustar00rootroot00000000000000php-amqplib-2.11.0/.github/CODE_OF_CONDUCT.md000066400000000000000000000044761356514014400201620ustar00rootroot00000000000000# Contributor Code of Conduct As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery * Personal attacks * Trolling or insulting/derogatory comments * Public or private harassment * Publishing other's private information, such as physical or electronic addresses, without explicit permission * Other unethical or unprofessional conduct Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team. This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting a project maintainer. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. Maintainers are obligated to maintain confidentiality with regard to the reporter of an incident. This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.3.0, available at [http://contributor-covenant.org/version/1/3/0/][version] [homepage]: http://contributor-covenant.org [version]: http://contributor-covenant.org/version/1/3/0/ php-amqplib-2.11.0/.github/ISSUE_TEMPLATE/000077500000000000000000000000001356514014400175335ustar00rootroot00000000000000php-amqplib-2.11.0/.github/ISSUE_TEMPLATE/1_Bug_report.md000066400000000000000000000010511356514014400224020ustar00rootroot00000000000000--- name: 🐛 Bug Report about: Report errors and problems --- **Version(s) affected**: x.y.z **Description** **How to reproduce** **Possible Solution** **Additional context** php-amqplib-2.11.0/.github/ISSUE_TEMPLATE/2_Feature_request.md000066400000000000000000000005661356514014400234500ustar00rootroot00000000000000--- name: 🚀 Feature Request about: RFC and ideas for new features and improvements --- **Description** **Example** php-amqplib-2.11.0/.github/ISSUE_TEMPLATE/3_Support_question.md000066400000000000000000000001121356514014400236740ustar00rootroot00000000000000--- name: ⛔ Support Question about: Questions about using library --- php-amqplib-2.11.0/.gitignore000066400000000000000000000001021356514014400157710ustar00rootroot00000000000000vendor/ composer.lock phpunit.xml build/ docs/ phpDocumentor.phar php-amqplib-2.11.0/.gitmodules000066400000000000000000000001511356514014400161620ustar00rootroot00000000000000[submodule "docs"] path = docs url = https://github.com/php-amqplib/php-amqplib.git branch = gh-pages php-amqplib-2.11.0/.scrutinizer.yml000066400000000000000000000012451356514014400171740ustar00rootroot00000000000000filter: paths: [PhpAmqpLib/*] excluded_paths: [tests/*, demo/*, benchmark/*, spec/*, PhpAmqpLib/Helper/Protocol/*, PhpAmqpLib/Wire/Constants*] checks: php: remove_extra_empty_lines: true remove_php_closing_tag: true remove_trailing_whitespace: true fix_use_statements: remove_unused: true preserve_multiple: false preserve_blanklines: true order_alphabetically: true fix_php_opening_tag: true fix_linefeed: true fix_line_ending: true fix_identation_4spaces: true fix_doc_comments: true tools: external_code_coverage: timeout: 1200 php-amqplib-2.11.0/.travis.yml000066400000000000000000000020771356514014400161270ustar00rootroot00000000000000language: php matrix: include: - php: 5.6 - php: 7.0 - php: 7.1 - php: 7.2 - php: 7.3 env: COVERAGE=true - php: 7.4snapshot fast_finish: true allow_failures: - php: 7.4snapshot git: depth: 1 services: - docker addons: apt: packages: - rabbitmq-server cache: directories: - $HOME/.composer - vendor before_install: - docker pull shopify/toxiproxy - docker run -d --rm --net=host -p 8474:8474 -p 5673:5673 shopify/toxiproxy - docker ps -a - if [[ $COVERAGE != true ]]; then phpenv config-rm xdebug.ini || true; fi env: global: - TOXIPROXY_HOST=localhost TOXIPROXY_AMQP_PORT=5673 before_script: - travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-dist script: - vendor/bin/phpunit -d zend.enable_gc=0 --exclude-group management --coverage-text --coverage-clover=coverage.clover after_success: > if [[ $COVERAGE = true ]]; then wget https://scrutinizer-ci.com/ocular.phar php ocular.phar code-coverage:upload --format=php-clover coverage.clover fi php-amqplib-2.11.0/CHANGELOG.md000066400000000000000000000125341356514014400156260ustar00rootroot00000000000000# Changelog All Notable changes to `php-amqplib` will be documented in this file ## 2.11.0 - 2019-11-19 [GitHub Milestone](https://github.com/php-amqplib/php-amqplib/milestone/12?closed=1 ## 2.10.1 - 2019-10-10 [GitHub Milestone](https://github.com/php-amqplib/php-amqplib/milestone/11?closed=1 ## 2.10.0 - 2019-08-09 [GitHub Milestone](https://github.com/php-amqplib/php-amqplib/milestone/10?closed=1) - Heartbeats are disabled by default. This reverts the following changes: [Issue](https://github.com/php-amqplib/php-amqplib/issues/563) / [PR](https://github.com/php-amqplib/php-amqplib/pull/648) ## 2.9.2 - 2019-04-24 [GitHub Milestone](https://github.com/php-amqplib/php-amqplib/milestone/9?closed=1) ## 2.9.1 - 2019-03-26 [GitHub Milestone](https://github.com/php-amqplib/php-amqplib/milestone/8?closed=1) ## 2.9.0 - 2019-03-23 [GitHub Milestone](https://github.com/php-amqplib/php-amqplib/milestone/7?closed=1) - heartbeats are now enabled by default [Issue](https://github.com/php-amqplib/php-amqplib/issues/563) / [PR](https://github.com/php-amqplib/php-amqplib/pull/648) ## 2.8.1 - 2018-11-13 [GitHub Milestone](https://github.com/php-amqplib/php-amqplib/milestone/6?closed=1) - `ext-sockets` is now required: [PR](https://github.com/php-amqplib/php-amqplib/pull/610) - Fix `errno=11 Resource temporarily unavailable` error: [Issue](https://github.com/php-amqplib/php-amqplib/issues/613) / [PR](https://github.com/php-amqplib/php-amqplib/pull/615) ## 2.8.0 - 2018-10-23 [GitHub Milestone](https://github.com/php-amqplib/php-amqplib/milestone/3?closed=1) - Drop testing and support for PHP 5.3 - Use specific exceptions instead of general `AMQPRuntimeException`: [PR](https://github.com/php-amqplib/php-amqplib/pull/600) - Allow overriding of `LIBRARY_PROPERTIES` - [PR](https://github.com/php-amqplib/php-amqplib/pull/606) ## 2.7.2 - 2018-02-11 [GitHub Milestone](https://github.com/php-amqplib/php-amqplib/milestone/5?closed=1) - PHP `5.3` compatibility [PR](https://github.com/php-amqplib/php-amqplib/issues/539) ## 2.7.1 - 2018-02-01 - Support PHPUnit 6 [PR](https://github.com/php-amqplib/php-amqplib/pull/530) - Use `tcp_nodelay` for `StreamIO` [PR](https://github.com/php-amqplib/php-amqplib/pull/517) - Pass connection timeout to `wait` method [PR](https://github.com/php-amqplib/php-amqplib/pull/512) - Fix possible indefinite waiting for data in StreamIO [PR](https://github.com/php-amqplib/php-amqplib/pull/423), [PR](https://github.com/php-amqplib/php-amqplib/pull/534) - Change protected method check_heartbeat to public [PR](https://github.com/php-amqplib/php-amqplib/pull/520) - Ensure access levels are consistent for calling `check_heartbeat` [PR](https://github.com/php-amqplib/php-amqplib/pull/535) ## 2.7.0 - 2017-09-20 ### Added - Increased overall test coverage - Bring heartbeat support to socket connection - Add message delivery tag for publisher confirms - Add support for serializing DateTimeImmutable objects ### Fixed - Fixed infinite loop on reconnect - check_heartbeat - Fixed signal handling exit example - Fixed exchange_unbind arguments - Fixed invalid annotation for channel_id - Fixed socket null error on php 5.3 version - Fixed timeout parameters on HHVM before calling stream_select ### Changed - declare(ticks=1) no longer needed after PHP5.3 / amqplib 2.4.1 - Minor DebugHelper improvements ### Enhancements - Add extensions requirements to README.md - Add PHP 7.1 to Travis build - Reduce memory usage in StreamIO::write() - Re-enable heartbeats after reconnection ## 2.6.3 - 2016-04-11 ### Added - Added the ability to set timeout as float ### Fixed - Fixed restoring of error_handler on connection error ### Enhancements - Verify read_write_timeout is at least 2x the heartbeat (if set) - Many PHPDoc fixes - Throw exception when trying to create an exchange on a closed connection ## 2.6.2 - 2016-03-02 ### Added - Added AMQPLazySocketConnection - AbstractConnection::getServerProperties method to retrieve server properties. - AMQPReader::wait() will throw IOWaitException on stream_select failure - Add PHPDocs to Auto-generated Protocol Classes ### Fixed - Disable heartbeat when closing connection - Fix for when the default error handler is not restored in StreamIO ### Enhancements - Cleanup tests and improve testing performance - Confirm received valid frame type on wait_frame in AbstractConnection - Update DEMO files closer to PSR-2 standards ## 2.6.1 - 2016-02-12 ### Added - Add constants for delivery modes to AMQPMessage ### Fixed - Fix some PHPDoc problems - AbstractCollection value de/encoding on PHP7 - StreamIO: fix "bad write retry" in SSL mode ### Enhancements - Update PHPUnit configuration - Add scrutinizer-ci configuration - Organizational changes from videlalvaro to php-amqplib org - Minor complexity optimizations, code organization, and code cleanup ## 2.6.0 - 2015-09-23 ### BC Breaking Changes - The `AMQPStreamConnection` class now throws `ErrorExceptions` when errors happen while reading/writing to the network. ### Added - Heartbeat frames will decrease the timeout used when calling wait_channel - heartbeat frames do not reset the timeout ### Fixed - Declared the class AbstractChannel as being an abstract class - Reads, writes and signals respond immediately instead of waiting for a timeout - Fatal error in some cases on Channel.wait with timeout when RabbitMQ restarted - Remove warning when trying to push a deferred frame php-amqplib-2.11.0/CONTRIBUTING.md000066400000000000000000000025161356514014400162450ustar00rootroot00000000000000# Contributing Contributions are **welcome** and will be fully **credited**. We accept contributions via Pull Requests on [Github](https://github.com/php-amqplib/php-amqplib). ## Pull Requests - **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer). - **Add tests!** - Your patch won't be accepted if it doesn't have tests. - **Document any change in behaviour** - Make sure the README and any other relevant documentation are kept up-to-date. - **Consider our release cycle** - We try to follow semver. Randomly breaking public APIs is not an option. - **Create topic branches** - Don't ask us to pull from your master branch. - **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. - **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting. ## Running Tests To successfully run the tests you need to first have a stock RabbitMQ broker running locally. Then, run tests like this: ``` bash $ vendor/bin/phpunit ``` or ``` bash $ make test ``` **Happy coding**! php-amqplib-2.11.0/CREDITS000066400000000000000000000004671356514014400150370ustar00rootroot00000000000000 Following people contributed to this project: Barry Pederson - author of original Python lib Vadim Zaliva - PHP paort taavi013@gmail.com patches - patches Sean Murphy http://code.google.com/u/sgmurphy/ - patches spiderbill http://code.google.com/u/spiderbill/ - patches php-amqplib-2.11.0/LICENSE000066400000000000000000000575061356514014400150320ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS php-amqplib-2.11.0/Makefile000066400000000000000000000011331356514014400154460ustar00rootroot00000000000000.PHONY: test test: ./vendor/bin/phpunit .PHONY: docs docs: wget -qN https://github.com/phpDocumentor/phpDocumentor2/releases/download/v2.9.0/phpDocumentor.phar php ./phpDocumentor.phar --template=responsive-twig --defaultpackagename=PhpAmqpLib --title='php-amqplib' -d ./PhpAmqpLib -t ./docs .PHONY: benchmark benchmark: @echo "Publishing 4000 msgs with 1KB of content:" php benchmark/producer.php 4000 @echo "Consuming 4000:" php benchmark/consumer.php @echo "Stream produce 100:" php benchmark/stream_tmp_produce.php 100 @echo "Socket produce 100:" php benchmark/socket_tmp_produce.php 100 php-amqplib-2.11.0/NOTE.DEVELOPMENT.NOV.2011.md000066400000000000000000000012311356514014400177000ustar00rootroot00000000000000## BC BREAKING CHANGES ## As of November 2011 I retook the development of this library therefore I __tagged__ the __previous version__ of the library [here](https://github.com/videlalvaro/php-amqplib/tarball/v1.0). If you are looking for the old library then use the code on that tag. If you are going to use it in a new project I advice that you use the current master branch. There are many performance improvements in that branch and I'm adding more and more tests to it. Besides that the library has been refactored to use PHP 5.3 `namespaces`. The classes have been split into their separate files and so on. The idea is to make the library easier to test. php-amqplib-2.11.0/NOTE.THENETCIRCLE.md000066400000000000000000000004751356514014400167550ustar00rootroot00000000000000## NOTE ## This library is a fork of the [php-amqplib](http://code.google.com/p/php-amqplib/) library. At The Netcircle we modified that library in order to work with PHP 5.3 Strict. Also we improved the debug method to increase performance. We use it daily in prod for sending/consuming 600K + messages per day. php-amqplib-2.11.0/PhpAmqpLib/000077500000000000000000000000001356514014400160055ustar00rootroot00000000000000php-amqplib-2.11.0/PhpAmqpLib/Channel/000077500000000000000000000000001356514014400173555ustar00rootroot00000000000000php-amqplib-2.11.0/PhpAmqpLib/Channel/AMQPChannel.php000066400000000000000000001256121356514014400221240ustar00rootroot00000000000000get_free_channel_id(); } parent::__construct($connection, $channel_id); $this->debug->debug_msg('using channel_id: ' . $channel_id); $this->auto_decode = $auto_decode; $this->channel_rpc_timeout = $channel_rpc_timeout; try { $this->x_open(); } catch (\Exception $e) { $this->close(); throw $e; } } /** * @return bool */ public function is_open() { return $this->is_open; } /** * Tear down this object, after we've agreed to close with the server. */ protected function do_close() { if ($this->channel_id !== null) { unset($this->connection->channels[$this->channel_id]); } $this->channel_id = $this->connection = null; $this->is_open = false; $this->callbacks = array(); } /** * Only for AMQP0.8.0 * This method allows the server to send a non-fatal warning to * the client. This is used for methods that are normally * asynchronous and thus do not have confirmations, and for which * the server may detect errors that need to be reported. Fatal * errors are handled as channel or connection exceptions; non- * fatal errors are sent through this method. * * @param AMQPReader $reader */ protected function channel_alert($reader) { $reply_code = $reader->read_short(); $reply_text = $reader->read_shortstr(); $details = $reader->read_table(); array_push($this->alerts, array($reply_code, $reply_text, $details)); } /** * Request a channel close * * @param int $reply_code * @param string $reply_text * @param array $method_sig * @throws \PhpAmqpLib\Exception\AMQPTimeoutException if the specified operation timeout was exceeded * @return mixed */ public function close($reply_code = 0, $reply_text = '', $method_sig = array(0, 0)) { $this->callbacks = array(); if ($this->is_open === false || $this->connection === null) { $this->do_close(); return null; // already closed } list($class_id, $method_id, $args) = $this->protocolWriter->channelClose( $reply_code, $reply_text, $method_sig[0], $method_sig[1] ); try { $this->send_method_frame(array($class_id, $method_id), $args); } catch (\Exception $e) { $this->do_close(); throw $e; } return $this->wait(array( $this->waitHelper->get_wait('channel.close_ok') ), false, $this->channel_rpc_timeout ); } /** * @param AMQPReader $reader * @throws \PhpAmqpLib\Exception\AMQPProtocolChannelException */ protected function channel_close($reader) { $reply_code = $reader->read_short(); $reply_text = $reader->read_shortstr(); $class_id = $reader->read_short(); $method_id = $reader->read_short(); $this->send_method_frame(array(20, 41)); $this->do_close(); throw new AMQPProtocolChannelException($reply_code, $reply_text, array($class_id, $method_id)); } /** * Confirm a channel close * Alias of AMQPChannel::do_close() * * @param AMQPReader $reader */ protected function channel_close_ok($reader) { $this->do_close(); } /** * Enables/disables flow from peer * * @param $active * @throws \PhpAmqpLib\Exception\AMQPTimeoutException if the specified operation timeout was exceeded * @return mixed */ public function flow($active) { list($class_id, $method_id, $args) = $this->protocolWriter->channelFlow($active); $this->send_method_frame(array($class_id, $method_id), $args); return $this->wait(array( $this->waitHelper->get_wait('channel.flow_ok') ), false, $this->channel_rpc_timeout); } /** * @param AMQPReader $reader */ protected function channel_flow($reader) { $this->active = $reader->read_bit(); $this->x_flow_ok($this->active); } /** * @param bool $active */ protected function x_flow_ok($active) { list($class_id, $method_id, $args) = $this->protocolWriter->channelFlow($active); $this->send_method_frame(array($class_id, $method_id), $args); } /** * @param AMQPReader $reader * @return bool */ protected function channel_flow_ok($reader) { return $reader->read_bit(); } /** * @param string $out_of_band * @throws \PhpAmqpLib\Exception\AMQPTimeoutException if the specified operation timeout was exceeded * @return mixed */ protected function x_open($out_of_band = '') { if ($this->is_open) { return null; } list($class_id, $method_id, $args) = $this->protocolWriter->channelOpen($out_of_band); $this->send_method_frame(array($class_id, $method_id), $args); return $this->wait(array( $this->waitHelper->get_wait('channel.open_ok') ), false, $this->channel_rpc_timeout); } /** * @param AMQPReader $reader */ protected function channel_open_ok($reader) { $this->is_open = true; $this->debug->debug_msg('Channel open'); } /** * Requests an access ticket * * @param string $realm * @param bool $exclusive * @param bool $passive * @param bool $active * @param bool $write * @param bool $read * @throws \PhpAmqpLib\Exception\AMQPTimeoutException if the specified operation timeout was exceeded * @return mixed */ public function access_request( $realm, $exclusive = false, $passive = false, $active = false, $write = false, $read = false ) { list($class_id, $method_id, $args) = $this->protocolWriter->accessRequest( $realm, $exclusive, $passive, $active, $write, $read ); $this->send_method_frame(array($class_id, $method_id), $args); return $this->wait(array( $this->waitHelper->get_wait('access.request_ok') ), false, $this->channel_rpc_timeout); } /** * Grants access to server resources * * @param AMQPReader $reader * @return string */ protected function access_request_ok($reader) { $this->default_ticket = $reader->read_short(); return $this->default_ticket; } /** * Declares exchange * * @param string $exchange * @param string $type * @param bool $passive * @param bool $durable * @param bool $auto_delete * @param bool $internal * @param bool $nowait * @param array $arguments * @param int|null $ticket * @throws \PhpAmqpLib\Exception\AMQPTimeoutException if the specified operation timeout was exceeded * @return mixed|null */ public function exchange_declare( $exchange, $type, $passive = false, $durable = false, $auto_delete = true, $internal = false, $nowait = false, $arguments = array(), $ticket = null ) { $ticket = $this->getTicket($ticket); list($class_id, $method_id, $args) = $this->protocolWriter->exchangeDeclare( $ticket, $exchange, $type, $passive, $durable, $auto_delete, $internal, $nowait, $arguments ); $this->send_method_frame(array($class_id, $method_id), $args); if ($nowait) { return null; } return $this->wait(array( $this->waitHelper->get_wait('exchange.declare_ok') ), false, $this->channel_rpc_timeout); } /** * Confirms an exchange declaration * @param AMQPReader $reader */ protected function exchange_declare_ok($reader) { } /** * Deletes an exchange * * @param string $exchange * @param bool $if_unused * @param bool $nowait * @param int|null $ticket * @throws \PhpAmqpLib\Exception\AMQPTimeoutException if the specified operation timeout was exceeded * @return mixed|null */ public function exchange_delete( $exchange, $if_unused = false, $nowait = false, $ticket = null ) { $ticket = $this->getTicket($ticket); list($class_id, $method_id, $args) = $this->protocolWriter->exchangeDelete( $ticket, $exchange, $if_unused, $nowait ); $this->send_method_frame(array($class_id, $method_id), $args); if ($nowait) { return null; } return $this->wait(array( $this->waitHelper->get_wait('exchange.delete_ok') ), false, $this->channel_rpc_timeout); } /** * Confirms deletion of an exchange * * @param AMQPReader $reader */ protected function exchange_delete_ok($reader) { } /** * Binds dest exchange to source exchange * * @param string $destination * @param string $source * @param string $routing_key * @param bool $nowait * @param array $arguments * @param int|null $ticket * @throws \PhpAmqpLib\Exception\AMQPTimeoutException if the specified operation timeout was exceeded * @return mixed|null */ public function exchange_bind( $destination, $source, $routing_key = '', $nowait = false, $arguments = array(), $ticket = null ) { $ticket = $this->getTicket($ticket); list($class_id, $method_id, $args) = $this->protocolWriter->exchangeBind( $ticket, $destination, $source, $routing_key, $nowait, $arguments ); $this->send_method_frame(array($class_id, $method_id), $args); if ($nowait) { return null; } return $this->wait(array( $this->waitHelper->get_wait('exchange.bind_ok') ), false, $this->channel_rpc_timeout); } /** * Confirms bind successful * @param AMQPReader $reader */ protected function exchange_bind_ok($reader) { } /** * Unbinds dest exchange from source exchange * * @param string $destination * @param string $source * @param string $routing_key * @param bool $nowait * @param array $arguments * @param int|null $ticket * @throws \PhpAmqpLib\Exception\AMQPTimeoutException if the specified operation timeout was exceeded * @return mixed */ public function exchange_unbind( $destination, $source, $routing_key = '', $nowait = false, $arguments = array(), $ticket = null ) { $ticket = $this->getTicket($ticket); list($class_id, $method_id, $args) = $this->protocolWriter->exchangeUnbind( $ticket, $destination, $source, $routing_key, $nowait, $arguments ); $this->send_method_frame(array($class_id, $method_id), $args); return $this->wait(array( $this->waitHelper->get_wait('exchange.unbind_ok') ), false, $this->channel_rpc_timeout); } /** * Confirms unbind successful * * @param AMQPReader $reader */ protected function exchange_unbind_ok($reader) { } /** * Binds queue to an exchange * * @param string $queue * @param string $exchange * @param string $routing_key * @param bool $nowait * @param array $arguments * @param int|null $ticket * @throws \PhpAmqpLib\Exception\AMQPTimeoutException if the specified operation timeout was exceeded * @return mixed|null */ public function queue_bind( $queue, $exchange, $routing_key = '', $nowait = false, $arguments = array(), $ticket = null ) { $ticket = $this->getTicket($ticket); list($class_id, $method_id, $args) = $this->protocolWriter->queueBind( $ticket, $queue, $exchange, $routing_key, $nowait, $arguments ); $this->send_method_frame(array($class_id, $method_id), $args); if ($nowait) { return null; } return $this->wait(array( $this->waitHelper->get_wait('queue.bind_ok') ), false, $this->channel_rpc_timeout); } /** * Confirms bind successful * * @param AMQPReader $reader */ protected function queue_bind_ok($reader) { } /** * Unbind queue from an exchange * * @param string $queue * @param string $exchange * @param string $routing_key * @param array $arguments * @param int|null $ticket * @throws \PhpAmqpLib\Exception\AMQPTimeoutException if the specified operation timeout was exceeded * @return mixed */ public function queue_unbind( $queue, $exchange, $routing_key = '', $arguments = array(), $ticket = null ) { $ticket = $this->getTicket($ticket); list($class_id, $method_id, $args) = $this->protocolWriter->queueUnbind( $ticket, $queue, $exchange, $routing_key, $arguments ); $this->send_method_frame(array($class_id, $method_id), $args); return $this->wait(array( $this->waitHelper->get_wait('queue.unbind_ok') ), false, $this->channel_rpc_timeout); } /** * Confirms unbind successful * @param AMQPReader $reader */ protected function queue_unbind_ok($reader) { } /** * Declares queue, creates if needed * * @param string $queue * @param bool $passive * @param bool $durable * @param bool $exclusive * @param bool $auto_delete * @param bool $nowait * @param array|\PhpAmqpLib\Wire\AMQPTable $arguments * @param int|null $ticket * @throws \PhpAmqpLib\Exception\AMQPTimeoutException if the specified operation timeout was exceeded * @return array|null */ public function queue_declare( $queue = '', $passive = false, $durable = false, $exclusive = false, $auto_delete = true, $nowait = false, $arguments = array(), $ticket = null ) { $ticket = $this->getTicket($ticket); list($class_id, $method_id, $args) = $this->protocolWriter->queueDeclare( $ticket, $queue, $passive, $durable, $exclusive, $auto_delete, $nowait, $arguments ); $this->send_method_frame(array($class_id, $method_id), $args); if ($nowait) { return null; } return $this->wait(array( $this->waitHelper->get_wait('queue.declare_ok') ), false, $this->channel_rpc_timeout); } /** * Confirms a queue definition * * @param AMQPReader $reader * @return string[] */ protected function queue_declare_ok($reader) { $queue = $reader->read_shortstr(); $message_count = $reader->read_long(); $consumer_count = $reader->read_long(); return array($queue, $message_count, $consumer_count); } /** * Deletes a queue * * @param string $queue * @param bool $if_unused * @param bool $if_empty * @param bool $nowait * @param int|null $ticket * @throws \PhpAmqpLib\Exception\AMQPTimeoutException if the specified operation timeout was exceeded * @return mixed|null */ public function queue_delete($queue = '', $if_unused = false, $if_empty = false, $nowait = false, $ticket = null) { $ticket = $this->getTicket($ticket); list($class_id, $method_id, $args) = $this->protocolWriter->queueDelete( $ticket, $queue, $if_unused, $if_empty, $nowait ); $this->send_method_frame(array($class_id, $method_id), $args); if ($nowait) { return null; } return $this->wait(array( $this->waitHelper->get_wait('queue.delete_ok') ), false, $this->channel_rpc_timeout); } /** * Confirms deletion of a queue * * @param AMQPReader $reader * @return string */ protected function queue_delete_ok($reader) { return $reader->read_long(); } /** * Purges a queue * * @param string $queue * @param bool $nowait * @param int|null $ticket * @throws \PhpAmqpLib\Exception\AMQPTimeoutException if the specified operation timeout was exceeded * @return mixed|null */ public function queue_purge($queue = '', $nowait = false, $ticket = null) { $ticket = $this->getTicket($ticket); list($class_id, $method_id, $args) = $this->protocolWriter->queuePurge($ticket, $queue, $nowait); $this->send_method_frame(array($class_id, $method_id), $args); if ($nowait) { return null; } return $this->wait(array( $this->waitHelper->get_wait('queue.purge_ok') ), false, $this->channel_rpc_timeout); } /** * Confirms a queue purge * * @param AMQPReader $reader * @return string */ protected function queue_purge_ok($reader) { return $reader->read_long(); } /** * Acknowledges one or more messages * * @param string $delivery_tag * @param bool $multiple */ public function basic_ack($delivery_tag, $multiple = false) { list($class_id, $method_id, $args) = $this->protocolWriter->basicAck($delivery_tag, $multiple); $this->send_method_frame(array($class_id, $method_id), $args); } /** * Called when the server sends a basic.ack * * @param AMQPReader $reader * @throws AMQPRuntimeException */ protected function basic_ack_from_server(AMQPReader $reader) { $delivery_tag = $reader->read_longlong(); $multiple = (bool) $reader->read_bit(); if (!isset($this->published_messages[$delivery_tag])) { throw new AMQPRuntimeException(sprintf( 'Server ack\'ed unknown delivery_tag "%s"', $delivery_tag )); } $this->internal_ack_handler($delivery_tag, $multiple, $this->ack_handler); } /** * Called when the server sends a basic.nack * * @param AMQPReader $reader * @throws AMQPRuntimeException */ protected function basic_nack_from_server($reader) { $delivery_tag = $reader->read_longlong(); $multiple = (bool) $reader->read_bit(); if (!isset($this->published_messages[$delivery_tag])) { throw new AMQPRuntimeException(sprintf( 'Server nack\'ed unknown delivery_tag "%s"', $delivery_tag )); } $this->internal_ack_handler($delivery_tag, $multiple, $this->nack_handler); } /** * Handles the deletion of messages from this->publishedMessages and dispatches them to the $handler * * @param string $delivery_tag * @param bool $multiple * @param callable $handler */ protected function internal_ack_handler($delivery_tag, $multiple, $handler) { if ($multiple) { $keys = $this->get_keys_less_or_equal($this->published_messages, $delivery_tag); foreach ($keys as $key) { $this->internal_ack_handler($key, false, $handler); } } else { $message = $this->get_and_unset_message($delivery_tag); $message->delivery_info['delivery_tag'] = $delivery_tag; $this->dispatch_to_handler($handler, array($message)); } } /** * @param AMQPMessage[] $messages * @param string $value * @return mixed */ protected function get_keys_less_or_equal(array $messages, $value) { $value = (int) $value; $keys = array_reduce( array_keys($messages), /** * @param string $key */ function ($keys, $key) use ($value) { if ($key <= $value) { $keys[] = $key; } return $keys; }, array() ); return $keys; } /** * Rejects one or several received messages * * @param string $delivery_tag * @param bool $multiple * @param bool $requeue */ public function basic_nack($delivery_tag, $multiple = false, $requeue = false) { list($class_id, $method_id, $args) = $this->protocolWriter->basicNack($delivery_tag, $multiple, $requeue); $this->send_method_frame(array($class_id, $method_id), $args); } /** * Ends a queue consumer * * @param string $consumer_tag * @param bool $nowait * @param bool $noreturn * @throws \PhpAmqpLib\Exception\AMQPTimeoutException if the specified operation timeout was exceeded * @return mixed */ public function basic_cancel($consumer_tag, $nowait = false, $noreturn = false) { list($class_id, $method_id, $args) = $this->protocolWriter->basicCancel($consumer_tag, $nowait); $this->send_method_frame(array($class_id, $method_id), $args); if ($nowait || $noreturn) { unset($this->callbacks[$consumer_tag]); return $consumer_tag; } return $this->wait(array( $this->waitHelper->get_wait('basic.cancel_ok') ), false, $this->channel_rpc_timeout); } /** * @param AMQPReader $reader * @throws \PhpAmqpLib\Exception\AMQPBasicCancelException */ protected function basic_cancel_from_server(AMQPReader $reader) { throw new AMQPBasicCancelException($reader->read_shortstr()); } /** * Confirm a cancelled consumer * * @param AMQPReader $reader * @return string */ protected function basic_cancel_ok($reader) { $consumerTag = $reader->read_shortstr(); unset($this->callbacks[$consumerTag]); return $consumerTag; } /** * @return bool */ public function is_consuming() { return !empty($this->callbacks); } /** * Starts a queue consumer * * @param string $queue * @param string $consumer_tag * @param bool $no_local * @param bool $no_ack * @param bool $exclusive * @param bool $nowait * @param callable|null $callback * @param int|null $ticket * @param array $arguments * @throws \PhpAmqpLib\Exception\AMQPTimeoutException if the specified operation timeout was exceeded * @return mixed|string */ public function basic_consume( $queue = '', $consumer_tag = '', $no_local = false, $no_ack = false, $exclusive = false, $nowait = false, $callback = null, $ticket = null, $arguments = array() ) { $ticket = $this->getTicket($ticket); list($class_id, $method_id, $args) = $this->protocolWriter->basicConsume( $ticket, $queue, $consumer_tag, $no_local, $no_ack, $exclusive, $nowait, $this->protocolVersion === Wire\Constants091::VERSION ? $arguments : null ); $this->send_method_frame(array($class_id, $method_id), $args); if (false === $nowait) { $consumer_tag = $this->wait(array( $this->waitHelper->get_wait('basic.consume_ok') ), false, $this->channel_rpc_timeout); } $this->callbacks[$consumer_tag] = $callback; return $consumer_tag; } /** * Confirms a new consumer * * @param AMQPReader $reader * @return string */ protected function basic_consume_ok($reader) { return $reader->read_shortstr(); } /** * Notifies the client of a consumer message * * @param AMQPReader $reader * @param AMQPMessage $message */ protected function basic_deliver($reader, $message) { $consumer_tag = $reader->read_shortstr(); $delivery_tag = $reader->read_longlong(); $redelivered = $reader->read_bit(); $exchange = $reader->read_shortstr(); $routing_key = $reader->read_shortstr(); $message->delivery_info = array( 'channel' => $this, 'consumer_tag' => $consumer_tag, 'delivery_tag' => $delivery_tag, 'redelivered' => $redelivered, 'exchange' => $exchange, 'routing_key' => $routing_key ); if (isset($this->callbacks[$consumer_tag])) { call_user_func($this->callbacks[$consumer_tag], $message); } } /** * Direct access to a queue if no message was available in the queue, return null * * @param string $queue * @param bool $no_ack * @param int|null $ticket * @throws \PhpAmqpLib\Exception\AMQPTimeoutException if the specified operation timeout was exceeded * @return mixed */ public function basic_get($queue = '', $no_ack = false, $ticket = null) { $ticket = $this->getTicket($ticket); list($class_id, $method_id, $args) = $this->protocolWriter->basicGet($ticket, $queue, $no_ack); $this->send_method_frame(array($class_id, $method_id), $args); return $this->wait(array( $this->waitHelper->get_wait('basic.get_ok'), $this->waitHelper->get_wait('basic.get_empty') ), false, $this->channel_rpc_timeout); } /** * Indicates no messages available * * @param AMQPReader $reader */ protected function basic_get_empty($reader) { } /** * Provides client with a message * * @param AMQPReader $reader * @param AMQPMessage $message * @return AMQPMessage */ protected function basic_get_ok($reader, $message) { $delivery_tag = $reader->read_longlong(); $redelivered = $reader->read_bit(); $exchange = $reader->read_shortstr(); $routing_key = $reader->read_shortstr(); $message_count = $reader->read_long(); $message->delivery_info = array( 'delivery_tag' => $delivery_tag, 'redelivered' => $redelivered, 'exchange' => $exchange, 'routing_key' => $routing_key, 'message_count' => $message_count ); return $message; } /** * @param string $exchange * @param string $routing_key * @param $mandatory * @param $immediate * @param int $ticket * @return mixed */ private function pre_publish($exchange, $routing_key, $mandatory, $immediate, $ticket) { $cache_key = sprintf( '%s|%s|%s|%s|%s', $exchange, $routing_key, $mandatory, $immediate, $ticket ); if (false === isset($this->publish_cache[$cache_key])) { $ticket = $this->getTicket($ticket); list($class_id, $method_id, $args) = $this->protocolWriter->basicPublish( $ticket, $exchange, $routing_key, $mandatory, $immediate ); $pkt = $this->prepare_method_frame(array($class_id, $method_id), $args); $this->publish_cache[$cache_key] = $pkt->getvalue(); if (count($this->publish_cache) > $this->publish_cache_max_size) { reset($this->publish_cache); $old_key = key($this->publish_cache); unset($this->publish_cache[$old_key]); } } return $this->publish_cache[$cache_key]; } /** * Publishes a message * * @param AMQPMessage $msg * @param string $exchange * @param string $routing_key * @param bool $mandatory * @param bool $immediate * @param int|null $ticket */ public function basic_publish( $msg, $exchange = '', $routing_key = '', $mandatory = false, $immediate = false, $ticket = null ) { if ($this->connection === null) { throw new AMQPChannelClosedException('Channel connection is closed.'); } $pkt = new AMQPWriter(); $pkt->write($this->pre_publish($exchange, $routing_key, $mandatory, $immediate, $ticket)); try { $this->connection->send_content( $this->channel_id, 60, 0, mb_strlen($msg->body, 'ASCII'), $msg->serialize_properties(), $msg->body, $pkt ); } catch (AMQPConnectionClosedException $e) { $this->do_close(); throw $e; } if ($this->next_delivery_tag > 0) { $this->published_messages[$this->next_delivery_tag] = $msg; $this->next_delivery_tag++; } } /** * @param AMQPMessage $msg * @param string $exchange * @param string $routing_key * @param bool $mandatory * @param bool $immediate * @param int|null $ticket */ public function batch_basic_publish( $msg, $exchange = '', $routing_key = '', $mandatory = false, $immediate = false, $ticket = null ) { $this->batch_messages[] = func_get_args(); } /** * Publish batch * * @return void */ public function publish_batch() { if (empty($this->batch_messages)) { return null; } /** @var AMQPWriter $pkt */ $pkt = new AMQPWriter(); /** @var AMQPMessage $msg */ foreach ($this->batch_messages as $m) { $msg = $m[0]; $exchange = isset($m[1]) ? $m[1] : ''; $routing_key = isset($m[2]) ? $m[2] : ''; $mandatory = isset($m[3]) ? $m[3] : false; $immediate = isset($m[4]) ? $m[4] : false; $ticket = isset($m[5]) ? $m[5] : null; $pkt->write($this->pre_publish($exchange, $routing_key, $mandatory, $immediate, $ticket)); $this->connection->prepare_content( $this->channel_id, 60, 0, mb_strlen($msg->body, 'ASCII'), $msg->serialize_properties(), $msg->body, $pkt ); if ($this->next_delivery_tag > 0) { $this->published_messages[$this->next_delivery_tag] = $msg; $this->next_delivery_tag++; } } //call write here $this->connection->write($pkt->getvalue()); $this->batch_messages = array(); } /** * Specifies QoS * * @param int $prefetch_size * @param int $prefetch_count * @param bool $a_global * @throws \PhpAmqpLib\Exception\AMQPTimeoutException if the specified operation timeout was exceeded * @return mixed */ public function basic_qos($prefetch_size, $prefetch_count, $a_global) { list($class_id, $method_id, $args) = $this->protocolWriter->basicQos( $prefetch_size, $prefetch_count, $a_global ); $this->send_method_frame(array($class_id, $method_id), $args); return $this->wait(array( $this->waitHelper->get_wait('basic.qos_ok') ), false, $this->channel_rpc_timeout); } /** * Confirms QoS request * @param AMQPReader $reader */ protected function basic_qos_ok($reader) { } /** * Redelivers unacknowledged messages * * @param bool $requeue * @throws \PhpAmqpLib\Exception\AMQPTimeoutException if the specified operation timeout was exceeded * @return mixed */ public function basic_recover($requeue = false) { list($class_id, $method_id, $args) = $this->protocolWriter->basicRecover($requeue); $this->send_method_frame(array($class_id, $method_id), $args); return $this->wait(array( $this->waitHelper->get_wait('basic.recover_ok') ), false, $this->channel_rpc_timeout); } /** * Confirm the requested recover * @param AMQPReader $reader */ protected function basic_recover_ok($reader) { } /** * Rejects an incoming message * * @param string $delivery_tag * @param bool $requeue */ public function basic_reject($delivery_tag, $requeue) { list($class_id, $method_id, $args) = $this->protocolWriter->basicReject($delivery_tag, $requeue); $this->send_method_frame(array($class_id, $method_id), $args); } /** * Returns a failed message * * @param AMQPReader $reader * @param AMQPMessage $message * @return null */ protected function basic_return($reader, $message) { $callback = $this->basic_return_callback; if (!is_callable($callback)) { $this->debug->debug_msg('Skipping unhandled basic_return message'); return null; } $reply_code = $reader->read_short(); $reply_text = $reader->read_shortstr(); $exchange = $reader->read_shortstr(); $routing_key = $reader->read_shortstr(); call_user_func_array($callback, array( $reply_code, $reply_text, $exchange, $routing_key, $message, )); } /** * @throws \PhpAmqpLib\Exception\AMQPTimeoutException if the specified operation timeout was exceeded * @return mixed */ public function tx_commit() { $this->send_method_frame(array(90, 20)); return $this->wait(array( $this->waitHelper->get_wait('tx.commit_ok') ), false, $this->channel_rpc_timeout); } /** * Confirms a successful commit * @param AMQPReader $reader */ protected function tx_commit_ok($reader) { } /** * Rollbacks the current transaction * * @throws \PhpAmqpLib\Exception\AMQPTimeoutException if the specified operation timeout was exceeded * @return mixed */ public function tx_rollback() { $this->send_method_frame(array(90, 30)); return $this->wait(array( $this->waitHelper->get_wait('tx.rollback_ok') ), false, $this->channel_rpc_timeout); } /** * Confirms a successful rollback * * @param AMQPReader $reader */ protected function tx_rollback_ok($reader) { } /** * Puts the channel into confirm mode * Beware that only non-transactional channels may be put into confirm mode and vice versa * * @param bool $nowait * @throws \PhpAmqpLib\Exception\AMQPTimeoutException if the specified operation timeout was exceeded * @return null */ public function confirm_select($nowait = false) { list($class_id, $method_id, $args) = $this->protocolWriter->confirmSelect($nowait); $this->send_method_frame(array($class_id, $method_id), $args); if ($nowait) { return null; } $this->wait(array( $this->waitHelper->get_wait('confirm.select_ok') ), false, $this->channel_rpc_timeout); $this->next_delivery_tag = 1; } /** * Confirms a selection * * @param AMQPReader $reader */ public function confirm_select_ok($reader) { } /** * Waits for pending acks and nacks from the server. * If there are no pending acks, the method returns immediately * * @param int|float $timeout Waits until $timeout value is reached * @throws \PhpAmqpLib\Exception\AMQPTimeoutException * @throws \PhpAmqpLib\Exception\AMQPRuntimeException */ public function wait_for_pending_acks($timeout = 0) { $functions = array( $this->waitHelper->get_wait('basic.ack'), $this->waitHelper->get_wait('basic.nack'), ); $timeout = max(0, $timeout); while (!empty($this->published_messages)) { $this->wait($functions, false, $timeout); } } /** * Waits for pending acks, nacks and returns from the server. * If there are no pending acks, the method returns immediately. * * @param int|float $timeout If set to value > 0 the method will wait at most $timeout seconds for pending acks. * @throws \PhpAmqpLib\Exception\AMQPTimeoutException * @throws \PhpAmqpLib\Exception\AMQPRuntimeException */ public function wait_for_pending_acks_returns($timeout = 0) { $functions = array( $this->waitHelper->get_wait('basic.ack'), $this->waitHelper->get_wait('basic.nack'), $this->waitHelper->get_wait('basic.return'), ); $timeout = max(0, $timeout); while (!empty($this->published_messages)) { $this->wait($functions, false, $timeout); } } /** * Selects standard transaction mode * * @throws \PhpAmqpLib\Exception\AMQPTimeoutException if the specified operation timeout was exceeded * @return mixed */ public function tx_select() { $this->send_method_frame(array(90, 10)); return $this->wait(array( $this->waitHelper->get_wait('tx.select_ok') ), false, $this->channel_rpc_timeout); } /** * Confirms transaction mode * @param AMQPReader $reader */ protected function tx_select_ok($reader) { } /** * @param array $arguments * @return array */ protected function getArguments($arguments) { @trigger_error(sprintf( 'Method "%s" is deprecated, please use an array as a default argument instead', __METHOD__ ), E_USER_DEPRECATED); return (null === $arguments) ? array() : $arguments; } /** * @param int|null $ticket * @return int */ protected function getTicket($ticket) { return (null === $ticket) ? $this->default_ticket : $ticket; } /** * Helper method to get a particular method from $this->publishedMessages, removes it from the array and returns it. * * @param int $index * @return AMQPMessage */ protected function get_and_unset_message($index) { $message = $this->published_messages[$index]; unset($this->published_messages[$index]); return $message; } /** * Sets callback for basic_return * * @param callable $callback * @throws \InvalidArgumentException if $callback is not callable */ public function set_return_listener($callback) { if (!is_callable($callback)) { throw new \InvalidArgumentException(sprintf( 'Given callback "%s" should be callable. %s type was given.', $callback, gettype($callback) )); } $this->basic_return_callback = $callback; } /** * Sets a handler which called for any message nack'ed by the server, with the AMQPMessage as first argument. * * @param callable $callback * @throws \InvalidArgumentException */ public function set_nack_handler($callback) { if (!is_callable($callback)) { throw new \InvalidArgumentException(sprintf( 'Given callback "%s" should be callable. %s type was given.', $callback, gettype($callback) )); } $this->nack_handler = $callback; } /** * Sets a handler which called for any message ack'ed by the server, with the AMQPMessage as first argument. * * @param callable $callback * @throws \InvalidArgumentException */ public function set_ack_handler($callback) { if (!is_callable($callback)) { throw new \InvalidArgumentException(sprintf( 'Given callback "%s" should be callable. %s type was given.', $callback, gettype($callback) )); } $this->ack_handler = $callback; } } php-amqplib-2.11.0/PhpAmqpLib/Channel/AbstractChannel.php000066400000000000000000000367741356514014400231430ustar00rootroot00000000000000connection = $connection; $this->channel_id = $channel_id; $connection->channels[$channel_id] = $this; $this->msg_property_reader = new AMQPReader(null); $this->wait_content_reader = new AMQPReader(null); $this->dispatch_reader = new AMQPReader(null); $this->protocolVersion = self::getProtocolVersion(); switch ($this->protocolVersion) { case Wire\Constants091::VERSION: $constantClass = Wire\Constants091::class; $this->protocolWriter = new Protocol091(); $this->waitHelper = new Wait091(); $this->methodMap = new MethodMap091(); break; case Wire\Constants080::VERSION: $constantClass = Wire\Constants080::class; $this->protocolWriter = new Protocol080(); $this->waitHelper = new Wait080(); $this->methodMap = new MethodMap080(); break; default: throw new AMQPNotImplementedException(sprintf( 'Protocol: %s not implemented.', $this->protocolVersion )); } $this->constants = new $constantClass; $this->debug = new DebugHelper($this->constants); } /** * @return string * @throws AMQPOutOfRangeException */ public static function getProtocolVersion() { $protocol = defined('AMQP_PROTOCOL') ? AMQP_PROTOCOL : Wire\Constants091::VERSION; //adding check here to catch unknown protocol ASAP, as this method may be called from the outside if (!in_array($protocol, array(Wire\Constants080::VERSION, Wire\Constants091::VERSION), TRUE)) { throw new AMQPOutOfRangeException(sprintf('Protocol version %s not implemented.', $protocol)); } return $protocol; } /** * @return string */ public function getChannelId() { return $this->channel_id; } /** * @param int $max_bytes Max message body size for this channel * @return $this */ public function setBodySizeLimit($max_bytes) { $max_bytes = (int) $max_bytes; if ($max_bytes > 0) { $this->maxBodySize = $max_bytes; } return $this; } /** * @return AbstractConnection */ public function getConnection() { return $this->connection; } /** * @return array */ public function getMethodQueue() { return $this->method_queue; } /** * @return bool */ public function hasPendingMethods() { return !empty($this->method_queue); } /** * @param string $method_sig * @param string $args * @param AMQPMessage|null $amqpMessage * @return mixed * @throws \PhpAmqpLib\Exception\AMQPRuntimeException */ public function dispatch($method_sig, $args, $amqpMessage) { if (!$this->methodMap->valid_method($method_sig)) { throw new AMQPNotImplementedException(sprintf( 'Unknown AMQP method "%s"', $method_sig )); } $amqp_method = $this->methodMap->get_method($method_sig); if (!method_exists($this, $amqp_method)) { throw new AMQPNotImplementedException(sprintf( 'Method: "%s" not implemented by class: %s', $amqp_method, get_class($this) )); } $this->dispatch_reader->reuse($args); if ($amqpMessage == null) { return call_user_func(array($this, $amqp_method), $this->dispatch_reader); } return call_user_func(array($this, $amqp_method), $this->dispatch_reader, $amqpMessage); } /** * @param int|float|null $timeout * @return array|mixed */ public function next_frame($timeout = 0) { $this->debug->debug_msg('waiting for a new frame'); if (!empty($this->frame_queue)) { return array_shift($this->frame_queue); } return $this->connection->wait_channel($this->channel_id, $timeout); } /** * @param array $method_sig * @param \PhpAmqpLib\Wire\AMQPWriter|string $args */ protected function send_method_frame($method_sig, $args = '') { if ($this->connection === null) { throw new AMQPChannelClosedException('Channel connection is closed.'); } $this->connection->send_channel_method_frame($this->channel_id, $method_sig, $args); } /** * This is here for performance reasons to batch calls to fwrite from basic.publish * * @param array $method_sig * @param \PhpAmqpLib\Wire\AMQPWriter|string $args * @param \PhpAmqpLib\Wire\AMQPWriter $pkt * @return \PhpAmqpLib\Wire\AMQPWriter */ protected function prepare_method_frame($method_sig, $args = '', $pkt = null) { return $this->connection->prepare_channel_method_frame($this->channel_id, $method_sig, $args, $pkt); } /** * @return AMQPMessage * @throws \PhpAmqpLib\Exception\AMQPRuntimeException */ public function wait_content() { list($frame_type, $payload) = $this->next_frame(); $this->validate_header_frame($frame_type); $this->wait_content_reader->reuse(mb_substr($payload, 0, 12, 'ASCII')); $class_id = $this->wait_content_reader->read_short(); $weight = $this->wait_content_reader->read_short(); //hack to avoid creating new instances of AMQPReader; $this->msg_property_reader->reuse(mb_substr($payload, 12, mb_strlen($payload, 'ASCII') - 12, 'ASCII')); return $this->createMessage( $this->msg_property_reader, $this->wait_content_reader ); } /** * @param AMQPReader $propertyReader * @param AMQPReader $contentReader * @return \PhpAmqpLib\Message\AMQPMessage */ protected function createMessage($propertyReader, $contentReader) { $bodyChunks = array(); $bodyReceivedBytes = 0; $message = new AMQPMessage(); $message ->load_properties($propertyReader) ->setBodySize($contentReader->read_longlong()); while ($message->getBodySize() > $bodyReceivedBytes) { list($frame_type, $payload) = $this->next_frame(); $this->validate_body_frame($frame_type); $bodyReceivedBytes += mb_strlen($payload, 'ASCII'); if (is_int($this->maxBodySize) && $bodyReceivedBytes > $this->maxBodySize ) { $message->setIsTruncated(true); continue; } $bodyChunks[] = $payload; } $message->setBody(implode('', $bodyChunks)); return $message; } /** * Wait for some expected AMQP methods and dispatch to them. * Unexpected methods are queued up for later calls to this PHP * method. * * @param array $allowed_methods * @param bool $non_blocking * @param int|float|null $timeout * @throws \PhpAmqpLib\Exception\AMQPOutOfBoundsException * @throws \PhpAmqpLib\Exception\AMQPRuntimeException * @throws \PhpAmqpLib\Exception\AMQPTimeoutException * @throws \ErrorException * @return mixed */ public function wait($allowed_methods = null, $non_blocking = false, $timeout = 0) { $this->debug->debug_allowed_methods($allowed_methods); $deferred = $this->process_deferred_methods($allowed_methods); if ($deferred['dispatch'] === true) { return $this->dispatch_deferred_method($deferred['queued_method']); } // timeouts must be deactivated for non-blocking actions if (true === $non_blocking) { $timeout = null; } // No deferred methods? wait for new ones while (true) { try { list($frame_type, $payload) = $this->next_frame($timeout); } catch (AMQPNoDataException $e) { // no data ready for non-blocking actions - stop and exit break; } catch (AMQPConnectionClosedException $exception) { if ($this instanceof AMQPChannel) { $this->do_close(); } throw $exception; } $this->validate_method_frame($frame_type); $this->validate_frame_payload($payload); $method_sig = $this->build_method_signature($payload); $args = $this->extract_args($payload); $this->debug->debug_method_signature('> %s', $method_sig); $amqpMessage = $this->maybe_wait_for_content($method_sig); if ($this->should_dispatch_method($allowed_methods, $method_sig)) { return $this->dispatch($method_sig, $args, $amqpMessage); } // Wasn't what we were looking for? save it for later $this->debug->debug_method_signature('Queueing for later: %s', $method_sig); $this->method_queue[] = array($method_sig, $args, $amqpMessage); if ($non_blocking) { break; } } } /** * @param array $allowed_methods * @return array */ protected function process_deferred_methods($allowed_methods) { $dispatch = false; $queued_method = array(); foreach ($this->method_queue as $qk => $qm) { $this->debug->debug_msg('checking queue method ' . $qk); $method_sig = $qm[0]; if ($allowed_methods == null || in_array($method_sig, $allowed_methods)) { unset($this->method_queue[$qk]); $dispatch = true; $queued_method = $qm; break; } } return array('dispatch' => $dispatch, 'queued_method' => $queued_method); } /** * @param array $queued_method * @return mixed */ protected function dispatch_deferred_method($queued_method) { $this->debug->debug_method_signature('Executing queued method: %s', $queued_method[0]); return $this->dispatch($queued_method[0], $queued_method[1], $queued_method[2]); } /** * @param int $frame_type * @throws \PhpAmqpLib\Exception\AMQPInvalidFrameException */ protected function validate_method_frame($frame_type) { $this->validate_frame($frame_type, 1, 'AMQP method'); } /** * @param int $frame_type * @throws \PhpAmqpLib\Exception\AMQPInvalidFrameException */ protected function validate_header_frame($frame_type) { $this->validate_frame($frame_type, 2, 'AMQP Content header'); } /** * @param int $frame_type * @throws \PhpAmqpLib\Exception\AMQPInvalidFrameException */ protected function validate_body_frame($frame_type) { $this->validate_frame($frame_type, 3, 'AMQP Content body'); } /** * @param int $frameType * @param int $expectedType * @param string $expectedMessage */ protected function validate_frame($frameType, $expectedType, $expectedMessage) { if ($frameType != $expectedType) { throw new AMQPInvalidFrameException(sprintf( 'Expecting %s, received frame type %s (%s)', $expectedMessage, $frameType, $this->constants->getFrameType($frameType) )); } } /** * @param string $payload * @throws \PhpAmqpLib\Exception\AMQPOutOfBoundsException */ protected function validate_frame_payload($payload) { if (mb_strlen($payload, 'ASCII') < 4) { throw new AMQPOutOfBoundsException('Method frame too short'); } } /** * @param string $payload * @return string */ protected function build_method_signature($payload) { $method_sig_array = unpack('n2', mb_substr($payload, 0, 4, 'ASCII')); return sprintf('%s,%s', $method_sig_array[1], $method_sig_array[2]); } /** * @param string $payload * @return string */ protected function extract_args($payload) { return mb_substr($payload, 4, mb_strlen($payload, 'ASCII') - 4, 'ASCII'); } /** * @param array|null $allowed_methods * @param string $method_sig * @return bool */ protected function should_dispatch_method($allowed_methods, $method_sig) { return $allowed_methods == null || in_array($method_sig, $allowed_methods) || $this->constants->isCloseMethod($method_sig); } /** * @param string $method_sig * @return AMQPMessage|null */ protected function maybe_wait_for_content($method_sig) { $amqpMessage = null; if ($this->constants->isContentMethod($method_sig)) { $amqpMessage = $this->wait_content(); } return $amqpMessage; } /** * @param callable $handler * @param array $arguments */ protected function dispatch_to_handler($handler, array $arguments) { if (is_callable($handler)) { call_user_func_array($handler, $arguments); } } } php-amqplib-2.11.0/PhpAmqpLib/Connection/000077500000000000000000000000001356514014400201045ustar00rootroot00000000000000php-amqplib-2.11.0/PhpAmqpLib/Connection/AMQPConnection.php000066400000000000000000000002421356514014400233710ustar00rootroot00000000000000connect(); return parent::getSocket(); } /** * {@inheritdoc} */ public function channel($channel_id = null) { $this->connect(); return parent::channel($channel_id); } /** * @return null|\PhpAmqpLib\Wire\IO\AbstractIO */ public function getIO() { if (empty($this->io)) { $this->connect(); } return $this->io; } /** * Should the connection be attempted during construction? * * @return bool */ public function connectOnConstruct() { return false; } } php-amqplib-2.11.0/PhpAmqpLib/Connection/AMQPLazySocketConnection.php000066400000000000000000000017311356514014400254060ustar00rootroot00000000000000connect(); return parent::getSocket(); } /** * {@inheritdoc} */ public function channel($channel_id = null) { $this->connect(); return parent::channel($channel_id); } /** * @return null|\PhpAmqpLib\Wire\IO\AbstractIO */ public function getIO() { if (empty($this->io)) { $this->connect(); } return $this->io; } /** * Should the connection be attempted during construction? * * @return bool */ public function connectOnConstruct() { return false; } } php-amqplib-2.11.0/PhpAmqpLib/Connection/AMQPSSLConnection.php000066400000000000000000000042151356514014400237570ustar00rootroot00000000000000create_ssl_context($ssl_options); parent::__construct( $host, $port, $user, $password, $vhost, isset($options['insist']) ? $options['insist'] : false, isset($options['login_method']) ? $options['login_method'] : 'AMQPLAIN', isset($options['login_response']) ? $options['login_response'] : null, isset($options['locale']) ? $options['locale'] : 'en_US', isset($options['connection_timeout']) ? $options['connection_timeout'] : 3, isset($options['read_write_timeout']) ? $options['read_write_timeout'] : 130, $ssl_context, isset($options['keepalive']) ? $options['keepalive'] : false, isset($options['heartbeat']) ? $options['heartbeat'] : 0, isset($options['channel_rpc_timeout']) ? $options['channel_rpc_timeout'] : 0.0, $ssl_protocol ); } public static function try_create_connection($host, $port, $user, $password, $vhost, $options) { $ssl_options = isset($options['ssl_options']) ? $options['ssl_options'] : []; return new static($host, $port, $user, $password, $vhost, $ssl_options, $options); } /** * @param array $options * @return resource */ private function create_ssl_context($options) { $ssl_context = stream_context_create(); foreach ($options as $k => $v) { stream_context_set_option($ssl_context, 'ssl', $k, $v); } return $ssl_context; } } php-amqplib-2.11.0/PhpAmqpLib/Connection/AMQPSocketConnection.php000066400000000000000000000060471356514014400245530ustar00rootroot00000000000000 $read_timeout) { throw new \InvalidArgumentException('channel RPC timeout must not be greater than I/O read timeout'); } $io = new SocketIO($host, $port, $read_timeout, $keepalive, $write_timeout, $heartbeat); parent::__construct( $user, $password, $vhost, $insist, $login_method, $login_response, $locale, $io, $heartbeat, max($read_timeout, $write_timeout), $channel_rpc_timeout ); } protected static function try_create_connection($host, $port, $user, $password, $vhost, $options){ $insist = isset($options['insist']) ? $options['insist'] : false; $login_method = isset($options['login_method']) ? $options['login_method'] :'AMQPLAIN'; $login_response = isset($options['login_response']) ? $options['login_response'] : null; $locale = isset($options['locale']) ? $options['locale'] : 'en_US'; $read_timeout = isset($options['read_timeout']) ? $options['read_timeout'] : 3; $keepalive = isset($options['keepalive']) ? $options['keepalive'] : false; $write_timeout = isset($options['write_timeout']) ? $options['write_timeout'] : 3; $heartbeat = isset($options['heartbeat']) ? $options['heartbeat'] : 0; return new static($host, $port, $user, $password, $vhost, $insist, $login_method, $login_response, $locale, $read_timeout, $keepalive, $write_timeout, $heartbeat); } } php-amqplib-2.11.0/PhpAmqpLib/Connection/AMQPStreamConnection.php000066400000000000000000000071271356514014400245560ustar00rootroot00000000000000 $read_write_timeout) { throw new \InvalidArgumentException('channel RPC timeout must not be greater than I/O read-write timeout'); } $io = new StreamIO( $host, $port, $connection_timeout, $read_write_timeout, $context, $keepalive, $heartbeat, $ssl_protocol ); parent::__construct( $user, $password, $vhost, $insist, $login_method, $login_response, $locale, $io, $heartbeat, $connection_timeout, $channel_rpc_timeout ); // save the params for the use of __clone, this will overwrite the parent $this->construct_params = func_get_args(); } protected static function try_create_connection($host, $port, $user, $password, $vhost, $options){ $insist = isset($options['insist']) ? $options['insist'] : false; $login_method = isset($options['login_method']) ? $options['login_method'] :'AMQPLAIN'; $login_response = isset($options['login_response']) ? $options['login_response'] : null; $locale = isset($options['locale']) ? $options['locale'] : 'en_US'; $connection_timeout = isset($options['connection_timeout']) ? $options['connection_timeout'] : 3.0; $read_write_timeout = isset($options['read_write_timeout']) ? $options['read_write_timeout'] : 130.0; $context = isset($options['context']) ? $options['context'] : null; $keepalive = isset($options['keepalive']) ? $options['keepalive'] : false; $heartbeat = isset($options['heartbeat']) ? $options['heartbeat'] : 60; return new static($host, $port, $user, $password, $vhost, $insist, $login_method, $login_response, $locale, $connection_timeout, $read_write_timeout, $context, $keepalive, $heartbeat); } } php-amqplib-2.11.0/PhpAmqpLib/Connection/AbstractConnection.php000066400000000000000000000764171356514014400244170ustar00rootroot00000000000000 array('S', 'AMQPLib'), 'platform' => array('S', 'PHP'), 'version' => array('S', '2.11.0'), 'information' => array('S', ''), 'copyright' => array('S', ''), 'capabilities' => array( 'F', array( 'authentication_failure_close' => array('t', true), 'publisher_confirms' => array('t', true), 'consumer_cancel_notify' => array('t', true), 'exchange_exchange_bindings' => array('t', true), 'basic.nack' => array('t', true), 'connection.blocked' => array('t', true) ) ) ); /** * @var AMQPChannel[] * @internal */ public $channels = array(); /** @var int */ protected $version_major; /** @var int */ protected $version_minor; /** @var array */ protected $server_properties; /** @var array */ protected $mechanisms; /** @var array */ protected $locales; /** @var bool */ protected $wait_tune_ok; /** @var string */ protected $known_hosts; /** @var AMQPReader */ protected $input; /** @var string */ protected $vhost; /** @var bool */ protected $insist; /** @var string */ protected $login_method; /** * @var string * @deprecated */ protected $login_response; /** @var string */ protected $locale; /** @var int */ protected $heartbeat; /** @var float */ protected $last_frame; /** @var int */ protected $channel_max = 65535; /** @var int */ protected $frame_max = 131072; /** @var array Constructor parameters for clone */ protected $construct_params; /** @var bool Close the connection in destructor */ protected $close_on_destruct = true; /** @var bool Maintain connection status */ protected $is_connected = false; /** @var \PhpAmqpLib\Wire\IO\AbstractIO */ protected $io; /** @var \PhpAmqpLib\Wire\AMQPReader */ protected $wait_frame_reader; /** @var callable Handles connection blocking from the server */ private $connection_block_handler; /** @var callable Handles connection unblocking from the server */ private $connection_unblock_handler; /** @var int Connection timeout value*/ protected $connection_timeout ; /** * Circular buffer to speed up prepare_content(). * Max size limited by $prepare_content_cache_max_size. * * @var array * @see prepare_content() */ private $prepare_content_cache = array(); /** @var int Maximal size of $prepare_content_cache */ private $prepare_content_cache_max_size = 100; /** * Maximum time to wait for channel operations, in seconds * @var float $channel_rpc_timeout */ private $channel_rpc_timeout; /** * @param string $user * @param string $password * @param string $vhost * @param bool $insist * @param string $login_method * @param null $login_response @deprecated * @param string $locale * @param AbstractIO $io * @param int $heartbeat * @param int $connection_timeout * @param float $channel_rpc_timeout * @throws \Exception */ public function __construct( $user, $password, $vhost = '/', $insist = false, $login_method = 'AMQPLAIN', $login_response = null, $locale = 'en_US', AbstractIO $io, $heartbeat = 0, $connection_timeout = 0, $channel_rpc_timeout = 0.0 ) { // save the params for the use of __clone $this->construct_params = func_get_args(); $this->wait_frame_reader = new AMQPReader(null); $this->vhost = $vhost; $this->insist = $insist; $this->login_method = $login_method; $this->login_response = $login_response; $this->locale = $locale; $this->io = $io; $this->heartbeat = $heartbeat; $this->connection_timeout = $connection_timeout; $this->channel_rpc_timeout = $channel_rpc_timeout; if ($user && $password) { if ($login_method === 'PLAIN') { $this->login_response = sprintf("\0%s\0%s", $user, $password); } elseif ($login_method === 'AMQPLAIN') { $this->login_response = new AMQPWriter(); $this->login_response->write_table(array( 'LOGIN' => array('S', $user), 'PASSWORD' => array('S', $password) )); // Skip the length $responseValue = $this->login_response->getvalue(); $this->login_response = mb_substr($responseValue, 4, mb_strlen($responseValue, 'ASCII') - 4, 'ASCII'); } else { throw new \InvalidArgumentException('Unknown login method: ' . $login_method); } } else { $this->login_response = null; } // Lazy Connection waits on connecting if ($this->connectOnConstruct()) { $this->connect(); } } /** * Connects to the AMQP server */ protected function connect() { try { // Loop until we connect while (!$this->isConnected()) { // Assume we will connect, until we dont $this->setIsConnected(true); // Connect the socket $this->io->connect(); $this->channels = array(); // The connection object itself is treated as channel 0 parent::__construct($this, 0); $this->input = new AMQPReader(null, $this->io); $this->write($this->constants->getHeader()); // assume frame was sent successfully, used in $this->wait_channel() $this->last_frame = microtime(true); $this->wait(array($this->waitHelper->get_wait('connection.start')),false,$this->connection_timeout); $this->x_start_ok( $this->getLibraryProperties(), $this->login_method, $this->login_response, $this->locale ); $this->wait_tune_ok = true; while ($this->wait_tune_ok) { $this->wait(array( $this->waitHelper->get_wait('connection.secure'), $this->waitHelper->get_wait('connection.tune') ), false, $this->connection_timeout); } $host = $this->x_open($this->vhost, '', $this->insist); if (!$host) { //Reconnected $this->io->reenableHeartbeat(); return null; // we weren't redirected } $this->setIsConnected(false); $this->closeChannels(); // we were redirected, close the socket, loop and try again $this->close_socket(); } } catch (\Exception $e) { // Something went wrong, set the connection status $this->setIsConnected(false); $this->closeChannels(); $this->close_input(); $this->close_socket(); throw $e; // Rethrow exception } } /** * Reconnects using the original connection settings. * This will not recreate any channels that were established previously */ public function reconnect() { // Try to close the AMQP connection $this->safeClose(); // Reconnect the socket/stream then AMQP $this->io->close(); $this->setIsConnected(false); // getIO can initiate the connection setting via LazyConnection, set it here to be sure $this->connect(); } /** * Cloning will use the old properties to make a new connection to the same server */ public function __clone() { call_user_func_array(array($this, '__construct'), $this->construct_params); } public function __destruct() { if ($this->close_on_destruct) { $this->safeClose(); } } /** * Attempts to close the connection safely */ protected function safeClose() { try { if (isset($this->input) && $this->input) { $this->close(); } } catch (\Exception $e) { // Nothing here } } /** * @param int $sec * @param int $usec * @return mixed */ public function select($sec, $usec = 0) { try { return $this->io->select($sec, $usec); } catch (AMQPConnectionClosedException $e) { $this->do_close(); throw $e; } catch (AMQPRuntimeException $e) { $this->setIsConnected(false); throw $e; } } /** * Allows to not close the connection * it's useful after the fork when you don't want to close parent process connection * * @param bool $close */ public function set_close_on_destruct($close = true) { $this->close_on_destruct = (bool) $close; } protected function close_input() { $this->debug && $this->debug->debug_msg('closing input'); if (!is_null($this->input)) { $this->input->close(); $this->input = null; } } protected function close_socket() { $this->debug && $this->debug->debug_msg('closing socket'); if ($this->io) { $this->io->close(); } } /** * @param string $data */ public function write($data) { $this->debug->debug_hexdump($data); try { $this->io->write($data); } catch (AMQPConnectionClosedException $e) { $this->do_close(); throw $e; } catch (AMQPRuntimeException $e) { $this->setIsConnected(false); throw $e; } } protected function do_close() { $this->frame_queue = []; $this->method_queue = []; $this->setIsConnected(false); $this->close_input(); $this->close_socket(); } /** * @return int * @throws \PhpAmqpLib\Exception\AMQPRuntimeException */ public function get_free_channel_id() { for ($i = 1; $i <= $this->channel_max; $i++) { if (!isset($this->channels[$i])) { return $i; } } throw new AMQPRuntimeException('No free channel ids'); } /** * @param string $channel * @param int $class_id * @param int $weight * @param int $body_size * @param string $packed_properties * @param string $body * @param AMQPWriter $pkt */ public function send_content($channel, $class_id, $weight, $body_size, $packed_properties, $body, $pkt = null) { $this->prepare_content($channel, $class_id, $weight, $body_size, $packed_properties, $body, $pkt); $this->write($pkt->getvalue()); } /** * Returns a new AMQPWriter or mutates the provided $pkt * * @param string $channel * @param int $class_id * @param int $weight * @param int $body_size * @param string $packed_properties * @param string $body * @param AMQPWriter $pkt * @return AMQPWriter */ public function prepare_content($channel, $class_id, $weight, $body_size, $packed_properties, $body, $pkt = null) { $pkt = $pkt ?: new AMQPWriter(); // Content already prepared ? $key_cache = sprintf( '%s|%s|%s|%s', $channel, $packed_properties, $class_id, $weight ); if (!isset($this->prepare_content_cache[$key_cache])) { $w = new AMQPWriter(); $w->write_octet(2); $w->write_short($channel); $w->write_long(mb_strlen($packed_properties, 'ASCII') + 12); $w->write_short($class_id); $w->write_short($weight); $this->prepare_content_cache[$key_cache] = $w->getvalue(); if (count($this->prepare_content_cache) > $this->prepare_content_cache_max_size) { reset($this->prepare_content_cache); $old_key = key($this->prepare_content_cache); unset($this->prepare_content_cache[$old_key]); } } $pkt->write($this->prepare_content_cache[$key_cache]); $pkt->write_longlong($body_size); $pkt->write($packed_properties); $pkt->write_octet(0xCE); // memory efficiency: walk the string instead of biting // it. good for very large packets (close in size to // memory_limit setting) $position = 0; $bodyLength = mb_strlen($body,'ASCII'); while ($position < $bodyLength) { $payload = mb_substr($body, $position, $this->frame_max - 8, 'ASCII'); $position += $this->frame_max - 8; $pkt->write_octet(3); $pkt->write_short($channel); $pkt->write_long(mb_strlen($payload, 'ASCII')); $pkt->write($payload); $pkt->write_octet(0xCE); } return $pkt; } /** * @param string $channel * @param array $method_sig * @param AMQPWriter|string $args * @param null $pkt */ protected function send_channel_method_frame($channel, $method_sig, $args = '', $pkt = null) { $pkt = $this->prepare_channel_method_frame($channel, $method_sig, $args, $pkt); $this->write($pkt->getvalue()); $this->debug->debug_method_signature1($method_sig); } /** * Returns a new AMQPWriter or mutates the provided $pkt * * @param string $channel * @param array $method_sig * @param AMQPWriter|string $args * @param AMQPWriter $pkt * @return AMQPWriter */ protected function prepare_channel_method_frame($channel, $method_sig, $args = '', $pkt = null) { if ($args instanceof AMQPWriter) { $args = $args->getvalue(); } $pkt = $pkt ?: new AMQPWriter(); $pkt->write_octet(1); $pkt->write_short($channel); $pkt->write_long(mb_strlen($args, 'ASCII') + 4); // 4 = length of class_id and method_id // in payload $pkt->write_short($method_sig[0]); // class_id $pkt->write_short($method_sig[1]); // method_id $pkt->write($args); $pkt->write_octet(0xCE); $this->debug->debug_method_signature1($method_sig); return $pkt; } /** * Waits for a frame from the server * * @param int|float|null $timeout * @return array * @throws \Exception * @throws \PhpAmqpLib\Exception\AMQPTimeoutException * @throws \PhpAmqpLib\Exception\AMQPRuntimeException */ protected function wait_frame($timeout = 0) { if (is_null($this->input)) { $this->setIsConnected(false); throw new AMQPConnectionClosedException('Broken pipe or closed connection'); } $currentTimeout = $this->input->getTimeout(); $this->input->setTimeout($timeout); try { // frame_type + channel_id + size $this->wait_frame_reader->reuse( $this->input->read(AMQPReader::OCTET + AMQPReader::SHORT + AMQPReader::LONG) ); $frame_type = $this->wait_frame_reader->read_octet(); if (!$this->constants->isFrameType($frame_type)) { throw new AMQPInvalidFrameException('Invalid frame type ' . $frame_type); } $channel = $this->wait_frame_reader->read_short(); $size = $this->wait_frame_reader->read_long(); // payload + ch $this->wait_frame_reader->reuse($this->input->read(AMQPReader::OCTET + (int) $size)); $payload = $this->wait_frame_reader->read($size); $ch = $this->wait_frame_reader->read_octet(); } catch (AMQPTimeoutException $e) { if ($this->input) { $this->input->setTimeout($currentTimeout); } throw $e; } catch (AMQPNoDataException $e) { if ($this->input) { $this->input->setTimeout($currentTimeout); } throw $e; } catch (AMQPConnectionClosedException $exception) { $this->do_close(); throw $exception; } $this->input->setTimeout($currentTimeout); if ($ch != 0xCE) { throw new AMQPInvalidFrameException(sprintf( 'Framing error, unexpected byte: %x', $ch )); } return array($frame_type, $channel, $payload); } /** * Waits for a frame from the server destined for a particular channel. * * @param string $channel_id * @param int|float|null $timeout * @return array */ protected function wait_channel($channel_id, $timeout = 0) { // Keeping the original timeout unchanged. $_timeout = $timeout; while (true) { $start = microtime(true); try { list($frame_type, $frame_channel, $payload) = $this->wait_frame($_timeout); } catch (AMQPTimeoutException $e) { if ($this->heartbeat && $this->last_frame && microtime(true) - ($this->heartbeat * 2) > $this->last_frame) { $this->debug->debug_msg("missed server heartbeat (at threshold * 2)"); $this->setIsConnected(false); throw new AMQPHeartbeatMissedException("Missed server heartbeat"); } throw $e; } $this->last_frame = microtime(true); if ($frame_channel === 0 && $frame_type === 8) { // skip heartbeat frames and reduce the timeout by the time passed $this->debug->debug_msg("received server heartbeat"); if($_timeout > 0) { $_timeout -= $this->last_frame - $start; if($_timeout <= 0) { // If timeout has been reached, throw the exception without calling wait_frame throw new AMQPTimeoutException("Timeout waiting on channel"); } } continue; } if ($frame_channel == $channel_id) { return array($frame_type, $payload); } // Not the channel we were looking for. Queue this frame //for later, when the other channel is looking for frames. // Make sure the channel still exists, it could have been // closed by a previous Exception. if (isset($this->channels[$frame_channel])) { array_push($this->channels[$frame_channel]->frame_queue, array($frame_type, $payload)); } // If we just queued up a method for channel 0 (the Connection // itself) it's probably a close method in reaction to some // error, so deal with it right away. if ($frame_type == 1 && $frame_channel == 0) { $this->wait(); } } } /** * Fetches a channel object identified by the numeric channel_id, or * create that object if it doesn't already exist. * * @param int $channel_id * @return AMQPChannel */ public function channel($channel_id = null) { if (isset($this->channels[$channel_id])) { return $this->channels[$channel_id]; } $channel_id = $channel_id ? $channel_id : $this->get_free_channel_id(); $ch = new AMQPChannel($this->connection, $channel_id, true, $this->channel_rpc_timeout); $this->channels[$channel_id] = $ch; return $ch; } /** * Requests a connection close * * @param int $reply_code * @param string $reply_text * @param array $method_sig * @return mixed|null */ public function close($reply_code = 0, $reply_text = '', $method_sig = array(0, 0)) { $result = null; $this->io->disableHeartbeat(); if (empty($this->protocolWriter) || !$this->isConnected()) { return $result; } try { $this->closeChannels(); list($class_id, $method_id, $args) = $this->protocolWriter->connectionClose( $reply_code, $reply_text, $method_sig[0], $method_sig[1] ); $this->send_method_frame(array($class_id, $method_id), $args); $result = $this->wait( array($this->waitHelper->get_wait('connection.close_ok')), false, $this->connection_timeout ); } catch (\Exception $exception) { $this->do_close(); throw $exception; } $this->setIsConnected(false); return $result; } /** * @param AMQPReader $reader * @throws AMQPConnectionClosedException */ protected function connection_close(AMQPReader $reader) { $code = (int)$reader->read_short(); $reason = $reader->read_shortstr(); $class = $reader->read_short(); $method = $reader->read_short(); $reason .= sprintf('(%s, %s)', $class, $method); $this->x_close_ok(); throw new AMQPConnectionClosedException($reason, $code); } /** * Confirms a connection close */ protected function x_close_ok() { $this->send_method_frame( explode(',', $this->waitHelper->get_wait('connection.close_ok')) ); $this->do_close(); } /** * Confirm a connection close * * @param AMQPReader $args */ protected function connection_close_ok($args) { $this->do_close(); } /** * @param string $virtual_host * @param string $capabilities * @param bool $insist * @return mixed */ protected function x_open($virtual_host, $capabilities = '', $insist = false) { $args = new AMQPWriter(); $args->write_shortstr($virtual_host); $args->write_shortstr($capabilities); $args->write_bits(array($insist)); $this->send_method_frame(array(10, 40), $args); $wait = array( $this->waitHelper->get_wait('connection.open_ok') ); if ($this->protocolVersion === Wire\Constants080::VERSION) { $wait[] = $this->waitHelper->get_wait('connection.redirect'); } return $this->wait($wait); } /** * Signals that the connection is ready * * @param AMQPReader $args */ protected function connection_open_ok($args) { $this->known_hosts = $args->read_shortstr(); $this->debug->debug_msg('Open OK! known_hosts: ' . $this->known_hosts); } /** * Asks the client to use a different server * * @param AMQPReader $args * @return string */ protected function connection_redirect($args) { $host = $args->read_shortstr(); $this->known_hosts = $args->read_shortstr(); $this->debug->debug_msg(sprintf( 'Redirected to [%s], known_hosts [%s]', $host, $this->known_hosts )); return $host; } /** * Security mechanism challenge * * @param AMQPReader $args */ protected function connection_secure($args) { $challenge = $args->read_longstr(); } /** * Security mechanism response * * @param string $response */ protected function x_secure_ok($response) { $args = new AMQPWriter(); $args->write_longstr($response); $this->send_method_frame(array(10, 21), $args); } /** * Starts connection negotiation * * @param AMQPReader $args */ protected function connection_start($args) { $this->version_major = $args->read_octet(); $this->version_minor = $args->read_octet(); $this->server_properties = $args->read_table(); $this->mechanisms = explode(' ', $args->read_longstr()); $this->locales = explode(' ', $args->read_longstr()); $this->debug->debug_connection_start( $this->version_major, $this->version_minor, $this->server_properties, $this->mechanisms, $this->locales ); } /** * @param AMQPTable|array $clientProperties * @param string $mechanism * @param string $response * @param string $locale */ protected function x_start_ok($clientProperties, $mechanism, $response, $locale) { $args = new AMQPWriter(); $args->write_table($clientProperties); $args->write_shortstr($mechanism); $args->write_longstr($response); $args->write_shortstr($locale); $this->send_method_frame(array(10, 11), $args); } /** * Proposes connection tuning parameters * * @param AMQPReader $args */ protected function connection_tune($args) { $v = $args->read_short(); if ($v) { $this->channel_max = $v; } $v = $args->read_long(); if ($v) { $this->frame_max = $v; } // use server proposed value if not set if ($this->heartbeat === null) { $this->heartbeat = $args->read_short(); } $this->x_tune_ok($this->channel_max, $this->frame_max, $this->heartbeat); } /** * Negotiates connection tuning parameters * * @param int $channel_max * @param int $frame_max * @param int $heartbeat */ protected function x_tune_ok($channel_max, $frame_max, $heartbeat) { $args = new AMQPWriter(); $args->write_short($channel_max); $args->write_long($frame_max); $args->write_short($heartbeat); $this->send_method_frame(array(10, 31), $args); $this->wait_tune_ok = false; } /** * @return resource * @deprecated No direct access to communication socket should be available. */ public function getSocket() { return $this->io->getSocket(); } /** * @return \PhpAmqpLib\Wire\IO\AbstractIO * @deprecated */ public function getIO() { return $this->io; } /** * Check connection heartbeat if enabled. * @throws AMQPHeartbeatMissedException If too much time passed since last connection activity. * @throws AMQPConnectionClosedException If connection was closed due to network issues or timeouts. * @throws AMQPSocketException If connection was already closed. * @throws AMQPTimeoutException If heartbeat write takes too much time. * @throws AMQPIOException If other connection problems occurred. */ public function checkHeartBeat() { $this->io->check_heartbeat(); } /** * Handles connection blocked notifications * * @param AMQPReader $args */ protected function connection_blocked(AMQPReader $args) { // Call the block handler and pass in the reason $this->dispatch_to_handler($this->connection_block_handler, array($args->read_shortstr())); } /** * Handles connection unblocked notifications * * @param AMQPReader $args */ protected function connection_unblocked(AMQPReader $args) { // No args to an unblock event $this->dispatch_to_handler($this->connection_unblock_handler, array()); } /** * Sets a handler which is called whenever a connection.block is sent from the server * * @param callable $callback */ public function set_connection_block_handler($callback) { $this->connection_block_handler = $callback; } /** * Sets a handler which is called whenever a connection.block is sent from the server * * @param callable $callback */ public function set_connection_unblock_handler($callback) { $this->connection_unblock_handler = $callback; } /** * Gets the connection status * * @return bool */ public function isConnected() { return $this->is_connected; } /** * Set the connection status * * @param bool $is_connected */ protected function setIsConnected($is_connected) { $this->is_connected = (bool) $is_connected; } /** * Closes all available channels */ protected function closeChannels() { foreach ($this->channels as $key => $channel) { // channels[0] is this connection object, so don't close it yet if ($key === 0) { continue; } try { $channel->close(); } catch (\Exception $e) { /* Ignore closing errors */ } } } /** * Should the connection be attempted during construction? * * @return bool */ public function connectOnConstruct() { return true; } /** * @return array */ public function getServerProperties() { return $this->server_properties; } /** * Get the library properties for populating the client protocol information * * @return array */ public function getLibraryProperties() { return self::$LIBRARY_PROPERTIES; } public static function create_connection($hosts, $options = array()){ $latest_exception = null; foreach ($hosts as $hostdef) { AbstractConnection::validate_host($hostdef); $host = $hostdef['host']; $port = $hostdef['port']; $user = $hostdef['user']; $password = $hostdef['password']; $vhost = isset($hostdef['vhost']) ? $hostdef['vhost'] : "/"; try { $conn = static::try_create_connection($host, $port, $user, $password, $vhost, $options); return $conn; } catch (\Exception $e) { $latest_exception = $e; } } throw $latest_exception; } public static function validate_host($host) { if(!isset($host['host'])){ throw new \InvalidArgumentException("'host' key is required."); } if(!isset($host['port'])){ throw new \InvalidArgumentException("'port' key is required."); } if(!isset($host['user'])){ throw new \InvalidArgumentException("'user' key is required."); } if(!isset($host['password'])){ throw new \InvalidArgumentException("'password' key is required."); } } } php-amqplib-2.11.0/PhpAmqpLib/Exception/000077500000000000000000000000001356514014400177435ustar00rootroot00000000000000php-amqplib-2.11.0/PhpAmqpLib/Exception/AMQPBasicCancelException.php000066400000000000000000000010601356514014400251360ustar00rootroot00000000000000consumerTag = $consumerTag; } /** * @return string */ public function getConsumerTag() { return $this->consumerTag; } } php-amqplib-2.11.0/PhpAmqpLib/Exception/AMQPChannelClosedException.php000066400000000000000000000001511356514014400255110ustar00rootroot00000000000000amqp_reply_code = $reply_code; // redundant, but kept for BC $this->amqp_reply_text = $reply_text; // redundant, but kept for BC $this->amqp_method_sig = $method_sig; $this->args = array($reply_code, $reply_text, $method_sig, ''); } } php-amqplib-2.11.0/PhpAmqpLib/Exception/AMQPExceptionInterface.php000066400000000000000000000001141356514014400247060ustar00rootroot00000000000000amqp_reply_code = $reply_code; // redundant, but kept for BC $this->amqp_reply_text = $reply_text; // redundant, but kept for BC $this->amqp_method_sig = $method_sig; $this->args = array($reply_code, $reply_text, $method_sig); } } php-amqplib-2.11.0/PhpAmqpLib/Exception/AMQPRuntimeException.php000066400000000000000000000002021356514014400244270ustar00rootroot00000000000000timeout = $timeout; } /** * @param int|float|null $timeout * @param int $code * @return self */ public static function writeTimeout($timeout, $code = 0) { return new self('Error sending data. Connection timed out.', $timeout, $code); } /** * @return int|float|null */ public function getTimeout() { return $this->timeout; } } php-amqplib-2.11.0/PhpAmqpLib/Exchange/000077500000000000000000000000001356514014400175275ustar00rootroot00000000000000php-amqplib-2.11.0/PhpAmqpLib/Exchange/AMQPExchangeType.php000066400000000000000000000002731356514014400233050ustar00rootroot00000000000000debug = defined('AMQP_DEBUG') ? AMQP_DEBUG : false; $this->debug_output = defined('AMQP_DEBUG_OUTPUT') ? AMQP_DEBUG_OUTPUT : STDOUT; $this->constants = $constants; } /** * @param string $msg */ public function debug_msg($msg) { if ($this->debug) { $this->print_msg($msg); } } /** * @param array $allowed_methods */ public function debug_allowed_methods($allowed_methods) { if ($allowed_methods) { $msg = 'waiting for ' . implode(', ', $allowed_methods); } else { $msg = 'waiting for any method'; } $this->debug_msg($msg); } /** * @param string $method_sig */ public function debug_method_signature1($method_sig) { $this->debug_method_signature('< %s:', $method_sig); } /** * @param string $msg * @param string $method_sig */ public function debug_method_signature($msg, $method_sig) { if ($this->debug) { $constants = $this->constants; $methods = $constants::$GLOBAL_METHOD_NAMES; $key = MiscHelper::methodSig($method_sig); $this->debug_msg(sprintf($msg . ': %s', $key, $methods[$key])); } } /** * @param string $data */ public function debug_hexdump($data) { if ($this->debug) { $this->debug_msg(sprintf( '< [hex]: %s%s', PHP_EOL, MiscHelper::hexdump($data, $htmloutput = false, $uppercase = true, $return = true) )); } } /** * @param int $version_major * @param int $version_minor * @param array $server_properties * @param array $mechanisms * @param array $locales */ public function debug_connection_start($version_major, $version_minor, $server_properties, $mechanisms, $locales) { if ($this->debug) { $this->debug_msg(sprintf( 'Start from server, version: %d.%d, properties: %s, mechanisms: %s, locales: %s', $version_major, $version_minor, MiscHelper::dump_table($server_properties), implode(', ', $mechanisms), implode(', ', $locales) )); } } /** * @param string $s */ protected function print_msg($s) { fwrite($this->debug_output, $s . PHP_EOL); } } php-amqplib-2.11.0/PhpAmqpLib/Helper/MiscHelper.php000066400000000000000000000100031356514014400217620ustar00rootroot00000000000000 * @author Peter Waller * @link http://aidanlister.com/repos/v/function.hexdump.php * * @param string $data The string to be dumped * @param bool $htmloutput Set to false for non-HTML output * @param bool $uppercase Set to true for uppercase hex * @param bool $return Set to true to return the dump * @return string|null */ public static function hexdump($data, $htmloutput = true, $uppercase = false, $return = false) { // Init $hexi = ''; $ascii = ''; $dump = $htmloutput ? '
' : '';
        $offset = 0;
        $len = mb_strlen($data, 'ASCII');

        // Upper or lower case hexidecimal
        $hexFormat = $uppercase ? 'X' : 'x';

        // Iterate string
        for ($i = $j = 0; $i < $len; $i++) {
            // Convert to hexidecimal
            // We must use concatenation here because the $hexFormat value
            // is needed for sprintf() to parse the format
            $hexi .= sprintf('%02' .  $hexFormat . ' ', ord($data[$i]));

            // Replace non-viewable bytes with '.'
            if (ord($data[$i]) >= 32) {
                $ascii .= $htmloutput ? htmlentities($data[$i]) : $data[$i];
            } else {
                $ascii .= '.';
            }

            // Add extra column spacing
            if ($j === 7) {
                $hexi .= ' ';
                $ascii .= ' ';
            }

            // Add row
            if (++$j === 16 || $i === $len - 1) {
                // Join the hexi / ascii output
                // We must use concatenation here because the $hexFormat value
                // is needed for sprintf() to parse the format
                $dump .= sprintf('%04' . $hexFormat . '  %-49s  %s', $offset, $hexi, $ascii);

                // Reset vars
                $hexi = $ascii = '';
                $offset += 16;
                $j = 0;

                // Add newline
                if ($i !== $len - 1) {
                    $dump .= PHP_EOL;
                }
            }
        }

        // Finish dump
        $dump .= $htmloutput ? '
' : ''; $dump .= PHP_EOL; if ($return) { return $dump; } echo $dump; } /** * @param array $table * @return string */ public static function dump_table($table) { $tokens = array(); foreach ($table as $name => $value) { switch ($value[0]) { case 'D': $val = $value[1]->n . 'E' . $value[1]->e; break; case 'F': $val = '(' . self::dump_table($value[1]) . ')'; break; case 'T': $val = date('Y-m-d H:i:s', $value[1]); break; default: $val = $value[1]; } $tokens[] = $name . '=' . $val; } return implode(', ', $tokens); } } php-amqplib-2.11.0/PhpAmqpLib/Helper/Protocol/000077500000000000000000000000001356514014400210255ustar00rootroot00000000000000php-amqplib-2.11.0/PhpAmqpLib/Helper/Protocol/MethodMap080.php000066400000000000000000000076141356514014400236540ustar00rootroot00000000000000 'connection_start', '10,11' => 'connection_start_ok', '10,20' => 'connection_secure', '10,21' => 'connection_secure_ok', '10,30' => 'connection_tune', '10,31' => 'connection_tune_ok', '10,40' => 'connection_open', '10,41' => 'connection_open_ok', '10,50' => 'connection_redirect', '10,60' => 'connection_close', '10,61' => 'connection_close_ok', '20,10' => 'channel_open', '20,11' => 'channel_open_ok', '20,20' => 'channel_flow', '20,21' => 'channel_flow_ok', '20,30' => 'channel_alert', '20,40' => 'channel_close', '20,41' => 'channel_close_ok', '30,10' => 'access_request', '30,11' => 'access_request_ok', '40,10' => 'exchange_declare', '40,11' => 'exchange_declare_ok', '40,20' => 'exchange_delete', '40,21' => 'exchange_delete_ok', '50,10' => 'queue_declare', '50,11' => 'queue_declare_ok', '50,20' => 'queue_bind', '50,21' => 'queue_bind_ok', '50,30' => 'queue_purge', '50,31' => 'queue_purge_ok', '50,40' => 'queue_delete', '50,41' => 'queue_delete_ok', '50,50' => 'queue_unbind', '50,51' => 'queue_unbind_ok', '60,10' => 'basic_qos', '60,11' => 'basic_qos_ok', '60,20' => 'basic_consume', '60,21' => 'basic_consume_ok', '60,30' => 'basic_cancel', '60,31' => 'basic_cancel_ok', '60,40' => 'basic_publish', '60,50' => 'basic_return', '60,60' => 'basic_deliver', '60,70' => 'basic_get', '60,71' => 'basic_get_ok', '60,72' => 'basic_get_empty', '60,80' => 'basic_ack', '60,90' => 'basic_reject', '60,100' => 'basic_recover_async', '60,110' => 'basic_recover', '60,111' => 'basic_recover_ok', '70,10' => 'file_qos', '70,11' => 'file_qos_ok', '70,20' => 'file_consume', '70,21' => 'file_consume_ok', '70,30' => 'file_cancel', '70,31' => 'file_cancel_ok', '70,40' => 'file_open', '70,41' => 'file_open_ok', '70,50' => 'file_stage', '70,60' => 'file_publish', '70,70' => 'file_return', '70,80' => 'file_deliver', '70,90' => 'file_ack', '70,100' => 'file_reject', '80,10' => 'stream_qos', '80,11' => 'stream_qos_ok', '80,20' => 'stream_consume', '80,21' => 'stream_consume_ok', '80,30' => 'stream_cancel', '80,31' => 'stream_cancel_ok', '80,40' => 'stream_publish', '80,50' => 'stream_return', '80,60' => 'stream_deliver', '90,10' => 'tx_select', '90,11' => 'tx_select_ok', '90,20' => 'tx_commit', '90,21' => 'tx_commit_ok', '90,30' => 'tx_rollback', '90,31' => 'tx_rollback_ok', '100,10' => 'dtx_select', '100,11' => 'dtx_select_ok', '100,20' => 'dtx_start', '100,21' => 'dtx_start_ok', '110,10' => 'tunnel_request', '120,10' => 'test_integer', '120,11' => 'test_integer_ok', '120,20' => 'test_string', '120,21' => 'test_string_ok', '120,30' => 'test_table', '120,31' => 'test_table_ok', '120,40' => 'test_content', '120,41' => 'test_content_ok', ); /** * @var string $method_sig * @return string */ public function get_method($method_sig) { return $this->method_map[$method_sig]; } /** * @var string $method_sig * @return bool */ public function valid_method($method_sig) { return array_key_exists($method_sig, $this->method_map); } } php-amqplib-2.11.0/PhpAmqpLib/Helper/Protocol/MethodMap091.php000066400000000000000000000056751356514014400236630ustar00rootroot00000000000000 'connection_start', '10,11' => 'connection_start_ok', '10,20' => 'connection_secure', '10,21' => 'connection_secure_ok', '10,30' => 'connection_tune', '10,31' => 'connection_tune_ok', '10,40' => 'connection_open', '10,41' => 'connection_open_ok', '10,50' => 'connection_close', '10,51' => 'connection_close_ok', '10,60' => 'connection_blocked', '10,61' => 'connection_unblocked', '20,10' => 'channel_open', '20,11' => 'channel_open_ok', '20,20' => 'channel_flow', '20,21' => 'channel_flow_ok', '20,40' => 'channel_close', '20,41' => 'channel_close_ok', '30,10' => 'access_request', '30,11' => 'access_request_ok', '40,10' => 'exchange_declare', '40,11' => 'exchange_declare_ok', '40,20' => 'exchange_delete', '40,21' => 'exchange_delete_ok', '40,30' => 'exchange_bind', '40,31' => 'exchange_bind_ok', '40,40' => 'exchange_unbind', '40,51' => 'exchange_unbind_ok', '50,10' => 'queue_declare', '50,11' => 'queue_declare_ok', '50,20' => 'queue_bind', '50,21' => 'queue_bind_ok', '50,30' => 'queue_purge', '50,31' => 'queue_purge_ok', '50,40' => 'queue_delete', '50,41' => 'queue_delete_ok', '50,50' => 'queue_unbind', '50,51' => 'queue_unbind_ok', '60,10' => 'basic_qos', '60,11' => 'basic_qos_ok', '60,20' => 'basic_consume', '60,21' => 'basic_consume_ok', '60,30' => 'basic_cancel_from_server', '60,31' => 'basic_cancel_ok', '60,40' => 'basic_publish', '60,50' => 'basic_return', '60,60' => 'basic_deliver', '60,70' => 'basic_get', '60,71' => 'basic_get_ok', '60,72' => 'basic_get_empty', '60,80' => 'basic_ack_from_server', '60,90' => 'basic_reject', '60,100' => 'basic_recover_async', '60,110' => 'basic_recover', '60,111' => 'basic_recover_ok', '60,120' => 'basic_nack_from_server', '90,10' => 'tx_select', '90,11' => 'tx_select_ok', '90,20' => 'tx_commit', '90,21' => 'tx_commit_ok', '90,30' => 'tx_rollback', '90,31' => 'tx_rollback_ok', '85,10' => 'confirm_select', '85,11' => 'confirm_select_ok', ); /** * @var string $method_sig * @return string */ public function get_method($method_sig) { return $this->method_map[$method_sig]; } /** * @var string $method_sig * @return bool */ public function valid_method($method_sig) { return array_key_exists($method_sig, $this->method_map); } } php-amqplib-2.11.0/PhpAmqpLib/Helper/Protocol/Protocol080.php000066400000000000000000001016531356514014400235750ustar00rootroot00000000000000write_octet($version_major); $writer->write_octet($version_minor); $writer->write_table(empty($server_properties) ? array() : $server_properties); $writer->write_longstr($mechanisms); $writer->write_longstr($locales); return array(10, 10, $writer); } /** * @param AMQPReader $reader * @return array */ public static function connectionStartOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_table(); $response[] = $reader->read_shortstr(); $response[] = $reader->read_longstr(); $response[] = $reader->read_shortstr(); return $response; } /** * @param string $challenge * @return array */ public function connectionSecure($challenge) { $writer = new AMQPWriter(); $writer->write_longstr($challenge); return array(10, 20, $writer); } /** * @param AMQPReader $reader * @return array */ public static function connectionSecureOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_longstr(); return $response; } /** * @param int $channel_max * @param int $frame_max * @param int $heartbeat * @return array */ public function connectionTune($channel_max = 0, $frame_max = 0, $heartbeat = 0) { $writer = new AMQPWriter(); $writer->write_short($channel_max); $writer->write_long($frame_max); $writer->write_short($heartbeat); return array(10, 30, $writer); } /** * @param AMQPReader $reader * @return array */ public static function connectionTuneOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_short(); $response[] = $reader->read_long(); $response[] = $reader->read_short(); return $response; } /** * @param string $virtual_host * @param string $capabilities * @param bool $insist * @return array */ public function connectionOpen($virtual_host = '/', $capabilities = '', $insist = false) { $writer = new AMQPWriter(); $writer->write_shortstr($virtual_host); $writer->write_shortstr($capabilities); $writer->write_bits(array($insist)); return array(10, 40, $writer); } /** * @param AMQPReader $reader * @return array */ public static function connectionOpenOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_shortstr(); return $response; } /** * @param string $host * @param string $known_hosts * @return array */ public function connectionRedirect($host, $known_hosts = '') { $writer = new AMQPWriter(); $writer->write_shortstr($host); $writer->write_shortstr($known_hosts); return array(10, 50, $writer); } /** * @param int $reply_code * @param string $reply_text * @param int $class_id * @param int $method_id * @return array */ public function connectionClose($reply_code, $reply_text = '', $class_id, $method_id) { $writer = new AMQPWriter(); $writer->write_short($reply_code); $writer->write_shortstr($reply_text); $writer->write_short($class_id); $writer->write_short($method_id); return array(10, 60, $writer); } /** * @param AMQPReader $reader * @return array */ public static function connectionCloseOk(AMQPReader $reader) { $response = array(); return $response; } /** * @param string $out_of_band * @return array */ public function channelOpen($out_of_band = '') { $writer = new AMQPWriter(); $writer->write_shortstr($out_of_band); return array(20, 10, $writer); } /** * @param AMQPReader $reader * @return array */ public static function channelOpenOk(AMQPReader $reader) { $response = array(); return $response; } /** * @param bool $active * @return array */ public function channelFlow($active) { $writer = new AMQPWriter(); $writer->write_bits(array($active)); return array(20, 20, $writer); } /** * @param AMQPReader $reader * @return array */ public static function channelFlowOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_bit(); return $response; } /** * @param int $reply_code * @param string $reply_text * @param array $details * @return array */ public function channelAlert($reply_code, $reply_text = '', $details = array()) { $writer = new AMQPWriter(); $writer->write_short($reply_code); $writer->write_shortstr($reply_text); $writer->write_table(empty($details) ? array() : $details); return array(20, 30, $writer); } /** * @param int $reply_code * @param string $reply_text * @param int $class_id * @param int $method_id * @return array */ public function channelClose($reply_code, $reply_text = '', $class_id, $method_id) { $writer = new AMQPWriter(); $writer->write_short($reply_code); $writer->write_shortstr($reply_text); $writer->write_short($class_id); $writer->write_short($method_id); return array(20, 40, $writer); } /** * @param AMQPReader $reader * @return array */ public static function channelCloseOk(AMQPReader $reader) { $response = array(); return $response; } /** * @param string $realm * @param bool $exclusive * @param bool $passive * @param bool $active * @param bool $write * @param bool $read * @return array */ public function accessRequest($realm = '/data', $exclusive = false, $passive = true, $active = true, $write = true, $read = true) { $writer = new AMQPWriter(); $writer->write_shortstr($realm); $writer->write_bits(array($exclusive, $passive, $active, $write, $read)); return array(30, 10, $writer); } /** * @param AMQPReader $reader * @return array */ public static function accessRequestOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_short(); return $response; } /** * @param int $ticket * @param string $exchange * @param string $type * @param bool $passive * @param bool $durable * @param bool $auto_delete * @param bool $internal * @param bool $nowait * @param array $arguments * @return array */ public function exchangeDeclare($ticket = 1, $exchange, $type = 'direct', $passive = false, $durable = false, $auto_delete = false, $internal = false, $nowait = false, $arguments = array()) { $writer = new AMQPWriter(); $writer->write_short($ticket); $writer->write_shortstr($exchange); $writer->write_shortstr($type); $writer->write_bits(array($passive, $durable, $auto_delete, $internal, $nowait)); $writer->write_table(empty($arguments) ? array() : $arguments); return array(40, 10, $writer); } /** * @param AMQPReader $reader * @return array */ public static function exchangeDeclareOk(AMQPReader $reader) { $response = array(); return $response; } /** * @param int $ticket * @param string $exchange * @param bool $if_unused * @param bool $nowait * @return array */ public function exchangeDelete($ticket = 1, $exchange, $if_unused = false, $nowait = false) { $writer = new AMQPWriter(); $writer->write_short($ticket); $writer->write_shortstr($exchange); $writer->write_bits(array($if_unused, $nowait)); return array(40, 20, $writer); } /** * @param AMQPReader $reader * @return array */ public static function exchangeDeleteOk(AMQPReader $reader) { $response = array(); return $response; } /** * @param int $ticket * @param string $queue * @param bool $passive * @param bool $durable * @param bool $exclusive * @param bool $auto_delete * @param bool $nowait * @param array $arguments * @return array */ public function queueDeclare($ticket = 1, $queue = '', $passive = false, $durable = false, $exclusive = false, $auto_delete = false, $nowait = false, $arguments = array()) { $writer = new AMQPWriter(); $writer->write_short($ticket); $writer->write_shortstr($queue); $writer->write_bits(array($passive, $durable, $exclusive, $auto_delete, $nowait)); $writer->write_table(empty($arguments) ? array() : $arguments); return array(50, 10, $writer); } /** * @param AMQPReader $reader * @return array */ public static function queueDeclareOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_shortstr(); $response[] = $reader->read_long(); $response[] = $reader->read_long(); return $response; } /** * @param int $ticket * @param string $queue * @param string $exchange * @param string $routing_key * @param bool $nowait * @param array $arguments * @return array */ public function queueBind($ticket = 1, $queue = '', $exchange, $routing_key = '', $nowait = false, $arguments = array()) { $writer = new AMQPWriter(); $writer->write_short($ticket); $writer->write_shortstr($queue); $writer->write_shortstr($exchange); $writer->write_shortstr($routing_key); $writer->write_bits(array($nowait)); $writer->write_table(empty($arguments) ? array() : $arguments); return array(50, 20, $writer); } /** * @param AMQPReader $reader * @return array */ public static function queueBindOk(AMQPReader $reader) { $response = array(); return $response; } /** * @param int $ticket * @param string $queue * @param bool $nowait * @return array */ public function queuePurge($ticket = 1, $queue = '', $nowait = false) { $writer = new AMQPWriter(); $writer->write_short($ticket); $writer->write_shortstr($queue); $writer->write_bits(array($nowait)); return array(50, 30, $writer); } /** * @param AMQPReader $reader * @return array */ public static function queuePurgeOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_long(); return $response; } /** * @param int $ticket * @param string $queue * @param bool $if_unused * @param bool $if_empty * @param bool $nowait * @return array */ public function queueDelete($ticket = 1, $queue = '', $if_unused = false, $if_empty = false, $nowait = false) { $writer = new AMQPWriter(); $writer->write_short($ticket); $writer->write_shortstr($queue); $writer->write_bits(array($if_unused, $if_empty, $nowait)); return array(50, 40, $writer); } /** * @param AMQPReader $reader * @return array */ public static function queueDeleteOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_long(); return $response; } /** * @param int $ticket * @param string $queue * @param string $exchange * @param string $routing_key * @param array $arguments * @return array */ public function queueUnbind($ticket = 1, $queue = '', $exchange, $routing_key = '', $arguments = array()) { $writer = new AMQPWriter(); $writer->write_short($ticket); $writer->write_shortstr($queue); $writer->write_shortstr($exchange); $writer->write_shortstr($routing_key); $writer->write_table(empty($arguments) ? array() : $arguments); return array(50, 50, $writer); } /** * @param AMQPReader $reader * @return array */ public static function queueUnbindOk(AMQPReader $reader) { $response = array(); return $response; } /** * @param int $prefetch_size * @param int $prefetch_count * @param bool $global * @return array */ public function basicQos($prefetch_size = 0, $prefetch_count = 0, $global = false) { $writer = new AMQPWriter(); $writer->write_long($prefetch_size); $writer->write_short($prefetch_count); $writer->write_bits(array($global)); return array(60, 10, $writer); } /** * @param AMQPReader $reader * @return array */ public static function basicQosOk(AMQPReader $reader) { $response = array(); return $response; } /** * @param int $ticket * @param string $queue * @param string $consumer_tag * @param bool $no_local * @param bool $no_ack * @param bool $exclusive * @param bool $nowait * @return array */ public function basicConsume($ticket = 1, $queue = '', $consumer_tag = '', $no_local = false, $no_ack = false, $exclusive = false, $nowait = false) { $writer = new AMQPWriter(); $writer->write_short($ticket); $writer->write_shortstr($queue); $writer->write_shortstr($consumer_tag); $writer->write_bits(array($no_local, $no_ack, $exclusive, $nowait)); return array(60, 20, $writer); } /** * @param AMQPReader $reader * @return array */ public static function basicConsumeOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_shortstr(); return $response; } /** * @param string $consumer_tag * @param bool $nowait * @return array */ public function basicCancel($consumer_tag, $nowait = false) { $writer = new AMQPWriter(); $writer->write_shortstr($consumer_tag); $writer->write_bits(array($nowait)); return array(60, 30, $writer); } /** * @param AMQPReader $reader * @return array */ public static function basicCancelOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_shortstr(); return $response; } /** * @param int $ticket * @param string $exchange * @param string $routing_key * @param bool $mandatory * @param bool $immediate * @return array */ public function basicPublish($ticket = 1, $exchange = '', $routing_key = '', $mandatory = false, $immediate = false) { $writer = new AMQPWriter(); $writer->write_short($ticket); $writer->write_shortstr($exchange); $writer->write_shortstr($routing_key); $writer->write_bits(array($mandatory, $immediate)); return array(60, 40, $writer); } /** * @param int $reply_code * @param string $reply_text * @param string $exchange * @param string $routing_key * @return array */ public function basicReturn($reply_code, $reply_text = '', $exchange, $routing_key) { $writer = new AMQPWriter(); $writer->write_short($reply_code); $writer->write_shortstr($reply_text); $writer->write_shortstr($exchange); $writer->write_shortstr($routing_key); return array(60, 50, $writer); } /** * @param string $consumer_tag * @param int $delivery_tag * @param bool $redelivered * @param string $exchange * @param string $routing_key * @return array */ public function basicDeliver($consumer_tag, $delivery_tag, $redelivered = false, $exchange, $routing_key) { $writer = new AMQPWriter(); $writer->write_shortstr($consumer_tag); $writer->write_longlong($delivery_tag); $writer->write_bits(array($redelivered)); $writer->write_shortstr($exchange); $writer->write_shortstr($routing_key); return array(60, 60, $writer); } /** * @param int $ticket * @param string $queue * @param bool $no_ack * @return array */ public function basicGet($ticket = 1, $queue = '', $no_ack = false) { $writer = new AMQPWriter(); $writer->write_short($ticket); $writer->write_shortstr($queue); $writer->write_bits(array($no_ack)); return array(60, 70, $writer); } /** * @param AMQPReader $reader * @return array */ public static function basicGetOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_longlong(); $response[] = $reader->read_bit(); $response[] = $reader->read_shortstr(); $response[] = $reader->read_shortstr(); $response[] = $reader->read_long(); return $response; } /** * @param AMQPReader $reader * @return array */ public static function basicGetEmpty(AMQPReader $reader) { $response = array(); $response[] = $reader->read_shortstr(); return $response; } /** * @param int $delivery_tag * @param bool $multiple * @return array */ public function basicAck($delivery_tag = 0, $multiple = false) { $writer = new AMQPWriter(); $writer->write_longlong($delivery_tag); $writer->write_bits(array($multiple)); return array(60, 80, $writer); } /** * @param int $delivery_tag * @param bool $requeue * @return array */ public function basicReject($delivery_tag, $requeue = true) { $writer = new AMQPWriter(); $writer->write_longlong($delivery_tag); $writer->write_bits(array($requeue)); return array(60, 90, $writer); } /** * @param bool $requeue * @return array */ public function basicRecoverAsync($requeue = false) { $writer = new AMQPWriter(); $writer->write_bits(array($requeue)); return array(60, 100, $writer); } /** * @param bool $requeue * @return array */ public function basicRecover($requeue = false) { $writer = new AMQPWriter(); $writer->write_bits(array($requeue)); return array(60, 110, $writer); } /** * @param AMQPReader $reader * @return array */ public static function basicRecoverOk(AMQPReader $reader) { $response = array(); return $response; } /** * @param int $prefetch_size * @param int $prefetch_count * @param bool $global * @return array */ public function fileQos($prefetch_size = 0, $prefetch_count = 0, $global = false) { $writer = new AMQPWriter(); $writer->write_long($prefetch_size); $writer->write_short($prefetch_count); $writer->write_bits(array($global)); return array(70, 10, $writer); } /** * @param AMQPReader $reader * @return array */ public static function fileQosOk(AMQPReader $reader) { $response = array(); return $response; } /** * @param int $ticket * @param string $queue * @param string $consumer_tag * @param bool $no_local * @param bool $no_ack * @param bool $exclusive * @param bool $nowait * @return array */ public function fileConsume($ticket = 1, $queue = '', $consumer_tag = '', $no_local = false, $no_ack = false, $exclusive = false, $nowait = false) { $writer = new AMQPWriter(); $writer->write_short($ticket); $writer->write_shortstr($queue); $writer->write_shortstr($consumer_tag); $writer->write_bits(array($no_local, $no_ack, $exclusive, $nowait)); return array(70, 20, $writer); } /** * @param AMQPReader $reader * @return array */ public static function fileConsumeOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_shortstr(); return $response; } /** * @param string $consumer_tag * @param bool $nowait * @return array */ public function fileCancel($consumer_tag, $nowait = false) { $writer = new AMQPWriter(); $writer->write_shortstr($consumer_tag); $writer->write_bits(array($nowait)); return array(70, 30, $writer); } /** * @param AMQPReader $reader * @return array */ public static function fileCancelOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_shortstr(); return $response; } /** * @param string $identifier * @param int $content_size * @return array */ public function fileOpen($identifier, $content_size) { $writer = new AMQPWriter(); $writer->write_shortstr($identifier); $writer->write_longlong($content_size); return array(70, 40, $writer); } /** * @param AMQPReader $reader * @return array */ public static function fileOpenOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_longlong(); return $response; } /** * @return array */ public function fileStage() { $writer = new AMQPWriter(); return array(70, 50, $writer); } /** * @param int $ticket * @param string $exchange * @param string $routing_key * @param bool $mandatory * @param bool $immediate * @param string $identifier * @return array */ public function filePublish($ticket = 1, $exchange = '', $routing_key = '', $mandatory = false, $immediate = false, $identifier) { $writer = new AMQPWriter(); $writer->write_short($ticket); $writer->write_shortstr($exchange); $writer->write_shortstr($routing_key); $writer->write_bits(array($mandatory, $immediate)); $writer->write_shortstr($identifier); return array(70, 60, $writer); } /** * @param int $reply_code * @param string $reply_text * @param string $exchange * @param string $routing_key * @return array */ public function fileReturn($reply_code = 200, $reply_text = '', $exchange, $routing_key) { $writer = new AMQPWriter(); $writer->write_short($reply_code); $writer->write_shortstr($reply_text); $writer->write_shortstr($exchange); $writer->write_shortstr($routing_key); return array(70, 70, $writer); } /** * @param string $consumer_tag * @param int $delivery_tag * @param bool $redelivered * @param string $exchange * @param string $routing_key * @param string $identifier * @return array */ public function fileDeliver($consumer_tag, $delivery_tag, $redelivered = false, $exchange, $routing_key, $identifier) { $writer = new AMQPWriter(); $writer->write_shortstr($consumer_tag); $writer->write_longlong($delivery_tag); $writer->write_bits(array($redelivered)); $writer->write_shortstr($exchange); $writer->write_shortstr($routing_key); $writer->write_shortstr($identifier); return array(70, 80, $writer); } /** * @param int $delivery_tag * @param bool $multiple * @return array */ public function fileAck($delivery_tag = 0, $multiple = false) { $writer = new AMQPWriter(); $writer->write_longlong($delivery_tag); $writer->write_bits(array($multiple)); return array(70, 90, $writer); } /** * @param int $delivery_tag * @param bool $requeue * @return array */ public function fileReject($delivery_tag, $requeue = true) { $writer = new AMQPWriter(); $writer->write_longlong($delivery_tag); $writer->write_bits(array($requeue)); return array(70, 100, $writer); } /** * @param int $prefetch_size * @param int $prefetch_count * @param int $consume_rate * @param bool $global * @return array */ public function streamQos($prefetch_size = 0, $prefetch_count = 0, $consume_rate = 0, $global = false) { $writer = new AMQPWriter(); $writer->write_long($prefetch_size); $writer->write_short($prefetch_count); $writer->write_long($consume_rate); $writer->write_bits(array($global)); return array(80, 10, $writer); } /** * @param AMQPReader $reader * @return array */ public static function streamQosOk(AMQPReader $reader) { $response = array(); return $response; } /** * @param int $ticket * @param string $queue * @param string $consumer_tag * @param bool $no_local * @param bool $exclusive * @param bool $nowait * @return array */ public function streamConsume($ticket = 1, $queue = '', $consumer_tag = '', $no_local = false, $exclusive = false, $nowait = false) { $writer = new AMQPWriter(); $writer->write_short($ticket); $writer->write_shortstr($queue); $writer->write_shortstr($consumer_tag); $writer->write_bits(array($no_local, $exclusive, $nowait)); return array(80, 20, $writer); } /** * @param AMQPReader $reader * @return array */ public static function streamConsumeOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_shortstr(); return $response; } /** * @param string $consumer_tag * @param bool $nowait * @return array */ public function streamCancel($consumer_tag, $nowait = false) { $writer = new AMQPWriter(); $writer->write_shortstr($consumer_tag); $writer->write_bits(array($nowait)); return array(80, 30, $writer); } /** * @param AMQPReader $reader * @return array */ public static function streamCancelOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_shortstr(); return $response; } /** * @param int $ticket * @param string $exchange * @param string $routing_key * @param bool $mandatory * @param bool $immediate * @return array */ public function streamPublish($ticket = 1, $exchange = '', $routing_key = '', $mandatory = false, $immediate = false) { $writer = new AMQPWriter(); $writer->write_short($ticket); $writer->write_shortstr($exchange); $writer->write_shortstr($routing_key); $writer->write_bits(array($mandatory, $immediate)); return array(80, 40, $writer); } /** * @param int $reply_code * @param string $reply_text * @param string $exchange * @param string $routing_key * @return array */ public function streamReturn($reply_code = 200, $reply_text = '', $exchange, $routing_key) { $writer = new AMQPWriter(); $writer->write_short($reply_code); $writer->write_shortstr($reply_text); $writer->write_shortstr($exchange); $writer->write_shortstr($routing_key); return array(80, 50, $writer); } /** * @param string $consumer_tag * @param int $delivery_tag * @param string $exchange * @param string $queue * @return array */ public function streamDeliver($consumer_tag, $delivery_tag, $exchange, $queue) { $writer = new AMQPWriter(); $writer->write_shortstr($consumer_tag); $writer->write_longlong($delivery_tag); $writer->write_shortstr($exchange); $writer->write_shortstr($queue); return array(80, 60, $writer); } /** * @return array */ public function txSelect() { $writer = new AMQPWriter(); return array(90, 10, $writer); } /** * @param AMQPReader $reader * @return array */ public static function txSelectOk(AMQPReader $reader) { $response = array(); return $response; } /** * @return array */ public function txCommit() { $writer = new AMQPWriter(); return array(90, 20, $writer); } /** * @param AMQPReader $reader * @return array */ public static function txCommitOk(AMQPReader $reader) { $response = array(); return $response; } /** * @return array */ public function txRollback() { $writer = new AMQPWriter(); return array(90, 30, $writer); } /** * @param AMQPReader $reader * @return array */ public static function txRollbackOk(AMQPReader $reader) { $response = array(); return $response; } /** * @return array */ public function dtxSelect() { $writer = new AMQPWriter(); return array(100, 10, $writer); } /** * @param AMQPReader $reader * @return array */ public static function dtxSelectOk(AMQPReader $reader) { $response = array(); return $response; } /** * @param string $dtx_identifier * @return array */ public function dtxStart($dtx_identifier) { $writer = new AMQPWriter(); $writer->write_shortstr($dtx_identifier); return array(100, 20, $writer); } /** * @param AMQPReader $reader * @return array */ public static function dtxStartOk(AMQPReader $reader) { $response = array(); return $response; } /** * @param mixed $meta_data * @return array */ public function tunnelRequest($meta_data) { $writer = new AMQPWriter(); $writer->write_table(empty($meta_data) ? array() : $meta_data); return array(110, 10, $writer); } /** * @param mixed $integer_1 * @param int $integer_2 * @param int $integer_3 * @param int $integer_4 * @param mixed $operation * @return array */ public function testInteger($integer_1, $integer_2, $integer_3, $integer_4, $operation) { $writer = new AMQPWriter(); $writer->write_octet($integer_1); $writer->write_short($integer_2); $writer->write_long($integer_3); $writer->write_longlong($integer_4); $writer->write_octet($operation); return array(120, 10, $writer); } /** * @param AMQPReader $reader * @return array */ public static function testIntegerOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_longlong(); return $response; } /** * @param string $string_1 * @param string $string_2 * @param mixed $operation * @return array */ public function testString($string_1, $string_2, $operation) { $writer = new AMQPWriter(); $writer->write_shortstr($string_1); $writer->write_longstr($string_2); $writer->write_octet($operation); return array(120, 20, $writer); } /** * @param AMQPReader $reader * @return array */ public static function testStringOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_longstr(); return $response; } /** * @param mixed $table * @param mixed $integer_op * @param mixed $string_op * @return array */ public function testTable($table, $integer_op, $string_op) { $writer = new AMQPWriter(); $writer->write_table(empty($table) ? array() : $table); $writer->write_octet($integer_op); $writer->write_octet($string_op); return array(120, 30, $writer); } /** * @param AMQPReader $reader * @return array */ public static function testTableOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_longlong(); $response[] = $reader->read_longstr(); return $response; } /** * @return array */ public function testContent() { $writer = new AMQPWriter(); return array(120, 40, $writer); } /** * @param AMQPReader $reader * @return array */ public static function testContentOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_long(); return $response; } } php-amqplib-2.11.0/PhpAmqpLib/Helper/Protocol/Protocol091.php000066400000000000000000000552251356514014400236020ustar00rootroot00000000000000write_octet($version_major); $writer->write_octet($version_minor); $writer->write_table(empty($server_properties) ? array() : $server_properties); $writer->write_longstr($mechanisms); $writer->write_longstr($locales); return array(10, 10, $writer); } /** * @param AMQPReader $reader * @return array */ public static function connectionStartOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_table(); $response[] = $reader->read_shortstr(); $response[] = $reader->read_longstr(); $response[] = $reader->read_shortstr(); return $response; } /** * @param string $challenge * @return array */ public function connectionSecure($challenge) { $writer = new AMQPWriter(); $writer->write_longstr($challenge); return array(10, 20, $writer); } /** * @param AMQPReader $reader * @return array */ public static function connectionSecureOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_longstr(); return $response; } /** * @param int $channel_max * @param int $frame_max * @param int $heartbeat * @return array */ public function connectionTune($channel_max = 0, $frame_max = 0, $heartbeat = 0) { $writer = new AMQPWriter(); $writer->write_short($channel_max); $writer->write_long($frame_max); $writer->write_short($heartbeat); return array(10, 30, $writer); } /** * @param AMQPReader $reader * @return array */ public static function connectionTuneOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_short(); $response[] = $reader->read_long(); $response[] = $reader->read_short(); return $response; } /** * @param string $virtual_host * @param string $capabilities * @param bool $insist * @return array */ public function connectionOpen($virtual_host = '/', $capabilities = '', $insist = false) { $writer = new AMQPWriter(); $writer->write_shortstr($virtual_host); $writer->write_shortstr($capabilities); $writer->write_bits(array($insist)); return array(10, 40, $writer); } /** * @param AMQPReader $reader * @return array */ public static function connectionOpenOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_shortstr(); return $response; } /** * @param int $reply_code * @param string $reply_text * @param int $class_id * @param int $method_id * @return array */ public function connectionClose($reply_code, $reply_text = '', $class_id, $method_id) { $writer = new AMQPWriter(); $writer->write_short($reply_code); $writer->write_shortstr($reply_text); $writer->write_short($class_id); $writer->write_short($method_id); return array(10, 50, $writer); } /** * @param AMQPReader $reader * @return array */ public static function connectionCloseOk(AMQPReader $reader) { $response = array(); return $response; } /** * @param string $reason * @return array */ public function connectionBlocked($reason = '') { $writer = new AMQPWriter(); $writer->write_shortstr($reason); return array(10, 60, $writer); } /** * @param AMQPReader $reader * @return array */ public static function connectionUnblocked(AMQPReader $reader) { $response = array(); return $response; } /** * @param string $out_of_band * @return array */ public function channelOpen($out_of_band = '') { $writer = new AMQPWriter(); $writer->write_shortstr($out_of_band); return array(20, 10, $writer); } /** * @param AMQPReader $reader * @return array */ public static function channelOpenOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_longstr(); return $response; } /** * @param bool $active * @return array */ public function channelFlow($active) { $writer = new AMQPWriter(); $writer->write_bits(array($active)); return array(20, 20, $writer); } /** * @param AMQPReader $reader * @return array */ public static function channelFlowOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_bit(); return $response; } /** * @param int $reply_code * @param string $reply_text * @param int $class_id * @param int $method_id * @return array */ public function channelClose($reply_code, $reply_text = '', $class_id, $method_id) { $writer = new AMQPWriter(); $writer->write_short($reply_code); $writer->write_shortstr($reply_text); $writer->write_short($class_id); $writer->write_short($method_id); return array(20, 40, $writer); } /** * @param AMQPReader $reader * @return array */ public static function channelCloseOk(AMQPReader $reader) { $response = array(); return $response; } /** * @param string $realm * @param bool $exclusive * @param bool $passive * @param bool $active * @param bool $write * @param bool $read * @return array */ public function accessRequest($realm = '/data', $exclusive = false, $passive = true, $active = true, $write = true, $read = true) { $writer = new AMQPWriter(); $writer->write_shortstr($realm); $writer->write_bits(array($exclusive, $passive, $active, $write, $read)); return array(30, 10, $writer); } /** * @param AMQPReader $reader * @return array */ public static function accessRequestOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_short(); return $response; } /** * @param int $ticket * @param string $exchange * @param string $type * @param bool $passive * @param bool $durable * @param bool $auto_delete * @param bool $internal * @param bool $nowait * @param array $arguments * @return array */ public function exchangeDeclare($ticket = 0, $exchange, $type = 'direct', $passive = false, $durable = false, $auto_delete = false, $internal = false, $nowait = false, $arguments = array()) { $writer = new AMQPWriter(); $writer->write_short($ticket); $writer->write_shortstr($exchange); $writer->write_shortstr($type); $writer->write_bits(array($passive, $durable, $auto_delete, $internal, $nowait)); $writer->write_table(empty($arguments) ? array() : $arguments); return array(40, 10, $writer); } /** * @param AMQPReader $reader * @return array */ public static function exchangeDeclareOk(AMQPReader $reader) { $response = array(); return $response; } /** * @param int $ticket * @param string $exchange * @param bool $if_unused * @param bool $nowait * @return array */ public function exchangeDelete($ticket = 0, $exchange, $if_unused = false, $nowait = false) { $writer = new AMQPWriter(); $writer->write_short($ticket); $writer->write_shortstr($exchange); $writer->write_bits(array($if_unused, $nowait)); return array(40, 20, $writer); } /** * @param AMQPReader $reader * @return array */ public static function exchangeDeleteOk(AMQPReader $reader) { $response = array(); return $response; } /** * @param int $ticket * @param string $destination * @param string $source * @param string $routing_key * @param bool $nowait * @param array $arguments * @return array */ public function exchangeBind($ticket = 0, $destination, $source, $routing_key = '', $nowait = false, $arguments = array()) { $writer = new AMQPWriter(); $writer->write_short($ticket); $writer->write_shortstr($destination); $writer->write_shortstr($source); $writer->write_shortstr($routing_key); $writer->write_bits(array($nowait)); $writer->write_table(empty($arguments) ? array() : $arguments); return array(40, 30, $writer); } /** * @param AMQPReader $reader * @return array */ public static function exchangeBindOk(AMQPReader $reader) { $response = array(); return $response; } /** * @param int $ticket * @param string $destination * @param string $source * @param string $routing_key * @param bool $nowait * @param array $arguments * @return array */ public function exchangeUnbind($ticket = 0, $destination, $source, $routing_key = '', $nowait = false, $arguments = array()) { $writer = new AMQPWriter(); $writer->write_short($ticket); $writer->write_shortstr($destination); $writer->write_shortstr($source); $writer->write_shortstr($routing_key); $writer->write_bits(array($nowait)); $writer->write_table(empty($arguments) ? array() : $arguments); return array(40, 40, $writer); } /** * @param AMQPReader $reader * @return array */ public static function exchangeUnbindOk(AMQPReader $reader) { $response = array(); return $response; } /** * @param int $ticket * @param string $queue * @param bool $passive * @param bool $durable * @param bool $exclusive * @param bool $auto_delete * @param bool $nowait * @param array $arguments * @return array */ public function queueDeclare($ticket = 0, $queue = '', $passive = false, $durable = false, $exclusive = false, $auto_delete = false, $nowait = false, $arguments = array()) { $writer = new AMQPWriter(); $writer->write_short($ticket); $writer->write_shortstr($queue); $writer->write_bits(array($passive, $durable, $exclusive, $auto_delete, $nowait)); $writer->write_table(empty($arguments) ? array() : $arguments); return array(50, 10, $writer); } /** * @param AMQPReader $reader * @return array */ public static function queueDeclareOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_shortstr(); $response[] = $reader->read_long(); $response[] = $reader->read_long(); return $response; } /** * @param int $ticket * @param string $queue * @param string $exchange * @param string $routing_key * @param bool $nowait * @param array $arguments * @return array */ public function queueBind($ticket = 0, $queue = '', $exchange, $routing_key = '', $nowait = false, $arguments = array()) { $writer = new AMQPWriter(); $writer->write_short($ticket); $writer->write_shortstr($queue); $writer->write_shortstr($exchange); $writer->write_shortstr($routing_key); $writer->write_bits(array($nowait)); $writer->write_table(empty($arguments) ? array() : $arguments); return array(50, 20, $writer); } /** * @param AMQPReader $reader * @return array */ public static function queueBindOk(AMQPReader $reader) { $response = array(); return $response; } /** * @param int $ticket * @param string $queue * @param bool $nowait * @return array */ public function queuePurge($ticket = 0, $queue = '', $nowait = false) { $writer = new AMQPWriter(); $writer->write_short($ticket); $writer->write_shortstr($queue); $writer->write_bits(array($nowait)); return array(50, 30, $writer); } /** * @param AMQPReader $reader * @return array */ public static function queuePurgeOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_long(); return $response; } /** * @param int $ticket * @param string $queue * @param bool $if_unused * @param bool $if_empty * @param bool $nowait * @return array */ public function queueDelete($ticket = 0, $queue = '', $if_unused = false, $if_empty = false, $nowait = false) { $writer = new AMQPWriter(); $writer->write_short($ticket); $writer->write_shortstr($queue); $writer->write_bits(array($if_unused, $if_empty, $nowait)); return array(50, 40, $writer); } /** * @param AMQPReader $reader * @return array */ public static function queueDeleteOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_long(); return $response; } /** * @param int $ticket * @param string $queue * @param string $exchange * @param string $routing_key * @param array $arguments * @return array */ public function queueUnbind($ticket = 0, $queue = '', $exchange, $routing_key = '', $arguments = array()) { $writer = new AMQPWriter(); $writer->write_short($ticket); $writer->write_shortstr($queue); $writer->write_shortstr($exchange); $writer->write_shortstr($routing_key); $writer->write_table(empty($arguments) ? array() : $arguments); return array(50, 50, $writer); } /** * @param AMQPReader $reader * @return array */ public static function queueUnbindOk(AMQPReader $reader) { $response = array(); return $response; } /** * @param int $prefetch_size * @param int $prefetch_count * @param bool $global * @return array */ public function basicQos($prefetch_size = 0, $prefetch_count = 0, $global = false) { $writer = new AMQPWriter(); $writer->write_long($prefetch_size); $writer->write_short($prefetch_count); $writer->write_bits(array($global)); return array(60, 10, $writer); } /** * @param AMQPReader $reader * @return array */ public static function basicQosOk(AMQPReader $reader) { $response = array(); return $response; } /** * @param int $ticket * @param string $queue * @param string $consumer_tag * @param bool $no_local * @param bool $no_ack * @param bool $exclusive * @param bool $nowait * @param array $arguments * @return array */ public function basicConsume($ticket = 0, $queue = '', $consumer_tag = '', $no_local = false, $no_ack = false, $exclusive = false, $nowait = false, $arguments = array()) { $writer = new AMQPWriter(); $writer->write_short($ticket); $writer->write_shortstr($queue); $writer->write_shortstr($consumer_tag); $writer->write_bits(array($no_local, $no_ack, $exclusive, $nowait)); $writer->write_table(empty($arguments) ? array() : $arguments); return array(60, 20, $writer); } /** * @param AMQPReader $reader * @return array */ public static function basicConsumeOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_shortstr(); return $response; } /** * @param string $consumer_tag * @param bool $nowait * @return array */ public function basicCancel($consumer_tag, $nowait = false) { $writer = new AMQPWriter(); $writer->write_shortstr($consumer_tag); $writer->write_bits(array($nowait)); return array(60, 30, $writer); } /** * @param AMQPReader $reader * @return array */ public static function basicCancelOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_shortstr(); return $response; } /** * @param int $ticket * @param string $exchange * @param string $routing_key * @param bool $mandatory * @param bool $immediate * @return array */ public function basicPublish($ticket = 0, $exchange = '', $routing_key = '', $mandatory = false, $immediate = false) { $writer = new AMQPWriter(); $writer->write_short($ticket); $writer->write_shortstr($exchange); $writer->write_shortstr($routing_key); $writer->write_bits(array($mandatory, $immediate)); return array(60, 40, $writer); } /** * @param int $reply_code * @param string $reply_text * @param string $exchange * @param string $routing_key * @return array */ public function basicReturn($reply_code, $reply_text = '', $exchange, $routing_key) { $writer = new AMQPWriter(); $writer->write_short($reply_code); $writer->write_shortstr($reply_text); $writer->write_shortstr($exchange); $writer->write_shortstr($routing_key); return array(60, 50, $writer); } /** * @param string $consumer_tag * @param int $delivery_tag * @param bool $redelivered * @param string $exchange * @param string $routing_key * @return array */ public function basicDeliver($consumer_tag, $delivery_tag, $redelivered = false, $exchange, $routing_key) { $writer = new AMQPWriter(); $writer->write_shortstr($consumer_tag); $writer->write_longlong($delivery_tag); $writer->write_bits(array($redelivered)); $writer->write_shortstr($exchange); $writer->write_shortstr($routing_key); return array(60, 60, $writer); } /** * @param int $ticket * @param string $queue * @param bool $no_ack * @return array */ public function basicGet($ticket = 0, $queue = '', $no_ack = false) { $writer = new AMQPWriter(); $writer->write_short($ticket); $writer->write_shortstr($queue); $writer->write_bits(array($no_ack)); return array(60, 70, $writer); } /** * @param AMQPReader $reader * @return array */ public static function basicGetOk(AMQPReader $reader) { $response = array(); $response[] = $reader->read_longlong(); $response[] = $reader->read_bit(); $response[] = $reader->read_shortstr(); $response[] = $reader->read_shortstr(); $response[] = $reader->read_long(); return $response; } /** * @param AMQPReader $reader * @return array */ public static function basicGetEmpty(AMQPReader $reader) { $response = array(); $response[] = $reader->read_shortstr(); return $response; } /** * @param int $delivery_tag * @param bool $multiple * @return array */ public function basicAck($delivery_tag = 0, $multiple = false) { $writer = new AMQPWriter(); $writer->write_longlong($delivery_tag); $writer->write_bits(array($multiple)); return array(60, 80, $writer); } /** * @param int $delivery_tag * @param bool $requeue * @return array */ public function basicReject($delivery_tag, $requeue = true) { $writer = new AMQPWriter(); $writer->write_longlong($delivery_tag); $writer->write_bits(array($requeue)); return array(60, 90, $writer); } /** * @param bool $requeue * @return array */ public function basicRecoverAsync($requeue = false) { $writer = new AMQPWriter(); $writer->write_bits(array($requeue)); return array(60, 100, $writer); } /** * @param bool $requeue * @return array */ public function basicRecover($requeue = false) { $writer = new AMQPWriter(); $writer->write_bits(array($requeue)); return array(60, 110, $writer); } /** * @param AMQPReader $reader * @return array */ public static function basicRecoverOk(AMQPReader $reader) { $response = array(); return $response; } /** * @param int $delivery_tag * @param bool $multiple * @param bool $requeue * @return array */ public function basicNack($delivery_tag = 0, $multiple = false, $requeue = true) { $writer = new AMQPWriter(); $writer->write_longlong($delivery_tag); $writer->write_bits(array($multiple, $requeue)); return array(60, 120, $writer); } /** * @return array */ public function txSelect() { $writer = new AMQPWriter(); return array(90, 10, $writer); } /** * @param AMQPReader $reader * @return array */ public static function txSelectOk(AMQPReader $reader) { $response = array(); return $response; } /** * @return array */ public function txCommit() { $writer = new AMQPWriter(); return array(90, 20, $writer); } /** * @param AMQPReader $reader * @return array */ public static function txCommitOk(AMQPReader $reader) { $response = array(); return $response; } /** * @return array */ public function txRollback() { $writer = new AMQPWriter(); return array(90, 30, $writer); } /** * @param AMQPReader $reader * @return array */ public static function txRollbackOk(AMQPReader $reader) { $response = array(); return $response; } /** * @param bool $nowait * @return array */ public function confirmSelect($nowait = false) { $writer = new AMQPWriter(); $writer->write_bits(array($nowait)); return array(85, 10, $writer); } /** * @param AMQPReader $reader * @return array */ public static function confirmSelectOk(AMQPReader $reader) { $response = array(); return $response; } } php-amqplib-2.11.0/PhpAmqpLib/Helper/Protocol/Wait080.php000066400000000000000000000072561356514014400227040ustar00rootroot00000000000000 '10,10', 'connection.start_ok' => '10,11', 'connection.secure' => '10,20', 'connection.secure_ok' => '10,21', 'connection.tune' => '10,30', 'connection.tune_ok' => '10,31', 'connection.open' => '10,40', 'connection.open_ok' => '10,41', 'connection.redirect' => '10,50', 'connection.close' => '10,60', 'connection.close_ok' => '10,61', 'channel.open' => '20,10', 'channel.open_ok' => '20,11', 'channel.flow' => '20,20', 'channel.flow_ok' => '20,21', 'channel.alert' => '20,30', 'channel.close' => '20,40', 'channel.close_ok' => '20,41', 'access.request' => '30,10', 'access.request_ok' => '30,11', 'exchange.declare' => '40,10', 'exchange.declare_ok' => '40,11', 'exchange.delete' => '40,20', 'exchange.delete_ok' => '40,21', 'queue.declare' => '50,10', 'queue.declare_ok' => '50,11', 'queue.bind' => '50,20', 'queue.bind_ok' => '50,21', 'queue.purge' => '50,30', 'queue.purge_ok' => '50,31', 'queue.delete' => '50,40', 'queue.delete_ok' => '50,41', 'queue.unbind' => '50,50', 'queue.unbind_ok' => '50,51', 'basic.qos' => '60,10', 'basic.qos_ok' => '60,11', 'basic.consume' => '60,20', 'basic.consume_ok' => '60,21', 'basic.cancel' => '60,30', 'basic.cancel_ok' => '60,31', 'basic.publish' => '60,40', 'basic.return' => '60,50', 'basic.deliver' => '60,60', 'basic.get' => '60,70', 'basic.get_ok' => '60,71', 'basic.get_empty' => '60,72', 'basic.ack' => '60,80', 'basic.reject' => '60,90', 'basic.recover_async' => '60,100', 'basic.recover' => '60,110', 'basic.recover_ok' => '60,111', 'file.qos' => '70,10', 'file.qos_ok' => '70,11', 'file.consume' => '70,20', 'file.consume_ok' => '70,21', 'file.cancel' => '70,30', 'file.cancel_ok' => '70,31', 'file.open' => '70,40', 'file.open_ok' => '70,41', 'file.stage' => '70,50', 'file.publish' => '70,60', 'file.return' => '70,70', 'file.deliver' => '70,80', 'file.ack' => '70,90', 'file.reject' => '70,100', 'stream.qos' => '80,10', 'stream.qos_ok' => '80,11', 'stream.consume' => '80,20', 'stream.consume_ok' => '80,21', 'stream.cancel' => '80,30', 'stream.cancel_ok' => '80,31', 'stream.publish' => '80,40', 'stream.return' => '80,50', 'stream.deliver' => '80,60', 'tx.select' => '90,10', 'tx.select_ok' => '90,11', 'tx.commit' => '90,20', 'tx.commit_ok' => '90,21', 'tx.rollback' => '90,30', 'tx.rollback_ok' => '90,31', 'dtx.select' => '100,10', 'dtx.select_ok' => '100,11', 'dtx.start' => '100,20', 'dtx.start_ok' => '100,21', 'tunnel.request' => '110,10', 'test.integer' => '120,10', 'test.integer_ok' => '120,11', 'test.string' => '120,20', 'test.string_ok' => '120,21', 'test.table' => '120,30', 'test.table_ok' => '120,31', 'test.content' => '120,40', 'test.content_ok' => '120,41', ); /** * @var string $method * @return string */ public function get_wait($method) { return $this->wait[$method]; } } php-amqplib-2.11.0/PhpAmqpLib/Helper/Protocol/Wait091.php000066400000000000000000000052731356514014400227030ustar00rootroot00000000000000 '10,10', 'connection.start_ok' => '10,11', 'connection.secure' => '10,20', 'connection.secure_ok' => '10,21', 'connection.tune' => '10,30', 'connection.tune_ok' => '10,31', 'connection.open' => '10,40', 'connection.open_ok' => '10,41', 'connection.close' => '10,50', 'connection.close_ok' => '10,51', 'connection.blocked' => '10,60', 'connection.unblocked' => '10,61', 'channel.open' => '20,10', 'channel.open_ok' => '20,11', 'channel.flow' => '20,20', 'channel.flow_ok' => '20,21', 'channel.close' => '20,40', 'channel.close_ok' => '20,41', 'access.request' => '30,10', 'access.request_ok' => '30,11', 'exchange.declare' => '40,10', 'exchange.declare_ok' => '40,11', 'exchange.delete' => '40,20', 'exchange.delete_ok' => '40,21', 'exchange.bind' => '40,30', 'exchange.bind_ok' => '40,31', 'exchange.unbind' => '40,40', 'exchange.unbind_ok' => '40,51', 'queue.declare' => '50,10', 'queue.declare_ok' => '50,11', 'queue.bind' => '50,20', 'queue.bind_ok' => '50,21', 'queue.purge' => '50,30', 'queue.purge_ok' => '50,31', 'queue.delete' => '50,40', 'queue.delete_ok' => '50,41', 'queue.unbind' => '50,50', 'queue.unbind_ok' => '50,51', 'basic.qos' => '60,10', 'basic.qos_ok' => '60,11', 'basic.consume' => '60,20', 'basic.consume_ok' => '60,21', 'basic.cancel' => '60,30', 'basic.cancel_ok' => '60,31', 'basic.publish' => '60,40', 'basic.return' => '60,50', 'basic.deliver' => '60,60', 'basic.get' => '60,70', 'basic.get_ok' => '60,71', 'basic.get_empty' => '60,72', 'basic.ack' => '60,80', 'basic.reject' => '60,90', 'basic.recover_async' => '60,100', 'basic.recover' => '60,110', 'basic.recover_ok' => '60,111', 'basic.nack' => '60,120', 'tx.select' => '90,10', 'tx.select_ok' => '90,11', 'tx.commit' => '90,20', 'tx.commit_ok' => '90,21', 'tx.rollback' => '90,30', 'tx.rollback_ok' => '90,31', 'confirm.select' => '85,10', 'confirm.select_ok' => '85,11', ); /** * @var string $method * @return string */ public function get_wait($method) { return $this->wait[$method]; } } php-amqplib-2.11.0/PhpAmqpLib/Helper/SocketConstants.php000066400000000000000000000031661356514014400230700ustar00rootroot00000000000000constants = $constants['sockets']; } else { trigger_error('Sockets extension is not enabled', E_USER_WARNING); $this->constants = array(); } } /** * @param string $name * @return int */ public function __get($name) { return isset($this->constants[$name]) ? $this->constants[$name] : 0; } /** * @param string $name * @param int $value * @internal */ public function __set($name, $value) { } /** * @param string $name * @return bool */ public function __isset($name) { return isset($this->constants[$name]); } /** * @return self */ public static function getInstance() { if (!self::$instance) { self::$instance = new self; } return self::$instance; } } php-amqplib-2.11.0/PhpAmqpLib/Message/000077500000000000000000000000001356514014400173715ustar00rootroot00000000000000php-amqplib-2.11.0/PhpAmqpLib/Message/AMQPMessage.php000066400000000000000000000053561356514014400221560ustar00rootroot00000000000000 'shortstr', 'content_encoding' => 'shortstr', 'application_headers' => 'table_object', 'delivery_mode' => 'octet', 'priority' => 'octet', 'correlation_id' => 'shortstr', 'reply_to' => 'shortstr', 'expiration' => 'shortstr', 'message_id' => 'shortstr', 'timestamp' => 'timestamp', 'type' => 'shortstr', 'user_id' => 'shortstr', 'app_id' => 'shortstr', 'cluster_id' => 'shortstr', ); /** * @param string $body * @param array $properties */ public function __construct($body = '', $properties = array()) { $this->setBody($body); parent::__construct($properties, static::$propertyDefinitions); } /** * @return string */ public function getBody() { return $this->body; } /** * Sets the message payload * * @param string $body * @return $this */ public function setBody($body) { $this->body = $body; return $this; } /** * @return string */ public function getContentEncoding() { return $this->content_encoding; } /** * @return int */ public function getBodySize() { return $this->body_size; } /** * @param int $body_size Message body size in byte(s) * @return AMQPMessage */ public function setBodySize($body_size) { $this->body_size = (int) $body_size; return $this; } /** * @return boolean */ public function isTruncated() { return $this->is_truncated; } /** * @param bool $is_truncated * @return AMQPMessage */ public function setIsTruncated($is_truncated) { $this->is_truncated = (bool) $is_truncated; return $this; } /** * @return int * * @throws \PhpAmqpLib\Exception\AMQPEmptyDeliveryTagException */ public function getDeliveryTag() { if (!isset($this->delivery_info['delivery_tag'])) { throw new \PhpAmqpLib\Exception\AMQPEmptyDeliveryTagException(); } return (int) $this->delivery_info['delivery_tag']; } } php-amqplib-2.11.0/PhpAmqpLib/Wire/000077500000000000000000000000001356514014400167135ustar00rootroot00000000000000php-amqplib-2.11.0/PhpAmqpLib/Wire/AMQPAbstractCollection.php000066400000000000000000000310471356514014400236670ustar00rootroot00000000000000 'I', self::T_DECIMAL => 'D', self::T_TIMESTAMP => 'T', self::T_STRING_LONG => 'S', self::T_TABLE => 'F' ); /** * @var array */ private static $_types_091 = array( self::T_INT_SHORTSHORT => 'b', self::T_INT_SHORTSHORT_U => 'B', self::T_INT_SHORT => 'U', self::T_INT_SHORT_U => 'u', self::T_INT_LONG => 'I', self::T_INT_LONG_U => 'i', self::T_INT_LONGLONG => 'L', self::T_INT_LONGLONG_U => 'l', self::T_DECIMAL => 'D', self::T_TIMESTAMP => 'T', self::T_VOID => 'V', self::T_BOOL => 't', self::T_STRING_SHORT => 's', self::T_STRING_LONG => 'S', self::T_ARRAY => 'A', self::T_TABLE => 'F', self::T_BYTES => 'x', ); /** * @var array */ private static $_types_rabbit = array( self::T_INT_SHORTSHORT => 'b', self::T_INT_SHORT => 's', self::T_INT_LONG => 'I', self::T_INT_LONGLONG => 'l', self::T_DECIMAL => 'D', self::T_TIMESTAMP => 'T', self::T_VOID => 'V', self::T_BOOL => 't', self::T_STRING_LONG => 'S', self::T_ARRAY => 'A', self::T_TABLE => 'F', self::T_BYTES => 'x', ); /** * @var array */ protected $data = array(); public function __construct(array $data = null) { if (!empty($data)) { $this->data = $this->encodeCollection($data); } } /** * @return int */ abstract public function getType(); /** * @param mixed $val * @param int $type * @param string $key */ final protected function setValue($val, $type = null, $key = null) { if ($val instanceof self) { if ($type && ($type != $val->getType())) { throw new Exception\AMQPInvalidArgumentException( 'Attempted to add instance of ' . get_class($val) . ' representing type [' . $val->getType() . '] as mismatching type [' . $type . ']' ); } $type = $val->getType(); } elseif ($type) { //ensuring data integrity and that all members are properly validated switch ($type) { case self::T_ARRAY: throw new Exception\AMQPInvalidArgumentException('Arrays must be passed as AMQPArray instance'); break; case self::T_TABLE: throw new Exception\AMQPInvalidArgumentException('Tables must be passed as AMQPTable instance'); break; case self::T_DECIMAL: if (!($val instanceof AMQPDecimal)) { throw new Exception\AMQPInvalidArgumentException('Decimal values must be instance of AMQPDecimal'); } break; } } if ($type) { self::checkDataTypeIsSupported($type, false); $val = array($type, $val); } else { $val = $this->encodeValue($val); } if ($key === null) { $this->data[] = $val; } else { $this->data[$key] = $val; } } /** * @return array */ final public function getNativeData() { return $this->decodeCollection($this->data); } /** * @param array $val * @return array */ final protected function encodeCollection(array $val) { foreach ($val as $k=>$v) { $val[$k] = $this->encodeValue($v); } return $val; } /** * @param array $val * @return array */ final protected function decodeCollection(array $val) { foreach ($val as $k=>$v) { $val[$k] = $this->decodeValue($v[1], $v[0]); } return $val; } /** * @param mixed $val * @return mixed * @throws Exception\AMQPOutOfBoundsException */ protected function encodeValue($val) { if (is_string($val)) { $val = $this->encodeString($val); } elseif (is_float($val)) { $val = $this->encodeFloat($val); } elseif (is_int($val)) { $val = $this->encodeInt($val); } elseif (is_bool($val)) { $val = $this->encodeBool($val); } elseif (is_null($val)) { $val = $this->encodeVoid(); } elseif ($val instanceof \DateTimeInterface) { $val = array(self::T_TIMESTAMP, $val->getTimestamp()); } elseif ($val instanceof \DateTime) { // PHP <= 5.4 has no DateTimeInterface $val = array(self::T_TIMESTAMP, $val->getTimestamp()); } elseif ($val instanceof AMQPDecimal) { $val = array(self::T_DECIMAL, $val); } elseif ($val instanceof self) { //avoid silent type correction of strictly typed values self::checkDataTypeIsSupported($val->getType(), false); $val = array($val->getType(), $val); } elseif (is_array($val)) { //AMQP specs says "Field names MUST start with a letter, '$' or '#'" //so beware, some servers may raise an exception with 503 code in cases when indexed array is encoded as table if (self::isProtocol(Wire\Constants080::VERSION)) { //080 doesn't support arrays, forcing table $val = array(self::T_TABLE, new AMQPTable($val)); } elseif (empty($val) || (array_keys($val) === range(0, count($val) - 1))) { $val = array(self::T_ARRAY, new AMQPArray($val)); } else { $val = array(self::T_TABLE, new AMQPTable($val)); } } else { throw new Exception\AMQPOutOfBoundsException(sprintf('Encountered value of unsupported type: %s', gettype($val))); } return $val; } /** * @param mixed $val * @param int $type * @return array|bool|\DateTime|null */ protected function decodeValue($val, $type) { if ($val instanceof self) { //covering arrays and tables $val = $val->getNativeData(); } else { switch ($type) { case self::T_BOOL: $val = (bool) $val; break; case self::T_TIMESTAMP: $val = \DateTime::createFromFormat('U', $val); break; case self::T_VOID: $val = null; break; case self::T_ARRAY: case self::T_TABLE: throw new Exception\AMQPLogicException( 'Encountered an array/table struct which is not an instance of AMQPCollection. ' . 'This is considered a bug and should be fixed, please report' ); } } return $val; } /** * @param string $val * @return array */ protected function encodeString($val) { return array(self::T_STRING_LONG, $val); } /** * @param int $val * @return array */ protected function encodeInt($val) { if (($val >= -2147483648) && ($val <= 2147483647)) { $ev = array(self::T_INT_LONG, $val); } elseif (self::isProtocol(Wire\Constants080::VERSION)) { //080 doesn't support longlong $ev = $this->encodeString((string) $val); } else { $ev = array(self::T_INT_LONGLONG, $val); } return $ev; } /** * @param float $val * @return array */ protected function encodeFloat($val) { return static::encodeString((string) $val); } /** * @param bool $val * @return array */ protected function encodeBool($val) { $val = (bool) $val; return self::isProtocol(Wire\Constants080::VERSION) ? array(self::T_INT_LONG, (int) $val) : array(self::T_BOOL, $val); } /** * @return array */ protected function encodeVoid() { return self::isProtocol(Wire\Constants080::VERSION) ? $this->encodeString('') : array(self::T_VOID, null); } /** * @return string */ final public static function getProtocol() { if (self::$_protocol === null) { self::$_protocol = defined('AMQP_STRICT_FLD_TYPES') && AMQP_STRICT_FLD_TYPES ? AbstractChannel::getProtocolVersion() : self::PROTOCOL_RBT; } return self::$_protocol; } /** * @param string $proto * @return bool */ final public static function isProtocol($proto) { return self::getProtocol() == $proto; } /** * @return array [dataTypeConstant => dataTypeSymbol] */ final public static function getSupportedDataTypes() { switch ($proto = self::getProtocol()) { case Wire\Constants080::VERSION: $types = self::$_types_080; break; case Wire\Constants091::VERSION: $types = self::$_types_091; break; case self::PROTOCOL_RBT: $types = self::$_types_rabbit; break; default: throw new Exception\AMQPOutOfRangeException(sprintf('Unknown protocol: %s', $proto)); } return $types; } /** * @param string $type * @param bool $return Whether to return or raise AMQPOutOfRangeException * @return boolean */ final public static function checkDataTypeIsSupported($type, $return = true) { try { $supported = self::getSupportedDataTypes(); if (!isset($supported[$type])) { throw new Exception\AMQPOutOfRangeException(sprintf('AMQP-%s doesn\'t support data of type [%s]', self::getProtocol(), $type)); } return true; } catch (Exception\AMQPOutOfRangeException $ex) { if (!$return) { throw $ex; } return false; } } /** * @param int $type * @return string */ final public static function getSymbolForDataType($type) { $types = self::getSupportedDataTypes(); if (!isset($types[$type])) { throw new Exception\AMQPOutOfRangeException(sprintf('AMQP-%s doesn\'t support data of type [%s]', self::getProtocol(), $type)); } return $types[$type]; } /** * @param string $symbol * @return integer */ final public static function getDataTypeForSymbol($symbol) { $symbols = array_flip(self::getSupportedDataTypes()); if (!isset($symbols[$symbol])) { throw new Exception\AMQPOutOfRangeException(sprintf('AMQP-%s doesn\'t define data of type [%s]', self::getProtocol(), $symbol)); } return $symbols[$symbol]; } public function current() { return current($this->data); } public function key() { return key($this->data); } public function next() { next($this->data); } public function rewind() { reset($this->data); } public function valid() { return key($this->data) !== null; } } php-amqplib-2.11.0/PhpAmqpLib/Wire/AMQPArray.php000066400000000000000000000011161356514014400211600ustar00rootroot00000000000000setValue($val, $type); return $this; } } php-amqplib-2.11.0/PhpAmqpLib/Wire/AMQPDecimal.php000066400000000000000000000024561356514014400214500ustar00rootroot00000000000000n = $n; $this->e = $e; } /** * @return string */ public function asBCvalue() { $n = new BigInteger($this->n); $e = new BigInteger('1' . str_repeat('0', $this->e)); list($q) = $n->divide($e); return $q->toString(); } /** * @return int */ public function getE() { return $this->e; } /** * @return int */ public function getN() { return $this->n; } } php-amqplib-2.11.0/PhpAmqpLib/Wire/AMQPReader.php000066400000000000000000000370541356514014400213160ustar00rootroot00000000000000str = (string)$str; $this->str_length = mb_strlen($this->str, 'ASCII'); } $this->io = $io; $this->timeout = $timeout; } /** * Resets the object from the injected param * * Used to not need to create a new AMQPReader instance every time. * when we can just pass a string and reset the object state. * NOTE: since we are working with strings we don't need to pass an AbstractIO * or a timeout. * * @param string $str */ public function reuse($str) { $this->str = $str; $this->str_length = mb_strlen($this->str, 'ASCII'); $this->offset = 0; $this->resetCounters(); } /** * Closes the stream */ public function close() { if ($this->io) { $this->io->close(); } } /** * @param int $n * @return string */ public function read($n) { $this->resetCounters(); return $this->rawread($n); } /** * Waits until some data is retrieved from the socket. * * AMQPTimeoutException can be raised if the timeout is set * * @throws \PhpAmqpLib\Exception\AMQPIOWaitException on network errors * @throws \PhpAmqpLib\Exception\AMQPTimeoutException when timeout is set and no data received * @throws \PhpAmqpLib\Exception\AMQPNoDataException when no data is ready to read from IO */ protected function wait() { $timeout = $this->getTimeout(); if (null === $timeout) { // timeout=null just poll state and return instantly $sec = 0; $usec = 0; } elseif ($timeout > 0) { list($sec, $usec) = MiscHelper::splitSecondsMicroseconds($this->getTimeout()); } else { // wait indefinitely for data if timeout=0 $sec = null; $usec = 0; } $result = $this->io->select($sec, $usec); if ($result === false) { throw new AMQPIOWaitException('A network error occurred while awaiting for incoming data'); } if ($result === 0) { if ($timeout > 0) { throw new AMQPTimeoutException(sprintf( 'The connection timed out after %s sec while awaiting incoming data', $timeout )); } else { throw new AMQPNoDataException('No data is ready to read'); } } } /** * @param int $n * @return string * @throws \RuntimeException * @throws \PhpAmqpLib\Exception\AMQPDataReadException * @throws \PhpAmqpLib\Exception\AMQPNoDataException */ protected function rawread($n) { if ($this->io) { $res = ''; while (true) { $this->wait(); try { $res = $this->io->read($n); break; } catch (AMQPTimeoutException $e) { if ($this->getTimeout() > 0) { throw $e; } } } $this->offset += $n; return $res; } if ($this->str_length < $n) { throw new AMQPDataReadException(sprintf( 'Error reading data. Requested %s bytes while string buffer has only %s', $n, $this->str_length )); } $res = mb_substr($this->str, 0, $n, 'ASCII'); $this->str = mb_substr($this->str, $n, null, 'ASCII'); $this->str_length -= $n; $this->offset += $n; return $res; } /** * @return bool */ public function read_bit() { if (empty($this->bitcount)) { $this->bits = ord($this->rawread(1)); $this->bitcount = 8; } $result = ($this->bits & 1) === 1; $this->bits >>= 1; $this->bitcount--; return $result; } /** * @return mixed */ public function read_octet() { $this->resetCounters(); list(, $res) = unpack('C', $this->rawread(1)); return $res; } /** * @return mixed */ public function read_signed_octet() { $this->resetCounters(); list(, $res) = unpack('c', $this->rawread(1)); return $res; } /** * @return mixed */ public function read_short() { $this->resetCounters(); list(, $res) = unpack('n', $this->rawread(2)); return $res; } /** * @return mixed */ public function read_signed_short() { $this->resetCounters(); list(, $res) = unpack('s', $this->correctEndianness($this->rawread(2))); return $res; } /** * Reads 32 bit integer in big-endian byte order. * * On 64 bit systems it will return always unsigned int * value in 0..2^32 range. * * On 32 bit systems it will return signed int value in * -2^31...+2^31 range. * * Use with caution! */ public function read_php_int() { list(, $res) = unpack('N', $this->rawread(4)); if ($this->is64bits) { return (int) sprintf('%u', $res); } return $res; } /** * PHP does not have unsigned 32 bit int, * so we return it as a string * * @return string */ public function read_long() { $this->resetCounters(); list(, $res) = unpack('N', $this->rawread(4)); if (!$this->is64bits && $this->getLongMSB($res)) { return sprintf('%u', $res); } return $res; } /** * @return integer */ private function read_signed_long() { $this->resetCounters(); list(, $res) = unpack('l', $this->correctEndianness($this->rawread(4))); return $res; } /** * Even on 64 bit systems PHP integers are signed. * Since we need an unsigned value here we return it as a string. * * @return int|string */ public function read_longlong() { $this->resetCounters(); $bytes = $this->rawread(8); if ($this->is64bits) { // we can "unpack" if MSB bit is 0 (at most 63 bit integer), fallback to BigInteger otherwise if (!$this->getMSB($bytes)) { $res = unpack('J', $bytes); return $res[1]; } } else { // on 32-bit systems we can "unpack" up to 31 bits integer list(, $hi, $lo) = unpack('N2', $bytes); if ($hi === 0 && $lo > 0) { return $lo; } } $var = new BigInteger($bytes, 256); return $var->toString(); } /** * @return int|string */ public function read_signed_longlong() { $this->resetCounters(); $bytes = $this->rawread(8); if ($this->is64bits) { $res = unpack('q', $this->correctEndianness($bytes)); return $res[1]; } else { // on 32-bit systems we can "unpack" up to 31 bits integer list(, $hi, $lo) = unpack('N2', $bytes); if ($hi === 0 && $lo > 0) { // positive and less than 2^31-1 return $lo; } // negative and more than -2^31 if ($hi === -1 && $this->getLongMSB($lo)) { return $lo; } } $var = new BigInteger($bytes, -256); return $var->toString(); } /** * Read a utf-8 encoded string that's stored in up to * 255 bytes. Return it decoded as a PHP unicode object. */ public function read_shortstr() { $this->resetCounters(); list(, $slen) = unpack('C', $this->rawread(1)); return $this->rawread($slen); } /** * Read a string that's up to 2**32 bytes, the encoding * isn't specified in the AMQP spec, so just return it as * a plain PHP string. */ public function read_longstr() { $this->resetCounters(); $slen = $this->read_php_int(); if ($slen < 0) { throw new AMQPOutOfBoundsException('Strings longer than supported on this platform'); } return $this->rawread($slen); } /** * Read and AMQP timestamp, which is a 64-bit integer representing * seconds since the Unix epoch in 1-second resolution. */ public function read_timestamp() { return $this->read_longlong(); } /** * Read an AMQP table, and return as a PHP array. keys are strings, * values are (type,value) tuples. * * @param bool $returnObject Whether to return AMQPArray instance instead of plain array * @return array|AMQPTable */ public function read_table($returnObject = false) { $this->resetCounters(); $tlen = $this->read_php_int(); if ($tlen < 0) { throw new AMQPOutOfBoundsException('Table is longer than supported'); } $table_data = new AMQPReader($this->rawread($tlen), null); $result = $returnObject ? new AMQPTable() : array(); while ($table_data->tell() < $tlen) { $name = $table_data->read_shortstr(); $ftype = AMQPAbstractCollection::getDataTypeForSymbol($ftypeSym = $table_data->rawread(1)); $val = $table_data->read_value($ftype, $returnObject); $returnObject ? $result->set($name, $val, $ftype) : $result[$name] = array($ftypeSym, $val); } return $result; } /** * @return array|AMQPTable */ public function read_table_object() { return $this->read_table(true); } /** * Reads the array in the next value. * * @param bool $returnObject Whether to return AMQPArray instance instead of plain array * @return array|AMQPArray */ public function read_array($returnObject = false) { $this->resetCounters(); // Determine array length and its end position $arrayLength = $this->read_php_int(); $endOffset = $this->offset + $arrayLength; $result = $returnObject ? new AMQPArray() : array(); // Read values until we reach the end of the array while ($this->offset < $endOffset) { $fieldType = AMQPAbstractCollection::getDataTypeForSymbol($this->rawread(1)); $fieldValue = $this->read_value($fieldType, $returnObject); $returnObject ? $result->push($fieldValue, $fieldType) : $result[] = $fieldValue; } return $result; } /** * @return array|AMQPArray */ public function read_array_object() { return $this->read_array(true); } /** * Reads the next value as the provided field type. * * @param int $fieldType One of AMQPAbstractCollection::T_* constants * @param bool $collectionsAsObjects Description * @return mixed * @throws \PhpAmqpLib\Exception\AMQPDataReadException */ public function read_value($fieldType, $collectionsAsObjects = false) { $this->resetCounters(); switch ($fieldType) { case AMQPAbstractCollection::T_INT_SHORTSHORT: //according to AMQP091 spec, 'b' is not bit, it is short-short-int, also valid for rabbit/qpid //$val=$this->read_bit(); $val = $this->read_signed_octet(); break; case AMQPAbstractCollection::T_INT_SHORTSHORT_U: $val = $this->read_octet(); break; case AMQPAbstractCollection::T_INT_SHORT: $val = $this->read_signed_short(); break; case AMQPAbstractCollection::T_INT_SHORT_U: $val = $this->read_short(); break; case AMQPAbstractCollection::T_INT_LONG: $val = $this->read_signed_long(); break; case AMQPAbstractCollection::T_INT_LONG_U: $val = $this->read_long(); break; case AMQPAbstractCollection::T_INT_LONGLONG: $val = $this->read_signed_longlong(); break; case AMQPAbstractCollection::T_INT_LONGLONG_U: $val = $this->read_longlong(); break; case AMQPAbstractCollection::T_DECIMAL: $e = $this->read_octet(); $n = $this->read_signed_long(); $val = new AMQPDecimal($n, $e); break; case AMQPAbstractCollection::T_TIMESTAMP: $val = $this->read_timestamp(); break; case AMQPAbstractCollection::T_BOOL: $val = $this->read_octet(); break; case AMQPAbstractCollection::T_STRING_SHORT: $val = $this->read_shortstr(); break; case AMQPAbstractCollection::T_STRING_LONG: $val = $this->read_longstr(); break; case AMQPAbstractCollection::T_ARRAY: $val = $this->read_array($collectionsAsObjects); break; case AMQPAbstractCollection::T_TABLE: $val = $this->read_table($collectionsAsObjects); break; case AMQPAbstractCollection::T_VOID: $val = null; break; case AMQPAbstractCollection::T_BYTES: $val = $this->read_longstr(); break; default: throw new AMQPInvalidArgumentException(sprintf( 'Unsupported type "%s"', $fieldType )); } return isset($val) ? $val : null; } /** * @return int */ protected function tell() { return $this->offset; } /** * Sets the timeout (second) * * @param int|float|null $timeout */ public function setTimeout($timeout) { $this->timeout = $timeout; } /** * @return int|float|null */ public function getTimeout() { return $this->timeout; } private function resetCounters() { $this->bitcount = $this->bits = 0; } } php-amqplib-2.11.0/PhpAmqpLib/Wire/AMQPTable.php000066400000000000000000000022461356514014400211360ustar00rootroot00000000000000 128)) { throw new Exception\AMQPInvalidArgumentException('Table key must be non-empty string up to 128 chars in length'); } $this->setValue($val, $type, $key); } } php-amqplib-2.11.0/PhpAmqpLib/Wire/AMQPWriter.php000066400000000000000000000272451356514014400213710ustar00rootroot00000000000000bits)) { $this->out .= implode('', array_map('chr', $this->bits)); $this->bits = array(); $this->bitcount = 0; } } /** * Get what's been encoded so far. * * @return string */ public function getvalue() { /* temporarily needed for compatibility with write_bit unit tests */ if ($this->bitcount) { $this->flushbits(); } return $this->out; } /** * Write a plain PHP string, with no special encoding. * * @param string $s * * @return $this */ public function write($s) { $this->out .= $s; return $this; } /** * Write a boolean value. * (deprecated, use write_bits instead) * * @deprecated * @param bool $b * @return $this */ public function write_bit($b) { $b = $b ? 1 : 0; $shift = $this->bitcount % 8; $last = $shift === 0 ? 0 : array_pop($this->bits); $last |= ($b << $shift); $this->bits[] = $last; $this->bitcount++; return $this; } /** * Write multiple bits as an octet * * @param bool[] $bits * @return $this */ public function write_bits($bits) { $value = 0; foreach ($bits as $n => $bit) { $bit = $bit ? 1 : 0; $value |= ($bit << $n); } $this->out .= chr($value); return $this; } /** * Write an integer as an unsigned 8-bit value * * @param int $n * @return $this * @throws \PhpAmqpLib\Exception\AMQPInvalidArgumentException */ public function write_octet($n) { if ($n < 0 || $n > 255) { throw new AMQPInvalidArgumentException('Octet out of range: ' . $n); } $this->out .= chr($n); return $this; } /** * @param int $n * @return $this */ public function write_signed_octet($n) { if (($n < -128) || ($n > 127)) { throw new AMQPInvalidArgumentException('Signed octet out of range: ' . $n); } $this->out .= pack('c', $n); return $this; } /** * Write an integer as an unsigned 16-bit value * * @param int $n * @return $this * @throws \PhpAmqpLib\Exception\AMQPInvalidArgumentException */ public function write_short($n) { if ($n < 0 || $n > 65535) { throw new AMQPInvalidArgumentException('Short out of range: ' . $n); } $this->out .= pack('n', $n); return $this; } /** * @param int $n * @return $this */ public function write_signed_short($n) { if (($n < -32768) || ($n > 32767)) { throw new AMQPInvalidArgumentException('Signed short out of range: ' . $n); } $this->out .= $this->correctEndianness(pack('s', $n)); return $this; } /** * Write an integer as an unsigned 32-bit value * * @param int|string $n * @return $this */ public function write_long($n) { if (($n < 0) || ($n > 4294967295)) { throw new AMQPInvalidArgumentException('Long out of range: ' . $n); } //Numeric strings >PHP_INT_MAX on 32bit are casted to PHP_INT_MAX, damn PHP if (!$this->is64bits && is_string($n)) { $n = (float) $n; } $this->out .= pack('N', $n); return $this; } /** * @param int $n * @return $this */ private function write_signed_long($n) { if (($n < -2147483648) || ($n > 2147483647)) { throw new AMQPInvalidArgumentException('Signed long out of range: ' . $n); } //on my 64bit debian this approach is slightly faster than splitIntoQuads() $this->out .= $this->correctEndianness(pack('l', $n)); return $this; } /** * Write a numeric value as an unsigned 64-bit value * * @param int|string $n * @return $this * @throws AMQPOutOfRangeException */ public function write_longlong($n) { if (is_int($n)) { if ($n < 0) { throw new AMQPOutOfRangeException('Longlong out of range: ' . $n); } if ($this->is64bits) { $res = pack('J', $n); $this->out .= $res; } else { $this->out .= pack('NN', 0, $n); } return $this; } $value = new BigInteger($n); if ($value->compare(self::getBigInteger('0')) < 0 || $value->compare(self::getBigInteger('FFFFFFFFFFFFFFFF', 16)) > 0) { throw new AMQPInvalidArgumentException('Longlong out of range: ' . $n); } $value->setPrecision(64); $this->out .= $value->toBytes(); return $this; } /** * @param int|string $n * @return $this */ public function write_signed_longlong($n) { if (is_int($n)) { if ($this->is64bits) { // q is for 64-bit signed machine byte order $packed = pack('q', $n); if (self::isLittleEndian()) { $packed = $this->convertByteOrder($packed); } $this->out .= $packed; } else { $hi = $n < 0 ? -1 : 0; $lo = $n; $this->out .= pack('NN', $hi, $lo); } return $this; } $value = new BigInteger($n); if ($value->compare(self::getBigInteger('-8000000000000000', 16)) < 0 || $value->compare(self::getBigInteger('7FFFFFFFFFFFFFFF', 16)) > 0) { throw new AMQPInvalidArgumentException('Signed longlong out of range: ' . $n); } $value->setPrecision(64); $this->out .= substr($value->toBytes(true), -8); return $this; } /** * Write a string up to 255 bytes long after encoding. * Assume UTF-8 encoding * * @param string $s * @return $this * @throws \PhpAmqpLib\Exception\AMQPInvalidArgumentException */ public function write_shortstr($s) { $len = mb_strlen($s, 'ASCII'); if ($len > 255) { throw new AMQPInvalidArgumentException('String too long'); } $this->write_octet($len); $this->out .= $s; return $this; } /** * Write a string up to 2**32 bytes long. Assume UTF-8 encoding * * @param string $s * @return $this */ public function write_longstr($s) { $this->write_long(mb_strlen($s, 'ASCII')); $this->out .= $s; return $this; } /** * Supports the writing of Array types, so that you can implement * array methods, like Rabbitmq's HA parameters * * @param AMQPArray|array $a Instance of AMQPArray or PHP array WITHOUT format hints (unlike write_table()) * @return self */ public function write_array($a) { if (!($a instanceof AMQPArray)) { $a = new AMQPArray($a); } $data = new self(); foreach ($a as $v) { $data->write_value($v[0], $v[1]); } $data = $data->getvalue(); $this->write_long(mb_strlen($data, 'ASCII')); $this->write($data); return $this; } /** * Write unix time_t value as 64 bit timestamp * * @param int $v * @return $this */ public function write_timestamp($v) { $this->write_longlong($v); return $this; } /** * Write PHP array, as table. Input array format: keys are strings, * values are (type,value) tuples. * * @param AMQPTable|array $d Instance of AMQPTable or PHP array WITH format hints (unlike write_array()) * @return $this * @throws \PhpAmqpLib\Exception\AMQPInvalidArgumentException */ public function write_table($d) { $typeIsSym = !($d instanceof AMQPTable); //purely for back-compat purposes $table_data = new AMQPWriter(); foreach ($d as $k => $va) { list($ftype, $v) = $va; $table_data->write_shortstr($k); $table_data->write_value($typeIsSym ? AMQPAbstractCollection::getDataTypeForSymbol($ftype) : $ftype, $v); } $table_data = $table_data->getvalue(); $this->write_long(mb_strlen($table_data, 'ASCII')); $this->write($table_data); return $this; } /** * for compat with method mapping used by AMQPMessage * * @param AMQPTable|array $d * @return $this */ public function write_table_object($d) { return $this->write_table($d); } /** * @param int $type One of AMQPAbstractCollection::T_* constants * @param mixed $val */ private function write_value($type, $val) { //This will find appropriate symbol for given data type for currently selected protocol //Also will raise an exception on unknown type $this->write(AMQPAbstractCollection::getSymbolForDataType($type)); switch ($type) { case AMQPAbstractCollection::T_INT_SHORTSHORT: $this->write_signed_octet($val); break; case AMQPAbstractCollection::T_INT_SHORTSHORT_U: $this->write_octet($val); break; case AMQPAbstractCollection::T_INT_SHORT: $this->write_signed_short($val); break; case AMQPAbstractCollection::T_INT_SHORT_U: $this->write_short($val); break; case AMQPAbstractCollection::T_INT_LONG: $this->write_signed_long($val); break; case AMQPAbstractCollection::T_INT_LONG_U: $this->write_long($val); break; case AMQPAbstractCollection::T_INT_LONGLONG: $this->write_signed_longlong($val); break; case AMQPAbstractCollection::T_INT_LONGLONG_U: $this->write_longlong($val); break; case AMQPAbstractCollection::T_DECIMAL: $this->write_octet($val->getE()); $this->write_signed_long($val->getN()); break; case AMQPAbstractCollection::T_TIMESTAMP: $this->write_timestamp($val); break; case AMQPAbstractCollection::T_BOOL: $this->write_octet($val ? 1 : 0); break; case AMQPAbstractCollection::T_STRING_SHORT: $this->write_shortstr($val); break; case AMQPAbstractCollection::T_STRING_LONG: $this->write_longstr($val); break; case AMQPAbstractCollection::T_ARRAY: $this->write_array($val); break; case AMQPAbstractCollection::T_TABLE: $this->write_table($val); break; case AMQPAbstractCollection::T_VOID: break; case AMQPAbstractCollection::T_BYTES: $this->write_longstr($val); break; default: throw new AMQPInvalidArgumentException(sprintf( 'Unsupported type "%s"', $type )); } } } php-amqplib-2.11.0/PhpAmqpLib/Wire/AbstractClient.php000066400000000000000000000037451356514014400223370ustar00rootroot00000000000000is64bits = PHP_INT_SIZE === 8; } /** * Converts byte-string between native and network byte order, in both directions * * @param string $bytes * @return string */ protected function correctEndianness($bytes) { return self::isLittleEndian() ? $this->convertByteOrder($bytes) : $bytes; } /** * @param string $bytes * @return string */ protected function convertByteOrder($bytes) { return strrev($bytes); } /** * @param int $longInt * @return bool */ protected function getLongMSB($longInt) { return (bool) ($longInt & 0x80000000); } /** * @param string $bytes * @return bool */ protected function getMSB($bytes) { return ord($bytes[0]) > 127; } /** * @return bool */ protected static function isLittleEndian() { if (self::$isLittleEndian === null) { $tmp = unpack('S', "\x01\x00"); // to maintain 5.3 compatibility self::$isLittleEndian = $tmp[1] === 1; } return self::$isLittleEndian; } /** * @param string $value * @param int $base * @return BigInteger */ protected static function getBigInteger($value, $base = 10) { if (!isset(self::$bigIntegers[$base])) { self::$bigIntegers[$base] = array(); } if (isset(self::$bigIntegers[$base][$value])) { return self::$bigIntegers[$base][$value]; } $integer = new BigInteger($value, $base); self::$bigIntegers[$base][$value] = $integer; return $integer; } } php-amqplib-2.11.0/PhpAmqpLib/Wire/Constants.php000066400000000000000000000024621356514014400214040ustar00rootroot00000000000000 */ protected static $FRAME_TYPES = array(); /** * @var array */ protected static $CONTENT_METHODS = array(); /** * @var array */ protected static $CLOSE_METHODS = array(); /** * @var array */ public static $GLOBAL_METHOD_NAMES = array(); /** * @return string */ public function getHeader() { return static::AMQP_HEADER; } /** * @param int $type * @return bool */ public function isFrameType($type) { return array_key_exists($type, static::$FRAME_TYPES); } /** * @param int $type * @return string */ public function getFrameType($type) { return static::$FRAME_TYPES[$type]; } /** * @param string $method * @return bool */ public function isContentMethod($method) { return in_array($method, static::$CONTENT_METHODS, false); } /** * @param string $method * @return bool */ public function isCloseMethod($method) { return in_array($method, static::$CLOSE_METHODS, false); } } php-amqplib-2.11.0/PhpAmqpLib/Wire/Constants080.php000066400000000000000000000110221356514014400216240ustar00rootroot00000000000000 'FRAME-METHOD', 2 => 'FRAME-HEADER', 3 => 'FRAME-BODY', 4 => 'FRAME-OOB-METHOD', 5 => 'FRAME-OOB-HEADER', 6 => 'FRAME-OOB-BODY', 7 => 'FRAME-TRACE', 8 => 'FRAME-HEARTBEAT', 4096 => 'FRAME-MIN-SIZE', 206 => 'FRAME-END', 501 => 'FRAME-ERROR', ); /** * @var array */ protected static $CONTENT_METHODS = array( 0 => '60,40', 1 => '60,50', 2 => '60,60', 3 => '60,71', 4 => '70,50', 5 => '70,70', 6 => '80,40', 7 => '80,50', 8 => '80,60', 9 => '110,10', 10 => '120,40', 11 => '120,41', ); /** * @var array */ protected static $CLOSE_METHODS = array( 0 => '10,60', 1 => '20,40', ); /** * @var array */ public static $GLOBAL_METHOD_NAMES = array( '10,10' => 'Connection.start', '10,11' => 'Connection.start_ok', '10,20' => 'Connection.secure', '10,21' => 'Connection.secure_ok', '10,30' => 'Connection.tune', '10,31' => 'Connection.tune_ok', '10,40' => 'Connection.open', '10,41' => 'Connection.open_ok', '10,50' => 'Connection.redirect', '10,60' => 'Connection.close', '10,61' => 'Connection.close_ok', '20,10' => 'Channel.open', '20,11' => 'Channel.open_ok', '20,20' => 'Channel.flow', '20,21' => 'Channel.flow_ok', '20,30' => 'Channel.alert', '20,40' => 'Channel.close', '20,41' => 'Channel.close_ok', '30,10' => 'Access.request', '30,11' => 'Access.request_ok', '40,10' => 'Exchange.declare', '40,11' => 'Exchange.declare_ok', '40,20' => 'Exchange.delete', '40,21' => 'Exchange.delete_ok', '50,10' => 'Queue.declare', '50,11' => 'Queue.declare_ok', '50,20' => 'Queue.bind', '50,21' => 'Queue.bind_ok', '50,30' => 'Queue.purge', '50,31' => 'Queue.purge_ok', '50,40' => 'Queue.delete', '50,41' => 'Queue.delete_ok', '50,50' => 'Queue.unbind', '50,51' => 'Queue.unbind_ok', '60,10' => 'Basic.qos', '60,11' => 'Basic.qos_ok', '60,20' => 'Basic.consume', '60,21' => 'Basic.consume_ok', '60,30' => 'Basic.cancel', '60,31' => 'Basic.cancel_ok', '60,40' => 'Basic.publish', '60,50' => 'Basic.return', '60,60' => 'Basic.deliver', '60,70' => 'Basic.get', '60,71' => 'Basic.get_ok', '60,72' => 'Basic.get_empty', '60,80' => 'Basic.ack', '60,90' => 'Basic.reject', '60,100' => 'Basic.recover_async', '60,110' => 'Basic.recover', '60,111' => 'Basic.recover_ok', '70,10' => 'File.qos', '70,11' => 'File.qos_ok', '70,20' => 'File.consume', '70,21' => 'File.consume_ok', '70,30' => 'File.cancel', '70,31' => 'File.cancel_ok', '70,40' => 'File.open', '70,41' => 'File.open_ok', '70,50' => 'File.stage', '70,60' => 'File.publish', '70,70' => 'File.return', '70,80' => 'File.deliver', '70,90' => 'File.ack', '70,100' => 'File.reject', '80,10' => 'Stream.qos', '80,11' => 'Stream.qos_ok', '80,20' => 'Stream.consume', '80,21' => 'Stream.consume_ok', '80,30' => 'Stream.cancel', '80,31' => 'Stream.cancel_ok', '80,40' => 'Stream.publish', '80,50' => 'Stream.return', '80,60' => 'Stream.deliver', '90,10' => 'Tx.select', '90,11' => 'Tx.select_ok', '90,20' => 'Tx.commit', '90,21' => 'Tx.commit_ok', '90,30' => 'Tx.rollback', '90,31' => 'Tx.rollback_ok', '100,10' => 'Dtx.select', '100,11' => 'Dtx.select_ok', '100,20' => 'Dtx.start', '100,21' => 'Dtx.start_ok', '110,10' => 'Tunnel.request', '120,10' => 'Test.integer', '120,11' => 'Test.integer_ok', '120,20' => 'Test.string', '120,21' => 'Test.string_ok', '120,30' => 'Test.table', '120,31' => 'Test.table_ok', '120,40' => 'Test.content', '120,41' => 'Test.content_ok', ); } php-amqplib-2.11.0/PhpAmqpLib/Wire/Constants091.php000066400000000000000000000063461356514014400216430ustar00rootroot00000000000000 'FRAME-METHOD', 2 => 'FRAME-HEADER', 3 => 'FRAME-BODY', 8 => 'FRAME-HEARTBEAT', 4096 => 'FRAME-MIN-SIZE', 206 => 'FRAME-END', 501 => 'FRAME-ERROR', ); /** * @var array */ public static $CONTENT_METHODS = array( 0 => '60,40', 1 => '60,50', 2 => '60,60', 3 => '60,71', ); /** * @var array */ public static $CLOSE_METHODS = array( 0 => '10,50', 1 => '20,40', ); /** * @var array */ public static $GLOBAL_METHOD_NAMES = array( '10,10' => 'Connection.start', '10,11' => 'Connection.start_ok', '10,20' => 'Connection.secure', '10,21' => 'Connection.secure_ok', '10,30' => 'Connection.tune', '10,31' => 'Connection.tune_ok', '10,40' => 'Connection.open', '10,41' => 'Connection.open_ok', '10,50' => 'Connection.close', '10,51' => 'Connection.close_ok', '10,60' => 'Connection.blocked', '10,61' => 'Connection.unblocked', '20,10' => 'Channel.open', '20,11' => 'Channel.open_ok', '20,20' => 'Channel.flow', '20,21' => 'Channel.flow_ok', '20,40' => 'Channel.close', '20,41' => 'Channel.close_ok', '30,10' => 'Access.request', '30,11' => 'Access.request_ok', '40,10' => 'Exchange.declare', '40,11' => 'Exchange.declare_ok', '40,20' => 'Exchange.delete', '40,21' => 'Exchange.delete_ok', '40,30' => 'Exchange.bind', '40,31' => 'Exchange.bind_ok', '40,40' => 'Exchange.unbind', '40,51' => 'Exchange.unbind_ok', '50,10' => 'Queue.declare', '50,11' => 'Queue.declare_ok', '50,20' => 'Queue.bind', '50,21' => 'Queue.bind_ok', '50,30' => 'Queue.purge', '50,31' => 'Queue.purge_ok', '50,40' => 'Queue.delete', '50,41' => 'Queue.delete_ok', '50,50' => 'Queue.unbind', '50,51' => 'Queue.unbind_ok', '60,10' => 'Basic.qos', '60,11' => 'Basic.qos_ok', '60,20' => 'Basic.consume', '60,21' => 'Basic.consume_ok', '60,30' => 'Basic.cancel', '60,31' => 'Basic.cancel_ok', '60,40' => 'Basic.publish', '60,50' => 'Basic.return', '60,60' => 'Basic.deliver', '60,70' => 'Basic.get', '60,71' => 'Basic.get_ok', '60,72' => 'Basic.get_empty', '60,80' => 'Basic.ack', '60,90' => 'Basic.reject', '60,100' => 'Basic.recover_async', '60,110' => 'Basic.recover', '60,111' => 'Basic.recover_ok', '60,120' => 'Basic.nack', '90,10' => 'Tx.select', '90,11' => 'Tx.select_ok', '90,20' => 'Tx.commit', '90,21' => 'Tx.commit_ok', '90,30' => 'Tx.rollback', '90,31' => 'Tx.rollback_ok', '85,10' => 'Confirm.select', '85,11' => 'Confirm.select_ok', ); } php-amqplib-2.11.0/PhpAmqpLib/Wire/GenericContent.php000066400000000000000000000131731356514014400223400ustar00rootroot00000000000000 'shortstr' ); /** * @param array $properties Message property content * @param array $propertyTypes Message property definitions */ public function __construct($properties, $propertyTypes = null) { $this->prop_types = !empty($propertyTypes) ? $propertyTypes : self::$propertyDefinitions; if (!empty($properties)) { $this->properties = array_intersect_key($properties, $this->prop_types); } } /** * Check whether a property exists in the 'properties' dictionary * or if present - in the 'delivery_info' dictionary. * * @param string $name * @return bool */ public function has($name) { return isset($this->properties[$name]) || isset($this->delivery_info[$name]); } /** * Look for additional properties in the 'properties' dictionary, * and if present - the 'delivery_info' dictionary. * * @param string $name * @throws \OutOfBoundsException * @return mixed|AMQPChannel */ public function get($name) { if (isset($this->properties[$name])) { return $this->properties[$name]; } if (isset($this->delivery_info[$name])) { return $this->delivery_info[$name]; } throw new \OutOfBoundsException(sprintf( 'No "%s" property', $name )); } /** * Returns the properties content * * @return array */ public function get_properties() { return $this->properties; } /** * Sets a property value * * @param string $name The property name (one of the property definition) * @param mixed $value The property value * @throws \OutOfBoundsException */ public function set($name, $value) { if (!array_key_exists($name, $this->prop_types)) { throw new \OutOfBoundsException(sprintf( 'No "%s" property', $name )); } if (isset($this->properties[$name]) && $this->properties[$name] !== $value || !isset($this->properties[$name])) { $this->serialized_properties = null; } $this->properties[$name] = $value; } /** * Given the raw bytes containing the property-flags and * property-list from a content-frame-header, parse and insert * into a dictionary stored in this object as an attribute named * 'properties'. * * @param AMQPReader $reader * NOTE: do not mutate $reader * @return $this */ public function load_properties(AMQPReader $reader) { // Read 16-bit shorts until we get one with a low bit set to zero $flags = array(); while (true) { $flag_bits = $reader->read_short(); $flags[] = $flag_bits; if (($flag_bits & 1) === 0) { break; } } $shift = 0; $data = array(); foreach ($this->prop_types as $key => $proptype) { if ($shift === 0) { if (!$flags) { break; } $flag_bits = array_shift($flags); $shift = 15; } if ($flag_bits & (1 << $shift)) { $data[$key] = $reader->{'read_' . $proptype}(); } $shift -= 1; } $this->properties = $data; return $this; } /** * Serializes the 'properties' attribute (a dictionary) into the * raw bytes making up a set of property flags and a property * list, suitable for putting into a content frame header. * * @return string * @todo Inject the AMQPWriter to make the method easier to test */ public function serialize_properties() { if (!empty($this->serialized_properties)) { return $this->serialized_properties; } $shift = 15; $flag_bits = 0; $flags = array(); $raw_bytes = new AMQPWriter(); foreach ($this->prop_types as $key => $prototype) { $val = isset($this->properties[$key]) ? $this->properties[$key] : null; // Very important: PHP type eval is weak, use the === to test the // value content. Zero or false value should not be removed if ($val === null) { $shift -= 1; continue; } if ($shift === 0) { $flags[] = $flag_bits; $flag_bits = 0; $shift = 15; } $flag_bits |= (1 << $shift); if ($prototype != 'bit') { $raw_bytes->{'write_' . $prototype}($val); } $shift -= 1; } $flags[] = $flag_bits; $result = new AMQPWriter(); foreach ($flags as $flag_bits) { $result->write_short($flag_bits); } $result->write($raw_bytes->getvalue()); $this->serialized_properties = $result->getvalue(); return $this->serialized_properties; } } php-amqplib-2.11.0/PhpAmqpLib/Wire/IO/000077500000000000000000000000001356514014400172225ustar00rootroot00000000000000php-amqplib-2.11.0/PhpAmqpLib/Wire/IO/AbstractIO.php000066400000000000000000000135311356514014400217310ustar00rootroot00000000000000check_heartbeat(); $this->set_error_handler(); try { $result = $this->do_select($sec, $usec); $this->cleanup_error_handler(); } catch (\ErrorException $e) { throw new AMQPIOWaitException($e->getMessage(), $e->getCode(), $e); } if ($this->canDispatchPcntlSignal) { pcntl_signal_dispatch(); } // no exception and false result - either timeout or signal was sent if ($result === false) { $result = 0; } return $result; } /** * @param int|null $sec * @param int|null $usec * @return int|bool */ abstract protected function do_select($sec, $usec); /** * Set ups the connection. * @return void * @throws \PhpAmqpLib\Exception\AMQPIOException * @throws \PhpAmqpLib\Exception\AMQPRuntimeException */ abstract public function connect(); /** * @return resource */ abstract public function getSocket(); /** * Heartbeat logic: check connection health here * @return void * @throws \PhpAmqpLib\Exception\AMQPRuntimeException */ public function check_heartbeat() { // ignore unless heartbeat interval is set if ($this->heartbeat !== 0 && $this->last_read && $this->last_write) { $t = microtime(true); $t_read = round($t - $this->last_read); $t_write = round($t - $this->last_write); // server has gone away if (($this->heartbeat * 2) < $t_read) { $this->close(); throw new AMQPHeartbeatMissedException('Missed server heartbeat'); } // time for client to send a heartbeat if (($this->heartbeat / 2) < $t_write) { $this->write_heartbeat(); } } } /** * @return $this */ public function disableHeartbeat() { $this->heartbeat = 0; return $this; } /** * @return $this */ public function reenableHeartbeat() { $this->heartbeat = $this->initial_heartbeat; return $this; } /** * Sends a heartbeat message */ protected function write_heartbeat() { $pkt = new AMQPWriter(); $pkt->write_octet(8); $pkt->write_short(0); $pkt->write_long(0); $pkt->write_octet(0xCE); $this->write($pkt->getvalue()); } /** * Begin tracking errors and set the error handler */ protected function set_error_handler() { $this->last_error = null; set_error_handler(array($this, 'error_handler')); } /** * throws an ErrorException if an error was handled * @throws \ErrorException */ protected function cleanup_error_handler() { restore_error_handler(); if ($this->last_error !== null) { throw new \ErrorException( $this->last_error['errstr'], 0, $this->last_error['errno'], $this->last_error['errfile'], $this->last_error['errline'] ); } } /** * Internal error handler to deal with stream and socket errors. * * @param int $errno * @param string $errstr * @param string $errfile * @param int $errline * @param array $errcontext * @return void */ public function error_handler($errno, $errstr, $errfile, $errline, $errcontext = null) { // throwing an exception in an error handler will halt execution // set the last error and continue $this->last_error = compact('errno', 'errstr', 'errfile', 'errline', 'errcontext'); } /** * @return bool */ protected function isPcntlSignalEnabled() { return extension_loaded('pcntl') && function_exists('pcntl_signal_dispatch') && (defined('AMQP_WITHOUT_SIGNALS') ? !AMQP_WITHOUT_SIGNALS : true); } } php-amqplib-2.11.0/PhpAmqpLib/Wire/IO/SocketIO.php000066400000000000000000000224271356514014400214220ustar00rootroot00000000000000host = $host; $this->port = $port; $this->read_timeout = $read_timeout; $this->write_timeout = $write_timeout ?: $read_timeout; $this->heartbeat = $heartbeat; $this->initial_heartbeat = $heartbeat; $this->keepalive = $keepalive; $this->canDispatchPcntlSignal = $this->isPcntlSignalEnabled(); /* TODO FUTURE enable this check php-amqplib/php-amqplib#648, php-amqplib/php-amqplib#666 if ($this->heartbeat !== 0 && ($this->read_timeout <= ($this->heartbeat * 2))) { throw new \InvalidArgumentException('read_timeout must be greater than 2x the heartbeat'); } if ($this->heartbeat !== 0 && ($this->write_timeout <= ($this->heartbeat * 2))) { throw new \InvalidArgumentException('send_timeout must be greater than 2x the heartbeat'); } */ } /** * @inheritdoc */ public function connect() { $this->sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); list($sec, $uSec) = MiscHelper::splitSecondsMicroseconds($this->write_timeout); socket_set_option($this->sock, SOL_SOCKET, SO_SNDTIMEO, array('sec' => $sec, 'usec' => $uSec)); list($sec, $uSec) = MiscHelper::splitSecondsMicroseconds($this->read_timeout); socket_set_option($this->sock, SOL_SOCKET, SO_RCVTIMEO, array('sec' => $sec, 'usec' => $uSec)); $this->set_error_handler(); try { $connected = socket_connect($this->sock, $this->host, $this->port); $this->cleanup_error_handler(); } catch (\ErrorException $e) { $connected = false; } if (!$connected) { $errno = socket_last_error($this->sock); $errstr = socket_strerror($errno); throw new AMQPIOException(sprintf( 'Error Connecting to server (%s): %s', $errno, $errstr ), $errno); } socket_set_block($this->sock); socket_set_option($this->sock, SOL_TCP, TCP_NODELAY, 1); if ($this->keepalive) { $this->enable_keepalive(); } $this->heartbeat = $this->initial_heartbeat; } /** * @inheritdoc */ public function getSocket() { return $this->sock; } /** * @inheritdoc */ public function read($len) { if (is_null($this->sock)) { throw new AMQPSocketException(sprintf( 'Socket was null! Last SocketError was: %s', socket_strerror(socket_last_error()) )); } $this->check_heartbeat(); list($timeout_sec, $timeout_uSec) = MiscHelper::splitSecondsMicroseconds($this->read_timeout); $read_start = microtime(true); $read = 0; $data = ''; while ($read < $len) { $buffer = null; $result = socket_recv($this->sock, $buffer, $len - $read, 0); if ($result === 0) { // From linux recv() manual: // When a stream socket peer has performed an orderly shutdown, // the return value will be 0 (the traditional "end-of-file" return). // http://php.net/manual/en/function.socket-recv.php#47182 $this->close(); throw new AMQPConnectionClosedException('Broken pipe or closed connection'); } if (empty($buffer)) { $read_now = microtime(true); $t_read = $read_now - $read_start; if ($t_read > $this->read_timeout) { throw new AMQPTimeoutException('Too many read attempts detected in SocketIO'); } $this->select($timeout_sec, $timeout_uSec); continue; } $read += mb_strlen($buffer, 'ASCII'); $data .= $buffer; } if (mb_strlen($data, 'ASCII') != $len) { throw new AMQPIOException(sprintf( 'Error reading data. Received %s instead of expected %s bytes', mb_strlen($data, 'ASCII'), $len )); } $this->last_read = microtime(true); return $data; } /** * @inheritdoc */ public function write($data) { $written = 0; $len = mb_strlen($data, 'ASCII'); $write_start = microtime(true); while ($written < $len) { // Null sockets are invalid, throw exception if (is_null($this->sock)) { throw new AMQPSocketException(sprintf( 'Socket was null! Last SocketError was: %s', socket_strerror(socket_last_error()) )); } $this->set_error_handler(); try { $buffer = mb_substr($data, $written, self::BUFFER_SIZE, 'ASCII'); $result = socket_write($this->sock, $buffer, self::BUFFER_SIZE); $this->cleanup_error_handler(); } catch (\ErrorException $e) { $code = socket_last_error($this->sock); $constants = SocketConstants::getInstance(); switch ($code) { case $constants->SOCKET_EPIPE: case $constants->SOCKET_ENETDOWN: case $constants->SOCKET_ENETUNREACH: case $constants->SOCKET_ENETRESET: case $constants->SOCKET_ECONNABORTED: case $constants->SOCKET_ECONNRESET: case $constants->SOCKET_ECONNREFUSED: case $constants->SOCKET_ETIMEDOUT: $this->close(); throw new AMQPConnectionClosedException(socket_strerror($code), $code, $e); default: throw new AMQPIOException(sprintf( 'Error sending data. Last SocketError: %s', socket_strerror($code) ), $code, $e); } } if ($result === false) { throw new AMQPIOException(sprintf( 'Error sending data. Last SocketError: %s', socket_strerror(socket_last_error($this->sock)) )); } $now = microtime(true); if ($result > 0) { $this->last_write = $write_start = $now; $written += $result; } else { if (($now - $write_start) > $this->write_timeout) { throw AMQPTimeoutException::writeTimeout($this->write_timeout); } $this->select_write(); } } } /** * @inheritdoc */ public function close() { $this->disableHeartbeat(); if (is_resource($this->sock)) { socket_close($this->sock); } $this->sock = null; $this->last_read = null; $this->last_write = null; } /** * @inheritdoc */ protected function do_select($sec, $usec) { $read = array($this->sock); $write = null; $except = null; return socket_select($read, $write, $except, $sec, $usec); } /** * @return int|bool */ protected function select_write() { $read = $except = null; $write = array($this->sock); return socket_select($read, $write, $except, 0, 100000); } /** * @throws \PhpAmqpLib\Exception\AMQPIOException */ protected function enable_keepalive() { if (!defined('SOL_SOCKET') || !defined('SO_KEEPALIVE')) { throw new AMQPIOException('Can not enable keepalive: SOL_SOCKET or SO_KEEPALIVE is not defined'); } socket_set_option($this->sock, SOL_SOCKET, SO_KEEPALIVE, 1); } /** * @inheritdoc */ public function error_handler($errno, $errstr, $errfile, $errline, $errcontext = null) { $constants = SocketConstants::getInstance(); // socket_select warning that it has been interrupted by a signal - EINTR if (isset($constants->SOCKET_EINTR) && false !== strrpos($errstr, socket_strerror($constants->SOCKET_EINTR))) { // it's allowed while processing signals return; } parent::error_handler($errno, $errstr, $errfile, $errline, $errcontext); } /** * @inheritdoc */ protected function set_error_handler() { parent::set_error_handler(); socket_clear_error($this->sock); } } php-amqplib-2.11.0/PhpAmqpLib/Wire/IO/StreamIO.php000066400000000000000000000306161356514014400214240ustar00rootroot00000000000000protocol = 'tcp'; $this->host = $host; $this->port = $port; $this->connection_timeout = $connection_timeout; $this->read_timeout = $read_write_timeout; $this->write_timeout = $read_write_timeout; $this->context = $context; $this->keepalive = $keepalive; $this->heartbeat = $heartbeat; $this->initial_heartbeat = $heartbeat; $this->canDispatchPcntlSignal = $this->isPcntlSignalEnabled(); if (!is_resource($this->context) || get_resource_type($this->context) !== 'stream-context') { $this->context = stream_context_create(); } // tcp_nodelay was added in 7.1.0 if (PHP_VERSION_ID >= 70100) { stream_context_set_option($this->context, 'socket', 'tcp_nodelay', true); } $options = stream_context_get_options($this->context); if (!empty($options['ssl'])) { if (isset($ssl_protocol)) { $this->protocol = $ssl_protocol; } else { $this->protocol = 'ssl'; } } } /** * @inheritdoc */ public function connect() { $errstr = $errno = null; $remote = sprintf( '%s://%s:%s', $this->protocol, $this->host, $this->port ); $this->set_error_handler(); try { $this->sock = stream_socket_client( $remote, $errno, $errstr, $this->connection_timeout, STREAM_CLIENT_CONNECT, $this->context ); $this->cleanup_error_handler(); } catch (\ErrorException $e) { throw new AMQPIOException($e->getMessage()); } if (false === $this->sock) { throw new AMQPIOException( sprintf( 'Error Connecting to server(%s): %s ', $errno, $errstr ), $errno ); } if (false === stream_socket_get_name($this->sock, true)) { throw new AMQPIOException( sprintf( 'Connection refused: %s ', $remote ) ); } list($sec, $uSec) = MiscHelper::splitSecondsMicroseconds(max($this->read_timeout, $this->write_timeout)); if (!stream_set_timeout($this->sock, $sec, $uSec)) { throw new AMQPIOException('Timeout could not be set'); } // php cannot capture signals while streams are blocking if ($this->canDispatchPcntlSignal) { stream_set_blocking($this->sock, 0); stream_set_write_buffer($this->sock, 0); if (function_exists('stream_set_read_buffer')) { stream_set_read_buffer($this->sock, 0); } } else { stream_set_blocking($this->sock, true); } if ($this->keepalive) { $this->enable_keepalive(); } $this->heartbeat = $this->initial_heartbeat; } /** * @inheritdoc */ public function read($len) { $this->check_heartbeat(); list($timeout_sec, $timeout_uSec) = MiscHelper::splitSecondsMicroseconds($this->read_timeout); $read_start = microtime(true); $read = 0; $data = ''; while ($read < $len) { if (!is_resource($this->sock) || feof($this->sock)) { $this->close(); throw new AMQPConnectionClosedException('Broken pipe or closed connection'); } $this->set_error_handler(); try { $buffer = fread($this->sock, ($len - $read)); $this->cleanup_error_handler(); } catch (\ErrorException $e) { throw new AMQPDataReadException($e->getMessage(), $e->getCode(), $e); } if ($buffer === false) { throw new AMQPDataReadException('Error receiving data'); } if ($buffer === '') { $read_now = microtime(true); $t_read = $read_now - $read_start; if ($t_read > $this->read_timeout) { throw new AMQPTimeoutException('Too many read attempts detected in StreamIO'); } $this->select($timeout_sec, $timeout_uSec); continue; } $this->last_read = microtime(true); $read_start = $this->last_read; $read += mb_strlen($buffer, 'ASCII'); $data .= $buffer; } if (mb_strlen($data, 'ASCII') !== $len) { throw new AMQPDataReadException( sprintf( 'Error reading data. Received %s instead of expected %s bytes', mb_strlen($data, 'ASCII'), $len ) ); } $this->last_read = microtime(true); return $data; } /** * @inheritdoc */ public function write($data) { $written = 0; $len = mb_strlen($data, 'ASCII'); $write_start = microtime(true); while ($written < $len) { if (!is_resource($this->sock)) { throw new AMQPConnectionClosedException('Broken pipe or closed connection'); } $result = false; $this->set_error_handler(); // OpenSSL's C library function SSL_write() can balk on buffers > 8192 // bytes in length, so we're limiting the write size here. On both TLS // and plaintext connections, the write loop will continue until the // buffer has been fully written. // This behavior has been observed in OpenSSL dating back to at least // September 2002: // http://comments.gmane.org/gmane.comp.encryption.openssl.user/4361 try { $buffer = mb_substr($data, $written, self::BUFFER_SIZE, 'ASCII'); $result = fwrite($this->sock, $buffer); $this->cleanup_error_handler(); } catch (\ErrorException $e) { $code = $this->last_error['errno']; $constants = SocketConstants::getInstance(); switch ($code) { case $constants->SOCKET_EPIPE: case $constants->SOCKET_ENETDOWN: case $constants->SOCKET_ENETUNREACH: case $constants->SOCKET_ENETRESET: case $constants->SOCKET_ECONNABORTED: case $constants->SOCKET_ECONNRESET: case $constants->SOCKET_ECONNREFUSED: case $constants->SOCKET_ETIMEDOUT: $this->close(); throw new AMQPConnectionClosedException(socket_strerror($code), $code, $e); default: throw new AMQPRuntimeException($e->getMessage(), $code, $e); } } if ($result === false) { throw new AMQPRuntimeException('Error sending data'); } if ($this->timed_out()) { throw AMQPTimeoutException::writeTimeout($this->write_timeout); } $now = microtime(true); if ($result > 0) { $this->last_write = $write_start = $now; $written += $result; } else { if (feof($this->sock)) { $this->close(); throw new AMQPConnectionClosedException('Broken pipe or closed connection'); } if (($now - $write_start) > $this->write_timeout) { throw AMQPTimeoutException::writeTimeout($this->write_timeout); } // check stream and prevent from high CPU usage $this->select_write(); } } } /** * @inheritdoc */ public function error_handler($errno, $errstr, $errfile, $errline, $errcontext = null) { $code = $this->extract_error_code($errstr); $constants = SocketConstants::getInstance(); switch ($code) { // fwrite notice that the stream isn't ready - EAGAIN or EWOULDBLOCK case $constants->SOCKET_EAGAIN: case $constants->SOCKET_EWOULDBLOCK: // stream_select warning that it has been interrupted by a signal - EINTR case $constants->SOCKET_EINTR: return; } parent::error_handler($code > 0 ? $code : $errno, $errstr, $errfile, $errline, $errcontext); } public function close() { $this->disableHeartbeat(); if (is_resource($this->sock)) { fclose($this->sock); } $this->sock = null; $this->last_read = null; $this->last_write = null; } /** * @inheritdoc */ public function getSocket() { return $this->sock; } /** * @inheritdoc */ protected function do_select($sec, $usec) { $read = array($this->sock); $write = null; $except = null; return stream_select($read, $write, $except, $sec, $usec); } /** * @return int|bool */ protected function select_write() { $read = $except = null; $write = array($this->sock); return stream_select($read, $write, $except, 0, 100000); } /** * @return mixed */ protected function timed_out() { // get status of socket to determine whether or not it has timed out $info = stream_get_meta_data($this->sock); return $info['timed_out']; } /** * @throws \PhpAmqpLib\Exception\AMQPIOException */ protected function enable_keepalive() { if ($this->protocol === 'ssl') { throw new AMQPIOException('Can not enable keepalive: ssl connection does not support keepalive (#70939)'); } if ($this->protocol === 'tls') { throw new AMQPIOException('Can not enable keepalive: tls connection does not support keepalive (#70939)'); } if (!function_exists('socket_import_stream')) { throw new AMQPIOException('Can not enable keepalive: function socket_import_stream does not exist'); } if (!defined('SOL_SOCKET') || !defined('SO_KEEPALIVE')) { throw new AMQPIOException('Can not enable keepalive: SOL_SOCKET or SO_KEEPALIVE is not defined'); } $socket = socket_import_stream($this->sock); socket_set_option($socket, SOL_SOCKET, SO_KEEPALIVE, 1); } /** * @param string $message * @return int */ protected function extract_error_code($message) { if (0 === strpos($message, 'stream_select():')) { $pattern = '/\s+\[(\d+)\]:\s+/'; } else { $pattern = '/\s+errno=(\d+)\s+/'; } $matches = array(); $result = preg_match($pattern, $message, $matches); if ($result > 0) { return (int)$matches[1]; } return 0; } } php-amqplib-2.11.0/README.md000066400000000000000000000326651356514014400153030ustar00rootroot00000000000000# php-amqplib # [![Latest Version on Packagist][ico-version]][link-packagist] [![Software License][ico-license]](LICENSE) [![Build Status][ico-travis]][link-travis] [![Coverage Status][ico-scrutinizer]][link-scrutinizer] [![Quality Score][ico-code-quality]][link-code-quality] [![Total Downloads][ico-downloads]][link-downloads] This library is a _pure PHP_ implementation of the [AMQP 0-9-1 protocol](http://www.rabbitmq.com/tutorials/amqp-concepts.html). It's been tested against [RabbitMQ](http://www.rabbitmq.com/). The library was used for the PHP examples of [RabbitMQ in Action](http://manning.com/videla/) and the [official RabbitMQ tutorials](http://www.rabbitmq.com/tutorials/tutorial-one-php.html). Please note that this project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms. ## Project Maintainers Thanks to [videlalvaro](https://github.com/videlalvaro) and [postalservice14](https://github.com/postalservice14) for their hard work maintaining php-amqplib! The library wouldn't be where it is without them. The package is now maintained by [nubeiro](https://github.com/nubeiro) and several Pivotal engineers working on RabbitMQ and related projects. ## Supported RabbitMQ Versions ## Starting with version 2.0 this library uses `AMQP 0.9.1` by default and thus requires [RabbitMQ 2.0 or later version](http://www.rabbitmq.com/download.html). Usually server upgrades do not require any application code changes since the protocol changes very infrequently but please conduct your own testing before upgrading. ## Supported RabbitMQ Extensions ## Since the library uses `AMQP 0.9.1` we added support for the following RabbitMQ extensions: * Exchange to Exchange Bindings * Basic Nack * Publisher Confirms * Consumer Cancel Notify Extensions that modify existing methods like `alternate exchanges` are also supported. ### Related libraries * [enqueue/amqp-lib](https://github.com/php-enqueue/amqp-lib) is a [amqp interop](https://github.com/queue-interop/queue-interop#amqp-interop) compatible wrapper. ## Setup ## Ensure you have [composer](http://getcomposer.org) installed, then run the following command: ```bash $ composer require php-amqplib/php-amqplib ``` That will fetch the library and its dependencies inside your vendor folder. Then you can add the following to your .php files in order to use the library ```php require_once __DIR__.'/vendor/autoload.php'; ``` Then you need to `use` the relevant classes, for example: ```php use PhpAmqpLib\Connection\AMQPStreamConnection; use PhpAmqpLib\Message\AMQPMessage; ``` ## Usage ## With RabbitMQ running open two Terminals and on the first one execute the following commands to start the consumer: ```bash $ cd php-amqplib/demo $ php amqp_consumer.php ``` Then on the other Terminal do: ```bash $ cd php-amqplib/demo $ php amqp_publisher.php some text to publish ``` You should see the message arriving to the process on the other Terminal Then to stop the consumer, send to it the `quit` message: ```bash $ php amqp_publisher.php quit ``` If you need to listen to the sockets used to connect to RabbitMQ then see the example in the non blocking consumer. ```bash $ php amqp_consumer_non_blocking.php ``` ## Change log Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently. ## API Documentation ## http://php-amqplib.github.io/php-amqplib/ ## Tutorials ## To not repeat ourselves, if you want to learn more about this library, please refer to the [official RabbitMQ tutorials](http://www.rabbitmq.com/tutorials/tutorial-one-php.html). ## More Examples ## - `amqp_ha_consumer.php`: demos the use of mirrored queues - `amqp_consumer_exclusive.php` and `amqp_publisher_exclusive.php`: demos fanout exchanges using exclusive queues. - `amqp_consumer_fanout_{1,2}.php` and `amqp_publisher_fanout.php`: demos fanout exchanges with named queues. - `basic_get.php`: demos obtaining messages from the queues by using the _basic get_ AMQP call. ## Multiple hosts connections ## If you have a cluster of multiple nodes to which your application can connect, you can start a connection with an array of hosts. To do that you should use the `create_connection` static method. For example: ```php $connection = AMQPStreamConnection::create_connection([ ['host' => HOST1, 'port' => PORT, 'user' => USER, 'password' => PASS, 'vhost' => VHOST], ['host' => HOST2, 'port' => PORT, 'user' => USER, 'password' => PASS, 'vhost' => VHOST] ], $options); ``` This code will try to connect to `HOST1` first, and connect to `HOST2` if the first connection fails. The method returns a connection object for the first successful connection. Should all connections fail it will throw the exception from the last connection attempt. See `demo/amqp_connect_multiple_hosts.php` for more examples. ## Batch Publishing ## Let's say you have a process that generates a bunch of messages that are going to be published to the same `exchange` using the same `routing_key` and options like `mandatory`. Then you could make use of the `batch_basic_publish` library feature. You can batch messages like this: ```php $msg = new AMQPMessage($msg_body); $ch->batch_basic_publish($msg, $exchange); $msg2 = new AMQPMessage($msg_body); $ch->batch_basic_publish($msg2, $exchange); ``` and then send the batch like this: ```php $ch->publish_batch(); ``` ### When do we publish the message batch? ### Let's say our program needs to read from a file and then publish one message per line. Depending on the message size, you will have to decide when it's better to send the batch. You could send it every 50 messages, or every hundred. That's up to you. ## Optimized Message Publishing ## Another way to speed up your message publishing is by reusing the `AMQPMessage` message instances. You can create your new message like this: ```php $properties = array('content_type' => 'text/plain', 'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT); $msg = new AMQPMessage($body, $properties); $ch->basic_publish($msg, $exchange); ``` Now let's say that while you want to change the message body for future messages, you will keep the same properties, that is, your messages will still be `text/plain` and the `delivery_mode` will still be `AMQPMessage::DELIVERY_MODE_PERSISTENT`. If you create a new `AMQPMessage` instance for every published message, then those properties would have to be re-encoded in the AMQP binary format. You could avoid all that by just reusing the `AMQPMessage` and then resetting the message body like this: ```php $msg->setBody($body2); $ch->basic_publish($msg, $exchange); ``` ## Truncating Large Messages ## AMQP imposes no limit on the size of messages; if a very large message is received by a consumer, PHP's memory limit may be reached within the library before the callback passed to `basic_consume` is called. To avoid this, you can call the method `AMQPChannel::setBodySizeLimit(int $bytes)` on your Channel instance. Body sizes exceeding this limit will be truncated, and delivered to your callback with a `AMQPMessage::$is_truncated` flag set to `true`. The property `AMQPMessage::$body_size` will reflect the true body size of a received message, which will be higher than `strlen(AMQPMessage::getBody())` if the message has been truncated. Note that all data above the limit is read from the AMQP Channel and immediately discarded, so there is no way to retrieve it within your callback. If you have another consumer which can handle messages with larger payloads, you can use `basic_reject` or `basic_nack` to tell the server (which still has a complete copy) to forward it to a Dead Letter Exchange. By default, no truncation will occur. To disable truncation on a Channel that has had it enabled, pass `0` (or `null`) to `AMQPChannel::setBodySizeLimit()`. ## Connection recovery ## Some RabbitMQ clients using automated connection recovery mechanisms to reconnect and recover channels and consumers in case of network errors. Since this client is using a single-thread, you can set up connection recovery using exception handling mechanism. Exceptions which might be thrown in case of connection errors: ```php PhpAmqpLib\Exception\AMQPConnectionClosedException PhpAmqpLib\Exception\AMQPIOException \RuntimeException \ErrorException ``` Some other exceptions might be thrown, but connection can still be there. It's always a good idea to clean up an old connection when handling an exception before reconnecting. For example, if you want to set up a recovering connection: ```php $connection = null; $channel = null; while(true){ try { $connection = new AMQPStreamConnection(HOST, PORT, USER, PASS, VHOST); // Your application code goes here. do_something_with_connection($connection); } catch(AMQPRuntimeException $e) { echo $e->getMessage(); cleanup_connection($connection); usleep(WAIT_BEFORE_RECONNECT_uS); } catch(\RuntimeException $e) { cleanup_connection($connection); usleep(WAIT_BEFORE_RECONNECT_uS); } catch(\ErrorException $e) { cleanup_connection($connection); usleep(WAIT_BEFORE_RECONNECT_uS); } } ``` A full example is in `demo/connection_recovery_consume.php`. This code will reconnect and retry the application code every time the exception occurs. Some exceptions can still be thrown and should not be handled as a part of reconnection process, because they might be application errors. This approach makes sense mostly for consumer applications, producers will require some additional application code to avoid publishing the same message multiple times. This was a simplest example, in a real-life application you might want to control retr count and maybe gracefully degrade wait time to reconnection. You can find a more excessive example in [#444](https://github.com/php-amqplib/php-amqplib/issues/444) ## UNIX Signals ## If you have installed [PCNTL extension](http://www.php.net/manual/en/book.pcntl.php) dispatching of signal will be handled when consumer is not processing message. ```php $pcntlHandler = function ($signal) { switch ($signal) { case \SIGTERM: case \SIGUSR1: case \SIGINT: // some stuff before stop consumer e.g. delete lock etc pcntl_signal($signal, SIG_DFL); // restore handler posix_kill(posix_getpid(), $signal); // kill self with signal, see https://www.cons.org/cracauer/sigint.html case \SIGHUP: // some stuff to restart consumer break; default: // do nothing } }; pcntl_signal(\SIGTERM, $pcntlHandler); pcntl_signal(\SIGINT, $pcntlHandler); pcntl_signal(\SIGUSR1, $pcntlHandler); pcntl_signal(\SIGHUP, $pcntlHandler); ``` To disable this feature just define constant `AMQP_WITHOUT_SIGNALS` as `true` ```php ``` ## Benchmarks ## To run the publishing/consume benchmark type: ```bash $ make benchmark ``` ## Tests ## To successfully run the tests you need to first have a stock RabbitMQ broker running locally.Then, run tests like this: ```bash $ make test ``` ## Contributing Please see [CONTRIBUTING](CONTRIBUTING.md) for details. ## Using AMQP 0.8 ## If you still want to use the old version of the protocol then you can do it by setting the following constant in your configuration code: ```php define('AMQP_PROTOCOL', '0.8'); ``` The default value is `'0.9.1'`. ## Providing your own autoloader ## If for some reason you don't want to use composer, then you need to have an autoloader in place fo the library classes. People have [reported](https://github.com/videlalvaro/php-amqplib/issues/61#issuecomment-37855050) to use this [autoloader](https://gist.github.com/jwage/221634) with success. ## Original README: ## Below is the original README file content. Credits goes to the original authors. PHP library implementing Advanced Message Queuing Protocol (AMQP). The library is port of python code of py-amqplib http://barryp.org/software/py-amqplib/ It have been tested with RabbitMQ server. Project home page: http://code.google.com/p/php-amqplib/ For discussion, please join the group: http://groups.google.com/group/php-amqplib-devel For bug reports, please use bug tracking system at the project page. Patches are very welcome! Author: Vadim Zaliva [ico-version]: https://img.shields.io/packagist/v/php-amqplib/php-amqplib.svg?style=flat-square [ico-license]: https://img.shields.io/badge/license-LGPL_2.1-brightgreen.svg?style=flat-square [ico-travis]: https://img.shields.io/travis/php-amqplib/php-amqplib/master.svg?style=flat-square [ico-scrutinizer]: https://img.shields.io/scrutinizer/coverage/g/php-amqplib/php-amqplib.svg?style=flat-square [ico-code-quality]: https://img.shields.io/scrutinizer/g/php-amqplib/php-amqplib.svg?style=flat-square [ico-downloads]: https://img.shields.io/packagist/dt/php-amqplib/php-amqplib.svg?style=flat-square [link-packagist]: https://packagist.org/packages/php-amqplib/php-amqplib [link-travis]: https://travis-ci.org/php-amqplib/php-amqplib [link-scrutinizer]: https://scrutinizer-ci.com/g/php-amqplib/php-amqplib/code-structure [link-code-quality]: https://scrutinizer-ci.com/g/php-amqplib/php-amqplib [link-downloads]: https://packagist.org/packages/php-amqplib/php-amqplib [link-author]: https://github.com/php-amqplib [link-contributors]: ../../contributors php-amqplib-2.11.0/appveyor.yml000066400000000000000000000034701356514014400164040ustar00rootroot00000000000000## https://ci.appveyor.com/project/ramunasd/php-amqplib build: false platform: - x64 - x86 image: Visual Studio 2017 ## Build matrix for lowest and highest possible targets environment: matrix: - dependencies: lowest PHP_VERSION: 5.6 - dependencies: lowest PHP_VERSION: 7.0 - dependencies: current PHP_VERSION: 7.1 - dependencies: current PHP_VERSION: 7.2 - dependencies: highest PHP_VERSION: 7.3 COMPOSER_CACHE: "%USERPROFILE%\\composer" RABBITMQ_VERSION: 3.7.17 ERLANG_VERSION: 10.4 ## Cache CI dependencies cache: - '%COMPOSER_CACHE% -> composer.json' - "%USERPROFILE%\\packages" ## Set up environment variables init: - SET ANSICON=121x90 (121x90) ## Install PHP and composer, and run the appropriate composer command install: - choco config set cacheLocation "%USERPROFILE%\\packages" - ps: Invoke-WebRequest "https://raw.githubusercontent.com/ChadSikorra/ps-install-php/master/Install-PHP.ps1" -OutFile "Install-PHP.ps1" - ps: .\Install-PHP.ps1 -Version $Env:PHP_VERSION -Highest -Arch $Env:PLATFORM -Extensions mbstring,intl,openssl,curl,sockets - cinst composer -i -y - refreshenv - cd %APPVEYOR_BUILD_FOLDER% - SET COMPOSER_NO_INTERACTION=1 - SET COMPOSER_CACHE_DIR=%COMPOSER_CACHE% - IF %dependencies%==lowest composer update --prefer-lowest --no-progress - IF %dependencies%==current composer update --prefer-stable --no-progress - IF %dependencies%==highest composer update --no-progress --prefer-dist - ps: Invoke-WebRequest "https://raw.githubusercontent.com/ramunasd/appveyor-rabbitmq/v1.2/install.ps1" -OutFile "install-rabbitmq.ps1" - ps: .\install-rabbitmq.ps1 ## Run the actual test test_script: - cd %APPVEYOR_BUILD_FOLDER% - php tests/phpinfo.php - vendor/bin/phpunit --exclude-group proxy,signals,linux php-amqplib-2.11.0/benchmark/000077500000000000000000000000001356514014400157425ustar00rootroot00000000000000php-amqplib-2.11.0/benchmark/config.php000066400000000000000000000004141356514014400177170ustar00rootroot00000000000000channel(); $ch->queue_declare($queue, false, false, false, false); $ch->exchange_declare($exchange, 'direct', false, false, false); $ch->queue_bind($queue, $exchange); class Consumer { protected $msgCount = 0; protected $startTime = null; /** * @param \PhpAmqpLib\Message\AMQPMessage $msg */ public function process_message($msg) { if ($this->startTime === null) { $this->startTime = microtime(true); } if ($msg->body == 'quit') { echo sprintf("Pid: %s, Count: %s, Time: %.4f\n", getmypid(), $this->msgCount, microtime(true) - $this->startTime); die; } $this->msgCount++; } } $ch->basic_consume($queue, '', false, true, false, false, array(new Consumer(), 'process_message')); function shutdown($ch, $conn) { $ch->close(); $conn->close(); } register_shutdown_function('shutdown', $ch, $conn); while ($ch->is_consuming()) { $ch->wait(); } php-amqplib-2.11.0/benchmark/file_consume.php000066400000000000000000000023561356514014400211310ustar00rootroot00000000000000channel(); $ch->queue_declare($queue, false, false, false, false); $ch->exchange_declare($exchange, 'direct', false, false, false); $ch->queue_bind($queue, $exchange); class FileConsumer { protected $msgCount = 0; protected $startTime = null; /** * @param \PhpAmqpLib\Message\AMQPMessage $msg */ public function process_message($msg) { if ($this->startTime === null) { $this->startTime = microtime(true); } if ($msg->body == 'quit') { echo sprintf("Pid: %s, Count: %s, Time: %.4f\n", getmypid(), $this->msgCount, microtime(true) - $this->startTime); die; } $this->msgCount++; } } $ch->basic_consume($queue, '', false, true, false, false, array(new FileConsumer(), 'process_message')); function shutdown($ch, $conn) { $ch->close(); $conn->close(); } register_shutdown_function('shutdown', $ch, $conn); while ($ch->is_consuming()) { $ch->wait(); } php-amqplib-2.11.0/benchmark/file_publish.php000066400000000000000000000027411356514014400211240ustar00rootroot00000000000000channel(); $ch->queue_declare($queue, false, false, false, false); $ch->exchange_declare($exchange, 'direct', false, false, false); $ch->queue_bind($queue, $exchange); $max = isset($argv[1]) ? (int) $argv[1] : 1; $msg_size = 1024 * 1024 * 5 + 1; $msg_body = generate_random_content($msg_size); $msg = new AMQPMessage($msg_body); $time = microtime(true); // Publishes $max messages using $msg_body as the content. for ($i = 0; $i < $max; $i++) { $ch->basic_publish($msg, $exchange); } echo microtime(true) - $time, "\n"; $ch->basic_publish(new AMQPMessage('quit'), $exchange); $ch->close(); $conn->close(); php-amqplib-2.11.0/benchmark/producer.php000066400000000000000000000036431356514014400203040ustar00rootroot00000000000000channel(); $ch->queue_declare($queue, false, false, false, false); $ch->exchange_declare($exchange, 'direct', false, false, false); $ch->queue_bind($queue, $exchange); $msg_body = <<basic_publish($msg, $exchange); } echo microtime(true) - $time, "\n"; $ch->basic_publish(new AMQPMessage('quit'), $exchange); $ch->close(); $conn->close(); php-amqplib-2.11.0/benchmark/socket_tmp_produce.php000066400000000000000000000032011356514014400223400ustar00rootroot00000000000000channel(); list($queue,) = $ch->queue_declare("", false, false, true, true); $msg = new AMQPMessage($msg_body); $ch->basic_publish($msg, "", $queue); $ch->close(); } echo microtime(true) - $time, "\n"; $conn->close(); php-amqplib-2.11.0/benchmark/stream_tmp_produce.php000066400000000000000000000031641356514014400223530ustar00rootroot00000000000000channel(); list($queue,) = $ch->queue_declare("", false, false, true, true); $msg = new AMQPMessage($msg_body); $ch->basic_publish($msg, "", $queue); $ch->close(); } echo microtime(true) - $time, "\n"; $conn->close(); php-amqplib-2.11.0/composer.json000066400000000000000000000031731356514014400165360ustar00rootroot00000000000000{ "name": "php-amqplib/php-amqplib", "replace": { "videlalvaro/php-amqplib": "self.version" }, "type": "library", "description": "Formerly videlalvaro/php-amqplib. This library is a pure PHP implementation of the AMQP protocol. It's been tested against RabbitMQ.", "keywords": ["rabbitmq", "message", "queue"], "homepage": "https://github.com/php-amqplib/php-amqplib/", "authors": [ { "name": "Alvaro Videla", "role": "Original Maintainer" }, { "name": "John Kelly", "email": "johnmkelly86@gmail.com", "role": "Maintainer" }, { "name": "Raúl Araya", "email": "nubeiro@gmail.com", "role": "Maintainer" }, { "name": "Luke Bakken", "email": "luke@bakken.io", "role": "Maintainer" } ], "require": { "php": ">=5.6.3", "ext-sockets": "*", "ext-mbstring": "*", "phpseclib/phpseclib": "^2.0.0" }, "require-dev": { "ext-curl": "*", "phpunit/phpunit": "^5.7|^6.5|^7.0", "squizlabs/php_codesniffer": "^2.5", "nategood/httpful": "^0.2.20" }, "autoload": { "psr-4": { "PhpAmqpLib\\": "PhpAmqpLib/" } }, "autoload-dev": { "psr-4": { "PhpAmqpLib\\Tests\\Functional\\": "tests/Functional", "PhpAmqpLib\\Tests\\Unit\\": "tests/Unit" } }, "license": "LGPL-2.1-or-later", "extra": { "branch-alias": { "dev-master": "2.11-dev" } } } php-amqplib-2.11.0/demo/000077500000000000000000000000001356514014400147345ustar00rootroot00000000000000php-amqplib-2.11.0/demo/amqp_connect_multiple_hosts.php000066400000000000000000000065601356514014400232560ustar00rootroot00000000000000 CERTS_PATH . '/rmqca/cacert.pem', 'local_cert' => CERTS_PATH . '/phpcert.pem', 'verify_peer' => true ); /* create_connection takes an array of host configurations and an array of options It will try connecting to hosts one-by-one and return the first successful connection. After reaching the end of the array, it will throw the last connection exception. Options will be mapped to constructor arguments for used connection type. */ $connection = AMQPStreamConnection::create_connection([ ['host' => HOST, 'port' => PORT, 'user' => USER, 'password' => PASS, 'vhost' => VHOST], ['host' => HOST, 'port' => 5673, 'user' => USER, 'password' => PASS, 'vhost' => VHOST], ['host' => HOST, 'port' => 5674, 'user' => USER, 'password' => PASS, 'vhost' => VHOST] ], [ 'insist' => false, 'login_method' => 'AMQPLAIN', 'login_response' => null, 'locale' => 'en_US', 'connection_timeout' => 3.0, 'read_write_timeout' => 10.0, 'context' => null, 'keepalive' => false, 'heartbeat' => 5 ]); // Use empty options array for defaults $connection = AMQPStreamConnection::create_connection([ ['host' => HOST, 'port' => PORT, 'user' => USER, 'password' => PASS, 'vhost' => VHOST], ['host' => HOST, 'port' => 5673, 'user' => USER, 'password' => PASS, 'vhost' => VHOST], ['host' => HOST, 'port' => 5674, 'user' => USER, 'password' => PASS, 'vhost' => VHOST] ], []); // Options keys are different for different connection types $connection = AMQPSocketConnection::create_connection([ ['host' => HOST, 'port' => PORT, 'user' => USER, 'password' => PASS, 'vhost' => VHOST], ['host' => HOST, 'port' => 5673, 'user' => USER, 'password' => PASS, 'vhost' => VHOST], ['host' => HOST, 'port' => 5674, 'user' => USER, 'password' => PASS, 'vhost' => VHOST] ], [ 'insist' => false, 'login_method' => 'AMQPLAIN', 'login_response' => null, 'locale' => 'en_US', 'read_timeout' => 10, 'keepalive' => false, 'write_timeout' => 10, 'heartbeat' => 5 ]); // Use empty options array for defaults $connection = AMQPSocketConnection::create_connection([ ['host' => HOST, 'port' => PORT, 'user' => USER, 'password' => PASS, 'vhost' => VHOST], ['host' => HOST, 'port' => 5673, 'user' => USER, 'password' => PASS, 'vhost' => VHOST], ['host' => HOST, 'port' => 5674, 'user' => USER, 'password' => PASS, 'vhost' => VHOST] ], []); /* For SSL connections you should set 'ssl_options' in the options array */ $ssl_connection = AMQPSSLConnection::create_connection([ ['host' => HOST, 'port' => PORT, 'user' => USER, 'password' => PASS, 'vhost' => VHOST], ['host' => HOST, 'port' => 5673, 'user' => USER, 'password' => PASS, 'vhost' => VHOST], ['host' => HOST, 'port' => 5674, 'user' => USER, 'password' => PASS, 'vhost' => VHOST] ], [ 'ssl_options' => $ssl_options ]); /** * @param \PhpAmqpLib\Connection\AbstractConnection $connection */ function shutdown($connection) { $connection->close(); } register_shutdown_function('shutdown', $connection); register_shutdown_function('shutdown', $ssl_connection); while (true) { } php-amqplib-2.11.0/demo/amqp_consumer.php000066400000000000000000000050101356514014400203120ustar00rootroot00000000000000channel(); /* The following code is the same both in the consumer and the producer. In this way we are sure we always have a queue to consume from and an exchange where to publish messages. */ /* name: $queue passive: false durable: true // the queue will survive server restarts exclusive: false // the queue can be accessed in other channels auto_delete: false //the queue won't be deleted once the channel is closed. */ $channel->queue_declare($queue, false, true, false, false); /* name: $exchange type: direct passive: false durable: true // the exchange will survive server restarts auto_delete: false //the exchange won't be deleted once the channel is closed. */ $channel->exchange_declare($exchange, AMQPExchangeType::DIRECT, false, true, false); $channel->queue_bind($queue, $exchange); /** * @param \PhpAmqpLib\Message\AMQPMessage $message */ function process_message($message) { echo "\n--------\n"; echo $message->body; echo "\n--------\n"; $message->delivery_info['channel']->basic_ack($message->delivery_info['delivery_tag']); // Send a message with the string "quit" to cancel the consumer. if ($message->body === 'quit') { $message->delivery_info['channel']->basic_cancel($message->delivery_info['consumer_tag']); } } /* queue: Queue from where to get the messages consumer_tag: Consumer identifier no_local: Don't receive messages published by this consumer. no_ack: If set to true, automatic acknowledgement mode will be used by this consumer. See https://www.rabbitmq.com/confirms.html for details. exclusive: Request exclusive consumer access, meaning only this consumer can access the queue nowait: callback: A PHP Callback */ $channel->basic_consume($queue, $consumerTag, false, false, false, false, 'process_message'); /** * @param \PhpAmqpLib\Channel\AMQPChannel $channel * @param \PhpAmqpLib\Connection\AbstractConnection $connection */ function shutdown($channel, $connection) { $channel->close(); $connection->close(); } register_shutdown_function('shutdown', $channel, $connection); // Loop as long as the channel has callbacks registered while ($channel ->is_consuming()) { $channel->wait(); } php-amqplib-2.11.0/demo/amqp_consumer_exclusive.php000066400000000000000000000056261356514014400224160ustar00rootroot00000000000000channel(); /* name: $queue // should be unique in fanout exchange. Let RabbitMQ create // a queue name for us passive: false // don't check if a queue with the same name exists durable: false // the queue will not survive server restarts exclusive: true // the queue can not be accessed by other channels auto_delete: true // the queue will be deleted once the channel is closed. */ list($queueName, ,) = $channel->queue_declare($queue, false, false, true, true); /* name: $exchange type: direct passive: false // don't check if an exchange with the same name exists durable: false // the exchange will not survive server restarts auto_delete: true // the exchange will be deleted once the channel is closed. */ $channel->exchange_declare($exchange, AMQPExchangeType::FANOUT, false, false, true); $channel->queue_bind($queueName, $exchange); /** * @param \PhpAmqpLib\Message\AMQPMessage $message */ function process_message($message) { echo "\n--------\n"; echo $message->body; echo "\n--------\n"; $message->delivery_info['channel']->basic_ack($message->delivery_info['delivery_tag']); // Send a message with the string "quit" to cancel the consumer. if ($message->body === 'quit') { $message->delivery_info['channel']->basic_cancel($message->delivery_info['consumer_tag']); } } /* queue: Queue from where to get the messages consumer_tag: Consumer identifier no_local: Don't receive messages published by this consumer. no_ack: If set to true, automatic acknowledgement mode will be used by this consumer. See https://www.rabbitmq.com/confirms.html for details. exclusive: Request exclusive consumer access, meaning only this consumer can access the queue nowait: don't wait for a server response. In case of error the server will raise a channel exception callback: A PHP Callback */ $channel->basic_consume($queueName, $consumerTag, false, false, true, false, 'process_message'); /** * @param \PhpAmqpLib\Channel\AMQPChannel $channel * @param \PhpAmqpLib\Connection\AbstractConnection $connection */ function shutdown($channel, $connection) { $channel->close(); $connection->close(); } register_shutdown_function('shutdown', $channel, $connection); // Loop as long as the channel has callbacks registered while ($channel->is_consuming()) { $channel->wait(); } php-amqplib-2.11.0/demo/amqp_consumer_fanout_1.php000066400000000000000000000053231356514014400221150ustar00rootroot00000000000000channel(); /* name: $queue // should be unique in fanout exchange. passive: false // don't check if a queue with the same name exists durable: false // the queue will not survive server restarts exclusive: false // the queue might be accessed by other channels auto_delete: true //the queue will be deleted once the channel is closed. */ $channel->queue_declare($queue, false, false, false, true); /* name: $exchange type: direct passive: false // don't check if a exchange with the same name exists durable: false // the exchange will not survive server restarts auto_delete: true //the exchange will be deleted once the channel is closed. */ $channel->exchange_declare($exchange, AMQPExchangeType::FANOUT, false, false, true); $channel->queue_bind($queue, $exchange); /** * @param \PhpAmqpLib\Message\AMQPMessage $message */ function process_message($message) { echo "\n--------\n"; echo $message->body; echo "\n--------\n"; $message->delivery_info['channel']->basic_ack($message->delivery_info['delivery_tag']); // Send a message with the string "quit" to cancel the consumer. if ($message->body === 'quit') { $message->delivery_info['channel']->basic_cancel($message->delivery_info['consumer_tag']); } } /* queue: Queue from where to get the messages consumer_tag: Consumer identifier no_local: Don't receive messages published by this consumer. no_ack: If set to true, automatic acknowledgement mode will be used by this consumer. See https://www.rabbitmq.com/confirms.html for details. exclusive: Request exclusive consumer access, meaning only this consumer can access the queue nowait: don't wait for a server response. In case of error the server will raise a channel exception callback: A PHP Callback */ $channel->basic_consume($queue, $consumerTag, false, false, false, false, 'process_message'); /** * @param \PhpAmqpLib\Channel\AMQPChannel $channel * @param \PhpAmqpLib\Connection\AbstractConnection $connection */ function shutdown($channel, $connection) { $channel->close(); $connection->close(); } register_shutdown_function('shutdown', $channel, $connection); // Loop as long as the channel has callbacks registered while ($channel->is_consuming()) { $channel->wait(); } php-amqplib-2.11.0/demo/amqp_consumer_fanout_2.php000066400000000000000000000053671356514014400221260ustar00rootroot00000000000000channel(); /* name: $queue // should be unique in fanout exchange. passive: false // don't check if a queue with the same name exists durable: false // the queue will not survive server restarts exclusive: false // the queue might be accessed by other channels auto_delete: true //the queue will be deleted once the channel is closed. */ $channel->queue_declare($queue, false, false, false, true); /* name: $exchange type: direct passive: false // don't check if a exchange with the same name exists durable: false // the exchange will not survive server restarts auto_delete: true //the exchange will be deleted once the channel is closed. */ $channel->exchange_declare($exchange, AMQPExchangeType::FANOUT, false, false, true); $channel->queue_bind($queue, $exchange); /** * @param \PhpAmqpLib\Message\AMQPMessage $message */ function process_message($message) { echo "\n--------\n"; echo $message->body; echo "\n--------\n"; $message->delivery_info['channel']->basic_ack($message->delivery_info['delivery_tag']); // Send a message with the string "quit" to cancel the consumer. if ($message->body === 'quit') { $message->delivery_info['channel']->basic_cancel($message->delivery_info['consumer_tag']); } } /* queue: Queue from where to get the messages consumer_tag: Consumer identifier no_local: Don't receive messages published by this consumer. no_ack: If set to true, automatic acknowledgement mode will be used by this consumer. See https://www.rabbitmq.com/confirms.html for details. exclusive: Request exclusive consumer access, meaning only this consumer can access the queue nowait: don't wait for a server response. In case of error the server will raise a channel exception callback: A PHP Callback */ $channel->basic_consume($queue, $consumerTag, false, false, false, false, 'process_message'); /** * @param \PhpAmqpLib\Channel\AMQPChannel $channel * @param \PhpAmqpLib\Connection\AbstractConnection $connection */ function shutdown($channel, $connection) { $channel->close(); $connection->close(); } register_shutdown_function('shutdown', $channel, $connection); // Loop as long as the channel has callbacks registered while ($channel->is_consuming()) { $channel->wait(); } php-amqplib-2.11.0/demo/amqp_consumer_non_blocking.php000066400000000000000000000050761356514014400230500ustar00rootroot00000000000000channel(); /* The following code is the same both in the consumer and the producer. In this way we are sure we always have a queue to consume from and an exchange where to publish messages. */ /* name: $queue passive: false durable: true // the queue will survive server restarts exclusive: false // the queue can be accessed in other channels auto_delete: false //the queue won't be deleted once the channel is closed. */ $channel->queue_declare($queue, false, true, false, false); /* name: $exchange type: direct passive: false durable: true // the exchange will survive server restarts auto_delete: false //the exchange won't be deleted once the channel is closed. */ $channel->exchange_declare($exchange, AMQPExchangeType::DIRECT, false, true, false); $channel->queue_bind($queue, $exchange); /** * @param \PhpAmqpLib\Message\AMQPMessage $message */ function process_message($message) { echo "\n--------\n"; echo $message->body; echo "\n--------\n"; $message->delivery_info['channel']->basic_ack($message->delivery_info['delivery_tag']); // Send a message with the string "quit" to cancel the consumer. if ($message->body === 'quit') { $message->delivery_info['channel']->basic_cancel($message->delivery_info['consumer_tag']); } } /* queue: Queue from where to get the messages consumer_tag: Consumer identifier no_local: Don't receive messages published by this consumer. no_ack: If set to true, automatic acknowledgement mode will be used by this consumer. See https://www.rabbitmq.com/confirms.html for details. exclusive: Request exclusive consumer access, meaning only this consumer can access the queue nowait: callback: A PHP Callback */ $channel->basic_consume($queue, $consumerTag, false, false, false, false, 'process_message'); /** * @param \PhpAmqpLib\Channel\AMQPChannel $channel * @param \PhpAmqpLib\Connection\AbstractConnection $connection */ function shutdown($channel, $connection) { $channel->close(); $connection->close(); } register_shutdown_function('shutdown', $channel, $connection); // Loop as long as the channel has callbacks registered while ($channel->is_consuming()) { $channel->wait(null, true); // do something else usleep(300000); } php-amqplib-2.11.0/demo/amqp_consumer_signals.php000066400000000000000000000137101356514014400220400ustar00rootroot00000000000000 false, 'verify_peer_name' => false ]; } $this->connection = new PhpAmqpLib\Connection\AMQPSSLConnection( HOST, PORT, USER, PASS, VHOST, $ssl, [ 'read_write_timeout' => 30, // needs to be at least 2x heartbeat 'keepalive' => false, // doesn't work with ssl connections 'heartbeat' => 15 ] ); } /** * Signal handler * * @param int $signalNumber * @return void */ public function signalHandler($signalNumber) { echo 'Handling signal: #' . $signalNumber . PHP_EOL; global $consumer; switch ($signalNumber) { case SIGTERM: // 15 : supervisor default stop case SIGQUIT: // 3 : kill -s QUIT $consumer->stopHard(); break; case SIGINT: // 2 : ctrl+c $consumer->stop(); break; case SIGHUP: // 1 : kill -s HUP $consumer->restart(); break; case SIGUSR1: // 10 : kill -s USR1 // send an alarm in 1 second pcntl_alarm(1); break; case SIGUSR2: // 12 : kill -s USR2 // send an alarm in 10 seconds pcntl_alarm(10); break; default: break; } } /** * Alarm handler * * @param int $signalNumber * @return void */ public function alarmHandler($signalNumber) { echo 'Handling alarm: #' . $signalNumber . PHP_EOL; echo memory_get_usage(true) . PHP_EOL; return; } /** * Message handler * * @param PhpAmqpLib\Message\AMQPMessage $message * @return void */ public function messageHandler(PhpAmqpLib\Message\AMQPMessage $message) { echo "\n--------\n"; echo $message->body; echo "\n--------\n"; $message->delivery_info['channel']->basic_ack($message->delivery_info['delivery_tag']); if ($message->body === 'quit') { $message->delivery_info['channel']->basic_cancel($message->delivery_info['consumer_tag']); } } /** * Start a consumer on an existing connection * * @return void */ public function start() { if ($this->restart) { echo 'Restarting consumer.' . PHP_EOL; $this->restart = false; } else { echo 'Starting consumer.' . PHP_EOL; } $exchange = 'router'; $queue = 'msgs'; $this->channel = $this->connection->channel(); $this->channel->queue_declare($queue, false, true, false, false); $this->channel->exchange_declare($exchange, AMQPExchangeType::DIRECT, false, true, false); $this->channel->queue_bind($queue, $exchange); $this->channel->basic_consume( $queue, $this->consumerTag, false, false, false, false, [$this,'messageHandler'], null, ['x-cancel-on-ha-failover' => ['t', true]] // fail over to another node ); echo 'Enter wait.' . PHP_EOL; while ($this->channel->is_consuming()) { $this->channel->wait(); } echo 'Exit wait.' . PHP_EOL; } /** * Restart the consumer on an existing connection */ public function restart() { $this->stopSoft(); $this->restart = true; } /** * Close the connection to the server */ public function stopHard() { echo 'Stopping consumer by closing connection.' . PHP_EOL; $this->connection->close(); } /** * Close the channel to the server */ public function stopSoft() { echo 'Stopping consumer by closing channel.' . PHP_EOL; $this->channel->close(); } /** * Tell the server you are going to stop consuming * It will finish up the last message and not send you any more */ public function stop() { echo 'Stopping consumer by cancel command.' . PHP_EOL; // this gets stuck and will not exit without the last two parameters set $this->channel->basic_cancel($this->consumerTag, false, true); } public function shouldRestart() { return $this->restart; } /** * Current connection * * @var PhpAmqpLib\Connection\AMQPSSLConnection */ protected $connection = null; /** * Current channel * * @var PhpAmqpLib\Channel\AMQPChannel */ protected $channel = null; /** * Consumer tag * * @var string */ protected $consumerTag = 'consumer'; /** * @var bool */ protected $restart = false; } $consumer = new Consumer(); do { $consumer->start(); } while ($consumer->shouldRestart()); php-amqplib-2.11.0/demo/amqp_ha_consumer.php000066400000000000000000000061561356514014400207760ustar00rootroot00000000000000channel(); /* The following code is the same both in the consumer and the producer. In this way we are sure we always have a queue to consume from and an exchange where to publish messages. */ $haConnection = new AMQPTable(array('x-ha-policy' => 'all')); $haSpecificConnection = new AMQPTable(array( 'x-ha-policy' => 'nodes', 'x-ha-policy-params' => array( 'rabbit@' . HOST, 'hare@' . HOST, ), )); /* name: $queue passive: false durable: true // the queue will survive server restarts exclusive: false // the queue can be accessed in other channels auto_delete: false //the queue won't be deleted once the channel is closed. nowait: false // Doesn't wait on replies for certain things. parameters: array // How you send certain extra data to the queue declare */ $channel->queue_declare($queue, false, false, false, false, false, $haConnection); $channel->queue_declare($specificQueue, false, false, false, false, false, $haSpecificConnection); /* name: $exchange type: direct passive: false durable: true // the exchange will survive server restarts auto_delete: false //the exchange won't be deleted once the channel is closed. */ $channel->exchange_declare($exchange, AMQPExchangeType::DIRECT, false, true, false); $channel->queue_bind($queue, $exchange); $channel->queue_bind($specificQueue, $exchange); /** * @param \PhpAmqpLib\Message\AMQPMessage $message */ function process_message($message) { echo "\n--------\n"; echo $message->body; echo "\n--------\n"; $message->delivery_info['channel']->basic_ack($message->delivery_info['delivery_tag']); // Send a message with the string "quit" to cancel the consumer. if ($message->body === 'quit') { $message->delivery_info['channel']->basic_cancel($message->delivery_info['consumer_tag']); } } /* queue: Queue from where to get the messages consumer_tag: Consumer identifier no_local: Don't receive messages published by this consumer. no_ack: If set to true, automatic acknowledgement mode will be used by this consumer. See https://www.rabbitmq.com/confirms.html for details. exclusive: Request exclusive consumer access, meaning only this consumer can access the queue nowait: callback: A PHP Callback */ $channel->basic_consume($queue, $consumerTag, false, false, false, false, 'process_message'); /** * @param \PhpAmqpLib\Channel\AMQPChannel $channel * @param \PhpAmqpLib\Connection\AbstractConnection $connection */ function shutdown($channel, $connection) { $channel->close(); $connection->close(); } register_shutdown_function('shutdown', $channel, $connection); // Loop as long as the channel has callbacks registered while ($channel->is_consuming()) { $channel->wait(); } php-amqplib-2.11.0/demo/amqp_message_headers_recv.php000066400000000000000000000030271356514014400226230ustar00rootroot00000000000000channel(); $exchangeName = 'topic_headers_test'; $channel->exchange_declare($exchangeName, AMQPExchangeType::HEADERS); list($queueName, ,) = $channel->queue_declare('', false, false, true); $bindArguments = []; foreach ($headers as $header) { list ($key, $value) = explode('=', $header, 2); $bindArguments[$key] = $value; } $channel->queue_bind($queueName, $exchangeName, '', false, new AMQPTable($bindArguments)); echo ' [*] Waiting for logs. To exit press CTRL+C', "\n"; $callback = function (AMQPMessage $message) { echo PHP_EOL . ' [x] ', $message->delivery_info['routing_key'], ':', $message->body, "\n"; echo 'Message headers follows' . PHP_EOL; var_dump($message->get('application_headers')->getNativeData()); echo PHP_EOL; }; $channel->basic_consume($queueName, '', false, true, true, false, $callback); while ($channel->is_consuming()) { try { $channel->wait(null, false, 2); } catch (AMQPTimeoutException $exception) { } echo '*' . PHP_EOL; } $channel->close(); $connection->close(); php-amqplib-2.11.0/demo/amqp_message_headers_snd.php000066400000000000000000000036221356514014400224510ustar00rootroot00000000000000channel(); $exchangeName = 'topic_headers_test'; $channel->exchange_declare($exchangeName, AMQPExchangeType::HEADERS); $data = implode(' ', array_slice($argv, 2)); if (empty($data)) { $data = "Hello World!"; } $message = new AMQPMessage($data); $headers = new Wire\AMQPTable(array( 'foo' => 'bar', 'table' => array('figuf', 'ghf' => 5, 5 => 675), 'num1' => -4294967295, 'num2' => 5, 'num3' => -2147483648, 'true' => true, 'false' => false, 'void' => null, 'date' => new DateTime('now', new DateTimeZone('UTC')), 'array' => array(null, 'foo', 'bar', 5, 5674625, 'ttt', array(5, 8, 2)), 'arr_with_tbl' => array( 'bar', 5, array( 'foo', 57, 'ee', array( 'foo' => 'bar', 'baz' => 'boo', 'arr' => array(1, 2, 3, true, new DateTime('now', new DateTimeZone('UTC'))), ), ), 67, array( 'foo' => 'bar', 5 => 7, 8 => 'boo', 'baz' => 3, ), ), '64bitint' => 9223372036854775807, '64bit_uint' => '18446744073709600000', '64bitint_neg' => -pow(2, 40), )); $headers->set('shortshort', -5, Wire\AMQPTable::T_INT_SHORTSHORT); $headers->set('short', -1024, Wire\AMQPTable::T_INT_SHORT); echo PHP_EOL . PHP_EOL . 'SENDING MESSAGE WITH HEADERS' . PHP_EOL . PHP_EOL; var_dump($headers->getNativeData()); echo PHP_EOL; $message->set('application_headers', $headers); $channel->basic_publish($message, $exchangeName); echo ' [x] Sent :', $data, PHP_EOL; $channel->close(); $connection->close(); php-amqplib-2.11.0/demo/amqp_publisher.php000066400000000000000000000026421356514014400204640ustar00rootroot00000000000000channel(); /* The following code is the same both in the consumer and the producer. In this way we are sure we always have a queue to consume from and an exchange where to publish messages. */ /* name: $queue passive: false durable: true // the queue will survive server restarts exclusive: false // the queue can be accessed in other channels auto_delete: false //the queue won't be deleted once the channel is closed. */ $channel->queue_declare($queue, false, true, false, false); /* name: $exchange type: direct passive: false durable: true // the exchange will survive server restarts auto_delete: false //the exchange won't be deleted once the channel is closed. */ $channel->exchange_declare($exchange, AMQPExchangeType::DIRECT, false, true, false); $channel->queue_bind($queue, $exchange); $messageBody = implode(' ', array_slice($argv, 1)); $message = new AMQPMessage($messageBody, array('content_type' => 'text/plain', 'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT)); $channel->basic_publish($message, $exchange); $channel->close(); $connection->close(); php-amqplib-2.11.0/demo/amqp_publisher_exclusive.php000066400000000000000000000016031356514014400225470ustar00rootroot00000000000000channel(); /* name: $exchange type: fanout passive: false // don't check if an exchange with the same name exists durable: false // the exchange won't survive server restarts auto_delete: true // the exchange will be deleted once the channel is closed. */ $channel->exchange_declare($exchange, AMQPExchangeType::FANOUT, false, false, true); $messageBody = implode(' ', array_slice($argv, 1)); $message = new AMQPMessage($messageBody, array('content_type' => 'text/plain')); $channel->basic_publish($message, $exchange); $channel->close(); $connection->close(); php-amqplib-2.11.0/demo/amqp_publisher_fanout.php000066400000000000000000000015701356514014400220370ustar00rootroot00000000000000channel(); /* name: $exchange type: fanout passive: false // don't check is an exchange with the same name exists durable: false // the exchange won't survive server restarts auto_delete: true //the exchange will be deleted once the channel is closed. */ $channel->exchange_declare($exchange, AMQPExchangeType::FANOUT, false, false, true); $messageBody = implode(' ', array_slice($argv, 1)); $message = new AMQPMessage($messageBody, array('content_type' => 'text/plain')); $channel->basic_publish($message, $exchange); $channel->close(); $connection->close(); php-amqplib-2.11.0/demo/amqp_publisher_with_confirms.php000066400000000000000000000036511356514014400234200ustar00rootroot00000000000000channel(); $channel->set_ack_handler( function (AMQPMessage $message) { echo "Message acked with content " . $message->body . PHP_EOL; } ); $channel->set_nack_handler( function (AMQPMessage $message) { echo "Message nacked with content " . $message->body . PHP_EOL; } ); /* * bring the channel into publish confirm mode. * if you would call $ch->tx_select() before or after you brought the channel into this mode * the next call to $ch->wait() would result in an exception as the publish confirm mode and transactions * are mutually exclusive */ $channel->confirm_select(); /* name: $exchange type: fanout passive: false // don't check if an exchange with the same name exists durable: false // the exchange won't survive server restarts auto_delete: true //the exchange will be deleted once the channel is closed. */ $channel->exchange_declare($exchange, AMQPExchangeType::FANOUT, false, false, true); $i = 1; $msg = new AMQPMessage($i, array('content_type' => 'text/plain')); $channel->basic_publish($msg, $exchange); /* * watching the amqp debug output you can see that the server will ack the message with delivery tag 1 and the * multiple flag probably set to false */ $channel->wait_for_pending_acks(); while ($i <= 11) { $msg = new AMQPMessage($i++, array('content_type' => 'text/plain')); $channel->basic_publish($msg, $exchange); } /* * you do not have to wait for pending acks after each message sent. in fact it will be much more efficient * to wait for as many messages to be acked as possible. */ $channel->wait_for_pending_acks(); $channel->close(); $connection->close(); php-amqplib-2.11.0/demo/amqp_publisher_with_confirms_mandatory.php000066400000000000000000000042511356514014400254730ustar00rootroot00000000000000channel(); $channel->set_ack_handler( function (AMQPMessage $message) { echo "Message acked with content " . $message->body . PHP_EOL; } ); $channel->set_nack_handler( function (AMQPMessage $message) { echo "Message nacked with content " . $message->body . PHP_EOL; } ); $channel->set_return_listener( function ($replyCode, $replyText, $exchange, $routingKey, AMQPMessage $message) { echo "Message returned with content " . $message->body . PHP_EOL; } ); /* * bring the channel into publish confirm mode. * if you would call $ch->tx_select() befor or after you brought the channel into this mode * the next call to $ch->wait() would result in an exception as the publish confirm mode and transactions * are mutually exclusive */ $channel->confirm_select(); /* name: $exchange type: fanout passive: false // don't check if an exchange with the same name exists durable: false // the exchange won't survive server restarts auto_delete: true //the exchange will be deleted once the channel is closed. */ $channel->exchange_declare($exchange, AMQPExchangeType::FANOUT, false, false, true); $i = 1; $message = new AMQPMessage($i, array('content_type' => 'text/plain')); $channel->basic_publish($message, $exchange, null, true); /* * watching the amqp debug output you can see that the server will ack the message with delivery tag 1 and the * multiple flag probably set to false */ $channel->wait_for_pending_acks_returns(); while ($i <= 11) { $message = new AMQPMessage($i++, array('content_type' => 'text/plain')); $channel->basic_publish($message, $exchange, null, true); } /* * you do not have to wait for pending acks after each message sent. in fact it will be much more efficient * to wait for as many messages to be acked as possible. */ $channel->wait_for_pending_acks_returns(); $channel->close(); $connection->close(); php-amqplib-2.11.0/demo/basic_cancel.php000066400000000000000000000015301356514014400200320ustar00rootroot00000000000000channel(); $channel->queue_declare($queue); $waitHelper = new Wait091(); $channel->basic_consume($queue, $consumerTag); $channel->queue_delete($queue); /* * if the server is capable of sending basic.cancel messages, too, this call will end in an AMQPBasicCancelException. */ $channel->wait(array($waitHelper->get_wait('basic.cancel'))); php-amqplib-2.11.0/demo/basic_get.php000066400000000000000000000027371356514014400173760ustar00rootroot00000000000000channel(); /* The following code is the same both in the consumer and the producer. In this way we are sure we always have a queue to consume from and an exchange where to publish messages. */ /* name: $queue passive: false durable: true // the queue will survive server restarts exclusive: false // the queue can be accessed in other channels auto_delete: false //the queue won't be deleted once the channel is closed. */ $channel->queue_declare($queue, false, true, false, false); /* name: $exchange type: direct passive: false durable: true // the exchange will survive server restarts auto_delete: false //the exchange won't be deleted once the channel is closed. */ $channel->exchange_declare($exchange, AMQPExchangeType::DIRECT, false, true, false); $channel->queue_bind($queue, $exchange); $toSend = new AMQPMessage('test message', array('content_type' => 'text/plain', 'delivery_mode' => 2)); $channel->basic_publish($toSend, $exchange); $message = $channel->basic_get($queue); $channel->basic_ack($message->delivery_info['delivery_tag']); var_dump($message->body); $channel->close(); $connection->close(); php-amqplib-2.11.0/demo/basic_nack.php000066400000000000000000000035121356514014400175230ustar00rootroot00000000000000channel(); $channel->queue_declare($queue, false, true, false, false); $channel->exchange_declare($exchange, AMQPExchangeType::DIRECT, false, true, false); $channel->queue_bind($queue, $exchange); /** * @param \PhpAmqpLib\Message\AMQPMessage $message */ function process_message($message) { if ($message->body == 'good') { $message->delivery_info['channel']->basic_ack($message->delivery_info['delivery_tag']); } else { $message->delivery_info['channel']->basic_nack($message->delivery_info['delivery_tag']); } // Send a message with the string "quit" to cancel the consumer. if ($message->body === 'quit') { $message->delivery_info['channel']->basic_cancel($message->delivery_info['consumer_tag']); } } $channel->basic_consume($queue, $consumerTag, false, false, false, false, 'process_message'); /** * @param \PhpAmqpLib\Channel\AMQPChannel $channel * @param \PhpAmqpLib\Connection\AbstractConnection $connection */ function shutdown($channel, $connection) { $channel->close(); $connection->close(); } register_shutdown_function('shutdown', $channel, $connection); // Loop as long as the channel has callbacks registered while ($channel->is_consuming()) { $channel->wait(); } php-amqplib-2.11.0/demo/basic_qos.php000066400000000000000000000012251356514014400174100ustar00rootroot00000000000000channel(); $channel->queue_declare('qos_queue', false, true, false, false); $channel->basic_qos(null, 10000, null); function process_message($message) { $message->delivery_info['channel']->basic_ack($message->delivery_info['delivery_tag']); } $channel->basic_consume('qos_queue', '', false, false, false, false, 'process_message'); while ($channel->is_consuming()) { // After 10 seconds there will be a timeout exception. $channel->wait(null, false, 10); } php-amqplib-2.11.0/demo/basic_return.php000066400000000000000000000022171356514014400201270ustar00rootroot00000000000000channel(); // declare exchange but don`t bind any queue $channel->exchange_declare('hidden_exchange', AMQPExchangeType::TOPIC); $message = new AMQPMessage("Hello World!"); echo " [x] Sent non-mandatory ..."; $channel->basic_publish( $message, 'hidden_exchange', 'rkey' ); echo " done.\n"; $wait = true; $returnListener = function ( $replyCode, $replyText, $exchange, $routingKey, $message ) use ($wait) { $GLOBALS['wait'] = false; echo "return: ", $replyCode, "\n", $replyText, "\n", $exchange, "\n", $routingKey, "\n", $message->body, "\n"; }; $channel->set_return_listener($returnListener); echo " [x] Sent mandatory ... "; $channel->basic_publish( $message, 'hidden_exchange', 'rkey', true ); echo " done.\n"; while ($wait) { $channel->wait(); } $channel->close(); $connection->close(); php-amqplib-2.11.0/demo/batch_publish.php000066400000000000000000000043311356514014400202550ustar00rootroot00000000000000channel(); $channel->queue_declare($queue, false, false, false, false); $channel->exchange_declare($exchange, AMQPExchangeType::DIRECT, false, false, false); $channel->queue_bind($queue, $exchange); $messageBody = <<batch_basic_publish($message, $exchange); if ($i % $batch == 0) { $channel->publish_batch(); } } $channel->publish_batch(); echo microtime(true) - $time, "\n"; $channel->basic_publish(new AMQPMessage('quit'), $exchange); $channel->close(); $connection->close(); php-amqplib-2.11.0/demo/config.php000066400000000000000000000002061356514014400167100ustar00rootroot00000000000000 HOST, 'port' => PORT1, 'user' => USER, 'password' => PASS, 'vhost' => VHOST], ['host' => HOST, 'port' => PORT2, 'user' => USER, 'password' => PASS, 'vhost' => VHOST], ['host' => HOST, 'port' => PORT3, 'user' => USER, 'password' => PASS, 'vhost' => VHOST] ], [ 'insist' => false, 'login_method' => 'AMQPLAIN', 'login_response' => null, 'locale' => 'en_US', 'connection_timeout' => 3.0, 'read_write_timeout' => 3.0, 'context' => null, 'keepalive' => false, 'heartbeat' => 0 ]); } function cleanup_connection($connection) { // Connection might already be closed. // Ignoring exceptions. try { if($connection !== null) { $connection->close(); } } catch (\ErrorException $e) { } } $connection = null; while(true){ try { $connection = connect(); register_shutdown_function('shutdown', $connection); // Your application code goes here. do_something_with_connection($connection); } catch(AMQPRuntimeException $e) { echo $e->getMessage() . PHP_EOL; cleanup_connection($connection); usleep(WAIT_BEFORE_RECONNECT_uS); } catch(\RuntimeException $e) { echo "Runtime exception " . PHP_EOL; cleanup_connection($connection); usleep(WAIT_BEFORE_RECONNECT_uS); } catch(\ErrorException $e) { echo "Error exception " . PHP_EOL; cleanup_connection($connection); usleep(WAIT_BEFORE_RECONNECT_uS); } } function do_something_with_connection($connection) { $queue = 'receive'; $consumerTag = 'consumer'; $channel = $connection->channel(); $channel->queue_declare($queue, false, true, false, false); $channel->basic_consume($queue, $consumerTag, false, false, false, false, 'process_message'); while ($channel->is_consuming()) { $channel->wait(); } } /** * @param \PhpAmqpLib\Message\AMQPMessage $message */ function process_message($message) { echo "\n--------\n"; echo $message->body; echo "\n--------\n"; $message->delivery_info['channel']->basic_ack($message->delivery_info['delivery_tag']); // Send a message with the string "quit" to cancel the consumer. if ($message->body === 'quit') { $message->delivery_info['channel']->basic_cancel($message->delivery_info['consumer_tag']); } } /** * @param \PhpAmqpLib\Connection\AbstractConnection $connection */ function shutdown($connection) { $connection->close(); } php-amqplib-2.11.0/demo/delayed_message.php000066400000000000000000000050741356514014400205660ustar00rootroot00000000000000channel(); /** * Declares exchange * * @param string $exchange * @param string $type * @param bool $passive * @param bool $durable * @param bool $auto_delete * @param bool $internal * @param bool $nowait * @return mixed|null */ $channel->exchange_declare('delayed_exchange', 'x-delayed-message', false, true, false, false, false, new AMQPTable(array( "x-delayed-type" => AMQPExchangeType::FANOUT ))); /** * Declares queue, creates if needed * * @param string $queue * @param bool $passive * @param bool $durable * @param bool $exclusive * @param bool $auto_delete * @param bool $nowait * @param null $arguments * @param null $ticket * @return mixed|null */ $channel->queue_declare('delayed_queue', false, false, false, false, false, new AMQPTable(array( "x-dead-letter-exchange" => "delayed" ))); $channel->queue_bind('delayed_queue', 'delayed_exchange'); $headers = new AMQPTable(array("x-delay" => 7000)); $message = new AMQPMessage('hello', array('delivery_mode' => 2)); $message->set('application_headers', $headers); $channel->basic_publish($message, 'delayed_exchange'); function process_message(AMQPMessage $message) { $headers = $message->get('application_headers'); $nativeData = $headers->getNativeData(); var_dump($nativeData['x-delay']); $message->delivery_info['channel']->basic_ack($message->delivery_info['delivery_tag']); } /* queue: Queue from where to get the messages consumer_tag: Consumer identifier no_local: Don't receive messages published by this consumer. no_ack: If set to true, automatic acknowledgement mode will be used by this consumer. See https://www.rabbitmq.com/confirms.html for details. exclusive: Request exclusive consumer access, meaning only this consumer can access the queue nowait: callback: A PHP Callback */ $channel->basic_consume('delayed_queue', '', false, false, false, false, 'process_message'); /** * @param \PhpAmqpLib\Channel\AMQPChannel $channel * @param \PhpAmqpLib\Connection\AbstractConnection $connection */ function shutdown($channel, $connection) { $channel->close(); $connection->close(); } register_shutdown_function('shutdown', $channel, $connection); // Loop as long as the channel has callbacks registered while ($channel->is_consuming()) { $channel->wait(); } php-amqplib-2.11.0/demo/e2e_bindings.php000066400000000000000000000011551356514014400177770ustar00rootroot00000000000000channel(); $channel->exchange_declare($source, AMQPExchangeType::TOPIC, false, true, false); $channel->exchange_declare($destination, AMQPExchangeType::DIRECT, false, true, false); $channel->exchange_bind($destination, $source); $channel->exchange_unbind($source, $destination); $channel->close(); $connection->close(); php-amqplib-2.11.0/demo/queue_arguments.php000066400000000000000000000010701356514014400206540ustar00rootroot00000000000000channel(); $channel->queue_declare('test11', false, true, false, false, false, new AMQPTable(array( "x-dead-letter-exchange" => "t_test1", "x-message-ttl" => 15000, "x-expires" => 16000 ))); $channel->close(); $connection->close(); php-amqplib-2.11.0/demo/ssl_connection.php000066400000000000000000000011241356514014400204630ustar00rootroot00000000000000 CERTS_PATH . '/rmqca/cacert.pem', 'local_cert' => CERTS_PATH . '/phpcert.pem', 'verify_peer' => true ); $connection = new AMQPSSLConnection(HOST, PORT, USER, PASS, VHOST, $sslOptions); /** * @param \PhpAmqpLib\Connection\AbstractConnection $connection */ function shutdown($connection) { $connection->close(); } register_shutdown_function('shutdown', $connection); while (true) { } php-amqplib-2.11.0/doc/000077500000000000000000000000001356514014400145555ustar00rootroot00000000000000php-amqplib-2.11.0/doc/AMQPMessage.md000066400000000000000000000034541356514014400171500ustar00rootroot00000000000000# AMQPMessage # ## Message Durability ## When creating a new message set the `delivery_mode` to `AMQPMessage::DELIVERY_MODE_PERSISTENT`: $msg = new AMQPMessage( $msg_body, array( 'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT ) ); ## Supported message properties ## "content_type" => "shortstr", "content_encoding" => "shortstr", "application_headers" => "table", "delivery_mode" => "octet", "priority" => "octet", "correlation_id" => "shortstr", "reply_to" => "shortstr", "expiration" => "shortstr", "message_id" => "shortstr", "timestamp" => "timestamp", "type" => "shortstr", "user_id" => "shortstr", "app_id" => "shortstr", "cluster_id" => "shortst" Getting message properties: $msg->get('correlation_id'); $msg->get('delivery_mode'); ## Acknowledging messages ## You can acknowledge messages by sending a `basic_ack` on the channel: $msg->delivery_info['channel']-> basic_ack($msg->delivery_info['delivery_tag']); Keep in mind that the `delivery_tag` has to be valid so most of the time just use the one provide by the server. If you don't want to access the `delivery_info` array directly you can also use `$msg->get('delivery_tag')` but keep in mind that's slower than just accessing the array by key. ## What's on the delivery info? ## When RabbitMQ delivers a message the library will add the following `delivery_info` to the message: $delivery_info = array( "channel" => $this, "consumer_tag" => $consumer_tag, "delivery_tag" => $delivery_tag, "redelivered" => $redelivered, "exchange" => $exchange, "routing_key" => $routing_key ); They can also be accessed using the AMQPMessage::get function: $msg->get('channel'); php-amqplib-2.11.0/docker-compose.yaml000066400000000000000000000010251356514014400176040ustar00rootroot00000000000000version: '3' services: php: build: ./docker/php volumes: - .:/src working_dir: /src environment: - TEST_RABBITMQ_HOST=rabbitmq - TOXIPROXY_HOST=proxy - TOXIPROXY_AMQP_PORT=5673 links: - rabbitmq depends_on: - rabbitmq - proxy entrypoint: ['tail', '-f', '/dev/null'] rabbitmq: image: rabbitmq:3-management ports: - "5672:5672" proxy: image: shopify/toxiproxy ports: - "8474:8474" - "5673:5673" links: - rabbitmq php-amqplib-2.11.0/docker/000077500000000000000000000000001356514014400152575ustar00rootroot00000000000000php-amqplib-2.11.0/docker/php/000077500000000000000000000000001356514014400160465ustar00rootroot00000000000000php-amqplib-2.11.0/docker/php/Dockerfile000066400000000000000000000005401356514014400200370ustar00rootroot00000000000000FROM php:5.6-cli RUN apt update && \ apt -qy install git unzip zlib1g-dev && \ docker-php-ext-install sockets pcntl zip WORKDIR /src RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" && \ php composer-setup.php && \ php -r "unlink('composer-setup.php');" && \ mv composer.phar /usr/local/bin/composer php-amqplib-2.11.0/docs/000077500000000000000000000000001356514014400147405ustar00rootroot00000000000000php-amqplib-2.11.0/phpunit.xml.dist000066400000000000000000000026701356514014400171700ustar00rootroot00000000000000 tests/Unit tests/Functional PhpAmqpLib/ PhpAmqpLib/Helper/Protocol PhpAmqpLib/Wire/Constants080.php PhpAmqpLib/Wire/Constants091.php php-amqplib-2.11.0/spec/000077500000000000000000000000001356514014400147425ustar00rootroot00000000000000php-amqplib-2.11.0/spec/amqp-rabbitmq-0.8.json000066400000000000000000001136011356514014400206770ustar00rootroot00000000000000{ "name": "AMQP", "major-version": 8, "minor-version": 0, "port": 5672, "copyright": [ "Copyright (C) 2008-2012 VMware, Inc.\n", "\n", "Permission is hereby granted, free of charge, to any person\n", "obtaining a copy of this file (the \"Software\"), to deal in the\n", "Software without restriction, including without limitation the \n", "rights to use, copy, modify, merge, publish, distribute, \n", "sublicense, and/or sell copies of the Software, and to permit \n", "persons to whom the Software is furnished to do so, subject to \n", "the following conditions:\n", "\n", "The above copyright notice and this permission notice shall be\n", "included in all copies or substantial portions of the Software.\n", "\n", "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n", "EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n", "OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n", "NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n", "HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n", "WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n", "FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n", "OTHER DEALINGS IN THE SOFTWARE.\n", "\n", "Class information entered from amqp_xml0-8.pdf and domain types from amqp-xml-doc0-9.pdf\n", "\n", "b3cb053f15e7b98808c0ccc67f23cb3e amqp_xml0-8.pdf\n", "http://www.twiststandards.org/index.php?option=com_docman&task=cat_view&gid=28&&Itemid=90\n", "8444db91e2949dbecfb2585e9eef6d64 amqp-xml-doc0-9.pdf\n", "https://jira.amqp.org/confluence/download/attachments/720900/amqp-xml-doc0-9.pdf?version=1\n"], "domains": [ ["access-ticket", "short"], ["bit", "bit"], ["channel-id", "longstr"], ["class-id", "short"], ["consumer-tag", "shortstr"], ["delivery-tag", "longlong"], ["destination", "shortstr"], ["duration", "longlong"], ["exchange-name", "shortstr"], ["known-hosts", "shortstr"], ["long", "long"], ["longlong", "longlong"], ["longstr", "longstr"], ["method-id", "short"], ["no-ack", "bit"], ["no-local", "bit"], ["octet", "octet"], ["offset", "longlong"], ["path", "shortstr"], ["peer-properties", "table"], ["queue-name", "shortstr"], ["redelivered", "bit"], ["reference", "longstr"], ["reject-code", "short"], ["reject-text", "shortstr"], ["reply-code", "short"], ["reply-text", "shortstr"], ["security-token", "longstr"], ["short", "short"], ["shortstr", "shortstr"], ["table", "table"], ["timestamp", "timestamp"] ], "constants": [ {"name": "FRAME-METHOD", "value": 1}, {"name": "FRAME-HEADER", "value": 2}, {"name": "FRAME-BODY", "value": 3}, {"name": "FRAME-OOB-METHOD", "value": 4}, {"name": "FRAME-OOB-HEADER", "value": 5}, {"name": "FRAME-OOB-BODY", "value": 6}, {"name": "FRAME-TRACE", "value": 7}, {"name": "FRAME-HEARTBEAT", "value": 8}, {"name": "FRAME-MIN-SIZE", "value": 4096}, {"name": "FRAME-END", "value": 206}, {"name": "REPLY-SUCCESS", "value": 200}, {"name": "NOT-DELIVERED", "value": 310, "class": "soft-error"}, {"name": "CONTENT-TOO-LARGE", "value": 311, "class": "soft-error"}, {"name": "NO-ROUTE", "value": 312, "class": "soft-error"}, {"name": "NO-CONSUMERS", "value": 313, "class": "soft-error"}, {"name": "ACCESS-REFUSED", "value": 403, "class": "soft-error"}, {"name": "NOT-FOUND", "value": 404, "class": "soft-error"}, {"name": "RESOURCE-LOCKED", "value": 405, "class": "soft-error"}, {"name": "PRECONDITION-FAILED", "value": 406, "class": "soft-error"}, {"name": "CONNECTION-FORCED", "value": 320, "class": "hard-error"}, {"name": "INVALID-PATH", "value": 402, "class": "hard-error"}, {"name": "FRAME-ERROR", "value": 501, "class": "hard-error"}, {"name": "SYNTAX-ERROR", "value": 502, "class": "hard-error"}, {"name": "COMMAND-INVALID", "value": 503, "class": "hard-error"}, {"name": "CHANNEL-ERROR", "value": 504, "class": "hard-error"}, {"name": "UNEXPECTED-FRAME", "value": 505, "class": "hard-error"}, {"name": "RESOURCE-ERROR", "value": 506, "class": "hard-error"}, {"name": "NOT-ALLOWED", "value": 530, "class": "hard-error"}, {"name": "NOT-IMPLEMENTED", "value": 540, "class": "hard-error"}, {"name": "INTERNAL-ERROR", "value": 541, "class": "hard-error"} ], "classes": [ { "id": 10, "methods": [{"id": 10, "arguments": [{"type": "octet", "name": "version-major", "default-value": 0}, {"type": "octet", "name": "version-minor", "default-value": 8}, {"domain": "peer-properties", "name": "server-properties"}, {"type": "longstr", "name": "mechanisms", "default-value": "PLAIN"}, {"type": "longstr", "name": "locales", "default-value": "en_US"}], "name": "start", "synchronous" : true}, {"id": 11, "arguments": [{"domain": "peer-properties", "name": "client-properties"}, {"type": "shortstr", "name": "mechanism", "default-value": "PLAIN"}, {"type": "longstr", "name": "response"}, {"type": "shortstr", "name": "locale", "default-value": "en_US"}], "name": "start-ok"}, {"id": 20, "arguments": [{"type": "longstr", "name": "challenge"}], "name": "secure", "synchronous" : true}, {"id": 21, "arguments": [{"type": "longstr", "name": "response"}], "name": "secure-ok"}, {"id": 30, "arguments": [{"type": "short", "name": "channel-max", "default-value": 0}, {"type": "long", "name": "frame-max", "default-value": 0}, {"type": "short", "name": "heartbeat", "default-value": 0}], "name": "tune", "synchronous" : true}, {"id": 31, "arguments": [{"type": "short", "name": "channel-max", "default-value": 0}, {"type": "long", "name": "frame-max", "default-value": 0}, {"type": "short", "name": "heartbeat", "default-value": 0}], "name": "tune-ok"}, {"id": 40, "arguments": [{"type": "shortstr", "name": "virtual-host", "default-value": "/"}, {"type": "shortstr", "name": "capabilities", "default-value": ""}, {"type": "bit", "name": "insist", "default-value": false}], "name": "open", "synchronous" : true}, {"id": 41, "arguments": [{"type": "shortstr", "name": "known-hosts", "default-value": ""}], "name": "open-ok"}, {"id": 50, "arguments": [{"type": "shortstr", "name": "host"}, {"type": "shortstr", "name": "known-hosts", "default-value": ""}], "name": "redirect"}, {"id": 60, "arguments": [{"type": "short", "name": "reply-code"}, {"type": "shortstr", "name": "reply-text", "default-value": ""}, {"type": "short", "name": "class-id"}, {"type": "short", "name": "method-id"}], "name": "close", "synchronous" : true}, {"id": 61, "arguments": [], "name": "close-ok"}], "name": "connection", "properties": [] }, { "id": 20, "methods": [{"id": 10, "arguments": [{"type": "shortstr", "name": "out-of-band", "default-value": ""}], "name": "open", "synchronous" : true}, {"id": 11, "arguments": [], "name": "open-ok"}, {"id": 20, "arguments": [{"type": "bit", "name": "active"}], "name": "flow", "synchronous" : true}, {"id": 21, "arguments": [{"type": "bit", "name": "active"}], "name": "flow-ok"}, {"id": 30, "arguments": [{"type": "short", "name": "reply-code"}, {"type": "shortstr", "name": "reply-text", "default-value": ""}, {"type": "table", "name": "details", "default-value": {}}], "name": "alert"}, {"id": 40, "arguments": [{"type": "short", "name": "reply-code"}, {"type": "shortstr", "name": "reply-text", "default-value": ""}, {"type": "short", "name": "class-id"}, {"type": "short", "name": "method-id"}], "name": "close", "synchronous" : true}, {"id": 41, "arguments": [], "name": "close-ok"}], "name": "channel" }, { "id": 30, "methods": [{"id": 10, "arguments": [{"type": "shortstr", "name": "realm", "default-value": "/data"}, {"type": "bit", "name": "exclusive", "default-value": false}, {"type": "bit", "name": "passive", "default-value": true}, {"type": "bit", "name": "active", "default-value": true}, {"type": "bit", "name": "write", "default-value": true}, {"type": "bit", "name": "read", "default-value": true}], "name": "request", "synchronous" : true}, {"id": 11, "arguments": [{"type": "short", "name": "ticket", "default-value": 1}], "name": "request-ok"}], "name": "access" }, { "id": 40, "methods": [{"id": 10, "arguments": [{"type": "short", "name": "ticket", "default-value": 1}, {"type": "shortstr", "name": "exchange"}, {"type": "shortstr", "name": "type", "default-value": "direct"}, {"type": "bit", "name": "passive", "default-value": false}, {"type": "bit", "name": "durable", "default-value": false}, {"type": "bit", "name": "auto-delete", "default-value": false}, {"type": "bit", "name": "internal", "default-value": false}, {"type": "bit", "name": "nowait", "default-value": false}, {"type": "table", "name": "arguments", "default-value": {}}], "name": "declare", "synchronous" : true}, {"id": 11, "arguments": [], "name": "declare-ok"}, {"id": 20, "arguments": [{"type": "short", "name": "ticket", "default-value": 1}, {"type": "shortstr", "name": "exchange"}, {"type": "bit", "name": "if-unused", "default-value": false}, {"type": "bit", "name": "nowait", "default-value": false}], "name": "delete", "synchronous" : true}, {"id": 21, "arguments": [], "name": "delete-ok"}], "name": "exchange" }, { "id": 50, "methods": [{"id": 10, "arguments": [{"type": "short", "name": "ticket", "default-value": 1}, {"type": "shortstr", "name": "queue", "default-value": ""}, {"type": "bit", "name": "passive", "default-value": false}, {"type": "bit", "name": "durable", "default-value": false}, {"type": "bit", "name": "exclusive", "default-value": false}, {"type": "bit", "name": "auto-delete", "default-value": false}, {"type": "bit", "name": "nowait", "default-value": false}, {"type": "table", "name": "arguments", "default-value": {}}], "name": "declare", "synchronous" : true}, {"id": 11, "arguments": [{"type": "shortstr", "name": "queue"}, {"type": "long", "name": "message-count"}, {"type": "long", "name": "consumer-count"}], "name": "declare-ok"}, {"id": 20, "arguments": [{"type": "short", "name": "ticket", "default-value": 1}, {"type": "shortstr", "name": "queue", "default-value": ""}, {"type": "shortstr", "name": "exchange"}, {"type": "shortstr", "name": "routing-key", "default-value": ""}, {"type": "bit", "name": "nowait", "default-value": false}, {"type": "table", "name": "arguments", "default-value": {}}], "name": "bind", "synchronous" : true}, {"id": 21, "arguments": [], "name": "bind-ok"}, {"id": 30, "arguments": [{"type": "short", "name": "ticket", "default-value": 1}, {"type": "shortstr", "name": "queue", "default-value": ""}, {"type": "bit", "name": "nowait", "default-value": false}], "name": "purge", "synchronous" : true}, {"id": 31, "arguments": [{"type": "long", "name": "message-count"}], "name": "purge-ok"}, {"id": 40, "arguments": [{"type": "short", "name": "ticket", "default-value": 1}, {"type": "shortstr", "name": "queue", "default-value": ""}, {"type": "bit", "name": "if-unused", "default-value": false}, {"type": "bit", "name": "if-empty", "default-value": false}, {"type": "bit", "name": "nowait", "default-value": false}], "name": "delete", "synchronous" : true}, {"id": 41, "arguments": [{"type": "long", "name": "message-count"}], "name": "delete-ok"}, {"id": 50, "arguments": [{"type": "short", "name": "ticket", "default-value": 1}, {"type": "shortstr", "name": "queue", "default-value": ""}, {"type": "shortstr", "name": "exchange"}, {"type": "shortstr", "name": "routing-key", "default-value": ""}, {"type": "table", "name": "arguments", "default-value": {}}], "name": "unbind", "synchronous" : true}, {"id": 51, "arguments": [], "name": "unbind-ok"} ], "name": "queue" }, { "id": 60, "methods": [{"id": 10, "arguments": [{"type": "long", "name": "prefetch-size", "default-value": 0}, {"type": "short", "name": "prefetch-count", "default-value": 0}, {"type": "bit", "name": "global", "default-value": false}], "name": "qos", "synchronous" : true}, {"id": 11, "arguments": [], "name": "qos-ok"}, {"id": 20, "arguments": [{"domain": "access-ticket", "name": "ticket", "default-value": 1}, {"type": "shortstr", "name": "queue", "default-value": ""}, {"type": "shortstr", "name": "consumer-tag", "default-value": ""}, {"type": "bit", "name": "no-local", "default-value": false}, {"type": "bit", "name": "no-ack", "default-value": false}, {"type": "bit", "name": "exclusive", "default-value": false}, {"type": "bit", "name": "nowait", "default-value": false}], "name": "consume", "synchronous" : true}, {"id": 21, "arguments": [{"type": "shortstr", "name": "consumer-tag"}], "name": "consume-ok"}, {"id": 30, "arguments": [{"type": "shortstr", "name": "consumer-tag"}, {"type": "bit", "name": "nowait", "default-value": false}], "name": "cancel", "synchronous" : true}, {"id": 31, "arguments": [{"type": "shortstr", "name": "consumer-tag"}], "name": "cancel-ok"}, {"content": true, "id": 40, "arguments": [{"type": "short", "name": "ticket", "default-value": 1}, {"type": "shortstr", "name": "exchange", "default-value": ""}, {"type": "shortstr", "name": "routing-key", "default-value": ""}, {"type": "bit", "name": "mandatory", "default-value": false}, {"type": "bit", "name": "immediate", "default-value": false}], "name": "publish"}, {"content": true, "id": 50, "arguments": [{"type": "short", "name": "reply-code"}, {"type": "shortstr", "name": "reply-text", "default-value": ""}, {"type": "shortstr", "name": "exchange"}, {"type": "shortstr", "name": "routing-key"}], "name": "return"}, {"content": true, "id": 60, "arguments": [{"type": "shortstr", "name": "consumer-tag"}, {"type": "longlong", "name": "delivery-tag"}, {"type": "bit", "name": "redelivered", "default-value": false}, {"type": "shortstr", "name": "exchange"}, {"type": "shortstr", "name": "routing-key"}], "name": "deliver"}, {"id": 70, "arguments": [{"type": "short", "name": "ticket", "default-value": 1}, {"type": "shortstr", "name": "queue", "default-value": ""}, {"type": "bit", "name": "no-ack", "default-value": false}], "name": "get", "synchronous" : true}, {"content": true, "id": 71, "arguments": [{"type": "longlong", "name": "delivery-tag"}, {"type": "bit", "name": "redelivered", "default-value": false}, {"type": "shortstr", "name": "exchange"}, {"type": "shortstr", "name": "routing-key"}, {"type": "long", "name": "message-count"}], "name": "get-ok"}, {"id": 72, "arguments": [{"type": "shortstr", "name": "cluster-id", "default-value": ""}], "name": "get-empty"}, {"id": 80, "arguments": [{"type": "longlong", "name": "delivery-tag", "default-value": 0}, {"type": "bit", "name": "multiple", "default-value": false}], "name": "ack"}, {"id": 90, "arguments": [{"type": "longlong", "name": "delivery-tag"}, {"type": "bit", "name": "requeue", "default-value": true}], "name": "reject"}, {"id": 100, "arguments": [{"type": "bit", "name": "requeue", "default-value": false}], "name": "recover-async"}, {"id": 110, "arguments": [{"type": "bit", "name": "requeue", "default-value": false}], "name": "recover", "synchronous" : true}, {"id": 111, "arguments": [], "name": "recover-ok"}], "name": "basic", "properties": [{"type": "shortstr", "name": "content-type"}, {"type": "shortstr", "name": "content-encoding"}, {"type": "table", "name": "headers"}, {"type": "octet", "name": "delivery-mode"}, {"type": "octet", "name": "priority"}, {"type": "shortstr", "name": "correlation-id"}, {"type": "shortstr", "name": "reply-to"}, {"type": "shortstr", "name": "expiration"}, {"type": "shortstr", "name": "message-id"}, {"type": "timestamp", "name": "timestamp"}, {"type": "shortstr", "name": "type"}, {"type": "shortstr", "name": "user-id"}, {"type": "shortstr", "name": "app-id"}, {"type": "shortstr", "name": "cluster-id"}] }, { "id": 70, "methods": [{"id": 10, "arguments": [{"type": "long", "name": "prefetch-size", "default-value": 0}, {"type": "short", "name": "prefetch-count", "default-value": 0}, {"type": "bit", "name": "global", "default-value": false}], "name": "qos", "synchronous" : true}, {"id": 11, "arguments": [], "name": "qos-ok"}, {"id": 20, "arguments": [{"type": "short", "name": "ticket", "default-value": 1}, {"type": "shortstr", "name": "queue", "default-value": ""}, {"type": "shortstr", "name": "consumer-tag", "default-value": ""}, {"type": "bit", "name": "no-local", "default-value": false}, {"type": "bit", "name": "no-ack", "default-value": false}, {"type": "bit", "name": "exclusive", "default-value": false}, {"type": "bit", "name": "nowait", "default-value": false}], "name": "consume", "synchronous" : true}, {"id": 21, "arguments": [{"type": "shortstr", "name": "consumer-tag"}], "name": "consume-ok"}, {"id": 30, "arguments": [{"type": "shortstr", "name": "consumer-tag"}, {"type": "bit", "name": "nowait", "default-value": false}], "name": "cancel", "synchronous" : true}, {"id": 31, "arguments": [{"type": "shortstr", "name": "consumer-tag"}], "name": "cancel-ok"}, {"id": 40, "arguments": [{"type": "shortstr", "name": "identifier"}, {"type": "longlong", "name": "content-size"}], "name": "open", "synchronous" : true}, {"id": 41, "arguments": [{"type": "longlong", "name": "staged-size"}], "name": "open-ok"}, {"content": true, "id": 50, "arguments": [], "name": "stage"}, {"id": 60, "arguments": [{"type": "short", "name": "ticket", "default-value": 1}, {"type": "shortstr", "name": "exchange", "default-value": ""}, {"type": "shortstr", "name": "routing-key", "default-value": ""}, {"type": "bit", "name": "mandatory", "default-value": false}, {"type": "bit", "name": "immediate", "default-value": false}, {"type": "shortstr", "name": "identifier"}], "name": "publish"}, {"content": true, "id": 70, "arguments": [{"type": "short", "name": "reply-code", "default-value": 200}, {"type": "shortstr", "name": "reply-text", "default-value": ""}, {"type": "shortstr", "name": "exchange"}, {"type": "shortstr", "name": "routing-key"}], "name": "return"}, {"id": 80, "arguments": [{"type": "shortstr", "name": "consumer-tag"}, {"type": "longlong", "name": "delivery-tag"}, {"type": "bit", "name": "redelivered", "default-value": false}, {"type": "shortstr", "name": "exchange"}, {"type": "shortstr", "name": "routing-key"}, {"type": "shortstr", "name": "identifier"}], "name": "deliver"}, {"id": 90, "arguments": [{"type": "longlong", "name": "delivery-tag", "default-value": 0}, {"type": "bit", "name": "multiple", "default-value": false}], "name": "ack"}, {"id": 100, "arguments": [{"type": "longlong", "name": "delivery-tag"}, {"type": "bit", "name": "requeue", "default-value": true}], "name": "reject"}], "name": "file", "properties": [{"type": "shortstr", "name": "content-type"}, {"type": "shortstr", "name": "content-encoding"}, {"type": "table", "name": "headers"}, {"type": "octet", "name": "priority"}, {"type": "shortstr", "name": "reply-to"}, {"type": "shortstr", "name": "message-id"}, {"type": "shortstr", "name": "filename"}, {"type": "timestamp", "name": "timestamp"}, {"type": "shortstr", "name": "cluster-id"}] }, { "id": 80, "methods": [{"id": 10, "arguments": [{"type": "long", "name": "prefetch-size", "default-value": 0}, {"type": "short", "name": "prefetch-count", "default-value": 0}, {"type": "long", "name": "consume-rate", "default-value": 0}, {"type": "bit", "name": "global", "default-value": false}], "name": "qos", "synchronous" : true}, {"id": 11, "arguments": [], "name": "qos-ok"}, {"id": 20, "arguments": [{"type": "short", "name": "ticket", "default-value": 1}, {"type": "shortstr", "name": "queue", "default-value": ""}, {"type": "shortstr", "name": "consumer-tag", "default-value": ""}, {"type": "bit", "name": "no-local", "default-value": false}, {"type": "bit", "name": "exclusive", "default-value": false}, {"type": "bit", "name": "nowait", "default-value": false}], "name": "consume", "synchronous" : true}, {"id": 21, "arguments": [{"type": "shortstr", "name": "consumer-tag"}], "name": "consume-ok"}, {"id": 30, "arguments": [{"type": "shortstr", "name": "consumer-tag"}, {"type": "bit", "name": "nowait", "default-value": false}], "name": "cancel", "synchronous" : true}, {"id": 31, "arguments": [{"type": "shortstr", "name": "consumer-tag"}], "name": "cancel-ok"}, {"content": true, "id": 40, "arguments": [{"type": "short", "name": "ticket", "default-value": 1}, {"type": "shortstr", "name": "exchange", "default-value": ""}, {"type": "shortstr", "name": "routing-key", "default-value": ""}, {"type": "bit", "name": "mandatory", "default-value": false}, {"type": "bit", "name": "immediate", "default-value": false}], "name": "publish"}, {"content": true, "id": 50, "arguments": [{"type": "short", "name": "reply-code", "default-value": 200}, {"type": "shortstr", "name": "reply-text", "default-value": ""}, {"type": "shortstr", "name": "exchange"}, {"type": "shortstr", "name": "routing-key"}], "name": "return"}, {"content": true, "id": 60, "arguments": [{"type": "shortstr", "name": "consumer-tag"}, {"type": "longlong", "name": "delivery-tag"}, {"type": "shortstr", "name": "exchange"}, {"type": "shortstr", "name": "queue"}], "name": "deliver"}], "name": "stream", "properties": [{"type": "shortstr", "name": "content-type"}, {"type": "shortstr", "name": "content-encoding"}, {"type": "table", "name": "headers"}, {"type": "octet", "name": "priority"}, {"type": "timestamp", "name": "timestamp"}] }, { "id": 90, "methods": [{"id": 10, "arguments": [], "name": "select", "synchronous" : true}, {"id": 11, "arguments": [], "name": "select-ok"}, {"id": 20, "arguments": [], "name": "commit", "synchronous" : true}, {"id": 21, "arguments": [], "name": "commit-ok"}, {"id": 30, "arguments": [], "name": "rollback", "synchronous" : true}, {"id": 31, "arguments": [], "name": "rollback-ok"}], "name": "tx" }, { "id": 100, "methods": [{"id": 10, "arguments": [], "name": "select", "synchronous" : true}, {"id": 11, "arguments": [], "name": "select-ok"}, {"id": 20, "arguments": [{"type": "shortstr", "name": "dtx-identifier"}], "name": "start", "synchronous" : true}, {"id": 21, "arguments": [], "name": "start-ok"}], "name": "dtx" }, { "id": 110, "methods": [{"content": true, "id": 10, "arguments": [{"type": "table", "name": "meta-data"}], "name": "request"}], "name": "tunnel", "properties": [{"type": "table", "name": "headers"}, {"type": "shortstr", "name": "proxy-name"}, {"type": "shortstr", "name": "data-name"}, {"type": "octet", "name": "durable"}, {"type": "octet", "name": "broadcast"}] }, { "id": 120, "methods": [{"id": 10, "arguments": [{"type": "octet", "name": "integer-1"}, {"type": "short", "name": "integer-2"}, {"type": "long", "name": "integer-3"}, {"type": "longlong", "name": "integer-4"}, {"type": "octet", "name": "operation"}], "name": "integer", "synchronous" : true}, {"id": 11, "arguments": [{"type": "longlong", "name": "result"}], "name": "integer-ok"}, {"id": 20, "arguments": [{"type": "shortstr", "name": "string-1"}, {"type": "longstr", "name": "string-2"}, {"type": "octet", "name": "operation"}], "name": "string", "synchronous" : true}, {"id": 21, "arguments": [{"type": "longstr", "name": "result"}], "name": "string-ok"}, {"id": 30, "arguments": [{"type": "table", "name": "table"}, {"type": "octet", "name": "integer-op"}, {"type": "octet", "name": "string-op"}], "name": "table", "synchronous" : true}, {"id": 31, "arguments": [{"type": "longlong", "name": "integer-result"}, {"type": "longstr", "name": "string-result"}], "name": "table-ok"}, {"content": true, "id": 40, "arguments": [], "name": "content", "synchronous" : true}, {"content": true, "id": 41, "arguments": [{"type": "long", "name": "content-checksum"}], "name": "content-ok"}], "name": "test" } ] } php-amqplib-2.11.0/spec/amqp-rabbitmq-0.9.1.json000066400000000000000000000656401356514014400210500ustar00rootroot00000000000000{ "name": "AMQP", "major-version": 0, "minor-version": 9, "revision": 1, "port": 5672, "copyright": [ "Copyright (C) 2008-2012 VMware, Inc.\n", "\n", "Permission is hereby granted, free of charge, to any person\n", "obtaining a copy of this file (the \"Software\"), to deal in the\n", "Software without restriction, including without limitation the \n", "rights to use, copy, modify, merge, publish, distribute, \n", "sublicense, and/or sell copies of the Software, and to permit \n", "persons to whom the Software is furnished to do so, subject to \n", "the following conditions:\n", "\n", "The above copyright notice and this permission notice shall be\n", "included in all copies or substantial portions of the Software.\n", "\n", "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n", "EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n", "OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n", "NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n", "HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n", "WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n", "FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n", "OTHER DEALINGS IN THE SOFTWARE.\n", "\n", "Class information entered from amqp_xml0-8.pdf and domain types from amqp-xml-doc0-9.pdf\n", "Updated for 0-9-1 by Tony Garnock-Jones\n", "\n", "b3cb053f15e7b98808c0ccc67f23cb3e amqp_xml0-8.pdf\n", "http://www.twiststandards.org/index.php?option=com_docman&task=cat_view&gid=28&&Itemid=90\n", "8444db91e2949dbecfb2585e9eef6d64 amqp-xml-doc0-9.pdf\n", "https://jira.amqp.org/confluence/download/attachments/720900/amqp-xml-doc0-9.pdf?version=1\n"], "domains": [ ["bit", "bit"], ["channel-id", "longstr"], ["class-id", "short"], ["consumer-tag", "shortstr"], ["delivery-tag", "longlong"], ["destination", "shortstr"], ["duration", "longlong"], ["exchange-name", "shortstr"], ["long", "long"], ["longlong", "longlong"], ["longstr", "longstr"], ["method-id", "short"], ["no-ack", "bit"], ["no-local", "bit"], ["octet", "octet"], ["offset", "longlong"], ["path", "shortstr"], ["peer-properties", "table"], ["queue-name", "shortstr"], ["redelivered", "bit"], ["reference", "longstr"], ["reject-code", "short"], ["reject-text", "shortstr"], ["reply-code", "short"], ["reply-text", "shortstr"], ["security-token", "longstr"], ["short", "short"], ["shortstr", "shortstr"], ["table", "table"], ["timestamp", "timestamp"] ], "constants": [ {"name": "FRAME-METHOD", "value": 1}, {"name": "FRAME-HEADER", "value": 2}, {"name": "FRAME-BODY", "value": 3}, {"name": "FRAME-HEARTBEAT", "value": 8}, {"name": "FRAME-MIN-SIZE", "value": 4096}, {"name": "FRAME-END", "value": 206}, {"name": "REPLY-SUCCESS", "value": 200}, {"name": "CONTENT-TOO-LARGE", "value": 311, "class": "soft-error"}, {"name": "NO-ROUTE", "value": 312, "class": "soft-error"}, {"name": "NO-CONSUMERS", "value": 313, "class": "soft-error"}, {"name": "ACCESS-REFUSED", "value": 403, "class": "soft-error"}, {"name": "NOT-FOUND", "value": 404, "class": "soft-error"}, {"name": "RESOURCE-LOCKED", "value": 405, "class": "soft-error"}, {"name": "PRECONDITION-FAILED", "value": 406, "class": "soft-error"}, {"name": "CONNECTION-FORCED", "value": 320, "class": "hard-error"}, {"name": "INVALID-PATH", "value": 402, "class": "hard-error"}, {"name": "FRAME-ERROR", "value": 501, "class": "hard-error"}, {"name": "SYNTAX-ERROR", "value": 502, "class": "hard-error"}, {"name": "COMMAND-INVALID", "value": 503, "class": "hard-error"}, {"name": "CHANNEL-ERROR", "value": 504, "class": "hard-error"}, {"name": "UNEXPECTED-FRAME", "value": 505, "class": "hard-error"}, {"name": "RESOURCE-ERROR", "value": 506, "class": "hard-error"}, {"name": "NOT-ALLOWED", "value": 530, "class": "hard-error"}, {"name": "NOT-IMPLEMENTED", "value": 540, "class": "hard-error"}, {"name": "INTERNAL-ERROR", "value": 541, "class": "hard-error"} ], "classes": [ { "id": 10, "methods": [{"id": 10, "arguments": [{"type": "octet", "name": "version-major", "default-value": 0}, {"type": "octet", "name": "version-minor", "default-value": 9}, {"domain": "peer-properties", "name": "server-properties"}, {"type": "longstr", "name": "mechanisms", "default-value": "PLAIN"}, {"type": "longstr", "name": "locales", "default-value": "en_US"}], "name": "start", "synchronous" : true}, {"id": 11, "arguments": [{"domain": "peer-properties", "name": "client-properties"}, {"type": "shortstr", "name": "mechanism", "default-value": "PLAIN"}, {"type": "longstr", "name": "response"}, {"type": "shortstr", "name": "locale", "default-value": "en_US"}], "name": "start-ok"}, {"id": 20, "arguments": [{"type": "longstr", "name": "challenge"}], "name": "secure", "synchronous" : true}, {"id": 21, "arguments": [{"type": "longstr", "name": "response"}], "name": "secure-ok"}, {"id": 30, "arguments": [{"type": "short", "name": "channel-max", "default-value": 0}, {"type": "long", "name": "frame-max", "default-value": 0}, {"type": "short", "name": "heartbeat", "default-value": 0}], "name": "tune", "synchronous" : true}, {"id": 31, "arguments": [{"type": "short", "name": "channel-max", "default-value": 0}, {"type": "long", "name": "frame-max", "default-value": 0}, {"type": "short", "name": "heartbeat", "default-value": 0}], "name": "tune-ok"}, {"id": 40, "arguments": [{"type": "shortstr", "name": "virtual-host", "default-value": "/"}, {"type": "shortstr", "name": "capabilities", "default-value": ""}, {"type": "bit", "name": "insist", "default-value": false}], "name": "open", "synchronous" : true}, {"id": 41, "arguments": [{"type": "shortstr", "name": "known-hosts", "default-value": ""}], "name": "open-ok"}, {"id": 50, "arguments": [{"type": "short", "name": "reply-code"}, {"type": "shortstr", "name": "reply-text", "default-value": ""}, {"type": "short", "name": "class-id"}, {"type": "short", "name": "method-id"}], "name": "close", "synchronous" : true}, {"id": 51, "arguments": [], "name": "close-ok"}, {"id": 60, "arguments": [{"type": "shortstr", "name": "reason", "default-value": ""}], "name": "blocked"}, {"id": 61, "arguments": [], "name": "unblocked"}], "name": "connection", "properties": [] }, { "id": 20, "methods": [{"id": 10, "arguments": [{"type": "shortstr", "name": "out-of-band", "default-value": ""}], "name": "open", "synchronous" : true}, {"id": 11, "arguments": [{"type": "longstr", "name": "channel-id", "default-value": ""}], "name": "open-ok"}, {"id": 20, "arguments": [{"type": "bit", "name": "active"}], "name": "flow", "synchronous" : true}, {"id": 21, "arguments": [{"type": "bit", "name": "active"}], "name": "flow-ok"}, {"id": 40, "arguments": [{"type": "short", "name": "reply-code"}, {"type": "shortstr", "name": "reply-text", "default-value": ""}, {"type": "short", "name": "class-id"}, {"type": "short", "name": "method-id"}], "name": "close", "synchronous" : true}, {"id": 41, "arguments": [], "name": "close-ok"}], "name": "channel" }, { "id": 30, "methods": [{"id": 10, "arguments": [{"type": "shortstr", "name": "realm", "default-value": "/data"}, {"type": "bit", "name": "exclusive", "default-value": false}, {"type": "bit", "name": "passive", "default-value": true}, {"type": "bit", "name": "active", "default-value": true}, {"type": "bit", "name": "write", "default-value": true}, {"type": "bit", "name": "read", "default-value": true}], "name": "request", "synchronous" : true}, {"id": 11, "arguments": [{"type": "short", "name": "ticket", "default-value": 1}], "name": "request-ok"}], "name": "access" }, { "id": 40, "methods": [{"id": 10, "arguments": [{"type": "short", "name": "ticket", "default-value": 0}, {"type": "shortstr", "name": "exchange"}, {"type": "shortstr", "name": "type", "default-value": "direct"}, {"type": "bit", "name": "passive", "default-value": false}, {"type": "bit", "name": "durable", "default-value": false}, {"type": "bit", "name": "auto-delete", "default-value": false}, {"type": "bit", "name": "internal", "default-value": false}, {"type": "bit", "name": "nowait", "default-value": false}, {"type": "table", "name": "arguments", "default-value": {}}], "name": "declare", "synchronous" : true}, {"id": 11, "arguments": [], "name": "declare-ok"}, {"id": 20, "arguments": [{"type": "short", "name": "ticket", "default-value": 0}, {"type": "shortstr", "name": "exchange"}, {"type": "bit", "name": "if-unused", "default-value": false}, {"type": "bit", "name": "nowait", "default-value": false}], "name": "delete", "synchronous" : true}, {"id": 21, "arguments": [], "name": "delete-ok"}, {"id": 30, "arguments": [{"type": "short", "name": "ticket", "default-value": 0}, {"type": "shortstr", "name": "destination"}, {"type": "shortstr", "name": "source"}, {"type": "shortstr", "name": "routing-key", "default-value": ""}, {"type": "bit", "name": "nowait", "default-value": false}, {"type": "table", "name": "arguments", "default-value": {}}], "name": "bind", "synchronous" : true}, {"id": 31, "arguments": [], "name": "bind-ok"}, {"id": 40, "arguments": [{"type": "short", "name": "ticket", "default-value": 0}, {"type": "shortstr", "name": "destination"}, {"type": "shortstr", "name": "source"}, {"type": "shortstr", "name": "routing-key", "default-value": ""}, {"type": "bit", "name": "nowait", "default-value": false}, {"type": "table", "name": "arguments", "default-value": {}}], "name": "unbind", "synchronous" : true}, {"id": 51, "arguments": [], "name": "unbind-ok"}], "name": "exchange" }, { "id": 50, "methods": [{"id": 10, "arguments": [{"type": "short", "name": "ticket", "default-value": 0}, {"type": "shortstr", "name": "queue", "default-value": ""}, {"type": "bit", "name": "passive", "default-value": false}, {"type": "bit", "name": "durable", "default-value": false}, {"type": "bit", "name": "exclusive", "default-value": false}, {"type": "bit", "name": "auto-delete", "default-value": false}, {"type": "bit", "name": "nowait", "default-value": false}, {"type": "table", "name": "arguments", "default-value": {}}], "name": "declare", "synchronous" : true}, {"id": 11, "arguments": [{"type": "shortstr", "name": "queue"}, {"type": "long", "name": "message-count"}, {"type": "long", "name": "consumer-count"}], "name": "declare-ok"}, {"id": 20, "arguments": [{"type": "short", "name": "ticket", "default-value": 0}, {"type": "shortstr", "name": "queue", "default-value": ""}, {"type": "shortstr", "name": "exchange"}, {"type": "shortstr", "name": "routing-key", "default-value": ""}, {"type": "bit", "name": "nowait", "default-value": false}, {"type": "table", "name": "arguments", "default-value": {}}], "name": "bind", "synchronous" : true}, {"id": 21, "arguments": [], "name": "bind-ok"}, {"id": 30, "arguments": [{"type": "short", "name": "ticket", "default-value": 0}, {"type": "shortstr", "name": "queue", "default-value": ""}, {"type": "bit", "name": "nowait", "default-value": false}], "name": "purge", "synchronous" : true}, {"id": 31, "arguments": [{"type": "long", "name": "message-count"}], "name": "purge-ok"}, {"id": 40, "arguments": [{"type": "short", "name": "ticket", "default-value": 0}, {"type": "shortstr", "name": "queue", "default-value": ""}, {"type": "bit", "name": "if-unused", "default-value": false}, {"type": "bit", "name": "if-empty", "default-value": false}, {"type": "bit", "name": "nowait", "default-value": false}], "name": "delete", "synchronous" : true}, {"id": 41, "arguments": [{"type": "long", "name": "message-count"}], "name": "delete-ok"}, {"id": 50, "arguments": [{"type": "short", "name": "ticket", "default-value": 0}, {"type": "shortstr", "name": "queue", "default-value": ""}, {"type": "shortstr", "name": "exchange"}, {"type": "shortstr", "name": "routing-key", "default-value": ""}, {"type": "table", "name": "arguments", "default-value": {}}], "name": "unbind", "synchronous" : true}, {"id": 51, "arguments": [], "name": "unbind-ok"} ], "name": "queue" }, { "id": 60, "methods": [{"id": 10, "arguments": [{"type": "long", "name": "prefetch-size", "default-value": 0}, {"type": "short", "name": "prefetch-count", "default-value": 0}, {"type": "bit", "name": "global", "default-value": false}], "name": "qos", "synchronous" : true}, {"id": 11, "arguments": [], "name": "qos-ok"}, {"id": 20, "arguments": [{"domain": "short", "name": "ticket", "default-value": 0}, {"type": "shortstr", "name": "queue", "default-value": ""}, {"type": "shortstr", "name": "consumer-tag", "default-value": ""}, {"type": "bit", "name": "no-local", "default-value": false}, {"type": "bit", "name": "no-ack", "default-value": false}, {"type": "bit", "name": "exclusive", "default-value": false}, {"type": "bit", "name": "nowait", "default-value": false}, {"type": "table", "name": "arguments", "default-value": {}}], "name": "consume", "synchronous" : true}, {"id": 21, "arguments": [{"type": "shortstr", "name": "consumer-tag"}], "name": "consume-ok"}, {"id": 30, "arguments": [{"type": "shortstr", "name": "consumer-tag"}, {"type": "bit", "name": "nowait", "default-value": false}], "name": "cancel", "synchronous" : true}, {"id": 31, "arguments": [{"type": "shortstr", "name": "consumer-tag"}], "name": "cancel-ok"}, {"content": true, "id": 40, "arguments": [{"type": "short", "name": "ticket", "default-value": 0}, {"type": "shortstr", "name": "exchange", "default-value": ""}, {"type": "shortstr", "name": "routing-key", "default-value": ""}, {"type": "bit", "name": "mandatory", "default-value": false}, {"type": "bit", "name": "immediate", "default-value": false}], "name": "publish"}, {"content": true, "id": 50, "arguments": [{"type": "short", "name": "reply-code"}, {"type": "shortstr", "name": "reply-text", "default-value": ""}, {"type": "shortstr", "name": "exchange"}, {"type": "shortstr", "name": "routing-key"}], "name": "return"}, {"content": true, "id": 60, "arguments": [{"type": "shortstr", "name": "consumer-tag"}, {"type": "longlong", "name": "delivery-tag"}, {"type": "bit", "name": "redelivered", "default-value": false}, {"type": "shortstr", "name": "exchange"}, {"type": "shortstr", "name": "routing-key"}], "name": "deliver"}, {"id": 70, "arguments": [{"type": "short", "name": "ticket", "default-value": 0}, {"type": "shortstr", "name": "queue", "default-value": ""}, {"type": "bit", "name": "no-ack", "default-value": false}], "name": "get", "synchronous" : true}, {"content": true, "id": 71, "arguments": [{"type": "longlong", "name": "delivery-tag"}, {"type": "bit", "name": "redelivered", "default-value": false}, {"type": "shortstr", "name": "exchange"}, {"type": "shortstr", "name": "routing-key"}, {"type": "long", "name": "message-count"}], "name": "get-ok"}, {"id": 72, "arguments": [{"type": "shortstr", "name": "cluster-id", "default-value": ""}], "name": "get-empty"}, {"id": 80, "arguments": [{"type": "longlong", "name": "delivery-tag", "default-value": 0}, {"type": "bit", "name": "multiple", "default-value": false}], "name": "ack"}, {"id": 90, "arguments": [{"type": "longlong", "name": "delivery-tag"}, {"type": "bit", "name": "requeue", "default-value": true}], "name": "reject"}, {"id": 100, "arguments": [{"type": "bit", "name": "requeue", "default-value": false}], "name": "recover-async"}, {"id": 110, "arguments": [{"type": "bit", "name": "requeue", "default-value": false}], "name": "recover", "synchronous" : true}, {"id": 111, "arguments": [], "name": "recover-ok"}, {"id": 120, "arguments": [{"type": "longlong", "name": "delivery-tag", "default-value": 0}, {"type": "bit", "name": "multiple", "default-value": false}, {"type": "bit", "name": "requeue", "default-value": true}], "name": "nack"}], "name": "basic", "properties": [{"type": "shortstr", "name": "content-type"}, {"type": "shortstr", "name": "content-encoding"}, {"type": "table", "name": "headers"}, {"type": "octet", "name": "delivery-mode"}, {"type": "octet", "name": "priority"}, {"type": "shortstr", "name": "correlation-id"}, {"type": "shortstr", "name": "reply-to"}, {"type": "shortstr", "name": "expiration"}, {"type": "shortstr", "name": "message-id"}, {"type": "timestamp", "name": "timestamp"}, {"type": "shortstr", "name": "type"}, {"type": "shortstr", "name": "user-id"}, {"type": "shortstr", "name": "app-id"}, {"type": "shortstr", "name": "cluster-id"}] }, { "id": 90, "methods": [{"id": 10, "arguments": [], "name": "select", "synchronous" : true}, {"id": 11, "arguments": [], "name": "select-ok"}, {"id": 20, "arguments": [], "name": "commit", "synchronous" : true}, {"id": 21, "arguments": [], "name": "commit-ok"}, {"id": 30, "arguments": [], "name": "rollback", "synchronous" : true}, {"id": 31, "arguments": [], "name": "rollback-ok"}], "name": "tx" }, { "id": 85, "methods": [{"id": 10, "arguments": [ {"type": "bit", "name": "nowait", "default-value": false}], "name": "select", "synchronous": true}, {"id": 11, "arguments": [], "name": "select-ok"}], "name": "confirm" } ] } php-amqplib-2.11.0/spec/parser.php000066400000000000000000000313761356514014400167610ustar00rootroot00000000000000 0) { $s = preg_replace('#(?:^|[\r\n]+)(?=[^\r\n])#', '$0' . str_repeat($chars, $level), $s); } return $s; } function add_method_arguments($arguments) { $ret = array(); foreach ($arguments as $arg) { $ret[] = '$' . to_snake_case($arg['name']) . argument_default_val($arg); } return implode(", ", $ret); } /** * @param array $domains * @param string $domain * @return string * @throws Exception */ function domain_to_type($domains, $domain) { foreach ($domains as $d) { if ($d[0] == $domain) { return $d[1]; } } throw new \Exception("Invalid domain: " . $domain); } /** * @param array $domains * @param array $arg * @return string * @throws Exception */ function argument_type($domains, $arg) { return isset($arg['type']) ? $arg['type'] : domain_to_type($domains, $arg['domain']); } class ArgumentWriter { protected $bit_args = array(); public function call_write_argument($domains, $arg) { $a_type = argument_type($domains, $arg); if ($a_type == 'bit') { $this->bit_args[] = '$' . to_snake_case($arg['name']); $ret = ''; } else { $ret = $this->write_bits(); $a_name = '$' . to_snake_case($arg['name']); $ret .= '$writer->write_' . $a_type . '(' . ($a_type === 'table' ? 'empty(' . $a_name . ') ? array() : ' : '') . $a_name . ");\n"; } return $ret; } public function write_bits() { if (empty($this->bit_args)) { return ''; } $ret = '$writer->write_bits(array(' . implode(', ', $this->bit_args) . "));\n"; $this->bit_args = array(); return $ret; } } function call_read_argument($domains, $arg) { return '$reader->read_' . argument_type($domains, $arg) . "();\n"; } function protocol_version($json_spec) { if (isset($json_spec['revision'])) { return $json_spec['major-version'] . $json_spec['minor-version'] . $json_spec['revision']; } else { return '0' . $json_spec['major-version'] . $json_spec['minor-version']; } } function protocol_header($json_spec) { if (isset($json_spec['revision'])) { $args = array(0, $json_spec['major-version'], $json_spec['minor-version'], $json_spec['revision']); } else { $args = array(1, 1, $json_spec['major-version'], $json_spec['minor-version']); } array_unshift($args, 'AMQP\x%02x\x%02x\x%02x\x%02x'); return '"' . call_user_func_array('sprintf', $args) . '"'; } $argumentWriter = new ArgumentWriter(); $out = 'call_write_argument($json_spec['domains'], $arg); } $methodBody .= $argumentWriter->write_bits(); $methodBody .= 'return array(' . $c['id'] . ", " . $m['id'] . ', $writer);'; $methods .= '/**' . "\n"; $methods .= addPhpDocParams($m['arguments']) . "\n"; $methods .= ' * @return array' . "\n"; $methods .= ' */' . "\n"; $methods .= 'public function ' . method_name($c['name'], $m['name']) . "("; $methods .= add_method_arguments($m['arguments']); $methods .= ")\n{\n"; $methods .= indent($methodBody) . "\n"; $methods .= "}\n"; } else { $methodBody = '$response = array();' . "\n"; foreach ($m['arguments'] as $arg) { $methodBody .= '$response[] = ' . call_read_argument($json_spec['domains'], $arg); } $methodBody .= 'return $response;'; $methods .= '/**' . "\n"; $methods .= ' * @param AMQPReader $reader' . "\n"; $methods .= ' * @return array' . "\n"; $methods .= ' */' . "\n"; $methods .= 'public static function ' . method_name($c['name'], $m['name']) . '(AMQPReader $reader)' . "\n{\n"; $methods .= indent($methodBody) . "\n"; $methods .= "}\n"; } } } $out .= indent(rtrim($methods)) . "\n"; $out .= "}\n"; file_put_contents(__DIR__ . '/../PhpAmqpLib/Helper/Protocol/Protocol' . protocol_version($json_spec) . '.php', $out); function export_property($ret) { if (!is_array($ret)) { return var_export($ret, true); } $code = ''; foreach ($ret as $key => $value) { $code .= var_export($key, true) . ' => ' . export_property($value) . ",\n"; } return "array(\n" . indent($code) . ")"; } function frame_types($json_spec) { $ret = array(); foreach ($json_spec['constants'] as $c) { if (mb_substr($c['name'], 0, 5, 'ASCII') == "FRAME") { $ret[$c['value']] = $c['name']; } } return export_property($ret); } function content_methods($json_spec) { $ret = array(); foreach ($json_spec['classes'] as $c) { foreach ($c['methods'] as $m) { if (isset($m['content']) && $m['content']) { $ret[] = $c['id'] . "," . $m['id']; } } } return export_property($ret); } function close_methods($json_spec) { $ret = array(); foreach ($json_spec['classes'] as $c) { foreach ($c['methods'] as $m) { if ($m['name'] == 'close') { $ret[] = $c['id'] . "," . $m['id']; } } } return export_property($ret); } function global_method_names($json_spec) { $ret = array(); foreach ($json_spec['classes'] as $c) { foreach ($c['methods'] as $m) { $ret[$c['id'] . "," . $m['id']] = ucfirst($c['name']) . '.' . to_snake_case($m['name']); } } return export_property($ret); } /** * @param string $type * @param string $variableName * @param string $returnType (optional) * @return string */ function get_type_phpdoc($type, $variableName = null, $returnType = null) { $properties = "/**\n"; $properties .= " * @var " . $type; if ($variableName != null) { $properties .= " " . $variableName; } $properties .= "\n"; if ($returnType != null) { $properties .= " * @return " . $returnType . "\n"; } $properties .= " */\n"; return $properties; } $properties = sprintf("const VERSION = '%s';", implode('.', array_filter([$json_spec['major-version'], $json_spec['minor-version'], @$json_spec['revision']], function ($value) {return $value !== null;}))); $properties .= PHP_EOL; $properties .= 'const AMQP_HEADER = ' . protocol_header($json_spec) . ';'; $properties .= PHP_EOL . PHP_EOL; $properties .= get_type_phpdoc('array'); $properties .= 'public static $FRAME_TYPES = ' . frame_types($json_spec) . ";\n\n"; $properties .= get_type_phpdoc('array'); $properties .= 'public static $CONTENT_METHODS = ' . content_methods($json_spec) . ";\n\n"; $properties .= get_type_phpdoc('array'); $properties .= 'public static $CLOSE_METHODS = ' . close_methods($json_spec) . ";\n\n"; $properties .= get_type_phpdoc('array'); $properties .= 'public static $GLOBAL_METHOD_NAMES = ' . global_method_names($json_spec) . ";\n"; $out = 'wait[$method];') . "\n"; $classBody .= "}"; $out = ' 'basic_cancel_from_server', '60,80' => 'basic_ack_from_server', '60,120' => 'basic_nack_from_server' ); foreach ($json_spec['classes'] as $c) { foreach ($c['methods'] as $m) { if (isset($special_map[$c['id'] . ',' . $m['id']]) && protocol_version($json_spec) == '091') { $ret[$c['id'] . "," . $m['id']] = $special_map[$c['id'] . ',' . $m['id']]; } else { $ret[$c['id'] . "," . $m['id']] = $c['name'] . '_' . to_snake_case($m['name']); } } } return export_property($ret); } $classBody = ''; $classBody .= get_type_phpdoc('array'); $classBody .= 'protected $method_map = ' . method_map($json_spec) . ";\n\n"; $classBody .= get_type_phpdoc('string', '$method_sig', 'string'); $classBody .= 'public function get_method($method_sig)' . "\n{\n"; $classBody .= indent('return $this->method_map[$method_sig];') . "\n"; $classBody .= "}\n\n"; $classBody .= get_type_phpdoc('string', '$method_sig', 'bool'); $classBody .= 'public function valid_method($method_sig)' . "\n{\n"; $classBody .= indent('return array_key_exists($method_sig, $this->method_map);') . "\n"; $classBody .= "}"; $out = 'assertTrue($connection->isConnected()); return $connection; } protected function queue_bind(AMQPChannel $channel, $exchange_name, &$queue_name) { $channel->exchange_declare($exchange_name, AMQPExchangeType::DIRECT); list($queue_name, ,) = $channel->queue_declare(); $channel->queue_bind($queue_name, $exchange_name, $queue_name); } /** * @param string $name * @return ToxiProxy */ protected function create_proxy($name = 'amqp_connection') { $proxy = new ToxiProxy($name, $this->get_toxiproxy_host()); $proxy->open(HOST, PORT, $this->get_toxiproxy_amqp_port()); return $proxy; } protected function get_toxiproxy_host() { $host = getenv('TOXIPROXY_HOST'); if (!$host) { $this->markTestSkipped('TOXIPROXY_HOST is not set'); } return $host; } protected function get_toxiproxy_amqp_port() { $port = getenv('TOXIPROXY_AMQP_PORT'); if (!$port) { $this->markTestSkipped('TOXIPROXY_AMQP_PORT is not set'); } return $port; } protected function assertConnectionClosed(AbstractConnection $connection) { $this->assertFalse($connection->isConnected()); $this->assertNotNull($connection->getIO()); $this->assertNull($connection->getIO()->getSocket()); // all channels must be closed foreach ($connection->channels as $ch) { if ($ch instanceof AMQPChannel) { $this->assertFalse($ch->is_open()); } if ($ch instanceof AbstractConnection) { $this->assertFalse($ch->isConnected()); } } $this->assertNotEmpty($connection->channels); } protected function assertChannelClosed(AbstractChannel $channel) { $this->assertFalse($channel->is_open()); $this->assertEmpty($channel->callbacks); } } // mock low level IO write functions namespace PhpAmqpLib\Wire\IO; function fwrite() { if (\PhpAmqpLib\Tests\Functional\AbstractConnectionTest::$blocked) { return 0; } return call_user_func_array('\fwrite', func_get_args()); } namespace PhpAmqpLib\Wire\IO; function socket_write() { if (\PhpAmqpLib\Tests\Functional\AbstractConnectionTest::$blocked) { return 0; } return call_user_func_array('\socket_write', func_get_args()); } php-amqplib-2.11.0/tests/Functional/Bug/000077500000000000000000000000001356514014400177715ustar00rootroot00000000000000php-amqplib-2.11.0/tests/Functional/Bug/Bug256Test.php000066400000000000000000000054121356514014400223160ustar00rootroot00000000000000connection = $this->conection_create('socket'); $this->channel = $this->connection->channel(); $this->channel->exchange_declare($this->exchangeName, 'direct', false, true, false); $this->connection2 = $this->conection_create('stream'); $this->channel2 = $this->connection->channel(); list($this->queueName, ,) = $this->channel2->queue_declare(); $this->channel2->queue_bind($this->queueName, $this->exchangeName, $this->queueName); } public function tearDown() { if ($this->channel) { $this->channel->exchange_delete($this->exchangeName); $this->channel->close(); $this->channel = null; } if ($this->connection) { $this->connection->close(); $this->connection = null; } if ($this->channel2) { $this->channel2->close(); $this->channel2 = null; } if ($this->connection2) { $this->connection2->close(); $this->connection2 = null; } } /** * @test */ public function frame_order() { $msg = new AMQPMessage(''); $hdrs = new AMQPTable(['x-foo' => 'bar']); $msg->set('application_headers', $hdrs); for ($i = 0; $i < $this->messageCount; $i++) { $this->channel->basic_publish($msg, $this->exchangeName, $this->queueName); } $this->channel2->basic_consume( $this->queueName, '', false, true, false, false, [$this, 'processMessage'] ); while (count($this->channel2->callbacks)) { $this->channel2->wait(); } } public function processMessage(AMQPMessage $message) { $this->consumedCount++; $this->assertEquals(['x-foo' => 'bar'], $message->get('application_headers')->getNativeData()); if ($this->consumedCount >= $this->messageCount) { $delivery_info = $message->delivery_info; $delivery_info['channel']->basic_cancel($delivery_info['consumer_tag']); } } } php-amqplib-2.11.0/tests/Functional/Bug/Bug40Test.php000066400000000000000000000061471356514014400222330ustar00rootroot00000000000000connection = new AMQPStreamConnection(HOST, PORT, USER, PASS, VHOST); $this->channel = $this->connection->channel(); $this->channel2 = $this->connection->channel(); $this->channel->exchange_declare($this->exchangeName, 'direct', false, false, false); list($this->queueName1, ,) = $this->channel->queue_declare(); list($this->queueName2, ,) = $this->channel->queue_declare(); $this->channel->queue_bind($this->queueName1, $this->exchangeName, $this->queueName1); $this->channel->queue_bind($this->queueName2, $this->exchangeName, $this->queueName2); } public function tearDown() { if ($this->channel) { $this->channel->exchange_delete($this->exchangeName); $this->channel->close(); $this->channel = null; } if ($this->channel2) { $this->channel2->close(); $this->channel2 = null; } if ($this->connection) { $this->connection->close(); $this->connection = null; } } /** * @test */ public function frame_order() { $msg = new AMQPMessage('test message'); $this->channel->basic_publish($msg, $this->exchangeName, $this->queueName1); $this->channel->basic_publish($msg, $this->exchangeName, $this->queueName1); $this->channel->basic_publish($msg, $this->exchangeName, $this->queueName2); $this->channel->basic_consume( $this->queueName1, '', false, true, false, false, [$this, 'processMessage1'] ); while ($this->channel->is_consuming()) { $this->channel->wait(); } } public function processMessage1($msg) { $this->queue1Messages++; if ($this->queue1Messages === 1) { $this->channel2->basic_consume( $this->queueName2, '', false, true, false, false, [$this, 'processMessage2'] ); } while ($this->channel2->is_consuming()) { $this->channel2->wait(); } if ($this->queue1Messages === 2) { $delivery_info = $msg->delivery_info; $delivery_info['channel']->basic_cancel($delivery_info['consumer_tag']); } } public function processMessage2($msg) { $delivery_info = $msg->delivery_info; $delivery_info['channel']->basic_cancel($delivery_info['consumer_tag']); $this->assertLessThan(2, $this->queue1Messages); } } php-amqplib-2.11.0/tests/Functional/Bug/Bug458Test.php000066400000000000000000000024601356514014400223220ustar00rootroot00000000000000markTestSkipped('pcntl extension is not available'); } $connection = new AMQPStreamConnection(HOST, PORT, USER, PASS, VHOST); $this->channel = $connection->channel(); $this->addSignalHandlers(); } protected function tearDown() { if ($this->channel && $this->channel->is_open()) { $this->channel->close(); } $this->channel = null; } /** * This test will be skipped in Windows, because pcntl extension is not available there * * @test * * @expectedException \PhpAmqpLib\Exception\AMQPTimeoutException */ public function stream_select_interruption() { $pid = getmypid(); exec('php -r "sleep(1);posix_kill(' . $pid . ', SIGTERM);" > /dev/null 2>/dev/null &'); $this->channel->wait(null, false, 2); } private function addSignalHandlers() { pcntl_signal(SIGTERM, function () { // do nothing }); } } php-amqplib-2.11.0/tests/Functional/Bug/Bug49Test.php000066400000000000000000000030671356514014400222420ustar00rootroot00000000000000connection = new AMQPStreamConnection(HOST, PORT, USER, PASS, VHOST); $this->channel = $this->connection->channel(); $this->channel2 = $this->connection->channel(); } protected function tearDown() { if ($this->channel) { $this->channel->close(); $this->channel = null; } if ($this->channel2) { $this->channel2->close(); $this->channel2 = null; } if ($this->connection) { $this->connection->close(); $this->connection = null; } } /** * @test */ public function declaration() { try { $this->channel->queue_declare($queue = 'pretty.queue', true, true); $this->fail('Should have raised an exception'); } catch (AMQPProtocolException $exception) { $this->assertInstanceOf(AMQPProtocolChannelException::class, $exception); $this->assertEquals(404, $exception->getCode()); } $this->channel2->queue_declare($queue, false, true, true, true); $this->channel2->queue_delete($queue, false, false, true); } } php-amqplib-2.11.0/tests/Functional/Channel/000077500000000000000000000000001356514014400206245ustar00rootroot00000000000000php-amqplib-2.11.0/tests/Functional/Channel/ChannelTestCase.php000066400000000000000000000023751356514014400243500ustar00rootroot00000000000000connection = new AMQPSocketConnection(HOST, PORT, USER, PASS, VHOST); $this->channel = $this->connection->channel(); $this->exchange = (object) [ 'name' => null, ]; $this->queue = (object) [ 'name' => null, ]; $this->message = (object) [ 'body' => null, 'properties' => null, ]; } public function tearDown() { if ($this->channel) { $this->channel->close(); $this->channel = null; } if ($this->connection) { $this->connection->close(); $this->connection = null; } } } php-amqplib-2.11.0/tests/Functional/Channel/ChannelTimeoutTest.php000066400000000000000000000057411356514014400251230ustar00rootroot00000000000000channel_rpc_timeout_seconds, $this->channel_rpc_timeout_microseconds ) = MiscHelper::splitSecondsMicroseconds( $channel_rpc_timeout ); $this->io = $this->getMockBuilder(StreamIO::class) ->setConstructorArgs(array(HOST, PORT, 3, 3, null, false, 0)) ->setMethods(array('select')) ->getMock(); $this->connection = $this->getMockBuilder(AbstractConnection::class) ->setConstructorArgs(array(USER, PASS, '/', false, 'AMQPLAIN', null, 'en_US', $this->io, 0, 0, $channel_rpc_timeout)) ->setMethods(array()) ->getMockForAbstractClass(); $this->channel = $this->connection->channel(); } /** * @test * * @dataProvider provide_operations * @param string $operation * @param array $args * * @covers \PhpAmqpLib\Channel\AMQPChannel::exchange_declare * @covers \PhpAmqpLib\Channel\AMQPChannel::queue_declare * @covers \PhpAmqpLib\Channel\AMQPChannel::confirm_select * * @expectedException \PhpAmqpLib\Exception\AMQPTimeoutException * @expectedExceptionMessage The connection timed out after 3.5 sec while awaiting incoming data */ public function should_throw_exception_for_basic_operations_when_timeout_exceeded($operation, $args) { // simulate blocking on the I/O level $this->io->expects($this->any()) ->method('select') ->with($this->channel_rpc_timeout_seconds, $this->channel_rpc_timeout_microseconds) ->willReturn(0); call_user_func_array(array($this->channel, $operation), $args); } public function provide_operations() { return array( array('exchange_declare', array('test_ex', 'fanout')), array('queue_declare', array('test_queue')), array('confirm_select', array()), ); } protected function tearDown() { if ($this->channel) { $this->channel->close(); } $this->channel = null; if ($this->connection) { $this->connection->close(); } $this->connection = null; } } php-amqplib-2.11.0/tests/Functional/Channel/ChannelWaitTest.php000066400000000000000000000112721356514014400243750ustar00rootroot00000000000000deferSignal(0.5); /** @var AMQPChannel $channel */ $channel = $factory(); $result = false; try { $result = $channel->wait(); } catch (\Exception $exception) { $this->fail($exception->getMessage()); } $this->closeChannel($channel); $this->assertNull($result); } /** * @test * @small * @dataProvider provide_channels * @param callable $factory * @expectedException \PhpAmqpLib\Exception\AMQPTimeoutException */ public function should_throw_timeout_exception($factory) { $channel = $factory(); $channel->wait(null, false, 0.01); $this->closeChannel($channel); } /** * @test * @small * @dataProvider provide_channels * @param callable $factory */ public function should_return_instantly_non_blocking($factory) { $channel = $factory(); $start = microtime(true); $channel->wait(null, true); $took = microtime(true) - $start; $this->assertLessThan(0.1, $took); $this->closeChannel($channel); } /** * @test * @small * */ public function should_call_handler_on_ack() { $receivedAck = false; $handler = function ($message) use (&$receivedAck) { $this->assertFalse($receivedAck); $this->assertInstanceOf(AMQPMessage::class, $message); $receivedAck = true; }; $factory = $this->channelFactory(); /** @var AMQPChannel $channel */ $channel = $factory(); $channel->set_ack_handler($handler); $channel->confirm_select(); $channel->basic_publish(new AMQPMessage('test'), 'basic_get_test'); $channel->wait_for_pending_acks(1); $this->assertTrue($receivedAck); } public function provide_channels() { if (!defined('HOST')) { $this->markTestSkipped('Unkown RabbitMQ host'); } return [ [$this->channelFactory(true, 0.1, 0)], [$this->channelFactory(false, 0.1, 0)], [$this->channelFactory(true, 3, 1)], [$this->channelFactory(false, 3, 1)], ]; } protected function channelFactory($stream = true, $connectionTimeout = 1, $heartBeat = 0) { $factory = function () use ($stream, $connectionTimeout, $heartBeat) { try { if ($stream) { $connection = new AMQPStreamConnection( HOST, PORT, USER, PASS, VHOST, false, 'AMQPLAIN', null, 'en_us', $connectionTimeout, $connectionTimeout, null, false, $heartBeat ); } else { $connection = new AMQPSocketConnection( HOST, PORT, USER, PASS, VHOST, false, 'AMQPLAIN', null, 'en_US', $connectionTimeout, false, $connectionTimeout, $heartBeat ); } } catch (\ErrorException $exception) { $this->markTestSkipped('Cannot connect to RabbitMQ: ' . $exception->getMessage()); } $channel = $connection->channel(); $channel->queue_declare($queue = 'basic_get_queue', false, true, false, false); $channel->exchange_declare($exchange = 'basic_get_test', 'fanout', false, true, false); $channel->queue_bind($queue, $exchange); return $channel; }; return $factory; } protected function deferSignal($delay = 1) { if (!extension_loaded('pcntl')) { $this->markTestSkipped('pcntl extension is not available'); } pcntl_signal(SIGTERM, function () { }); $pid = getmypid(); exec('php -r "usleep(' . $delay * 1e6 . ');posix_kill(' . $pid . ', SIGTERM);" > /dev/null 2>/dev/null &'); } protected function closeChannel(AMQPChannel $channel) { $connection = $channel->getConnection(); $channel->close(); $connection->close(); } } php-amqplib-2.11.0/tests/Functional/Channel/DirectExchangeTest.php000066400000000000000000000056731356514014400250650ustar00rootroot00000000000000exchange->name = 'test_direct_exchange'; } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPChannelClosedException */ public function exchange_declare_with_closed_connection() { $this->connection->close(); $this->channel->exchange_declare($this->exchange->name, 'direct', false, false, false); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPChannelClosedException */ public function exchange_declare_with_closed_channel() { $this->channel->close(); $this->channel->exchange_declare($this->exchange->name, 'direct', false, false, false); } /** * @test */ public function basic_consume_foo() { $this->channel->exchange_declare($this->exchange->name, 'direct', false, false, false); list($this->queue->name, ,) = $this->channel->queue_declare(); $this->channel->queue_bind($this->queue->name, $this->exchange->name, $this->queue->name); $this->message = (object) [ 'body' => 'foo', 'properties' => [ 'content_type' => 'text/plain', 'delivery_mode' => AMQPMessage::DELIVERY_MODE_NON_PERSISTENT, 'correlation_id' => 'my_correlation_id', 'reply_to' => 'my_reply_to', ], ]; $msg = new AMQPMessage($this->message->body, $this->message->properties); $this->channel->basic_publish($msg, $this->exchange->name, $this->queue->name); $callback = function ($msg) { $this->assertEquals($this->message->body, $msg->body); $this->assertEquals(getmypid(), $msg->delivery_info['consumer_tag']); $this->assertEquals($this->queue->name, $msg->delivery_info['routing_key']); $this->assertEquals($this->exchange->name, $msg->delivery_info['exchange']); $this->assertEquals(false, $msg->delivery_info['redelivered']); $this->assertEquals($this->message->properties['content_type'], $msg->get('content_type')); $this->assertEquals($this->message->properties['correlation_id'], $msg->get('correlation_id')); $this->assertEquals($this->message->properties['reply_to'], $msg->get('reply_to')); $this->expectException('OutOfBoundsException'); $msg->get('no_property'); }; $this->channel->basic_consume( $this->queue->name, getmypid(), false, false, false, false, $callback ); while (count($this->channel->callbacks)) { $this->channel->wait(); } } } php-amqplib-2.11.0/tests/Functional/Channel/HeadersExchangeTest.php000066400000000000000000000044121356514014400252140ustar00rootroot00000000000000exchange->name = 'amq.headers'; } /** * @test * @small * @covers \PhpAmqpLib\Channel\AMQPChannel::queue_bind() * @covers \PhpAmqpLib\Exchange\AMQPExchangeType */ public function consume_specific_headers() { list($queue1) = $this->channel->queue_declare(); $this->channel->queue_bind($queue1, $this->exchange->name); $bindArguments = [ 'foo' => 'bar', ]; list($queue2) = $this->channel->queue_declare(); $this->channel->queue_bind($queue2, $this->exchange->name, '', false, new AMQPTable($bindArguments)); // publish message without headers - should appear in 1st queue without filters $message = new AMQPMessage('test'); $this->channel->basic_publish($message, $this->exchange->name); $received1 = $this->channel->basic_get($queue1, true); $received2 = $this->channel->basic_get($queue2, true); $this->assertInstanceOf(AMQPMessage::class, $received1); $this->assertNull($received2); // publish message with matching headers $message->set('application_headers', new AMQPTable($bindArguments)); $this->channel->basic_publish($message, $this->exchange->name); $received1 = $this->channel->basic_get($queue1, true); $received2 = $this->channel->basic_get($queue2, true); // should appear in both queues $this->assertInstanceOf(AMQPMessage::class, $received1); $this->assertInstanceOf(AMQPMessage::class, $received2); // publish with not matching headers $message->set('application_headers', new AMQPTable(array('foo' => false))); $this->channel->basic_publish($message, $this->exchange->name); $received1 = $this->channel->basic_get($queue1, true); $received2 = $this->channel->basic_get($queue2, true); // should appear in non filtered queue only $this->assertInstanceOf(AMQPMessage::class, $received1); $this->assertNull($received2); } } php-amqplib-2.11.0/tests/Functional/Channel/TopicExchangeTest.php000066400000000000000000000047221356514014400247230ustar00rootroot00000000000000exchange->name = 'test_topic_exchange'; } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPChannelClosedException */ public function exchange_declare_with_closed_connection() { $this->connection->close(); $this->channel->exchange_declare($this->exchange->name, 'topic'); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPChannelClosedException */ public function exchange_declare_with_closed_channel() { $this->channel->close(); $this->channel->exchange_declare($this->exchange->name, 'topic'); } /** * @test */ public function publish_with_confirm() { $this->channel->exchange_declare($this->exchange->name, 'topic'); $deliveryTags = []; $this->channel->set_ack_handler(function (AMQPMessage $message) use (&$deliveryTags) { $deliveryTags[] = (int) $message->get('delivery_tag'); return false; }); $this->channel->confirm_select(); $connection2 = new AMQPSocketConnection(HOST, PORT, USER, PASS, VHOST); $channel2 = $connection2->channel(); $channel2->queue_declare('tst.queue3'); $channel2->queue_bind('tst.queue3', $this->exchange->name, '#'); $this->channel->basic_publish(new AMQPMessage('foo'), $this->exchange->name); $this->channel->basic_publish(new AMQPMessage('bar'), $this->exchange->name); $publishedMessagesProperty = new \ReflectionProperty(get_class($this->channel), 'published_messages'); $publishedMessagesProperty->setAccessible(true); $this->channel->wait_for_pending_acks_returns(1); $msg1 = $channel2->basic_get('tst.queue3'); $msg2 = $channel2->basic_get('tst.queue3'); $this->assertInstanceOf('PhpAmqpLib\Message\AMQPMessage', $msg1); $this->assertInstanceOf('PhpAmqpLib\Message\AMQPMessage', $msg2); $this->assertSame('foo', $msg1->getBody()); $this->assertSame('bar', $msg2->getBody()); $this->assertSame([1, 2], $deliveryTags); $channel2->close(); $connection2->close(); } } php-amqplib-2.11.0/tests/Functional/Connection/000077500000000000000000000000001356514014400213535ustar00rootroot00000000000000php-amqplib-2.11.0/tests/Functional/Connection/ConnectionAuthTest.php000066400000000000000000000071401356514014400256470ustar00rootroot00000000000000createUser($username, ''); try { $connection = new AMQPStreamConnection(HOST, PORT, $username, '', '/', false, 'PLAIN', null, 'en_US', 1); $this->assertInstanceOf(AMQPStreamConnection::class, $connection); $this->assertTrue($connection->isConnected()); } catch (AMQPExceptionInterface $exception) { // rabbitmq does not respond to wrong auth content due to empty password $this->assertInstanceOf(AMQPTimeoutException::class, $exception); } finally { $this->deleteUser($username); } $this->createUser($username, $password = 'password'); try { $connection = new AMQPStreamConnection(HOST, PORT, $username, $password, '/', false, 'PLAIN', null, 'en_US', 1); $this->assertInstanceOf(AMQPStreamConnection::class, $connection); $this->assertTrue($connection->isConnected()); $channel = $connection->channel(); $this->assertInstanceOf(AMQPChannel::class, $channel); $connection->close(); } finally { $this->deleteUser($username); } } private function createUser($username, $password) { $userEndpoint = HOST . ':15672/api/users/' . $username; $passwordHash = ''; if (!empty($password)) { $salt = substr(md5(mt_rand()), 0, 4); $passwordHash = base64_encode($salt . hash('sha256', $salt . $password, true)); } $request = Request::put( $userEndpoint, json_encode([ 'password_hash' => $passwordHash, 'tags' => '', 'hashing_algorithm' => 'rabbit_password_hashing_sha256', ]) ); $request->expectsJson(); $request->basicAuth(USER, PASS); $request->whenError(function ($error) { }); try { $response = $request->send(); } catch (ConnectionErrorException $exception) { $this->markTestSkipped($exception->getMessage()); } if ($response->code !== 201) { $this->markTestSkipped('Cannot create temporary user'); } $request = Request::put( HOST . ':15672/api/permissions/%2f/' . $username, json_encode(['configure' => '', 'write' => '.*', 'read' => '.*']) ); $request->expectsJson(); $request->basicAuth(USER, PASS); $response = $request->send(); if ($response->code !== 201) { $this->markTestSkipped('Cannot set vhost permission'); } } private function deleteUser($username) { $userEndpoint = HOST . ':15672/api/users/' . $username; $request = Request::delete($userEndpoint); $request->expectsJson(); $request->basicAuth(USER, PASS); $request->send(); } } php-amqplib-2.11.0/tests/Functional/Connection/ConnectionClosedTest.php000066400000000000000000000131011356514014400261510ustar00rootroot00000000000000create_proxy(); $options = array( 'keepalive' => $keepalive, ); /** @var AbstractConnection $connection */ $connection = $this->conection_create( $type, $proxy->getHost(), $proxy->getPort(), $options ); $channel = $connection->channel(); $this->assertTrue($channel->is_open()); $exception = null; // block and close connection after delay $proxy->mode('timeout', array('timeout' => 100)); try { $channel->wait(null, false, 1); } catch (\Exception $exception) { } $this->assertInstanceOf('Exception', $exception); $this->assertInstanceOf('PhpAmqpLib\Exception\AMQPConnectionClosedException', $exception); $this->assertEquals(0, $exception->getCode()); $this->assertChannelClosed($channel); $this->assertConnectionClosed($connection); } /** * Try to write(publish) to blocked(unresponsive) connection. * @test * @small * @group connection * @group proxy * @testWith ["stream"] * ["socket"] * @covers \PhpAmqpLib\Wire\IO\StreamIO::write() * @covers \PhpAmqpLib\Wire\IO\SocketIO::write() * * @param string $type */ public function must_throw_exception_broken_pipe_write($type) { $proxy = $this->create_proxy(); /** @var AbstractConnection $connection */ $connection = $this->conection_create( $type, $proxy->getHost(), $proxy->getPort() ); $channel = $connection->channel(); $this->assertTrue($channel->is_open()); $this->queue_bind($channel, $exchange_name = 'test_exchange_broken', $queue_name); $message = new AMQPMessage( str_repeat('0', 1024 * 32), // 32kb fills up buffer completely on most OS ['delivery_mode' => AMQPMessage::DELIVERY_MODE_NON_PERSISTENT] ); $exception = null; // block proxy connection $proxy->disable(); try { $channel->basic_publish($message, $exchange_name, $queue_name); } catch (\Exception $exception) { } $this->assertInstanceOf('PhpAmqpLib\Exception\AMQPConnectionClosedException', $exception); $this->assertEquals(SOCKET_EPIPE, $exception->getCode()); $this->assertChannelClosed($channel); $this->assertConnectionClosed($connection); // 2nd publish call must return exception instantly cause connection is already closed $exception = null; try { $channel->basic_publish($message, $exchange_name, $queue_name); } catch (\Exception $exception) { } $this->assertInstanceOf('PhpAmqpLib\Exception\AMQPChannelClosedException', $exception); } /** * Try to close and reopen connection after timeout. * * @test * @small * @group connection * @group proxy * @testWith ["stream"] * ["socket"] * @covers \PhpAmqpLib\Wire\IO\StreamIO::write() * @covers \PhpAmqpLib\Wire\IO\SocketIO::write() * @param string $type */ public function must_throw_exception_after_connection_was_restored($type) { $timeout = 1; $proxy = $this->create_proxy(); /** @var AbstractConnection $connection */ $connection = $this->conection_create( $type, $proxy->getHost(), $proxy->getPort(), array('timeout' => $timeout) ); $channel = $connection->channel(); $this->assertTrue($channel->is_open()); $this->queue_bind($channel, $exchange_name = 'test_exchange_broken', $queue_name); $message = new AMQPMessage( str_repeat('0', 1024 * 32), // 32kb fills up buffer completely on most OS ['delivery_mode' => AMQPMessage::DELIVERY_MODE_NON_PERSISTENT] ); $channel->basic_publish($message, $exchange_name, $queue_name); // close proxy and wait longer than timeout unset($proxy); sleep($timeout); usleep(100000); $proxy = $this->create_proxy(); $exception = null; try { $channel->basic_publish($message, $exchange_name, $queue_name); } catch (\Exception $exception) { } $this->assertInstanceOf('Exception', $exception); $this->assertInstanceOf('PhpAmqpLib\Exception\AMQPConnectionClosedException', $exception); $this->assertGreaterThan(0, $exception->getCode()); $this->assertChannelClosed($channel); $this->assertConnectionClosed($connection); } } php-amqplib-2.11.0/tests/Functional/Connection/ConnectionCreationTest.php000066400000000000000000000024451356514014400265150ustar00rootroot00000000000000 array( array( array('host' => HOST, 'port' => PORT, 'user' => USER, 'password' => PASS), array('host' => HOST, 'port' => PORT, 'user' => USER, 'password' => PASS) ) ), 'keys' => array( array( 'host1' => array('host' => HOST, 'port' => PORT, 'user' => USER, 'password' => PASS), 'host2' => array('host' => HOST, 'port' => PORT, 'user' => USER, 'password' => PASS) ) ) ); } /** * @test * @dataProvider hostDataProvider * @covers \PhpAmqpLib\Connection\AbstractConnection::create_connection() */ public function create_connection(array $hosts) { $conn = AMQPStreamConnection::create_connection($hosts, array()); $this->assertInstanceOf('PhpAmqpLib\Connection\AMQPStreamConnection', $conn); } } php-amqplib-2.11.0/tests/Functional/Connection/ConnectionUnresponsiveTest.php000066400000000000000000000050131356514014400274430ustar00rootroot00000000000000conection_create($type); $channel = $connection->channel(); $this->assertTrue($channel->is_open()); $this->queue_bind($channel, $exchange_name = 'test_exchange_broken', $queue_name); self::$blocked = true; $message = new AMQPMessage( str_repeat('0', 8), ['delivery_mode' => AMQPMessage::DELIVERY_MODE_NON_PERSISTENT] ); $exception = null; try { $channel->basic_publish($message, $exchange_name, $queue_name); } catch (\Exception $exception) { } self::$blocked = false; $this->assertInstanceOf(\Exception::class, $exception); $this->assertInstanceOf(Exception\AMQPTimeoutException::class, $exception); $this->assertEquals(1, $exception->getTimeout()); $this->assertTrue($channel->is_open()); $this->assertTrue($connection->isConnected()); } /** * @test * @testWith ["stream"] * @group proxy * @covers \PhpAmqpLib\Connection\AbstractConnection::connect() * @param string $type */ public function must_throw_timeout_exception_on_missing_connect_response($type) { $proxy = $this->create_proxy(); $proxy->mode('timeout', ['timeout' => 0], 'downstream'); $connection = null; $exception = null; try { $connection = $this->conection_create( $type, $proxy->getHost(), $proxy->getPort(), array('timeout' => 3, 'connectionTimeout' => .1, 'heartbeat' => 1) ); } catch (\Exception $exception) { } $this->assertInstanceOf(\Exception::class, $exception); $this->assertInstanceOf(Exception\AMQPTimeoutException::class, $exception); $this->assertNull($connection); } } php-amqplib-2.11.0/tests/Functional/FileTransferTest.php000066400000000000000000000051421356514014400232130ustar00rootroot00000000000000connection = new AMQPConnection(HOST, PORT, USER, PASS, VHOST); $this->channel = $this->connection->channel(); $this->channel->exchange_declare($this->exchangeName, 'direct', false, false, false); list($this->queueName, ,) = $this->channel->queue_declare(); $this->channel->queue_bind($this->queueName, $this->exchangeName, $this->queueName); } public function tearDown() { if ($this->channel) { $this->channel->exchange_delete($this->exchangeName); $this->channel->close(); $this->channel = null; } if ($this->connection) { $this->connection->close(); $this->connection = null; } } /** * @test */ public function send_file() { $this->messageBody = $this->generateRandomBytes(1024 * 1024); $msg = new AMQPMessage($this->messageBody, ['delivery_mode' => AMQPMessage::DELIVERY_MODE_NON_PERSISTENT]); $this->channel->basic_publish($msg, $this->exchangeName, $this->queueName); $this->channel->basic_consume( $this->queueName, '', false, false, false, false, [$this, 'processMessage'] ); while (count($this->channel->callbacks)) { $this->channel->wait(); } } public function processMessage($msg) { $delivery_info = $msg->delivery_info; $delivery_info['channel']->basic_ack($delivery_info['delivery_tag']); $delivery_info['channel']->basic_cancel($delivery_info['consumer_tag']); $this->assertEquals($this->messageBody, $msg->body); } private function generateRandomBytes($num_bytes) { // If random_bytes exists (PHP 7) or has been polyfilled, use it if ( function_exists('random_bytes') ) { return random_bytes($num_bytes); } // Otherwise, just make some noise quickly else { $data = ''; for ($i = 0; $i < $num_bytes; $i++) { $data .= chr(rand(0, 255)); } return $data; } } } php-amqplib-2.11.0/tests/Functional/ReconnectConnectionTest.php000066400000000000000000000076761356514014400246050ustar00rootroot00000000000000channel) { $this->channel->exchange_delete($this->exchange); $this->channel->queue_delete($this->queue); $this->channel->close(); $this->channel = null; } if ($this->connection) { $this->connection->close(); $this->connection = null; } } /** * @test */ public function lazy_connection_reconnect() { $this->connection = $this->getLazyConnection(); $this->doTest(); } /** * @test */ public function lazy_connection_close_reconnect() { $this->connection = $this->getLazyConnection(); $this->setupChannel(); $this->connection->close(); $this->connection->reconnect(); $this->setupChannel(); $this->assertEquals($this->msgBody, $this->publishGet()->body); } /** * @test */ public function socket_connection_reconnect() { $this->connection = $this->getSocketConnection(); $this->doTest(); } /** * @test */ public function socket_connection_close_reconnect() { $this->connection = $this->getSocketConnection(); $this->connection->close(); $this->connection->reconnect(); $this->setupChannel(); $this->assertEquals($this->msgBody, $this->publishGet()->body); } /** * @test */ public function lazy_socket_connection_close_reconnect() { $this->connection = $this->getLazySocketConnection(); $this->connection->close(); $this->connection->reconnect(); $this->setupChannel(); $this->assertEquals($this->msgBody, $this->publishGet()->body); } /** * @test */ public function lazy_connection_socket_reconnect() { $this->connection = $this->getLazySocketConnection(); $this->doTest(); } protected function getSocketConnection() { return new AMQPSocketConnection(HOST, PORT, USER, PASS, VHOST); } protected function getLazyConnection() { return new AMQPLazyConnection(HOST, PORT, USER, PASS, VHOST); } protected function getLazySocketConnection() { return new AMQPLazySocketConnection(HOST, PORT, USER, PASS, VHOST); } protected function doTest() { $this->setupChannel(); $this->assertEquals($this->msgBody, $this->publishGet()->body); $this->connection->reconnect(); $this->setupChannel(); $this->assertEquals($this->msgBody, $this->publishGet()->body); } protected function setupChannel() { $this->channel = $this->connection->channel(); $this->channel->exchange_declare($this->exchange, 'direct', false, false, false); $this->channel->queue_declare($this->queue); $this->channel->queue_bind($this->queue, $this->exchange, $this->queue); } protected function publishGet() { $msg = new AMQPMessage($this->msgBody, [ 'content_type' => 'text/plain', 'delivery_mode' => AMQPMessage::DELIVERY_MODE_NON_PERSISTENT, 'correlation_id' => 'my_correlation_id', 'reply_to' => 'my_reply_to' ]); $this->channel->basic_publish($msg, $this->exchange, $this->queue); return $this->channel->basic_get($this->queue); } } php-amqplib-2.11.0/tests/Functional/StreamIOTest.php000066400000000000000000000040171356514014400223120ustar00rootroot00000000000000last_error = null; set_error_handler(array($this, 'custom_error_handler')); error_reporting(~E_NOTICE); $exceptionThrown = false; try { new AMQPStreamConnection(HOST, PORT - 1, USER, PASS, VHOST); } catch (\Exception $exception) { $exceptionThrown = true; } $this->assertTrue($exceptionThrown, 'Custom error handler was not set.'); $this->assertInstanceOf('PhpAmqpLib\Exception\AMQPIOException', $exception); $this->assertNull($this->last_error); $exceptionThrown = false; $arr = []; try { $notice = $arr['second-key-that-does-not-exist-and-should-generate-a-notice']; } catch (\Exception $exception) { $exceptionThrown = true; } $this->assertFalse($exceptionThrown, 'Default error handler was not restored.'); error_reporting(E_ALL); $previousErrorHandler = set_error_handler(array($this, 'custom_error_handler')); $this->assertSame('custom_error_handler', $previousErrorHandler[1]); } /** * @test */ public function error_handler_is_restored_on_success() { set_error_handler(array($this, 'custom_error_handler')); new AMQPStreamConnection(HOST, PORT, USER, PASS, VHOST); $previousErrorHandler = set_error_handler(array($this, 'custom_error_handler')); $this->assertSame('custom_error_handler', $previousErrorHandler[1]); } public function custom_error_handler($errno, $errstr, $errfile, $errline, $errcontext = null) { $this->last_error = compact('errno', 'errstr', 'errfile', 'errline', 'errcontext'); } } php-amqplib-2.11.0/tests/Functional/ToxiProxy.php000066400000000000000000000070771356514014400217650ustar00rootroot00000000000000name = $name; $this->host = $host; $this->api = 'http://' . $host . ':' . $port; } public function __destruct() { if ($this->isOpen) { $this->close(); } } /** * Open new proxy connection to $upstream and listen on port $port. * @param string $upstream * @param int $listen */ public function open($host, $port, $listen) { $payload = array( 'name' => $this->name, 'upstream' => $host . ':' . $port, 'listen' => ':' . $listen, ); $url = $this->api . '/proxies'; $request = Request::post($url, json_encode($payload), 'json'); $request->timeout(1); $request->expectsJson(); $response = $request->send(); if ($response->code !== 201) { throw new \RuntimeException('Cannot create Toxiproxy connection'); } $this->listen = $listen; $this->isOpen = true; } /** * Enable proxy $type manipulation. * @param $type One of latency, bandwidth, slow_close, timeout, slicer, limit_data * @param array $attributes * @param string $direction Either upstream or downstream. * @param float $toxicity * @see https://github.com/Shopify/toxiproxy#toxics */ public function mode($type, $attributes = array(), $direction = 'upstream', $toxicity = 1.0) { $payload = [ 'name' => null, 'stream' => $direction, 'type' => $type, 'toxicity' => $toxicity, 'attributes' => !empty($attributes) ? $attributes : null, ]; $url = sprintf('%s/proxies/%s/toxics', $this->api, $this->name); $request = Request::post($url, json_encode($payload), 'json'); $request->timeout(1); $request->expectsJson(); $response = $request->send(); if ($response->code !== 200) { throw new \RuntimeException('Cannot set Toxiproxy connection mode'); } } /** * Disable(block) proxy connection so no data can be transferred. * @throws \Httpful\Exception\ConnectionErrorException */ public function disable() { $url = sprintf('%s/proxies/%s', $this->api, $this->name); $response = Request::post($url, json_encode(array('enabled' => false)), 'json')->send(); if ($response->code !== 200) { throw new \RuntimeException('Cannot disable Toxiproxy connection'); } } /** * Completely close connection to upstream. * @throws \Httpful\Exception\ConnectionErrorException */ public function close() { $url = sprintf('%s/proxies/%s', $this->api, $this->name); $response = Request::delete($url)->send(); if ($response->code !== 204 && $response->code !== 404) { throw new \RuntimeException('Cannot close Toxiproxy connection'); } } /** * @return string */ public function getHost() { return $this->host; } /** * @return int|null */ public function getPort() { return $this->listen; } } php-amqplib-2.11.0/tests/Unit/000077500000000000000000000000001356514014400160715ustar00rootroot00000000000000php-amqplib-2.11.0/tests/Unit/Connection/000077500000000000000000000000001356514014400201705ustar00rootroot00000000000000php-amqplib-2.11.0/tests/Unit/Connection/AMQPSocketConnectionTest.php000066400000000000000000000014021356514014400254650ustar00rootroot00000000000000getMockBuilder('\PhpAmqpLib\Connection\AMQPStreamConnection') ->setMethods(null) ->disableOriginalConstructor() ->getMock(); $properties = $connection->getLibraryProperties(); // Assert that the library properties method returns an array $this->assertInternalType('array', $properties); // Ensure that the required properties exist in the array $this->assertArrayHasKey('product', $properties); $this->assertArrayHasKey('version', $properties); $this->assertArrayHasKey('platform', $properties); $this->assertArrayHasKey('copyright', $properties); $this->assertArrayHasKey('information', $properties); } /** * AMQPWriter::table_write expects values given with data types and values * ensure each property is an array with the first value being a data type * * @test */ public function propertyTypes() { $connection = $this->getMockBuilder('\PhpAmqpLib\Connection\AMQPStreamConnection') ->setMethods(null) ->disableOriginalConstructor() ->getMock(); $properties = $connection->getLibraryProperties(); // Assert that the library properties method returns an array $this->assertInternalType('array', $properties); // Iterate array checking each value is suitable foreach ($properties as $property) { // Property should be an array with exactly 2 properties $this->assertInternalType('array', $property); $this->assertCount(2, $property); // Retreive the datatype and ensure it matches our signature $dataType = $property[0]; $this->assertInternalType('string', $dataType); $this->assertStringMatchesFormat('%c', $dataType); } } } php-amqplib-2.11.0/tests/Unit/Helper/000077500000000000000000000000001356514014400173105ustar00rootroot00000000000000php-amqplib-2.11.0/tests/Unit/Helper/MiscHelperTest.php000066400000000000000000000025701356514014400227200ustar00rootroot00000000000000assertEquals($expected, MiscHelper::splitSecondsMicroseconds($input)); } /** * @dataProvider hexdumpData * @test */ public function hexdump($args, $expected) { $this->assertRegExp($expected, MiscHelper::hexdump($args[0], $args[1], $args[2], $args[3])); } /** * @test */ public function method_sig() { $this->assertEquals('test', MiscHelper::methodSig('test')); } public function splitSecondsMicrosecondsData() { return [ [0, [0, 0]], [0.3, [0, 300000]], ['0.3', [0, 300000]], [3, [3, 0]], ['3', [3, 0]], [3.0, [3, 0]], ['3.0', [3, 0]], [3.1, [3, 100000]], ['3.1', [3, 100000]], [3.123456, [3, 123456]], ['3.123456', [3, 123456]], ]; } public function hexdumpData() { return [ [['FM', false, false, true], '/000\s+46 4d\s+FM/'], [['FM', false, true, true], '/000\s+46 4D\s+FM/'], ]; } } php-amqplib-2.11.0/tests/Unit/Helper/Protocol/000077500000000000000000000000001356514014400211115ustar00rootroot00000000000000php-amqplib-2.11.0/tests/Unit/Helper/Protocol/Protocol091Test.php000066400000000000000000000212351356514014400245200ustar00rootroot00000000000000protocol091 = new Protocol091(); } /** * @test */ public function channel_close() { $expected = "\x00\x00\x00\x00\x00\x00\x00"; list($class_id, $method_id, $args) = $this->protocol091->channelClose(0, '', 0, 0); $this->assertEquals($expected, $args->getvalue()); } /** * @test */ public function channel_close_error() { $expected = "\x00\x00\x05error\x00\x00\x00\x00"; list($class_id, $method_id, $args) = $this->protocol091->channelClose(0, 'error', 0, 0); $this->assertEquals($expected, $args->getvalue()); $expected = "\x00\x00\x05error\x00\x14\x00\x28"; list($class_id, $method_id, $args) = $this->protocol091->channelClose(0, 'error', 20, 40); $this->assertEquals($expected, $args->getvalue()); } /** * @test */ public function channel_flow_true() { $expected = "\x01"; list($class_id, $method_id, $args) = $this->protocol091->channelFlow(true); $this->assertEquals($expected, $args->getvalue()); } /** * @test */ public function channel_flow_false() { $expected = "\x00"; list($class_id, $method_id, $args) = $this->protocol091->channelFlow(false); $this->assertEquals($expected, $args->getvalue()); } /** * @test */ public function channel_open_foo() { $expected = "\x03foo"; list($class_id, $method_id, $args) = $this->protocol091->channelOpen('foo'); $this->assertEquals($expected, $args->getvalue()); } /** * @test */ public function channel_open_empty_string() { $expected = "\x00"; list($class_id, $method_id, $args) = $this->protocol091->channelOpen(''); $this->assertEquals($expected, $args->getvalue()); } /** * @test */ public function access_request() { $expected = "\x01/\x00"; list($class_id, $method_id, $args) = $this->protocol091->accessRequest('/', false, false, false, false, false); $this->assertEquals($expected, $args->getvalue()); } /** * @test */ public function access_request_foo() { $expected = "\x04/foo\x00"; list($class_id, $method_id, $args) = $this->protocol091->accessRequest( '/foo', false, false, false, false, false ); $this->assertEquals($expected, $args->getvalue()); } /** * @test */ public function exchange_declare() { $expected = "\x00\x00\x03foo\x06direct\x00\x00\x00\x00\x00"; list($class_id, $method_id, $args) = $this->protocol091->exchangeDeclare( 0, 'foo', 'direct', false, false, false, false, false, [] ); $this->assertEquals($expected, $args->getvalue()); } /** * @test */ public function exchange_delete() { $expected = "\x00\x00\x03foo\x00"; list($class_id, $method_id, $args) = $this->protocol091->exchangeDelete(0, 'foo', false, false); $this->assertEquals($expected, $args->getvalue()); } /** * @test */ public function exchange_bind() { $expected = "\x00\x00\x03foo\x03bar\x03baz\x00\x00\x00\x00\x00"; list($class_id, $method_id, $args) = $this->protocol091->exchangeBind(0, 'foo', 'bar', 'baz', false, []); $this->assertEquals($expected, $args->getvalue()); } /** * @test */ public function exchange_unbind() { $expected = "\x00\x00\x03foo\x03bar\x03baz\x00\x00\x00\x00\x00"; list($class_id, $method_id, $args) = $this->protocol091->exchangeUnbind(0, 'foo', 'bar', 'baz', false, []); $this->assertEquals($expected, $args->getvalue()); } /** * @test */ public function queue_bind() { $expected = "\x00\x00\x03foo\x03bar\x03baz\x00\x00\x00\x00\x00"; list($class_id, $method_id, $args) = $this->protocol091->queueBind(0, 'foo', 'bar', 'baz', false, []); $this->assertEquals($expected, $args->getvalue()); } /** * @test */ public function queue_unbind() { $expected = "\x00\x00\x03foo\x03bar\x03baz\x00\x00\x00\x00"; list($class_id, $method_id, $args) = $this->protocol091->queueUnbind(0, 'foo', 'bar', 'baz', []); $this->assertEquals($expected, $args->getvalue()); } /** * @test */ public function queue_declare() { $expected = "\x00\x00\x03foo\x00\x00\x00\x00\x00"; list($class_id, $method_id, $args) = $this->protocol091->queueDeclare( 0, 'foo', false, false, false, false, false, [] ); $this->assertEquals($expected, $args->getvalue()); } /** * @test */ public function queue_delete() { $expected = "\x00\x00\x03foo\x00"; list($class_id, $method_id, $args) = $this->protocol091->queueDelete(0, 'foo', false, false, false); $this->assertEquals($expected, $args->getvalue()); } /** * @test */ public function queue_purge() { $expected = "\x00\x00\x03foo\x00"; list($class_id, $method_id, $args) = $this->protocol091->queuePurge(0, 'foo', false); $this->assertEquals($expected, $args->getvalue()); } /** * @test */ public function basic_ack() { $expected = "\x00\x00\x00\x00\x00\x00\x00\x01\x00"; list($class_id, $method_id, $args) = $this->protocol091->basicAck(1, false); $this->assertEquals($expected, $args->getvalue()); } /** * @test */ public function basic_cancel() { $expected = "\x03foo\x00"; list($class_id, $method_id, $args) = $this->protocol091->basicCancel('foo', false); $this->assertEquals($expected, $args->getvalue()); } /** * @test */ public function basic_consume() { $expected = "\x00\x00\x03foo\x03bar\x00\x00\x00\x00\x00"; list($class_id, $method_id, $args) = $this->protocol091->basicConsume( 0, 'foo', 'bar', false, false, false, false ); $this->assertEquals($expected, $args->getvalue()); } /** * @test */ public function basic_get() { $expected = "\x00\x00\x03foo\x00"; list($class_id, $method_id, $args) = $this->protocol091->basicGet(0, 'foo', false); $this->assertEquals($expected, $args->getvalue()); } /** * @test */ public function basic_publish() { $expected = "\x00\x00\x03foo\x03bar\x00"; list($class_id, $method_id, $args) = $this->protocol091->basicPublish(0, 'foo', 'bar', false, false); $this->assertEquals($expected, $args->getvalue()); } /** * @test */ public function basic_qos() { $expected = "\x00\x00\x00\xA\x00\x01\x00"; list($class_id, $method_id, $args) = $this->protocol091->basicQos(10, 1, false); $this->assertEquals($expected, $args->getvalue()); } /** * @test */ public function basic_recover_true() { $expected = "\x01"; list($class_id, $method_id, $args) = $this->protocol091->basicRecover(true); $this->assertEquals($expected, $args->getvalue()); } /** * @test */ public function basic_recover_false() { $expected = "\x00"; list($class_id, $method_id, $args) = $this->protocol091->basicRecover(false); $this->assertEquals($expected, $args->getvalue()); } /** * @test */ public function basic_reject_1_true() { $expected = "\x00\x00\x00\x00\x00\x00\x00\x01\x01"; list($class_id, $method_id, $args) = $this->protocol091->basicReject(1, true); $this->assertEquals($expected, $args->getvalue()); } /** * @test */ public function basic_reject_1_false() { $expected = "\x00\x00\x00\x00\x00\x00\x00\x01\x00"; list($class_id, $method_id, $args) = $this->protocol091->basicReject(1, false); $this->assertEquals($expected, $args->getvalue()); } /** * @test */ public function connection_blocked() { $expected = 'Low on memory'; list($class_id, $method_id, $args) = $this->protocol091->connectionBlocked($expected); $this->assertEquals($class_id, 10); $this->assertEquals($method_id, 60); $this->assertEquals($expected, trim($args->getValue())); } } php-amqplib-2.11.0/tests/Unit/Message/000077500000000000000000000000001356514014400174555ustar00rootroot00000000000000php-amqplib-2.11.0/tests/Unit/Message/AMQPMessageTest.php000066400000000000000000000071131356514014400230730ustar00rootroot00000000000000serialize_properties(); $reader->reuse($encodedData); $message->load_properties($reader); $props = $message->get_properties(); if (isset($props['application_headers'])) { $props['application_headers'] = $props['application_headers']->getNativeData(); } $this->assertEquals($expected, $props); } /** * @test */ public function get_and_set_body() { $message = new AMQPMessage(''); $message->setBody('body'); $message->setIsTruncated(true); $message->content_encoding = 'shortstr'; $this->assertEquals($message->getBody(), 'body'); $this->assertTrue($message->isTruncated()); $this->assertEquals($message->getContentEncoding(), 'shortstr'); } /** * @test */ public function get_delivery_tag() { $message = new AMQPMessage(''); $message->delivery_info['delivery_tag'] = "10"; $this->assertEquals(10, $message->getDeliveryTag()); $message->delivery_info['delivery_tag'] = 1231; $this->assertEquals(1231, $message->getDeliveryTag()); unset($message->delivery_info['delivery_tag']); $this->expectException('\PhpAmqpLib\Exception\AMQPEmptyDeliveryTagException'); $message->getDeliveryTag(); } public function propertiesData() { return [ [ ['priority' => 1, 'timestamp' => time()], ['priority' => 1, 'timestamp' => time()], ], [ ['message_id' => '5414cfa74899a'], ['message_id' => '5414cfa74899a'], ], [ ['message_id' => 0], ['message_id' => 0], ], [ [], ['timestamp' => null], ], [ [], ['priority' => null], ], [ ['priority' => 0], ['priority' => 0], ], [ ['priority' => false], ['priority' => false], ], [ ['priority' => '0'], ['priority' => '0'], ], [ ['application_headers' => ['x-foo' => '']], ['application_headers' => ['x-foo' => ['S', '']]], ], [ ['application_headers' => ['x-foo' => '']], ['application_headers' => ['x-foo' => ['S', null]]], ], [ ['application_headers' => ['x-foo' => 0]], ['application_headers' => ['x-foo' => ['I', 0]]], ], [ ['application_headers' => ['x-foo' => 1]], ['application_headers' => ['x-foo' => ['I', true]]], ], [ ['application_headers' => ['x-foo' => 0]], ['application_headers' => ['x-foo' => ['I', '0']]], ], [ ['application_headers' => ['x-foo' => []]], ['application_headers' => ['x-foo' => ['A', []]]], ], [ ['application_headers' => ['x-foo' => [null]]], ['application_headers' => ['x-foo' => ['A', [null]]]], ], ]; } } php-amqplib-2.11.0/tests/Unit/Wire/000077500000000000000000000000001356514014400167775ustar00rootroot00000000000000php-amqplib-2.11.0/tests/Unit/Wire/AMQPCollectionTest.php000066400000000000000000000564531356514014400231370ustar00rootroot00000000000000setProtoVersion(Wire\Constants080::VERSION); $a = new Wire\AMQPArray([ 1, (int) -2147483648, (int) 2147483647, -2147483649, 2147483648, true, false, ['foo' => 'bar'], ['foo'], [], new \DateTime('2009-02-13 23:31:30'), (class_exists('DateTimeImmutable') ? new \DateTimeImmutable('2009-02-13 23:31:30') : new \DateTime('2009-02-13 23:31:30') ), ]); $this->assertEquals( [ [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('I'), 1, ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('I'), -2147483648, ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('I'), 2147483647, ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('S'), -2147483649, ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('S'), 2147483648, ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('I'), 1, ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('I'), 0, ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('F'), [ 'foo' => [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('S'), 'bar', ], ], ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('F'), [ 0 => [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('S'), 'foo', ], ], ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('F'), [], ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('T'), 1234567890, ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('T'), 1234567890, ], ], $this->getEncodedRawData($a) ); $eData = $this->getEncodedRawData($a, false); $this->assertEquals(true, $eData[7][1] instanceof Wire\AMQPTable); $this->assertEquals(true, $eData[8][1] instanceof Wire\AMQPTable); $this->assertEquals(true, $eData[9][1] instanceof Wire\AMQPTable); } /** * @test */ public function encode_091() { $this->setProtoVersion(Wire\Constants091::VERSION); $a = new Wire\AMQPArray([ 1, (int) -2147483648, (int) 2147483647, -2147483649, 2147483648, true, false, ['foo' => 'bar'], ['foo'], [], ]); $is64 = PHP_INT_SIZE == 8; $this->assertEquals( [ [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('I'), 1, ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('I'), -2147483648, ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('I'), 2147483647, ], [ $is64 ? Wire\AMQPAbstractCollection::getDataTypeForSymbol('L') : Wire\AMQPAbstractCollection::getDataTypeForSymbol('S'), -2147483649, ], [ $is64 ? Wire\AMQPAbstractCollection::getDataTypeForSymbol('L') : Wire\AMQPAbstractCollection::getDataTypeForSymbol('S'), 2147483648, ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('t'), true, ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('t'), false, ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('F'), [ 'foo' => [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('S'), 'bar', ], ], ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('A'), [ [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('S'), 'foo', ], ], ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('A'), [], ], ], $this->getEncodedRawData($a) ); $eData = $this->getEncodedRawData($a, false); $this->assertEquals(true, $eData[7][1] instanceof Wire\AMQPTable); $this->assertEquals(true, $eData[8][1] instanceof Wire\AMQPArray); $this->assertEquals(true, $eData[9][1] instanceof Wire\AMQPArray); } /** * @test */ public function encode_rabbit() { $this->setProtoVersion(Wire\AMQPAbstractCollection::PROTOCOL_RBT); $a = new Wire\AMQPArray([ 1, (int) -2147483648, (int) 2147483647, -2147483649, 2147483648, true, false, ['foo' => 'bar'], ['foo'], [], ]); $is64 = PHP_INT_SIZE == 8; $this->assertEquals( [ [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('I'), 1, ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('I'), -2147483648, ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('I'), 2147483647, ], [ $is64 ? Wire\AMQPAbstractCollection::getDataTypeForSymbol('l') : Wire\AMQPAbstractCollection::getDataTypeForSymbol('S'), -2147483649, ], [ $is64 ? Wire\AMQPAbstractCollection::getDataTypeForSymbol('l') : Wire\AMQPAbstractCollection::getDataTypeForSymbol('S'), 2147483648, ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('t'), true, ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('t'), false, ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('F'), [ 'foo' => [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('S'), 'bar' ], ], ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('A'), [ [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('S'), 'foo', ], ], ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('A'), [], ], ], $this->getEncodedRawData($a) ); $eData = $this->getEncodedRawData($a, false); $this->assertEquals(true, $eData[7][1] instanceof Wire\AMQPTable); $this->assertEquals(true, $eData[8][1] instanceof Wire\AMQPArray); $this->assertEquals(true, $eData[9][1] instanceof Wire\AMQPArray); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPOutOfBoundsException */ public function encode_unknown_data_type() { $a = new Wire\AMQPArray(array(new \stdClass())); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPOutOfRangeException */ public function push_unsupported_data_type_080() { $this->setProtoVersion(Wire\Constants080::VERSION); $a = new Wire\AMQPArray(); $a->push(12345, Wire\AMQPArray::T_INT_LONGLONG); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPOutOfRangeException */ public function push_unsupported_data_type_091() { $this->setProtoVersion(Wire\Constants091::VERSION); $a = new Wire\AMQPArray(); $a->push(12345, 'foo'); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPOutOfRangeException */ public function push_unsupported_data_type_rabbit() { $this->setProtoVersion(Wire\AMQPAbstractCollection::PROTOCOL_RBT); $a = new Wire\AMQPArray(); $a->push(12345, Wire\AMQPArray::T_INT_LONGLONG_U); } /** * @test */ public function push_with_type() { $a = new Wire\AMQPArray(); $a->push(576, Wire\AMQPArray::T_INT_LONG); $a->push('foo', Wire\AMQPArray::T_STRING_LONG); $a->push(new Wire\AMQPTable(['foo' => 'bar'])); $a->push(new Wire\AMQPArray(['bar'])); $this->assertEquals( [ [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('I'), 576, ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('S'), 'foo', ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('F'), [ 'foo' => [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('S'), 'bar', ], ], ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('A'), [ [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('S'), 'bar', ], ], ], ], $this->getEncodedRawData($a) ); } /** * @test */ public function conflicting_field_symbols() { $this->setProtoVersion(Wire\Constants091::VERSION); $a = new Wire\AMQPArray(); $a->push(576, Wire\AMQPArray::T_INT_SHORT); $a->push(1234567, Wire\AMQPArray::T_INT_LONGLONG); $this->assertEquals( [ [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('U'), 576, ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('L'), 1234567, ], ], $this->getEncodedRawData($a) ); $this->setProtoVersion(Wire\AMQPAbstractCollection::PROTOCOL_RBT); $a = new Wire\AMQPArray(); $a->push(576, Wire\AMQPArray::T_INT_SHORT); $a->push(1234567, Wire\AMQPArray::T_INT_LONGLONG); $this->assertEquals( [ [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('s'), 576, ], [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('l'), 1234567, ], ], $this->getEncodedRawData($a) ); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPInvalidArgumentException * @expectedExceptionMessage Table key must be non-empty string up to 128 chars in length */ public function set_empty_key() { $t = new Wire\AMQPTable(); $t->set('', 'foo'); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPInvalidArgumentException * @expectedExceptionMessage Table key must be non-empty string up to 128 chars in length */ public function set_long_key() { $t = new Wire\AMQPTable(); $t->set(str_repeat('a', 129), 'bar'); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPInvalidArgumentException */ public function push_mismatched_type() { $a = new Wire\AMQPArray(); $a->push(new Wire\AMQPArray(), Wire\AMQPArray::T_TABLE); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPInvalidArgumentException * @expectedExceptionMessage Arrays must be passed as AMQPArray instance */ public function push_raw_array_with_type() { $a = new Wire\AMQPArray(); $a->push(array(), Wire\AMQPArray::T_ARRAY); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPInvalidArgumentException * @expectedExceptionMessage Tables must be passed as AMQPTable instance */ public function push_raw_table_with_type() { $a = new Wire\AMQPArray(); $a->push(array(), Wire\AMQPArray::T_TABLE); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPInvalidArgumentException * @expectedExceptionMessage Decimal values must be instance of AMQPDecimal */ public function push_float_with_decimal_type() { $a = new Wire\AMQPArray(); $a->push(35.2, Wire\AMQPArray::T_DECIMAL); } /** * @test */ public function array_round_trip_080() { $this->setProtoVersion(Wire\Constants080::VERSION); $a = new Wire\AMQPArray($this->getTestDataSrc()); $this->assertEquals(array_values($this->getTestDataCmp080()), $a->getNativeData()); } /** * @test */ public function array_round_trip_091() { $this->setProtoVersion(Wire\Constants091::VERSION); $a = new Wire\AMQPArray($this->getTestDataSrc()); $this->assertEquals(array_values($this->getTestDataCmp()), $a->getNativeData()); } /** * @test */ public function array_round_trip_rabbit() { $this->setProtoVersion(Wire\AMQPAbstractCollection::PROTOCOL_RBT); $a = new Wire\AMQPArray($this->getTestDataSrc()); $this->assertEquals(array_values($this->getTestDataCmp()), $a->getNativeData()); } /** * @test */ public function table_round_trip_080() { $this->setProtoVersion(Wire\Constants080::VERSION); $a = new Wire\AMQPTable($this->getTestDataSrc()); $this->assertEquals($this->getTestDataCmp080(), $a->getNativeData()); } /** * @test */ public function table_round_trip_091() { $this->setProtoVersion(Wire\Constants091::VERSION); $a = new Wire\AMQPTable($this->getTestDataSrc()); $this->assertEquals($this->getTestDataCmp(), $a->getNativeData()); } /** * @test */ public function table_round_trip_rabbit() { $this->setProtoVersion(Wire\AMQPAbstractCollection::PROTOCOL_RBT); $a = new Wire\AMQPTable($this->getTestDataSrc()); $this->assertEquals($this->getTestDataCmp(), $a->getNativeData()); } /** * @test */ public function iterator() { $d = [ 'a' => 1, 'b' => -2147, 'c' => [ 'foo' => 'bar', ], 'd' => true, 'e' => false, ]; $ed = [ 'a' => [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('I'), 1, ], 'b' => [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('I'), -2147, ], 'c' => [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('F'), [ 'foo' => [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('S'), 'bar', ], ], ], 'd' => [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('t'), true, ], 'e' => [ Wire\AMQPAbstractCollection::getDataTypeForSymbol('t'), false, ], ]; $this->setProtoVersion(Wire\Constants091::VERSION); $a = new Wire\AMQPTable($d); foreach ($a as $key => $val) { if (!isset($d[$key])) { $this->fail('Unknown key: '.$key); } $this->assertEquals( $ed[$key], $val[1] instanceof Wire\AMQPAbstractCollection ? [$val[0], $this->getEncodedRawData($val[1])] : $val ); } } protected function setProtoVersion($proto) { $r = new \ReflectionProperty('\\PhpAmqpLib\\Wire\\AMQPAbstractCollection', '_protocol'); $r->setAccessible(true); $r->setValue(null, $proto); } protected function getEncodedRawData(Wire\AMQPAbstractCollection $c, $recursive = true) { $r = new \ReflectionProperty($c, 'data'); $r->setAccessible(true); $data = $r->getValue($c); unset($r); if ($recursive) { foreach ($data as &$v) { if ($v[1] instanceof Wire\AMQPAbstractCollection) { $v[1] = $this->getEncodedRawData($v[1]); } } unset($v); } return $data; } protected function getTestDataSrc() { return [ 'long' => 12345, 'long_neg' => -12345, 'longlong' => 3000000000, 'longlong_neg' => -3000000000, 'float_low' => (float) 9.2233720368548, 'float_high' => (float) 9223372036854800000, 'bool_true' => true, 'bool_false' => false, 'void' => null, 'array' => [ 1, 2, 3, 'foo', ['bar' => 'baz'], ['boo', false, 5], true, null ], 'array_empty' => [], 'table' => [ 'foo' => 'bar', 'baz' => 'boo', 'bool' => true, 'tbl' => ['bar' => 'baz'], 'arr' => ['boo', false, 5], ], 'table_num' => [ 1 => 5, 3 => 'foo', 786 => 674, ], 'array_nested' => [ 1, [ 2, [ 3, [4], ], ], ], 'table_nested' => [ 'i' => 1, 'n' => [ 'i' => 2, 'n' => [ 'i' => 3, 'n' => [ 'i' => 4, ], ], ], ], ]; } /** * The only purpose of this *Cmp / *Cmp080 shit is to pass tests on travis's ancient phpunit 3.7.38. */ protected function getTestDataCmp() { return [ 'long' => 12345, 'long_neg' => -12345, 'longlong' => 3000000000, 'longlong_neg' => -3000000000, 'float_low' => (string) (float) 9.2233720368548, 'float_high' => (string) (float) 9223372036854800000, 'bool_true' => true, 'bool_false' => false, 'void' => null, 'array' => [ 1, 2, 3, 'foo', ['bar' => 'baz'], ['boo', false, 5], true, null ], 'array_empty' => [], 'table' => [ 'foo' => 'bar', 'baz' => 'boo', 'bool' => true, 'tbl' => ['bar' => 'baz'], 'arr' => ['boo', false, 5], ], 'table_num' => [ 1 => 5, 3 => 'foo', 786 => 674, ], 'array_nested' => [ 1, [ 2, [ 3, [4], ], ], ], 'table_nested' => [ 'i' => 1, 'n' => [ 'i' => 2, 'n' => [ 'i' => 3, 'n' => [ 'i' => 4, ], ], ], ], ]; } protected function getTestDataCmp080() { return [ 'long' => 12345, 'long_neg' => -12345, 'longlong' => (string) 3000000000, 'longlong_neg' => (string) -3000000000, 'float_low' => (string) (float) 9.2233720368548, 'float_high' => (string) (float) 9223372036854800000, 'bool_true' => 1, 'bool_false' => 0, 'void' => '', 'array' => [ 1, 2, 3, 'foo', ['bar' => 'baz'], ['boo', 0, 5], 1, '', ], 'array_empty' => [], 'table' => [ 'foo' => 'bar', 'baz' => 'boo', 'bool' => 1, 'tbl' => ['bar' => 'baz'], 'arr' => ['boo', 0, 5], ], 'table_num' => [ 1 => 5, 3 => 'foo', 786 => 674, ], 'array_nested' => [ 1, [ 2, [ 3, [4], ], ], ], 'table_nested' => [ 'i' => 1, 'n' => [ 'i' => 2, 'n' => [ 'i' => 3, 'n' => [ 'i' => 4, ], ], ], ], ]; } } php-amqplib-2.11.0/tests/Unit/Wire/AMQPDecimalTest.php000066400000000000000000000015201356514014400223630ustar00rootroot00000000000000assertEquals($decimal->asBCvalue(), 1); } /** * @test */ public function get_n() { $decimal = new AMQPDecimal(100, 2); $this->assertEquals($decimal->getN(), 100); } /** * @test */ public function get_e() { $decimal = new AMQPDecimal(100, 2); $this->assertEquals($decimal->getE(), 2); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPOutOfBoundsException */ public function negative_value() { new AMQPDecimal(100, -1); } } php-amqplib-2.11.0/tests/Unit/Wire/AMQPReaderTest.php000066400000000000000000000032121356514014400222270ustar00rootroot00000000000000setProtoVersion(Wire\Constants091::VERSION); } protected function setProtoVersion($proto) { $r = new \ReflectionProperty('\\PhpAmqpLib\\Wire\\AMQPAbstractCollection', '_protocol'); $r->setAccessible(true); $r->setValue(null, $proto); } public function tearDown() { } public function testReadBytes() { $expected = [ 'snowman' => ['x', "\x26\x03"] ]; $data = hex2bin('0000000f07736e6f776d616e78000000022603'); $reader = new AMQPReader($data); $parsed = $reader->read_table(); $this->assertEquals($expected, $parsed); } public function test32bitSignedIntegerOverflow() { $data = hex2bin('0000000080000000'); $reader = new AMQPReader($data); $parsed = $reader->read_signed_longlong(); if (PHP_INT_SIZE === 8) { $this->assertInternalType('integer', $parsed); $this->assertEquals(0x80000000, $parsed); } else { $this->assertInternalType('string', $parsed); $this->assertEquals('2147483648', $parsed); } } public function test64bitUnsignedIntegerOverflow() { $data = hex2bin(str_repeat('f', 16)); $reader = new AMQPReader($data); $parsed = $reader->read_longlong(); $this->assertInternalType('string', $parsed); $this->assertEquals('18446744073709551615', $parsed); } } php-amqplib-2.11.0/tests/Unit/Wire/AMQPWriterTest.php000066400000000000000000000100611356514014400223010ustar00rootroot00000000000000setProtoVersion(Wire\Constants091::VERSION); $this->writer = new AMQPWriter(); } public function tearDown() { $this->setProtoVersion(AMQPArray::PROTOCOL_RBT); $this->writer = null; } /** * @test */ public function write_array() { $this->writer->write_array([ 'rabbit@localhost', 'hare@localhost', 42, true ]); $out = $this->writer->getvalue(); $expected = "\x00\x00\x00\x2fS\x00\x00\x00\x10rabbit@localhostS\x00\x00\x00\x0Ehare@localhostI\x00\x00\x00\x2at\x01"; $this->assertEquals(51, mb_strlen($out, 'ASCII')); $this->assertEquals($expected, $out); } /** * @test */ public function write_AMQP_array() { $this->writer->write_array( new AMQPArray([ 'rabbit@localhost', 'hare@localhost', 42, true ]) ); $this->assertEquals( "\x00\x00\x00\x2fS\x00\x00\x00\x10rabbit@localhostS\x00\x00\x00\x0Ehare@localhostI\x00\x00\x00\x2at\x01", $this->writer->getvalue() ); } /** * @test */ public function write_table() { $this->writer->write_table([ 'x-foo' => ['S', 'bar'], 'x-bar' => ['A', ['baz', 'qux']], 'x-baz' => ['I', 42], 'x-true' => ['t', true], 'x-false' => ['t', false], 'x-shortshort' => ['b', -5], 'x-shortshort-u' => ['B', 5], 'x-short' => ['U', -1024], 'x-short-u' => ['u', 125], 'x-short-str' => ['s', 'foo'], 'x-bytes' => array('x', 'foobar'), ]); $out = $this->writer->getvalue(); $expected = "\x00\x00\x00\xa3\x05x-fooS\x00\x00\x00\x03bar\x05x-barA\x00\x00\x00\x10S\x00\x00\x00\x03bazS\x00\x00\x00\x03qux\x05x-bazI\x00\x00\x00\x2a\x06x-truet\x01\x07x-falset\x00" . "\X0cx-shortshortb\xfb\x0ex-shortshort-uB\x05\x07x-shortU\xfc\x00\x09x-short-uu\x00\x7d\x0bx-short-strs\x03foo\x07x-bytesx\x00\x00\x00\x06foobar"; $this->assertEquals($expected, $out); } /** * @test */ public function write_AMQP_table() { $t = new AMQPTable(); $t->set('x-foo', 'bar', AMQPTable::T_STRING_LONG); $t->set('x-bar', new AMQPArray(['baz', 'qux'])); $t->set('x-baz', 42, AMQPTable::T_INT_LONG); $t->set('x-true', true, AMQPTable::T_BOOL); $t->set('x-false', false, AMQPTable::T_BOOL); $t->set('x-shortshort', -5, AMQPTable::T_INT_SHORTSHORT); $t->set('x-shortshort-u', 5, AMQPTable::T_INT_SHORTSHORT_U); $t->set('x-short', -1024, AMQPTable::T_INT_SHORT); $t->set('x-short-u', 125, AMQPTable::T_INT_SHORT_U); $t->set('x-short-str', 'foo', AMQPTable::T_STRING_SHORT); $this->writer->write_table($t); $this->assertEquals( "\x00\x00\x00\x90\x05x-fooS\x00\x00\x00\x03bar\x05x-barA\x00\x00\x00\x10S\x00\x00\x00\x03bazS\x00\x00\x00\x03qux\x05x-bazI\x00\x00\x00\x2a\x06x-truet\x01\x07x-falset\x00" . "\X0cx-shortshortb\xfb\x0ex-shortshort-uB\x05\x07x-shortU\xfc\x00\x09x-short-uu\x00\x7d\x0bx-short-strs\x03foo", $this->writer->getvalue() ); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPOutOfRangeException */ public function write_table_with_invalid_type() { $this->writer->write_table([ 'x-foo' => ['_', 'bar'], ]); } protected function setProtoVersion($proto) { $r = new \ReflectionProperty('\\PhpAmqpLib\\Wire\\AMQPAbstractCollection', '_protocol'); $r->setAccessible(true); $r->setValue(null, $proto); } } php-amqplib-2.11.0/tests/Unit/Wire/IO/000077500000000000000000000000001356514014400173065ustar00rootroot00000000000000php-amqplib-2.11.0/tests/Unit/Wire/IO/SocketIOTest.php000066400000000000000000000036151356514014400223440ustar00rootroot00000000000000connect(); $ready = $socketIO->select(0, 0); $this->assertEquals(0, $ready); return $socketIO; } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPIOException */ public function connect_with_invalid_credentials() { $socket = new SocketIO('invalid_host', 5672); @$socket->connect(); } // TODO FUTURE re-enable test // php-amqplib/php-amqplib#648, php-amqplib/php-amqplib#666 // /** // * @test // * @expectedException \InvalidArgumentException // * @expectedExceptionMessage read_timeout must be greater than 2x the heartbeat // */ // public function read_timeout_must_be_greater_than_2x_the_heartbeat() // { // new SocketIO('localhost', 5512, 1); // } // /** // * @test // * @expectedException \InvalidArgumentException // * @expectedExceptionMessage send_timeout must be greater than 2x the heartbeat // */ // public function send_timeout_must_be_greater_than_2x_the_heartbeat() // { // new SocketIO('localhost', '5512', 30, true, 20, 10); // } /** * @test * @depends connect * @expectedException \PhpAmqpLib\Exception\AMQPSocketException */ public function read_when_closed(SocketIO $socketIO) { $socketIO->close(); $socketIO->read(1); } /** * @test * @depends connect * @expectedException \PhpAmqpLib\Exception\AMQPSocketException */ public function write_when_closed(SocketIO $socketIO) { $socketIO->write('data'); } } php-amqplib-2.11.0/tests/Unit/Wire/IO/StreamIOTest.php000066400000000000000000000022421356514014400223420ustar00rootroot00000000000000setAccessible(true); $resource = fopen('php://temp', 'r'); fclose($resource); $stream = new StreamIO('0.0.0.0', PORT, 0.1, 0.1, null, false, 0); $property->setValue($stream, $resource); $stream->select(0, 0); } } php-amqplib-2.11.0/tests/Unit/WireTest.php000066400000000000000000000417511356514014400203600ustar00rootroot00000000000000wr($value, 'write_bit', 'read_bit'); } /** * @dataProvider octetWrData * @test */ public function octet_wr($value) { $this->wr($value, 'write_octet', 'read_octet'); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPInvalidArgumentException */ public function octet_wr_out_of_range_lower() { $this->wr(-1, 'write_octet', 'read_octet'); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPInvalidArgumentException */ public function octet_wr_out_of_range_upper() { $this->wr(256, 'write_octet', 'read_octet'); } /** * @dataProvider signedOctetWrData * @test */ public function signed_octet_wr($value) { $this->wr($value, 'write_signed_octet', 'read_signed_octet'); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPInvalidArgumentException */ public function signed_octet_wr_out_of_range_lower() { $this->wr(-129, 'write_signed_octet', 'read_signed_octet'); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPInvalidArgumentException */ public function signed_octet_wr_out_of_range_upper() { $this->wr(128, 'write_signed_octet', 'read_signed_octet'); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPInvalidArgumentException * @expectedExceptionMessage Short out of range: 65536 */ public function short_wr() { $this->wr(65536, 'write_short', 'read_short'); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPInvalidArgumentException */ public function short_wr_out_of_range_lower() { $this->wr(-1, 'write_short', 'read_short'); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPInvalidArgumentException */ public function short_wr_out_of_range_upper() { $this->wr(65536, 'write_short', 'read_short'); } /** * @dataProvider signedShortWrData * @test */ public function signed_short_wr($value) { $this->wr($value, 'write_signed_short', 'read_signed_short'); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPInvalidArgumentException */ public function signed_short_wr_out_of_range_lower() { $this->wr(-32769, 'write_signed_short', 'read_signed_short'); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPInvalidArgumentException */ public function signed_short_wr_out_of_range_upper() { $this->wr(32768, 'write_signed_short', 'read_signed_short'); } /** * @dataProvider longWrData * @test */ public function long_wr($value) { $this->wr($value, 'write_long', 'read_long'); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPInvalidArgumentException */ public function long_wr_out_of_range_lower() { $this->wr(-1, 'write_long', 'read_long'); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPInvalidArgumentException */ public function long_wr_out_of_range_upper() { $this->wr('4294967296', 'write_long', 'read_long'); } /** * @dataProvider signedLongWrData * @test */ public function signed_long_wr($value) { $this->wr($value, 'write_signed_long', 'read_signed_long', true); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPInvalidArgumentException */ public function signed_long_wr_out_of_range_lower() { $this->wr('-2147483649', 'write_signed_long', 'read_signed_long', true); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPInvalidArgumentException */ public function signed_long_wr_out_of_range_upper() { $this->wr('2147483648', 'write_signed_long', 'read_signed_long', true); } /** * @dataProvider longlongWrData * @test */ public function longlong_wr($value) { $this->wr($value, 'write_longlong', 'read_longlong'); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPInvalidArgumentException */ public function longlong_wr_out_of_range_lower() { $this->wr('-1', 'write_longlong', 'read_longlong'); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPInvalidArgumentException */ public function longlong_wr_out_of_range_upper() { $this->wr('18446744073709551616', 'write_longlong', 'read_longlong'); } /** * @dataProvider signedLonglongWrData * @test */ public function signed_longlong_wr($value) { $this->wr($value, 'write_signed_longlong', 'read_signed_longlong'); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPInvalidArgumentException */ public function signed_longlong_wr_out_of_range_lower() { $this->wr('-9223372036854775809', 'write_signed_longlong', 'read_signed_longlong'); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPInvalidArgumentException */ public function signed_longlong_wr_out_of_range_upper() { $this->wr('9223372036854775808', 'write_signed_longlong', 'read_signed_longlong'); } /** * @dataProvider shortstrWrData * @test */ public function shortstr_wr($value) { $this->wr($value, 'write_shortstr', 'read_shortstr'); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPInvalidArgumentException */ public function shortstr_wr_out_of_range_ASCII() { $this->wr(str_repeat('z', 256), 'write_shortstr', 'read_shortstr'); } /** * @test * @expectedException \PhpAmqpLib\Exception\AMQPInvalidArgumentException */ public function shortstr_wr_out_of_range_utf_two_byte() { $this->wr(str_repeat("\xd0\xaf", 128), 'write_shortstr', 'read_shortstr'); } /** * @dataProvider longstrWrData * @test */ public function longstr_wr($value) { $this->wr($value, 'write_longstr', 'read_longstr'); } /** * @test */ public function array_wr_native() { $d = [ 1, -2147483648, 2147483647, true, false, [['foo', ['bar']]], [], ]; $w = new AMQPWriter(); $w->write_array($d); $r = new AMQPReader($w->getvalue()); $rd = $r->read_array(); $this->assertEquals($d, $rd); } /** * @test */ public function array_wr_collection() { $w = new AMQPWriter(); $w->write_array( new AMQPArray( [ 12345, -12345, 3000000000, -3000000000, 9.2233720368548, (float)9223372036854800000, true, false, [1, 2, 3, 'foo', ['bar' => 'baz'], ['boo', false, 5], true], [], [ 'foo' => 'bar', 'baz' => 'boo', 'bool' => true, 'tbl' => ['bar' => 'baz'], 'arr' => ['boo', false, 5] ], [1 => 5, 3 => 'foo', 786 => 674], [1, [2, [3, [4]]]], ['i' => 1, 'n' => ['i' => 2, 'n' => ['i' => 3, 'n' => ['i' => 4]]]] ] ) ); $r = new AMQPReader($w->getvalue()); //type casting - thanks to ancient phpunit on travis $this->assertEquals( [ 12345, -12345, (string)3000000000, (string)-3000000000, (string)(float)9.2233720368548, (string)(float)9223372036854800000, true, false, [1, 2, 3, 'foo', ['bar' => 'baz'], ['boo', false, 5], true], [], [ 'foo' => 'bar', 'baz' => 'boo', 'bool' => true, 'tbl' => ['bar' => 'baz'], 'arr' => ['boo', false, 5] ], [1 => 5, 3 => 'foo', 786 => 674], [1, [2, [3, [4]]]], ['i' => 1, 'n' => ['i' => 2, 'n' => ['i' => 3, 'n' => ['i' => 4]]]] ], $r->read_array(true)->getNativeData() ); } /** * @test */ public function table_wr_native() { $d = [ 'a' => ['I', 1], 'b' => ['I', -2147483648], 'c' => ['I', 2147483647], 'd' => ['l', '-2147483649'], 'e' => ['l', '2147483648'], 'f' => ['t', true], 'g' => ['t', false], 'h' => ['F', ['foo' => ['S', 'baz']]], 'i' => ['A', [['foo', ['bar']]]], 'j' => ['A', []], ]; $w = new AMQPWriter(); $w->write_table($d); $r = new AMQPReader($w->getvalue()); $rd = $r->read_table(); $this->assertEquals($d, $rd); } /** * @test */ public function table_wr_collection() { $w = new AMQPWriter(); $w->write_table( new AMQPTable( [ 'long' => 12345, 'long_neg' => -12345, 'longlong' => 3000000000, 'longlong_neg' => -3000000000, 'float_low' => 9.2233720368548, 'float_high' => (float)9223372036854800000, 'bool_true' => true, 'bool_false' => false, 'array' => [1, 2, 3, 'foo', ['bar' => 'baz'], ['boo', false, 5], true], 'array_empty' => [], 'table' => [ 'foo' => 'bar', 'baz' => 'boo', 'bool' => true, 'tbl' => ['bar' => 'baz'], 'arr' => ['boo', false, 5] ], 'table_num' => [1 => 5, 3 => 'foo', 786 => 674], 'array_nested' => [1, [2, [3, [4]]]], 'table_nested' => [ 'i' => 1, 'n' => ['i' => 2, 'n' => ['i' => 3, 'n' => ['i' => 4]]], ], ] ) ); $r = new AMQPReader($w->getvalue()); //type casting - thanks to ancient phpunit on travis $this->assertEquals( [ 'long' => 12345, 'long_neg' => -12345, 'longlong' => (string)3000000000, 'longlong_neg' => (string)-3000000000, 'float_low' => (string)(float)9.2233720368548, 'float_high' => (string)(float)9223372036854800000, 'bool_true' => true, 'bool_false' => false, 'array' => [1, 2, 3, 'foo', ['bar' => 'baz'], ['boo', false, 5], true], 'array_empty' => [], 'table' => [ 'foo' => 'bar', 'baz' => 'boo', 'bool' => true, 'tbl' => ['bar' => 'baz'], 'arr' => ['boo', false, 5] ], 'table_num' => [1 => 5, 3 => 'foo', 786 => 674], 'array_nested' => [1, [2, [3, [4]]]], 'table_nested' => [ 'i' => 1, 'n' => ['i' => 2, 'n' => ['i' => 3, 'n' => ['i' => 4]]] ] ], $r->read_table(true)->getNativeData() ); } public function bitWrData() { return [ [true], [false], ]; } public function octetWrData() { $data = []; for ($i = 0; $i <= 255; $i++) { $data[] = [$i]; } return $data; } public function signedOctetWrData() { $data = []; for ($i = -128; $i <= 127; $i++) { $data[] = [$i]; } return $data; } public function signedShortWrData() { return [ [-32768], [-32767], [32766], [32767], ]; } public function longWrData() { $max = PHP_INT_SIZE === 8 ? 4294967295 : PHP_INT_MAX; return [ [0], [1], [2], [2147483646], [2147483647], [2147483648], [$max - 1], [$max], ['0'], ['1'], ['2'], ['2147483646'], ['2147483647'], ['2147483648'], ['4294967293'], ['4294967294'], ['4294967295'], ]; } public function signedLongWrData() { return [ [-2147483648], [-2147483647], [-2], [-1], [0], [1], [2], [2147483646], [2147483647], ['-2147483648'], ['-2147483647'], ['-2147483646'], ['-2'], ['-1'], ['0'], ['1'], ['2'], ['2147483645'], ['2147483646'], ['2147483647'], ]; } public function longlongWrData() { return [ [0], [1], [2], [PHP_INT_MAX - 1], [PHP_INT_MAX], ['0'], ['1'], ['2'], ['2147483646'], ['2147483647'], ['2147483648'], ['4294967294'], ['4294967295'], ['4294967296'], ['9223372036854775806'], ['9223372036854775807'], ['9223372036854775808'], ['18446744073709551613'], ['18446744073709551614'], ['18446744073709551615'], ]; } public function signedLonglongWrData() { $min = defined('PHP_INT_MIN') ? PHP_INT_MIN : ~PHP_INT_MAX; return [ [$min], [$min + 1], ['-9223372036854775808'], ['-9223372036854775807'], ['-9223372036854775806'], ['-4294967297'], ['-4294967296'], ['-4294967295'], ['-2147483649'], ['-2147483648'], ['-2147483647'], ['-2'], ['-1'], [-1], ['0'], [0], ['1'], [1], ['2'], ['2147483646'], [2147483646], ['2147483647'], [2147483647], // 32-bit PHP_INT_MAX ['2147483648'], [2147483648], // float on 32-bit systems ['4294967294'], ['4294967295'], ['4294967296'], ['9223372036854775805'], ['9223372036854775806'], ['9223372036854775807'], [PHP_INT_MAX - 1], [PHP_INT_MAX], ]; } public function shortstrWrData() { return [ ['a'], ['üıß∑œ´®†¥¨πøˆ¨¥†®'], ]; } public function longstrWrData() { return [ ['a'], ['üıß∑œ´®†¥¨πøˆ¨¥†®'], [ 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz' . 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz' . 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz' ] ]; } protected function wr($value, $write_method, $read_method, $reflection = false) { $writer = new AMQPWriter(); if ($reflection) { $m = new \ReflectionMethod($writer, $write_method); $m->setAccessible(true); $m->invoke($writer, $value); } else { $writer->{$write_method}($value); } $reader = new AMQPReader($writer->getvalue()); if ($reflection) { $m = new \ReflectionMethod($reader, $read_method); $m->setAccessible(true); $readValue = $m->invoke($reader); } else { $readValue = $reader->{$read_method}(); } $this->assertEquals( $value, $readValue, 'Written: ' . bin2hex($writer->getvalue()) . ', read: ' . bin2hex($readValue) ); } } php-amqplib-2.11.0/tests/bootstrap.php000066400000000000000000000001371356514014400177010ustar00rootroot00000000000000 $value) { echo sprintf('%-30s', $name), $value, PHP_EOL; }