pax_global_header00006660000000000000000000000064126574071170014524gustar00rootroot0000000000000052 comment=2acff762b2cd15e5a57fce7e3ea6e8d8fb3d7171 php-amqplib-2.6.1/000077500000000000000000000000001265740711700137445ustar00rootroot00000000000000php-amqplib-2.6.1/CHANGELOG.md000066400000000000000000000012401265740711700155520ustar00rootroot00000000000000# Changelog All Notable changes to `PhpAmqpLib` will be documented in this file ## 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.6.1/CONTRIBUTING.md000066400000000000000000000022551265740711700162010ustar00rootroot00000000000000# Contributing Contributions are **welcome** and will be fully **credited**. We accept contributions via Pull Requests on [Github](https://github.com/videlalvaro/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 ``` bash $ phpunit ``` **Happy coding**! php-amqplib-2.6.1/CREDITS000066400000000000000000000004671265740711700147730ustar00rootroot00000000000000 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.6.1/LICENSE000066400000000000000000000575061265740711700147660ustar00rootroot00000000000000 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.6.1/PhpAmqpLib/000077500000000000000000000000001265740711700157415ustar00rootroot00000000000000php-amqplib-2.6.1/PhpAmqpLib/Channel/000077500000000000000000000000001265740711700173115ustar00rootroot00000000000000php-amqplib-2.6.1/PhpAmqpLib/Channel/AMQPChannel.php000066400000000000000000001135531265740711700220610ustar00rootroot00000000000000get_free_channel_id(); } parent::__construct($connection, $channel_id); $this->publish_cache = array(); $this->publish_cache_max_size = 100; $this->debug->debug_msg('using channel_id: ' . $channel_id); $this->default_ticket = 0; $this->is_open = false; $this->active = true; // Flow control $this->alerts = array(); $this->callbacks = array(); $this->auto_decode = $auto_decode; try { $this->x_open(); } catch (\Exception $e) { $this->close(); throw $e; } } /** * 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; } /** * 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 $args */ protected function channel_alert($args) { $reply_code = $args->read_short(); $reply_text = $args->read_shortstr(); $details = $args->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 * @return mixed */ public function close($reply_code = 0, $reply_text = '', $method_sig = array(0, 0)) { 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] ); $this->send_method_frame(array($class_id, $method_id), $args); return $this->wait(array( $this->waitHelper->get_wait('channel.close_ok') )); } /** * @param AMQPReader $args * @throws \PhpAmqpLib\Exception\AMQPProtocolChannelException */ protected function channel_close($args) { $reply_code = $args->read_short(); $reply_text = $args->read_shortstr(); $class_id = $args->read_short(); $method_id = $args->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 $args */ protected function channel_close_ok($args) { $this->do_close(); } /** * Enables/disables flow from peer * * @param $active * @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') )); } /** * @param AMQPReader $args */ protected function channel_flow($args) { $this->active = $args->read_bit(); $this->x_flow_ok($this->active); } /** * @param $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 $args * @return bool */ protected function channel_flow_ok($args) { return $args->read_bit(); } /** * @param string $out_of_band * @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') )); } /** * @param AMQPReader $args */ protected function channel_open_ok($args) { $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 * @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') )); } /** * Grants access to server resources * * @param AMQPReader $args * @return string */ protected function access_request_ok($args) { $this->default_ticket = $args->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 * @return mixed|null */ public function exchange_declare( $exchange, $type, $passive = false, $durable = false, $auto_delete = true, $internal = false, $nowait = false, $arguments = null, $ticket = null ) { $arguments = $this->getArguments($arguments); $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') )); } /** * Confirms an exchange declaration */ protected function exchange_declare_ok($args) { } /** * Deletes an exchange * * @param string $exchange * @param bool $if_unused * @param bool $nowait * @param null $ticket * @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') )); } /** * Confirms deletion of an exchange */ protected function exchange_delete_ok($args) { } /** * Binds dest exchange to source exchange * * @param string $destination * @param string $source * @param string $routing_key * @param bool $nowait * @param null $arguments * @param null $ticket * @return mixed|null */ public function exchange_bind( $destination, $source, $routing_key = '', $nowait = false, $arguments = null, $ticket = null ) { $arguments = $this->getArguments($arguments); $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') )); } /** * Confirms bind successful */ protected function exchange_bind_ok($args) { } /** * Unbinds dest exchange from source exchange * * @param string $destination * @param string $source * @param string $routing_key * @param null $arguments * @param null $ticket * @return mixed */ public function exchange_unbind($destination, $source, $routing_key = '', $arguments = null, $ticket = null) { $arguments = $this->getArguments($arguments); $ticket = $this->getTicket($ticket); list($class_id, $method_id, $args) = $this->protocolWriter->exchangeUnbind( $ticket, $destination, $source, $routing_key, $arguments ); $this->send_method_frame(array($class_id, $method_id), $args); return $this->wait(array( $this->waitHelper->get_wait('exchange.unbind_ok') )); } /** * Confirms unbind successful */ protected function exchange_unbind_ok($args) { } /** * Binds queue to an exchange * * @param string $queue * @param string $exchange * @param string $routing_key * @param bool $nowait * @param null $arguments * @param null $ticket * @return mixed|null */ public function queue_bind($queue, $exchange, $routing_key = '', $nowait = false, $arguments = null, $ticket = null) { $arguments = $this->getArguments($arguments); $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') )); } /** * Confirms bind successful */ protected function queue_bind_ok($args) { } /** * Unbind queue from an exchange * * @param string $queue * @param string $exchange * @param string $routing_key * @param null $arguments * @param null $ticket * @return mixed */ public function queue_unbind($queue, $exchange, $routing_key = '', $arguments = null, $ticket = null) { $arguments = $this->getArguments($arguments); $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') )); } /** * Confirms unbind successful */ protected function queue_unbind_ok($args) { } /** * 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 */ public function queue_declare( $queue = '', $passive = false, $durable = false, $exclusive = false, $auto_delete = true, $nowait = false, $arguments = null, $ticket = null ) { $arguments = $this->getArguments($arguments); $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') )); } /** * Confirms a queue definition * * @param AMQPReader $args * @return array */ protected function queue_declare_ok($args) { $queue = $args->read_shortstr(); $message_count = $args->read_long(); $consumer_count = $args->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 null $ticket * @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') )); } /** * Confirms deletion of a queue * * @param AMQPReader $args * @return string */ protected function queue_delete_ok($args) { return $args->read_long(); } /** * Purges a queue * * @param string $queue * @param bool $nowait * @param null $ticket * @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') )); } /** * Confirms a queue purge * * @param AMQPReader $args * @return string */ protected function queue_purge_ok($args) { return $args->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 $args * @throws AMQPRuntimeException */ protected function basic_ack_from_server(AMQPReader $args) { $delivery_tag = $args->read_longlong(); $multiple = (bool) $args->read_bit(); if (false === 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 $args * @throws AMQPRuntimeException */ protected function basic_nack_from_server($args) { $delivery_tag = $args->read_longlong(); $multiple = (bool) $args->read_bit(); if (false === 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 $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); $this->dispatch_to_handler($handler, array($message)); } } /** * @param array $array * @param $value * @return mixed */ protected function get_keys_less_or_equal(array $array, $value) { $keys = array_reduce( array_keys($array), function ($keys, $key) use ($value) { if (bccomp($key, $value, 0) <= 0) { $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 * @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') )); } /** * @param AMQPReader $args * @throws \PhpAmqpLib\Exception\AMQPBasicCancelException */ protected function basic_cancel_from_server(AMQPReader $args) { throw new AMQPBasicCancelException($args->read_shortstr()); } /** * Confirm a cancelled consumer * * @param AMQPReader $args * @return string */ protected function basic_cancel_ok($args) { $consumer_tag = $args->read_shortstr(); unset($this->callbacks[$consumer_tag]); return $consumer_tag; } /** * 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 callback|null $callback * @param int|null $ticket * @param array $arguments * @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 == '0.9.1' ? $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') )); } $this->callbacks[$consumer_tag] = $callback; return $consumer_tag; } /** * Confirms a new consumer * * @param AMQPReader $args * @return string */ protected function basic_consume_ok($args) { return $args->read_shortstr(); } /** * Notifies the client of a consumer message * * @param AMQPReader $args * @param AMQPMessage $msg */ protected function basic_deliver($args, $msg) { $consumer_tag = $args->read_shortstr(); $delivery_tag = $args->read_longlong(); $redelivered = $args->read_bit(); $exchange = $args->read_shortstr(); $routing_key = $args->read_shortstr(); $msg->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], $msg); } } /** * Direct access to a queue if no message was available in the queue, return null * * @param string $queue * @param bool $no_ack * @param null $ticket * @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') )); } /** * Indicates no messages available * * @param AMQPReader $args */ protected function basic_get_empty($args) { $cluster_id = $args->read_shortstr(); } /** * Provides client with a message * * @param AMQPReader $args * @param AMQPMessage $msg * @return AMQPMessage */ protected function basic_get_ok($args, $msg) { $delivery_tag = $args->read_longlong(); $redelivered = $args->read_bit(); $exchange = $args->read_shortstr(); $routing_key = $args->read_shortstr(); $message_count = $args->read_long(); $msg->delivery_info = array( 'delivery_tag' => $delivery_tag, 'redelivered' => $redelivered, 'exchange' => $exchange, 'routing_key' => $routing_key, 'message_count' => $message_count ); return $msg; } /** * @param string $exchange * @param string $routing_key * @param $mandatory * @param $immediate * @param $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 null $ticket */ public function basic_publish( $msg, $exchange = '', $routing_key = '', $mandatory = false, $immediate = false, $ticket = null ) { $pkt = new AMQPWriter(); $pkt->write($this->pre_publish($exchange, $routing_key, $mandatory, $immediate, $ticket)); $this->connection->send_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 = bcadd($this->next_delivery_tag, '1', 0); } } /** * @param AMQPMessage $msg * @param string $exchange * @param string $routing_key * @param bool $mandatory * @param bool $immediate * @param 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 = bcadd($this->next_delivery_tag, '1', 0); } } //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 * @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') )); } /** * Confirms QoS request */ protected function basic_qos_ok($args) { } /** * Redelivers unacknowledged messages * * @param bool $requeue * @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') )); } /** * Confirm the requested recover */ protected function basic_recover_ok($args) { } /** * 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 $args * @param AMQPMessage $msg * @return null */ protected function basic_return($args, $msg) { $reply_code = $args->read_short(); $reply_text = $args->read_shortstr(); $exchange = $args->read_shortstr(); $routing_key = $args->read_shortstr(); $callback = $this->basic_return_callback; if (!is_callable($callback)) { $this->debug->debug_msg('Skipping unhandled basic_return message'); return null; } call_user_func_array($callback, array( $reply_code, $reply_text, $exchange, $routing_key, $msg, )); } /** * @return mixed */ public function tx_commit() { $this->send_method_frame(array(90, 20)); return $this->wait(array( $this->waitHelper->get_wait('tx.commit_ok') )); } /** * Confirms a successful commit */ protected function tx_commit_ok($args) { } /** * Rollbacks the current transaction * * @return mixed */ public function tx_rollback() { $this->send_method_frame(array(90, 30)); return $this->wait(array( $this->waitHelper->get_wait('tx.rollback_ok') )); } /** * Confirms a successful rollback */ protected function tx_rollback_ok($args) { } /** * Puts the channel into confirm mode * Beware that only non-transactional channels may be put into confirm mode and vice versa * * @param bool $nowait */ 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'))); $this->next_delivery_tag = 1; } /** * Confirms a selection * * @return void */ public function confirm_select_ok() { } /** * Waits for pending acks and nacks from the server. * If there are no pending acks, the method returns immediately * * @param int $timeout Waits until $timeout value is reached */ public function wait_for_pending_acks($timeout = 0) { $functions = array( $this->waitHelper->get_wait('basic.ack'), $this->waitHelper->get_wait('basic.nack'), ); while (count($this->published_messages) !== 0) { if ($timeout > 0) { $this->wait($functions, true, $timeout); } else { $this->wait($functions); } } } /** * Waits for pending acks, nacks and returns from the server. If there are no pending acks, the method returns immediately. * * @param int $timeout If set to value > 0 the method will wait at most $timeout seconds for pending acks. */ 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'), ); while (count($this->published_messages) !== 0) { if ($timeout > 0) { $this->wait($functions, true, $timeout); } else { $this->wait($functions); } } } /** * Selects standard transaction mode * * @return mixed */ public function tx_select() { $this->send_method_frame(array(90, 10)); return $this->wait(array( $this->waitHelper->get_wait('tx.select_ok') )); } /** * Confirms transaction mode */ protected function tx_select_ok($args) { } /** * @param mixed $arguments * @return array|mixed */ protected function getArguments($arguments) { return (null === $arguments) ? array() : $arguments; } /** * @param mixed $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 $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.6.1/PhpAmqpLib/Channel/AbstractChannel.php000066400000000000000000000351371265740711700230670ustar00rootroot00000000000000connection = $connection; $this->channel_id = $channel_id; $connection->channels[$channel_id] = $this; $this->frame_queue = array(); // Lower level queue for frames $this->method_queue = array(); // Higher level queue for methods $this->auto_decode = false; $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 self::PROTOCOL_091: self::$PROTOCOL_CONSTANTS_CLASS = 'PhpAmqpLib\Wire\Constants091'; $c = self::$PROTOCOL_CONSTANTS_CLASS; $this->debug = new DebugHelper($c); $this->amqp_protocol_header = $c::$AMQP_PROTOCOL_HEADER; $this->protocolWriter = new Protocol091(); $this->waitHelper = new Wait091(); $this->methodMap = new MethodMap091(); break; case self::PROTOCOL_080: self::$PROTOCOL_CONSTANTS_CLASS = 'PhpAmqpLib\Wire\Constants080'; $c = self::$PROTOCOL_CONSTANTS_CLASS; $this->debug = new DebugHelper($c); $this->amqp_protocol_header = $c::$AMQP_PROTOCOL_HEADER; $this->protocolWriter = new Protocol080(); $this->waitHelper = new Wait080(); $this->methodMap = new MethodMap080(); break; default: throw new AMQPRuntimeException(sprintf( 'Protocol: %s not implemented.', $this->protocolVersion )); break; } } /** * @return string * @throws AMQPOutOfRangeException */ public static function getProtocolVersion() { $protocol = defined('AMQP_PROTOCOL') ? AMQP_PROTOCOL : self::PROTOCOL_091; //adding check here to catch unknown protocol ASAP, as this method may be called from the outside if (!in_array($protocol, array(self::PROTOCOL_080, self::PROTOCOL_091), 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; } /** * @param string $method_sig * @param string $args * @param $content * @return mixed * @throws \PhpAmqpLib\Exception\AMQPRuntimeException */ public function dispatch($method_sig, $args, $content) { if (!$this->methodMap->valid_method($method_sig)) { throw new AMQPRuntimeException(sprintf( 'Unknown AMQP method "%s"', $method_sig )); } $amqp_method = $this->methodMap->get_method($method_sig); if (!method_exists($this, $amqp_method)) { throw new AMQPRuntimeException(sprintf( 'Method: "%s" not implemented by class: %s', $amqp_method, get_class($this) )); } $this->dispatch_reader->reuse($args); if ($content == null) { return call_user_func(array($this, $amqp_method), $this->dispatch_reader); } return call_user_func(array($this, $amqp_method), $this->dispatch_reader, $content); } /** * @param int $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 $method_sig * @param string $args */ protected function send_method_frame($method_sig, $args = '') { $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 $method_sig * @param string $args * @param null $pkt * @return null|\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')); // $payload_reader = new AMQPReader(substr($payload,0,12)); $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 (bccomp($message->getBodySize(), $bodyReceivedBytes, 0) == 1) { list($frame_type, $payload) = $this->next_frame(); $this->validate_body_frame($frame_type); $bodyReceivedBytes = bcadd($bodyReceivedBytes, mb_strlen($payload, 'ASCII'), 0); if (is_int($this->maxBodySize) && $bodyReceivedBytes > $this->maxBodySize ) { $message->setIsTruncated(true); continue; } $bodyChunks[] = $payload; } $message->setBody(implode('', $bodyChunks)); $messageEncoding = $message->getContentEncoding(); if ($this->auto_decode && !empty($messageEncoding)) { try { // Where does the decode() method come from if body is a string? $decodedBody = $message->getBody()->decode($messageEncoding); $message->setBody($decodedBody); } catch (\Exception $e) { $this->debug->debug_msg('Ignoring body decoding exception: ' . $e->getMessage()); } } 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 $timeout * @throws \PhpAmqpLib\Exception\AMQPOutOfBoundsException * @throws \PhpAmqpLib\Exception\AMQPRuntimeException * @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']); } // No deferred methods? wait for new ones while (true) { list($frame_type, $payload) = $this->next_frame($timeout); $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); $content = $this->maybe_wait_for_content($method_sig); if ($this->should_dispatch_method($allowed_methods, $method_sig)) { return $this->dispatch($method_sig, $args, $content); } // 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, $content); if ($non_blocking) { break; } } } 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); } 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 $frame_type * @throws \PhpAmqpLib\Exception\AMQPRuntimeException */ protected function validate_method_frame($frame_type) { $this->validate_frame($frame_type, 1, 'AMQP method'); } protected function validate_header_frame($frame_type) { $this->validate_frame($frame_type, 2, 'AMQP Content header'); } protected function validate_body_frame($frame_type) { $this->validate_frame($frame_type, 3, 'AMQP Content body'); } protected function validate_frame($frame_type, $expected_type, $expected_msg) { if ($frame_type != $expected_type) { $PROTOCOL_CONSTANTS_CLASS = self::$PROTOCOL_CONSTANTS_CLASS; throw new AMQPRuntimeException(sprintf( 'Expecting %s, received frame type %s (%s)', $expected_msg, $frame_type, $PROTOCOL_CONSTANTS_CLASS::$FRAME_TYPES[$frame_type] )); } } /** * @param $payload * @throws \PhpAmqpLib\Exception\AMQPOutOfBoundsException */ protected function validate_frame_payload($payload) { if (mb_strlen($payload, 'ASCII') < 4) { throw new AMQPOutOfBoundsException('Method frame too short'); } } 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]); } protected function extract_args($payload) { return mb_substr($payload, 4, mb_strlen($payload, 'ASCII') - 4, 'ASCII'); } protected function should_dispatch_method($allowed_methods, $method_sig) { $PROTOCOL_CONSTANTS_CLASS = self::$PROTOCOL_CONSTANTS_CLASS; return $allowed_methods == null || in_array($method_sig, $allowed_methods) || in_array($method_sig, $PROTOCOL_CONSTANTS_CLASS::$CLOSE_METHODS); } protected function maybe_wait_for_content($method_sig) { $PROTOCOL_CONSTANTS_CLASS = self::$PROTOCOL_CONSTANTS_CLASS; $content = null; if (in_array($method_sig, $PROTOCOL_CONSTANTS_CLASS::$CONTENT_METHODS)) { $content = $this->wait_content(); } return $content; } /** * @param $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.6.1/PhpAmqpLib/Connection/000077500000000000000000000000001265740711700200405ustar00rootroot00000000000000php-amqplib-2.6.1/PhpAmqpLib/Connection/AMQPConnection.php000066400000000000000000000002421265740711700233250ustar00rootroot00000000000000connect(); return parent::getSocket(); } /** * {@inheritdoc} */ public function channel($channel_id = null) { $this->connect(); return parent::channel($channel_id); } /** * @return null|\PhpAmqpLib\Wire\IO\AbstractIO */ protected function getIO() { if (!$this->io) { $this->connect(); } return $this->io; } /** * Should the connection be attempted during construction? * * @return bool */ public function connectOnConstruct() { return false; } } php-amqplib-2.6.1/PhpAmqpLib/Connection/AMQPSSLConnection.php000066400000000000000000000032571265740711700237200ustar00rootroot00000000000000create_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'] : 3, $ssl_context, isset($options['keepalive']) ? $options['keepalive'] : false, isset($options['heartbeat']) ? $options['heartbeat'] : 0 ); } /** * @param $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.6.1/PhpAmqpLib/Connection/AMQPSocketConnection.php000066400000000000000000000020321265740711700244750ustar00rootroot00000000000000construct_params = func_get_args(); } } php-amqplib-2.6.1/PhpAmqpLib/Connection/AbstractConnection.php000066400000000000000000000627101265740711700243420ustar00rootroot00000000000000 array('S', 'AMQPLib'), 'platform' => array('S', 'PHP'), 'version' => array('S', '2.4'), '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[] */ 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 AMQPWriter */ protected $login_response; /** @var string */ protected $locale; /** @var int */ protected $heartbeat; /** @var SocketIO */ protected $sock; /** @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; /** * 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; /** @var int Maximal size of $prepare_content_cache */ private $prepare_content_cache_max_size; /** * @param string $user * @param string $password * @param string $vhost * @param bool $insist * @param string $login_method * @param null $login_response * @param string $locale * @param AbstractIO $io * @param int $heartbeat * @throws \Exception */ public function __construct( $user, $password, $vhost = '/', $insist = false, $login_method = 'AMQPLAIN', $login_response = null, $locale = 'en_US', AbstractIO $io, $heartbeat = 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; if ($user && $password) { $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 { $this->login_response = null; } $this->prepare_content_cache = array(); $this->prepare_content_cache_max_size = 100; // 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->getIO()->connect(); $this->channels = array(); // The connection object itself is treated as channel 0 parent::__construct($this, 0); $this->input = new AMQPReader(null, $this->getIO()); $this->write($this->amqp_protocol_header); $this->wait(array($this->waitHelper->get_wait('connection.start'))); $this->x_start_ok(self::$LIBRARY_PROPERTIES, $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') )); } $host = $this->x_open($this->vhost, '', $this->insist); if (!$host) { 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(); 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->getIO()->reconnect(); $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) { return $this->getIO()->select($sec, $usec); } /** * 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->debug_msg('closing input'); if (!is_null($this->input)) { $this->input->close(); $this->input = null; } } protected function close_socket() { $this->debug->debug_msg('closing socket'); if (!is_null($this->getIO())) { $this->getIO()->close(); } } /** * @param $data */ public function write($data) { $this->debug->debug_hexdump($data); try { $this->getIO()->write($data); } catch (AMQPRuntimeException $e) { $this->setIsConnected(false); throw $e; } } protected function do_close() { $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 $channel * @param $method_sig * @param 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 $channel * @param $method_sig * @param string $args * @param AMQPWriter $pkt * @return null|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 $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 AMQPRuntimeException('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(); $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) { $this->input->setTimeout($currentTimeout); throw $e; } $this->input->setTimeout($currentTimeout); if ($ch != 0xCE) { throw new AMQPRuntimeException(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 $timeout * @return array */ protected function wait_channel($channel_id, $timeout = 0) { // Keeping the original timeout unchanged. $_timeout = $timeout; while (true) { $now = time(); list($frame_type, $frame_channel, $payload) = $this->wait_frame($_timeout); if ($frame_channel === 0 && $frame_type === 8) { // skip heartbeat frames and reduce the timeout by the time passed if($_timeout > 0) { $_timeout -= time() - $now; if($_timeout <= 0) { // If timeout has been reached, throw the exception without calling wait_frame throw new AMQPTimeoutException("Timeout waiting on channel"); } } continue; } else { 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 string $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); $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)) { if (!$this->protocolWriter || !$this->isConnected()) { return null; } $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); $this->setIsConnected(false); return $this->wait(array( $this->waitHelper->get_wait('connection.close_ok') )); } /** * @param AMQPReader $args * @throws \PhpAmqpLib\Exception\AMQPProtocolConnectionException */ protected function connection_close($args) { $reply_code = $args->read_short(); $reply_text = $args->read_shortstr(); $class_id = $args->read_short(); $method_id = $args->read_short(); $this->x_close_ok(); throw new AMQPProtocolConnectionException($reply_code, $reply_text, array($class_id, $method_id)); } /** * 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 */ 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 == '0.8') { $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 */ 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 $client_properties * @param $mechanism * @param $response * @param $locale */ protected function x_start_ok($client_properties, $mechanism, $response, $locale) { $args = new AMQPWriter(); $args->write_table($client_properties); $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 $channel_max * @param $frame_max * @param $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 SocketIO */ public function getSocket() { return $this->io->getSocket(); } /** * @return \PhpAmqpLib\Wire\IO\AbstractIO */ protected function getIO() { return $this->io; } /** * 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 */ 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; } } php-amqplib-2.6.1/PhpAmqpLib/Exception/000077500000000000000000000000001265740711700176775ustar00rootroot00000000000000php-amqplib-2.6.1/PhpAmqpLib/Exception/AMQPBasicCancelException.php000066400000000000000000000005071265740711700250770ustar00rootroot00000000000000consumerTag = $consumerTag; } } php-amqplib-2.6.1/PhpAmqpLib/Exception/AMQPChannelException.php000066400000000000000000000002341265740711700243150ustar00rootroot00000000000000amqp_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; $ms = MiscHelper::methodSig($method_sig); $PROTOCOL_CONSTANTS_CLASS = AbstractChannel::$PROTOCOL_CONSTANTS_CLASS; $mn = isset($PROTOCOL_CONSTANTS_CLASS::$GLOBAL_METHOD_NAMES[$ms]) ? $PROTOCOL_CONSTANTS_CLASS::$GLOBAL_METHOD_NAMES[$ms] : $mn = ''; $this->args = array($reply_code, $reply_text, $method_sig, $mn); } } php-amqplib-2.6.1/PhpAmqpLib/Exception/AMQPExceptionInterface.php000066400000000000000000000001141265740711700246420ustar00rootroot00000000000000amqp_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; $ms = MiscHelper::methodSig($method_sig); $PROTOCOL_CONSTANTS_CLASS = AbstractChannel::$PROTOCOL_CONSTANTS_CLASS; $mn = isset($PROTOCOL_CONSTANTS_CLASS::$GLOBAL_METHOD_NAMES[$ms]) ? $PROTOCOL_CONSTANTS_CLASS::$GLOBAL_METHOD_NAMES[$ms] : $mn = ''; $this->args = array($reply_code, $reply_text, $method_sig, $mn); } } php-amqplib-2.6.1/PhpAmqpLib/Exception/AMQPRuntimeException.php000066400000000000000000000002021265740711700243630ustar00rootroot00000000000000debug = defined('AMQP_DEBUG') ? AMQP_DEBUG : false; $this->PROTOCOL_CONSTANTS_CLASS = $PROTOCOL_CONSTANTS_CLASS; } public function debug_msg($msg) { if ($this->debug) { $this->print_msg($msg); } } 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); } public function debug_method_signature1($method_sig) { $this->debug_method_signature('< %s:', $method_sig); } public function debug_method_signature($msg, $method_sig) { if ($this->debug) { $PROTOCOL_CONSTANTS_CLASS = $this->PROTOCOL_CONSTANTS_CLASS; $this->debug_msg(sprintf( $msg . ': %s', MiscHelper::methodSig($method_sig), $PROTOCOL_CONSTANTS_CLASS::$GLOBAL_METHOD_NAMES[MiscHelper::methodSig($method_sig)] )); } } 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) )); } } 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) )); } } protected function print_msg($s) { echo $s . PHP_EOL; } }php-amqplib-2.6.1/PhpAmqpLib/Helper/MiscHelper.php000066400000000000000000000102311265740711700217210ustar00rootroot00000000000000 * @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 */ 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 $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.6.1/PhpAmqpLib/Helper/Protocol/000077500000000000000000000000001265740711700207615ustar00rootroot00000000000000php-amqplib-2.6.1/PhpAmqpLib/Helper/Protocol/MethodMap080.php000066400000000000000000000073501265740711700236050ustar00rootroot00000000000000 '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', ); public function get_method($method_sig) { return $this->method_map[$method_sig]; } public function valid_method($method_sig) { return array_key_exists($method_sig, $this->method_map); } } php-amqplib-2.6.1/PhpAmqpLib/Helper/Protocol/MethodMap091.php000066400000000000000000000054311265740711700236050ustar00rootroot00000000000000 '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', ); public function get_method($method_sig) { return $this->method_map[$method_sig]; } public function valid_method($method_sig) { return array_key_exists($method_sig, $this->method_map); } } php-amqplib-2.6.1/PhpAmqpLib/Helper/Protocol/Protocol080.php000066400000000000000000000641601265740711700235320ustar00rootroot00000000000000write_octet($version_major); $args->write_octet($version_minor); $args->write_table(empty($server_properties) ? array() : $server_properties); $args->write_longstr($mechanisms); $args->write_longstr($locales); return array(10, 10, $args); } /** * @param AMQPReader $args * @return array */ public static function connectionStartOk($args) { $ret = array(); $ret[] = $args->read_table(); $ret[] = $args->read_shortstr(); $ret[] = $args->read_longstr(); $ret[] = $args->read_shortstr(); return $ret; } /** * @return array */ public function connectionSecure($challenge) { $args = new AMQPWriter(); $args->write_longstr($challenge); return array(10, 20, $args); } /** * @param AMQPReader $args * @return array */ public static function connectionSecureOk($args) { $ret = array(); $ret[] = $args->read_longstr(); return $ret; } /** * @return array */ public function connectionTune($channel_max = 0, $frame_max = 0, $heartbeat = 0) { $args = new AMQPWriter(); $args->write_short($channel_max); $args->write_long($frame_max); $args->write_short($heartbeat); return array(10, 30, $args); } /** * @param AMQPReader $args * @return array */ public static function connectionTuneOk($args) { $ret = array(); $ret[] = $args->read_short(); $ret[] = $args->read_long(); $ret[] = $args->read_short(); return $ret; } /** * @return array */ public function connectionOpen($virtual_host = '/', $capabilities = '', $insist = false) { $args = new AMQPWriter(); $args->write_shortstr($virtual_host); $args->write_shortstr($capabilities); $args->write_bits(array($insist)); return array(10, 40, $args); } /** * @param AMQPReader $args * @return array */ public static function connectionOpenOk($args) { $ret = array(); $ret[] = $args->read_shortstr(); return $ret; } /** * @return array */ public function connectionRedirect($host, $known_hosts = '') { $args = new AMQPWriter(); $args->write_shortstr($host); $args->write_shortstr($known_hosts); return array(10, 50, $args); } /** * @return array */ public function connectionClose($reply_code, $reply_text = '', $class_id, $method_id) { $args = new AMQPWriter(); $args->write_short($reply_code); $args->write_shortstr($reply_text); $args->write_short($class_id); $args->write_short($method_id); return array(10, 60, $args); } /** * @param AMQPReader $args * @return array */ public static function connectionCloseOk($args) { $ret = array(); return $ret; } /** * @return array */ public function channelOpen($out_of_band = '') { $args = new AMQPWriter(); $args->write_shortstr($out_of_band); return array(20, 10, $args); } /** * @param AMQPReader $args * @return array */ public static function channelOpenOk($args) { $ret = array(); return $ret; } /** * @return array */ public function channelFlow($active) { $args = new AMQPWriter(); $args->write_bits(array($active)); return array(20, 20, $args); } /** * @param AMQPReader $args * @return array */ public static function channelFlowOk($args) { $ret = array(); $ret[] = $args->read_bit(); return $ret; } /** * @return array */ public function channelAlert($reply_code, $reply_text = '', $details = array()) { $args = new AMQPWriter(); $args->write_short($reply_code); $args->write_shortstr($reply_text); $args->write_table(empty($details) ? array() : $details); return array(20, 30, $args); } /** * @return array */ public function channelClose($reply_code, $reply_text = '', $class_id, $method_id) { $args = new AMQPWriter(); $args->write_short($reply_code); $args->write_shortstr($reply_text); $args->write_short($class_id); $args->write_short($method_id); return array(20, 40, $args); } /** * @param AMQPReader $args * @return array */ public static function channelCloseOk($args) { $ret = array(); return $ret; } /** * @return array */ public function accessRequest($realm = '/data', $exclusive = false, $passive = true, $active = true, $write = true, $read = true) { $args = new AMQPWriter(); $args->write_shortstr($realm); $args->write_bits(array($exclusive, $passive, $active, $write, $read)); return array(30, 10, $args); } /** * @param AMQPReader $args * @return array */ public static function accessRequestOk($args) { $ret = array(); $ret[] = $args->read_short(); return $ret; } /** * @return array */ public function exchangeDeclare($ticket = 1, $exchange, $type = 'direct', $passive = false, $durable = false, $auto_delete = false, $internal = false, $nowait = false, $arguments = array()) { $args = new AMQPWriter(); $args->write_short($ticket); $args->write_shortstr($exchange); $args->write_shortstr($type); $args->write_bits(array($passive, $durable, $auto_delete, $internal, $nowait)); $args->write_table(empty($arguments) ? array() : $arguments); return array(40, 10, $args); } /** * @param AMQPReader $args * @return array */ public static function exchangeDeclareOk($args) { $ret = array(); return $ret; } /** * @return array */ public function exchangeDelete($ticket = 1, $exchange, $if_unused = false, $nowait = false) { $args = new AMQPWriter(); $args->write_short($ticket); $args->write_shortstr($exchange); $args->write_bits(array($if_unused, $nowait)); return array(40, 20, $args); } /** * @param AMQPReader $args * @return array */ public static function exchangeDeleteOk($args) { $ret = array(); return $ret; } /** * @return array */ public function queueDeclare($ticket = 1, $queue = '', $passive = false, $durable = false, $exclusive = false, $auto_delete = false, $nowait = false, $arguments = array()) { $args = new AMQPWriter(); $args->write_short($ticket); $args->write_shortstr($queue); $args->write_bits(array($passive, $durable, $exclusive, $auto_delete, $nowait)); $args->write_table(empty($arguments) ? array() : $arguments); return array(50, 10, $args); } /** * @param AMQPReader $args * @return array */ public static function queueDeclareOk($args) { $ret = array(); $ret[] = $args->read_shortstr(); $ret[] = $args->read_long(); $ret[] = $args->read_long(); return $ret; } /** * @return array */ public function queueBind($ticket = 1, $queue = '', $exchange, $routing_key = '', $nowait = false, $arguments = array()) { $args = new AMQPWriter(); $args->write_short($ticket); $args->write_shortstr($queue); $args->write_shortstr($exchange); $args->write_shortstr($routing_key); $args->write_bits(array($nowait)); $args->write_table(empty($arguments) ? array() : $arguments); return array(50, 20, $args); } /** * @param AMQPReader $args * @return array */ public static function queueBindOk($args) { $ret = array(); return $ret; } /** * @return array */ public function queuePurge($ticket = 1, $queue = '', $nowait = false) { $args = new AMQPWriter(); $args->write_short($ticket); $args->write_shortstr($queue); $args->write_bits(array($nowait)); return array(50, 30, $args); } /** * @param AMQPReader $args * @return array */ public static function queuePurgeOk($args) { $ret = array(); $ret[] = $args->read_long(); return $ret; } /** * @return array */ public function queueDelete($ticket = 1, $queue = '', $if_unused = false, $if_empty = false, $nowait = false) { $args = new AMQPWriter(); $args->write_short($ticket); $args->write_shortstr($queue); $args->write_bits(array($if_unused, $if_empty, $nowait)); return array(50, 40, $args); } /** * @param AMQPReader $args * @return array */ public static function queueDeleteOk($args) { $ret = array(); $ret[] = $args->read_long(); return $ret; } /** * @return array */ public function queueUnbind($ticket = 1, $queue = '', $exchange, $routing_key = '', $arguments = array()) { $args = new AMQPWriter(); $args->write_short($ticket); $args->write_shortstr($queue); $args->write_shortstr($exchange); $args->write_shortstr($routing_key); $args->write_table(empty($arguments) ? array() : $arguments); return array(50, 50, $args); } /** * @param AMQPReader $args * @return array */ public static function queueUnbindOk($args) { $ret = array(); return $ret; } /** * @return array */ public function basicQos($prefetch_size = 0, $prefetch_count = 0, $global = false) { $args = new AMQPWriter(); $args->write_long($prefetch_size); $args->write_short($prefetch_count); $args->write_bits(array($global)); return array(60, 10, $args); } /** * @param AMQPReader $args * @return array */ public static function basicQosOk($args) { $ret = array(); return $ret; } /** * @return array */ public function basicConsume($ticket = 1, $queue = '', $consumer_tag = '', $no_local = false, $no_ack = false, $exclusive = false, $nowait = false) { $args = new AMQPWriter(); $args->write_short($ticket); $args->write_shortstr($queue); $args->write_shortstr($consumer_tag); $args->write_bits(array($no_local, $no_ack, $exclusive, $nowait)); return array(60, 20, $args); } /** * @param AMQPReader $args * @return array */ public static function basicConsumeOk($args) { $ret = array(); $ret[] = $args->read_shortstr(); return $ret; } /** * @return array */ public function basicCancel($consumer_tag, $nowait = false) { $args = new AMQPWriter(); $args->write_shortstr($consumer_tag); $args->write_bits(array($nowait)); return array(60, 30, $args); } /** * @param AMQPReader $args * @return array */ public static function basicCancelOk($args) { $ret = array(); $ret[] = $args->read_shortstr(); return $ret; } /** * @return array */ public function basicPublish($ticket = 1, $exchange = '', $routing_key = '', $mandatory = false, $immediate = false) { $args = new AMQPWriter(); $args->write_short($ticket); $args->write_shortstr($exchange); $args->write_shortstr($routing_key); $args->write_bits(array($mandatory, $immediate)); return array(60, 40, $args); } /** * @return array */ public function basicReturn($reply_code, $reply_text = '', $exchange, $routing_key) { $args = new AMQPWriter(); $args->write_short($reply_code); $args->write_shortstr($reply_text); $args->write_shortstr($exchange); $args->write_shortstr($routing_key); return array(60, 50, $args); } /** * @return array */ public function basicDeliver($consumer_tag, $delivery_tag, $redelivered = false, $exchange, $routing_key) { $args = new AMQPWriter(); $args->write_shortstr($consumer_tag); $args->write_longlong($delivery_tag); $args->write_bits(array($redelivered)); $args->write_shortstr($exchange); $args->write_shortstr($routing_key); return array(60, 60, $args); } /** * @return array */ public function basicGet($ticket = 1, $queue = '', $no_ack = false) { $args = new AMQPWriter(); $args->write_short($ticket); $args->write_shortstr($queue); $args->write_bits(array($no_ack)); return array(60, 70, $args); } /** * @param AMQPReader $args * @return array */ public static function basicGetOk($args) { $ret = array(); $ret[] = $args->read_longlong(); $ret[] = $args->read_bit(); $ret[] = $args->read_shortstr(); $ret[] = $args->read_shortstr(); $ret[] = $args->read_long(); return $ret; } /** * @param AMQPReader $args * @return array */ public static function basicGetEmpty($args) { $ret = array(); $ret[] = $args->read_shortstr(); return $ret; } /** * @return array */ public function basicAck($delivery_tag = 0, $multiple = false) { $args = new AMQPWriter(); $args->write_longlong($delivery_tag); $args->write_bits(array($multiple)); return array(60, 80, $args); } /** * @return array */ public function basicReject($delivery_tag, $requeue = true) { $args = new AMQPWriter(); $args->write_longlong($delivery_tag); $args->write_bits(array($requeue)); return array(60, 90, $args); } /** * @return array */ public function basicRecoverAsync($requeue = false) { $args = new AMQPWriter(); $args->write_bits(array($requeue)); return array(60, 100, $args); } /** * @return array */ public function basicRecover($requeue = false) { $args = new AMQPWriter(); $args->write_bits(array($requeue)); return array(60, 110, $args); } /** * @param AMQPReader $args * @return array */ public static function basicRecoverOk($args) { $ret = array(); return $ret; } /** * @return array */ public function fileQos($prefetch_size = 0, $prefetch_count = 0, $global = false) { $args = new AMQPWriter(); $args->write_long($prefetch_size); $args->write_short($prefetch_count); $args->write_bits(array($global)); return array(70, 10, $args); } /** * @param AMQPReader $args * @return array */ public static function fileQosOk($args) { $ret = array(); return $ret; } /** * @return array */ public function fileConsume($ticket = 1, $queue = '', $consumer_tag = '', $no_local = false, $no_ack = false, $exclusive = false, $nowait = false) { $args = new AMQPWriter(); $args->write_short($ticket); $args->write_shortstr($queue); $args->write_shortstr($consumer_tag); $args->write_bits(array($no_local, $no_ack, $exclusive, $nowait)); return array(70, 20, $args); } /** * @param AMQPReader $args * @return array */ public static function fileConsumeOk($args) { $ret = array(); $ret[] = $args->read_shortstr(); return $ret; } /** * @return array */ public function fileCancel($consumer_tag, $nowait = false) { $args = new AMQPWriter(); $args->write_shortstr($consumer_tag); $args->write_bits(array($nowait)); return array(70, 30, $args); } /** * @param AMQPReader $args * @return array */ public static function fileCancelOk($args) { $ret = array(); $ret[] = $args->read_shortstr(); return $ret; } /** * @return array */ public function fileOpen($identifier, $content_size) { $args = new AMQPWriter(); $args->write_shortstr($identifier); $args->write_longlong($content_size); return array(70, 40, $args); } /** * @param AMQPReader $args * @return array */ public static function fileOpenOk($args) { $ret = array(); $ret[] = $args->read_longlong(); return $ret; } /** * @return array */ public function fileStage() { $args = new AMQPWriter(); return array(70, 50, $args); } /** * @return array */ public function filePublish($ticket = 1, $exchange = '', $routing_key = '', $mandatory = false, $immediate = false, $identifier) { $args = new AMQPWriter(); $args->write_short($ticket); $args->write_shortstr($exchange); $args->write_shortstr($routing_key); $args->write_bits(array($mandatory, $immediate)); $args->write_shortstr($identifier); return array(70, 60, $args); } /** * @return array */ public function fileReturn($reply_code = 200, $reply_text = '', $exchange, $routing_key) { $args = new AMQPWriter(); $args->write_short($reply_code); $args->write_shortstr($reply_text); $args->write_shortstr($exchange); $args->write_shortstr($routing_key); return array(70, 70, $args); } /** * @return array */ public function fileDeliver($consumer_tag, $delivery_tag, $redelivered = false, $exchange, $routing_key, $identifier) { $args = new AMQPWriter(); $args->write_shortstr($consumer_tag); $args->write_longlong($delivery_tag); $args->write_bits(array($redelivered)); $args->write_shortstr($exchange); $args->write_shortstr($routing_key); $args->write_shortstr($identifier); return array(70, 80, $args); } /** * @return array */ public function fileAck($delivery_tag = 0, $multiple = false) { $args = new AMQPWriter(); $args->write_longlong($delivery_tag); $args->write_bits(array($multiple)); return array(70, 90, $args); } /** * @return array */ public function fileReject($delivery_tag, $requeue = true) { $args = new AMQPWriter(); $args->write_longlong($delivery_tag); $args->write_bits(array($requeue)); return array(70, 100, $args); } /** * @return array */ public function streamQos($prefetch_size = 0, $prefetch_count = 0, $consume_rate = 0, $global = false) { $args = new AMQPWriter(); $args->write_long($prefetch_size); $args->write_short($prefetch_count); $args->write_long($consume_rate); $args->write_bits(array($global)); return array(80, 10, $args); } /** * @param AMQPReader $args * @return array */ public static function streamQosOk($args) { $ret = array(); return $ret; } /** * @return array */ public function streamConsume($ticket = 1, $queue = '', $consumer_tag = '', $no_local = false, $exclusive = false, $nowait = false) { $args = new AMQPWriter(); $args->write_short($ticket); $args->write_shortstr($queue); $args->write_shortstr($consumer_tag); $args->write_bits(array($no_local, $exclusive, $nowait)); return array(80, 20, $args); } /** * @param AMQPReader $args * @return array */ public static function streamConsumeOk($args) { $ret = array(); $ret[] = $args->read_shortstr(); return $ret; } /** * @return array */ public function streamCancel($consumer_tag, $nowait = false) { $args = new AMQPWriter(); $args->write_shortstr($consumer_tag); $args->write_bits(array($nowait)); return array(80, 30, $args); } /** * @param AMQPReader $args * @return array */ public static function streamCancelOk($args) { $ret = array(); $ret[] = $args->read_shortstr(); return $ret; } /** * @return array */ public function streamPublish($ticket = 1, $exchange = '', $routing_key = '', $mandatory = false, $immediate = false) { $args = new AMQPWriter(); $args->write_short($ticket); $args->write_shortstr($exchange); $args->write_shortstr($routing_key); $args->write_bits(array($mandatory, $immediate)); return array(80, 40, $args); } /** * @return array */ public function streamReturn($reply_code = 200, $reply_text = '', $exchange, $routing_key) { $args = new AMQPWriter(); $args->write_short($reply_code); $args->write_shortstr($reply_text); $args->write_shortstr($exchange); $args->write_shortstr($routing_key); return array(80, 50, $args); } /** * @return array */ public function streamDeliver($consumer_tag, $delivery_tag, $exchange, $queue) { $args = new AMQPWriter(); $args->write_shortstr($consumer_tag); $args->write_longlong($delivery_tag); $args->write_shortstr($exchange); $args->write_shortstr($queue); return array(80, 60, $args); } /** * @return array */ public function txSelect() { $args = new AMQPWriter(); return array(90, 10, $args); } /** * @param AMQPReader $args * @return array */ public static function txSelectOk($args) { $ret = array(); return $ret; } /** * @return array */ public function txCommit() { $args = new AMQPWriter(); return array(90, 20, $args); } /** * @param AMQPReader $args * @return array */ public static function txCommitOk($args) { $ret = array(); return $ret; } /** * @return array */ public function txRollback() { $args = new AMQPWriter(); return array(90, 30, $args); } /** * @param AMQPReader $args * @return array */ public static function txRollbackOk($args) { $ret = array(); return $ret; } /** * @return array */ public function dtxSelect() { $args = new AMQPWriter(); return array(100, 10, $args); } /** * @param AMQPReader $args * @return array */ public static function dtxSelectOk($args) { $ret = array(); return $ret; } /** * @return array */ public function dtxStart($dtx_identifier) { $args = new AMQPWriter(); $args->write_shortstr($dtx_identifier); return array(100, 20, $args); } /** * @param AMQPReader $args * @return array */ public static function dtxStartOk($args) { $ret = array(); return $ret; } /** * @return array */ public function tunnelRequest($meta_data) { $args = new AMQPWriter(); $args->write_table(empty($meta_data) ? array() : $meta_data); return array(110, 10, $args); } /** * @return array */ public function testInteger($integer_1, $integer_2, $integer_3, $integer_4, $operation) { $args = new AMQPWriter(); $args->write_octet($integer_1); $args->write_short($integer_2); $args->write_long($integer_3); $args->write_longlong($integer_4); $args->write_octet($operation); return array(120, 10, $args); } /** * @param AMQPReader $args * @return array */ public static function testIntegerOk($args) { $ret = array(); $ret[] = $args->read_longlong(); return $ret; } /** * @return array */ public function testString($string_1, $string_2, $operation) { $args = new AMQPWriter(); $args->write_shortstr($string_1); $args->write_longstr($string_2); $args->write_octet($operation); return array(120, 20, $args); } /** * @param AMQPReader $args * @return array */ public static function testStringOk($args) { $ret = array(); $ret[] = $args->read_longstr(); return $ret; } /** * @return array */ public function testTable($table, $integer_op, $string_op) { $args = new AMQPWriter(); $args->write_table(empty($table) ? array() : $table); $args->write_octet($integer_op); $args->write_octet($string_op); return array(120, 30, $args); } /** * @param AMQPReader $args * @return array */ public static function testTableOk($args) { $ret = array(); $ret[] = $args->read_longlong(); $ret[] = $args->read_longstr(); return $ret; } /** * @return array */ public function testContent() { $args = new AMQPWriter(); return array(120, 40, $args); } /** * @param AMQPReader $args * @return array */ public static function testContentOk($args) { $ret = array(); $ret[] = $args->read_long(); return $ret; } } php-amqplib-2.6.1/PhpAmqpLib/Helper/Protocol/Protocol091.php000066400000000000000000000440511265740711700235310ustar00rootroot00000000000000write_octet($version_major); $args->write_octet($version_minor); $args->write_table(empty($server_properties) ? array() : $server_properties); $args->write_longstr($mechanisms); $args->write_longstr($locales); return array(10, 10, $args); } /** * @param AMQPReader $args * @return array */ public static function connectionStartOk($args) { $ret = array(); $ret[] = $args->read_table(); $ret[] = $args->read_shortstr(); $ret[] = $args->read_longstr(); $ret[] = $args->read_shortstr(); return $ret; } /** * @return array */ public function connectionSecure($challenge) { $args = new AMQPWriter(); $args->write_longstr($challenge); return array(10, 20, $args); } /** * @param AMQPReader $args * @return array */ public static function connectionSecureOk($args) { $ret = array(); $ret[] = $args->read_longstr(); return $ret; } /** * @return array */ public function connectionTune($channel_max = 0, $frame_max = 0, $heartbeat = 0) { $args = new AMQPWriter(); $args->write_short($channel_max); $args->write_long($frame_max); $args->write_short($heartbeat); return array(10, 30, $args); } /** * @param AMQPReader $args * @return array */ public static function connectionTuneOk($args) { $ret = array(); $ret[] = $args->read_short(); $ret[] = $args->read_long(); $ret[] = $args->read_short(); return $ret; } /** * @return array */ public function connectionOpen($virtual_host = '/', $capabilities = '', $insist = false) { $args = new AMQPWriter(); $args->write_shortstr($virtual_host); $args->write_shortstr($capabilities); $args->write_bits(array($insist)); return array(10, 40, $args); } /** * @param AMQPReader $args * @return array */ public static function connectionOpenOk($args) { $ret = array(); $ret[] = $args->read_shortstr(); return $ret; } /** * @return array */ public function connectionClose($reply_code, $reply_text = '', $class_id, $method_id) { $args = new AMQPWriter(); $args->write_short($reply_code); $args->write_shortstr($reply_text); $args->write_short($class_id); $args->write_short($method_id); return array(10, 50, $args); } /** * @param AMQPReader $args * @return array */ public static function connectionCloseOk($args) { $ret = array(); return $ret; } /** * @return array */ public function connectionBlocked($reason = '') { $args = new AMQPWriter(); $args->write_shortstr($reason); return array(10, 60, $args); } /** * @param AMQPReader $args * @return array */ public static function connectionUnblocked($args) { $ret = array(); return $ret; } /** * @return array */ public function channelOpen($out_of_band = '') { $args = new AMQPWriter(); $args->write_shortstr($out_of_band); return array(20, 10, $args); } /** * @param AMQPReader $args * @return array */ public static function channelOpenOk($args) { $ret = array(); $ret[] = $args->read_longstr(); return $ret; } /** * @return array */ public function channelFlow($active) { $args = new AMQPWriter(); $args->write_bits(array($active)); return array(20, 20, $args); } /** * @param AMQPReader $args * @return array */ public static function channelFlowOk($args) { $ret = array(); $ret[] = $args->read_bit(); return $ret; } /** * @return array */ public function channelClose($reply_code, $reply_text = '', $class_id, $method_id) { $args = new AMQPWriter(); $args->write_short($reply_code); $args->write_shortstr($reply_text); $args->write_short($class_id); $args->write_short($method_id); return array(20, 40, $args); } /** * @param AMQPReader $args * @return array */ public static function channelCloseOk($args) { $ret = array(); return $ret; } /** * @return array */ public function accessRequest($realm = '/data', $exclusive = false, $passive = true, $active = true, $write = true, $read = true) { $args = new AMQPWriter(); $args->write_shortstr($realm); $args->write_bits(array($exclusive, $passive, $active, $write, $read)); return array(30, 10, $args); } /** * @param AMQPReader $args * @return array */ public static function accessRequestOk($args) { $ret = array(); $ret[] = $args->read_short(); return $ret; } /** * @return array */ public function exchangeDeclare($ticket = 0, $exchange, $type = 'direct', $passive = false, $durable = false, $auto_delete = false, $internal = false, $nowait = false, $arguments = array()) { $args = new AMQPWriter(); $args->write_short($ticket); $args->write_shortstr($exchange); $args->write_shortstr($type); $args->write_bits(array($passive, $durable, $auto_delete, $internal, $nowait)); $args->write_table(empty($arguments) ? array() : $arguments); return array(40, 10, $args); } /** * @param AMQPReader $args * @return array */ public static function exchangeDeclareOk($args) { $ret = array(); return $ret; } /** * @return array */ public function exchangeDelete($ticket = 0, $exchange, $if_unused = false, $nowait = false) { $args = new AMQPWriter(); $args->write_short($ticket); $args->write_shortstr($exchange); $args->write_bits(array($if_unused, $nowait)); return array(40, 20, $args); } /** * @param AMQPReader $args * @return array */ public static function exchangeDeleteOk($args) { $ret = array(); return $ret; } /** * @return array */ public function exchangeBind($ticket = 0, $destination, $source, $routing_key = '', $nowait = false, $arguments = array()) { $args = new AMQPWriter(); $args->write_short($ticket); $args->write_shortstr($destination); $args->write_shortstr($source); $args->write_shortstr($routing_key); $args->write_bits(array($nowait)); $args->write_table(empty($arguments) ? array() : $arguments); return array(40, 30, $args); } /** * @param AMQPReader $args * @return array */ public static function exchangeBindOk($args) { $ret = array(); return $ret; } /** * @return array */ public function exchangeUnbind($ticket = 0, $destination, $source, $routing_key = '', $nowait = false, $arguments = array()) { $args = new AMQPWriter(); $args->write_short($ticket); $args->write_shortstr($destination); $args->write_shortstr($source); $args->write_shortstr($routing_key); $args->write_bits(array($nowait)); $args->write_table(empty($arguments) ? array() : $arguments); return array(40, 40, $args); } /** * @param AMQPReader $args * @return array */ public static function exchangeUnbindOk($args) { $ret = array(); return $ret; } /** * @return array */ public function queueDeclare($ticket = 0, $queue = '', $passive = false, $durable = false, $exclusive = false, $auto_delete = false, $nowait = false, $arguments = array()) { $args = new AMQPWriter(); $args->write_short($ticket); $args->write_shortstr($queue); $args->write_bits(array($passive, $durable, $exclusive, $auto_delete, $nowait)); $args->write_table(empty($arguments) ? array() : $arguments); return array(50, 10, $args); } /** * @param AMQPReader $args * @return array */ public static function queueDeclareOk($args) { $ret = array(); $ret[] = $args->read_shortstr(); $ret[] = $args->read_long(); $ret[] = $args->read_long(); return $ret; } /** * @return array */ public function queueBind($ticket = 0, $queue = '', $exchange, $routing_key = '', $nowait = false, $arguments = array()) { $args = new AMQPWriter(); $args->write_short($ticket); $args->write_shortstr($queue); $args->write_shortstr($exchange); $args->write_shortstr($routing_key); $args->write_bits(array($nowait)); $args->write_table(empty($arguments) ? array() : $arguments); return array(50, 20, $args); } /** * @param AMQPReader $args * @return array */ public static function queueBindOk($args) { $ret = array(); return $ret; } /** * @return array */ public function queuePurge($ticket = 0, $queue = '', $nowait = false) { $args = new AMQPWriter(); $args->write_short($ticket); $args->write_shortstr($queue); $args->write_bits(array($nowait)); return array(50, 30, $args); } /** * @param AMQPReader $args * @return array */ public static function queuePurgeOk($args) { $ret = array(); $ret[] = $args->read_long(); return $ret; } /** * @return array */ public function queueDelete($ticket = 0, $queue = '', $if_unused = false, $if_empty = false, $nowait = false) { $args = new AMQPWriter(); $args->write_short($ticket); $args->write_shortstr($queue); $args->write_bits(array($if_unused, $if_empty, $nowait)); return array(50, 40, $args); } /** * @param AMQPReader $args * @return array */ public static function queueDeleteOk($args) { $ret = array(); $ret[] = $args->read_long(); return $ret; } /** * @return array */ public function queueUnbind($ticket = 0, $queue = '', $exchange, $routing_key = '', $arguments = array()) { $args = new AMQPWriter(); $args->write_short($ticket); $args->write_shortstr($queue); $args->write_shortstr($exchange); $args->write_shortstr($routing_key); $args->write_table(empty($arguments) ? array() : $arguments); return array(50, 50, $args); } /** * @param AMQPReader $args * @return array */ public static function queueUnbindOk($args) { $ret = array(); return $ret; } /** * @return array */ public function basicQos($prefetch_size = 0, $prefetch_count = 0, $global = false) { $args = new AMQPWriter(); $args->write_long($prefetch_size); $args->write_short($prefetch_count); $args->write_bits(array($global)); return array(60, 10, $args); } /** * @param AMQPReader $args * @return array */ public static function basicQosOk($args) { $ret = array(); return $ret; } /** * @return array */ public function basicConsume($ticket = 0, $queue = '', $consumer_tag = '', $no_local = false, $no_ack = false, $exclusive = false, $nowait = false, $arguments = array()) { $args = new AMQPWriter(); $args->write_short($ticket); $args->write_shortstr($queue); $args->write_shortstr($consumer_tag); $args->write_bits(array($no_local, $no_ack, $exclusive, $nowait)); $args->write_table(empty($arguments) ? array() : $arguments); return array(60, 20, $args); } /** * @param AMQPReader $args * @return array */ public static function basicConsumeOk($args) { $ret = array(); $ret[] = $args->read_shortstr(); return $ret; } /** * @return array */ public function basicCancel($consumer_tag, $nowait = false) { $args = new AMQPWriter(); $args->write_shortstr($consumer_tag); $args->write_bits(array($nowait)); return array(60, 30, $args); } /** * @param AMQPReader $args * @return array */ public static function basicCancelOk($args) { $ret = array(); $ret[] = $args->read_shortstr(); return $ret; } /** * @return array */ public function basicPublish($ticket = 0, $exchange = '', $routing_key = '', $mandatory = false, $immediate = false) { $args = new AMQPWriter(); $args->write_short($ticket); $args->write_shortstr($exchange); $args->write_shortstr($routing_key); $args->write_bits(array($mandatory, $immediate)); return array(60, 40, $args); } /** * @return array */ public function basicReturn($reply_code, $reply_text = '', $exchange, $routing_key) { $args = new AMQPWriter(); $args->write_short($reply_code); $args->write_shortstr($reply_text); $args->write_shortstr($exchange); $args->write_shortstr($routing_key); return array(60, 50, $args); } /** * @return array */ public function basicDeliver($consumer_tag, $delivery_tag, $redelivered = false, $exchange, $routing_key) { $args = new AMQPWriter(); $args->write_shortstr($consumer_tag); $args->write_longlong($delivery_tag); $args->write_bits(array($redelivered)); $args->write_shortstr($exchange); $args->write_shortstr($routing_key); return array(60, 60, $args); } /** * @return array */ public function basicGet($ticket = 0, $queue = '', $no_ack = false) { $args = new AMQPWriter(); $args->write_short($ticket); $args->write_shortstr($queue); $args->write_bits(array($no_ack)); return array(60, 70, $args); } /** * @param AMQPReader $args * @return array */ public static function basicGetOk($args) { $ret = array(); $ret[] = $args->read_longlong(); $ret[] = $args->read_bit(); $ret[] = $args->read_shortstr(); $ret[] = $args->read_shortstr(); $ret[] = $args->read_long(); return $ret; } /** * @param AMQPReader $args * @return array */ public static function basicGetEmpty($args) { $ret = array(); $ret[] = $args->read_shortstr(); return $ret; } /** * @return array */ public function basicAck($delivery_tag = 0, $multiple = false) { $args = new AMQPWriter(); $args->write_longlong($delivery_tag); $args->write_bits(array($multiple)); return array(60, 80, $args); } /** * @return array */ public function basicReject($delivery_tag, $requeue = true) { $args = new AMQPWriter(); $args->write_longlong($delivery_tag); $args->write_bits(array($requeue)); return array(60, 90, $args); } /** * @return array */ public function basicRecoverAsync($requeue = false) { $args = new AMQPWriter(); $args->write_bits(array($requeue)); return array(60, 100, $args); } /** * @return array */ public function basicRecover($requeue = false) { $args = new AMQPWriter(); $args->write_bits(array($requeue)); return array(60, 110, $args); } /** * @param AMQPReader $args * @return array */ public static function basicRecoverOk($args) { $ret = array(); return $ret; } /** * @return array */ public function basicNack($delivery_tag = 0, $multiple = false, $requeue = true) { $args = new AMQPWriter(); $args->write_longlong($delivery_tag); $args->write_bits(array($multiple, $requeue)); return array(60, 120, $args); } /** * @return array */ public function txSelect() { $args = new AMQPWriter(); return array(90, 10, $args); } /** * @param AMQPReader $args * @return array */ public static function txSelectOk($args) { $ret = array(); return $ret; } /** * @return array */ public function txCommit() { $args = new AMQPWriter(); return array(90, 20, $args); } /** * @param AMQPReader $args * @return array */ public static function txCommitOk($args) { $ret = array(); return $ret; } /** * @return array */ public function txRollback() { $args = new AMQPWriter(); return array(90, 30, $args); } /** * @param AMQPReader $args * @return array */ public static function txRollbackOk($args) { $ret = array(); return $ret; } /** * @return array */ public function confirmSelect($nowait = false) { $args = new AMQPWriter(); $args->write_bits(array($nowait)); return array(85, 10, $args); } /** * @param AMQPReader $args * @return array */ public static function confirmSelectOk($args) { $ret = array(); return $ret; } } php-amqplib-2.6.1/PhpAmqpLib/Helper/Protocol/Wait080.php000066400000000000000000000071171265740711700226340ustar00rootroot00000000000000 '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', ); public function get_wait($method) { return $this->wait[$method]; } } php-amqplib-2.6.1/PhpAmqpLib/Helper/Protocol/Wait091.php000066400000000000000000000051341265740711700226330ustar00rootroot00000000000000 '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', ); public function get_wait($method) { return $this->wait[$method]; } } php-amqplib-2.6.1/PhpAmqpLib/Message/000077500000000000000000000000001265740711700173255ustar00rootroot00000000000000php-amqplib-2.6.1/PhpAmqpLib/Message/AMQPMessage.php000066400000000000000000000046031265740711700221040ustar00rootroot00000000000000 '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 boolean $is_truncated * @return AMQPMessage */ public function setIsTruncated($is_truncated) { $this->is_truncated = (bool) $is_truncated; return $this; } } php-amqplib-2.6.1/PhpAmqpLib/Wire/000077500000000000000000000000001265740711700166475ustar00rootroot00000000000000php-amqplib-2.6.1/PhpAmqpLib/Wire/AMQPAbstractCollection.php000066400000000000000000000303051265740711700236170ustar00rootroot00000000000000 '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' ); /** * @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' ); /** * @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 \DateTime) { $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(self::PROTOCOL_080)) { //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 integer $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(self::PROTOCOL_080)) { //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(self::PROTOCOL_080) ? array(self::T_INT_LONG, (int) $val) : array(self::T_BOOL, $val); } /** * @return array */ protected function encodeVoid() { return self::isProtocol(self::PROTOCOL_080) ? $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 self::PROTOCOL_080: $types = self::$_types_080; break; case self::PROTOCOL_091: $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 integer $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.6.1/PhpAmqpLib/Wire/AMQPArray.php000066400000000000000000000010371265740711700211160ustar00rootroot00000000000000setValue($val, $type); return $this; } } php-amqplib-2.6.1/PhpAmqpLib/Wire/AMQPDecimal.php000066400000000000000000000022251265740711700213760ustar00rootroot00000000000000n = $n; $this->e = $e; } /** * @return string */ public function asBCvalue() { return bcdiv($this->n, bcpow(10, $this->e)); } /** * @return int */ public function getE() { return $this->e; } /** * @return int */ public function getN() { return $this->n; } } php-amqplib-2.6.1/PhpAmqpLib/Wire/AMQPReader.php000066400000000000000000000340071265740711700212450ustar00rootroot00000000000000str = $str; $this->str_length = mb_strlen($this->str, 'ASCII'); $this->io = $io; $this->offset = 0; $this->bitcount = $this->bits = 0; $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->bitcount = $this->bits = 0; } /** * Closes the stream */ public function close() { if ($this->io) { $this->io->close(); } } /** * @param $n * @return string */ public function read($n) { $this->bitcount = $this->bits = 0; 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\AMQPTimeoutException */ protected function wait() { if ($this->getTimeout() == 0) { return null; } // wait .. list($sec, $usec) = MiscHelper::splitSecondsMicroseconds($this->getTimeout()); $result = $this->io->select($sec, $usec); if ($result === false) { throw new AMQPRuntimeException('A network error occured while awaiting for incoming data'); } if ($result === 0) { throw new AMQPTimeoutException(sprintf( 'The connection timed out after %s sec while awaiting incoming data', $this->getTimeout() )); } } /** * @param $n * @return string * @throws \RuntimeException * @throws \PhpAmqpLib\Exception\AMQPRuntimeException */ protected function rawread($n) { if ($this->io) { $this->wait(); $res = $this->io->read($n); $this->offset += $n; } else { if ($this->str_length < $n) { throw new AMQPRuntimeException(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, mb_strlen($this->str, 'ASCII') - $n, 'ASCII'); $this->str_length -= $n; $this->offset += $n; } return $res; } /** * @return bool */ public function read_bit() { if (!$this->bitcount) { $this->bits = ord($this->rawread(1)); $this->bitcount = 8; } $result = ($this->bits & 1) == 1; $this->bits >>= 1; $this->bitcount -= 1; return $result; } /** * @return mixed */ public function read_octet() { $this->bitcount = $this->bits = 0; list(, $res) = unpack('C', $this->rawread(1)); return $res; } /** * @return mixed */ public function read_signed_octet() { $this->bitcount = $this->bits = 0; list(, $res) = unpack('c', $this->rawread(1)); return $res; } /** * @return mixed */ public function read_short() { $this->bitcount = $this->bits = 0; list(, $res) = unpack('n', $this->rawread(2)); return $res; } /** * @return mixed */ public function read_signed_short() { $this->bitcount = $this->bits = 0; 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->bitcount = $this->bits = 0; list(, $res) = unpack('N', $this->rawread(4)); return !$this->is64bits && self::getLongMSB($res) ? sprintf('%u', $res) : $res; } /** * @return integer */ private function read_signed_long() { $this->bitcount = $this->bits = 0; list(, $res) = unpack('l', $this->correctEndianness($this->rawread(4))); return $res; } /** * Even on 64 bit systems PHP integers are singed. * Since we need an unsigned value here we return it * as a string. * * @return string */ public function read_longlong() { $this->bitcount = $this->bits = 0; list(, $hi, $lo) = unpack('N2', $this->rawread(8)); $msb = self::getLongMSB($hi); if (!$this->is64bits) { if ($msb) { $hi = sprintf('%u', $hi); } if (self::getLongMSB($lo)) { $lo = sprintf('%u', $lo); } } return bcadd($this->is64bits && !$msb ? $hi << 32 : bcmul($hi, '4294967296', 0), $lo, 0); } /** * @return string */ public function read_signed_longlong() { $this->bitcount = $this->bits = 0; list(, $hi, $lo) = unpack('N2', $this->rawread(8)); if ($this->is64bits) { return bcadd($hi << 32, $lo, 0); } else { return bcadd(bcmul($hi, '4294967296', 0), self::getLongMSB($lo) ? sprintf('%u', $lo) : $lo, 0); } } /** * @param int $longInt * @return bool */ private static function getLongMSB($longInt) { return (bool) ($longInt & 0x80000000); } /** * 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->bitcount = $this->bits = 0; 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->bitcount = $this->bits = 0; $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->bitcount = $this->bits = 0; $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->bitcount = $this->bits = 0; // 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\AMQPRuntimeException */ public function read_value($fieldType, $collectionsAsObjects = false) { $this->bitcount = $this->bits = 0; $val = null; 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; default: throw new AMQPInvalidArgumentException(sprintf( 'Unsupported type "%s"', $fieldType )); } return $val; } /** * @return int */ protected function tell() { return $this->offset; } /** * Sets the timeout (second) * * @param $timeout */ public function setTimeout($timeout) { $this->timeout = $timeout; } /** * @return int */ public function getTimeout() { return $this->timeout; } } php-amqplib-2.6.1/PhpAmqpLib/Wire/AMQPTable.php000066400000000000000000000022451265740711700210710ustar00rootroot00000000000000 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.6.1/PhpAmqpLib/Wire/AMQPWriter.php000066400000000000000000000333121265740711700213150ustar00rootroot00000000000000out = ''; $this->bits = array(); $this->bitcount = 0; } /** * Packs integer into raw byte string in big-endian order * Supports positive and negative ints represented as PHP int or string (except scientific notation) * * Floats has some precision issues and so intentionally not supported. * Beware that floats out of PHP_INT_MAX range will be represented in scientific (exponential) notation when casted to string * * @param int|string $x Value to pack * @param int $bytes Must be multiply of 2 * @return string */ private static function packBigEndian($x, $bytes) { if (($bytes <= 0) || ($bytes % 2)) { throw new AMQPInvalidArgumentException(sprintf('Expected bytes count must be multiply of 2, %s given', $bytes)); } $ox = $x; //purely for dbg purposes (overflow exception) $isNeg = false; if (is_int($x)) { if ($x < 0) { $isNeg = true; $x = abs($x); } } elseif (is_string($x)) { if (!is_numeric($x)) { throw new AMQPInvalidArgumentException(sprintf('Unknown numeric string format: %s', $x)); } $x = preg_replace('/^-/', '', $x, 1, $isNeg); } else { throw new AMQPInvalidArgumentException('Only integer and numeric string values are supported'); } if ($isNeg) { $x = bcadd($x, -1, 0); } //in negative domain starting point is -1, not 0 $res = array(); for ($b = 0; $b < $bytes; $b += 2) { $chnk = (int) bcmod($x, 65536); $x = bcdiv($x, 65536, 0); $res[] = pack('n', $isNeg ? ~$chnk : $chnk); } if ($x || ($isNeg && ($chnk & 0x8000))) { throw new AMQPOutOfBoundsException(sprintf('Overflow detected while attempting to pack %s into %s bytes', $ox, $bytes)); } return implode(array_reverse($res)); } private function flushbits() { if (!empty($this->bits)) { $this->out .= implode('', array_map('chr', $this->bits)); $this->bits = array(); $this->bitcount = 0; } } /** * Get what's been encoded so far. */ 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. */ public function write($s) { $this->out .= $s; return $this; } /** * Write a boolean value. * (deprecated, use write_bits instead) * * @deprecated * @param $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); array_push($this->bits, $last); $this->bitcount += 1; return $this; } /** * Write multiple bits as an octet * * @param $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 $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; } 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 $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; } 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 $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 $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 an integer as an unsigned 64-bit value * * @param $n * @return $this */ public function write_longlong($n) { if ($n < 0) { throw new AMQPInvalidArgumentException('Longlong out of range: ' . $n); } // if PHP_INT_MAX is big enough for that // direct $n<=PHP_INT_MAX check is unreliable on 64bit (values close to max) due to limited float precision if (bcadd($n, -PHP_INT_MAX, 0) <= 0) { // trick explained in http://www.php.net/manual/fr/function.pack.php#109328 if ($this->is64bits) { list($hi, $lo) = $this->splitIntoQuads($n); } else { $hi = 0; $lo = $n; } //on 32bits hi quad is 0 a priori $this->out .= pack('NN', $hi, $lo); } else { try { $this->out .= self::packBigEndian($n, 8); } catch (AMQPOutOfBoundsException $ex) { throw new AMQPInvalidArgumentException('Longlong out of range: ' . $n, 0, $ex); } } return $this; } public function write_signed_longlong($n) { if ((bcadd($n, PHP_INT_MAX, 0) >= -1) && (bcadd($n, -PHP_INT_MAX, 0) <= 0)) { if ($this->is64bits) { list($hi, $lo) = $this->splitIntoQuads($n); } else { $hi = $n < 0 ? -1 : 0; $lo = $n; } //0xffffffff for negatives $this->out .= pack('NN', $hi, $lo); } elseif ($this->is64bits) { throw new AMQPInvalidArgumentException('Signed longlong out of range: ' . $n); } else { if (bcadd($n, '-9223372036854775807', 0) > 0) { throw new AMQPInvalidArgumentException('Signed longlong out of range: ' . $n); } try { //will catch only negative overflow, as values >9223372036854775807 are valid for 8bytes range (unsigned) $this->out .= self::packBigEndian($n, 8); } catch (AMQPOutOfBoundsException $ex) { throw new AMQPInvalidArgumentException('Signed longlong out of range: ' . $n, 0, $ex); } } return $this; } /** * @param int $n * @return array */ private function splitIntoQuads($n) { $n = (int) $n; return array($n >> 32, $n & 0x00000000ffffffff); } /** * Write a string up to 255 bytes long after encoding. * Assume UTF-8 encoding * * @param $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 $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 AMQPWriter(); 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 $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 self * @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 */ 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; default: throw new AMQPInvalidArgumentException(sprintf( 'Unsupported type "%s"', $type )); } } } php-amqplib-2.6.1/PhpAmqpLib/Wire/AbstractClient.php000066400000000000000000000012611265740711700222620ustar00rootroot00000000000000is64bits = PHP_INT_SIZE == 8; $tmp = unpack('S', "\x01\x00"); // to maintain 5.3 compatibility $this->isLittleEndian = $tmp[1] == 1; } /** * Converts byte-string between native and network byte order, in both directions * * @param string $byteStr * @return string */ protected function correctEndianness($byteStr) { return $this->isLittleEndian ? strrev($byteStr) : $byteStr; } } php-amqplib-2.6.1/PhpAmqpLib/Wire/Constants080.php000066400000000000000000000105421265740711700215660ustar00rootroot00000000000000 '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', ); public 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', ); public static $CLOSE_METHODS = array( 0 => '10,60', 1 => '20,40', ); 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.6.1/PhpAmqpLib/Wire/Constants091.php000066400000000000000000000060751265740711700215760ustar00rootroot00000000000000 'FRAME-METHOD', 2 => 'FRAME-HEADER', 3 => 'FRAME-BODY', 8 => 'FRAME-HEARTBEAT', 4096 => 'FRAME-MIN-SIZE', 206 => 'FRAME-END', 501 => 'FRAME-ERROR', ); public static $CONTENT_METHODS = array( 0 => '60,40', 1 => '60,50', 2 => '60,60', 3 => '60,71', ); public static $CLOSE_METHODS = array( 0 => '10,50', 1 => '20,40', ); 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.6.1/PhpAmqpLib/Wire/GenericContent.php000066400000000000000000000127361265740711700223000ustar00rootroot00000000000000 'shortstr' ); /** * @param array $props Message property content * @param array $prop_types Message property definitions */ public function __construct($props = array(), $prop_types = array()) { $this->prop_types = self::$propertyDefinitions; if (!empty($prop_types)) { $this->prop_types = $prop_types; } if (!empty($props)) { $this->properties = array_intersect_key($props, $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 )); } $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($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.6.1/PhpAmqpLib/Wire/IO/000077500000000000000000000000001265740711700171565ustar00rootroot00000000000000php-amqplib-2.6.1/PhpAmqpLib/Wire/IO/AbstractIO.php000066400000000000000000000012761265740711700216700ustar00rootroot00000000000000host = $host; $this->port = $port; $this->timeout = $timeout; $this->keepalive = $keepalive; } /** * Sets up the socket connection * * @throws \Exception */ public function connect() { $this->sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); socket_set_option($this->sock, SOL_SOCKET, SO_RCVTIMEO, array('sec' => $this->timeout, 'usec' => 0)); socket_set_option($this->sock, SOL_SOCKET, SO_SNDTIMEO, array('sec' => $this->timeout, 'usec' => 0)); if (!socket_connect($this->sock, $this->host, $this->port)) { $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(); } } /** * @return resource */ public function getSocket() { return $this->sock; } /** * Reconnects the socket */ public function reconnect() { $this->close(); $this->connect(); } /** * @param $n * @return mixed|string * @throws \PhpAmqpLib\Exception\AMQPIOException * @throws \PhpAmqpLib\Exception\AMQPRuntimeException */ public function read($n) { $res = ''; $read = 0; $buf = socket_read($this->sock, $n); while ($read < $n && $buf !== '' && $buf !== false) { // Null sockets are invalid, throw exception if (is_null($this->sock)) { throw new AMQPRuntimeException(sprintf( 'Socket was null! Last SocketError was: %s', socket_strerror(socket_last_error()) )); } $read += mb_strlen($buf, 'ASCII'); $res .= $buf; $buf = socket_read($this->sock, $n - $read); } if (mb_strlen($res, 'ASCII') != $n) { throw new AMQPIOException(sprintf( 'Error reading data. Received %s instead of expected %s bytes', mb_strlen($res, 'ASCII'), $n )); } return $res; } /** * @param $data * @return mixed|void * @throws \PhpAmqpLib\Exception\AMQPIOException * @throws \PhpAmqpLib\Exception\AMQPRuntimeException */ public function write($data) { $len = mb_strlen($data, 'ASCII'); while (true) { // Null sockets are invalid, throw exception if (is_null($this->sock)) { throw new AMQPRuntimeException(sprintf( 'Socket was null! Last SocketError was: %s', socket_strerror(socket_last_error()) )); } $sent = socket_write($this->sock, $data, $len); if ($sent === false) { throw new AMQPIOException(sprintf( 'Error sending data. Last SocketError: %s', socket_strerror(socket_last_error()) )); } // Check if the entire message has been sent if ($sent < $len) { // If not sent the entire message. // Get the part of the message that has not yet been sent as message $data = mb_substr($data, $sent, mb_strlen($data, 'ASCII') - $sent, 'ASCII'); // Get the length of the not sent part $len -= $sent; } else { break; } } } public function close() { if (is_resource($this->sock)) { socket_close($this->sock); } $this->sock = null; } /** * @param $sec * @param $usec * @return int|mixed */ public function select($sec, $usec) { $read = array($this->sock); $write = null; $except = null; return socket_select($read, $write, $except, $sec, $usec); } /** * @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); } } php-amqplib-2.6.1/PhpAmqpLib/Wire/IO/StreamIO.php000066400000000000000000000267711265740711700213670ustar00rootroot00000000000000protocol = 'tcp'; $this->host = $host; $this->port = $port; $this->connection_timeout = $connection_timeout; $this->read_write_timeout = $read_write_timeout; $this->context = $context; $this->keepalive = $keepalive; $this->heartbeat = $heartbeat; $this->canSelectNull = true; $this->canDispatchPcntlSignal = $this->isPcntlSignalEnabled(); if (is_null($this->context)) { $this->context = stream_context_create(); } else { $this->protocol = 'ssl'; // php bugs 41631 & 65137 prevent select null from working on ssl streams if (PHP_VERSION_ID < 50436) { $this->canSelectNull = false; } } } /** * @return bool */ private function isPcntlSignalEnabled() { return extension_loaded('pcntl') && function_exists('pcntl_signal_dispatch') && (defined('AMQP_WITHOUT_SIGNALS') && !AMQP_WITHOUT_SIGNALS); } /** * Sets up the stream connection * * @throws \PhpAmqpLib\Exception\AMQPRuntimeException * @throws \Exception */ public function connect() { $errstr = $errno = null; $remote = sprintf( '%s://%s:%s', $this->protocol, $this->host, $this->port ); set_error_handler(array($this, 'error_handler')); $this->sock = stream_socket_client( $remote, $errno, $errstr, $this->connection_timeout, STREAM_CLIENT_CONNECT, $this->context ); restore_error_handler(); if (false === $this->sock) { throw new AMQPRuntimeException( sprintf( 'Error Connecting to server(%s): %s ', $errno, $errstr ), $errno ); } if (false === stream_socket_get_name($this->sock, true)) { throw new AMQPRuntimeException( sprintf( 'Connection refused: %s ', $remote ) ); } list($sec, $uSec) = MiscHelper::splitSecondsMicroseconds($this->read_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, 1); } if ($this->keepalive) { $this->enable_keepalive(); } } /** * Reconnects the socket */ public function reconnect() { $this->close(); $this->connect(); } /** * @param $len * @throws \PhpAmqpLib\Exception\AMQPIOException * @return mixed|string */ public function read($len) { $read = 0; $data = ''; while ($read < $len) { $this->check_heartbeat(); if (!is_resource($this->sock) || feof($this->sock)) { throw new AMQPRuntimeException('Broken pipe or closed connection'); } set_error_handler(array($this, 'error_handler')); $buffer = fread($this->sock, ($len - $read)); restore_error_handler(); if ($buffer === false) { throw new AMQPRuntimeException('Error receiving data'); } if ($buffer === '') { if ($this->canDispatchPcntlSignal) { // prevent cpu from being consumed while waiting if ($this->canSelectNull) { $this->select(null, null); pcntl_signal_dispatch(); } else { usleep(100000); pcntl_signal_dispatch(); } } continue; } $read += mb_strlen($buffer, 'ASCII'); $data .= $buffer; } if (mb_strlen($data, 'ASCII') !== $len) { throw new AMQPRuntimeException( sprintf( 'Error reading data. Received %s instead of expected %s bytes', mb_strlen($data, 'ASCII'), $len ) ); } $this->last_read = microtime(true); return $data; } /** * @param $data * @return mixed|void * @throws \PhpAmqpLib\Exception\AMQPRuntimeException * @throws \PhpAmqpLib\Exception\AMQPTimeoutException */ public function write($data) { $written = 0; $len = mb_strlen($data, 'ASCII'); while ($written < $len) { if (!is_resource($this->sock)) { throw new AMQPRuntimeException('Broken pipe or closed connection'); } set_error_handler(array($this, '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 $buffer = fwrite($this->sock, $data, 8192); restore_error_handler(); if ($buffer === false) { throw new AMQPRuntimeException('Error sending data'); } if ($buffer === 0 && feof($this->sock)) { throw new AMQPRuntimeException('Broken pipe or closed connection'); } if ($this->timed_out()) { throw new AMQPTimeoutException('Error sending data. Socket connection timed out'); } $written += $buffer; if ($buffer > 0) { $data = mb_substr($data, $buffer, mb_strlen($data, 'ASCII') - $buffer, 'ASCII'); } } $this->last_write = microtime(true); } /** * Internal error handler to deal with stream and socket errors that need to be ignored * * @param int $errno * @param string $errstr * @param string $errfile * @param int $errline * @param array $errcontext * @return null * @throws \ErrorException */ public function error_handler($errno, $errstr, $errfile, $errline, $errcontext = null) { $this->last_error = compact('errno', 'errstr', 'errfile', 'errline', 'errcontext'); // fwrite notice that the stream isn't ready if (strstr($errstr, 'Resource temporarily unavailable')) { // it's allowed to retry return null; } // stream_select warning that it has been interrupted by a signal if (strstr($errstr, 'Interrupted system call')) { // it's allowed while processing signals return null; } restore_error_handler(); // raise all other issues to exceptions throw new \ErrorException($errstr, 0, $errno, $errfile, $errline); } /** * Heartbeat logic: check connection health here */ protected 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->reconnect(); } // time for client to send a heartbeat if (($this->heartbeat / 2) < $t_write) { $this->write_heartbeat(); } } } /** * 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()); } public function close() { if (is_resource($this->sock)) { fclose($this->sock); } $this->sock = null; } /** * @return resource */ public function get_socket() { return $this->sock; } /** * @return resource */ public function getSocket() { return $this->get_socket(); } /** * @param $sec * @param $usec * @return int|mixed */ public function select($sec, $usec) { $read = array($this->sock); $write = null; $except = null; $result = false; set_error_handler(array($this, 'error_handler')); $result = stream_select($read, $write, $except, $sec, $usec); restore_error_handler(); return $result; } /** * @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 (!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); } } php-amqplib-2.6.1/README.md000066400000000000000000000245071265740711700152330ustar00rootroot00000000000000# 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 protocol. It's been tested against [RabbitMQ](http://www.rabbitmq.com/). **Requirements: PHP 5.3** due to the use of `namespaces`. 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). ## New Maintainers (02/10/2016) ## Thanks to [videlalvaro](https://github.com/videlalvaro) for his hard work in maintaining php-amqplib! He's done a fantastic job and has left big shoes to fill. The package will now be maintained by [postalservice14](https://github.com/postalservice14) and [nubeiro](https://github.com/nubeiro). ## 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). You shouldn't need to change your code, but test 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. ## Setup ## Add a `composer.json` file to your project: ```javascript { "require": { "php-amqplib/php-amqplib": "2.5.*" } } ``` Then provided you have [composer](http://getcomposer.org) installed, you can run the following command: ```bash $ composer.phar install ``` 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. ## 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. ## 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: ``` $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()`. ##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 exit(0); break; case \SIGHUP: // some stuff to restart consumer break; default: // do nothing } }; declare(ticks = 1) { 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 setup the test `user` and test `virtual host`. You can do that by running the following commands after starting RabbitMQ: ```bash $ rabbitmqctl add_vhost phpamqplib_testbed $ rabbitmqctl add_user phpamqplib phpamqplib_password $ rabbitmqctl set_permissions -p phpamqplib_testbed phpamqplib ".*" ".*" ".*" ``` Once your environment is set up you can run your 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 settings 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-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.6.1/composer.json000066400000000000000000000027001265740711700164650ustar00rootroot00000000000000{ "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" } ], "require": { "php": ">=5.3.0", "ext-bcmath": "*", "ext-mbstring": "*" }, "require-dev": { "phpunit/phpunit": "^3.7", "scrutinizer/ocular": "^1.1" }, "suggest": { "ext-sockets": "Use AMQPSocketConnection" }, "autoload": { "psr-4": { "PhpAmqpLib\\": "PhpAmqpLib/" } }, "autoload-dev": { "psr-4": { "PhpAmqpLib\\Tests\\Functional\\": "tests/Functional", "PhpAmqpLib\\Tests\\Unit\\": "tests/Unit" } }, "license": "LGPL-2.1", "extra": { "branch-alias": { "dev-master": "2.7-dev" } } } php-amqplib-2.6.1/spec/000077500000000000000000000000001265740711700146765ustar00rootroot00000000000000php-amqplib-2.6.1/spec/amqp-rabbitmq-0.8.json000066400000000000000000001136011265740711700206330ustar00rootroot00000000000000{ "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.6.1/spec/amqp-rabbitmq-0.9.1.json000066400000000000000000000656401265740711700210040ustar00rootroot00000000000000{ "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.6.1/spec/parser.php000066400000000000000000000247321265740711700167130ustar00rootroot00000000000000 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); } /** * @return string */ function domain_to_type($domains, $domain) { foreach ($domains as $d) { if ($d[0] == $domain) { return $d[1]; } } throw new \Exception("Invalid domain: " . $domain); } /** * @return string */ 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 .= '$args->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 = '$args->write_bits(array(' . implode(', ', $this->bit_args) . "));\n"; $this->bit_args = array(); return $ret; } } function call_read_argument($domains, $arg) { return '$args->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'] . ', $args);'; $methods .= '/**' . "\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 = '$ret = array();' . "\n"; foreach ($m['arguments'] as $arg) { $methodBody .= '$ret[] = ' . call_read_argument($json_spec['domains'], $arg); } $methodBody .= 'return $ret;'; $methods .= '/**' . "\n"; $methods .= ' * @param AMQPReader $args' . "\n"; $methods .= ' * @return array' . "\n"; $methods .= ' */' . "\n"; $methods .= 'public static function ' . method_name($c['name'], $m['name']) . '($args)' . "\n{\n"; $methods .= indent($methodBody) . "\n"; $methods .= "}\n"; } $methods .= "\n\n"; } } $out .= indent(rtrim($methods)) . "\n\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); } $properties = ''; $properties .= 'public static $AMQP_PROTOCOL_HEADER = ' . protocol_header($json_spec) . ";\n\n"; $properties .= 'public static $FRAME_TYPES = ' . frame_types($json_spec) . ";\n\n"; $properties .= 'public static $CONTENT_METHODS = ' . content_methods($json_spec) . ";\n\n"; $properties .= 'public static $CLOSE_METHODS = ' . close_methods($json_spec) . ";\n\n"; $properties .= 'public static $GLOBAL_METHOD_NAMES = ' . global_method_names($json_spec) . ";\n"; $out = 'wait[$method];') . "\n"; $classBody .= "}\n"; $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 .= 'protected $method_map = ' . method_map($json_spec) . ";\n\n\n\n"; $classBody .= 'public function get_method($method_sig)' . "\n{\n"; $classBody .= indent('return $this->method_map[$method_sig];') . "\n"; $classBody .= "}\n\n\n\n"; $classBody .= 'public function valid_method($method_sig)' . "\n{\n"; $classBody .= indent('return array_key_exists($method_sig, $this->method_map);') . "\n"; $classBody .= "}\n"; $out = '