├── AMQP.Types.pas
├── AMQPTest.dpr
├── AMQPTest.dproj
├── AMQPTest.dproj.local
├── AMQPTest.identcache
├── AMQPTest.res
├── LICENSE
├── README.md
├── TestBinding.dpr
├── TestBinding.dproj
├── TestBinding.dproj.local
├── TestBinding.identcache
├── TestCreateExchange.dpr
├── TestCreateExchange.dproj
├── TestCreateExchange.dproj.local
├── TestCreateExchange.identcache
├── TestRPCClient.dpr
├── TestRPCClient.dproj
├── TestRPCClient.dproj.local
├── TestRPCClient.identcache
├── TestRPCClient.res
├── TestRpcServer.dpr
├── TestRpcServer.dproj
├── TestRpcServer.dproj.local
├── TestRpcServer.identcache
├── TestRpcServer.lpi
├── TestRpcServer.lps
├── TestRpcServer.res
├── TestSendString.dpr
├── TestSendString.dproj
├── TestSendString.dproj.local
├── TestSendString.identcache
├── TestSendString.res
├── TestTimeout.dpr
├── TestTimeout.dproj
├── TestTimeout.dproj.local
├── TestTimeout.identcache
├── TestUnbind.dpr
├── TestUnbind.dproj
├── TestUnbind.dproj.local
├── TestUnbind.identcache
├── amqp.api.pas
├── amqp.connection.pas
├── amqp.consumer.pas
├── amqp.framing.pas
├── amqp.mem.pas
├── amqp.privt.pas
├── amqp.socket.pas
├── amqp.table.pas
├── amqp.tcp_socket.pas
├── amqp.time.pas
├── amqp_tcp_socket.pas
└── config.inc
/AMQPTest.dpr:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sonadorje/rabbitmq-delphi/e4931fc10be22d84d0bafe83e3349403dbeb3b9b/AMQPTest.dpr
--------------------------------------------------------------------------------
/AMQPTest.dproj.local:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1899-12-30 00:00:00.000.292,=D:\MyCode\AMQP-Delphi\Unit1.pas
5 | 1899-12-30 00:00:00.000.528,=D:\MyCode\AMQP-Delphi\Unit1.pas
6 | 1899-12-30 00:00:00.000.640,=D:\MyCode\AMQP-Delphi\Unit1.pas
7 | 1899-12-30 00:00:00.000.620,=D:\MyCode\AMQP-Delphi\Unit1.pas
8 | 1899-12-30 00:00:00.000.284,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.MethodFrame.pas
9 | 1899-12-30 00:00:00.000.159,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.BasicAckFrame.pas
10 | 1899-12-30 00:00:00.000.437,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.BasicFrame.pas
11 | 1899-12-30 00:00:00.000.724,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.ConnectionImpl.pas
12 | 1899-12-30 00:00:00.000.382,=D:\MyCode\AMQP-Delphi\Unit1.pas
13 | 1899-12-30 00:00:00.000.483,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.Types.pas
14 | 1899-12-30 00:00:00.000.724,=D:\MyCode\AMQP-Delphi\Unit1.pas
15 | 1899-12-30 00:00:00.000.001,=D:\MyCode\AMQP-Delphi\Unit1.pas
16 | 1899-12-30 00:00:00.000.772,=D:\MyCode\AMQP-Delphi\Unit1.pas
17 | 1899-12-30 00:00:00.000.417,=D:\MyCode\AMQP-Delphi\Unit1.pas
18 | 1899-12-30 00:00:00.000.129,=D:\MyCode\AMQP-Delphi\Unit1.pas
19 | 1899-12-30 00:00:00.000.180,=D:\MyCode\AMQP-Delphi\Unit1.pas
20 | 1899-12-30 00:00:00.000.816,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.Watchable.pas
21 | 1899-12-30 00:00:00.000.204,D:\MyCode\AMQP-Delphi\amqp.privt.pas=D:\MyCode\AMQP-Delphi\Unit2.pas
22 | 1899-12-30 00:00:00.000.761,D:\MyCode\AMQP-Delphi\AMQP.MethodFrame.pas=
23 | 1899-12-30 00:00:00.000.567,=D:\MyCode\AMQP-Delphi\Unit2.pas
24 | 1899-12-30 00:00:00.000.472,D:\MyCode\AMQP-Delphi\amqp.privt.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
25 | 1899-12-30 00:00:00.000.832,=D:\MyCode\AMQP-Delphi\MyFunc.pas
26 | 1899-12-30 00:00:00.000.655,=D:\MyCode\AMQP-Delphi\MyFunc.pas
27 | 1899-12-30 00:00:00.000.284,D:\MyCode\AMQP-Delphi\amqp.api.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
28 | 1899-12-30 00:00:00.000.714,D:\MyCode\AMQP-Delphi\MyFunc.pas=
29 | 1899-12-30 00:00:00.000.214,=D:\MyCode\AMQP-Delphi\Unit1.pas
30 | 1899-12-30 00:00:00.000.231,=D:\MyCode\AMQP-Delphi\Unit1.pas
31 | 1899-12-30 00:00:00.000.732,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.Field.pas
32 | 1899-12-30 00:00:00.000.316,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.OutBuffer.pas
33 | 1899-12-30 00:00:00.000.887,D:\MyCode\AMQP-Delphi\AMQP.Watchable.pas=
34 | 1899-12-30 00:00:00.000.658,D:\MyCode\AMQP-Delphi\AMQP.Field.pas=
35 | 1899-12-30 00:00:00.000.200,=D:\MyCode\AMQP-Delphi\Unit1.pas
36 | 1899-12-30 00:00:00.000.595,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.ExtFrame.pas
37 | 1899-12-30 00:00:00.000.044,D:\MyCode\AMQP-Delphi\amqp.consumer.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
38 | 1899-12-30 00:00:00.000.997,D:\MyCode\AMQP-Delphi\amqp.socket.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
39 | 1899-12-30 00:00:00.000.666,D:\MyCode\AMQP-Delphi\amqp.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
40 | 1899-12-30 00:00:00.000.566,D:\MyCode\AMQP-Delphi\amqp.pas=
41 | 1899-12-30 00:00:00.000.642,D:\MyCode\AMQP-Delphi\AMQP.BasicAckFrame.pas=
42 | 1899-12-30 00:00:00.000.862,D:\MyCode\AMQP-Delphi\AMQP.BasicFrame.pas=
43 | 1899-12-30 00:00:00.000.485,D:\MyCode\AMQP-Delphi\amqp.framing.pas=D:\MyCode\AMQP-Delphi\framing.pas
44 | 1899-12-30 00:00:00.000.926,D:\MyCode\AMQP-Delphi\AMQP.ConnectionImpl.pas=
45 | 1899-12-30 00:00:00.000.617,D:\MyCode\AMQP-Delphi\amqp_tcp_socket.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
46 | 1899-12-30 00:00:00.000.706,D:\MyCode\AMQP-Delphi\amqp.connection.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
47 | 1899-12-30 00:00:00.000.506,D:\MyCode\AMQP-Delphi\AMQP.Login.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
48 | 1899-12-30 00:00:00.000.711,D:\MyCode\AMQP-Delphi\AMQP.Login.pas=
49 | 1899-12-30 00:00:00.000.119,D:\MyCode\AMQP-Delphi\amqp.tcp_socket.pas=D:\MyCode\AMQP-Delphi\amqp_tcp_socket.pas
50 | 1899-12-30 00:00:00.000.567,D:\MyCode\AMQP-Delphi\amqp.mem.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
51 | 1899-12-30 00:00:00.000.312,D:\MyCode\AMQP-Delphi\amqp.table.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
52 | 1899-12-30 00:00:00.000.984,D:\MyCode\AMQP-Delphi\AMQP.ExtFrame.pas=
53 | 1899-12-30 00:00:00.000.623,D:\MyCode\AMQP-Delphi\framing.pas=D:\MyCode\AMQP-Delphi\amqp.privt.pas
54 | 1899-12-30 00:00:00.000.966,=D:\MyCode\AMQP-Delphi\Unit1.pas
55 | 1899-12-30 00:00:00.000.659,=D:\MyCode\AMQP-Delphi\Unit1.pas
56 | 1899-12-30 00:00:00.000.607,D:\MyCode\AMQP-Delphi\amqp.time.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
57 | 1899-12-30 00:00:00.000.805,D:\MyCode\AMQP-Delphi\AMQP.OutBuffer.pas=
58 | 1899-12-30 00:00:00.000.014,=D:\MyCode\AMQP-Delphi\Unit1.pas
59 | 1899-12-30 00:00:00.000.582,=D:\MyCode\AMQP-Delphi\Unit1.pas
60 | 1899-12-30 00:00:00.000.004,=D:\MyCode\AMQP-Delphi\Unit1.pas
61 | 1899-12-30 00:00:00.000.438,=D:\MyCode\AMQP-Delphi\Unit1.pas
62 | 1899-12-30 00:00:00.000.261,=D:\MyCode\Unit1.pas
63 | 1899-12-30 00:00:00.000.090,=D:\MyCode\Unit1.pas
64 | 1899-12-30 00:00:00.000.844,D:\MyCode\AMQP-Delphi\AMQP.Types.pas=
65 | 1899-12-30 00:00:00.000.500,=D:\MyCode\AMQP-Delphi\AMQP.Types.pas
66 | 1899-12-30 00:00:00.000.569,=D:\MyCode\Unit1.pas
67 | 1899-12-30 00:00:00.000.090,D:\MyCode\Project1.dproj=D:\MyCode\AMQP-Delphi\AMQPTest.dproj
68 | 1899-12-30 00:00:00.000.980,=D:\MyCode\Unit1.pas
69 | 1899-12-30 00:00:00.000.058,=D:\MyCode\Unit1.pas
70 |
71 |
72 |
--------------------------------------------------------------------------------
/AMQPTest.identcache:
--------------------------------------------------------------------------------
1 |
-D:\MyCode\rabbitmq-Delphi\demo\AMQP.Types.pas 0D:\MyCode\rabbitmq-Delphi\demo\amqp.consumer.pas 2D:\MyCode\rabbitmq-Delphi\demo\amqp.connection.pas +D:\MyCode\rabbitmq-Delphi\demo\AMQPTest.dpr +D:\MyCode\rabbitmq-Delphi\demo\amqp.mem.pas .D:\MyCode\rabbitmq-Delphi\demo\amqp.socket.pas 2D:\MyCode\rabbitmq-Delphi\demo\amqp.tcp_socket.pas +D:\MyCode\rabbitmq-Delphi\demo\amqp.api.pas ,D:\MyCode\rabbitmq-Delphi\demo\amqp.time.pas )D:\MyCode\rabbitmq-Delphi\demo\MyFunc.pas /D:\MyCode\rabbitmq-Delphi\demo\amqp.framing.pas -D:\MyCode\rabbitmq-Delphi\demo\amqp.table.pas -D:\MyCode\rabbitmq-Delphi\demo\amqp.privt.pas
--------------------------------------------------------------------------------
/AMQPTest.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sonadorje/rabbitmq-delphi/e4931fc10be22d84d0bafe83e3349403dbeb3b9b/AMQPTest.res
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # rabbitmq-delphi
2 | This project is directly translated from the open source project rabbitmq-c. On windows, it is compiled with Lazarus and Delphi XE2 and above. The network library used is https://github.com/winddriver/Delphi-Cross-Socket.
3 | If you don't know what rabbitmq,please read https://en.wikipedia.org/wiki/RabbitMQ or visit official web http://www.rabbitmq.com.
4 |
--------------------------------------------------------------------------------
/TestBinding.dpr:
--------------------------------------------------------------------------------
1 | program TestBinding;
2 |
3 | {$APPTYPE CONSOLE}
4 |
5 | {$R *.res}
6 |
7 | uses
8 | System.SysUtils,
9 | amqp.api in '..\amqp.api.pas',
10 | amqp.connection in '..\amqp.connection.pas',
11 | amqp.consumer in '..\amqp.consumer.pas',
12 | amqp.framing in '..\amqp.framing.pas',
13 | amqp.mem in '..\amqp.mem.pas',
14 | amqp.privt in '..\amqp.privt.pas',
15 | amqp.socket in '..\amqp.socket.pas',
16 | amqp.table in '..\amqp.table.pas',
17 | amqp.tcp_socket in '..\amqp.tcp_socket.pas',
18 | amqp.time in '..\amqp.time.pas',
19 | AMQP.Types in '..\AMQP.Types.pas',
20 | amqp_tcp_socket in '..\amqp_tcp_socket.pas';
21 |
22 | {var MyEnum : TMyEnum;
23 | begin
24 |
25 | MyEnum := Two;
26 | writeln(Ord(MyEnum)); // writes 1, because first element in enumeration is numbered zero
27 |
28 | MyEnum := TMyEnum(2); // Use TMyEnum as if it were a function
29 | Writeln (GetEnumName(TypeInfo(TMyEnum), Ord(MyEnum))); // Use RTTI to return the enum value's name
30 | readln;
31 |
32 | end. }
33 |
34 | function main:integer;
35 | var
36 | port, status : integer;
37 | ret : Tamqp_rpc_reply;
38 | socket : Pamqp_socket;
39 | conn : Pamqp_connection_state;
40 | props : Tamqp_basic_properties;
41 | hostname, bindkey, exchange, queue: PAnsiChar;
42 | vl: Tva_list;
43 | begin
44 | socket := nil;
45 |
46 | hostname := 'localhost';
47 | port := 5672;
48 | exchange := 'Test.EX';
49 | bindkey := 'test-key';
50 | queue := 'Queue.Test';
51 |
52 | if initializeWinsockIfNecessary() < 1 then
53 | begin
54 | Writeln('Failed to initialize "winsock": ');
55 | Exit;
56 | end;
57 |
58 | conn := amqp_new_connection();
59 | socket := amqp_tcp_socket_new(conn);
60 | if not Assigned(socket) then begin
61 | Writeln('creating TCP socket failed!');
62 | Exit;
63 | end;
64 | status := amqp_socket_open(socket, hostname, port);
65 | if status > 0 then begin
66 | Writeln('opening TCP socket failed!');
67 | Exit;
68 | end;
69 | vl.username := 'sa';
70 | vl.password := 'admin';
71 | vl.identity := '';
72 | ret := amqp_login(conn, '/', 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, vl);
73 |
74 | if ret.library_error < 0 then
75 | Exit;
76 |
77 | var P := amqp_channel_open(conn, 1);
78 | IF P = nil then
79 | Exit;
80 | var reply := amqp_get_rpc_reply(conn);
81 | if reply.library_error < 0 then
82 | Exit;
83 |
84 | amqp_queue_bind(conn, 1, amqp_cstring_bytes(queue),
85 | amqp_cstring_bytes(exchange), amqp_cstring_bytes(bindkey),
86 | amqp_empty_table);
87 | if reply.library_error < 0 then
88 | Exit;
89 | amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS);
90 | amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
91 | amqp_destroy_connection(conn);
92 | Result := 0;
93 | end;
94 |
95 |
96 | begin
97 | try
98 | Main;
99 | except
100 | on e:Exception do
101 | WriteLn(e.Message);
102 | end;
103 | end.
104 |
105 |
--------------------------------------------------------------------------------
/TestBinding.dproj.local:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1899-12-30 00:00:00.000.417,=D:\MyCode\AMQP-Delphi\Unit1.pas
5 | 1899-12-30 00:00:00.000.292,=D:\MyCode\AMQP-Delphi\Unit1.pas
6 | 1899-12-30 00:00:00.000.528,=D:\MyCode\AMQP-Delphi\Unit1.pas
7 | 1899-12-30 00:00:00.000.966,=D:\MyCode\AMQP-Delphi\Unit1.pas
8 | 1899-12-30 00:00:00.000.472,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.privt.pas
9 | 1899-12-30 00:00:00.000.666,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.pas
10 | 1899-12-30 00:00:00.000.567,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.mem.pas
11 | 1899-12-30 00:00:00.000.284,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.api.pas
12 | 1899-12-30 00:00:00.000.180,=D:\MyCode\AMQP-Delphi\Unit1.pas
13 | 1899-12-30 00:00:00.000.772,=D:\MyCode\AMQP-Delphi\Unit1.pas
14 | 1899-12-30 00:00:00.000.659,=D:\MyCode\AMQP-Delphi\Unit1.pas
15 | 1899-12-30 00:00:00.000.640,=D:\MyCode\AMQP-Delphi\Unit1.pas
16 | 1899-12-30 00:00:00.000.004,=D:\MyCode\AMQP-Delphi\Unit1.pas
17 | 1899-12-30 00:00:00.000.231,=D:\MyCode\AMQP-Delphi\Unit1.pas
18 | 1899-12-30 00:00:00.000.214,=D:\MyCode\AMQP-Delphi\Unit1.pas
19 | 1899-12-30 00:00:00.000.200,=D:\MyCode\AMQP-Delphi\Unit1.pas
20 | 1899-12-30 00:00:00.000.129,=D:\MyCode\AMQP-Delphi\Unit1.pas
21 | 1899-12-30 00:00:00.000.001,=D:\MyCode\AMQP-Delphi\Unit1.pas
22 | 1899-12-30 00:00:00.000.620,=D:\MyCode\AMQP-Delphi\Unit1.pas
23 | 1899-12-30 00:00:00.000.623,D:\MyCode\AMQP-Delphi\amqp.privt.pas=D:\MyCode\AMQP-Delphi\framing.pas
24 | 1899-12-30 00:00:00.000.797,=D:\MyCode\rabbitmq-Delphi\AMQP.Types.pas
25 | 1899-12-30 00:00:00.000.204,D:\MyCode\AMQP-Delphi\Unit2.pas=D:\MyCode\AMQP-Delphi\amqp.privt.pas
26 | 1899-12-30 00:00:00.000.567,=D:\MyCode\AMQP-Delphi\Unit2.pas
27 | 1899-12-30 00:00:00.000.761,D:\MyCode\AMQP-Delphi\AMQP.MethodFrame.pas=
28 | 1899-12-30 00:00:00.000.832,=D:\MyCode\AMQP-Delphi\MyFunc.pas
29 | 1899-12-30 00:00:00.000.714,D:\MyCode\AMQP-Delphi\MyFunc.pas=
30 | 1899-12-30 00:00:00.000.284,D:\MyCode\AMQP-Delphi\AMQP.MethodFrame.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
31 | 1899-12-30 00:00:00.000.655,=D:\MyCode\AMQP-Delphi\MyFunc.pas
32 | 1899-12-30 00:00:00.000.732,D:\MyCode\AMQP-Delphi\AMQP.Field.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
33 | 1899-12-30 00:00:00.000.506,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.Login.pas
34 | 1899-12-30 00:00:00.000.706,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.connection.pas
35 | 1899-12-30 00:00:00.000.997,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.socket.pas
36 | 1899-12-30 00:00:00.000.617,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp_tcp_socket.pas
37 | 1899-12-30 00:00:00.000.312,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.table.pas
38 | 1899-12-30 00:00:00.000.816,D:\MyCode\AMQP-Delphi\AMQP.Watchable.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
39 | 1899-12-30 00:00:00.000.658,D:\MyCode\AMQP-Delphi\AMQP.Field.pas=
40 | 1899-12-30 00:00:00.000.607,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.time.pas
41 | 1899-12-30 00:00:00.000.887,D:\MyCode\AMQP-Delphi\AMQP.Watchable.pas=
42 | 1899-12-30 00:00:00.000.724,=D:\MyCode\AMQP-Delphi\Unit1.pas
43 | 1899-12-30 00:00:00.000.642,D:\MyCode\AMQP-Delphi\AMQP.BasicAckFrame.pas=
44 | 1899-12-30 00:00:00.000.566,D:\MyCode\AMQP-Delphi\amqp.pas=
45 | 1899-12-30 00:00:00.000.580,=D:\MyCode\rabbitmq-Delphi\amqp.framing.pas
46 | 1899-12-30 00:00:00.000.159,D:\MyCode\AMQP-Delphi\AMQP.BasicAckFrame.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
47 | 1899-12-30 00:00:00.000.724,D:\MyCode\AMQP-Delphi\AMQP.ConnectionImpl.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
48 | 1899-12-30 00:00:00.000.700,=D:\MyCode\rabbitmq-Delphi\amqp.table.pas
49 | 1899-12-30 00:00:00.000.489,=D:\MyCode\rabbitmq-Delphi\amqp_tcp_socket.pas
50 | 1899-12-30 00:00:00.000.926,D:\MyCode\AMQP-Delphi\AMQP.ConnectionImpl.pas=
51 | 1899-12-30 00:00:00.000.669,=D:\MyCode\rabbitmq-Delphi\amqp.socket.pas
52 | 1899-12-30 00:00:00.000.470,=D:\MyCode\rabbitmq-Delphi\amqp.api.pas
53 | 1899-12-30 00:00:00.000.119,D:\MyCode\AMQP-Delphi\amqp_tcp_socket.pas=D:\MyCode\AMQP-Delphi\amqp.tcp_socket.pas
54 | 1899-12-30 00:00:00.000.605,=D:\MyCode\rabbitmq-Delphi\amqp.mem.pas
55 | 1899-12-30 00:00:00.000.711,D:\MyCode\AMQP-Delphi\AMQP.Login.pas=
56 | 1899-12-30 00:00:00.000.502,=D:\MyCode\rabbitmq-Delphi\amqp.connection.pas
57 | 1899-12-30 00:00:00.000.760,=D:\MyCode\rabbitmq-Delphi\amqp.time.pas
58 | 1899-12-30 00:00:00.000.539,=D:\MyCode\rabbitmq-Delphi\amqp.consumer.pas
59 | 1899-12-30 00:00:00.000.595,D:\MyCode\AMQP-Delphi\TestBinding.dproj=D:\MyCode\AMQP-Delphi\AMQPTest.dproj
60 | 1899-12-30 00:00:00.000.595,D:\MyCode\AMQP-Delphi\AMQP.ExtFrame.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
61 | 1899-12-30 00:00:00.000.984,D:\MyCode\AMQP-Delphi\AMQP.ExtFrame.pas=
62 | 1899-12-30 00:00:00.000.090,D:\MyCode\AMQP-Delphi\AMQPTest.dproj=D:\MyCode\Project1.dproj
63 | 1899-12-30 00:00:00.000.316,D:\MyCode\AMQP-Delphi\AMQP.OutBuffer.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
64 | 1899-12-30 00:00:00.000.090,=D:\MyCode\Unit1.pas
65 | 1899-12-30 00:00:00.000.261,=D:\MyCode\Unit1.pas
66 | 1899-12-30 00:00:00.000.805,D:\MyCode\AMQP-Delphi\AMQP.OutBuffer.pas=
67 | 1899-12-30 00:00:00.000.014,=D:\MyCode\AMQP-Delphi\Unit1.pas
68 | 1899-12-30 00:00:00.000.582,=D:\MyCode\AMQP-Delphi\Unit1.pas
69 | 1899-12-30 00:00:00.000.727,=D:\MyCode\rabbitmq-Delphi\amqp.tcp_socket.pas
70 | 1899-12-30 00:00:00.000.438,=D:\MyCode\AMQP-Delphi\Unit1.pas
71 | 1899-12-30 00:00:00.000.569,=D:\MyCode\Unit1.pas
72 | 1899-12-30 00:00:00.000.485,D:\MyCode\AMQP-Delphi\framing.pas=D:\MyCode\AMQP-Delphi\amqp.framing.pas
73 | 1899-12-30 00:00:00.000.483,D:\MyCode\AMQP-Delphi\AMQP.Types.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
74 | 1899-12-30 00:00:00.000.437,D:\MyCode\AMQP-Delphi\AMQP.BasicFrame.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
75 | 1899-12-30 00:00:00.000.862,D:\MyCode\AMQP-Delphi\AMQP.BasicFrame.pas=
76 | 1899-12-30 00:00:00.000.500,=D:\MyCode\AMQP-Delphi\AMQP.Types.pas
77 | 1899-12-30 00:00:00.000.058,=D:\MyCode\Unit1.pas
78 | 1899-12-30 00:00:00.000.980,=D:\MyCode\Unit1.pas
79 | 1899-12-30 00:00:00.000.844,D:\MyCode\AMQP-Delphi\AMQP.Types.pas=
80 | 1899-12-30 00:00:00.000.634,=D:\MyCode\rabbitmq-Delphi\amqp.privt.pas
81 |
82 |
83 |
--------------------------------------------------------------------------------
/TestBinding.identcache:
--------------------------------------------------------------------------------
1 |
.D:\MyCode\rabbitmq-Delphi\demo\TestBinding.dpr (D:\MyCode\rabbitmq-Delphi\amqp.privt.pas +D:\MyCode\rabbitmq-Delphi\amqp.consumer.pas &D:\MyCode\rabbitmq-Delphi\amqp.mem.pas -D:\MyCode\rabbitmq-Delphi\amqp.connection.pas *D:\MyCode\rabbitmq-Delphi\amqp.framing.pas 'D:\MyCode\rabbitmq-Delphi\amqp.time.pas -D:\MyCode\rabbitmq-Delphi\amqp_tcp_socket.pas -D:\MyCode\rabbitmq-Delphi\amqp.tcp_socket.pas (D:\MyCode\rabbitmq-Delphi\amqp.table.pas &D:\MyCode\rabbitmq-Delphi\amqp.api.pas )D:\MyCode\rabbitmq-Delphi\amqp.socket.pas (D:\MyCode\rabbitmq-Delphi\AMQP.Types.pas
--------------------------------------------------------------------------------
/TestCreateExchange.dpr:
--------------------------------------------------------------------------------
1 | program TestCreateExchange;
2 |
3 | {$APPTYPE CONSOLE}
4 |
5 | {$R *.res}
6 |
7 | uses
8 | System.SysUtils,
9 | amqp.api in '..\amqp.api.pas',
10 | amqp.connection in '..\amqp.connection.pas',
11 | amqp.consumer in '..\amqp.consumer.pas',
12 | amqp.framing in '..\amqp.framing.pas',
13 | amqp.mem in '..\amqp.mem.pas',
14 | amqp.privt in '..\amqp.privt.pas',
15 | amqp.socket in '..\amqp.socket.pas',
16 | amqp.table in '..\amqp.table.pas',
17 | amqp.tcp_socket in '..\amqp.tcp_socket.pas',
18 | amqp.time in '..\amqp.time.pas',
19 | AMQP.Types in '..\AMQP.Types.pas',
20 | amqp_tcp_socket in '..\amqp_tcp_socket.pas';
21 |
22 | {var MyEnum : TMyEnum;
23 | begin
24 |
25 | MyEnum := Two;
26 | writeln(Ord(MyEnum)); // writes 1, because first element in enumeration is numbered zero
27 |
28 | MyEnum := TMyEnum(2); // Use TMyEnum as if it were a function
29 | Writeln (GetEnumName(TypeInfo(TMyEnum), Ord(MyEnum))); // Use RTTI to return the enum value's name
30 | readln;
31 |
32 | end. }
33 |
34 | function main:integer;
35 | var
36 | port, status : integer;
37 | ret : Tamqp_rpc_reply;
38 | socket : Pamqp_socket;
39 | conn : Pamqp_connection_state;
40 | props : Tamqp_basic_properties;
41 | hostname, exchange, exchangetype: PAnsiChar;
42 | vl: Tva_list;
43 | begin
44 | socket := nil;
45 |
46 | hostname := 'localhost';
47 | port := 5672;
48 | exchange := 'Test.X';
49 | exchangetype := 'direct';
50 |
51 | if initializeWinsockIfNecessary() < 1 then
52 | begin
53 | Writeln('Failed to initialize "winsock": ');
54 | Exit;
55 | end;
56 |
57 | conn := amqp_new_connection();
58 | socket := amqp_tcp_socket_new(conn);
59 | if not Assigned(socket) then begin
60 | Writeln('creating TCP socket failed!');
61 | Exit;
62 | end;
63 | status := amqp_socket_open(socket, hostname, port);
64 | if status > 0 then begin
65 | Writeln('opening TCP socket failed!');
66 | Exit;
67 | end;
68 | vl.username := 'sa';
69 | vl.password := 'admin';
70 | vl.identity := '';
71 | ret := amqp_login(conn, '/', 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, vl);
72 |
73 | if ret.library_error < 0 then
74 | Exit;
75 |
76 | var P := amqp_channel_open(conn, 1);
77 | IF P = nil then
78 | Exit;
79 | var reply := amqp_get_rpc_reply(conn);
80 | if reply.library_error < 0 then
81 | Exit;
82 |
83 | amqp_exchange_declare(conn, 1, amqp_cstring_bytes(exchange),
84 | amqp_cstring_bytes(exchangetype), 0, 0, 0, 0,
85 | amqp_empty_table);
86 | if reply.library_error < 0 then
87 | Exit;
88 | amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS);
89 | amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
90 | amqp_destroy_connection(conn);
91 | Result := 0;
92 | end;
93 |
94 |
95 | begin
96 | try
97 | Main;
98 | except
99 | on e:Exception do
100 | WriteLn(e.Message);
101 | end;
102 | end.
103 |
104 |
--------------------------------------------------------------------------------
/TestCreateExchange.dproj.local:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1899-12-30 00:00:00.000.014,=D:\MyCode\AMQP-Delphi\Unit1.pas
5 | 1899-12-30 00:00:00.000.724,=D:\MyCode\AMQP-Delphi\Unit1.pas
6 | 1899-12-30 00:00:00.000.659,=D:\MyCode\AMQP-Delphi\Unit1.pas
7 | 1899-12-30 00:00:00.000.200,=D:\MyCode\AMQP-Delphi\Unit1.pas
8 | 1899-12-30 00:00:00.000.472,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.privt.pas
9 | 1899-12-30 00:00:00.000.666,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.pas
10 | 1899-12-30 00:00:00.000.567,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.mem.pas
11 | 1899-12-30 00:00:00.000.284,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.api.pas
12 | 1899-12-30 00:00:00.000.004,=D:\MyCode\AMQP-Delphi\Unit1.pas
13 | 1899-12-30 00:00:00.000.438,=D:\MyCode\AMQP-Delphi\Unit1.pas
14 | 1899-12-30 00:00:00.000.528,=D:\MyCode\AMQP-Delphi\Unit1.pas
15 | 1899-12-30 00:00:00.000.966,=D:\MyCode\AMQP-Delphi\Unit1.pas
16 | 1899-12-30 00:00:00.000.129,=D:\MyCode\AMQP-Delphi\Unit1.pas
17 | 1899-12-30 00:00:00.000.231,=D:\MyCode\AMQP-Delphi\Unit1.pas
18 | 1899-12-30 00:00:00.000.417,=D:\MyCode\AMQP-Delphi\Unit1.pas
19 | 1899-12-30 00:00:00.000.180,=D:\MyCode\AMQP-Delphi\Unit1.pas
20 | 1899-12-30 00:00:00.000.640,=D:\MyCode\AMQP-Delphi\Unit1.pas
21 | 1899-12-30 00:00:00.000.214,=D:\MyCode\AMQP-Delphi\Unit1.pas
22 | 1899-12-30 00:00:00.000.582,=D:\MyCode\AMQP-Delphi\Unit1.pas
23 | 1899-12-30 00:00:00.000.623,D:\MyCode\AMQP-Delphi\amqp.privt.pas=D:\MyCode\AMQP-Delphi\framing.pas
24 | 1899-12-30 00:00:00.000.615,=D:\MyCode\rabbitmq-Delphi\AMQP.Types.pas
25 | 1899-12-30 00:00:00.000.204,D:\MyCode\AMQP-Delphi\Unit2.pas=D:\MyCode\AMQP-Delphi\amqp.privt.pas
26 | 1899-12-30 00:00:00.000.567,=D:\MyCode\AMQP-Delphi\Unit2.pas
27 | 1899-12-30 00:00:00.000.761,D:\MyCode\AMQP-Delphi\AMQP.MethodFrame.pas=
28 | 1899-12-30 00:00:00.000.655,=D:\MyCode\AMQP-Delphi\MyFunc.pas
29 | 1899-12-30 00:00:00.000.714,D:\MyCode\AMQP-Delphi\MyFunc.pas=
30 | 1899-12-30 00:00:00.000.284,D:\MyCode\AMQP-Delphi\AMQP.MethodFrame.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
31 | 1899-12-30 00:00:00.000.832,=D:\MyCode\AMQP-Delphi\MyFunc.pas
32 | 1899-12-30 00:00:00.000.732,D:\MyCode\AMQP-Delphi\AMQP.Field.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
33 | 1899-12-30 00:00:00.000.506,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.Login.pas
34 | 1899-12-30 00:00:00.000.706,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.connection.pas
35 | 1899-12-30 00:00:00.000.997,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.socket.pas
36 | 1899-12-30 00:00:00.000.617,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp_tcp_socket.pas
37 | 1899-12-30 00:00:00.000.312,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.table.pas
38 | 1899-12-30 00:00:00.000.816,D:\MyCode\AMQP-Delphi\AMQP.Watchable.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
39 | 1899-12-30 00:00:00.000.658,D:\MyCode\AMQP-Delphi\AMQP.Field.pas=
40 | 1899-12-30 00:00:00.000.607,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.time.pas
41 | 1899-12-30 00:00:00.000.887,D:\MyCode\AMQP-Delphi\AMQP.Watchable.pas=
42 | 1899-12-30 00:00:00.000.292,=D:\MyCode\AMQP-Delphi\Unit1.pas
43 | 1899-12-30 00:00:00.000.566,D:\MyCode\AMQP-Delphi\amqp.pas=
44 | 1899-12-30 00:00:00.000.724,D:\MyCode\AMQP-Delphi\AMQP.ConnectionImpl.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
45 | 1899-12-30 00:00:00.000.159,D:\MyCode\AMQP-Delphi\AMQP.BasicAckFrame.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
46 | 1899-12-30 00:00:00.000.642,D:\MyCode\AMQP-Delphi\AMQP.BasicAckFrame.pas=
47 | 1899-12-30 00:00:00.000.926,D:\MyCode\AMQP-Delphi\AMQP.ConnectionImpl.pas=
48 | 1899-12-30 00:00:00.000.516,=D:\MyCode\rabbitmq-Delphi\amqp.table.pas
49 | 1899-12-30 00:00:00.000.649,=D:\MyCode\rabbitmq-Delphi\amqp_tcp_socket.pas
50 | 1899-12-30 00:00:00.000.575,D:\MyCode\AMQP-Delphi\TestCreateExchange.dproj=D:\MyCode\AMQP-Delphi\AMQPTest.dproj
51 | 1899-12-30 00:00:00.000.481,=D:\MyCode\rabbitmq-Delphi\amqp.socket.pas
52 | 1899-12-30 00:00:00.000.366,=D:\MyCode\rabbitmq-Delphi\amqp.framing.pas
53 | 1899-12-30 00:00:00.000.119,D:\MyCode\AMQP-Delphi\amqp_tcp_socket.pas=D:\MyCode\AMQP-Delphi\amqp.tcp_socket.pas
54 | 1899-12-30 00:00:00.000.394,=D:\MyCode\rabbitmq-Delphi\amqp.mem.pas
55 | 1899-12-30 00:00:00.000.711,D:\MyCode\AMQP-Delphi\AMQP.Login.pas=
56 | 1899-12-30 00:00:00.000.297,=D:\MyCode\rabbitmq-Delphi\amqp.connection.pas
57 | 1899-12-30 00:00:00.000.577,=D:\MyCode\rabbitmq-Delphi\amqp.time.pas
58 | 1899-12-30 00:00:00.000.326,=D:\MyCode\rabbitmq-Delphi\amqp.consumer.pas
59 | 1899-12-30 00:00:00.000.266,=D:\MyCode\rabbitmq-Delphi\amqp.api.pas
60 | 1899-12-30 00:00:00.000.595,D:\MyCode\AMQP-Delphi\AMQP.ExtFrame.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
61 | 1899-12-30 00:00:00.000.984,D:\MyCode\AMQP-Delphi\AMQP.ExtFrame.pas=
62 | 1899-12-30 00:00:00.000.090,D:\MyCode\AMQP-Delphi\AMQPTest.dproj=D:\MyCode\Project1.dproj
63 | 1899-12-30 00:00:00.000.316,D:\MyCode\AMQP-Delphi\AMQP.OutBuffer.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
64 | 1899-12-30 00:00:00.000.569,=D:\MyCode\Unit1.pas
65 | 1899-12-30 00:00:00.000.058,=D:\MyCode\Unit1.pas
66 | 1899-12-30 00:00:00.000.805,D:\MyCode\AMQP-Delphi\AMQP.OutBuffer.pas=
67 | 1899-12-30 00:00:00.000.772,=D:\MyCode\AMQP-Delphi\Unit1.pas
68 | 1899-12-30 00:00:00.000.001,=D:\MyCode\AMQP-Delphi\Unit1.pas
69 | 1899-12-30 00:00:00.000.546,=D:\MyCode\rabbitmq-Delphi\amqp.tcp_socket.pas
70 | 1899-12-30 00:00:00.000.620,=D:\MyCode\AMQP-Delphi\Unit1.pas
71 | 1899-12-30 00:00:00.000.980,=D:\MyCode\Unit1.pas
72 | 1899-12-30 00:00:00.000.485,D:\MyCode\AMQP-Delphi\framing.pas=D:\MyCode\AMQP-Delphi\amqp.framing.pas
73 | 1899-12-30 00:00:00.000.483,D:\MyCode\AMQP-Delphi\AMQP.Types.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
74 | 1899-12-30 00:00:00.000.437,D:\MyCode\AMQP-Delphi\AMQP.BasicFrame.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
75 | 1899-12-30 00:00:00.000.862,D:\MyCode\AMQP-Delphi\AMQP.BasicFrame.pas=
76 | 1899-12-30 00:00:00.000.500,=D:\MyCode\AMQP-Delphi\AMQP.Types.pas
77 | 1899-12-30 00:00:00.000.090,=D:\MyCode\Unit1.pas
78 | 1899-12-30 00:00:00.000.261,=D:\MyCode\Unit1.pas
79 | 1899-12-30 00:00:00.000.844,D:\MyCode\AMQP-Delphi\AMQP.Types.pas=
80 | 1899-12-30 00:00:00.000.446,=D:\MyCode\rabbitmq-Delphi\amqp.privt.pas
81 |
82 |
83 |
--------------------------------------------------------------------------------
/TestCreateExchange.identcache:
--------------------------------------------------------------------------------
1 |
-D:\MyCode\rabbitmq-Delphi\amqp_tcp_socket.pas (D:\MyCode\rabbitmq-Delphi\amqp.privt.pas &D:\MyCode\rabbitmq-Delphi\amqp.api.pas +D:\MyCode\rabbitmq-Delphi\amqp.consumer.pas &D:\MyCode\rabbitmq-Delphi\amqp.mem.pas -D:\MyCode\rabbitmq-Delphi\amqp.connection.pas *D:\MyCode\rabbitmq-Delphi\amqp.framing.pas 'D:\MyCode\rabbitmq-Delphi\amqp.time.pas (D:\MyCode\rabbitmq-Delphi\AMQP.Types.pas (D:\MyCode\rabbitmq-Delphi\amqp.table.pas 5D:\MyCode\rabbitmq-Delphi\demo\TestCreateExchange.dpr )D:\MyCode\rabbitmq-Delphi\amqp.socket.pas -D:\MyCode\rabbitmq-Delphi\amqp.tcp_socket.pas
--------------------------------------------------------------------------------
/TestRPCClient.dpr:
--------------------------------------------------------------------------------
1 | program TestRPCClient;
2 |
3 | {$APPTYPE CONSOLE}
4 |
5 | {$R *.res}
6 |
7 | uses
8 | System.SysUtils,
9 | Net.Winsock2,
10 | amqp.api in '..\amqp.api.pas',
11 | amqp.connection in '..\amqp.connection.pas',
12 | amqp.consumer in '..\amqp.consumer.pas',
13 | amqp.framing in '..\amqp.framing.pas',
14 | amqp.mem in '..\amqp.mem.pas',
15 | amqp.privt in '..\amqp.privt.pas',
16 | amqp.socket in '..\amqp.socket.pas',
17 | amqp.table in '..\amqp.table.pas',
18 | amqp.tcp_socket in '..\amqp.tcp_socket.pas',
19 | amqp.time in '..\amqp.time.pas',
20 | AMQP.Types in '..\AMQP.Types.pas',
21 | amqp_tcp_socket in '..\amqp_tcp_socket.pas';
22 |
23 | {var MyEnum : TMyEnum;
24 | begin
25 |
26 | MyEnum := Two;
27 | writeln(Ord(MyEnum)); // writes 1, because first element in enumeration is numbered zero
28 |
29 | MyEnum := TMyEnum(2); // Use TMyEnum as if it were a function
30 | Writeln (GetEnumName(TypeInfo(TMyEnum), Ord(MyEnum))); // Use RTTI to return the enum value's name
31 | readln;
32 |
33 | end. }
34 |
35 | function main:integer;
36 | var
37 | port, status : integer;
38 | ret : Tamqp_rpc_reply;
39 | socket : Pamqp_socket;
40 | conn : Pamqp_connection_state;
41 | props : Tamqp_basic_properties;
42 | host: Ansistring;
43 | hostname, exchange, queue, bindkey, messagebody, reply_Q: PAnsiChar;
44 | tval: Ttimeval ;
45 | tv: Ptimeval ;
46 | vl: Tva_list;
47 | frame: Tamqp_frame;
48 | reply_to_queue: Tamqp_bytes;
49 | begin
50 | socket := nil;
51 |
52 | {
53 | if ( ParamCount > 0 ) then
54 | host := ParamStr(1)
55 | else
56 | Exit; }
57 |
58 | hostname := 'localhost';
59 | port := 5672;
60 | exchange := 'Test.EX';
61 | queue := 'Test.Q';
62 | bindkey := 'test-key';
63 | messagebody := 'hello';
64 | reply_Q := 'reply.Q';
65 | if initializeWinsockIfNecessary() < 1 then
66 | begin
67 | Writeln('Failed to initialize "winsock": ');
68 | Exit;
69 | end;
70 |
71 | conn := amqp_new_connection();
72 | socket := amqp_tcp_socket_new(conn);
73 | if socket = nil then begin
74 | Writeln('creating TCP socket failed!');
75 | Exit;
76 | end;
77 |
78 | var res := amqp_socket_open(socket, hostname, port);
79 | if res < 0 then
80 | Exit;
81 |
82 | vl.username := 'sa';
83 | vl.password := 'admin';
84 | vl.identity := '';
85 | die_on_amqp_error(amqp_login(conn, '/', 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, vl),
86 | 'Logging in');
87 |
88 |
89 |
90 | amqp_channel_open(conn, 1);
91 | die_on_amqp_error(amqp_get_rpc_reply(conn), 'Opening channel');
92 |
93 | //create private reply_to queue
94 | //var r := amqp_queue_declare(conn, 1, amqp_empty_bytes, 0, 0, 0, 1, amqp_empty_table);
95 | //die_on_amqp_error(amqp_get_rpc_reply(conn), 'Declaring queue');
96 |
97 | reply_to_queue:= Tamqp_bytes.Create(reply_Q);
98 |
99 | if reply_to_queue.bytes = nil then
100 | begin
101 | Writeln('Out of memory while copying queue name');
102 | Exit(1);
103 | end;
104 |
105 | {
106 | send the message
107 | }
108 | begin
109 |
110 | //set properties
111 |
112 | props._flags := AMQP_BASIC_CONTENT_TYPE_FLAG or AMQP_BASIC_DELIVERY_MODE_FLAG or
113 | AMQP_BASIC_REPLY_TO_FLAG or AMQP_BASIC_CORRELATION_ID_FLAG;
114 | props.content_type := amqp_cstring_bytes('text/plain');
115 | props.delivery_mode := 2; { persistent delivery mode }
116 | {$if CompilerVersion < 34}
117 | props.reply_to := @reply_to_queue;
118 | {$ELSE}
119 | props.reply_to := reply_to_queue;
120 | {$ENDIF}
121 | if props.reply_to.bytes = nil then begin
122 | Write('Out of memory while copying queue name');
123 | Exit(1);
124 | end;
125 |
126 | props.correlation_id := amqp_cstring_bytes('1');
127 | die_on_error(amqp_basic_publish(conn, 1, amqp_cstring_bytes(exchange),
128 | amqp_cstring_bytes(bindkey), 0, 0,
129 | @props, amqp_cstring_bytes(messagebody)
130 | ), 'Publishing');
131 |
132 | props.reply_to.Destroy;
133 | end;
134 | {
135 | wait an answer
136 | }
137 | begin
138 |
139 | amqp_basic_consume(conn, 1, reply_to_queue, amqp_empty_bytes, 0, 1, 0,
140 | amqp_empty_table);
141 | die_on_amqp_error(amqp_get_rpc_reply(conn), 'Consuming');
142 | reply_to_queue.Destroy;
143 |
144 | begin
145 | while True do
146 | begin
147 | amqp_maybe_release_buffers(conn);
148 | result := amqp_simple_wait_frame(conn, frame);
149 | writeln(format('Result: %d',[result]));
150 | if result < 0 then begin
151 | break;
152 | end;
153 | writeln(format('Frame type: %u channel: %u',[frame.frame_type, frame.channel]));
154 | if frame.frame_type <> AMQP_FRAME_METHOD then begin
155 | continue;
156 | end;
157 | writeln(format('Method: %s',[amqp_method_name(frame.payload.method.id)]));
158 | if frame.payload.method.id <> AMQP_BASIC_DELIVER_METHOD then begin
159 | continue;
160 | end;
161 | var d := Pamqp_basic_deliver(frame.payload.method.decoded);
162 | Writeln('Delivery: %u exchange: %d %s routingkey: %d %s\n',
163 | d.delivery_tag, d.exchange.len,
164 | PAnsiChar(d.exchange.bytes), d.routing_key.len,
165 | PAnsiChar(d.routing_key.bytes));
166 | result := amqp_simple_wait_frame(conn, frame);
167 | if result < 0 then begin
168 | break;
169 | end;
170 | if frame.frame_type <> AMQP_FRAME_HEADER then begin
171 | Write('Expected header!');
172 | abort();
173 | end;
174 | var p := Pamqp_basic_properties(frame.payload.properties.decoded);
175 | if (p._flags and AMQP_BASIC_CONTENT_TYPE_FLAG) > 0 then begin
176 | Writeln('Content-type: %d %s\n', p.content_type.len,
177 | PAnsiChar(p.content_type.bytes));
178 | end;
179 | Writeln('----');
180 | var body_target := size_t(frame.payload.properties.body_size);
181 | var body_received := 0;
182 | while body_received < body_target do
183 | begin
184 | result := amqp_simple_wait_frame(conn, frame);
185 | if result < 0 then
186 | break;
187 |
188 | if frame.frame_type <> AMQP_FRAME_BODY then
189 | begin
190 | Write('Expected body!');
191 | abort();
192 | end;
193 | body_received := body_received + frame.payload.body_fragment.len;
194 | assert(body_received <= body_target);
195 | amqp_dump(frame.payload.body_fragment.bytes,
196 | frame.payload.body_fragment.len);
197 | end;
198 | if body_received <> body_target then
199 | { Can only happen when amqp_simple_wait_frame returns <= 0 }
200 | { We break here to close the connection }
201 | break;
202 |
203 | { everything was fine, we can quit now because we received the reply }
204 | break;
205 | end;
206 | end;
207 | end;
208 |
209 | die_on_amqp_error(amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS),
210 | 'Closing channel');
211 | die_on_amqp_error(amqp_connection_close(conn, AMQP_REPLY_SUCCESS),
212 | 'Closing connection');
213 | die_on_error(amqp_destroy_connection(conn), 'Ending connection');
214 |
215 | end;
216 |
217 |
218 | begin
219 | try
220 | Main;
221 | except
222 | on e:Exception do
223 | WriteLn(e.Message);
224 | end;
225 | end.
226 |
227 |
--------------------------------------------------------------------------------
/TestRPCClient.dproj.local:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1899-12-30 00:00:00.000.640,=D:\MyCode\AMQP-Delphi\Unit1.pas
5 | 1899-12-30 00:00:00.000.620,=D:\MyCode\AMQP-Delphi\Unit1.pas
6 | 1899-12-30 00:00:00.000.732,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.Field.pas
7 | 1899-12-30 00:00:00.000.214,=D:\MyCode\AMQP-Delphi\Unit1.pas
8 | 1899-12-30 00:00:00.000.966,=D:\MyCode\AMQP-Delphi\Unit1.pas
9 | 1899-12-30 00:00:00.000.772,=D:\MyCode\AMQP-Delphi\Unit1.pas
10 | 1899-12-30 00:00:00.000.437,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.BasicFrame.pas
11 | 1899-12-30 00:00:00.000.582,=D:\MyCode\AMQP-Delphi\Unit1.pas
12 | 1899-12-30 00:00:00.000.816,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.Watchable.pas
13 | 1899-12-30 00:00:00.000.284,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.MethodFrame.pas
14 | 1899-12-30 00:00:00.000.200,=D:\MyCode\AMQP-Delphi\Unit1.pas
15 | 1899-12-30 00:00:00.000.724,=D:\MyCode\AMQP-Delphi\Unit1.pas
16 | 1899-12-30 00:00:00.000.014,=D:\MyCode\AMQP-Delphi\Unit1.pas
17 | 1899-12-30 00:00:00.000.292,=D:\MyCode\AMQP-Delphi\Unit1.pas
18 | 1899-12-30 00:00:00.000.001,=D:\MyCode\AMQP-Delphi\Unit1.pas
19 | 1899-12-30 00:00:00.000.231,=D:\MyCode\AMQP-Delphi\Unit1.pas
20 | 1899-12-30 00:00:00.000.438,=D:\MyCode\AMQP-Delphi\Unit1.pas
21 | 1899-12-30 00:00:00.000.528,=D:\MyCode\AMQP-Delphi\Unit1.pas
22 | 1899-12-30 00:00:00.000.417,=D:\MyCode\AMQP-Delphi\Unit1.pas
23 | 1899-12-30 00:00:00.000.724,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.ConnectionImpl.pas
24 | 1899-12-30 00:00:00.000.658,D:\MyCode\AMQP-Delphi\AMQP.Field.pas=
25 | 1899-12-30 00:00:00.000.385,=D:\MyCode\rabbitmq-Delphi\AMQP.Types.pas
26 | 1899-12-30 00:00:00.000.204,D:\MyCode\AMQP-Delphi\amqp.privt.pas=D:\MyCode\AMQP-Delphi\Unit2.pas
27 | 1899-12-30 00:00:00.000.567,=D:\MyCode\AMQP-Delphi\Unit2.pas
28 | 1899-12-30 00:00:00.000.761,D:\MyCode\AMQP-Delphi\AMQP.MethodFrame.pas=
29 | 1899-12-30 00:00:00.000.832,=D:\MyCode\AMQP-Delphi\MyFunc.pas
30 | 1899-12-30 00:00:00.000.714,D:\MyCode\AMQP-Delphi\MyFunc.pas=
31 | 1899-12-30 00:00:00.000.284,D:\MyCode\AMQP-Delphi\amqp.api.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
32 | 1899-12-30 00:00:00.000.655,=D:\MyCode\AMQP-Delphi\MyFunc.pas
33 | 1899-12-30 00:00:00.000.472,D:\MyCode\AMQP-Delphi\amqp.privt.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
34 | 1899-12-30 00:00:00.000.316,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.OutBuffer.pas
35 | 1899-12-30 00:00:00.000.180,=D:\MyCode\AMQP-Delphi\Unit1.pas
36 | 1899-12-30 00:00:00.000.595,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.ExtFrame.pas
37 | 1899-12-30 00:00:00.000.159,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.BasicAckFrame.pas
38 | 1899-12-30 00:00:00.000.382,=D:\MyCode\AMQP-Delphi\Unit1.pas
39 | 1899-12-30 00:00:00.000.483,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.Types.pas
40 | 1899-12-30 00:00:00.000.887,D:\MyCode\AMQP-Delphi\AMQP.Watchable.pas=
41 | 1899-12-30 00:00:00.000.129,=D:\MyCode\AMQP-Delphi\Unit1.pas
42 | 1899-12-30 00:00:00.000.004,=D:\MyCode\AMQP-Delphi\Unit1.pas
43 | 1899-12-30 00:00:00.000.659,=D:\MyCode\AMQP-Delphi\Unit1.pas
44 | 1899-12-30 00:00:00.000.053,=D:\MyCode\rabbitmq-Delphi\amqp.api.pas
45 | 1899-12-30 00:00:00.000.666,D:\MyCode\AMQP-Delphi\amqp.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
46 | 1899-12-30 00:00:00.000.567,D:\MyCode\AMQP-Delphi\amqp.mem.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
47 | 1899-12-30 00:00:00.000.113,=D:\MyCode\rabbitmq-Delphi\amqp.consumer.pas
48 | 1899-12-30 00:00:00.000.566,D:\MyCode\AMQP-Delphi\amqp.pas=
49 | 1899-12-30 00:00:00.000.926,D:\MyCode\AMQP-Delphi\AMQP.ConnectionImpl.pas=
50 | 1899-12-30 00:00:00.000.485,D:\MyCode\AMQP-Delphi\amqp.framing.pas=D:\MyCode\AMQP-Delphi\framing.pas
51 | 1899-12-30 00:00:00.000.044,D:\MyCode\AMQP-Delphi\amqp.consumer.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
52 | 1899-12-30 00:00:00.000.997,D:\MyCode\AMQP-Delphi\amqp.socket.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
53 | 1899-12-30 00:00:00.000.119,D:\MyCode\AMQP-Delphi\amqp.tcp_socket.pas=D:\MyCode\AMQP-Delphi\amqp_tcp_socket.pas
54 | 1899-12-30 00:00:00.000.083,=D:\MyCode\rabbitmq-Delphi\amqp.connection.pas
55 | 1899-12-30 00:00:00.000.617,D:\MyCode\AMQP-Delphi\amqp_tcp_socket.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
56 | 1899-12-30 00:00:00.000.506,D:\MyCode\AMQP-Delphi\AMQP.Login.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
57 | 1899-12-30 00:00:00.000.711,D:\MyCode\AMQP-Delphi\AMQP.Login.pas=
58 | 1899-12-30 00:00:00.000.185,=D:\MyCode\rabbitmq-Delphi\amqp.mem.pas
59 | 1899-12-30 00:00:00.000.984,D:\MyCode\AMQP-Delphi\AMQP.ExtFrame.pas=
60 | 1899-12-30 00:00:00.000.346,=D:\MyCode\rabbitmq-Delphi\amqp.time.pas
61 | 1899-12-30 00:00:00.000.706,D:\MyCode\AMQP-Delphi\amqp.connection.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
62 | 1899-12-30 00:00:00.000.312,D:\MyCode\AMQP-Delphi\amqp.table.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
63 | 1899-12-30 00:00:00.000.642,D:\MyCode\AMQP-Delphi\AMQP.BasicAckFrame.pas=
64 | 1899-12-30 00:00:00.000.261,=D:\MyCode\Unit1.pas
65 | 1899-12-30 00:00:00.000.569,=D:\MyCode\Unit1.pas
66 | 1899-12-30 00:00:00.000.980,=D:\MyCode\Unit1.pas
67 | 1899-12-30 00:00:00.000.058,=D:\MyCode\Unit1.pas
68 | 1899-12-30 00:00:00.000.184,D:\MyCode\AMQP-Delphi\AMQPTest.dproj=D:\MyCode\AMQP-Delphi\TestRPCClient.dproj
69 | 1899-12-30 00:00:00.000.805,D:\MyCode\AMQP-Delphi\AMQP.OutBuffer.pas=
70 | 1899-12-30 00:00:00.000.314,=D:\MyCode\rabbitmq-Delphi\amqp.tcp_socket.pas
71 | 1899-12-30 00:00:00.000.090,D:\MyCode\Project1.dproj=D:\MyCode\AMQP-Delphi\AMQPTest.dproj
72 | 1899-12-30 00:00:00.000.607,D:\MyCode\AMQP-Delphi\amqp.time.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
73 | 1899-12-30 00:00:00.000.090,=D:\MyCode\Unit1.pas
74 | 1899-12-30 00:00:00.000.283,=D:\MyCode\rabbitmq-Delphi\amqp.table.pas
75 | 1899-12-30 00:00:00.000.416,=D:\MyCode\rabbitmq-Delphi\amqp_tcp_socket.pas
76 | 1899-12-30 00:00:00.000.155,=D:\MyCode\rabbitmq-Delphi\amqp.framing.pas
77 | 1899-12-30 00:00:00.000.253,=D:\MyCode\rabbitmq-Delphi\amqp.socket.pas
78 | 1899-12-30 00:00:00.000.862,D:\MyCode\AMQP-Delphi\AMQP.BasicFrame.pas=
79 | 1899-12-30 00:00:00.000.844,D:\MyCode\AMQP-Delphi\AMQP.Types.pas=
80 | 1899-12-30 00:00:00.000.218,=D:\MyCode\rabbitmq-Delphi\amqp.privt.pas
81 | 1899-12-30 00:00:00.000.623,D:\MyCode\AMQP-Delphi\framing.pas=D:\MyCode\AMQP-Delphi\amqp.privt.pas
82 | 1899-12-30 00:00:00.000.500,=D:\MyCode\AMQP-Delphi\AMQP.Types.pas
83 |
84 |
85 |
--------------------------------------------------------------------------------
/TestRPCClient.identcache:
--------------------------------------------------------------------------------
1 |
-D:\MyCode\rabbitmq-Delphi\amqp_tcp_socket.pas (D:\MyCode\rabbitmq-Delphi\amqp.privt.pas 0D:\MyCode\rabbitmq-Delphi\demo\TestRPCClient.dpr +D:\MyCode\rabbitmq-Delphi\amqp.consumer.pas &D:\MyCode\rabbitmq-Delphi\amqp.mem.pas -D:\MyCode\rabbitmq-Delphi\amqp.connection.pas *D:\MyCode\rabbitmq-Delphi\amqp.framing.pas 'D:\MyCode\rabbitmq-Delphi\amqp.time.pas (D:\MyCode\rabbitmq-Delphi\AMQP.Types.pas (D:\MyCode\rabbitmq-Delphi\amqp.table.pas &D:\MyCode\rabbitmq-Delphi\amqp.api.pas )D:\MyCode\rabbitmq-Delphi\amqp.socket.pas -D:\MyCode\rabbitmq-Delphi\amqp.tcp_socket.pas
--------------------------------------------------------------------------------
/TestRPCClient.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sonadorje/rabbitmq-delphi/e4931fc10be22d84d0bafe83e3349403dbeb3b9b/TestRPCClient.res
--------------------------------------------------------------------------------
/TestRpcServer.dpr:
--------------------------------------------------------------------------------
1 | program TestRpcServer;
2 |
3 | {$IFDEF FPC}
4 | {$MODE Delphi}
5 | {$ENDIF}
6 |
7 | {$APPTYPE CONSOLE}
8 |
9 | {$R *.res}
10 |
11 | uses
12 | {$IFNDEF FPC}
13 | System.SysUtils,
14 | Net.Winsock2,
15 | {$else}
16 | winsock2, SysUtils,
17 | {$ENDIF}
18 |
19 |
20 | amqp.connection,
21 | amqp.framing,
22 | AMQP.Types,
23 | amqp.time,
24 | amqp.socket,
25 | amqp.privt,
26 | amqp.table,
27 | amqp.mem,
28 | amqp.tcp_socket,
29 | amqp.api,
30 | amqp.consumer;
31 |
32 | {var MyEnum : TMyEnum;
33 | begin
34 |
35 | MyEnum := Two;
36 | writeln(Ord(MyEnum)); // writes 1, because first element in enumeration is numbered zero
37 |
38 | MyEnum := TMyEnum(2); // Use TMyEnum as if it were a function
39 | Writeln (GetEnumName(TypeInfo(TMyEnum), Ord(MyEnum))); // Use RTTI to return the enum value's name
40 | readln;
41 |
42 | end. }
43 |
44 | function main:integer;
45 | var
46 | port, status : integer;
47 | ret : Tamqp_rpc_reply;
48 | socket : Pamqp_socket;
49 | conn : Pamqp_connection_state;
50 | props : Tamqp_basic_properties;
51 | host: Ansistring;
52 | hostname, exchange, queue, routingkey, messagebody: PAnsiChar;
53 | tval: Ttimeval ;
54 | tv: Ptimeval ;
55 | vl: Tva_list;
56 | frame: Tamqp_frame;
57 | recv_queue: Tamqp_bytes;
58 | envelope: Tamqp_envelope;
59 | s: string;
60 | res: int;
61 | reply_props :Tamqp_basic_properties;
62 | replyQ : Pansichar;
63 | begin
64 | socket := nil;
65 |
66 | {
67 | if ( ParamCount > 0 ) then
68 | host := ParamStr(1)
69 | else
70 | Exit; }
71 |
72 | hostname := 'localhost';
73 | port := 5672;
74 | exchange := 'Test.EX';
75 | queue := 'Test.Q';
76 | routingkey := 'test-key';
77 | messagebody := 'Hello RpcClient, I''v received your message!';
78 |
79 |
80 | if initializeWinsockIfNecessary() < 1 then
81 | begin
82 | Writeln('Failed to initialize "winsock": ');
83 | Exit;
84 | end;
85 |
86 |
87 | conn := amqp_new_connection();
88 | socket := amqp_tcp_socket_new(conn);
89 | if socket = nil then begin
90 | Writeln('creating TCP socket failed!');
91 |
92 | Exit;
93 | end;
94 |
95 | res := socket.open( hostname, port);
96 | if res < 0 then
97 | Exit;
98 |
99 | vl.username := 'sa';
100 | vl.password := 'admin';
101 | vl.identity := '';
102 | die_on_amqp_error(amqp_login(conn, '/', 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, vl),
103 | 'Logging in');
104 |
105 |
106 |
107 | amqp_channel_open(conn, 1);
108 | die_on_amqp_error(amqp_get_rpc_reply(conn), 'Opening channel');
109 |
110 | recv_queue := Tamqp_bytes.Create(queue);
111 | amqp_basic_consume(conn, 1, recv_queue, amqp_empty_bytes, 0, 1, 0,
112 | amqp_empty_table);
113 |
114 | die_on_amqp_error(amqp_get_rpc_reply(conn), 'Consuming');
115 | {
116 | Get MSG
117 | 3. 获取消息的具体内容
118 | }
119 | begin
120 | while True do
121 | begin
122 | amqp_maybe_release_buffers(conn);
123 | ret := amqp_consume_message(conn, envelope, nil, 0);
124 | if AMQP_RESPONSE_NORMAL <> ret.reply_type then begin
125 | break;
126 | end;
127 |
128 | s := Format('Delivery %u, exchange %.*s routingkey %.*s\n',
129 | [envelope.delivery_tag, envelope.exchange.len,
130 | Pansichar(envelope.exchange.bytes), envelope.routing_key.len,
131 | PAnsiChar(envelope.routing_key.bytes)]);
132 | Writeln(s);
133 | Writeln('**************************************************************');
134 | amqp_dump(envelope.message.body.bytes, envelope.message.body.len);
135 | {
136 | 4. 此处为作者个人修改部分
137 | 因为在发送的时候初始化props为0, 则如果不是一个RPC的消息类型,则此处的reply_to的长度应该是0,否则,不为0
138 | }
139 | if 0 <> envelope.message.properties.reply_to.len then
140 | begin
141 | Writeln('there is a RPC reply');
142 |
143 |
144 | reply_props._flags := AMQP_BASIC_CONTENT_TYPE_FLAG or AMQP_BASIC_DELIVERY_MODE_FLAG;
145 | reply_props.content_type := amqp_cstring_bytes('text/plain');
146 | reply_props.delivery_mode := 2; { persistent delivery mode }
147 | reply_props.correlation_id := envelope.message.properties.correlation_id;
148 | {
149 | 5. 重点需要照顾的部分
150 | 此处EXCHANGE_NAME也就是交换机的名称为空,如果填写了上面接收使用的名称,rpc client端将不会收到,或者使用其他的名称也不行
151 | 在原本需要写入ROUTE_KEY的部分则需要填入接收到的reply_to信息,只有当这两部分都填写正确rpc client才会收到回复的消息
152 | }
153 | replyQ := PAnsiChar(envelope.message.properties.reply_to.bytes);
154 | die_on_error(amqp_basic_publish(conn, 1, amqp_cstring_bytes(''),
155 | amqp_cstring_bytes(replyQ), 0, 0,
156 | @reply_props, amqp_cstring_bytes(messagebody)),
157 | 'Publishing');
158 | end;
159 | envelope.destroy;
160 | end;
161 | end;
162 |
163 | die_on_amqp_error(amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS),
164 | 'Closing channel');
165 | die_on_amqp_error(amqp_connection_close(conn, AMQP_REPLY_SUCCESS),
166 | 'Closing connection');
167 | die_on_error(amqp_destroy_connection(conn), 'Ending connection');
168 |
169 | end;
170 |
171 | begin
172 | try
173 | Main;
174 | except
175 | on e:Exception do
176 | WriteLn(e.Message);
177 | end;
178 | end.
179 |
180 |
181 |
--------------------------------------------------------------------------------
/TestRpcServer.dproj.local:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1899-12-30 00:00:00.000.382,=D:\MyCode\AMQP-Delphi\Unit1.pas
5 | 1899-12-30 00:00:00.000.607,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.time.pas
6 | 1899-12-30 00:00:00.000.567,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.mem.pas
7 | 1899-12-30 00:00:00.000.312,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.table.pas
8 | 1899-12-30 00:00:00.000.001,=D:\MyCode\AMQP-Delphi\Unit1.pas
9 | 1899-12-30 00:00:00.000.417,=D:\MyCode\AMQP-Delphi\Unit1.pas
10 | 1899-12-30 00:00:00.000.772,=D:\MyCode\AMQP-Delphi\Unit1.pas
11 | 1899-12-30 00:00:00.000.004,=D:\MyCode\AMQP-Delphi\Unit1.pas
12 | 1899-12-30 00:00:00.000.997,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.socket.pas
13 | 1899-12-30 00:00:00.000.044,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.consumer.pas
14 | 1899-12-30 00:00:00.000.200,=D:\MyCode\AMQP-Delphi\Unit1.pas
15 | 1899-12-30 00:00:00.000.640,=D:\MyCode\AMQP-Delphi\Unit1.pas
16 | 1899-12-30 00:00:00.000.706,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.connection.pas
17 | 1899-12-30 00:00:00.000.506,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.Login.pas
18 | 1899-12-30 00:00:00.000.666,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.pas
19 | 1899-12-30 00:00:00.000.617,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp_tcp_socket.pas
20 | 1899-12-30 00:00:00.000.816,D:\MyCode\AMQP-Delphi\AMQP.Watchable.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
21 | 1899-12-30 00:00:00.000.284,D:\MyCode\AMQP-Delphi\AMQP.MethodFrame.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
22 | 1899-12-30 00:00:00.000.761,D:\MyCode\AMQP-Delphi\AMQP.MethodFrame.pas=
23 | 1899-12-30 00:00:00.000.724,D:\MyCode\AMQP-Delphi\AMQP.ConnectionImpl.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
24 | 1899-12-30 00:00:00.000.926,D:\MyCode\AMQP-Delphi\AMQP.ConnectionImpl.pas=
25 | 1899-12-30 00:00:00.000.832,=D:\MyCode\AMQP-Delphi\MyFunc.pas
26 | 1899-12-30 00:00:00.000.623,D:\MyCode\AMQP-Delphi\amqp.privt.pas=D:\MyCode\AMQP-Delphi\framing.pas
27 | 1899-12-30 00:00:00.000.655,=D:\MyCode\AMQP-Delphi\MyFunc.pas
28 | 1899-12-30 00:00:00.000.714,D:\MyCode\AMQP-Delphi\MyFunc.pas=
29 | 1899-12-30 00:00:00.000.658,D:\MyCode\AMQP-Delphi\AMQP.Field.pas=
30 | 1899-12-30 00:00:00.000.159,D:\MyCode\AMQP-Delphi\AMQP.BasicAckFrame.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
31 | 1899-12-30 00:00:00.000.887,D:\MyCode\AMQP-Delphi\AMQP.Watchable.pas=
32 | 1899-12-30 00:00:00.000.732,D:\MyCode\AMQP-Delphi\AMQP.Field.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
33 | 1899-12-30 00:00:00.000.567,=D:\MyCode\AMQP-Delphi\Unit2.pas
34 | 1899-12-30 00:00:00.000.566,D:\MyCode\AMQP-Delphi\amqp.pas=
35 | 1899-12-30 00:00:00.000.642,D:\MyCode\AMQP-Delphi\AMQP.BasicAckFrame.pas=
36 | 1899-12-30 00:00:00.000.204,D:\MyCode\AMQP-Delphi\Unit2.pas=D:\MyCode\AMQP-Delphi\amqp.privt.pas
37 | 1899-12-30 00:00:00.000.528,=D:\MyCode\AMQP-Delphi\Unit1.pas
38 | 1899-12-30 00:00:00.000.090,=D:\MyCode\Unit1.pas
39 | 1899-12-30 00:00:00.000.980,=D:\MyCode\Unit1.pas
40 | 1899-12-30 00:00:00.000.261,=D:\MyCode\Unit1.pas
41 | 1899-12-30 00:00:00.000.058,=D:\MyCode\Unit1.pas
42 | 1899-12-30 00:00:00.000.090,D:\MyCode\AMQP-Delphi\AMQPTest.dproj=D:\MyCode\Project1.dproj
43 | 1899-12-30 00:00:00.000.595,D:\MyCode\AMQP-Delphi\AMQP.ExtFrame.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
44 | 1899-12-30 00:00:00.000.569,=D:\MyCode\Unit1.pas
45 | 1899-12-30 00:00:00.000.431,D:\MyCode\AMQP-Delphi\AMQPTest.dproj=D:\MyCode\AMQP-Delphi\TestRpcServer.dproj
46 | 1899-12-30 00:00:00.000.862,D:\MyCode\AMQP-Delphi\AMQP.BasicFrame.pas=
47 | 1899-12-30 00:00:00.000.485,D:\MyCode\AMQP-Delphi\framing.pas=D:\MyCode\AMQP-Delphi\amqp.framing.pas
48 | 1899-12-30 00:00:00.000.711,D:\MyCode\AMQP-Delphi\AMQP.Login.pas=
49 | 1899-12-30 00:00:00.000.437,D:\MyCode\AMQP-Delphi\AMQP.BasicFrame.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
50 | 1899-12-30 00:00:00.000.844,D:\MyCode\AMQP-Delphi\AMQP.Types.pas=
51 | 1899-12-30 00:00:00.000.119,D:\MyCode\AMQP-Delphi\amqp_tcp_socket.pas=D:\MyCode\AMQP-Delphi\amqp.tcp_socket.pas
52 | 1899-12-30 00:00:00.000.483,D:\MyCode\AMQP-Delphi\AMQP.Types.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
53 | 1899-12-30 00:00:00.000.500,=D:\MyCode\AMQP-Delphi\AMQP.Types.pas
54 | 1899-12-30 00:00:00.000.984,D:\MyCode\AMQP-Delphi\AMQP.ExtFrame.pas=
55 | 1899-12-30 00:00:00.000.438,=D:\MyCode\AMQP-Delphi\Unit1.pas
56 | 1899-12-30 00:00:00.000.472,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.privt.pas
57 | 1899-12-30 00:00:00.000.014,=D:\MyCode\AMQP-Delphi\Unit1.pas
58 | 1899-12-30 00:00:00.000.231,=D:\MyCode\AMQP-Delphi\Unit1.pas
59 | 1899-12-30 00:00:00.000.129,=D:\MyCode\AMQP-Delphi\Unit1.pas
60 | 1899-12-30 00:00:00.000.724,=D:\MyCode\AMQP-Delphi\Unit1.pas
61 | 1899-12-30 00:00:00.000.284,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.api.pas
62 | 1899-12-30 00:00:00.000.582,=D:\MyCode\AMQP-Delphi\Unit1.pas
63 | 1899-12-30 00:00:00.000.180,=D:\MyCode\AMQP-Delphi\Unit1.pas
64 | 1899-12-30 00:00:00.000.966,=D:\MyCode\AMQP-Delphi\Unit1.pas
65 | 1899-12-30 00:00:00.000.316,D:\MyCode\AMQP-Delphi\AMQP.OutBuffer.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
66 | 1899-12-30 00:00:00.000.805,D:\MyCode\AMQP-Delphi\AMQP.OutBuffer.pas=
67 | 1899-12-30 00:00:00.000.659,=D:\MyCode\AMQP-Delphi\Unit1.pas
68 | 1899-12-30 00:00:00.000.292,=D:\MyCode\AMQP-Delphi\Unit1.pas
69 | 1899-12-30 00:00:00.000.214,=D:\MyCode\AMQP-Delphi\Unit1.pas
70 | 1899-12-30 00:00:00.000.620,=D:\MyCode\AMQP-Delphi\Unit1.pas
71 |
72 |
73 |
--------------------------------------------------------------------------------
/TestRpcServer.identcache:
--------------------------------------------------------------------------------
1 | 0D:\MyCode\rabbitmq-Delphi\demo\TestRpcServer.dpr
--------------------------------------------------------------------------------
/TestRpcServer.lpi:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
--------------------------------------------------------------------------------
/TestRpcServer.lps:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
--------------------------------------------------------------------------------
/TestRpcServer.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sonadorje/rabbitmq-delphi/e4931fc10be22d84d0bafe83e3349403dbeb3b9b/TestRpcServer.res
--------------------------------------------------------------------------------
/TestSendString.dpr:
--------------------------------------------------------------------------------
1 | program TestSendString;
2 |
3 | {$APPTYPE CONSOLE}
4 |
5 | {$R *.res}
6 |
7 | uses
8 | System.SysUtils,
9 | amqp.api in '..\amqp.api.pas',
10 | amqp.connection in '..\amqp.connection.pas',
11 | amqp.consumer in '..\amqp.consumer.pas',
12 | amqp.framing in '..\amqp.framing.pas',
13 | amqp.mem in '..\amqp.mem.pas',
14 | amqp.privt in '..\amqp.privt.pas',
15 | amqp.socket in '..\amqp.socket.pas',
16 | amqp.table in '..\amqp.table.pas',
17 | amqp.tcp_socket in '..\amqp.tcp_socket.pas',
18 | amqp.time in '..\amqp.time.pas',
19 | AMQP.Types in '..\AMQP.Types.pas',
20 | amqp_tcp_socket in '..\amqp_tcp_socket.pas';
21 |
22 | {var MyEnum : TMyEnum;
23 | begin
24 |
25 | MyEnum := Two;
26 | writeln(Ord(MyEnum)); // writes 1, because first element in enumeration is numbered zero
27 |
28 | MyEnum := TMyEnum(2); // Use TMyEnum as if it were a function
29 | Writeln (GetEnumName(TypeInfo(TMyEnum), Ord(MyEnum))); // Use RTTI to return the enum value's name
30 | readln;
31 |
32 | end. }
33 |
34 | function main:integer;
35 | var
36 | port, status : integer;
37 | ret : Tamqp_rpc_reply;
38 | socket : Pamqp_socket;
39 | conn : Pamqp_connection_state;
40 | props : Tamqp_basic_properties;
41 | hostname, routingkey, exchange, messagebody: PAnsiChar;
42 | vl: Tva_list;
43 | begin
44 | socket := nil;
45 |
46 | hostname := 'localhost';
47 | port := 5672;
48 | exchange := 'Test.EX';
49 | routingkey := 'test-key';
50 | messagebody := 'Hello, World!';
51 |
52 | if initializeWinsockIfNecessary() < 1 then
53 | begin
54 | Writeln('Failed to initialize "winsock": ');
55 | Exit;
56 | end;
57 |
58 | conn := amqp_new_connection();
59 | socket := amqp_tcp_socket_new(conn);
60 | if not Assigned(socket) then begin
61 | Writeln('creating TCP socket failed!');
62 | Exit;
63 | end;
64 | status := amqp_socket_open(socket, hostname, port);
65 | if status > 0 then begin
66 | Writeln('opening TCP socket failed!');
67 | Exit;
68 | end;
69 | vl.username := 'sa';
70 | vl.password := 'admin';
71 | vl.identity := '';
72 | die_on_amqp_error(amqp_login(conn, '/', 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, vl),
73 | 'Logging in');
74 |
75 | amqp_channel_open(conn, 1);
76 | die_on_amqp_error(amqp_get_rpc_reply(conn), 'Opening channel');
77 |
78 | begin
79 | props._flags := AMQP_BASIC_CONTENT_TYPE_FLAG or AMQP_BASIC_DELIVERY_MODE_FLAG;
80 | props.content_type := amqp_cstring_bytes('text/plain');
81 | props.delivery_mode := 2; { persistent delivery mode }
82 | amqp_basic_publish(conn, 1, amqp_cstring_bytes(exchange),
83 | amqp_cstring_bytes(routingkey), 0, 0,
84 | @props, amqp_cstring_bytes(messagebody));
85 | end;
86 | die_on_amqp_error(amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS),
87 | 'Closing channel');
88 | die_on_amqp_error(amqp_connection_close(conn, AMQP_REPLY_SUCCESS),
89 | 'Closing connection');
90 | die_on_error(amqp_destroy_connection(conn), 'Ending connection');
91 | end;
92 |
93 |
94 | begin
95 | try
96 | Main;
97 | except
98 | on e:Exception do
99 | WriteLn(e.Message);
100 | end;
101 | end.
102 |
103 |
--------------------------------------------------------------------------------
/TestSendString.dproj.local:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1899-12-30 00:00:00.000.417,=D:\MyCode\AMQP-Delphi\Unit1.pas
5 | 1899-12-30 00:00:00.000.640,=D:\MyCode\AMQP-Delphi\Unit1.pas
6 | 1899-12-30 00:00:00.000.732,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.Field.pas
7 | 1899-12-30 00:00:00.000.292,=D:\MyCode\AMQP-Delphi\Unit1.pas
8 | 1899-12-30 00:00:00.000.200,=D:\MyCode\AMQP-Delphi\Unit1.pas
9 | 1899-12-30 00:00:00.000.620,=D:\MyCode\AMQP-Delphi\Unit1.pas
10 | 1899-12-30 00:00:00.000.437,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.BasicFrame.pas
11 | 1899-12-30 00:00:00.000.772,=D:\MyCode\AMQP-Delphi\Unit1.pas
12 | 1899-12-30 00:00:00.000.816,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.Watchable.pas
13 | 1899-12-30 00:00:00.000.284,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.MethodFrame.pas
14 | 1899-12-30 00:00:00.000.129,=D:\MyCode\AMQP-Delphi\Unit1.pas
15 | 1899-12-30 00:00:00.000.014,=D:\MyCode\AMQP-Delphi\Unit1.pas
16 | 1899-12-30 00:00:00.000.528,=D:\MyCode\AMQP-Delphi\Unit1.pas
17 | 1899-12-30 00:00:00.000.001,=D:\MyCode\AMQP-Delphi\Unit1.pas
18 | 1899-12-30 00:00:00.000.659,=D:\MyCode\AMQP-Delphi\Unit1.pas
19 | 1899-12-30 00:00:00.000.724,=D:\MyCode\AMQP-Delphi\Unit1.pas
20 | 1899-12-30 00:00:00.000.438,=D:\MyCode\AMQP-Delphi\Unit1.pas
21 | 1899-12-30 00:00:00.000.214,=D:\MyCode\AMQP-Delphi\Unit1.pas
22 | 1899-12-30 00:00:00.000.966,=D:\MyCode\AMQP-Delphi\Unit1.pas
23 | 1899-12-30 00:00:00.000.658,D:\MyCode\AMQP-Delphi\AMQP.Field.pas=
24 | 1899-12-30 00:00:00.000.847,=D:\MyCode\rabbitmq-Delphi\AMQP.Types.pas
25 | 1899-12-30 00:00:00.000.204,D:\MyCode\AMQP-Delphi\amqp.privt.pas=D:\MyCode\AMQP-Delphi\Unit2.pas
26 | 1899-12-30 00:00:00.000.567,=D:\MyCode\AMQP-Delphi\Unit2.pas
27 | 1899-12-30 00:00:00.000.761,D:\MyCode\AMQP-Delphi\AMQP.MethodFrame.pas=
28 | 1899-12-30 00:00:00.000.714,D:\MyCode\AMQP-Delphi\MyFunc.pas=
29 | 1899-12-30 00:00:00.000.655,=D:\MyCode\AMQP-Delphi\MyFunc.pas
30 | 1899-12-30 00:00:00.000.284,D:\MyCode\AMQP-Delphi\amqp.api.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
31 | 1899-12-30 00:00:00.000.832,=D:\MyCode\AMQP-Delphi\MyFunc.pas
32 | 1899-12-30 00:00:00.000.472,D:\MyCode\AMQP-Delphi\amqp.privt.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
33 | 1899-12-30 00:00:00.000.595,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.ExtFrame.pas
34 | 1899-12-30 00:00:00.000.159,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.BasicAckFrame.pas
35 | 1899-12-30 00:00:00.000.724,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.ConnectionImpl.pas
36 | 1899-12-30 00:00:00.000.483,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.Types.pas
37 | 1899-12-30 00:00:00.000.316,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.OutBuffer.pas
38 | 1899-12-30 00:00:00.000.231,=D:\MyCode\AMQP-Delphi\Unit1.pas
39 | 1899-12-30 00:00:00.000.887,D:\MyCode\AMQP-Delphi\AMQP.Watchable.pas=
40 | 1899-12-30 00:00:00.000.004,=D:\MyCode\AMQP-Delphi\Unit1.pas
41 | 1899-12-30 00:00:00.000.582,=D:\MyCode\AMQP-Delphi\Unit1.pas
42 | 1899-12-30 00:00:00.000.180,=D:\MyCode\AMQP-Delphi\Unit1.pas
43 | 1899-12-30 00:00:00.000.479,=D:\MyCode\rabbitmq-Delphi\amqp.api.pas
44 | 1899-12-30 00:00:00.000.642,D:\MyCode\AMQP-Delphi\AMQP.BasicAckFrame.pas=
45 | 1899-12-30 00:00:00.000.567,D:\MyCode\AMQP-Delphi\amqp.mem.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
46 | 1899-12-30 00:00:00.000.544,=D:\MyCode\rabbitmq-Delphi\amqp.consumer.pas
47 | 1899-12-30 00:00:00.000.666,D:\MyCode\AMQP-Delphi\amqp.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
48 | 1899-12-30 00:00:00.000.485,D:\MyCode\AMQP-Delphi\amqp.framing.pas=D:\MyCode\AMQP-Delphi\framing.pas
49 | 1899-12-30 00:00:00.000.926,D:\MyCode\AMQP-Delphi\AMQP.ConnectionImpl.pas=
50 | 1899-12-30 00:00:00.000.566,D:\MyCode\AMQP-Delphi\amqp.pas=
51 | 1899-12-30 00:00:00.000.997,D:\MyCode\AMQP-Delphi\amqp.socket.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
52 | 1899-12-30 00:00:00.000.119,D:\MyCode\AMQP-Delphi\amqp.tcp_socket.pas=D:\MyCode\AMQP-Delphi\amqp_tcp_socket.pas
53 | 1899-12-30 00:00:00.000.513,=D:\MyCode\rabbitmq-Delphi\amqp.connection.pas
54 | 1899-12-30 00:00:00.000.617,D:\MyCode\AMQP-Delphi\amqp_tcp_socket.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
55 | 1899-12-30 00:00:00.000.506,D:\MyCode\AMQP-Delphi\AMQP.Login.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
56 | 1899-12-30 00:00:00.000.711,D:\MyCode\AMQP-Delphi\AMQP.Login.pas=
57 | 1899-12-30 00:00:00.000.618,=D:\MyCode\rabbitmq-Delphi\amqp.mem.pas
58 | 1899-12-30 00:00:00.000.984,D:\MyCode\AMQP-Delphi\AMQP.ExtFrame.pas=
59 | 1899-12-30 00:00:00.000.807,=D:\MyCode\rabbitmq-Delphi\amqp.time.pas
60 | 1899-12-30 00:00:00.000.706,D:\MyCode\AMQP-Delphi\amqp.connection.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
61 | 1899-12-30 00:00:00.000.312,D:\MyCode\AMQP-Delphi\amqp.table.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
62 | 1899-12-30 00:00:00.000.090,=D:\MyCode\Unit1.pas
63 | 1899-12-30 00:00:00.000.980,=D:\MyCode\Unit1.pas
64 | 1899-12-30 00:00:00.000.569,=D:\MyCode\Unit1.pas
65 | 1899-12-30 00:00:00.000.261,=D:\MyCode\Unit1.pas
66 | 1899-12-30 00:00:00.000.096,D:\MyCode\AMQP-Delphi\TestSendString.dproj=D:\MyCode\AMQP-Delphi\AMQPTest.dproj
67 | 1899-12-30 00:00:00.000.805,D:\MyCode\AMQP-Delphi\AMQP.OutBuffer.pas=
68 | 1899-12-30 00:00:00.000.755,=D:\MyCode\rabbitmq-Delphi\amqp.tcp_socket.pas
69 | 1899-12-30 00:00:00.000.090,D:\MyCode\Project1.dproj=D:\MyCode\AMQP-Delphi\AMQPTest.dproj
70 | 1899-12-30 00:00:00.000.607,D:\MyCode\AMQP-Delphi\amqp.time.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
71 | 1899-12-30 00:00:00.000.058,=D:\MyCode\Unit1.pas
72 | 1899-12-30 00:00:00.000.720,=D:\MyCode\rabbitmq-Delphi\amqp.table.pas
73 | 1899-12-30 00:00:00.000.879,=D:\MyCode\rabbitmq-Delphi\amqp_tcp_socket.pas
74 | 1899-12-30 00:00:00.000.586,=D:\MyCode\rabbitmq-Delphi\amqp.framing.pas
75 | 1899-12-30 00:00:00.000.686,=D:\MyCode\rabbitmq-Delphi\amqp.socket.pas
76 | 1899-12-30 00:00:00.000.862,D:\MyCode\AMQP-Delphi\AMQP.BasicFrame.pas=
77 | 1899-12-30 00:00:00.000.844,D:\MyCode\AMQP-Delphi\AMQP.Types.pas=
78 | 1899-12-30 00:00:00.000.649,=D:\MyCode\rabbitmq-Delphi\amqp.privt.pas
79 | 1899-12-30 00:00:00.000.623,D:\MyCode\AMQP-Delphi\framing.pas=D:\MyCode\AMQP-Delphi\amqp.privt.pas
80 | 1899-12-30 00:00:00.000.500,=D:\MyCode\AMQP-Delphi\AMQP.Types.pas
81 |
82 |
83 |
--------------------------------------------------------------------------------
/TestSendString.identcache:
--------------------------------------------------------------------------------
1 |
-D:\MyCode\rabbitmq-Delphi\amqp_tcp_socket.pas (D:\MyCode\rabbitmq-Delphi\amqp.privt.pas +D:\MyCode\rabbitmq-Delphi\amqp.consumer.pas &D:\MyCode\rabbitmq-Delphi\amqp.mem.pas 1D:\MyCode\rabbitmq-Delphi\demo\TestSendString.dpr -D:\MyCode\rabbitmq-Delphi\amqp.connection.pas *D:\MyCode\rabbitmq-Delphi\amqp.framing.pas 'D:\MyCode\rabbitmq-Delphi\amqp.time.pas (D:\MyCode\rabbitmq-Delphi\AMQP.Types.pas (D:\MyCode\rabbitmq-Delphi\amqp.table.pas &D:\MyCode\rabbitmq-Delphi\amqp.api.pas )D:\MyCode\rabbitmq-Delphi\amqp.socket.pas -D:\MyCode\rabbitmq-Delphi\amqp.tcp_socket.pas
--------------------------------------------------------------------------------
/TestSendString.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sonadorje/rabbitmq-delphi/e4931fc10be22d84d0bafe83e3349403dbeb3b9b/TestSendString.res
--------------------------------------------------------------------------------
/TestTimeout.dpr:
--------------------------------------------------------------------------------
1 | program TestTimeout;
2 |
3 | {$APPTYPE CONSOLE}
4 |
5 | {$R *.res}
6 |
7 | uses
8 | System.SysUtils,
9 | Net.Winsock2,
10 | amqp.api in '..\amqp.api.pas',
11 | amqp.connection in '..\amqp.connection.pas',
12 | amqp.consumer in '..\amqp.consumer.pas',
13 | amqp.framing in '..\amqp.framing.pas',
14 | amqp.mem in '..\amqp.mem.pas',
15 | amqp.privt in '..\amqp.privt.pas',
16 | amqp.socket in '..\amqp.socket.pas',
17 | amqp.table in '..\amqp.table.pas',
18 | amqp.tcp_socket in '..\amqp.tcp_socket.pas',
19 | amqp.time in '..\amqp.time.pas',
20 | AMQP.Types in '..\AMQP.Types.pas',
21 | amqp_tcp_socket in '..\amqp_tcp_socket.pas';
22 |
23 | {var MyEnum : TMyEnum;
24 | begin
25 |
26 | MyEnum := Two;
27 | writeln(Ord(MyEnum)); // writes 1, because first element in enumeration is numbered zero
28 |
29 | MyEnum := TMyEnum(2); // Use TMyEnum as if it were a function
30 | Writeln (GetEnumName(TypeInfo(TMyEnum), Ord(MyEnum))); // Use RTTI to return the enum value's name
31 | readln;
32 |
33 | end. }
34 |
35 | function main:integer;
36 | var
37 | port, status : integer;
38 | ret : Tamqp_rpc_reply;
39 | socket : Pamqp_socket;
40 | conn : Pamqp_connection_state;
41 | props : Tamqp_basic_properties;
42 | hostname, exchange, queue, bindkey: PAnsiChar;
43 | tval: Ttimeval ;
44 | tv: Ptimeval ;
45 | vl: Tva_list;
46 | begin
47 | socket := nil;
48 |
49 | hostname := 'localhost';
50 | port := 5672;
51 | exchange := 'Test.EX';
52 | queue := 'Queue.Test';
53 | bindkey := 'test-key';
54 |
55 | tv := @tval;
56 | //timeout 5'
57 | tv.tv_sec := 5;
58 |
59 | if initializeWinsockIfNecessary() < 1 then
60 | begin
61 | Writeln('Failed to initialize "winsock": ');
62 | Exit;
63 | end;
64 |
65 | conn := amqp_new_connection();
66 | socket := amqp_tcp_socket_new(conn);
67 | if socket = nil then begin
68 | Writeln('creating TCP socket failed!');
69 | Exit;
70 | end;
71 |
72 | var res := try_socket_open_noblock(socket, hostname, port, tv);
73 | if res < 0 then
74 | Exit;
75 |
76 | vl.username := 'sa';
77 | vl.password := 'admin';
78 | vl.identity := '';
79 | ret := amqp_login(conn, '/', 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, vl);
80 |
81 | if ret.library_error < 0 then
82 | Exit;
83 |
84 |
85 |
86 | amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS);
87 | amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
88 | amqp_destroy_connection(conn);
89 |
90 | end;
91 |
92 |
93 | begin
94 | try
95 | Main;
96 | except
97 | on e:Exception do
98 | WriteLn(e.Message);
99 | end;
100 | end.
101 |
102 |
--------------------------------------------------------------------------------
/TestTimeout.dproj.local:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1899-12-30 00:00:00.000.292,=D:\MyCode\AMQP-Delphi\Unit1.pas
5 | 1899-12-30 00:00:00.000.472,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.privt.pas
6 | 1899-12-30 00:00:00.000.180,=D:\MyCode\AMQP-Delphi\Unit1.pas
7 | 1899-12-30 00:00:00.000.772,=D:\MyCode\AMQP-Delphi\Unit1.pas
8 | 1899-12-30 00:00:00.000.284,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.api.pas
9 | 1899-12-30 00:00:00.000.567,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.mem.pas
10 | 1899-12-30 00:00:00.000.997,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.socket.pas
11 | 1899-12-30 00:00:00.000.129,=D:\MyCode\AMQP-Delphi\Unit1.pas
12 | 1899-12-30 00:00:00.000.666,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.pas
13 | 1899-12-30 00:00:00.000.528,=D:\MyCode\AMQP-Delphi\Unit1.pas
14 | 1899-12-30 00:00:00.000.200,=D:\MyCode\AMQP-Delphi\Unit1.pas
15 | 1899-12-30 00:00:00.000.014,=D:\MyCode\AMQP-Delphi\Unit1.pas
16 | 1899-12-30 00:00:00.000.231,=D:\MyCode\AMQP-Delphi\Unit1.pas
17 | 1899-12-30 00:00:00.000.659,=D:\MyCode\AMQP-Delphi\Unit1.pas
18 | 1899-12-30 00:00:00.000.417,=D:\MyCode\AMQP-Delphi\Unit1.pas
19 | 1899-12-30 00:00:00.000.966,=D:\MyCode\AMQP-Delphi\Unit1.pas
20 | 1899-12-30 00:00:00.000.620,=D:\MyCode\AMQP-Delphi\Unit1.pas
21 | 1899-12-30 00:00:00.000.001,=D:\MyCode\AMQP-Delphi\Unit1.pas
22 | 1899-12-30 00:00:00.000.004,=D:\MyCode\AMQP-Delphi\Unit1.pas
23 | 1899-12-30 00:00:00.000.372,D:\MyCode\AMQP-Delphi\TestTimeout.dproj=D:\MyCode\AMQP-Delphi\AMQPTest.dproj
24 | 1899-12-30 00:00:00.000.712,=D:\MyCode\rabbitmq-Delphi\AMQP.Types.pas
25 | 1899-12-30 00:00:00.000.567,=D:\MyCode\AMQP-Delphi\Unit2.pas
26 | 1899-12-30 00:00:00.000.623,D:\MyCode\AMQP-Delphi\amqp.privt.pas=D:\MyCode\AMQP-Delphi\framing.pas
27 | 1899-12-30 00:00:00.000.761,D:\MyCode\AMQP-Delphi\AMQP.MethodFrame.pas=
28 | 1899-12-30 00:00:00.000.832,=D:\MyCode\AMQP-Delphi\MyFunc.pas
29 | 1899-12-30 00:00:00.000.714,D:\MyCode\AMQP-Delphi\MyFunc.pas=
30 | 1899-12-30 00:00:00.000.284,D:\MyCode\AMQP-Delphi\AMQP.MethodFrame.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
31 | 1899-12-30 00:00:00.000.655,=D:\MyCode\AMQP-Delphi\MyFunc.pas
32 | 1899-12-30 00:00:00.000.204,D:\MyCode\AMQP-Delphi\Unit2.pas=D:\MyCode\AMQP-Delphi\amqp.privt.pas
33 | 1899-12-30 00:00:00.000.706,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.connection.pas
34 | 1899-12-30 00:00:00.000.312,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.table.pas
35 | 1899-12-30 00:00:00.000.617,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp_tcp_socket.pas
36 | 1899-12-30 00:00:00.000.506,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.Login.pas
37 | 1899-12-30 00:00:00.000.607,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\amqp.time.pas
38 | 1899-12-30 00:00:00.000.658,D:\MyCode\AMQP-Delphi\AMQP.Field.pas=
39 | 1899-12-30 00:00:00.000.732,D:\MyCode\AMQP-Delphi\AMQP.Field.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
40 | 1899-12-30 00:00:00.000.887,D:\MyCode\AMQP-Delphi\AMQP.Watchable.pas=
41 | 1899-12-30 00:00:00.000.816,D:\MyCode\AMQP-Delphi\AMQP.Watchable.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
42 | 1899-12-30 00:00:00.000.640,=D:\MyCode\AMQP-Delphi\Unit1.pas
43 | 1899-12-30 00:00:00.000.566,D:\MyCode\AMQP-Delphi\amqp.pas=
44 | 1899-12-30 00:00:00.000.724,D:\MyCode\AMQP-Delphi\AMQP.ConnectionImpl.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
45 | 1899-12-30 00:00:00.000.159,D:\MyCode\AMQP-Delphi\AMQP.BasicAckFrame.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
46 | 1899-12-30 00:00:00.000.642,D:\MyCode\AMQP-Delphi\AMQP.BasicAckFrame.pas=
47 | 1899-12-30 00:00:00.000.926,D:\MyCode\AMQP-Delphi\AMQP.ConnectionImpl.pas=
48 | 1899-12-30 00:00:00.000.744,=D:\MyCode\rabbitmq-Delphi\amqp_tcp_socket.pas
49 | 1899-12-30 00:00:00.000.437,D:\MyCode\AMQP-Delphi\AMQP.BasicFrame.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
50 | 1899-12-30 00:00:00.000.542,=D:\MyCode\rabbitmq-Delphi\amqp.socket.pas
51 | 1899-12-30 00:00:00.000.580,=D:\MyCode\rabbitmq-Delphi\amqp.table.pas
52 | 1899-12-30 00:00:00.000.412,=D:\MyCode\rabbitmq-Delphi\amqp.framing.pas
53 | 1899-12-30 00:00:00.000.119,D:\MyCode\AMQP-Delphi\amqp_tcp_socket.pas=D:\MyCode\AMQP-Delphi\amqp.tcp_socket.pas
54 | 1899-12-30 00:00:00.000.459,=D:\MyCode\rabbitmq-Delphi\amqp.mem.pas
55 | 1899-12-30 00:00:00.000.711,D:\MyCode\AMQP-Delphi\AMQP.Login.pas=
56 | 1899-12-30 00:00:00.000.313,=D:\MyCode\rabbitmq-Delphi\amqp.connection.pas
57 | 1899-12-30 00:00:00.000.672,=D:\MyCode\rabbitmq-Delphi\amqp.time.pas
58 | 1899-12-30 00:00:00.000.358,=D:\MyCode\rabbitmq-Delphi\amqp.consumer.pas
59 | 1899-12-30 00:00:00.000.272,=D:\MyCode\rabbitmq-Delphi\amqp.api.pas
60 | 1899-12-30 00:00:00.000.595,D:\MyCode\AMQP-Delphi\AMQP.ExtFrame.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
61 | 1899-12-30 00:00:00.000.984,D:\MyCode\AMQP-Delphi\AMQP.ExtFrame.pas=
62 | 1899-12-30 00:00:00.000.316,D:\MyCode\AMQP-Delphi\AMQP.OutBuffer.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
63 | 1899-12-30 00:00:00.000.805,D:\MyCode\AMQP-Delphi\AMQP.OutBuffer.pas=
64 | 1899-12-30 00:00:00.000.090,=D:\MyCode\Unit1.pas
65 | 1899-12-30 00:00:00.000.090,D:\MyCode\AMQP-Delphi\AMQPTest.dproj=D:\MyCode\Project1.dproj
66 | 1899-12-30 00:00:00.000.636,=D:\MyCode\rabbitmq-Delphi\amqp.tcp_socket.pas
67 | 1899-12-30 00:00:00.000.214,=D:\MyCode\AMQP-Delphi\Unit1.pas
68 | 1899-12-30 00:00:00.000.724,=D:\MyCode\AMQP-Delphi\Unit1.pas
69 | 1899-12-30 00:00:00.000.582,=D:\MyCode\AMQP-Delphi\Unit1.pas
70 | 1899-12-30 00:00:00.000.438,=D:\MyCode\AMQP-Delphi\Unit1.pas
71 | 1899-12-30 00:00:00.000.980,=D:\MyCode\Unit1.pas
72 | 1899-12-30 00:00:00.000.483,D:\MyCode\AMQP-Delphi\AMQP.Types.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
73 | 1899-12-30 00:00:00.000.500,=D:\MyCode\AMQP-Delphi\AMQP.Types.pas
74 | 1899-12-30 00:00:00.000.862,D:\MyCode\AMQP-Delphi\AMQP.BasicFrame.pas=
75 | 1899-12-30 00:00:00.000.485,D:\MyCode\AMQP-Delphi\framing.pas=D:\MyCode\AMQP-Delphi\amqp.framing.pas
76 | 1899-12-30 00:00:00.000.844,D:\MyCode\AMQP-Delphi\AMQP.Types.pas=
77 | 1899-12-30 00:00:00.000.058,=D:\MyCode\Unit1.pas
78 | 1899-12-30 00:00:00.000.261,=D:\MyCode\Unit1.pas
79 | 1899-12-30 00:00:00.000.499,=D:\MyCode\rabbitmq-Delphi\amqp.privt.pas
80 | 1899-12-30 00:00:00.000.569,=D:\MyCode\Unit1.pas
81 |
82 |
83 |
--------------------------------------------------------------------------------
/TestTimeout.identcache:
--------------------------------------------------------------------------------
1 |
-D:\MyCode\rabbitmq-Delphi\amqp_tcp_socket.pas (D:\MyCode\rabbitmq-Delphi\amqp.privt.pas +D:\MyCode\rabbitmq-Delphi\amqp.consumer.pas &D:\MyCode\rabbitmq-Delphi\amqp.mem.pas -D:\MyCode\rabbitmq-Delphi\amqp.connection.pas .D:\MyCode\rabbitmq-Delphi\demo\TestTimeout.dpr *D:\MyCode\rabbitmq-Delphi\amqp.framing.pas 'D:\MyCode\rabbitmq-Delphi\amqp.time.pas (D:\MyCode\rabbitmq-Delphi\AMQP.Types.pas (D:\MyCode\rabbitmq-Delphi\amqp.table.pas &D:\MyCode\rabbitmq-Delphi\amqp.api.pas )D:\MyCode\rabbitmq-Delphi\amqp.socket.pas -D:\MyCode\rabbitmq-Delphi\amqp.tcp_socket.pas
--------------------------------------------------------------------------------
/TestUnbind.dpr:
--------------------------------------------------------------------------------
1 | program TestUnbind;
2 |
3 | {$APPTYPE CONSOLE}
4 |
5 | {$R *.res}
6 |
7 | uses
8 | System.SysUtils,
9 | amqp.api in '..\amqp.api.pas',
10 | amqp.connection in '..\amqp.connection.pas',
11 | amqp.consumer in '..\amqp.consumer.pas',
12 | amqp.framing in '..\amqp.framing.pas',
13 | amqp.mem in '..\amqp.mem.pas',
14 | amqp.privt in '..\amqp.privt.pas',
15 | amqp.socket in '..\amqp.socket.pas',
16 | amqp.table in '..\amqp.table.pas',
17 | amqp.tcp_socket in '..\amqp.tcp_socket.pas',
18 | amqp.time in '..\amqp.time.pas',
19 | AMQP.Types in '..\AMQP.Types.pas',
20 | amqp_tcp_socket in '..\amqp_tcp_socket.pas';
21 |
22 | {var MyEnum : TMyEnum;
23 | begin
24 |
25 | MyEnum := Two;
26 | writeln(Ord(MyEnum)); // writes 1, because first element in enumeration is numbered zero
27 |
28 | MyEnum := TMyEnum(2); // Use TMyEnum as if it were a function
29 | Writeln (GetEnumName(TypeInfo(TMyEnum), Ord(MyEnum))); // Use RTTI to return the enum value's name
30 | readln;
31 |
32 | end. }
33 |
34 | function main:integer;
35 | var
36 | port, status : integer;
37 | ret : Tamqp_rpc_reply;
38 | socket : Pamqp_socket;
39 | conn : Pamqp_connection_state;
40 | props : Tamqp_basic_properties;
41 | hostname, exchange, queue, bindkey: PAnsiChar;
42 | vl: Tva_list;
43 | begin
44 | socket := nil;
45 |
46 | hostname := 'localhost';
47 | port := 5672;
48 | exchange := 'Test.EX';
49 | queue := 'Queue.Test';
50 | bindkey := 'test-key';
51 |
52 | if initializeWinsockIfNecessary() < 1 then
53 | begin
54 | Writeln('Failed to initialize "winsock": ');
55 | Exit;
56 | end;
57 |
58 | conn := amqp_new_connection();
59 | socket := amqp_tcp_socket_new(conn);
60 | if not Assigned(socket) then begin
61 | Writeln('creating TCP socket failed!');
62 | Exit;
63 | end;
64 | status := amqp_socket_open(socket, hostname, port);
65 | if status > 0 then begin
66 | Writeln('opening TCP socket failed!');
67 | Exit;
68 | end;
69 | vl.username := 'sa';
70 | vl.password := 'admin';
71 | vl.identity := '';
72 | ret := amqp_login(conn, '/', 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, vl);
73 |
74 | if ret.library_error < 0 then
75 | Exit;
76 |
77 | var P := amqp_channel_open(conn, 1);
78 | IF P = nil then
79 | Exit;
80 | var reply := amqp_get_rpc_reply(conn);
81 | if reply.library_error < 0 then
82 | Exit;
83 |
84 | amqp_queue_unbind(conn, 1, amqp_cstring_bytes(queue),
85 | amqp_cstring_bytes(exchange),
86 | amqp_cstring_bytes(bindkey), amqp_empty_table);
87 | if reply.library_error < 0 then
88 | Exit;
89 | amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS);
90 | amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
91 | amqp_destroy_connection(conn);
92 |
93 | end;
94 |
95 |
96 | begin
97 | try
98 | Main;
99 | except
100 | on e:Exception do
101 | WriteLn(e.Message);
102 | end;
103 | end.
104 |
105 |
--------------------------------------------------------------------------------
/TestUnbind.dproj.local:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1899-12-30 00:00:00.000.724,=D:\MyCode\AMQP-Delphi\Unit1.pas
5 | 1899-12-30 00:00:00.000.640,=D:\MyCode\AMQP-Delphi\Unit1.pas
6 | 1899-12-30 00:00:00.000.732,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.Field.pas
7 | 1899-12-30 00:00:00.000.659,=D:\MyCode\AMQP-Delphi\Unit1.pas
8 | 1899-12-30 00:00:00.000.438,=D:\MyCode\AMQP-Delphi\Unit1.pas
9 | 1899-12-30 00:00:00.000.180,=D:\MyCode\AMQP-Delphi\Unit1.pas
10 | 1899-12-30 00:00:00.000.437,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.BasicFrame.pas
11 | 1899-12-30 00:00:00.000.014,=D:\MyCode\AMQP-Delphi\Unit1.pas
12 | 1899-12-30 00:00:00.000.816,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.Watchable.pas
13 | 1899-12-30 00:00:00.000.284,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.MethodFrame.pas
14 | 1899-12-30 00:00:00.000.214,=D:\MyCode\AMQP-Delphi\Unit1.pas
15 | 1899-12-30 00:00:00.000.966,=D:\MyCode\AMQP-Delphi\Unit1.pas
16 | 1899-12-30 00:00:00.000.200,=D:\MyCode\AMQP-Delphi\Unit1.pas
17 | 1899-12-30 00:00:00.000.582,=D:\MyCode\AMQP-Delphi\Unit1.pas
18 | 1899-12-30 00:00:00.000.528,=D:\MyCode\AMQP-Delphi\Unit1.pas
19 | 1899-12-30 00:00:00.000.292,=D:\MyCode\AMQP-Delphi\Unit1.pas
20 | 1899-12-30 00:00:00.000.772,=D:\MyCode\AMQP-Delphi\Unit1.pas
21 | 1899-12-30 00:00:00.000.001,=D:\MyCode\AMQP-Delphi\Unit1.pas
22 | 1899-12-30 00:00:00.000.417,=D:\MyCode\AMQP-Delphi\Unit1.pas
23 | 1899-12-30 00:00:00.000.658,D:\MyCode\AMQP-Delphi\AMQP.Field.pas=
24 | 1899-12-30 00:00:00.000.643,=D:\MyCode\rabbitmq-Delphi\AMQP.Types.pas
25 | 1899-12-30 00:00:00.000.204,D:\MyCode\AMQP-Delphi\amqp.privt.pas=D:\MyCode\AMQP-Delphi\Unit2.pas
26 | 1899-12-30 00:00:00.000.567,=D:\MyCode\AMQP-Delphi\Unit2.pas
27 | 1899-12-30 00:00:00.000.761,D:\MyCode\AMQP-Delphi\AMQP.MethodFrame.pas=
28 | 1899-12-30 00:00:00.000.714,D:\MyCode\AMQP-Delphi\MyFunc.pas=
29 | 1899-12-30 00:00:00.000.655,=D:\MyCode\AMQP-Delphi\MyFunc.pas
30 | 1899-12-30 00:00:00.000.284,D:\MyCode\AMQP-Delphi\amqp.api.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
31 | 1899-12-30 00:00:00.000.832,=D:\MyCode\AMQP-Delphi\MyFunc.pas
32 | 1899-12-30 00:00:00.000.472,D:\MyCode\AMQP-Delphi\amqp.privt.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
33 | 1899-12-30 00:00:00.000.595,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.ExtFrame.pas
34 | 1899-12-30 00:00:00.000.159,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.BasicAckFrame.pas
35 | 1899-12-30 00:00:00.000.724,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.ConnectionImpl.pas
36 | 1899-12-30 00:00:00.000.483,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.Types.pas
37 | 1899-12-30 00:00:00.000.316,D:\MyCode\AMQP-Delphi\Unit1.pas=D:\MyCode\AMQP-Delphi\AMQP.OutBuffer.pas
38 | 1899-12-30 00:00:00.000.129,=D:\MyCode\AMQP-Delphi\Unit1.pas
39 | 1899-12-30 00:00:00.000.887,D:\MyCode\AMQP-Delphi\AMQP.Watchable.pas=
40 | 1899-12-30 00:00:00.000.231,=D:\MyCode\AMQP-Delphi\Unit1.pas
41 | 1899-12-30 00:00:00.000.620,=D:\MyCode\AMQP-Delphi\Unit1.pas
42 | 1899-12-30 00:00:00.000.004,=D:\MyCode\AMQP-Delphi\Unit1.pas
43 | 1899-12-30 00:00:00.000.253,=D:\MyCode\rabbitmq-Delphi\amqp.api.pas
44 | 1899-12-30 00:00:00.000.642,D:\MyCode\AMQP-Delphi\AMQP.BasicAckFrame.pas=
45 | 1899-12-30 00:00:00.000.567,D:\MyCode\AMQP-Delphi\amqp.mem.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
46 | 1899-12-30 00:00:00.000.322,=D:\MyCode\rabbitmq-Delphi\amqp.consumer.pas
47 | 1899-12-30 00:00:00.000.666,D:\MyCode\AMQP-Delphi\amqp.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
48 | 1899-12-30 00:00:00.000.485,D:\MyCode\AMQP-Delphi\amqp.framing.pas=D:\MyCode\AMQP-Delphi\framing.pas
49 | 1899-12-30 00:00:00.000.926,D:\MyCode\AMQP-Delphi\AMQP.ConnectionImpl.pas=
50 | 1899-12-30 00:00:00.000.566,D:\MyCode\AMQP-Delphi\amqp.pas=
51 | 1899-12-30 00:00:00.000.997,D:\MyCode\AMQP-Delphi\amqp.socket.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
52 | 1899-12-30 00:00:00.000.119,D:\MyCode\AMQP-Delphi\amqp.tcp_socket.pas=D:\MyCode\AMQP-Delphi\amqp_tcp_socket.pas
53 | 1899-12-30 00:00:00.000.288,=D:\MyCode\rabbitmq-Delphi\amqp.connection.pas
54 | 1899-12-30 00:00:00.000.617,D:\MyCode\AMQP-Delphi\amqp_tcp_socket.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
55 | 1899-12-30 00:00:00.000.506,D:\MyCode\AMQP-Delphi\AMQP.Login.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
56 | 1899-12-30 00:00:00.000.711,D:\MyCode\AMQP-Delphi\AMQP.Login.pas=
57 | 1899-12-30 00:00:00.000.398,=D:\MyCode\rabbitmq-Delphi\amqp.mem.pas
58 | 1899-12-30 00:00:00.000.984,D:\MyCode\AMQP-Delphi\AMQP.ExtFrame.pas=
59 | 1899-12-30 00:00:00.000.602,=D:\MyCode\rabbitmq-Delphi\amqp.time.pas
60 | 1899-12-30 00:00:00.000.706,D:\MyCode\AMQP-Delphi\amqp.connection.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
61 | 1899-12-30 00:00:00.000.312,D:\MyCode\AMQP-Delphi\amqp.table.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
62 | 1899-12-30 00:00:00.000.980,=D:\MyCode\Unit1.pas
63 | 1899-12-30 00:00:00.000.058,=D:\MyCode\Unit1.pas
64 | 1899-12-30 00:00:00.000.261,=D:\MyCode\Unit1.pas
65 | 1899-12-30 00:00:00.000.090,=D:\MyCode\Unit1.pas
66 | 1899-12-30 00:00:00.000.569,=D:\MyCode\Unit1.pas
67 | 1899-12-30 00:00:00.000.805,D:\MyCode\AMQP-Delphi\AMQP.OutBuffer.pas=
68 | 1899-12-30 00:00:00.000.569,=D:\MyCode\rabbitmq-Delphi\amqp.tcp_socket.pas
69 | 1899-12-30 00:00:00.000.090,D:\MyCode\Project1.dproj=D:\MyCode\AMQP-Delphi\AMQPTest.dproj
70 | 1899-12-30 00:00:00.000.607,D:\MyCode\AMQP-Delphi\amqp.time.pas=D:\MyCode\AMQP-Delphi\Unit1.pas
71 | 1899-12-30 00:00:00.000.448,=D:\MyCode\rabbitmq-Delphi\amqp.privt.pas
72 | 1899-12-30 00:00:00.000.503,=D:\MyCode\rabbitmq-Delphi\amqp.socket.pas
73 | 1899-12-30 00:00:00.000.536,=D:\MyCode\rabbitmq-Delphi\amqp.table.pas
74 | 1899-12-30 00:00:00.000.576,D:\MyCode\AMQP-Delphi\TestUnbind.dproj=D:\MyCode\AMQP-Delphi\AMQPTest.dproj
75 | 1899-12-30 00:00:00.000.365,=D:\MyCode\rabbitmq-Delphi\amqp.framing.pas
76 | 1899-12-30 00:00:00.000.680,=D:\MyCode\rabbitmq-Delphi\amqp_tcp_socket.pas
77 | 1899-12-30 00:00:00.000.500,=D:\MyCode\AMQP-Delphi\AMQP.Types.pas
78 | 1899-12-30 00:00:00.000.844,D:\MyCode\AMQP-Delphi\AMQP.Types.pas=
79 | 1899-12-30 00:00:00.000.862,D:\MyCode\AMQP-Delphi\AMQP.BasicFrame.pas=
80 | 1899-12-30 00:00:00.000.623,D:\MyCode\AMQP-Delphi\framing.pas=D:\MyCode\AMQP-Delphi\amqp.privt.pas
81 |
82 |
83 |
--------------------------------------------------------------------------------
/TestUnbind.identcache:
--------------------------------------------------------------------------------
1 |
-D:\MyCode\rabbitmq-Delphi\demo\TestUnbind.dpr (D:\MyCode\rabbitmq-Delphi\amqp.privt.pas +D:\MyCode\rabbitmq-Delphi\amqp.consumer.pas &D:\MyCode\rabbitmq-Delphi\amqp.mem.pas -D:\MyCode\rabbitmq-Delphi\amqp.connection.pas *D:\MyCode\rabbitmq-Delphi\amqp.framing.pas 'D:\MyCode\rabbitmq-Delphi\amqp.time.pas -D:\MyCode\rabbitmq-Delphi\amqp_tcp_socket.pas -D:\MyCode\rabbitmq-Delphi\amqp.tcp_socket.pas (D:\MyCode\rabbitmq-Delphi\amqp.table.pas &D:\MyCode\rabbitmq-Delphi\amqp.api.pas )D:\MyCode\rabbitmq-Delphi\amqp.socket.pas (D:\MyCode\rabbitmq-Delphi\AMQP.Types.pas
--------------------------------------------------------------------------------
/amqp.api.pas:
--------------------------------------------------------------------------------
1 | unit amqp.api;
2 |
3 | {$IFDEF FPC}
4 | {$MODE Delphi}
5 | {$ENDIF}
6 |
7 | interface
8 | uses {$IFDEF FPC}SysUtils,{$Else} System.SysUtils, {$ENDIF} amqp.framing, AMQP.Types;
9 |
10 | function amqp_basic_publish( state : Pamqp_connection_state; channel : amqp_channel_t;
11 | exchange, routing_key : Tamqp_bytes;
12 | mandatory, immediate : amqp_boolean_t;
13 | properties: Pamqp_basic_properties;
14 | body : Tamqp_bytes):integer;
15 | function amqp_channel_close( state : Pamqp_connection_state; channel : amqp_channel_t; code : integer): Tamqp_rpc_reply;
16 | function amqp_connection_close( state : Pamqp_connection_state; code : integer):Tamqp_rpc_reply;
17 |
18 | implementation
19 |
20 | uses amqp.socket, amqp.connection, amqp.privt, amqp.time;
21 |
22 |
23 |
24 | function amqp_connection_close( state : Pamqp_connection_state; code : integer):Tamqp_rpc_reply;
25 | var
26 | codestr : array[0..12] of AMQPChar;
27 | replies : Tamqp_methods;
28 | req : Tamqp_channel_close;
29 | s: Ansistring;
30 | i, Size: Integer;
31 | begin
32 | SetLength(replies,2);
33 | replies[0] := AMQP_CONNECTION_CLOSE_OK_METHOD;
34 | replies[1] := 0;
35 |
36 | if (code < 0) or (code > UINT16_MAX) then
37 | Exit(amqp_rpc_reply_error(AMQP_STATUS_INVALID_PARAMETER));
38 |
39 | req.reply_code := uint16_t(code);
40 | req.reply_text.bytes := @codestr;
41 | s := Format('%d', [code]);
42 | size:=Length(S);
43 | For i:=1 To size Do
44 | Begin
45 | codestr[i-1]:=S[i];
46 | If (i = size) Then Break;
47 | End;
48 | req.reply_text.len := size;
49 | req.class_id := 0;
50 | req.method_id := 0;
51 | Result := amqp_simple_rpc(state, 0, AMQP_CONNECTION_CLOSE_METHOD, replies, @req);
52 | SetLength(replies,0);
53 | end;
54 |
55 | function amqp_channel_close( state : Pamqp_connection_state; channel : amqp_channel_t; code : integer): Tamqp_rpc_reply;
56 | var
57 | codestr : array[0..12] of AMQPChar;
58 | replies : Tamqp_methods;
59 | req : Tamqp_channel_close;
60 | s: Ansistring;
61 | i, Size: Integer;
62 | begin
63 | SetLength(replies,2);
64 | replies[0] := AMQP_CHANNEL_CLOSE_OK_METHOD;
65 | replies[1] := 0;
66 |
67 | if (code < 0) or (code > UINT16_MAX) then
68 | Exit(amqp_rpc_reply_error(AMQP_STATUS_INVALID_PARAMETER));
69 |
70 | req.reply_code := uint16_t(code);
71 | req.reply_text.bytes := @codestr;
72 | s := Format('%d', [code]);
73 | size:=Length(S);
74 | For i:=1 To size Do
75 | Begin
76 | codestr[i-1]:=S[i];
77 | If (i = size) Then Break;
78 | End;
79 | req.reply_text.len := size;
80 | req.class_id := 0;
81 | req.method_id := 0;
82 | Result := amqp_simple_rpc(state, channel, AMQP_CHANNEL_CLOSE_METHOD, replies, @req);
83 | SetLength(replies,0);
84 | end;
85 |
86 | function amqp_basic_publish( state : Pamqp_connection_state; channel : amqp_channel_t;
87 | exchange, routing_key : Tamqp_bytes;
88 | mandatory, immediate : amqp_boolean_t;
89 | properties: Pamqp_basic_properties;
90 | body : Tamqp_bytes):integer;
91 | var
92 | f : Tamqp_frame;
93 | body_offset,
94 | usable_body_payload_size : size_t;
95 | res,
96 | flagz : integer;
97 | m : Tamqp_basic_publish;
98 | default_properties : Tamqp_basic_properties;
99 | remaining : size_t;
100 | begin
101 | usable_body_payload_size := state.frame_max - (HEADER_SIZE + FOOTER_SIZE);
102 | m.exchange := exchange;
103 | m.routing_key := routing_key;
104 | m.mandatory := mandatory;
105 | m.immediate := immediate;
106 | m.ticket := 0;
107 | { TODO(alanxz): this heartbeat check is happening in the wrong place, it
108 | * should really be done in amqp_try_send/writev }
109 | res := amqp_time_has_past(state.next_recv_heartbeat);
110 | if Int(AMQP_STATUS_TIMER_FAILURE) = res then
111 | Exit(res)
112 |
113 | else
114 | if (Int(AMQP_STATUS_TIMEOUT) = res) then
115 | begin
116 | res := amqp_try_recv(state);
117 | if Int(AMQP_STATUS_TIMEOUT) = res then
118 | Exit(Int(AMQP_STATUS_HEARTBEAT_TIMEOUT))
119 | else if int(AMQP_STATUS_OK) <> res then
120 | Exit(res);
121 |
122 | end;
123 | res := amqp_send_method_inner(state, channel, AMQP_BASIC_PUBLISH_METHOD, @m,
124 | Int(AMQP_SF_MORE), Tamqp_time.infinite());
125 | if res < 0 then
126 | Exit(res);
127 |
128 | if properties = nil then
129 | begin
130 | memset(default_properties, 0, sizeof(default_properties));
131 | properties := @default_properties;
132 | end;
133 | f.frame_type := AMQP_FRAME_HEADER;
134 | f.channel := channel;
135 | f.payload.properties.class_id := AMQP_BASIC_CLASS;
136 | f.payload.properties.body_size := body.len;
137 | f.payload.properties.decoded := Pointer(properties);
138 | if body.len > 0 then
139 | flagz := Int(AMQP_SF_MORE)
140 | else
141 | flagz := Int(AMQP_SF_NONE);
142 |
143 | res := amqp_send_frame_inner(state, f, flagz, Tamqp_time.infinite);
144 | if res < 0 then
145 | Exit(res);
146 |
147 | body_offset := 0;
148 | while body_offset < body.len do
149 | begin
150 | remaining := body.len - body_offset;
151 | if remaining = 0 then
152 | break;
153 |
154 | f.frame_type := AMQP_FRAME_BODY;
155 | f.channel := channel;
156 | f.payload.body_fragment.bytes := amqp_offset(body.bytes, body_offset);
157 | if remaining >= usable_body_payload_size then
158 | begin
159 | f.payload.body_fragment.len := usable_body_payload_size;
160 | flagz := Int(AMQP_SF_MORE);
161 | end
162 | else
163 | begin
164 | f.payload.body_fragment.len := remaining;
165 | flagz := Int(AMQP_SF_NONE);
166 | end;
167 | body_offset := body_offset + f.payload.body_fragment.len;
168 | res := amqp_send_frame_inner(state, f, flagz, Tamqp_time.infinite());
169 | if res < 0 then
170 | Exit(res);
171 |
172 | end;
173 | Result := Int(AMQP_STATUS_OK);
174 | end;
175 |
176 | initialization
177 |
178 | end.
179 |
--------------------------------------------------------------------------------
/amqp.connection.pas:
--------------------------------------------------------------------------------
1 | unit amqp.connection;
2 |
3 | {$IFDEF FPC}
4 | {$MODE Delphi}
5 | {$ENDIF}
6 |
7 | {$INCLUDE config.inc}
8 | interface
9 | uses {$IFDEF FPC}SysUtils,{$Else} System.SysUtils, {$ENDIF}amqp.socket, AMQP.Types,
10 | amqp.framing, amqp.time, amqp.table,
11 | amqp.privt, amqp.mem, amqp.tcp_socket;
12 |
13 | function amqp_new_connection:Pamqp_connection_state;
14 | procedure amqp_set_sockfd( state : Pamqp_connection_state; sockfd : integer);
15 |
16 | function amqp_tune_connection( state : Pamqp_connection_state; channel_max, frame_max, heartbeat : integer):integer;
17 | function amqp_destroy_connection( state : Pamqp_connection_state):integer;
18 | procedure return_to_idle( state : Pamqp_connection_state);
19 | function consume_data(state : Pamqp_connection_state; out received_data : Tamqp_bytes):size_t;
20 |
21 | function amqp_release_buffers_ok( state : Pamqp_connection_state):amqp_boolean_t;
22 | procedure amqp_release_buffers( state : Pamqp_connection_state);
23 | procedure amqp_maybe_release_buffers( state : Pamqp_connection_state);
24 | procedure amqp_maybe_release_buffers_on_channel( state : Pamqp_connection_state; channel : amqp_channel_t);
25 | function amqp_frame_to_bytes(const Aframe : Tamqp_frame; Abuffer : Tamqp_bytes; out Aencoded : Tamqp_bytes):integer;
26 |
27 | function amqp_send_frame(Astate : Pamqp_connection_state;const Aframe : Pamqp_frame):integer;
28 | function amqp_send_frame_inner(Astate : Pamqp_connection_state;const Aframe : Tamqp_frame; Aflags : integer; Adeadline : Tamqp_time):integer;
29 |
30 | function amqp_handle_input(Astate : Pamqp_connection_state;
31 | var Areceived_data : Tamqp_bytes;
32 | out Adecoded_frame : Tamqp_frame):integer;
33 | //function amqp_heartbeat_send(state: Pamqp_connection_state): int;
34 | function amqp_heartbeat_recv(state: Pamqp_connection_state): int;
35 |
36 | const
37 | AMQP_INITIAL_FRAME_POOL_PAGE_SIZE = 65536;
38 | AMQP_INITIAL_INBOUND_SOCK_BUFFER_SIZE = 131072;
39 | AMQP_DEFAULT_LOGIN_TIMEOUT_SEC = 12;
40 |
41 | implementation
42 |
43 | function amqp_send_frame_inner(Astate : Pamqp_connection_state;const Aframe : Tamqp_frame;
44 | Aflags : integer; Adeadline : Tamqp_time):integer;
45 | var
46 | Lres, count, Level : integer;
47 | Lsent : ssize_t;
48 | Lencoded : Tamqp_bytes;
49 | Lnext_timeout : Tamqp_time;
50 | label start_send ;
51 | begin
52 | { TODO: if the AMQP_SF_MORE socket optimization can be shown to work
53 | * correctly, then this could be un-done so that body-frames are sent as 3
54 | * send calls, getting rid of the copy of the body content, some testing
55 | * would need to be done to see if this would actually a win for performance.
56 | * }
57 | Inc(gLevel);
58 | Level := gLevel;
59 | count := 0;
60 | {$IFDEF _DEBUG_}
61 | DebugOut(Level, 'step into amqp.connection:: amqp_frame_to_bytes==>');
62 | {$ENDIF}
63 |
64 | Lres := amqp_frame_to_bytes(Aframe, Astate.outbound_buffer, Lencoded);
65 | {$IFDEF _DEBUG_}
66 | DebugOut(Level, 'step over amqp.connection::amqp_frame_to_bytes, res=' + IntToStr(Lres));
67 | {$ENDIF}
68 | if Int(AMQP_STATUS_OK) <> Lres then
69 | Exit(Lres);
70 |
71 | start_send:
72 | Inc(count);
73 | Lnext_timeout := amqp_time_first(Adeadline, Astate.next_recv_heartbeat);
74 | {$IFDEF _DEBUG_}
75 | DebugOut(Level, 'step into amqp.socket:: amqp_try_send==>, start_send:' + IntToStr(count));
76 | {$ENDIF}
77 | Lsent := amqp_try_send(Astate, Lencoded.bytes, Lencoded.len, Lnext_timeout, Aflags);
78 | {$IFDEF _DEBUG_}
79 | DebugOut(Level, 'step over amqp.socket:: amqp_try_send, res=' + IntToStr(Lsent));
80 | {$ENDIF}
81 | if 0 > Lsent then
82 | Exit(int(Lsent));
83 |
84 | { A partial send has occurred, because of a heartbeat timeout (so try recv
85 | * something) or common timeout (so return AMQP_STATUS_TIMEOUT) }
86 | if ssize_t(Lencoded.len) <> Lsent then
87 | begin
88 | if Lnext_timeout = Adeadline then
89 | { timeout of method was received, so return from method}
90 | Exit(Integer(AMQP_STATUS_TIMEOUT));
91 |
92 | Lres := amqp_try_recv(Astate);
93 | if Int(AMQP_STATUS_TIMEOUT) = Lres then
94 | Exit(Integer(AMQP_STATUS_HEARTBEAT_TIMEOUT))
95 | else
96 | if (Int(AMQP_STATUS_OK) <> Lres) then
97 | Exit(Lres);
98 |
99 | Inc(Lencoded.bytes ,Lsent);
100 | Lencoded.len := Lencoded.len - Lsent;
101 | goto start_send;
102 | end;
103 | Lres := amqp_time_s_from_now(Astate.next_send_heartbeat,
104 | Astate.heartbeat);
105 | Result := Lres;
106 | end;
107 |
108 |
109 | function amqp_heartbeat_recv( state: Pamqp_connection_state): int;
110 | begin
111 | Result := 2 * state.heartbeat;
112 | end;
113 |
114 |
115 | function amqp_handle_input(Astate : Pamqp_connection_state;
116 | var Areceived_data : Tamqp_bytes;
117 | out Adecoded_frame : Tamqp_frame):integer;
118 | var
119 | bytes_consumed : size_t;
120 | raw_frame : PAMQPChar;
121 | channel : amqp_channel_t;
122 | channel_pool : Pamqp_pool;
123 | frame_size : uint32;
124 | encoded : Tamqp_bytes;
125 | res,Level : integer;
126 |
127 | begin
128 | { Returning frame_type of zero indicates either insufficient input,
129 | or a complete, ignored frame was read. }
130 | Inc(gLevel);
131 | Level := gLevel;
132 | Adecoded_frame.frame_type := 0;
133 | if Areceived_data.len = 0 then
134 | Exit(Int(AMQP_STATUS_OK));
135 |
136 | if Astate.state = CONNECTION_STATE_IDLE then
137 | Astate.state := CONNECTION_STATE_HEADER;
138 | {$IFDEF _DEBUG_}
139 | DebugOut(Level, 'step into amqp.connection:: consume_data==>');
140 | {$ENDIF}
141 | bytes_consumed := consume_data(Astate, Areceived_data);
142 | {$IFDEF _DEBUG_}
143 | DebugOut(Level, 'step over amqp.connection:: consume_data, bytes_consumed=' + IntToStr(bytes_consumed));
144 | {$ENDIF}
145 | { do we have target_size data yet? if not, return with the
146 | expectation that more will arrive }
147 | if Astate.inbound_offset < Astate.target_size then
148 | Exit(int(bytes_consumed));
149 |
150 | raw_frame := (Astate.inbound_buffer.bytes);
151 | //var p := PAnsiChar( state.inbound_buffer.bytes);
152 | case Astate.state of
153 | CONNECTION_STATE_INITIAL,
154 | CONNECTION_STATE_HEADER,
155 | CONNECTION_STATE_BODY:
156 | begin
157 | { check for a protocol header from the server }
158 | if CompareMem(raw_frame, PAnsiChar('AMQP'), 4) then
159 | //if PAnsiChar(raw_frame) = 'AMQP' then
160 | begin
161 | Adecoded_frame.frame_type := Ord(AMQP_PSEUDOFRAME_PROTOCOL_HEADER);
162 | Adecoded_frame.channel := 0;
163 | Adecoded_frame.payload.protocol_header.transport_high := amqp_d8(amqp_offset(raw_frame, 4));
164 | Adecoded_frame.payload.protocol_header.transport_low := amqp_d8(amqp_offset(raw_frame, 5));
165 | Adecoded_frame.payload.protocol_header.protocol_version_major := amqp_d8(amqp_offset(raw_frame, 6));
166 | Adecoded_frame.payload.protocol_header.protocol_version_minor := amqp_d8(amqp_offset(raw_frame, 7));
167 | return_to_idle(Astate);
168 | Exit(int(bytes_consumed));
169 | end;
170 |
171 | //CONNECTION_STATE_HEADER:
172 |
173 | channel := amqp_d16(amqp_offset(raw_frame, 1));
174 | { frame length is 3 bytes in }
175 | frame_size := amqp_d32(amqp_offset(raw_frame, 3));
176 | { To prevent the target_size calculation below from overflowing, check
177 | * that the stated frame_size is smaller than a signed 32-bit. Given
178 | * the library only allows configuring frame_max as an int32_t, and
179 | * frame_size is uint32_t, the math below is safe from overflow. }
180 | if frame_size >= INT32_MAX then
181 | Exit(Int(AMQP_STATUS_BAD_AMQP_DATA));
182 |
183 | Astate.target_size := frame_size + HEADER_SIZE + FOOTER_SIZE;
184 | if size_t(Astate.frame_max) < Astate.target_size then
185 | Exit(Int(AMQP_STATUS_BAD_AMQP_DATA));
186 |
187 | {$IFDEF _DEBUG_}
188 | DebugOut(Level, 'step into amqp.mem:: amqp_get_or_create_channel_pool==>');
189 | {$ENDIF}
190 | channel_pool := Astate.get_or_create_channel_pool(channel);
191 | {$IFDEF _DEBUG_}
192 | DebugOut(Level, 'step over amqp.mem:: amqp_get_or_create_channel_pool.');
193 | {$ENDIF}
194 | if nil = channel_pool then
195 | Exit(Int(AMQP_STATUS_NO_MEMORY));
196 |
197 | channel_pool.alloc_bytes( Astate.target_size, Astate.inbound_buffer);
198 | if nil = Astate.inbound_buffer.bytes then
199 | Exit(Int(AMQP_STATUS_NO_MEMORY));
200 |
201 | memcpy(Astate.inbound_buffer.bytes, @Astate.header_buffer, HEADER_SIZE);
202 | raw_frame := Astate.inbound_buffer.bytes;
203 | Astate.state := CONNECTION_STATE_BODY;
204 | bytes_consumed := bytes_consumed + consume_data(Astate, Areceived_data);
205 | { do we have target_size data yet? if not, return with the
206 | expectation that more will arrive }
207 | if Astate.inbound_offset < Astate.target_size then
208 | Exit(int(bytes_consumed));
209 |
210 |
211 | { fall through to process body }
212 | //CONNECTION_STATE_BODY:
213 |
214 | { Check frame end marker (footer) }
215 | if amqp_d8(amqp_offset(raw_frame, Astate.target_size - 1 )) <> AMQP_FRAME_END then
216 | Exit(Int(AMQP_STATUS_BAD_AMQP_DATA));
217 |
218 | Adecoded_frame.frame_type := amqp_d8(amqp_offset(raw_frame, 0));
219 | Adecoded_frame.channel := amqp_d16(amqp_offset(raw_frame, 1));
220 | {$IFDEF _DEBUG_}
221 | DebugOut(Level, 'step into amqp.mem:: amqp_get_or_create_channel_pool==>');
222 | {$ENDIF}
223 | channel_pool := Astate.get_or_create_channel_pool(Adecoded_frame.channel);
224 | {$IFDEF _DEBUG_}
225 | DebugOut(Level, 'step over amqp.mem:: amqp_get_or_create_channel_pool.');
226 | {$ENDIF}
227 | if nil = channel_pool then
228 | Exit(Int(AMQP_STATUS_NO_MEMORY));
229 |
230 | case Adecoded_frame.frame_type of
231 | AMQP_FRAME_METHOD:
232 | begin
233 | Adecoded_frame.payload.method.id := amqp_d32(amqp_offset(raw_frame, HEADER_SIZE));
234 | encoded.bytes := amqp_offset(raw_frame, HEADER_SIZE + 4);
235 | encoded.len := Astate.target_size - HEADER_SIZE - 4 - FOOTER_SIZE;
236 | {$IFDEF _DEBUG_}
237 | DebugOut(Level, 'AMQP_FRAME_METHOD step into amqp.framming:: amqp_decode_method==>');
238 | {$ENDIF}
239 | res := amqp_decode_method(Adecoded_frame.payload.method.id,
240 | channel_pool, encoded,
241 | Adecoded_frame.payload.method.decoded);
242 | {$IFDEF _DEBUG_}
243 | DebugOut(Level, 'AMQP_FRAME_METHOD step over amqp.framming:: amqp_decode_method, res=' + IntToStr(res));
244 | {$ENDIF}
245 | if res < 0 then
246 | Exit(res);
247 | end;
248 |
249 | AMQP_FRAME_HEADER:
250 | begin
251 | Adecoded_frame.payload.properties.class_id := amqp_d16(amqp_offset(raw_frame, HEADER_SIZE));
252 | { unused 2-byte weight field goes here }
253 | Adecoded_frame.payload.properties.body_size := amqp_d64(amqp_offset(raw_frame, HEADER_SIZE + 4));
254 | encoded.bytes := amqp_offset(raw_frame, HEADER_SIZE + 12);
255 | encoded.len := Astate.target_size - HEADER_SIZE - 12 - FOOTER_SIZE;
256 | Adecoded_frame.payload.properties.raw := encoded;
257 | {$IFDEF _DEBUG_}
258 | DebugOut(Level, 'AMQP_FRAME_HEADER step into amqp.framming:: amqp_decode_properties==>');
259 | {$ENDIF}
260 | res := amqp_decode_properties(Adecoded_frame.payload.properties.class_id,
261 | channel_pool, encoded,
262 | @Adecoded_frame.payload.properties.decoded);
263 | {$IFDEF _DEBUG_}
264 | DebugOut(Level, 'AMQP_FRAME_HEADER step over amqp.framming:: amqp_decode_properties, res=' + IntToStr(res));
265 | {$ENDIF}
266 | if res < 0 then
267 | Exit(res);
268 | end;
269 |
270 | AMQP_FRAME_BODY:
271 | begin
272 | Adecoded_frame.payload.body_fragment.len := Astate.target_size - HEADER_SIZE - FOOTER_SIZE;
273 | Adecoded_frame.payload.body_fragment.bytes := amqp_offset(raw_frame, HEADER_SIZE);
274 | end;
275 | AMQP_FRAME_HEARTBEAT:
276 | begin
277 | //
278 | end;
279 | else
280 | begin
281 | { Ignore the frame }
282 | Adecoded_frame.frame_type := 0;
283 | end;
284 | end;
285 | return_to_idle(Astate);
286 | Exit(int(bytes_consumed)) ;
287 | end;
288 | else
289 | raise Exception.Create('Internal error: invalid amqp_connection_state_t.state '
290 | + IntToStr(Int(Astate.state)));
291 | end;
292 | end;
293 |
294 | function amqp_new_connection:Pamqp_connection_state;
295 | var
296 | res : integer;
297 | state : Pamqp_connection_state;
298 | label out_nomem;
299 |
300 | begin
301 | state := Pamqp_connection_state(AllocMem(1* sizeof(Tamqp_connection_state)));
302 | if state = nil then
303 | Exit(nil);
304 |
305 | res := amqp_tune_connection(state, 0, AMQP_INITIAL_FRAME_POOL_PAGE_SIZE, 0);
306 | if 0 <> res then
307 | goto out_nomem;
308 |
309 | state.inbound_buffer.bytes := @state.header_buffer;
310 | state.inbound_buffer.len := sizeof(state.header_buffer);
311 | state.state := CONNECTION_STATE_INITIAL;
312 | { the server protocol version response is 8 bytes, which conveniently
313 | is also the minimum frame size }
314 | state.target_size := 8;
315 | state.sock_inbound_buffer.len := AMQP_INITIAL_INBOUND_SOCK_BUFFER_SIZE;
316 | state.sock_inbound_buffer.bytes := malloc(AMQP_INITIAL_INBOUND_SOCK_BUFFER_SIZE);
317 | if state.sock_inbound_buffer.bytes = nil then
318 | goto out_nomem;
319 |
320 | //init_amqp_pool(@state.properties_pool, 512);
321 | state.properties_pool.Create(512);
322 | { Use address of the internal_handshake_timeout object by default. }
323 | state.internal_handshake_timeout.tv_sec := AMQP_DEFAULT_LOGIN_TIMEOUT_SEC;
324 | state.internal_handshake_timeout.tv_usec := 0;
325 | state.handshake_timeout := @state.internal_handshake_timeout;
326 | Exit(state);
327 | out_nomem:
328 | free(state.sock_inbound_buffer.bytes);
329 | free(state);
330 | Result := nil;
331 | end;
332 |
333 |
334 | procedure amqp_set_sockfd( state : Pamqp_connection_state; sockfd : integer);
335 | var
336 | socket : Pamqp_socket;
337 | begin
338 | socket := amqp_tcp_socket_new(state);
339 | if not Assigned(socket) then
340 | //amqp_abort('%s', strerror(errno));
341 | raise Exception.Create('CRAETE new socket error!!!');
342 |
343 | amqp_tcp_socket_set_sockfd(socket, sockfd);
344 | end;
345 |
346 |
347 | procedure ENFORCE_STATE( statevec : Pamqp_connection_state; statenum : Tamqp_connection_state_enum);
348 | var
349 | _check_state : Pamqp_connection_state;
350 | _wanted_state : Tamqp_connection_state_enum;
351 | s: string;
352 | begin
353 | _check_state := (statevec);
354 | _wanted_state := (statenum);
355 | if _check_state.state <> _wanted_state then
356 | begin
357 | s := Format('Programming error: invalid AMQP connection state: expected %d, '+
358 | 'got %d',
359 | [Int(_wanted_state), Int(_check_state.state)]);
360 | raise Exception.Create(s);
361 | end;
362 | end;
363 |
364 |
365 | function amqp_tune_connection( state : Pamqp_connection_state; channel_max, frame_max, heartbeat : integer):integer;
366 | var
367 | newbuf : Pointer;
368 | res : integer;
369 | begin
370 | ENFORCE_STATE(state, CONNECTION_STATE_IDLE);
371 | state.channel_max := channel_max;
372 | state.frame_max := frame_max;
373 | state.heart_beat := heartbeat;
374 | if 0 > state.heart_beat then
375 | state.heart_beat := 0;
376 |
377 | res := amqp_time_s_from_now(state.next_send_heartbeat, state.heartbeat);
378 | if Int(AMQP_STATUS_OK) <> res then
379 | Exit(res);
380 |
381 | res := amqp_time_s_from_now(state.next_recv_heartbeat,
382 | amqp_heartbeat_recv(state));
383 | if Int(AMQP_STATUS_OK) <> res then
384 | Exit(res);
385 |
386 | state.outbound_buffer.len := frame_max;
387 | //newbuf := realloc(state.outbound_buffer.bytes, frame_max);
388 | reallocMem(state.outbound_buffer.bytes, frame_max);
389 | newbuf := state.outbound_buffer.bytes;
390 | if newbuf = nil then
391 | Exit(Int(AMQP_STATUS_NO_MEMORY));
392 |
393 | //state.outbound_buffer.bytes := newbuf;
394 | Result := Int(AMQP_STATUS_OK);
395 | end;
396 |
397 | function amqp_destroy_connection( state : Pamqp_connection_state):integer;
398 | var
399 | status,
400 | i : integer;
401 | entry,
402 | todelete : Pamqp_pool_table_entry;
403 | begin
404 | status := Int(AMQP_STATUS_OK);
405 | if Assigned(state) then
406 | begin //++i
407 | for i := 0 to POOL_TABLE_SIZE -1 do
408 | begin
409 | //Inc(i);
410 | entry := state.pool_table[i];
411 | while nil <> entry do
412 | begin
413 | todelete := entry;
414 | entry.pool.empty;
415 | entry := entry.next;
416 | free(todelete);
417 | end;
418 | end;
419 | free(state.outbound_buffer.bytes);
420 |
421 | free(state.sock_inbound_buffer.bytes);
422 | state.Fsocket.delete;
423 | state.properties_pool.empty;
424 | free(state);
425 | end;
426 | Result := status;
427 | end;
428 |
429 |
430 | procedure return_to_idle( state : Pamqp_connection_state);
431 | begin
432 | state.inbound_buffer.len := sizeof(state.header_buffer);
433 | state.inbound_buffer.bytes := @state.header_buffer;
434 | state.inbound_offset := 0;
435 | state.target_size := HEADER_SIZE;
436 | state.state := CONNECTION_STATE_IDLE;
437 | end;
438 |
439 |
440 | function consume_data(state : Pamqp_connection_state; out received_data : Tamqp_bytes):size_t;
441 | var
442 | bytes_consumed : size_t;
443 | begin
444 | { how much data is available and will fit? }
445 | bytes_consumed := state.target_size - state.inbound_offset;
446 | if received_data.len < bytes_consumed then
447 | bytes_consumed := received_data.len;
448 |
449 | //此句执行后导致state.Fsock不可访问
450 | memcpy(amqp_offset(state.inbound_buffer.bytes, state.inbound_offset), received_data.bytes, bytes_consumed);
451 | state.inbound_offset := state.inbound_offset + bytes_consumed;
452 | //received_data.bytes :=
453 | Inc(received_data.bytes, bytes_consumed);
454 | received_data.len := received_data.len - bytes_consumed;
455 | Result := bytes_consumed;
456 | end;
457 |
458 |
459 | function amqp_release_buffers_ok( state : Pamqp_connection_state):amqp_boolean_t;
460 | begin
461 | if (state.state = CONNECTION_STATE_IDLE) then
462 | Result := 1
463 | else
464 | Result := 0;
465 | end;
466 |
467 |
468 | procedure amqp_release_buffers( state : Pamqp_connection_state);
469 | var
470 | i : integer;
471 | Lentry : Pamqp_pool_table_entry;
472 | begin
473 | ENFORCE_STATE(state, CONNECTION_STATE_IDLE);
474 | for i := 0 to POOL_TABLE_SIZE-1 do
475 | begin
476 | Lentry := state.pool_table[i];
477 | While nil <> Lentry do
478 | begin
479 | amqp_maybe_release_buffers_on_channel(state, Lentry.channel);
480 | Lentry := Lentry.next;
481 | end;
482 | end;
483 | end;
484 |
485 | procedure amqp_maybe_release_buffers( state : Pamqp_connection_state);
486 | begin
487 | if amqp_release_buffers_ok(state) > 0 then
488 | amqp_release_buffers(state);
489 |
490 | end;
491 |
492 |
493 | procedure amqp_maybe_release_buffers_on_channel( state : Pamqp_connection_state; channel : amqp_channel_t);
494 | var
495 | queued_link : Pamqp_link;
496 | pool : Pamqp_pool;
497 | frame : Pamqp_frame;
498 | begin
499 | if CONNECTION_STATE_IDLE <> state.state then
500 | exit;
501 |
502 | queued_link := state.first_queued_frame;
503 | while nil <> queued_link do
504 | begin
505 | frame := queued_link.data;
506 | if channel = frame.channel then
507 | Exit;
508 |
509 | queued_link := queued_link.next;
510 | end;
511 |
512 | pool := state.get_channel_pool(channel);
513 | if pool <> nil then
514 | pool.recycle;
515 |
516 | end;
517 |
518 |
519 | function amqp_frame_to_bytes(const Aframe : Tamqp_frame; Abuffer : Tamqp_bytes;
520 | out Aencoded : Tamqp_bytes):integer;
521 | var
522 | Lout_frame : PAMQPChar;
523 | Lout_frame_len : size_t;
524 | Lres ,Level : integer;
525 | Lproperties_encoded,
526 | Lmethod_encoded : Tamqp_bytes;
527 | Lbody : Tamqp_bytes;
528 |
529 | begin
530 | Inc(gLevel);
531 | Level := gLevel;
532 | Lout_frame := Abuffer.bytes;
533 | amqp_e8(Aframe.frame_type, amqp_offset(Lout_frame, 0));
534 | amqp_e16(Aframe.channel, amqp_offset(Lout_frame, 1));
535 | case Aframe.frame_type of
536 | AMQP_FRAME_BODY:
537 | begin
538 | {$IFDEF _DEBUG_}
539 | DebugOut(Level, ' frame_type = AMQP_FRAME_BODY');
540 | {$ENDIF}
541 |
542 | Lbody := Aframe.payload.body_fragment;
543 | memcpy(amqp_offset(Lout_frame, HEADER_SIZE), Lbody.bytes, Lbody.len);
544 | Lout_frame_len := Lbody.len;
545 |
546 | end;
547 |
548 | AMQP_FRAME_METHOD:
549 | begin
550 | {$IFDEF _DEBUG_}
551 | DebugOut(Level, ' frame_type = AMQP_FRAME_METHOD');
552 | {$ENDIF}
553 | amqp_e32(Aframe.payload.method.id, amqp_offset(Lout_frame, HEADER_SIZE));
554 | Lmethod_encoded.bytes := amqp_offset(Lout_frame, HEADER_SIZE + 4);
555 | Lmethod_encoded.len := Abuffer.len - HEADER_SIZE - 4 - FOOTER_SIZE;
556 | Lres := amqp_encode_method(Aframe.payload.method.id,
557 | Aframe.payload.method.decoded, Lmethod_encoded);
558 | if Lres < 0 then
559 | Exit(Lres);
560 |
561 | Lout_frame_len := Lres + 4;
562 |
563 | end;
564 |
565 | AMQP_FRAME_HEADER:
566 | begin
567 | {$IFDEF _DEBUG_}
568 | DebugOut(Level, ' frame_type = AMQP_FRAME_HEADER');
569 | {$ENDIF}
570 | amqp_e16(Aframe.payload.properties.class_id,
571 | amqp_offset(Lout_frame, HEADER_SIZE));
572 | amqp_e16(0, amqp_offset(Lout_frame, HEADER_SIZE + 2)); { 'weight' }
573 | amqp_e64(Aframe.payload.properties.body_size,
574 | amqp_offset(Lout_frame, HEADER_SIZE + 4));
575 | Lproperties_encoded.bytes := amqp_offset(Lout_frame, HEADER_SIZE + 12);
576 | Lproperties_encoded.len := Abuffer.len - HEADER_SIZE - 12 - FOOTER_SIZE;
577 | Lres := amqp_encode_properties(Aframe.payload.properties.class_id,
578 | Aframe.payload.properties.decoded,
579 | Lproperties_encoded);
580 | if Lres < 0 then
581 | Exit(Lres);
582 |
583 | Lout_frame_len := Lres + 12;
584 |
585 | end;
586 | AMQP_FRAME_HEARTBEAT:
587 | begin
588 | {$IFDEF _DEBUG_}
589 | DebugOut(Level, ' frame_type = AMQP_FRAME_HEARTBEAT');
590 | {$ENDIF}
591 | Lout_frame_len := 0;
592 | end;
593 |
594 | else
595 | Exit(Int(AMQP_STATUS_INVALID_PARAMETER));
596 | end;
597 |
598 | amqp_e32(uint32_t(Lout_frame_len), amqp_offset(Lout_frame, 3));
599 | amqp_e8(AMQP_FRAME_END, amqp_offset(Lout_frame, HEADER_SIZE + Lout_frame_len));
600 | Aencoded.bytes := Lout_frame;
601 | Aencoded.len := Lout_frame_len + HEADER_SIZE + FOOTER_SIZE;
602 | Result := Int(AMQP_STATUS_OK);
603 | end;
604 |
605 |
606 | function amqp_send_frame(Astate : Pamqp_connection_state;const Aframe : Pamqp_frame):integer;
607 | begin
608 | Result := amqp_send_frame_inner(Astate, Aframe^, Int(AMQP_SF_NONE), Tamqp_time.infinite);
609 | end;
610 |
611 | initialization
612 |
613 |
614 | end.
615 |
--------------------------------------------------------------------------------
/amqp.consumer.pas:
--------------------------------------------------------------------------------
1 | unit amqp.consumer;
2 |
3 | {$IFDEF FPC}
4 | {$MODE Delphi}
5 | {$ENDIF}
6 |
7 | {$INCLUDE config.inc}
8 | interface
9 |
10 | uses {$IFNDEF FPC}
11 | {$IFDEF _WIN32}
12 | Net.Winsock2,
13 | {$ELSE}
14 | Net.SocketAPI,
15 | {$ENDIF}
16 | {$ELSE}
17 | Winsock2,
18 | {$ENDIF}
19 | amqp.mem, amqp.table, amqp.socket, AMQP.Types;
20 |
21 | function amqp_consume_message(Astate : Pamqp_connection_state;
22 | out Aenvelope : Tamqp_envelope;
23 | const Atimeout: Ptimeval;
24 | Aflags: int ):Tamqp_rpc_reply;
25 |
26 | function amqp_read_message(state : Pamqp_connection_state;
27 | channel : amqp_channel_t;
28 | out Amessage : Tamqp_message;
29 | flags: int):Tamqp_rpc_reply;
30 | function amqp_basic_consume( state : Pamqp_connection_state;
31 | channel : amqp_channel_t;
32 | queue, consumer_tag : Tamqp_bytes;
33 | no_local, no_ack, exclusive : amqp_boolean_t;
34 | arguments : Tamqp_table): Pamqp_basic_consume_ok;
35 | implementation
36 |
37 | function amqp_basic_consume( state : Pamqp_connection_state;
38 | channel : amqp_channel_t;
39 | queue, consumer_tag : Tamqp_bytes;
40 | no_local, no_ack, exclusive : amqp_boolean_t;
41 | arguments : Tamqp_table): Pamqp_basic_consume_ok;
42 | var
43 | req : Tamqp_basic_consume;
44 | begin
45 | req.ticket := 0;
46 | req.queue := queue;
47 | req.consumer_tag := consumer_tag;
48 | req.no_local := no_local;
49 | req.no_ack := no_ack;
50 | req.exclusive := exclusive;
51 | req.nowait := 0;
52 | req.arguments := arguments;
53 | Result := amqp_simple_rpc_decoded(state, channel, AMQP_BASIC_CONSUME_METHOD,
54 | AMQP_BASIC_CONSUME_OK_METHOD, @req);
55 | end;
56 |
57 | function amqp_consume_message(Astate : Pamqp_connection_state;
58 | out Aenvelope : Tamqp_envelope;
59 | const Atimeout: Ptimeval; Aflags: int):Tamqp_rpc_reply;
60 | var
61 | res : integer;
62 | Lframe : Tamqp_frame;
63 | delivery_method : Pamqp_basic_deliver;
64 | ret : Tamqp_rpc_reply;
65 | label error_out1;
66 | label error_out2;
67 | begin
68 | memset(ret, 0, sizeof(ret));
69 | memset(Aenvelope, 0, sizeof(Tamqp_envelope));
70 | res := amqp_simple_wait_frame_noblock(Astate, Lframe, Atimeout);
71 | if Int(AMQP_STATUS_OK) <> res then
72 | begin
73 | ret.reply_type := AMQP_RESPONSE_LIBRARY_EXCEPTION;
74 | ret.library_error := res;
75 | goto error_out1;
76 | end;
77 |
78 | if (AMQP_FRAME_METHOD <> Lframe.frame_type) or
79 | (AMQP_BASIC_DELIVER_METHOD <> Lframe.payload.method.id) then
80 | begin
81 | amqp_put_back_frame(Astate, @Lframe);
82 | ret.reply_type := AMQP_RESPONSE_LIBRARY_EXCEPTION;
83 | ret.library_error := Int(AMQP_STATUS_UNEXPECTED_STATE);
84 | goto error_out1;
85 | end;
86 |
87 | delivery_method := Pamqp_basic_deliver(Lframe.payload.method.decoded);
88 | Aenvelope.channel := Lframe.channel;
89 | Aenvelope.consumer_tag := (@delivery_method.consumer_tag);
90 | Aenvelope.exchange := (@delivery_method.exchange);
91 | Aenvelope.routing_key := (@delivery_method.routing_key);
92 |
93 | Aenvelope.delivery_tag := delivery_method.delivery_tag;
94 | Aenvelope.redelivered := delivery_method.redelivered;
95 | if (Aenvelope.consumer_tag.malloc_dup_failed > 0) or
96 | (Aenvelope.exchange.malloc_dup_failed > 0) or
97 | (Aenvelope.routing_key.malloc_dup_failed > 0) then
98 | begin
99 | ret.reply_type := AMQP_RESPONSE_LIBRARY_EXCEPTION;
100 | ret.library_error := Int(AMQP_STATUS_NO_MEMORY);
101 | goto error_out2;
102 | end;
103 |
104 | ret := amqp_read_message(Astate, Aenvelope.channel, Aenvelope.message, 0);
105 | if AMQP_RESPONSE_NORMAL <> ret.reply_type then
106 | begin
107 | goto error_out2;
108 | end;
109 |
110 | ret.reply_type := AMQP_RESPONSE_NORMAL;
111 | Exit(ret);
112 |
113 | error_out2:
114 | Aenvelope.routing_key.Destroy;
115 | Aenvelope.exchange.Destroy;
116 | Aenvelope.consumer_tag.Destroy;
117 | error_out1:
118 | Result := ret;
119 | end;
120 |
121 |
122 | function amqp_read_message(state : Pamqp_connection_state;
123 | channel : amqp_channel_t;
124 | out Amessage : Tamqp_message; flags: int):Tamqp_rpc_reply;
125 | var
126 | frame : Tamqp_frame;
127 | ret : Tamqp_rpc_reply;
128 | body_read : size_t;
129 | body_read_ptr : PAMQPChar;
130 | res : integer;
131 | label error_out1;
132 | label error_out2;
133 | label error_out3;
134 | begin
135 | memset(ret, 0, sizeof(ret));
136 | memset(Amessage, 0, sizeof( Tamqp_message));
137 | res := amqp_simple_wait_frame_on_channel(state, channel, frame);
138 | if Int(AMQP_STATUS_OK) <> res then
139 | begin
140 | ret.reply_type := AMQP_RESPONSE_LIBRARY_EXCEPTION;
141 | ret.library_error := res;
142 | goto error_out1;
143 | end;
144 |
145 | if frame.frame_type <> AMQP_FRAME_HEADER then
146 | begin
147 | if (AMQP_FRAME_METHOD = frame.frame_type) and
148 | ( (AMQP_CHANNEL_CLOSE_METHOD = frame.payload.method.id) or
149 | (AMQP_CONNECTION_CLOSE_METHOD = frame.payload.method.id) ) then
150 | begin
151 | ret.reply_type := AMQP_RESPONSE_SERVER_EXCEPTION;
152 | ret.reply := frame.payload.method;
153 | end
154 | else
155 | begin
156 | ret.reply_type := AMQP_RESPONSE_LIBRARY_EXCEPTION;
157 | ret.library_error := Int(AMQP_STATUS_UNEXPECTED_STATE);
158 | amqp_put_back_frame(state, @frame);
159 | end;
160 | goto error_out1;
161 | end;
162 |
163 | //init_amqp_pool(@Amessage.pool, 4096);
164 | Amessage.pool.Create(4096);
165 | res := Pamqp_basic_properties(frame.payload.properties.decoded)^.clone(
166 | Amessage.properties, @Amessage.pool);
167 | if Int(AMQP_STATUS_OK) <> res then
168 | begin
169 | ret.reply_type := AMQP_RESPONSE_LIBRARY_EXCEPTION;
170 | ret.library_error := res;
171 | goto error_out3;
172 | end;
173 |
174 | if 0 = frame.payload.properties.body_size then
175 | begin
176 | Amessage.body := amqp_empty_bytes;
177 | end
178 | else
179 | begin
180 | if SIZE_MAX < frame.payload.properties.body_size then
181 | begin
182 | ret.reply_type := AMQP_RESPONSE_LIBRARY_EXCEPTION;
183 | ret.library_error := Int(AMQP_STATUS_NO_MEMORY);
184 | goto error_out1;
185 | end;
186 | Amessage.body := Tamqp_bytes.Create(size_t(frame.payload.properties.body_size));
187 | if nil = Amessage.body.bytes then
188 | begin
189 | ret.reply_type := AMQP_RESPONSE_LIBRARY_EXCEPTION;
190 | ret.library_error := Int(AMQP_STATUS_NO_MEMORY);
191 | goto error_out1;
192 | end;
193 | end;
194 |
195 | body_read := 0;
196 | body_read_ptr := Amessage.body.bytes;
197 | while body_read < Amessage.body.len do
198 | begin
199 | res := amqp_simple_wait_frame_on_channel(state, channel, &frame);
200 | if Int(AMQP_STATUS_OK) <> res then
201 | begin
202 | ret.reply_type := AMQP_RESPONSE_LIBRARY_EXCEPTION;
203 | ret.library_error := res;
204 | goto error_out2;
205 | end;
206 |
207 | if AMQP_FRAME_BODY <> frame.frame_type then
208 | begin
209 | if (AMQP_FRAME_METHOD = frame.frame_type ) and
210 | ( (AMQP_CHANNEL_CLOSE_METHOD = frame.payload.method.id) or
211 | (AMQP_CONNECTION_CLOSE_METHOD = frame.payload.method.id)) then
212 | begin
213 | ret.reply_type := AMQP_RESPONSE_SERVER_EXCEPTION;
214 | ret.reply := frame.payload.method;
215 | end
216 | else
217 | begin
218 | ret.reply_type := AMQP_RESPONSE_LIBRARY_EXCEPTION;
219 | ret.library_error := Int(AMQP_STATUS_BAD_AMQP_DATA);
220 | end;
221 | goto error_out2;
222 | end;
223 |
224 | if body_read + frame.payload.body_fragment.len > Amessage.body.len then
225 | begin
226 | ret.reply_type := AMQP_RESPONSE_LIBRARY_EXCEPTION;
227 | ret.library_error := Int(AMQP_STATUS_BAD_AMQP_DATA);
228 | goto error_out2;
229 | end;
230 | memcpy(body_read_ptr, frame.payload.body_fragment.bytes,
231 | frame.payload.body_fragment.len);
232 | body_read := body_read + frame.payload.body_fragment.len;
233 | body_read_ptr := body_read_ptr + frame.payload.body_fragment.len;
234 | end;
235 | ret.reply_type := AMQP_RESPONSE_NORMAL;
236 | Exit(ret);
237 |
238 | error_out2:
239 | Amessage.body.Destroy;
240 |
241 | error_out3:
242 | Amessage.pool.empty;
243 |
244 | error_out1:
245 | Result := ret;
246 | end;
247 |
248 | end.
249 |
250 |
251 |
--------------------------------------------------------------------------------
/amqp.mem.pas:
--------------------------------------------------------------------------------
1 | unit amqp.mem;
2 |
3 | {$IFDEF FPC}
4 | {$MODE Delphi}
5 | {$ENDIF}
6 |
7 | {$INCLUDE config.inc}
8 | interface
9 | uses {$IFDEF FPC}SysUtils,{$Else} System.SysUtils, {$ENDIF} AMQP.Types;
10 |
11 |
12 | function amqp_cstring_bytes( const cstr: PAnsiChar):Tamqp_bytes;
13 |
14 | procedure amqp_dump( const buffer:Pointer; len : size_t);
15 |
16 | implementation
17 |
18 |
19 | function isprint( c : byte):byte;
20 | begin
21 | if (c >= $20 ) and (c <= $7e) then
22 | Exit(1);
23 | Result := 0;
24 | end;
25 |
26 | procedure dump_row(count : longint; numinrow : integer;chs : Pinteger);
27 | var
28 | i : integer;
29 | begin
30 | {$PointerMath on}
31 | write(format('%.8x:',[count - numinrow]));
32 | if numinrow > 0 then
33 | begin
34 | for i := 0 to numinrow-1 do
35 | begin
36 | if i = 8 then
37 | Write(':');
38 |
39 | write(format(' %.2x',[chs[i]]));
40 | end;
41 | for i := numinrow to 15 do
42 | begin
43 | if i = 8 then
44 | Write(':');
45 |
46 | Write('');
47 | end;
48 | Write('');
49 |
50 | for i := 0 to numinrow-1 do
51 | begin
52 | if isprint(chs[i])>0 then
53 | write(format('%s',[Chr(chs[i])]))
54 | else
55 | Write('.');
56 |
57 | end;
58 | end;
59 | Writeln;
60 | {$PointerMath off}
61 | end;
62 |
63 | function rows_eq(a, b : Pinteger):Boolean;
64 | var
65 | i : integer;
66 | begin
67 | {$PointerMath on}
68 | for i := 0 to 15 do
69 | if a[i] <> b[i] then
70 | Exit(False);
71 |
72 | Result := True;
73 | {$PointerMath off}
74 | end;
75 |
76 | procedure amqp_dump( const buffer:Pointer; len : size_t);
77 | var
78 | buf : Pbyte;
79 | count : longint;
80 | numinrow : integer;
81 | chs,
82 | oldchs : array[0..15] of integer;
83 | showed_dots : integer;
84 | i : size_t;
85 | ch,
86 | j : integer;
87 | begin
88 | buf := PByte(buffer);
89 | count := 0;
90 | numinrow := 0;
91 |
92 | showed_dots := 0;
93 | for i := 0 to len-1 do
94 | begin
95 | ch := buf[i];
96 | if numinrow = 16 then
97 | begin
98 | if rows_eq(@oldchs, @chs) then
99 | begin
100 | if 0>= showed_dots then
101 | begin
102 | showed_dots := 1;
103 | Writeln(
104 | ' .. .. .. .. .. .. .. .. : .. .. .. .. .. .. .. ..\n');
105 | end;
106 | end
107 | else
108 | begin
109 | showed_dots := 0;
110 | dump_row(count, numinrow, @chs);
111 | end;
112 | for j := 0 to 15 do
113 | oldchs[j] := chs[j];
114 |
115 | numinrow := 0;
116 | end;
117 | Inc(count);
118 | chs[numinrow] := ch;
119 | Inc(numinrow);
120 | end;
121 | dump_row(count, numinrow, @chs);
122 | if numinrow <> 0 then begin
123 | writeln(format('%.8x:',[count]));
124 | end;
125 | end;
126 |
127 | { replaced by Tamqp_bytes.Implicit
128 | function amqp_bytes_malloc_dup( src : Tamqp_bytes): Tamqp_bytes;
129 | begin
130 | result.len := src.len;
131 | result.bytes := malloc(src.len);
132 | if result.bytes <> nil then begin
133 | memcpy(result.bytes, src.bytes, src.len);
134 | end;
135 |
136 | end; }
137 |
138 | function amqp_cstring_bytes( const cstr: PAnsiChar):Tamqp_bytes;
139 | begin
140 | result.len := Length(cstr);
141 | result.bytes := PAMQPChar(cstr);
142 | end;
143 |
144 | initialization
145 |
146 | end.
147 |
--------------------------------------------------------------------------------
/amqp.privt.pas:
--------------------------------------------------------------------------------
1 | unit amqp.privt;
2 |
3 | {$IFDEF FPC}
4 | {$MODE Delphi}
5 | {$ENDIF}
6 |
7 | interface
8 | uses AMQP.Types;
9 |
10 | type
11 | Tbint = record
12 | case integer of
13 | 0: (i: uint32_t);
14 | 1: (c: array[0..3] of Byte);
15 |
16 | end;
17 |
18 |
19 | function is_bigendian: bool;
20 | function amqp_offset(data: PByte; offset : size_t): PByte;
21 | function amqp_rpc_reply_error( status : Tamqp_status_enum):Tamqp_rpc_reply;
22 |
23 | procedure amqp_e8(Aval : uint8_t; Adata: Pointer);
24 | procedure amqp_e16(Aval : uint16_t;Adata: Pointer);
25 | procedure amqp_e32(val : uint32_t;data: Pointer);
26 | procedure amqp_e64(val : uint64_t; data: Pointer);
27 |
28 | function amqp_encode_n(bits: Byte; encoded : Tamqp_bytes;offset : Psize_t; input : uint64_t):integer;
29 | function amqp_encode_bytes(encoded : Tamqp_bytes;offset : Psize_t; input : Tamqp_bytes):integer;
30 |
31 | function amqp_d8(data: Pointer):uint8_t;
32 | function amqp_d16(data: Pointer):uint16_t;
33 | function amqp_d32(data: Pointer):uint32_t;
34 | function amqp_d64(data: Pointer):uint64_t;
35 |
36 | function amqp_decode_8(encoded: Tamqp_bytes; offset: Psize_t; out output: uint8_t): int;
37 | function amqp_decode_16(encoded: Tamqp_bytes; offset: Psize_t; out output: uint16_t): int;
38 | function amqp_decode_32(encoded: Tamqp_bytes; offset: Psize_t; out output: uint32_t): int;
39 | function amqp_decode_64(encoded: Tamqp_bytes; offset: Psize_t; out output: uint64_t): int;
40 | function amqp_decode_bytes(encoded : Tamqp_bytes;offset : Psize_t; out output : Tamqp_bytes; len : size_t):integer;
41 |
42 |
43 |
44 | implementation
45 |
46 | function amqp_offset(data: PByte; offset : size_t): PByte;
47 | begin
48 | Inc(data , offset);
49 | Result := data;
50 | end;
51 |
52 | function amqp_rpc_reply_error( status : Tamqp_status_enum):Tamqp_rpc_reply;
53 | var
54 | reply : Tamqp_rpc_reply;
55 | begin
56 | reply.reply_type := AMQP_RESPONSE_LIBRARY_EXCEPTION;
57 | reply.library_error := Int(status);
58 | Result := reply;
59 | end;
60 |
61 | function amqp_decode_bytes(encoded : Tamqp_bytes;offset : Psize_t; out output : Tamqp_bytes; len : size_t):integer;
62 | var
63 | o : size_t;
64 | begin
65 | o := offset^;
66 | offset^ := o + len;
67 | if offset^ <= encoded.len then
68 | begin
69 | output.bytes := amqp_offset(encoded.bytes, o);
70 | output.len := len;
71 | Exit(1);
72 | end
73 | else
74 | Exit(0);
75 |
76 | end;
77 |
78 | function amqp_d32(data: Pointer):uint32_t;
79 | var
80 | val : uint32_t;
81 | begin
82 | memcpy(@val, data, sizeof(val));
83 | if not is_bigendian then
84 | begin
85 | val := ((val and $FF000000) shr 24) or ((val and $00FF0000) shr 8) or
86 | ((val and $0000FF00) shl 8) or ((val and $000000FF) shl 24);
87 | end;
88 | Result := val;
89 | end;
90 |
91 | procedure amqp_e64(val : uint64; data: Pointer);
92 | begin
93 | if not is_bigendian then
94 | begin
95 | val := ((val and 18374686479671623680) shr 56) or
96 | ((val and 71776119061217280) shr 40) or
97 | ((val and 280375465082880) shr 24) or
98 | ((val and 1095216660480) shr 8 ) or
99 | ((val and 4278190080) shl 8 ) or
100 | ((val and 16711680) shl 24) or
101 | ((val and 65280) shl 40) or
102 | ((val and 255) shl 56);
103 | end;
104 | memcpy(data, @val, sizeof(val));
105 | end;
106 |
107 | function amqp_d64(data: Pointer):uint64_t;
108 | var
109 | val : uint64_t;
110 | begin
111 | memcpy(@val, data, sizeof(val));
112 | if not is_bigendian then
113 | begin
114 | val := ((val and 18374686479671623680) shr 56) or
115 | ((val and 71776119061217280) shr 40) or
116 | ((val and 280375465082880) shr 24) or
117 | ((val and 1095216660480) shr 8 ) or
118 | ((val and 4278190080) shl 8 ) or
119 | ((val and 16711680) shl 24) or
120 | ((val and 65280) shl 40) or
121 | ((val and 255) shl 56);
122 | end;
123 | Result := val;
124 | end;
125 |
126 |
127 | function amqp_d16(data: Pointer):uint16_t;
128 | var
129 | val : uint16_t;
130 | begin
131 | memcpy(@val, data, sizeof(val));
132 | if not is_bigendian then
133 | val := ((val and $FF00) shr 8) or ((val and $00FF) shl 8);
134 |
135 | Result := val;
136 | end;
137 |
138 |
139 | function amqp_d8(data: Pointer):uint8_t;
140 | var
141 | val : uint8_t;
142 | begin
143 | memcpy(@val, data, sizeof(val));
144 | Result := val;
145 | end;
146 |
147 |
148 | function amqp_encode_bytes(encoded : Tamqp_bytes;offset : Psize_t; input : Tamqp_bytes):integer;
149 | var
150 | o : size_t;
151 | begin
152 | o := offset^;
153 | { The memcpy below has undefined behavior if the input is nil. It is valid
154 | * for a 0-length amqp_bytes_t to have .bytes = nil. Thus we should check
155 | * before encoding.
156 | }
157 | if input.len = 0 then
158 | Exit(1);
159 |
160 |
161 | offset^ := o + input.len;
162 | if offset^ <= encoded.len then
163 | begin
164 | memcpy(amqp_offset(encoded.bytes, o), input.bytes, input.len);
165 | Exit(1);
166 | end
167 | else
168 | Exit(0);
169 |
170 | end;
171 |
172 | function amqp_decode_8(encoded: Tamqp_bytes; offset: Psize_t; out output: uint8_t): int;
173 | var
174 | o : size_t;
175 | begin
176 | o := offset^;
177 | offset^ := o + 1;//Round(8 / 8);
178 | if offset^ <= encoded.len then
179 | begin
180 | output := amqp_d8(amqp_offset(encoded.bytes, o));
181 | Exit(1);
182 | end;
183 | Result := 0;
184 | end;
185 |
186 | function amqp_decode_16(encoded: Tamqp_bytes; offset: Psize_t; out output: uint16_t): int;
187 | var
188 | o : size_t;
189 | begin
190 | o := offset^;
191 | offset^ := o + 2;//Round(16 / 8);
192 | if offset^ <= encoded.len then
193 | begin
194 | output := amqp_d16(amqp_offset(encoded.bytes, o));
195 | Exit(1);
196 | end;
197 | Result := 0;
198 | end;
199 |
200 | function amqp_decode_32(encoded: Tamqp_bytes; offset: Psize_t; out output: uint32_t): int;
201 | var
202 | o : size_t;
203 | begin
204 | o := offset^;
205 | offset^ := o + 32 DIV 8;
206 | if offset^ <= encoded.len then
207 | begin
208 | output := amqp_d32(amqp_offset(encoded.bytes, o));
209 | Exit(1);
210 | end;
211 | Result := 0;
212 | end;
213 |
214 | function amqp_decode_64(encoded: Tamqp_bytes; offset: Psize_t; out output: uint64_t): int;
215 | var
216 | o : size_t;
217 | begin
218 | o := offset^;
219 | offset^ := o + 8;//Round(64 / 8);
220 | if offset^ <= encoded.len then
221 | begin
222 | output := amqp_d64(amqp_offset(encoded.bytes, o));
223 | Exit(1);
224 | end;
225 | Result := 0;
226 | end;
227 |
228 | function amqp_encode_n(bits: Byte; encoded : Tamqp_bytes;offset : Psize_t; input : uint64_t):integer;
229 | var
230 | o : size_t;
231 | begin
232 |
233 | o := offset^;
234 | offset^ := o + bits div 8;
235 | if offset^ <= encoded.len then
236 | begin
237 | case bits of
238 | 8:
239 | amqp_e8(input, amqp_offset(encoded.bytes, o));
240 | 16:
241 | amqp_e16(input, amqp_offset(encoded.bytes, o));
242 | 32:
243 | amqp_e32(input, amqp_offset(encoded.bytes, o));
244 | 64:
245 | amqp_e64(input, amqp_offset(encoded.bytes, o));
246 | end;
247 | Exit( 1);
248 | end;
249 |
250 | Exit( 0);
251 | end;
252 |
253 | procedure amqp_e8(Aval : uint8_t; Adata: Pointer);
254 | begin
255 | memcpy(Adata, @Aval, sizeof(Aval));
256 | end;
257 |
258 | procedure amqp_e16(Aval : uint16;Adata: Pointer);
259 | begin
260 | if not is_bigendian() then
261 | begin
262 | Aval := ((Aval and uint32_t($FF00)) shr uint32_t(8)) or ((Aval and uint32_t($00FF)) shl uint32_t(8));
263 | end;
264 | memcpy(Adata, @Aval, sizeof(Aval));
265 | end;
266 |
267 | procedure amqp_e32(val : uint32;data: Pointer);
268 | begin
269 | if not is_bigendian then
270 | begin
271 | val := ((val and UInt32($FF000000)) shr UInt32(24)) or ((val and UInt32($00FF0000)) shr UInt32(8)) or
272 | ((val and UInt32($0000FF00)) shl UInt32(8)) or ((val and UInt32($000000FF)) shl UInt32(24));
273 | end;
274 | memcpy(data, @val, sizeof(val));
275 | end;
276 |
277 |
278 |
279 | function is_bigendian: bool;
280 | var
281 | bint: Tbint;
282 | begin
283 | bint.i := $01020304;
284 | Result := Ord(bint.c[0]) = 1;
285 | end;
286 |
287 |
288 | initialization
289 |
290 | end.
291 |
--------------------------------------------------------------------------------
/amqp.table.pas:
--------------------------------------------------------------------------------
1 | unit amqp.table;
2 |
3 | {$IFDEF FPC}
4 | {$MODE Delphi}
5 | {$ENDIF}
6 |
7 | interface
8 | uses AMQP.Types, amqp.privt, amqp.mem;
9 |
10 |
11 | function amqp_decode_table(encoded : Tamqp_bytes; pool : Pamqp_pool; out output : Tamqp_table; offset : Psize_t):integer;
12 | function amqp_encode_table(encoded : Tamqp_bytes; input : Pamqp_table; offset : Psize_t):integer;
13 |
14 | function amqp_encode_field_value(encoded : Tamqp_bytes;const entry : Pamqp_field_value; offset : Psize_t):integer;
15 | function amqp_decode_field_value(encoded : Tamqp_bytes; pool : Pamqp_pool; out entry : Tamqp_field_value; offset : Psize_t):integer;
16 | //function amqp_table_get_entry_by_key(const table : Pamqp_table;const key : Tamqp_bytes):Pamqp_table_entry;
17 | function amqp_decode_array(encoded : Tamqp_bytes; pool : Pamqp_pool; out output : Tamqp_array; offset : Psize_t):integer;
18 | //function amqp_table_clone(const original: Tamqp_table;out clone : Tamqp_table; pool : Pamqp_pool):integer;
19 | //function amqp_table_entry_clone(const original: Pamqp_table_entry; clone : Pamqp_table_entry; pool : Pamqp_pool):integer;
20 | //function amqp_field_value_clone(const original: Pamqp_field_value; clone : Pamqp_field_value; pool : Pamqp_pool):integer;
21 |
22 | const
23 | INITIAL_ARRAY_SIZE =16;
24 | INITIAL_TABLE_SIZE =16;
25 |
26 | implementation
27 |
28 |
29 | function amqp_decode_array(encoded : Tamqp_bytes; pool : Pamqp_pool;
30 | out output : Tamqp_array; offset : Psize_t):integer;
31 | var
32 | arraysize : uint32;
33 | num_entries,
34 | allocated_entries : integer;
35 | entries : Pamqp_field_value;
36 | limit : size_t;
37 | res : integer;
38 | newentries : Pointer;
39 | label _out;
40 | begin
41 | {$POINTERMATH ON}
42 | num_entries := 0;
43 | allocated_entries := INITIAL_ARRAY_SIZE;
44 | if 0= amqp_decode_32(encoded, offset, &arraysize ) then
45 | begin
46 | Exit(Int(AMQP_STATUS_BAD_AMQP_DATA));
47 | end;
48 | if arraysize + offset^ > encoded.len then
49 | begin
50 | Exit(Int(AMQP_STATUS_BAD_AMQP_DATA));
51 | end;
52 | entries := allocMem(allocated_entries * sizeof(Tamqp_field_value));
53 | if entries = nil then
54 | Exit(Int(AMQP_STATUS_NO_MEMORY));
55 |
56 | limit := offset^ + arraysize;
57 | while offset^ < limit do
58 | begin
59 | if num_entries >= allocated_entries then
60 | begin
61 | allocated_entries := allocated_entries * 2;
62 | reallocMem(entries, allocated_entries * sizeof(Tamqp_field_value));
63 | res := Int(AMQP_STATUS_NO_MEMORY);
64 | if entries = nil then
65 | goto _out;
66 | end;
67 | res := amqp_decode_field_value(encoded, pool, entries[num_entries], offset);
68 | if res < 0 then
69 | goto _out;
70 | Inc(num_entries);
71 | end;
72 | output.num_entries := num_entries;
73 | output.entries := pool.alloc( num_entries * sizeof(Tamqp_field_value));
74 | { nil is legitimate if we requested a zero-length block. }
75 | if output.entries = nil then
76 | begin
77 | if num_entries = 0 then
78 | res := Int(AMQP_STATUS_OK)
79 | else
80 | res := Int(AMQP_STATUS_NO_MEMORY);
81 |
82 | end;
83 | memcpy(output.entries, entries, num_entries * sizeof(Tamqp_field_value));
84 | res := Int(AMQP_STATUS_OK);
85 | _out:
86 | freeMem(entries);
87 | Result := res;
88 | {$POINTERMATH OFF}
89 | end;
90 |
91 | function amqp_decode_field_value(encoded : Tamqp_bytes;pool : Pamqp_pool;
92 | out entry : Tamqp_field_value; offset : Psize_t):integer;
93 | var
94 | res : integer;
95 | len : uint32;
96 | label _out;
97 |
98 | procedure SIMPLE_FIELD_DECODER(bits: Byte; dest: string);
99 | var
100 | Lval8: uint8_t;
101 | Lval16: uint16_t;
102 | Lval32: uint32_t;
103 | Lval64: uint64_t;
104 | label _out;
105 | begin
106 | case bits of
107 | 8:
108 | begin
109 | if (0=amqp_decode_8(encoded, offset, Lval8)) then
110 | goto _out;
111 | if dest = 'i8' then
112 | entry.value.i8 := Lval8
113 | else
114 | if dest = 'boolean' then
115 | begin
116 | if Lval8 > 0 then
117 | entry.value.boolean := 1
118 | else
119 | entry.value.boolean := 0;
120 | end;
121 | end;
122 | 16:
123 | begin
124 |
125 | if (0=amqp_decode_16(encoded, offset, Lval16)) then
126 | goto _out;
127 | if dest = 'i16' then
128 | entry.value.i16 := Lval16;
129 | end;
130 | 32:
131 | begin
132 |
133 | if (0=amqp_decode_32(encoded, offset, Lval32)) then
134 | goto _out;
135 | if dest = 'i32' then
136 | entry.value.i32 := Lval32;
137 | end;
138 | 64:
139 | begin
140 |
141 | if (0=amqp_decode_64(encoded, offset, Lval64)) then
142 | goto _out;
143 | if dest = 'i64' then
144 | entry.value.i64 := Lval64
145 | end;
146 |
147 | end;
148 |
149 | _out:
150 | Result := res;
151 | end;
152 |
153 | procedure TRIVIAL_FIELD_DECODER(bits: byte);
154 | label _out;
155 | begin
156 | case bits of
157 | 8:
158 | if 0=amqp_decode_8(encoded, offset, entry.value.u8) then
159 | goto _out;
160 | 16:
161 | if 0=amqp_decode_16(encoded, offset, entry.value.u16) then
162 | goto _out;
163 | 32:
164 | if 0=amqp_decode_32(encoded, offset, entry.value.u32) then
165 | goto _out;
166 | end;
167 |
168 | _out:
169 | Result := res;
170 | end;
171 |
172 | begin
173 | res := Int(AMQP_STATUS_BAD_AMQP_DATA);
174 | if 0= amqp_decode_8(encoded, offset, entry.kind ) then
175 | goto _out;
176 | case entry.kind of
177 | Int(AMQP_FIELD_KIND_BOOLEAN):
178 | SIMPLE_FIELD_DECODER(8, 'boolean');
179 | Int(AMQP_FIELD_KIND_I8):
180 | SIMPLE_FIELD_DECODER(8, 'i8');
181 | Int(AMQP_FIELD_KIND_U8):
182 | TRIVIAL_FIELD_DECODER(8);
183 | Int(AMQP_FIELD_KIND_I16):
184 | SIMPLE_FIELD_DECODER(16, 'i16');
185 | Int(AMQP_FIELD_KIND_U16):
186 | TRIVIAL_FIELD_DECODER(16);
187 | Int(AMQP_FIELD_KIND_I32):
188 | SIMPLE_FIELD_DECODER(32, 'i32');
189 | Int(AMQP_FIELD_KIND_U32):
190 | TRIVIAL_FIELD_DECODER(32);
191 | Int(AMQP_FIELD_KIND_I64):
192 | SIMPLE_FIELD_DECODER(64, 'i64');
193 | Int(AMQP_FIELD_KIND_U64):
194 | TRIVIAL_FIELD_DECODER(64);
195 | Int(AMQP_FIELD_KIND_F32):
196 | TRIVIAL_FIELD_DECODER(32);
197 | { and by punning, f32 magically gets the right value...! }
198 | Int(AMQP_FIELD_KIND_F64):
199 | TRIVIAL_FIELD_DECODER(64);
200 | { and by punning, f64 magically gets the right value...! }
201 | Int(AMQP_FIELD_KIND_DECIMAL):
202 | if (0= amqp_decode_8(encoded, offset, entry.value.decimal.decimals)) or
203 | (0= amqp_decode_32(encoded, offset, entry.value.decimal.value))then
204 | goto _out;
205 |
206 | Int(AMQP_FIELD_KIND_UTF8),
207 | { AMQP_FIELD_KIND_UTF8 and AMQP_FIELD_KIND_BYTES have the
208 | same implementation, but different interpretations. }
209 | { fall through }
210 | Int(AMQP_FIELD_KIND_BYTES):
211 | begin
212 | if (0= amqp_decode_32(encoded, offset, &len)) or
213 | (0= amqp_decode_bytes(encoded, offset, entry.value.bytes, len)) then
214 | goto _out;
215 |
216 | end;
217 | Int(AMQP_FIELD_KIND_ARRAY):
218 | res := amqp_decode_array(encoded, pool, entry.value.&array, offset);
219 | Int(AMQP_FIELD_KIND_TIMESTAMP):
220 | TRIVIAL_FIELD_DECODER(64);
221 | Int(AMQP_FIELD_KIND_TABLE):
222 | res := amqp_decode_table(encoded, pool, entry.value.table, offset);
223 | Int(AMQP_FIELD_KIND_VOID):
224 |
225 | else goto _out;
226 | end;
227 | res := Int(AMQP_STATUS_OK);
228 | _out:
229 | Result := res;
230 | end;
231 |
232 | function amqp_decode_table(encoded : Tamqp_bytes; pool : Pamqp_pool;
233 | out output : Tamqp_table; offset : Psize_t):integer;
234 | var
235 | tablesize : uint32;
236 | num_entries : integer;
237 | entries : Pamqp_table_entry;
238 | allocated_entries : integer;
239 | limit : size_t;
240 | res : integer;
241 | keylen : byte;
242 |
243 | newentries : Pointer;
244 | label _out;
245 | begin
246 | {$POINTERMATH ON}
247 | num_entries := 0;
248 | allocated_entries := INITIAL_TABLE_SIZE;
249 | if 0= amqp_decode_32(encoded, offset, &tablesize )then
250 | begin
251 | Exit(Int(AMQP_STATUS_BAD_AMQP_DATA));
252 | end;
253 | if tablesize + offset^ > encoded.len then
254 | begin
255 | Exit(Int(AMQP_STATUS_BAD_AMQP_DATA));
256 | end;
257 | entries := allocMem(allocated_entries * sizeof(Tamqp_table_entry));
258 | if entries = nil then
259 | Exit(Int(AMQP_STATUS_NO_MEMORY));
260 |
261 | limit := offset^ + tablesize;
262 | while offset^ < limit do
263 | begin
264 | res := Int(AMQP_STATUS_BAD_AMQP_DATA);
265 | if 0= amqp_decode_8(encoded, offset, &keylen )then
266 | goto _out;
267 | if num_entries >= allocated_entries then
268 | begin
269 | allocated_entries := allocated_entries * 2;
270 | reallocMem(entries, allocated_entries * sizeof(Tamqp_table_entry));
271 | res := Int(AMQP_STATUS_NO_MEMORY);
272 | if entries = nil then
273 | goto _out;
274 |
275 | end;
276 | res := Int(AMQP_STATUS_BAD_AMQP_DATA);
277 | if 0= amqp_decode_bytes(encoded, offset, entries[num_entries].key, keylen) then
278 | goto _out;
279 | res := amqp_decode_field_value(encoded, pool, entries[num_entries].value,offset);
280 | if res < 0 then
281 | goto _out;
282 | Inc(num_entries);
283 | end;
284 |
285 | output.num_entries := num_entries;
286 | output.entries := pool.alloc( num_entries * sizeof(Tamqp_table_entry));
287 | { nil is legitimate if we requested a zero-length block. }
288 | if output.entries = nil then
289 | begin
290 | if num_entries = 0 then
291 | res := Int(AMQP_STATUS_OK)
292 | else
293 | res := Int(AMQP_STATUS_NO_MEMORY);
294 |
295 | end;
296 | memcpy(output.entries, entries, num_entries * sizeof(Tamqp_table_entry));
297 | res := Int(AMQP_STATUS_OK);
298 |
299 | _out:
300 | freemem(entries);
301 | Result := res;
302 | {$POINTERMATH OFF}
303 | end;
304 |
305 | function amqp_encode_array(encoded : Tamqp_bytes; input : Pamqp_array; offset : Psize_t):integer;
306 | var
307 | start : size_t;
308 | i, res : integer;
309 | label _out;
310 | begin
311 | {$POINTERMATH ON}
312 | start := offset^;
313 | offset^ := offset^ + 4;
314 | for i := 0 to input.num_entries-1 do
315 | begin
316 | res := amqp_encode_field_value(encoded, @input.entries[i], offset);
317 | if res < 0 then
318 | goto _out;
319 | end;
320 |
321 | if 0= amqp_encode_n(32, encoded, @start, uint32_t( offset^ - start - 4)) then
322 | begin
323 | res := Integer(AMQP_STATUS_TABLE_TOO_BIG);
324 | goto _out;
325 | end;
326 | res := Integer(AMQP_STATUS_OK);
327 | _out:
328 | Result := res;
329 | {$POINTERMATH OFF}
330 | end;
331 |
332 | function amqp_encode_field_value(encoded : Tamqp_bytes;const entry : Pamqp_field_value; offset : Psize_t):integer;
333 | var
334 | res, value : integer;
335 | label _out;
336 | procedure FIELD_ENCODER(bits, val: Byte);
337 | begin
338 | if 0= amqp_encode_n(bits, encoded, offset, val) then
339 | res := Integer(AMQP_STATUS_TABLE_TOO_BIG);
340 | end;
341 |
342 | begin
343 | res := Integer(AMQP_STATUS_BAD_AMQP_DATA);
344 | if 0= amqp_encode_n(8, encoded, offset, entry.kind) then
345 | goto _out;
346 |
347 | case entry.kind of
348 | uint8(AMQP_FIELD_KIND_BOOLEAN):
349 | begin
350 | if entry.value.boolean > 0 then
351 | value := 1
352 | else
353 | value := 0;
354 | FIELD_ENCODER(8, value);
355 | end;
356 | uint8(AMQP_FIELD_KIND_I8):
357 | FIELD_ENCODER(8, entry.value.i8);
358 | uint8(AMQP_FIELD_KIND_U8):
359 | FIELD_ENCODER(8, entry.value.u8);
360 | uint8(AMQP_FIELD_KIND_I16):
361 | FIELD_ENCODER(16, entry.value.i16);
362 | uint8(AMQP_FIELD_KIND_U16):
363 | FIELD_ENCODER(16, entry.value.u16);
364 | uint8(AMQP_FIELD_KIND_I32):
365 | FIELD_ENCODER(32, entry.value.i32);
366 | uint8(AMQP_FIELD_KIND_U32):
367 | FIELD_ENCODER(32, entry.value.u32);
368 | uint8(AMQP_FIELD_KIND_I64):
369 | FIELD_ENCODER(64, entry.value.i64);
370 | uint8(AMQP_FIELD_KIND_U64):
371 | FIELD_ENCODER(64, entry.value.u64);
372 | uint8(AMQP_FIELD_KIND_F32):
373 | { by punning, u32 magically gets the right value...! }
374 | FIELD_ENCODER(32, entry.value.u32);
375 | uint8(AMQP_FIELD_KIND_F64):
376 | { by punning, u64 magically gets the right value...! }
377 | FIELD_ENCODER(64, entry.value.u64);
378 | uint8(AMQP_FIELD_KIND_DECIMAL):
379 | begin
380 | if (0= amqp_encode_n(8, encoded, offset, entry.value.decimal.decimals)) or
381 | (0= amqp_encode_n(32, encoded, offset, entry.value.decimal.value)) then
382 | begin
383 | res := Integer(AMQP_STATUS_TABLE_TOO_BIG);
384 | goto _out;
385 | end;
386 | end;
387 |
388 | uint8(AMQP_FIELD_KIND_UTF8),
389 | { AMQP_FIELD_KIND_UTF8 and AMQP_FIELD_KIND_BYTES have the
390 | same implementation, but different interpretations. }
391 | { fall through }
392 | uint8(AMQP_FIELD_KIND_BYTES):
393 | begin
394 | if (0= amqp_encode_n(32, encoded, offset, uint32_t (entry.value.bytes.len))) or
395 | (0= amqp_encode_bytes(encoded, offset, entry.value.bytes)) then
396 | begin
397 | res := Integer(AMQP_STATUS_TABLE_TOO_BIG);
398 | goto _out;
399 | end;
400 | end;
401 | uint8(AMQP_FIELD_KIND_ARRAY):
402 | begin
403 | res := amqp_encode_array(encoded, @entry.value.&array, offset);
404 | goto _out;
405 | end;
406 | uint8(AMQP_FIELD_KIND_TIMESTAMP):
407 | FIELD_ENCODER(64, entry.value.u64);
408 | uint8(AMQP_FIELD_KIND_TABLE):
409 | begin
410 | res := amqp_encode_table(encoded, @entry.value.table, offset);
411 | goto _out;
412 | end;
413 | uint8(AMQP_FIELD_KIND_VOID):
414 | begin
415 | //
416 | end;
417 | else
418 | res := Integer(AMQP_STATUS_INVALID_PARAMETER);
419 | end;
420 | res := Integer(AMQP_STATUS_OK);
421 | _out:
422 | Result := res;
423 | end;
424 |
425 | function amqp_encode_table(encoded : Tamqp_bytes; input : Pamqp_table; offset : Psize_t):integer;
426 | var
427 | start : size_t;
428 | i, res : integer;
429 | label _out;
430 | begin
431 | {$POINTERMATH ON}
432 | start := offset^;
433 | offset^ := offset^ + 4;
434 | for i := 0 to input.num_entries-1 do
435 | begin
436 | if 0= amqp_encode_n(8, encoded, offset, uint8_t(input.entries[i].key.len)) then
437 | begin
438 | res := Integer(AMQP_STATUS_TABLE_TOO_BIG);
439 | goto _out;
440 | end;
441 | if 0= amqp_encode_bytes(encoded, offset, input.entries[i].key ) then
442 | begin
443 | res := Integer(AMQP_STATUS_TABLE_TOO_BIG);
444 | goto _out;
445 | end;
446 | res := amqp_encode_field_value(encoded, @input.entries[i].value, offset);
447 | if res < 0 then
448 | goto _out;
449 |
450 | end;
451 |
452 | if 0= amqp_encode_n(32, encoded, @start, uint32_t( offset^ - start - 4)) then
453 | begin
454 | res := Integer(AMQP_STATUS_TABLE_TOO_BIG);
455 | goto _out;
456 | end;
457 | res := Integer(AMQP_STATUS_OK);
458 | _out:
459 | Result := res;
460 | {$POINTERMATH OFF}
461 | end;
462 |
463 | initialization
464 |
465 | end.
466 |
--------------------------------------------------------------------------------
/amqp.tcp_socket.pas:
--------------------------------------------------------------------------------
1 | unit amqp.tcp_socket;
2 |
3 | {$IFDEF FPC}
4 | {$MODE Delphi}
5 | {$ENDIF}
6 |
7 | {$INCLUDE config.inc}
8 |
9 | //DEFINE EAGAIN Operation would have caused the process to be suspended.
10 | interface
11 | uses AMQP.Types, amqp.socket,
12 | {$IFNDEF FPC}
13 |
14 | {$IFDEF _WIN32}
15 | Net.Winsock2, Net.Wship6,
16 | {$ELSE}
17 | Net.SocketAPI,
18 | {$ENDIF}
19 | System.SysUtils;
20 | {$ELSE}
21 | winsock2, SysUtils;
22 | {$ENDIF}
23 |
24 | function amqp_tcp_socket_new( state : Pamqp_connection_state):Pamqp_socket;
25 | function amqp_tcp_socket_recv(base: Pointer; buf: Pointer; len : size_t; flags : integer):ssize_t;
26 | function amqp_tcp_socket_open( base: Pointer; const host : PAnsiChar; port : integer;const timeout: Ptimeval):integer;
27 | function amqp_tcp_socket_get_sockfd(base: Pointer):int;
28 | function amqp_tcp_socket_close(base: Pointer; force: Tamqp_socket_close_enum):integer;
29 | function amqp_tcp_socket_send(base: Pointer;const buf: Pointer; len : size_t; flags : integer):ssize_t;
30 | procedure amqp_tcp_socket_set_sockfd(base : Pamqp_socket; sockfd : integer);
31 | procedure amqp_tcp_socket_delete(base: Pointer);
32 |
33 |
34 | const
35 | //Record Constants Record constants cannot contain file-type values at any level.
36 | amqp_tcp_socket_class: Tamqp_socket_class = (
37 | send : amqp_tcp_socket_send;
38 | recv : amqp_tcp_socket_recv;
39 | open : amqp_tcp_socket_open;
40 | close : amqp_tcp_socket_close;
41 | get_sockfd : amqp_tcp_socket_get_sockfd;
42 | delete : amqp_tcp_socket_delete);
43 |
44 | implementation
45 |
46 | (*TCP_CORK is Linux only; TCP_NOPUSH is BSD only; Windows does its own thing:
47 | https://baus.net/on-tcp_cork/
48 | https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-tcp-socket-options
49 | *)
50 | procedure amqp_tcp_socket_set_sockfd(base : Pamqp_socket; sockfd : integer);
51 | var
52 | self : Pamqp_tcp_socket;
53 | s: string;
54 | begin
55 | if base.klass <> @amqp_tcp_socket_class then
56 | begin
57 | s := Format('<%p> is not of type Tamqp_tcp_socket', [base]);
58 | raise Exception.Create(s);
59 | end;
60 | self := Pamqp_tcp_socket(base);
61 | self.sockfd := sockfd;
62 | end;
63 |
64 | procedure amqp_tcp_socket_delete(base: Pointer);
65 | var
66 | self : Pamqp_tcp_socket;
67 | begin
68 | self := Pamqp_tcp_socket(base);
69 | if Assigned(self) then
70 | begin
71 | amqp_tcp_socket_close(self, AMQP_SC_NONE);
72 | freeMem(self);
73 | end;
74 | end;
75 |
76 | function amqp_tcp_socket_get_sockfd(base: Pointer):int;
77 | var
78 | self : Pamqp_tcp_socket;
79 | begin
80 | self := Pamqp_tcp_socket(base);
81 | Result := self.sockfd;
82 | end;
83 |
84 | function amqp_tcp_socket_close(base: Pointer; force: Tamqp_socket_close_enum):integer;
85 | var
86 | self : Pamqp_tcp_socket;
87 | begin
88 | self := Pamqp_tcp_socket(base);
89 | if -1 = self.sockfd then
90 | Exit(Int(AMQP_STATUS_SOCKET_CLOSED));
91 |
92 | if amqp_os_socket_close(self.sockfd) > 0 then
93 | Exit(Int(AMQP_STATUS_SOCKET_ERROR));
94 |
95 | self.sockfd := -1;
96 | Result := Int(AMQP_STATUS_OK);
97 | end;
98 |
99 |
100 | function amqp_tcp_socket_open( base: Pointer; const host : PAnsiChar; port : integer;const timeout: Ptimeval):integer;
101 | var
102 | Lself : Pamqp_tcp_socket;
103 | err : integer;
104 | begin
105 | Lself := Pamqp_tcp_socket(base);
106 | if -1 <> Lself.sockfd then
107 | Exit(Int(AMQP_STATUS_SOCKET_INUSE));
108 |
109 | Lself.sockfd := amqp_open_socket_noblock(host, port, timeout);
110 | if 0 > Lself.sockfd then
111 | begin
112 | err := Lself.sockfd;
113 | Lself.sockfd := -1;
114 | Exit(err);
115 | end;
116 | Result := Int(AMQP_STATUS_OK);
117 | end;
118 |
119 | function amqp_tcp_socket_recv(base: Pointer; buf: Pointer; len : size_t; flags : integer):ssize_t;
120 | var
121 | self : Pamqp_tcp_socket;
122 | ret : ssize_t;
123 | Level: int;
124 | s: string;
125 |
126 | label start;
127 | begin
128 | Inc(gLevel);
129 | Level := gLevel;
130 | {$IFDEF _DEBUG_}
131 | DebugOut(Level, 'step into amqp.tcp_socket::amqp_tcp_socket_recv!');
132 | {$ENDIF}
133 | self := Pamqp_tcp_socket(base);
134 | if -1 = self.sockfd then
135 | Exit(Int(AMQP_STATUS_SOCKET_CLOSED));
136 |
137 | start:
138 | {$IFDEF _WIN32}
139 |
140 | ret := recv(self.sockfd, Pbyte(buf)^, Int(len), flags);
141 | {$ELSE}
142 | ret = recv(self.sockfd, buf, len, flags);
143 | {$ENDIF}
144 | if 0 > ret then
145 | begin
146 | self.internal_error := amqp_os_socket_error();
147 | {$IFDEF _DEBUG_}
148 | s := Format('step over amqp.tcp_socket::recv, ret=%d os_socket_error=%d', [ret, self.internal_error] );
149 | DebugOut(Level, s);
150 | {$ENDIF}
151 | case self.internal_error of
152 | WSAEINTR: goto start;
153 | {$IFDEF _WIN32}
154 | WSAEWOULDBLOCK,
155 | {$ELSE}
156 | EWOULDBLOCK:
157 | {$ENDIF}
158 | {$IF EAGAIN <> 10035}//EWOULDBLOCK}
159 | EAGAIN:
160 | {$IFEND}
161 | ret := Int(AMQP_PRIVATE_STATUS_SOCKET_NEEDREAD);
162 | else
163 | ret := Int(AMQP_STATUS_SOCKET_ERROR);
164 | end;
165 | end
166 | else
167 | if (0 = ret) then
168 | ret := Int(AMQP_STATUS_CONNECTION_CLOSED);
169 |
170 | Result := ret;
171 |
172 | end;
173 |
174 | function amqp_tcp_socket_send(base: Pointer;const buf: Pointer; len : size_t; flags : integer):ssize_t;
175 | var
176 | Lself : Pamqp_tcp_socket;
177 | res : ssize_t;
178 | flagz, one, zero : integer;
179 | LBuffer : Puint8_t;
180 | LArray: array of AnsiChar;
181 | label start;
182 | begin
183 | {$POINTERMATH ON}
184 | Lself := Pamqp_tcp_socket(base);
185 | flagz := 0;
186 | //sockfd=-1 表示socket 已经closed
187 | if -1 = Lself.sockfd then
188 | Exit(Int(AMQP_STATUS_SOCKET_CLOSED));
189 |
190 | {$IFDEF MSG_NOSIGNAL}
191 | flagz := flagz or MSG_NOSIGNAL;
192 | {$ENDIF}
193 | {$IF defined(MSG_MORE)}
194 | if flags and AMQP_SF_MORE then begin
195 | flagz := flagz or MSG_MORE;
196 | end;
197 | { Cygwin defines TCP_NOPUSH, but trying to use it will return not
198 | * implemented. Disable it here. }
199 | {$ELSEIF defined(TCP_NOPUSH) and not defined(__CYGWIN__)}
200 | if ( (flags and Int(AMQP_SF_MORE))>0 ) and
201 | (0> (self.state and Int(AMQP_SF_MORE) )) then
202 | begin
203 | one := 1;
204 | res := setsockopt(self.sockfd, IPPROTO_TCP, TCP_NOPUSH, &one, sizeof(one));
205 | if 0 <> res then
206 | begin
207 | self.internal_error := res;
208 | Exit(AMQP_STATUS_SOCKET_ERROR);
209 | end;
210 | self.state := self.state or AMQP_SF_MORE;
211 | end
212 | else
213 | if ( 0= (flags and AMQP_SF_MORE) ) and ((self.state and AMQP_SF_MORE)>0) then
214 | begin
215 | zero := 0;
216 | res := setsockopt(self.sockfd, IPPROTO_TCP, TCP_NOPUSH, &zero, sizeof(&zero));
217 | if 0 <> res then
218 | begin
219 | self.internal_error := res;
220 | res := AMQP_STATUS_SOCKET_ERROR;
221 | end
222 | else
223 | begin
224 | self.state &= ~AMQP_SF_MORE;
225 | end;
226 | end;
227 | {$IFEND}
228 |
229 | start:
230 | {$IFDEF _WIN32}
231 | //LBuffer := Puint8_t(buf);
232 | {SetLength(LArray, len);
233 | for var I := 0 to Len - 1 do
234 | Larray[I] := AnsiChar(LBuffer[I]); }
235 | {$IFNDEF FPC}
236 | res := send(Lself.sockfd, buf^, Int(len), flagz);
237 | {$ELSE}
238 | res := send(Lself.sockfd, buf^, len, flagz);
239 | {$ENDIF}
240 | {$ELSE}
241 | res := send(Lself.sockfd, buf, len, flagz);
242 | {$ENDIF}
243 | if res < 0 then
244 | begin
245 | Lself.internal_error := amqp_os_socket_error();
246 | case Lself.internal_error of
247 | WSAEINTR: goto start;
248 | {$IFDEF _WIN32}
249 | WSAEWOULDBLOCK,
250 | {$ELSE }
251 | EWOULDBLOCK:
252 | {$ENDIF}
253 | {$if EAGAIN <> 10035}//EWOULDBLOCK}
254 | EAGAIN:
255 | {$IFEND}
256 | res := int(AMQP_PRIVATE_STATUS_SOCKET_NEEDWRITE);
257 |
258 | else
259 | res := Int(AMQP_STATUS_SOCKET_ERROR);
260 | end;
261 | end
262 | else
263 | Lself.internal_error := 0;
264 |
265 | Result := res;
266 | {$POINTERMATH ON}
267 | end;
268 |
269 |
270 | function amqp_tcp_socket_new( state : Pamqp_connection_state):Pamqp_socket;
271 | var
272 | Lself : Pamqp_tcp_socket;
273 | begin
274 | Lself := calloc(1, sizeof(Tamqp_tcp_socket));
275 | if not Assigned(Lself) then
276 | Exit(nil);
277 |
278 | Lself.klass := @amqp_tcp_socket_class;
279 | Lself.sockfd := -1;
280 | //amqp_set_socket(state, Pamqp_socket(Lself));
281 | state.socket := Pamqp_socket(Lself);
282 | Result := Pamqp_socket(Lself);
283 | end;
284 |
285 | initialization
286 |
287 | end.
288 |
--------------------------------------------------------------------------------
/amqp.time.pas:
--------------------------------------------------------------------------------
1 | unit amqp.time;
2 |
3 | {$IFDEF FPC}
4 | {$MODE Delphi}
5 | {$ENDIF}
6 |
7 | interface
8 | {$INCLUDE config.inc}
9 | uses {$IFNDEF FPC}
10 | {$IFDEF _WIN32}
11 | Net.Winsock2,
12 | {$ELSE}
13 | Net.SocketAPI,
14 | {$ENDIF}
15 |
16 | Winapi.Windows,
17 | {$ELSE}
18 | Windows, winsock2, //WS2tcpip,
19 | {$ENDIF} AMQP.Types;
20 |
21 |
22 | function amqp_time_from_now(var Atime : Tamqp_time;const Atimeout: Ptimeval):integer;
23 | function amqp_time_s_from_now(var Atime : Tamqp_time; Aseconds : integer):integer;
24 |
25 | function amqp_time_ms_until( Atime : Tamqp_time):integer;
26 | function amqp_time_tv_until( Atime : Tamqp_time; Ain: Ptimeval; Aout: PPtimeval):integer;
27 | function amqp_time_has_past( Atime : Tamqp_time):integer;
28 | function amqp_time_first( l, r : Tamqp_time):Tamqp_time;
29 |
30 |
31 | const
32 | //要指定 uint64_t,否则会引发计算错误
33 | AMQP_MS_PER_S: uint32_t =1000;
34 | AMQP_US_PER_MS: uint32_t =1000;
35 | AMQP_NS_PER_S: uint64_t =1000*1000*1000; //每秒=多少纳秒
36 | AMQP_NS_PER_MS: uint64_t =1000*1000; //每毫秒=多少纳秒
37 | AMQP_NS_PER_US: uint32_t =1000; //每微秒=多少纳秒
38 |
39 | var
40 | NS_PER_COUNT: double ;
41 |
42 | implementation
43 |
44 | function amqp_get_monotonic_timestamp:uint64;
45 | var
46 | perf_count,
47 | perf_frequency : Int64;//LARGE_INTEGER;
48 | begin
49 | //static double NS_PER_COUNT = 0;
50 | if 0 = NS_PER_COUNT then
51 | begin
52 | if not QueryPerformanceFrequency(perf_frequency) then
53 | Exit(0);
54 |
55 | //NS_PER_COUNT := double(AMQP_NS_PER_S / perf_frequency);
56 | NS_PER_COUNT := (AMQP_NS_PER_S / perf_frequency);
57 | end;
58 | if not QueryPerformanceCounter(perf_count) then
59 | Exit(0);
60 |
61 | Result := uint64_t(Round(perf_count * NS_PER_COUNT));
62 | end;
63 |
64 | function amqp_time_from_now(var Atime : Tamqp_time;const Atimeout: Ptimeval):integer;
65 | var
66 | now_ns,
67 | delta_ns : Uint64;
68 | LValue: int;
69 | Lns: Int64;
70 | begin
71 | //assert(nil <> Atime);
72 | if nil = Atimeout then
73 | begin
74 | Atime := Tamqp_time.infinite;
75 | LValue := Integer(AMQP_STATUS_OK);
76 | Exit(LValue);
77 | end;
78 | if (Atimeout.tv_sec < 0) or
79 | (Atimeout.tv_usec < 0) then
80 | begin
81 | LValue := Integer(AMQP_STATUS_INVALID_PARAMETER);
82 | Exit(LValue);
83 | end;
84 |
85 | Lns := Atimeout.tv_sec * AMQP_NS_PER_S;
86 | delta_ns := Lns +
87 | Atimeout.tv_usec * AMQP_NS_PER_US;
88 | now_ns := amqp_get_monotonic_timestamp();
89 |
90 | if 0 = now_ns then
91 | begin
92 | Exit(Integer(AMQP_STATUS_TIMER_FAILURE));
93 | end;
94 |
95 | Atime.time_point_ns := now_ns + delta_ns;
96 |
97 | if (now_ns > Atime.time_point_ns) or
98 | (delta_ns > Atime.time_point_ns) then
99 | begin
100 | Exit(Integer(AMQP_STATUS_INVALID_PARAMETER));
101 | end;
102 | Result := Integer(AMQP_STATUS_OK);
103 | end;
104 |
105 |
106 | function amqp_time_s_from_now(var Atime : Tamqp_time; Aseconds : integer):integer;
107 | var
108 | now_ns,
109 | delta_ns : uint64;
110 | begin
111 | //assert(nil <> Atime);
112 | if 0 >= Aseconds then
113 | begin
114 | Atime := Tamqp_time.infinite;
115 | Exit(Integer(AMQP_STATUS_OK));
116 | end;
117 | now_ns := amqp_get_monotonic_timestamp();
118 | if 0 = now_ns then
119 | begin
120 | Exit(Integer(AMQP_STATUS_TIMER_FAILURE));
121 | end;
122 | delta_ns := uint64_t(Aseconds * AMQP_NS_PER_S);
123 | Atime.time_point_ns := now_ns + delta_ns;
124 | if (now_ns > Atime.time_point_ns) or
125 | (delta_ns > Atime.time_point_ns) then
126 | begin
127 | Exit(Integer(AMQP_STATUS_INVALID_PARAMETER));
128 | end;
129 | Result := Integer(AMQP_STATUS_OK);
130 | end;
131 |
132 |
133 |
134 |
135 |
136 | function amqp_time_ms_until( Atime : Tamqp_time):integer;
137 | var
138 | now_ns,
139 | delta_ns : uint64;
140 | left_ms : integer;
141 | begin
142 | if UINT64_MAX = Atime.time_point_ns then
143 | begin
144 | Exit(-1);
145 | end;
146 | if 0 = Atime.time_point_ns then
147 | begin
148 | Exit(0);
149 | end;
150 | now_ns := amqp_get_monotonic_timestamp();
151 | if 0 = now_ns then
152 | begin
153 | Exit(Integer(AMQP_STATUS_TIMER_FAILURE));
154 | end;
155 | if now_ns >= Atime.time_point_ns then
156 | begin
157 | Exit(0);
158 | end;
159 | delta_ns := Atime.time_point_ns - now_ns;
160 | left_ms := delta_ns div AMQP_NS_PER_MS;
161 | Result := left_ms;
162 | end;
163 |
164 |
165 | function amqp_time_tv_until( Atime : Tamqp_time; Ain: Ptimeval; Aout: PPtimeval):integer;
166 | var
167 | now_ns,
168 | delta_ns : uint64;
169 | begin
170 | assert(Ain <> nil);
171 | if UINT64_MAX = Atime.time_point_ns then
172 | begin
173 | Aout^ := nil;
174 | Exit(Integer(AMQP_STATUS_OK));
175 | end;
176 | if 0 = Atime.time_point_ns then
177 | begin
178 | Ain.tv_sec := 0;
179 | Ain.tv_usec := 0;
180 | Aout^ := Ain;
181 | Exit(Integer(AMQP_STATUS_OK));
182 | end;
183 | now_ns := amqp_get_monotonic_timestamp();
184 | if 0 = now_ns then
185 | begin
186 | Exit(Integer(AMQP_STATUS_TIMER_FAILURE));
187 | end;
188 | if now_ns >= Atime.time_point_ns then
189 | begin
190 | Ain.tv_sec := 0;
191 | Ain.tv_usec := 0;
192 | Aout^ := Ain;
193 | Exit(Integer(AMQP_STATUS_OK));
194 | end;
195 | delta_ns := Atime.time_point_ns - now_ns;
196 | Ain.tv_sec := delta_ns div AMQP_NS_PER_S;
197 | Ain.tv_usec :=(delta_ns mod AMQP_NS_PER_S) div AMQP_NS_PER_US;
198 | Aout^ := Ain;
199 | Result := Integer(AMQP_STATUS_OK);
200 | end;
201 |
202 |
203 | function amqp_time_has_past( Atime : Tamqp_time):integer;
204 | var
205 | now_ns : uint64;
206 | begin
207 | if UINT64_MAX = Atime.time_point_ns then
208 | begin
209 | Exit(Integer(AMQP_STATUS_OK));
210 | end;
211 | now_ns := amqp_get_monotonic_timestamp();
212 | if 0 = now_ns then
213 | begin
214 | Exit(Integer(AMQP_STATUS_TIMER_FAILURE));
215 | end;
216 | if now_ns > Atime.time_point_ns then
217 | begin
218 | Exit(Integer(AMQP_STATUS_TIMEOUT));
219 | end;
220 | Result := Integer(AMQP_STATUS_OK);
221 | end;
222 |
223 |
224 | function amqp_time_first( l, r : Tamqp_time):Tamqp_time;
225 | begin
226 | if l.time_point_ns < r.time_point_ns then
227 | Exit(l);
228 |
229 | Result := r;
230 | end;
231 |
232 |
233 |
234 |
235 | initialization
236 | NS_PER_COUNT := 0;
237 |
238 | end.
239 |
--------------------------------------------------------------------------------
/amqp_tcp_socket.pas:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sonadorje/rabbitmq-delphi/e4931fc10be22d84d0bafe83e3349403dbeb3b9b/amqp_tcp_socket.pas
--------------------------------------------------------------------------------
/config.inc:
--------------------------------------------------------------------------------
1 | {$DEFINE _WIN32}
2 | //{$DEFINE CrossSocket}
3 | {$define HAVE_SELECT}
4 | {$define _DEBUG_}
5 |
6 |
--------------------------------------------------------------------------------