From 74478b24b0542e8b454f60cb99ff78099f550464 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Thu, 31 Oct 2019 14:04:25 -0700 Subject: [PATCH 01/10] add librabbitmq binaries for macos for testing central controller --- ext/librabbitmq/macos/include/amqp.h | 2538 +++++++++++++++++ ext/librabbitmq/macos/include/amqp_framing.h | 1144 ++++++++ .../macos/include/amqp_tcp_socket.h | 68 + ext/librabbitmq/macos/lib/librabbitmq.a | Bin 0 -> 95704 bytes make-mac.mk | 3 +- 5 files changed, 3752 insertions(+), 1 deletion(-) create mode 100644 ext/librabbitmq/macos/include/amqp.h create mode 100644 ext/librabbitmq/macos/include/amqp_framing.h create mode 100644 ext/librabbitmq/macos/include/amqp_tcp_socket.h create mode 100644 ext/librabbitmq/macos/lib/librabbitmq.a diff --git a/ext/librabbitmq/macos/include/amqp.h b/ext/librabbitmq/macos/include/amqp.h new file mode 100644 index 000000000..2983b1665 --- /dev/null +++ b/ext/librabbitmq/macos/include/amqp.h @@ -0,0 +1,2538 @@ +/** \file */ +/* + * ***** BEGIN LICENSE BLOCK ***** + * Version: MIT + * + * Portions created by Alan Antonuk are Copyright (c) 2012-2014 + * Alan Antonuk. All Rights Reserved. + * + * Portions created by VMware are Copyright (c) 2007-2012 VMware, Inc. + * All Rights Reserved. + * + * Portions created by Tony Garnock-Jones are Copyright (c) 2009-2010 + * VMware, Inc. and Tony Garnock-Jones. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * ***** END LICENSE BLOCK ***** + */ + +#ifndef AMQP_H +#define AMQP_H + +/** \cond HIDE_FROM_DOXYGEN */ + +#ifdef __cplusplus +#define AMQP_BEGIN_DECLS extern "C" { +#define AMQP_END_DECLS } +#else +#define AMQP_BEGIN_DECLS +#define AMQP_END_DECLS +#endif + +/* + * \internal + * Important API decorators: + * AMQP_PUBLIC_FUNCTION - a public API function + * AMQP_PUBLIC_VARIABLE - a public API external variable + * AMQP_CALL - calling convension (used on Win32) + */ + +#if defined(_WIN32) && defined(_MSC_VER) +#if defined(AMQP_BUILD) && !defined(AMQP_STATIC) +#define AMQP_PUBLIC_FUNCTION __declspec(dllexport) +#define AMQP_PUBLIC_VARIABLE __declspec(dllexport) extern +#else +#define AMQP_PUBLIC_FUNCTION +#if !defined(AMQP_STATIC) +#define AMQP_PUBLIC_VARIABLE __declspec(dllimport) extern +#else +#define AMQP_PUBLIC_VARIABLE extern +#endif +#endif +#define AMQP_CALL __cdecl + +#elif defined(_WIN32) && defined(__BORLANDC__) +#if defined(AMQP_BUILD) && !defined(AMQP_STATIC) +#define AMQP_PUBLIC_FUNCTION __declspec(dllexport) +#define AMQP_PUBLIC_VARIABLE __declspec(dllexport) extern +#else +#define AMQP_PUBLIC_FUNCTION +#if !defined(AMQP_STATIC) +#define AMQP_PUBLIC_VARIABLE __declspec(dllimport) extern +#else +#define AMQP_PUBLIC_VARIABLE extern +#endif +#endif +#define AMQP_CALL __cdecl + +#elif defined(_WIN32) && defined(__MINGW32__) +#if defined(AMQP_BUILD) && !defined(AMQP_STATIC) +#define AMQP_PUBLIC_FUNCTION __declspec(dllexport) +#define AMQP_PUBLIC_VARIABLE __declspec(dllexport) extern +#else +#define AMQP_PUBLIC_FUNCTION +#if !defined(AMQP_STATIC) +#define AMQP_PUBLIC_VARIABLE __declspec(dllimport) extern +#else +#define AMQP_PUBLIC_VARIABLE extern +#endif +#endif +#define AMQP_CALL __cdecl + +#elif defined(_WIN32) && defined(__CYGWIN__) +#if defined(AMQP_BUILD) && !defined(AMQP_STATIC) +#define AMQP_PUBLIC_FUNCTION __declspec(dllexport) +#define AMQP_PUBLIC_VARIABLE __declspec(dllexport) +#else +#define AMQP_PUBLIC_FUNCTION +#if !defined(AMQP_STATIC) +#define AMQP_PUBLIC_VARIABLE __declspec(dllimport) extern +#else +#define AMQP_PUBLIC_VARIABLE extern +#endif +#endif +#define AMQP_CALL __cdecl + +#elif defined(__GNUC__) && __GNUC__ >= 4 +#define AMQP_PUBLIC_FUNCTION __attribute__((visibility("default"))) +#define AMQP_PUBLIC_VARIABLE __attribute__((visibility("default"))) extern +#define AMQP_CALL +#else +#define AMQP_PUBLIC_FUNCTION +#define AMQP_PUBLIC_VARIABLE extern +#define AMQP_CALL +#endif + +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) +#define AMQP_DEPRECATED(function) function __attribute__((__deprecated__)) +#elif defined(_MSC_VER) +#define AMQP_DEPRECATED(function) __declspec(deprecated) function +#else +#define AMQP_DEPRECATED(function) +#endif + +/* Define ssize_t on Win32/64 platforms + See: http://lists.cs.uiuc.edu/pipermail/llvmdev/2010-April/030649.html for + details + */ +#if !defined(_W64) +#if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +#define _W64 __w64 +#else +#define _W64 +#endif +#endif + +#ifdef _MSC_VER +#ifdef _WIN64 +typedef __int64 ssize_t; +#else +typedef _W64 int ssize_t; +#endif +#endif + +#if defined(_WIN32) && defined(__MINGW32__) +#include +#endif + +/** \endcond */ + +#include +#include + +struct timeval; + +AMQP_BEGIN_DECLS + +/** + * \def AMQP_VERSION_MAJOR + * + * Major library version number compile-time constant + * + * The major version is incremented when backwards incompatible API changes + * are made. + * + * \sa AMQP_VERSION, AMQP_VERSION_STRING + * + * \since v0.4.0 + */ + +/** + * \def AMQP_VERSION_MINOR + * + * Minor library version number compile-time constant + * + * The minor version is incremented when new APIs are added. Existing APIs + * are left alone. + * + * \sa AMQP_VERSION, AMQP_VERSION_STRING + * + * \since v0.4.0 + */ + +/** + * \def AMQP_VERSION_PATCH + * + * Patch library version number compile-time constant + * + * The patch version is incremented when library code changes, but the API + * is not changed. + * + * \sa AMQP_VERSION, AMQP_VERSION_STRING + * + * \since v0.4.0 + */ + +/** + * \def AMQP_VERSION_IS_RELEASE + * + * Version constant set to 1 for tagged release, 0 otherwise + * + * NOTE: versions that are not tagged releases are not guaranteed to be API/ABI + * compatible with older releases, and may change commit-to-commit. + * + * \sa AMQP_VERSION, AMQP_VERSION_STRING + * + * \since v0.4.0 + */ +/* + * Developer note: when changing these, be sure to update SOVERSION constants + * in CMakeLists.txt and configure.ac + */ + +#define AMQP_VERSION_MAJOR 0 +#define AMQP_VERSION_MINOR 10 +#define AMQP_VERSION_PATCH 0 +#define AMQP_VERSION_IS_RELEASE 0 + +/** + * \def AMQP_VERSION_CODE + * + * Helper macro to geneate a packed version code suitable for + * comparison with AMQP_VERSION. + * + * \sa amqp_version_number() AMQP_VERSION_MAJOR, AMQP_VERSION_MINOR, + * AMQP_VERSION_PATCH, AMQP_VERSION_IS_RELEASE, AMQP_VERSION + * + * \since v0.6.1 + */ +#define AMQP_VERSION_CODE(major, minor, patch, release) \ + ((major << 24) | (minor << 16) | (patch << 8) | (release)) + +/** + * \def AMQP_VERSION + * + * Packed version number + * + * AMQP_VERSION is a 4-byte unsigned integer with the most significant byte + * set to AMQP_VERSION_MAJOR, the second most significant byte set to + * AMQP_VERSION_MINOR, third most significant byte set to AMQP_VERSION_PATCH, + * and the lowest byte set to AMQP_VERSION_IS_RELEASE. + * + * For example version 2.3.4 which is released version would be encoded as + * 0x02030401 + * + * \sa amqp_version_number() AMQP_VERSION_MAJOR, AMQP_VERSION_MINOR, + * AMQP_VERSION_PATCH, AMQP_VERSION_IS_RELEASE, AMQP_VERSION_CODE + * + * \since v0.4.0 + */ +#define AMQP_VERSION \ + AMQP_VERSION_CODE(AMQP_VERSION_MAJOR, AMQP_VERSION_MINOR, \ + AMQP_VERSION_PATCH, AMQP_VERSION_IS_RELEASE) + +/** \cond HIDE_FROM_DOXYGEN */ +#define AMQ_STRINGIFY(s) AMQ_STRINGIFY_HELPER(s) +#define AMQ_STRINGIFY_HELPER(s) #s + +#define AMQ_VERSION_STRING \ + AMQ_STRINGIFY(AMQP_VERSION_MAJOR) \ + "." AMQ_STRINGIFY(AMQP_VERSION_MINOR) "." AMQ_STRINGIFY(AMQP_VERSION_PATCH) +/** \endcond */ + +/** + * \def AMQP_VERSION_STRING + * + * Version string compile-time constant + * + * Non-released versions of the library will have "-pre" appended to the + * version string + * + * \sa amqp_version() + * + * \since v0.4.0 + */ +#if AMQP_VERSION_IS_RELEASE +#define AMQP_VERSION_STRING AMQ_VERSION_STRING +#else +#define AMQP_VERSION_STRING AMQ_VERSION_STRING "-pre" +#endif + +/** + * Returns the rabbitmq-c version as a packed integer. + * + * See \ref AMQP_VERSION + * + * \return packed 32-bit integer representing version of library at runtime + * + * \sa AMQP_VERSION, amqp_version() + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +uint32_t AMQP_CALL amqp_version_number(void); + +/** + * Returns the rabbitmq-c version as a string. + * + * See \ref AMQP_VERSION_STRING + * + * \return a statically allocated string describing the version of rabbitmq-c. + * + * \sa amqp_version_number(), AMQP_VERSION_STRING, AMQP_VERSION + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +char const *AMQP_CALL amqp_version(void); + +/** + * \def AMQP_DEFAULT_FRAME_SIZE + * + * Default frame size (128Kb) + * + * \sa amqp_login(), amqp_login_with_properties() + * + * \since v0.4.0 + */ +#define AMQP_DEFAULT_FRAME_SIZE 131072 + +/** + * \def AMQP_DEFAULT_MAX_CHANNELS + * + * Default maximum number of channels (2047, RabbitMQ default limit of 2048, + * minus 1 for channel 0). RabbitMQ set a default limit of 2048 channels per + * connection in v3.7.5 to prevent broken clients from leaking too many + * channels. + * + * \sa amqp_login(), amqp_login_with_properties() + * + * \since v0.4.0 + */ +#define AMQP_DEFAULT_MAX_CHANNELS 2047 + +/** + * \def AMQP_DEFAULT_HEARTBEAT + * + * Default heartbeat interval (0, heartbeat disabled) + * + * \sa amqp_login(), amqp_login_with_properties() + * + * \since v0.4.0 + */ +#define AMQP_DEFAULT_HEARTBEAT 0 + +/** + * \def AMQP_DEFAULT_VHOST + * + * Default RabbitMQ vhost: "/" + * + * \sa amqp_login(), amqp_login_with_properties() + * + * \since v0.9.0 + */ +#define AMQP_DEFAULT_VHOST "/" + +/** + * boolean type 0 = false, true otherwise + * + * \since v0.1 + */ +typedef int amqp_boolean_t; + +/** + * Method number + * + * \since v0.1 + */ +typedef uint32_t amqp_method_number_t; + +/** + * Bitmask for flags + * + * \since v0.1 + */ +typedef uint32_t amqp_flags_t; + +/** + * Channel type + * + * \since v0.1 + */ +typedef uint16_t amqp_channel_t; + +/** + * Buffer descriptor + * + * \since v0.1 + */ +typedef struct amqp_bytes_t_ { + size_t len; /**< length of the buffer in bytes */ + void *bytes; /**< pointer to the beginning of the buffer */ +} amqp_bytes_t; + +/** + * Decimal data type + * + * \since v0.1 + */ +typedef struct amqp_decimal_t_ { + uint8_t decimals; /**< the location of the decimal point */ + uint32_t value; /**< the value before the decimal point is applied */ +} amqp_decimal_t; + +/** + * AMQP field table + * + * An AMQP field table is a set of key-value pairs. + * A key is a UTF-8 encoded string up to 128 bytes long, and are not null + * terminated. + * A value can be one of several different datatypes. \sa + * amqp_field_value_kind_t + * + * \sa amqp_table_entry_t + * + * \since v0.1 + */ +typedef struct amqp_table_t_ { + int num_entries; /**< length of entries array */ + struct amqp_table_entry_t_ *entries; /**< an array of table entries */ +} amqp_table_t; + +/** + * An AMQP Field Array + * + * A repeated set of field values, all must be of the same type + * + * \since v0.1 + */ +typedef struct amqp_array_t_ { + int num_entries; /**< Number of entries in the table */ + struct amqp_field_value_t_ *entries; /**< linked list of field values */ +} amqp_array_t; + +/* + 0-9 0-9-1 Qpid/Rabbit Type Remarks +--------------------------------------------------------------------------- + t t Boolean + b b Signed 8-bit + B Unsigned 8-bit + U s Signed 16-bit (A1) + u Unsigned 16-bit + I I I Signed 32-bit + i Unsigned 32-bit + L l Signed 64-bit (B) + l Unsigned 64-bit + f f 32-bit float + d d 64-bit float + D D D Decimal + s Short string (A2) + S S S Long string + A Nested Array + T T T Timestamp (u64) + F F F Nested Table + V V V Void + x Byte array + +Remarks: + + A1, A2: Notice how the types **CONFLICT** here. In Qpid and Rabbit, + 's' means a signed 16-bit integer; in 0-9-1, it means a + short string. + + B: Notice how the signednesses **CONFLICT** here. In Qpid and Rabbit, + 'l' means a signed 64-bit integer; in 0-9-1, it means an unsigned + 64-bit integer. + +I'm going with the Qpid/Rabbit types, where there's a conflict, and +the 0-9-1 types otherwise. 0-8 is a subset of 0-9, which is a subset +of the other two, so this will work for both 0-8 and 0-9-1 branches of +the code. +*/ + +/** + * A field table value + * + * \since v0.1 + */ +typedef struct amqp_field_value_t_ { + uint8_t kind; /**< the type of the entry /sa amqp_field_value_kind_t */ + union { + amqp_boolean_t boolean; /**< boolean type AMQP_FIELD_KIND_BOOLEAN */ + int8_t i8; /**< int8_t type AMQP_FIELD_KIND_I8 */ + uint8_t u8; /**< uint8_t type AMQP_FIELD_KIND_U8 */ + int16_t i16; /**< int16_t type AMQP_FIELD_KIND_I16 */ + uint16_t u16; /**< uint16_t type AMQP_FIELD_KIND_U16 */ + int32_t i32; /**< int32_t type AMQP_FIELD_KIND_I32 */ + uint32_t u32; /**< uint32_t type AMQP_FIELD_KIND_U32 */ + int64_t i64; /**< int64_t type AMQP_FIELD_KIND_I64 */ + uint64_t u64; /**< uint64_t type AMQP_FIELD_KIND_U64, + AMQP_FIELD_KIND_TIMESTAMP */ + float f32; /**< float type AMQP_FIELD_KIND_F32 */ + double f64; /**< double type AMQP_FIELD_KIND_F64 */ + amqp_decimal_t decimal; /**< amqp_decimal_t AMQP_FIELD_KIND_DECIMAL */ + amqp_bytes_t bytes; /**< amqp_bytes_t type AMQP_FIELD_KIND_UTF8, + AMQP_FIELD_KIND_BYTES */ + amqp_table_t table; /**< amqp_table_t type AMQP_FIELD_KIND_TABLE */ + amqp_array_t array; /**< amqp_array_t type AMQP_FIELD_KIND_ARRAY */ + } value; /**< a union of the value */ +} amqp_field_value_t; + +/** + * An entry in a field-table + * + * \sa amqp_table_encode(), amqp_table_decode(), amqp_table_clone() + * + * \since v0.1 + */ +typedef struct amqp_table_entry_t_ { + amqp_bytes_t key; /**< the table entry key. Its a null-terminated UTF-8 + * string, with a maximum size of 128 bytes */ + amqp_field_value_t value; /**< the table entry values */ +} amqp_table_entry_t; + +/** + * Field value types + * + * \since v0.1 + */ +typedef enum { + AMQP_FIELD_KIND_BOOLEAN = + 't', /**< boolean type. 0 = false, 1 = true @see amqp_boolean_t */ + AMQP_FIELD_KIND_I8 = 'b', /**< 8-bit signed integer, datatype: int8_t */ + AMQP_FIELD_KIND_U8 = 'B', /**< 8-bit unsigned integer, datatype: uint8_t */ + AMQP_FIELD_KIND_I16 = 's', /**< 16-bit signed integer, datatype: int16_t */ + AMQP_FIELD_KIND_U16 = 'u', /**< 16-bit unsigned integer, datatype: uint16_t */ + AMQP_FIELD_KIND_I32 = 'I', /**< 32-bit signed integer, datatype: int32_t */ + AMQP_FIELD_KIND_U32 = 'i', /**< 32-bit unsigned integer, datatype: uint32_t */ + AMQP_FIELD_KIND_I64 = 'l', /**< 64-bit signed integer, datatype: int64_t */ + AMQP_FIELD_KIND_U64 = 'L', /**< 64-bit unsigned integer, datatype: uint64_t */ + AMQP_FIELD_KIND_F32 = + 'f', /**< single-precision floating point value, datatype: float */ + AMQP_FIELD_KIND_F64 = + 'd', /**< double-precision floating point value, datatype: double */ + AMQP_FIELD_KIND_DECIMAL = + 'D', /**< amqp-decimal value, datatype: amqp_decimal_t */ + AMQP_FIELD_KIND_UTF8 = 'S', /**< UTF-8 null-terminated character string, + datatype: amqp_bytes_t */ + AMQP_FIELD_KIND_ARRAY = 'A', /**< field array (repeated values of another + datatype. datatype: amqp_array_t */ + AMQP_FIELD_KIND_TIMESTAMP = 'T', /**< 64-bit timestamp. datatype uint64_t */ + AMQP_FIELD_KIND_TABLE = 'F', /**< field table. encapsulates a table inside a + table entry. datatype: amqp_table_t */ + AMQP_FIELD_KIND_VOID = 'V', /**< empty entry */ + AMQP_FIELD_KIND_BYTES = + 'x' /**< unformatted byte string, datatype: amqp_bytes_t */ +} amqp_field_value_kind_t; + +/** + * A list of allocation blocks + * + * \since v0.1 + */ +typedef struct amqp_pool_blocklist_t_ { + int num_blocks; /**< Number of blocks in the block list */ + void **blocklist; /**< Array of memory blocks */ +} amqp_pool_blocklist_t; + +/** + * A memory pool + * + * \since v0.1 + */ +typedef struct amqp_pool_t_ { + size_t pagesize; /**< the size of the page in bytes. Allocations less than or + * equal to this size are allocated in the pages block list. + * Allocations greater than this are allocated in their own + * own block in the large_blocks block list */ + + amqp_pool_blocklist_t pages; /**< blocks that are the size of pagesize */ + amqp_pool_blocklist_t + large_blocks; /**< allocations larger than the pagesize */ + + int next_page; /**< an index to the next unused page block */ + char *alloc_block; /**< pointer to the current allocation block */ + size_t alloc_used; /**< number of bytes in the current allocation block that + has been used */ +} amqp_pool_t; + +/** + * An amqp method + * + * \since v0.1 + */ +typedef struct amqp_method_t_ { + amqp_method_number_t id; /**< the method id number */ + void *decoded; /**< pointer to the decoded method, + * cast to the appropriate type to use */ +} amqp_method_t; + +/** + * An AMQP frame + * + * \since v0.1 + */ +typedef struct amqp_frame_t_ { + uint8_t frame_type; /**< frame type. The types: + * - AMQP_FRAME_METHOD - use the method union member + * - AMQP_FRAME_HEADER - use the properties union member + * - AMQP_FRAME_BODY - use the body_fragment union member + */ + amqp_channel_t channel; /**< the channel the frame was received on */ + union { + amqp_method_t + method; /**< a method, use if frame_type == AMQP_FRAME_METHOD */ + struct { + uint16_t class_id; /**< the class for the properties */ + uint64_t body_size; /**< size of the body in bytes */ + void *decoded; /**< the decoded properties */ + amqp_bytes_t raw; /**< amqp-encoded properties structure */ + } properties; /**< message header, a.k.a., properties, + use if frame_type == AMQP_FRAME_HEADER */ + amqp_bytes_t body_fragment; /**< a body fragment, use if frame_type == + AMQP_FRAME_BODY */ + struct { + uint8_t transport_high; /**< @internal first byte of handshake */ + uint8_t transport_low; /**< @internal second byte of handshake */ + uint8_t protocol_version_major; /**< @internal third byte of handshake */ + uint8_t protocol_version_minor; /**< @internal fourth byte of handshake */ + } protocol_header; /**< Used only when doing the initial handshake with the + broker, don't use otherwise */ + } payload; /**< the payload of the frame */ +} amqp_frame_t; + +/** + * Response type + * + * \since v0.1 + */ +typedef enum amqp_response_type_enum_ { + AMQP_RESPONSE_NONE = 0, /**< the library got an EOF from the socket */ + AMQP_RESPONSE_NORMAL, /**< response normal, the RPC completed successfully */ + AMQP_RESPONSE_LIBRARY_EXCEPTION, /**< library error, an error occurred in the + library, examine the library_error */ + AMQP_RESPONSE_SERVER_EXCEPTION /**< server exception, the broker returned an + error, check replay */ +} amqp_response_type_enum; + +/** + * Reply from a RPC method on the broker + * + * \since v0.1 + */ +typedef struct amqp_rpc_reply_t_ { + amqp_response_type_enum reply_type; /**< the reply type: + * - AMQP_RESPONSE_NORMAL - the RPC + * completed successfully + * - AMQP_RESPONSE_SERVER_EXCEPTION - the + * broker returned + * an exception, check the reply field + * - AMQP_RESPONSE_LIBRARY_EXCEPTION - the + * library + * encountered an error, check the + * library_error field + */ + amqp_method_t reply; /**< in case of AMQP_RESPONSE_SERVER_EXCEPTION this + * field will be set to the method returned from the + * broker */ + int library_error; /**< in case of AMQP_RESPONSE_LIBRARY_EXCEPTION this + * field will be set to an error code. An error + * string can be retrieved using amqp_error_string */ +} amqp_rpc_reply_t; + +/** + * SASL method type + * + * \since v0.1 + */ +typedef enum amqp_sasl_method_enum_ { + AMQP_SASL_METHOD_UNDEFINED = -1, /**< Invalid SASL method */ + AMQP_SASL_METHOD_PLAIN = + 0, /**< the PLAIN SASL method for authentication to the broker */ + AMQP_SASL_METHOD_EXTERNAL = + 1 /**< the EXTERNAL SASL method for authentication to the broker */ +} amqp_sasl_method_enum; + +/** + * connection state object + * + * \since v0.1 + */ +typedef struct amqp_connection_state_t_ *amqp_connection_state_t; + +/** + * Socket object + * + * \since v0.4.0 + */ +typedef struct amqp_socket_t_ amqp_socket_t; + +/** + * Status codes + * + * \since v0.4.0 + */ +/* NOTE: When updating this enum, update the strings in librabbitmq/amqp_api.c + */ +typedef enum amqp_status_enum_ { + AMQP_STATUS_OK = 0x0, /**< Operation successful */ + AMQP_STATUS_NO_MEMORY = -0x0001, /**< Memory allocation + failed */ + AMQP_STATUS_BAD_AMQP_DATA = -0x0002, /**< Incorrect or corrupt + data was received from + the broker. This is a + protocol error. */ + AMQP_STATUS_UNKNOWN_CLASS = -0x0003, /**< An unknown AMQP class + was received. This is + a protocol error. */ + AMQP_STATUS_UNKNOWN_METHOD = -0x0004, /**< An unknown AMQP method + was received. This is + a protocol error. */ + AMQP_STATUS_HOSTNAME_RESOLUTION_FAILED = -0x0005, /**< Unable to resolve the + * hostname */ + AMQP_STATUS_INCOMPATIBLE_AMQP_VERSION = -0x0006, /**< The broker advertised + an incompaible AMQP + version */ + AMQP_STATUS_CONNECTION_CLOSED = -0x0007, /**< The connection to the + broker has been closed + */ + AMQP_STATUS_BAD_URL = -0x0008, /**< malformed AMQP URL */ + AMQP_STATUS_SOCKET_ERROR = -0x0009, /**< A socket error + occurred */ + AMQP_STATUS_INVALID_PARAMETER = -0x000A, /**< An invalid parameter + was passed into the + function */ + AMQP_STATUS_TABLE_TOO_BIG = -0x000B, /**< The amqp_table_t object + cannot be serialized + because the output + buffer is too small */ + AMQP_STATUS_WRONG_METHOD = -0x000C, /**< The wrong method was + received */ + AMQP_STATUS_TIMEOUT = -0x000D, /**< Operation timed out */ + AMQP_STATUS_TIMER_FAILURE = -0x000E, /**< The underlying system + timer facility failed */ + AMQP_STATUS_HEARTBEAT_TIMEOUT = -0x000F, /**< Timed out waiting for + heartbeat */ + AMQP_STATUS_UNEXPECTED_STATE = -0x0010, /**< Unexpected protocol + state */ + AMQP_STATUS_SOCKET_CLOSED = -0x0011, /**< Underlying socket is + closed */ + AMQP_STATUS_SOCKET_INUSE = -0x0012, /**< Underlying socket is + already open */ + AMQP_STATUS_BROKER_UNSUPPORTED_SASL_METHOD = -0x0013, /**< Broker does not + support the requested + SASL mechanism */ + AMQP_STATUS_UNSUPPORTED = -0x0014, /**< Parameter is unsupported + in this version */ + _AMQP_STATUS_NEXT_VALUE = -0x0015, /**< Internal value */ + + AMQP_STATUS_TCP_ERROR = -0x0100, /**< A generic TCP error + occurred */ + AMQP_STATUS_TCP_SOCKETLIB_INIT_ERROR = -0x0101, /**< An error occurred trying + to initialize the + socket library*/ + _AMQP_STATUS_TCP_NEXT_VALUE = -0x0102, /**< Internal value */ + + AMQP_STATUS_SSL_ERROR = -0x0200, /**< A generic SSL error + occurred. */ + AMQP_STATUS_SSL_HOSTNAME_VERIFY_FAILED = -0x0201, /**< SSL validation of + hostname against + peer certificate + failed */ + AMQP_STATUS_SSL_PEER_VERIFY_FAILED = -0x0202, /**< SSL validation of peer + certificate failed. */ + AMQP_STATUS_SSL_CONNECTION_FAILED = -0x0203, /**< SSL handshake failed. */ + _AMQP_STATUS_SSL_NEXT_VALUE = -0x0204 /**< Internal value */ +} amqp_status_enum; + +/** + * AMQP delivery modes. + * Use these values for the #amqp_basic_properties_t::delivery_mode field. + * + * \since v0.5 + */ +typedef enum { + AMQP_DELIVERY_NONPERSISTENT = 1, /**< Non-persistent message */ + AMQP_DELIVERY_PERSISTENT = 2 /**< Persistent message */ +} amqp_delivery_mode_enum; + +AMQP_END_DECLS + +#include + +AMQP_BEGIN_DECLS + +/** + * Empty bytes structure + * + * \since v0.2 + */ +AMQP_PUBLIC_VARIABLE const amqp_bytes_t amqp_empty_bytes; + +/** + * Empty table structure + * + * \since v0.2 + */ +AMQP_PUBLIC_VARIABLE const amqp_table_t amqp_empty_table; + +/** + * Empty table array structure + * + * \since v0.2 + */ +AMQP_PUBLIC_VARIABLE const amqp_array_t amqp_empty_array; + +/* Compatibility macros for the above, to avoid the need to update + code written against earlier versions of librabbitmq. */ + +/** + * \def AMQP_EMPTY_BYTES + * + * Deprecated, use \ref amqp_empty_bytes instead + * + * \deprecated use \ref amqp_empty_bytes instead + * + * \since v0.1 + */ +#define AMQP_EMPTY_BYTES amqp_empty_bytes + +/** + * \def AMQP_EMPTY_TABLE + * + * Deprecated, use \ref amqp_empty_table instead + * + * \deprecated use \ref amqp_empty_table instead + * + * \since v0.1 + */ +#define AMQP_EMPTY_TABLE amqp_empty_table + +/** + * \def AMQP_EMPTY_ARRAY + * + * Deprecated, use \ref amqp_empty_array instead + * + * \deprecated use \ref amqp_empty_array instead + * + * \since v0.1 + */ +#define AMQP_EMPTY_ARRAY amqp_empty_array + +/** + * Initializes an amqp_pool_t memory allocation pool for use + * + * Readies an allocation pool for use. An amqp_pool_t + * must be initialized before use + * + * \param [in] pool the amqp_pool_t structure to initialize. + * Calling this function on a pool a pool that has + * already been initialized will result in undefined + * behavior + * \param [in] pagesize the unit size that the pool will allocate + * memory chunks in. Anything allocated against the pool + * with a requested size will be carved out of a block + * this size. Allocations larger than this will be + * allocated individually + * + * \sa recycle_amqp_pool(), empty_amqp_pool(), amqp_pool_alloc(), + * amqp_pool_alloc_bytes(), amqp_pool_t + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +void AMQP_CALL init_amqp_pool(amqp_pool_t *pool, size_t pagesize); + +/** + * Recycles an amqp_pool_t memory allocation pool + * + * Recycles the space allocate by the pool + * + * This invalidates all allocations made against the pool before this call is + * made, any use of any allocations made before recycle_amqp_pool() is called + * will result in undefined behavior. + * + * Note: this may or may not release memory, to force memory to be released + * call empty_amqp_pool(). + * + * \param [in] pool the amqp_pool_t to recycle + * + * \sa recycle_amqp_pool(), empty_amqp_pool(), amqp_pool_alloc(), + * amqp_pool_alloc_bytes() + * + * \since v0.1 + * + */ +AMQP_PUBLIC_FUNCTION +void AMQP_CALL recycle_amqp_pool(amqp_pool_t *pool); + +/** + * Empties an amqp memory pool + * + * Releases all memory associated with an allocation pool + * + * \param [in] pool the amqp_pool_t to empty + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +void AMQP_CALL empty_amqp_pool(amqp_pool_t *pool); + +/** + * Allocates a block of memory from an amqp_pool_t memory pool + * + * Memory will be aligned on a 8-byte boundary. If a 0-length allocation is + * requested, a NULL pointer will be returned. + * + * \param [in] pool the allocation pool to allocate the memory from + * \param [in] amount the size of the allocation in bytes. + * \return a pointer to the memory block, or NULL if the allocation cannot + * be satisfied. + * + * \sa init_amqp_pool(), recycle_amqp_pool(), empty_amqp_pool(), + * amqp_pool_alloc_bytes() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +void *AMQP_CALL amqp_pool_alloc(amqp_pool_t *pool, size_t amount); + +/** + * Allocates a block of memory from an amqp_pool_t to an amqp_bytes_t + * + * Memory will be aligned on a 8-byte boundary. If a 0-length allocation is + * requested, output.bytes = NULL. + * + * \param [in] pool the allocation pool to allocate the memory from + * \param [in] amount the size of the allocation in bytes + * \param [in] output the location to store the pointer. On success + * output.bytes will be set to the beginning of the buffer + * output.len will be set to amount + * On error output.bytes will be set to NULL and output.len + * set to 0 + * + * \sa init_amqp_pool(), recycle_amqp_pool(), empty_amqp_pool(), + * amqp_pool_alloc() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +void AMQP_CALL amqp_pool_alloc_bytes(amqp_pool_t *pool, size_t amount, + amqp_bytes_t *output); + +/** + * Wraps a c string in an amqp_bytes_t + * + * Takes a string, calculates its length and creates an + * amqp_bytes_t that points to it. The string is not duplicated. + * + * For a given input cstr, The amqp_bytes_t output.bytes is the + * same as cstr, output.len is the length of the string not including + * the \0 terminator + * + * This function uses strlen() internally so cstr must be properly + * terminated + * + * \param [in] cstr the c string to wrap + * \return an amqp_bytes_t that describes the string + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +amqp_bytes_t AMQP_CALL amqp_cstring_bytes(char const *cstr); + +/** + * Duplicates an amqp_bytes_t buffer. + * + * The buffer is cloned and the contents copied. + * + * The memory associated with the output is allocated + * with amqp_bytes_malloc() and should be freed with + * amqp_bytes_free() + * + * \param [in] src + * \return a clone of the src + * + * \sa amqp_bytes_free(), amqp_bytes_malloc() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +amqp_bytes_t AMQP_CALL amqp_bytes_malloc_dup(amqp_bytes_t src); + +/** + * Allocates a amqp_bytes_t buffer + * + * Creates an amqp_bytes_t buffer of the specified amount, the buffer should be + * freed using amqp_bytes_free() + * + * \param [in] amount the size of the buffer in bytes + * \returns an amqp_bytes_t with amount bytes allocated. + * output.bytes will be set to NULL on error + * + * \sa amqp_bytes_free(), amqp_bytes_malloc_dup() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +amqp_bytes_t AMQP_CALL amqp_bytes_malloc(size_t amount); + +/** + * Frees an amqp_bytes_t buffer + * + * Frees a buffer allocated with amqp_bytes_malloc() or amqp_bytes_malloc_dup() + * + * Calling amqp_bytes_free on buffers not allocated with one + * of those two functions will result in undefined behavior + * + * \param [in] bytes the buffer to free + * + * \sa amqp_bytes_malloc(), amqp_bytes_malloc_dup() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +void AMQP_CALL amqp_bytes_free(amqp_bytes_t bytes); + +/** + * Allocate and initialize a new amqp_connection_state_t object + * + * amqp_connection_state_t objects created with this function + * should be freed with amqp_destroy_connection() + * + * \returns an opaque pointer on success, NULL or 0 on failure. + * + * \sa amqp_destroy_connection() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +amqp_connection_state_t AMQP_CALL amqp_new_connection(void); + +/** + * Get the underlying socket descriptor for the connection + * + * \warning Use the socket returned from this function carefully, incorrect use + * of the socket outside of the library will lead to undefined behavior. + * Additionally rabbitmq-c may use the socket differently version-to-version, + * what may work in one version, may break in the next version. Be sure to + * throughly test any applications that use the socket returned by this + * function especially when using a newer version of rabbitmq-c + * + * \param [in] state the connection object + * \returns the socket descriptor if one has been set, -1 otherwise + * + * \sa amqp_tcp_socket_new(), amqp_ssl_socket_new(), amqp_socket_open() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_get_sockfd(amqp_connection_state_t state); + +/** + * Deprecated, use amqp_tcp_socket_new() or amqp_ssl_socket_new() + * + * \deprecated Use amqp_tcp_socket_new() or amqp_ssl_socket_new() + * + * Sets the socket descriptor associated with the connection. The socket + * should be connected to a broker, and should not be read to or written from + * before calling this function. A socket descriptor can be created and opened + * using amqp_open_socket() + * + * \param [in] state the connection object + * \param [in] sockfd the socket + * + * \sa amqp_open_socket(), amqp_tcp_socket_new(), amqp_ssl_socket_new() + * + * \since v0.1 + */ +AMQP_DEPRECATED(AMQP_PUBLIC_FUNCTION void AMQP_CALL + amqp_set_sockfd(amqp_connection_state_t state, int sockfd)); + +/** + * Tune client side parameters + * + * \warning This function may call abort() if the connection is in a certain + * state. As such it should probably not be called code outside the library. + * connection parameters should be specified when calling amqp_login() or + * amqp_login_with_properties() + * + * This function changes channel_max, frame_max, and heartbeat parameters, on + * the client side only. It does not try to renegotiate these parameters with + * the broker. Using this function will lead to unexpected results. + * + * \param [in] state the connection object + * \param [in] channel_max the maximum number of channels. + * The largest this can be is 65535 + * \param [in] frame_max the maximum size of an frame. + * The smallest this can be is 4096 + * The largest this can be is 2147483647 + * Unless you know what you're doing the recommended + * size is 131072 or 128KB + * \param [in] heartbeat the number of seconds between heartbeats + * + * \return AMQP_STATUS_OK on success, an amqp_status_enum value otherwise. + * Possible error codes include: + * - AMQP_STATUS_NO_MEMORY memory allocation failed. + * - AMQP_STATUS_TIMER_FAILURE the underlying system timer indicated it + * failed. + * + * \sa amqp_login(), amqp_login_with_properties() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_tune_connection(amqp_connection_state_t state, + int channel_max, int frame_max, + int heartbeat); + +/** + * Get the maximum number of channels the connection can handle + * + * The maximum number of channels is set when connection negotiation takes + * place in amqp_login() or amqp_login_with_properties(). + * + * \param [in] state the connection object + * \return the maximum number of channels. 0 if there is no limit + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_get_channel_max(amqp_connection_state_t state); + +/** + * Get the maximum size of an frame the connection can handle + * + * The maximum size of an frame is set when connection negotiation takes + * place in amqp_login() or amqp_login_with_properties(). + * + * \param [in] state the connection object + * \return the maximum size of an frame. + * + * \since v0.6 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_get_frame_max(amqp_connection_state_t state); + +/** + * Get the number of seconds between heartbeats of the connection + * + * The number of seconds between heartbeats is set when connection + * negotiation takes place in amqp_login() or amqp_login_with_properties(). + * + * \param [in] state the connection object + * \return the number of seconds between heartbeats. + * + * \since v0.6 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_get_heartbeat(amqp_connection_state_t state); + +/** + * Destroys an amqp_connection_state_t object + * + * Destroys a amqp_connection_state_t object that was created with + * amqp_new_connection(). If the connection with the broker is open, it will be + * implicitly closed with a reply code of 200 (success). Any memory that + * would be freed with amqp_maybe_release_buffers() or + * amqp_maybe_release_buffers_on_channel() will be freed, and use of that + * memory will caused undefined behavior. + * + * \param [in] state the connection object + * \return AMQP_STATUS_OK on success. amqp_status_enum value failure + * + * \sa amqp_new_connection() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_destroy_connection(amqp_connection_state_t state); + +/** + * Process incoming data + * + * \warning This is a low-level function intended for those who want to + * have greater control over input and output over the socket from the + * broker. Correctly using this function requires in-depth knowledge of AMQP + * and rabbitmq-c. + * + * For a given buffer of data received from the broker, decode the first + * frame in the buffer. If more than one frame is contained in the input buffer + * the return value will be less than the received_data size, the caller should + * adjust received_data buffer descriptor to point to the beginning of the + * buffer + the return value. + * + * \param [in] state the connection object + * \param [in] received_data a buffer of data received from the broker. The + * function will return the number of bytes of the buffer it used. The + * function copies these bytes to an internal buffer: this part of the buffer + * may be reused after this function successfully completes. + * \param [in,out] decoded_frame caller should pass in a pointer to an + * amqp_frame_t struct. If there is enough data in received_data for a + * complete frame, decoded_frame->frame_type will be set to something OTHER + * than 0. decoded_frame may contain members pointing to memory owned by + * the state object. This memory can be recycled with + * amqp_maybe_release_buffers() or amqp_maybe_release_buffers_on_channel(). + * \return number of bytes consumed from received_data or 0 if a 0-length + * buffer was passed. A negative return value indicates failure. Possible + * errors: + * - AMQP_STATUS_NO_MEMORY failure in allocating memory. The library is likely + * in an indeterminate state making recovery unlikely. Client should note the + * error and terminate the application + * - AMQP_STATUS_BAD_AMQP_DATA bad AMQP data was received. The connection + * should be shutdown immediately + * - AMQP_STATUS_UNKNOWN_METHOD: an unknown method was received from the + * broker. This is likely a protocol error and the connection should be + * shutdown immediately + * - AMQP_STATUS_UNKNOWN_CLASS: a properties frame with an unknown class + * was received from the broker. This is likely a protocol error and the + * connection should be shutdown immediately + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_handle_input(amqp_connection_state_t state, + amqp_bytes_t received_data, + amqp_frame_t *decoded_frame); + +/** + * Check to see if connection memory can be released + * + * \deprecated This function is deprecated in favor of + * amqp_maybe_release_buffers() or amqp_maybe_release_buffers_on_channel() + * + * Checks the state of an amqp_connection_state_t object to see if + * amqp_release_buffers() can be called successfully. + * + * \param [in] state the connection object + * \returns TRUE if the buffers can be released FALSE otherwise + * + * \sa amqp_release_buffers() amqp_maybe_release_buffers() + * amqp_maybe_release_buffers_on_channel() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +amqp_boolean_t AMQP_CALL amqp_release_buffers_ok(amqp_connection_state_t state); + +/** + * Release amqp_connection_state_t owned memory + * + * \deprecated This function is deprecated in favor of + * amqp_maybe_release_buffers() or amqp_maybe_release_buffers_on_channel() + * + * \warning caller should ensure amqp_release_buffers_ok() returns true before + * calling this function. Failure to do so may result in abort() being called. + * + * Release memory owned by the amqp_connection_state_t for reuse by the + * library. Use of any memory returned by the library before this function is + * called will result in undefined behavior. + * + * \note internally rabbitmq-c tries to reuse memory when possible. As a result + * its possible calling this function may not have a noticeable effect on + * memory usage. + * + * \param [in] state the connection object + * + * \sa amqp_release_buffers_ok() amqp_maybe_release_buffers() + * amqp_maybe_release_buffers_on_channel() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +void AMQP_CALL amqp_release_buffers(amqp_connection_state_t state); + +/** + * Release amqp_connection_state_t owned memory + * + * Release memory owned by the amqp_connection_state_t object related to any + * channel, allowing reuse by the library. Use of any memory returned by the + * library before this function is called with result in undefined behavior. + * + * \note internally rabbitmq-c tries to reuse memory when possible. As a result + * its possible calling this function may not have a noticeable effect on + * memory usage. + * + * \param [in] state the connection object + * + * \sa amqp_maybe_release_buffers_on_channel() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +void AMQP_CALL amqp_maybe_release_buffers(amqp_connection_state_t state); + +/** + * Release amqp_connection_state_t owned memory related to a channel + * + * Release memory owned by the amqp_connection_state_t object related to the + * specified channel, allowing reuse by the library. Use of any memory returned + * the library for a specific channel will result in undefined behavior. + * + * \note internally rabbitmq-c tries to reuse memory when possible. As a result + * its possible calling this function may not have a noticeable effect on + * memory usage. + * + * \param [in] state the connection object + * \param [in] channel the channel specifier for which memory should be + * released. Note that the library does not care about the state of the + * channel when calling this function + * + * \sa amqp_maybe_release_buffers() + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +void AMQP_CALL amqp_maybe_release_buffers_on_channel( + amqp_connection_state_t state, amqp_channel_t channel); + +/** + * Send a frame to the broker + * + * \param [in] state the connection object + * \param [in] frame the frame to send to the broker + * \return AMQP_STATUS_OK on success, an amqp_status_enum value on error. + * Possible error codes: + * - AMQP_STATUS_BAD_AMQP_DATA the serialized form of the method or + * properties was too large to fit in a single AMQP frame, or the + * method contains an invalid value. The frame was not sent. + * - AMQP_STATUS_TABLE_TOO_BIG the serialized form of an amqp_table_t is + * too large to fit in a single AMQP frame. Frame was not sent. + * - AMQP_STATUS_UNKNOWN_METHOD an invalid method type was passed in + * - AMQP_STATUS_UNKNOWN_CLASS an invalid properties type was passed in + * - AMQP_STATUS_TIMER_FAILURE system timer indicated failure. The frame + * was sent + * - AMQP_STATUS_SOCKET_ERROR + * - AMQP_STATUS_SSL_ERROR + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_send_frame(amqp_connection_state_t state, + amqp_frame_t const *frame); + +/** + * Compare two table entries + * + * Works just like strcmp(), comparing two the table keys, datatype, then values + * + * \param [in] entry1 the entry on the left + * \param [in] entry2 the entry on the right + * \return 0 if entries are equal, 0 < if left is greater, 0 > if right is + * greater + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_table_entry_cmp(void const *entry1, void const *entry2); + +/** + * Open a socket to a remote host + * + * \deprecated This function is deprecated in favor of amqp_socket_open() + * + * Looks up the hostname, then attempts to open a socket to the host using + * the specified portnumber. It also sets various options on the socket to + * improve performance and correctness. + * + * \param [in] hostname this can be a hostname or IP address. + * Both IPv4 and IPv6 are acceptable + * \param [in] portnumber the port to connect on. RabbitMQ brokers + * listen on port 5672, and 5671 for SSL + * \return a positive value indicates success and is the sockfd. A negative + * value (see amqp_status_enum)is returned on failure. Possible error codes: + * - AMQP_STATUS_TCP_SOCKETLIB_INIT_ERROR Initialization of underlying socket + * library failed. + * - AMQP_STATUS_HOSTNAME_RESOLUTION_FAILED hostname lookup failed. + * - AMQP_STATUS_SOCKET_ERROR a socket error occurred. errno or + * WSAGetLastError() may return more useful information. + * + * \note IPv6 support was added in v0.3 + * + * \sa amqp_socket_open() amqp_set_sockfd() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_open_socket(char const *hostname, int portnumber); + +/** + * Send initial AMQP header to the broker + * + * \warning this is a low level function intended for those who want to + * interact with the broker at a very low level. Use of this function without + * understanding what it does will result in AMQP protocol errors. + * + * This function sends the AMQP protocol header to the broker. + * + * \param [in] state the connection object + * \return AMQP_STATUS_OK on success, a negative value on failure. Possible + * error codes: + * - AMQP_STATUS_CONNECTION_CLOSED the connection to the broker was closed. + * - AMQP_STATUS_SOCKET_ERROR a socket error occurred. It is likely the + * underlying socket has been closed. errno or WSAGetLastError() may provide + * further information. + * - AMQP_STATUS_SSL_ERROR a SSL error occurred. The connection to the broker + * was closed. + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_send_header(amqp_connection_state_t state); + +/** + * Checks to see if there are any incoming frames ready to be read + * + * Checks to see if there are any amqp_frame_t objects buffered by the + * amqp_connection_state_t object. Having one or more frames buffered means + * that amqp_simple_wait_frame() or amqp_simple_wait_frame_noblock() will + * return a frame without potentially blocking on a read() call. + * + * \param [in] state the connection object + * \return TRUE if there are frames enqueued, FALSE otherwise + * + * \sa amqp_simple_wait_frame() amqp_simple_wait_frame_noblock() + * amqp_data_in_buffer() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +amqp_boolean_t AMQP_CALL amqp_frames_enqueued(amqp_connection_state_t state); + +/** + * Read a single amqp_frame_t + * + * Waits for the next amqp_frame_t frame to be read from the broker. + * This function has the potential to block for a long time in the case of + * waiting for a basic.deliver method frame from the broker. + * + * The library may buffer frames. When an amqp_connection_state_t object + * has frames buffered calling amqp_simple_wait_frame() will return an + * amqp_frame_t without entering a blocking read(). You can test to see if + * an amqp_connection_state_t object has frames buffered by calling the + * amqp_frames_enqueued() function. + * + * The library has a socket read buffer. When there is data in an + * amqp_connection_state_t read buffer, amqp_simple_wait_frame() may return an + * amqp_frame_t without entering a blocking read(). You can test to see if an + * amqp_connection_state_t object has data in its read buffer by calling the + * amqp_data_in_buffer() function. + * + * \param [in] state the connection object + * \param [out] decoded_frame the frame + * \return AMQP_STATUS_OK on success, an amqp_status_enum value + * is returned otherwise. Possible errors include: + * - AMQP_STATUS_NO_MEMORY failure in allocating memory. The library is likely + * in an indeterminate state making recovery unlikely. Client should note the + * error and terminate the application + * - AMQP_STATUS_BAD_AMQP_DATA bad AMQP data was received. The connection + * should be shutdown immediately + * - AMQP_STATUS_UNKNOWN_METHOD: an unknown method was received from the + * broker. This is likely a protocol error and the connection should be + * shutdown immediately + * - AMQP_STATUS_UNKNOWN_CLASS: a properties frame with an unknown class + * was received from the broker. This is likely a protocol error and the + * connection should be shutdown immediately + * - AMQP_STATUS_HEARTBEAT_TIMEOUT timed out while waiting for heartbeat + * from the broker. The connection has been closed. + * - AMQP_STATUS_TIMER_FAILURE system timer indicated failure. + * - AMQP_STATUS_SOCKET_ERROR a socket error occurred. The connection has + * been closed + * - AMQP_STATUS_SSL_ERROR a SSL socket error occurred. The connection has + * been closed. + * + * \sa amqp_simple_wait_frame_noblock() amqp_frames_enqueued() + * amqp_data_in_buffer() + * + * \note as of v0.4.0 this function will no longer return heartbeat frames + * when enabled by specifying a non-zero heartbeat value in amqp_login(). + * Heartbeating is handled internally by the library. + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_simple_wait_frame(amqp_connection_state_t state, + amqp_frame_t *decoded_frame); + +/** + * Read a single amqp_frame_t with a timeout. + * + * Waits for the next amqp_frame_t frame to be read from the broker, up to + * a timespan specified by tv. The function will return AMQP_STATUS_TIMEOUT + * if the timeout is reached. The tv value is not modified by the function. + * + * If a 0 timeval is specified, the function behaves as if its non-blocking: it + * will test to see if a frame can be read from the broker, and return + * immediately. + * + * If NULL is passed in for tv, the function will behave like + * amqp_simple_wait_frame() and block until a frame is received from the broker + * + * The library may buffer frames. When an amqp_connection_state_t object + * has frames buffered calling amqp_simple_wait_frame_noblock() will return an + * amqp_frame_t without entering a blocking read(). You can test to see if an + * amqp_connection_state_t object has frames buffered by calling the + * amqp_frames_enqueued() function. + * + * The library has a socket read buffer. When there is data in an + * amqp_connection_state_t read buffer, amqp_simple_wait_frame_noblock() may + * return + * an amqp_frame_t without entering a blocking read(). You can test to see if an + * amqp_connection_state_t object has data in its read buffer by calling the + * amqp_data_in_buffer() function. + * + * \note This function does not return heartbeat frames. When enabled, + * heartbeating is handed internally internally by the library. + * + * \param [in,out] state the connection object + * \param [out] decoded_frame the frame + * \param [in] tv the maximum time to wait for a frame to be read. Setting + * tv->tv_sec = 0 and tv->tv_usec = 0 will do a non-blocking read. Specifying + * NULL for tv will make the function block until a frame is read. + * \return AMQP_STATUS_OK on success. An amqp_status_enum value is returned + * otherwise. Possible errors include: + * - AMQP_STATUS_TIMEOUT the timeout was reached while waiting for a frame + * from the broker. + * - AMQP_STATUS_INVALID_PARAMETER the tv parameter contains an invalid value. + * - AMQP_STATUS_NO_MEMORY failure in allocating memory. The library is likely + * in an indeterminate state making recovery unlikely. Client should note the + * error and terminate the application + * - AMQP_STATUS_BAD_AMQP_DATA bad AMQP data was received. The connection + * should be shutdown immediately + * - AMQP_STATUS_UNKNOWN_METHOD: an unknown method was received from the + * broker. This is likely a protocol error and the connection should be + * shutdown immediately + * - AMQP_STATUS_UNKNOWN_CLASS: a properties frame with an unknown class + * was received from the broker. This is likely a protocol error and the + * connection should be shutdown immediately + * - AMQP_STATUS_HEARTBEAT_TIMEOUT timed out while waiting for heartbeat + * from the broker. The connection has been closed. + * - AMQP_STATUS_TIMER_FAILURE system timer indicated failure. + * - AMQP_STATUS_SOCKET_ERROR a socket error occurred. The connection has + * been closed + * - AMQP_STATUS_SSL_ERROR a SSL socket error occurred. The connection has + * been closed. + * + * \sa amqp_simple_wait_frame() amqp_frames_enqueued() amqp_data_in_buffer() + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_simple_wait_frame_noblock(amqp_connection_state_t state, + amqp_frame_t *decoded_frame, + struct timeval *tv); + +/** + * Waits for a specific method from the broker + * + * \warning You probably don't want to use this function. If this function + * doesn't receive exactly the frame requested it closes the whole connection. + * + * Waits for a single method on a channel from the broker. + * If a frame is received that does not match expected_channel + * or expected_method the program will abort + * + * \param [in] state the connection object + * \param [in] expected_channel the channel that the method should be delivered + * on + * \param [in] expected_method the method to wait for + * \param [out] output the method + * \returns AMQP_STATUS_OK on success. An amqp_status_enum value is returned + * otherwise. Possible errors include: + * - AMQP_STATUS_WRONG_METHOD a frame containing the wrong method, wrong frame + * type or wrong channel was received. The connection is closed. + * - AMQP_STATUS_NO_MEMORY failure in allocating memory. The library is likely + * in an indeterminate state making recovery unlikely. Client should note the + * error and terminate the application + * - AMQP_STATUS_BAD_AMQP_DATA bad AMQP data was received. The connection + * should be shutdown immediately + * - AMQP_STATUS_UNKNOWN_METHOD: an unknown method was received from the + * broker. This is likely a protocol error and the connection should be + * shutdown immediately + * - AMQP_STATUS_UNKNOWN_CLASS: a properties frame with an unknown class + * was received from the broker. This is likely a protocol error and the + * connection should be shutdown immediately + * - AMQP_STATUS_HEARTBEAT_TIMEOUT timed out while waiting for heartbeat + * from the broker. The connection has been closed. + * - AMQP_STATUS_TIMER_FAILURE system timer indicated failure. + * - AMQP_STATUS_SOCKET_ERROR a socket error occurred. The connection has + * been closed + * - AMQP_STATUS_SSL_ERROR a SSL socket error occurred. The connection has + * been closed. + * + * \since v0.1 + */ + +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_simple_wait_method(amqp_connection_state_t state, + amqp_channel_t expected_channel, + amqp_method_number_t expected_method, + amqp_method_t *output); + +/** + * Sends a method to the broker + * + * This is a thin wrapper around amqp_send_frame(), providing a way to send + * a method to the broker on a specified channel. + * + * \param [in] state the connection object + * \param [in] channel the channel object + * \param [in] id the method number + * \param [in] decoded the method object + * \returns AMQP_STATUS_OK on success, an amqp_status_enum value otherwise. + * Possible errors include: + * - AMQP_STATUS_BAD_AMQP_DATA the serialized form of the method or + * properties was too large to fit in a single AMQP frame, or the + * method contains an invalid value. The frame was not sent. + * - AMQP_STATUS_TABLE_TOO_BIG the serialized form of an amqp_table_t is + * too large to fit in a single AMQP frame. Frame was not sent. + * - AMQP_STATUS_UNKNOWN_METHOD an invalid method type was passed in + * - AMQP_STATUS_UNKNOWN_CLASS an invalid properties type was passed in + * - AMQP_STATUS_TIMER_FAILURE system timer indicated failure. The frame + * was sent + * - AMQP_STATUS_SOCKET_ERROR + * - AMQP_STATUS_SSL_ERROR + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_send_method(amqp_connection_state_t state, + amqp_channel_t channel, amqp_method_number_t id, + void *decoded); + +/** + * Sends a method to the broker and waits for a method response + * + * \param [in] state the connection object + * \param [in] channel the channel object + * \param [in] request_id the method number of the request + * \param [in] expected_reply_ids a 0 terminated array of expected response + * method numbers + * \param [in] decoded_request_method the method to be sent to the broker + * \return a amqp_rpc_reply_t: + * - r.reply_type == AMQP_RESPONSE_NORMAL. RPC completed successfully + * - r.reply_type == AMQP_RESPONSE_SERVER_EXCEPTION. The broker returned an + * exception: + * - If r.reply.id == AMQP_CHANNEL_CLOSE_METHOD a channel exception + * occurred, cast r.reply.decoded to amqp_channel_close_t* to see details + * of the exception. The client should amqp_send_method() a + * amqp_channel_close_ok_t. The channel must be re-opened before it + * can be used again. Any resources associated with the channel + * (auto-delete exchanges, auto-delete queues, consumers) are invalid + * and must be recreated before attempting to use them again. + * - If r.reply.id == AMQP_CONNECTION_CLOSE_METHOD a connection exception + * occurred, cast r.reply.decoded to amqp_connection_close_t* to see + * details of the exception. The client amqp_send_method() a + * amqp_connection_close_ok_t and disconnect from the broker. + * - r.reply_type == AMQP_RESPONSE_LIBRARY_EXCEPTION. An exception occurred + * within the library. Examine r.library_error and compare it against + * amqp_status_enum values to determine the error. + * + * \sa amqp_simple_rpc_decoded() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +amqp_rpc_reply_t AMQP_CALL amqp_simple_rpc( + amqp_connection_state_t state, amqp_channel_t channel, + amqp_method_number_t request_id, amqp_method_number_t *expected_reply_ids, + void *decoded_request_method); + +/** + * Sends a method to the broker and waits for a method response + * + * \param [in] state the connection object + * \param [in] channel the channel object + * \param [in] request_id the method number of the request + * \param [in] reply_id the method number expected in response + * \param [in] decoded_request_method the request method + * \return a pointer to the method returned from the broker, or NULL on error. + * On error amqp_get_rpc_reply() will return an amqp_rpc_reply_t with + * details on the error that occurred. + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +void *AMQP_CALL amqp_simple_rpc_decoded(amqp_connection_state_t state, + amqp_channel_t channel, + amqp_method_number_t request_id, + amqp_method_number_t reply_id, + void *decoded_request_method); + +/** + * Get the last global amqp_rpc_reply + * + * The API methods corresponding to most synchronous AMQP methods + * return a pointer to the decoded method result. Upon error, they + * return NULL, and we need some way of discovering what, if anything, + * went wrong. amqp_get_rpc_reply() returns the most recent + * amqp_rpc_reply_t instance corresponding to such an API operation + * for the given connection. + * + * Only use it for operations that do not themselves return + * amqp_rpc_reply_t; operations that do return amqp_rpc_reply_t + * generally do NOT update this per-connection-global amqp_rpc_reply_t + * instance. + * + * \param [in] state the connection object + * \return the most recent amqp_rpc_reply_t: + * - r.reply_type == AMQP_RESPONSE_NORMAL. RPC completed successfully + * - r.reply_type == AMQP_RESPONSE_SERVER_EXCEPTION. The broker returned an + * exception: + * - If r.reply.id == AMQP_CHANNEL_CLOSE_METHOD a channel exception + * occurred, cast r.reply.decoded to amqp_channel_close_t* to see details + * of the exception. The client should amqp_send_method() a + * amqp_channel_close_ok_t. The channel must be re-opened before it + * can be used again. Any resources associated with the channel + * (auto-delete exchanges, auto-delete queues, consumers) are invalid + * and must be recreated before attempting to use them again. + * - If r.reply.id == AMQP_CONNECTION_CLOSE_METHOD a connection exception + * occurred, cast r.reply.decoded to amqp_connection_close_t* to see + * details of the exception. The client amqp_send_method() a + * amqp_connection_close_ok_t and disconnect from the broker. + * - r.reply_type == AMQP_RESPONSE_LIBRARY_EXCEPTION. An exception occurred + * within the library. Examine r.library_error and compare it against + * amqp_status_enum values to determine the error. + * + * \sa amqp_simple_rpc_decoded() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +amqp_rpc_reply_t AMQP_CALL amqp_get_rpc_reply(amqp_connection_state_t state); + +/** + * Login to the broker + * + * After using amqp_open_socket and amqp_set_sockfd, call + * amqp_login to complete connecting to the broker + * + * \param [in] state the connection object + * \param [in] vhost the virtual host to connect to on the broker. The default + * on most brokers is "/" + * \param [in] channel_max the limit for number of channels for the connection. + * 0 means no limit, and is a good default + * (AMQP_DEFAULT_MAX_CHANNELS) + * Note that the maximum number of channels the protocol supports + * is 65535 (2^16, with the 0-channel reserved). The server can + * set a lower channel_max and then the client will use the lowest + * of the two + * \param [in] frame_max the maximum size of an AMQP frame on the wire to + * request of the broker for this connection. 4096 is the minimum + * size, 2^31-1 is the maximum, a good default is 131072 (128KB), + * or AMQP_DEFAULT_FRAME_SIZE + * \param [in] heartbeat the number of seconds between heartbeat frames to + * request of the broker. A value of 0 disables heartbeats. + * Note rabbitmq-c only has partial support for heartbeats, as of + * v0.4.0 they are only serviced during amqp_basic_publish() and + * amqp_simple_wait_frame()/amqp_simple_wait_frame_noblock() + * \param [in] sasl_method the SASL method to authenticate with the broker. + * followed by the authentication information. The following SASL + * methods are implemented: + * - AMQP_SASL_METHOD_PLAIN, the AMQP_SASL_METHOD_PLAIN argument + * should be followed by two arguments in this order: + * const char* username, and const char* password. + * - AMQP_SASL_METHOD_EXTERNAL, the AMQP_SASL_METHOD_EXTERNAL + * argument should be followed one argument: + * const char* identity. + * \return amqp_rpc_reply_t indicating success or failure. + * - r.reply_type == AMQP_RESPONSE_NORMAL. Login completed successfully + * - r.reply_type == AMQP_RESPONSE_LIBRARY_EXCEPTION. In most cases errors + * from the broker when logging in will be represented by the broker closing + * the socket. In this case r.library_error will be set to + * AMQP_STATUS_CONNECTION_CLOSED. This error can represent a number of + * error conditions including: invalid vhost, authentication failure. + * - r.reply_type == AMQP_RESPONSE_SERVER_EXCEPTION. The broker returned an + * exception: + * - If r.reply.id == AMQP_CHANNEL_CLOSE_METHOD a channel exception + * occurred, cast r.reply.decoded to amqp_channel_close_t* to see details + * of the exception. The client should amqp_send_method() a + * amqp_channel_close_ok_t. The channel must be re-opened before it + * can be used again. Any resources associated with the channel + * (auto-delete exchanges, auto-delete queues, consumers) are invalid + * and must be recreated before attempting to use them again. + * - If r.reply.id == AMQP_CONNECTION_CLOSE_METHOD a connection exception + * occurred, cast r.reply.decoded to amqp_connection_close_t* to see + * details of the exception. The client amqp_send_method() a + * amqp_connection_close_ok_t and disconnect from the broker. + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +amqp_rpc_reply_t AMQP_CALL amqp_login(amqp_connection_state_t state, + char const *vhost, int channel_max, + int frame_max, int heartbeat, + amqp_sasl_method_enum sasl_method, ...); + +/** + * Login to the broker passing a properties table + * + * This function is similar to amqp_login() and differs in that it provides a + * way to pass client properties to the broker. This is commonly used to + * negotiate newer protocol features as they are supported by the broker. + * + * \param [in] state the connection object + * \param [in] vhost the virtual host to connect to on the broker. The default + * on most brokers is "/" + * \param [in] channel_max the limit for the number of channels for the + * connection. + * 0 means no limit, and is a good default + * (AMQP_DEFAULT_MAX_CHANNELS) + * Note that the maximum number of channels the protocol supports + * is 65535 (2^16, with the 0-channel reserved). The server can + * set a lower channel_max and then the client will use the lowest + * of the two + * \param [in] frame_max the maximum size of an AMQP frame ont he wire to + * request of the broker for this connection. 4096 is the minimum + * size, 2^31-1 is the maximum, a good default is 131072 (128KB), + * or AMQP_DEFAULT_FRAME_SIZE + * \param [in] heartbeat the number of seconds between heartbeat frame to + * request of the broker. A value of 0 disables heartbeats. + * Note rabbitmq-c only has partial support for hearts, as of + * v0.4.0 heartbeats are only serviced during amqp_basic_publish(), + * and amqp_simple_wait_frame()/amqp_simple_wait_frame_noblock() + * \param [in] properties a table of properties to send the broker. + * \param [in] sasl_method the SASL method to authenticate with the broker + * followed by the authentication information. The following SASL + * methods are implemented: + * - AMQP_SASL_METHOD_PLAIN, the AMQP_SASL_METHOD_PLAIN argument + * should be followed by two arguments in this order: + * const char* username, and const char* password. + * - AMQP_SASL_METHOD_EXTERNAL, the AMQP_SASL_METHOD_EXTERNAL + * argument should be followed one argument: + * const char* identity. + * \return amqp_rpc_reply_t indicating success or failure. + * - r.reply_type == AMQP_RESPONSE_NORMAL. Login completed successfully + * - r.reply_type == AMQP_RESPONSE_LIBRARY_EXCEPTION. In most cases errors + * from the broker when logging in will be represented by the broker closing + * the socket. In this case r.library_error will be set to + * AMQP_STATUS_CONNECTION_CLOSED. This error can represent a number of + * error conditions including: invalid vhost, authentication failure. + * - r.reply_type == AMQP_RESPONSE_SERVER_EXCEPTION. The broker returned an + * exception: + * - If r.reply.id == AMQP_CHANNEL_CLOSE_METHOD a channel exception + * occurred, cast r.reply.decoded to amqp_channel_close_t* to see details + * of the exception. The client should amqp_send_method() a + * amqp_channel_close_ok_t. The channel must be re-opened before it + * can be used again. Any resources associated with the channel + * (auto-delete exchanges, auto-delete queues, consumers) are invalid + * and must be recreated before attempting to use them again. + * - If r.reply.id == AMQP_CONNECTION_CLOSE_METHOD a connection exception + * occurred, cast r.reply.decoded to amqp_connection_close_t* to see + * details of the exception. The client amqp_send_method() a + * amqp_connection_close_ok_t and disconnect from the broker. + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +amqp_rpc_reply_t AMQP_CALL amqp_login_with_properties( + amqp_connection_state_t state, char const *vhost, int channel_max, + int frame_max, int heartbeat, const amqp_table_t *properties, + amqp_sasl_method_enum sasl_method, ...); + +struct amqp_basic_properties_t_; + +/** + * Publish a message to the broker + * + * Publish a message on an exchange with a routing key. + * + * Note that at the AMQ protocol level basic.publish is an async method: + * this means error conditions that occur on the broker (such as publishing to + * a non-existent exchange) will not be reflected in the return value of this + * function. + * + * \param [in] state the connection object + * \param [in] channel the channel identifier + * \param [in] exchange the exchange on the broker to publish to + * \param [in] routing_key the routing key to use when publishing the message + * \param [in] mandatory indicate to the broker that the message MUST be routed + * to a queue. If the broker cannot do this it should respond with + * a basic.return method. + * \param [in] immediate indicate to the broker that the message MUST be + * delivered to a consumer immediately. If the broker cannot do this + * it should respond with a basic.return method. + * \param [in] properties the properties associated with the message + * \param [in] body the message body + * \return AMQP_STATUS_OK on success, amqp_status_enum value on failure. Note + * that basic.publish is an async method, the return value from this + * function only indicates that the message data was successfully + * transmitted to the broker. It does not indicate failures that occur + * on the broker, such as publishing to a non-existent exchange. + * Possible error values: + * - AMQP_STATUS_TIMER_FAILURE: system timer facility returned an error + * the message was not sent. + * - AMQP_STATUS_HEARTBEAT_TIMEOUT: connection timed out waiting for a + * heartbeat from the broker. The message was not sent. + * - AMQP_STATUS_NO_MEMORY: memory allocation failed. The message was + * not sent. + * - AMQP_STATUS_TABLE_TOO_BIG: a table in the properties was too large + * to fit in a single frame. Message was not sent. + * - AMQP_STATUS_CONNECTION_CLOSED: the connection was closed. + * - AMQP_STATUS_SSL_ERROR: a SSL error occurred. + * - AMQP_STATUS_TCP_ERROR: a TCP error occurred. errno or + * WSAGetLastError() may provide more information + * + * Note: this function does heartbeat processing as of v0.4.0 + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_basic_publish( + amqp_connection_state_t state, amqp_channel_t channel, + amqp_bytes_t exchange, amqp_bytes_t routing_key, amqp_boolean_t mandatory, + amqp_boolean_t immediate, struct amqp_basic_properties_t_ const *properties, + amqp_bytes_t body); + +/** + * Closes an channel + * + * \param [in] state the connection object + * \param [in] channel the channel identifier + * \param [in] code the reason for closing the channel, AMQP_REPLY_SUCCESS is a + * good default + * \return amqp_rpc_reply_t indicating success or failure + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +amqp_rpc_reply_t AMQP_CALL amqp_channel_close(amqp_connection_state_t state, + amqp_channel_t channel, int code); + +/** + * Closes the entire connection + * + * Implicitly closes all channels and informs the broker the connection + * is being closed, after receiving acknowledgment from the broker it closes + * the socket. + * + * \param [in] state the connection object + * \param [in] code the reason code for closing the connection. + * AMQP_REPLY_SUCCESS is a good default. + * \return amqp_rpc_reply_t indicating the result + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +amqp_rpc_reply_t AMQP_CALL amqp_connection_close(amqp_connection_state_t state, + int code); + +/** + * Acknowledges a message + * + * Does a basic.ack on a received message + * + * \param [in] state the connection object + * \param [in] channel the channel identifier + * \param [in] delivery_tag the delivery tag of the message to be ack'd + * \param [in] multiple if true, ack all messages up to this delivery tag, if + * false ack only this delivery tag + * \return 0 on success, 0 > on failing to send the ack to the broker. + * this will not indicate failure if something goes wrong on the + * broker + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_basic_ack(amqp_connection_state_t state, + amqp_channel_t channel, uint64_t delivery_tag, + amqp_boolean_t multiple); + +/** + * Do a basic.get + * + * Synchonously polls the broker for a message in a queue, and + * retrieves the message if a message is in the queue. + * + * \param [in] state the connection object + * \param [in] channel the channel identifier to use + * \param [in] queue the queue name to retrieve from + * \param [in] no_ack if true the message is automatically ack'ed + * if false amqp_basic_ack should be called once the message + * retrieved has been processed + * \return amqp_rpc_reply indicating success or failure + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +amqp_rpc_reply_t AMQP_CALL amqp_basic_get(amqp_connection_state_t state, + amqp_channel_t channel, + amqp_bytes_t queue, + amqp_boolean_t no_ack); + +/** + * Do a basic.reject + * + * Actively reject a message that has been delivered + * + * \param [in] state the connection object + * \param [in] channel the channel identifier + * \param [in] delivery_tag the delivery tag of the message to reject + * \param [in] requeue indicate to the broker whether it should requeue the + * message or just discard it. + * \return 0 on success, 0 > on failing to send the reject method to the broker. + * This will not indicate failure if something goes wrong on the + * broker. + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_basic_reject(amqp_connection_state_t state, + amqp_channel_t channel, uint64_t delivery_tag, + amqp_boolean_t requeue); + +/** + * Do a basic.nack + * + * Actively reject a message, this has the same effect as amqp_basic_reject() + * however, amqp_basic_nack() can negatively acknowledge multiple messages with + * one call much like amqp_basic_ack() can acknowledge mutliple messages with + * one call. + * + * \param [in] state the connection object + * \param [in] channel the channel identifier + * \param [in] delivery_tag the delivery tag of the message to reject + * \param [in] multiple if set to 1 negatively acknowledge all unacknowledged + * messages on this channel. + * \param [in] requeue indicate to the broker whether it should requeue the + * message or dead-letter it. + * \return AMQP_STATUS_OK on success, an amqp_status_enum value otherwise. + * + * \since v0.5.0 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_basic_nack(amqp_connection_state_t state, + amqp_channel_t channel, uint64_t delivery_tag, + amqp_boolean_t multiple, amqp_boolean_t requeue); +/** + * Check to see if there is data left in the receive buffer + * + * Can be used to see if there is data still in the buffer, if so + * calling amqp_simple_wait_frame will not immediately enter a + * blocking read. + * + * \param [in] state the connection object + * \return true if there is data in the recieve buffer, false otherwise + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +amqp_boolean_t AMQP_CALL amqp_data_in_buffer(amqp_connection_state_t state); + +/** + * Get the error string for the given error code. + * + * \deprecated This function has been deprecated in favor of + * \ref amqp_error_string2() which returns statically allocated + * string which do not need to be freed by the caller. + * + * The returned string resides on the heap; the caller is responsible + * for freeing it. + * + * \param [in] err return error code + * \return the error string + * + * \since v0.1 + */ +AMQP_DEPRECATED( + AMQP_PUBLIC_FUNCTION char *AMQP_CALL amqp_error_string(int err)); + +/** + * Get the error string for the given error code. + * + * Get an error string associated with an error code. The string is statically + * allocated and does not need to be freed + * + * \param [in] err the error code + * \return the error string + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +const char *AMQP_CALL amqp_error_string2(int err); + +/** + * Deserialize an amqp_table_t from AMQP wireformat + * + * This is an internal function and is not typically used by + * client applications + * + * \param [in] encoded the buffer containing the serialized data + * \param [in] pool memory pool used to allocate the table entries from + * \param [in] output the amqp_table_t structure to fill in. Any existing + * entries will be erased + * \param [in,out] offset The offset into the encoded buffer to start + * reading the serialized table. It will be updated + * by this function to end of the table + * \return AMQP_STATUS_OK on success, an amqp_status_enum value on failure + * Possible error codes: + * - AMQP_STATUS_NO_MEMORY out of memory + * - AMQP_STATUS_BAD_AMQP_DATA invalid wireformat + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_decode_table(amqp_bytes_t encoded, amqp_pool_t *pool, + amqp_table_t *output, size_t *offset); + +/** + * Serializes an amqp_table_t to the AMQP wireformat + * + * This is an internal function and is not typically used by + * client applications + * + * \param [in] encoded the buffer where to serialize the table to + * \param [in] input the amqp_table_t to serialize + * \param [in,out] offset The offset into the encoded buffer to start + * writing the serialized table. It will be updated + * by this function to where writing left off + * \return AMQP_STATUS_OK on success, an amqp_status_enum value on failure + * Possible error codes: + * - AMQP_STATUS_TABLE_TOO_BIG the serialized form is too large for the + * buffer + * - AMQP_STATUS_BAD_AMQP_DATA invalid table + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_encode_table(amqp_bytes_t encoded, amqp_table_t *input, + size_t *offset); + +/** + * Create a deep-copy of an amqp_table_t object + * + * Creates a deep-copy of an amqp_table_t object, using the provided pool + * object to allocate the necessary memory. This memory can be freed later by + * call recycle_amqp_pool(), or empty_amqp_pool() + * + * \param [in] original the table to copy + * \param [in,out] clone the table to copy to + * \param [in] pool the initialized memory pool to do allocations for the table + * from + * \return AMQP_STATUS_OK on success, amqp_status_enum value on failure. + * Possible error values: + * - AMQP_STATUS_NO_MEMORY - memory allocation failure. + * - AMQP_STATUS_INVALID_PARAMETER - invalid table (e.g., no key name) + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_table_clone(const amqp_table_t *original, + amqp_table_t *clone, amqp_pool_t *pool); + +/** + * A message object + * + * \since v0.4.0 + */ +typedef struct amqp_message_t_ { + amqp_basic_properties_t properties; /**< message properties */ + amqp_bytes_t body; /**< message body */ + amqp_pool_t pool; /**< pool used to allocate properties */ +} amqp_message_t; + +/** + * Reads the next message on a channel + * + * Reads a complete message (header + body) on a specified channel. This + * function is intended to be used with amqp_basic_get() or when an + * AMQP_BASIC_DELIVERY_METHOD method is received. + * + * \param [in,out] state the connection object + * \param [in] channel the channel on which to read the message from + * \param [in,out] message a pointer to a amqp_message_t object. Caller should + * call amqp_message_destroy() when it is done using the + * fields in the message object. The caller is responsible for + * allocating/destroying the amqp_message_t object itself. + * \param [in] flags pass in 0. Currently unused. + * \returns a amqp_rpc_reply_t object. ret.reply_type == AMQP_RESPONSE_NORMAL on + * success. + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +amqp_rpc_reply_t AMQP_CALL amqp_read_message(amqp_connection_state_t state, + amqp_channel_t channel, + amqp_message_t *message, + int flags); + +/** + * Frees memory associated with a amqp_message_t allocated in amqp_read_message + * + * \param [in] message + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +void AMQP_CALL amqp_destroy_message(amqp_message_t *message); + +/** + * Envelope object + * + * \since v0.4.0 + */ +typedef struct amqp_envelope_t_ { + amqp_channel_t channel; /**< channel message was delivered on */ + amqp_bytes_t + consumer_tag; /**< the consumer tag the message was delivered to */ + uint64_t delivery_tag; /**< the messages delivery tag */ + amqp_boolean_t redelivered; /**< flag indicating whether this message is being + redelivered */ + amqp_bytes_t exchange; /**< exchange this message was published to */ + amqp_bytes_t + routing_key; /**< the routing key this message was published with */ + amqp_message_t message; /**< the message */ +} amqp_envelope_t; + +/** + * Wait for and consume a message + * + * Waits for a basic.deliver method on any channel, upon receipt of + * basic.deliver it reads that message, and returns. If any other method is + * received before basic.deliver, this function will return an amqp_rpc_reply_t + * with ret.reply_type == AMQP_RESPONSE_LIBRARY_EXCEPTION, and + * ret.library_error == AMQP_STATUS_UNEXPECTED_STATE. The caller should then + * call amqp_simple_wait_frame() to read this frame and take appropriate action. + * + * This function should be used after starting a consumer with the + * amqp_basic_consume() function + * + * \param [in,out] state the connection object + * \param [in,out] envelope a pointer to a amqp_envelope_t object. Caller + * should call #amqp_destroy_envelope() when it is done using + * the fields in the envelope object. The caller is responsible + * for allocating/destroying the amqp_envelope_t object itself. + * \param [in] timeout a timeout to wait for a message delivery. Passing in + * NULL will result in blocking behavior. + * \param [in] flags pass in 0. Currently unused. + * \returns a amqp_rpc_reply_t object. ret.reply_type == AMQP_RESPONSE_NORMAL + * on success. If ret.reply_type == AMQP_RESPONSE_LIBRARY_EXCEPTION, + * and ret.library_error == AMQP_STATUS_UNEXPECTED_STATE, a frame other + * than AMQP_BASIC_DELIVER_METHOD was received, the caller should call + * amqp_simple_wait_frame() to read this frame and take appropriate + * action. + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +amqp_rpc_reply_t AMQP_CALL amqp_consume_message(amqp_connection_state_t state, + amqp_envelope_t *envelope, + struct timeval *timeout, + int flags); + +/** + * Frees memory associated with a amqp_envelope_t allocated in + * amqp_consume_message() + * + * \param [in] envelope + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +void AMQP_CALL amqp_destroy_envelope(amqp_envelope_t *envelope); + +/** + * Parameters used to connect to the RabbitMQ broker + * + * \since v0.2 + */ +struct amqp_connection_info { + char *user; /**< the username to authenticate with the broker, default on most + broker is 'guest' */ + char *password; /**< the password to authenticate with the broker, default on + most brokers is 'guest' */ + char *host; /**< the hostname of the broker */ + char *vhost; /**< the virtual host on the broker to connect to, a good default + is "/" */ + int port; /**< the port that the broker is listening on, default on most + brokers is 5672 */ + amqp_boolean_t ssl; +}; + +/** + * Initialze an amqp_connection_info to default values + * + * The default values are: + * - user: "guest" + * - password: "guest" + * - host: "localhost" + * - vhost: "/" + * - port: 5672 + * + * \param [out] parsed the connection info to set defaults on + * + * \since v0.2 + */ +AMQP_PUBLIC_FUNCTION +void AMQP_CALL + amqp_default_connection_info(struct amqp_connection_info *parsed); + +/** + * Parse a connection URL + * + * An amqp connection url takes the form: + * + * amqp://[$USERNAME[:$PASSWORD]\@]$HOST[:$PORT]/[$VHOST] + * + * Examples: + * amqp://guest:guest\@localhost:5672// + * amqp://guest:guest\@localhost/myvhost + * + * Any missing parts of the URL will be set to the defaults specified in + * amqp_default_connection_info. For amqps: URLs the default port will be set + * to 5671 instead of 5672 for non-SSL URLs. + * + * \note This function modifies url parameter. + * + * \param [in] url URI to parse, note that this parameter is modified by the + * function. + * \param [out] parsed the connection info gleaned from the URI. The char* + * members will point to parts of the url input parameter. + * Memory management will depend on how the url is allocated. + * \returns AMQP_STATUS_OK on success, AMQP_STATUS_BAD_URL on failure + * + * \since v0.2 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_parse_url(char *url, struct amqp_connection_info *parsed); + +/* socket API */ + +/** + * Open a socket connection. + * + * This function opens a socket connection returned from amqp_tcp_socket_new() + * or amqp_ssl_socket_new(). This function should be called after setting + * socket options and prior to assigning the socket to an AMQP connection with + * amqp_set_socket(). + * + * \param [in,out] self A socket object. + * \param [in] host Connect to this host. + * \param [in] port Connect on this remote port. + * + * \return AMQP_STATUS_OK on success, an amqp_status_enum on failure + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_socket_open(amqp_socket_t *self, const char *host, int port); + +/** + * Open a socket connection. + * + * This function opens a socket connection returned from amqp_tcp_socket_new() + * or amqp_ssl_socket_new(). This function should be called after setting + * socket options and prior to assigning the socket to an AMQP connection with + * amqp_set_socket(). + * + * \param [in,out] self A socket object. + * \param [in] host Connect to this host. + * \param [in] port Connect on this remote port. + * \param [in] timeout Max allowed time to spent on opening. If NULL - run in + * blocking mode + * + * \return AMQP_STATUS_OK on success, an amqp_status_enum on failure. + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_socket_open_noblock(amqp_socket_t *self, const char *host, + int port, struct timeval *timeout); + +/** + * Get the socket descriptor in use by a socket object. + * + * Retrieve the underlying socket descriptor. This function can be used to + * perform low-level socket operations that aren't supported by the socket + * interface. Use with caution! + * + * \param [in,out] self A socket object. + * + * \return The underlying socket descriptor, or -1 if there is no socket + * descriptor associated with + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_socket_get_sockfd(amqp_socket_t *self); + +/** + * Get the socket object associated with a amqp_connection_state_t + * + * \param [in] state the connection object to get the socket from + * \return a pointer to the socket object, or NULL if one has not been assigned + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +amqp_socket_t *AMQP_CALL amqp_get_socket(amqp_connection_state_t state); + +/** + * Get the broker properties table + * + * \param [in] state the connection object + * \return a pointer to an amqp_table_t containing the properties advertised + * by the broker on connection. The connection object owns the table, it + * should not be modified. + * + * \since v0.5.0 + */ +AMQP_PUBLIC_FUNCTION +amqp_table_t *AMQP_CALL + amqp_get_server_properties(amqp_connection_state_t state); + +/** + * Get the client properties table + * + * Get the properties that were passed to the broker on connection. + * + * \param [in] state the connection object + * \return a pointer to an amqp_table_t containing the properties advertised + * by the client on connection. The connection object owns the table, it + * should not be modified. + * + * \since v0.7.0 + */ +AMQP_PUBLIC_FUNCTION +amqp_table_t *AMQP_CALL + amqp_get_client_properties(amqp_connection_state_t state); + +/** + * Get the login handshake timeout. + * + * amqp_login and amqp_login_with_properties perform the login handshake with + * the broker. This function returns the timeout associated with completing + * this operation from the client side. This value can be set by using the + * amqp_set_handshake_timeout. + * + * Note that the RabbitMQ broker has configurable timeout for completing the + * login handshake, the default is 10 seconds. rabbitmq-c has a default of 12 + * seconds. + * + * \param [in] state the connection object + * \return a struct timeval representing the current login timeout for the state + * object. A NULL value represents an infinite timeout. The memory returned is + * owned by the connection object. + * + * \since v0.9.0 + */ +AMQP_PUBLIC_FUNCTION +struct timeval *AMQP_CALL + amqp_get_handshake_timeout(amqp_connection_state_t state); + +/** + * Set the login handshake timeout. + * + * amqp_login and amqp_login_with_properties perform the login handshake with + * the broker. This function sets the timeout associated with completing this + * operation from the client side. + * + * The timeout must be set before amqp_login or amqp_login_with_properties is + * called to change from the default timeout. + * + * Note that the RabbitMQ broker has a configurable timeout for completing the + * login handshake, the default is 10 seconds. rabbitmq-c has a default of 12 + * seconds. + * + * \param [in] state the connection object + * \param [in] timeout a struct timeval* representing new login timeout for the + * state object. NULL represents an infinite timeout. The value of timeout is + * copied internally, the caller is responsible for ownership of the passed in + * pointer, it does not need to remain valid after this function is called. + * \return AMQP_STATUS_OK on success. + * + * \since v0.9.0 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_set_handshake_timeout(amqp_connection_state_t state, + struct timeval *timeout); + +/** + * Get the RPC timeout + * + * Gets the timeout for any RPC-style AMQP command (e.g., amqp_queue_declare). + * This timeout may be changed at any time by calling \amqp_set_rpc_timeout + * function with a new timeout. The timeout applies individually to each RPC + * that is made. + * + * The default value is NULL, or an infinite timeout. + * + * When an RPC times out, the function will return an error AMQP_STATUS_TIMEOUT, + * and the connection will be closed. + * + *\warning RPC-timeouts are an advanced feature intended to be used to detect + * dead connections quickly when the rabbitmq-c implementation of heartbeats + * does not work. Do not use RPC timeouts unless you understand the implications + * of doing so. + * + * \param [in] state the connection object + * \return a struct timeval representing the current RPC timeout for the state + * object. A NULL value represents an infinite timeout. The memory returned is + * owned by the connection object. + * + * \since v0.9.0 + */ +AMQP_PUBLIC_FUNCTION +struct timeval *AMQP_CALL amqp_get_rpc_timeout(amqp_connection_state_t state); + +/** + * Set the RPC timeout + * + * Sets the timeout for any RPC-style AMQP command (e.g., amqp_queue_declare). + * This timeout may be changed at any time by calling this function with a new + * timeout. The timeout applies individually to each RPC that is made. + * + * The default value is NULL, or an infinite timeout. + * + * When an RPC times out, the function will return an error AMQP_STATUS_TIMEOUT, + * and the connection will be closed. + * + *\warning RPC-timeouts are an advanced feature intended to be used to detect + * dead connections quickly when the rabbitmq-c implementation of heartbeats + * does not work. Do not use RPC timeouts unless you understand the implications + * of doing so. + * + * \param [in] state the connection object + * \param [in] timeout a struct timeval* representing new RPC timeout for the + * state object. NULL represents an infinite timeout. The value of timeout is + * copied internally, the caller is responsible for ownership of the passed + * pointer, it does not need to remain valid after this function is called. + * \return AMQP_STATUS_SUCCESS on success. + * + * \since v0.9.0 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_set_rpc_timeout(amqp_connection_state_t state, + struct timeval *timeout); + +AMQP_END_DECLS + +#endif /* AMQP_H */ diff --git a/ext/librabbitmq/macos/include/amqp_framing.h b/ext/librabbitmq/macos/include/amqp_framing.h new file mode 100644 index 000000000..fb20acc1f --- /dev/null +++ b/ext/librabbitmq/macos/include/amqp_framing.h @@ -0,0 +1,1144 @@ +/* Generated code. Do not edit. Edit and re-run codegen.py instead. + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MIT + * + * Portions created by Alan Antonuk are Copyright (c) 2012-2013 + * Alan Antonuk. All Rights Reserved. + * + * Portions created by VMware are Copyright (c) 2007-2012 VMware, Inc. + * All Rights Reserved. + * + * Portions created by Tony Garnock-Jones are Copyright (c) 2009-2010 + * VMware, Inc. and Tony Garnock-Jones. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * ***** END LICENSE BLOCK ***** + */ + +/** @file amqp_framing.h */ +#ifndef AMQP_FRAMING_H +#define AMQP_FRAMING_H + +#include + +AMQP_BEGIN_DECLS + +#define AMQP_PROTOCOL_VERSION_MAJOR 0 /**< AMQP protocol version major */ +#define AMQP_PROTOCOL_VERSION_MINOR 9 /**< AMQP protocol version minor */ +#define AMQP_PROTOCOL_VERSION_REVISION \ + 1 /**< AMQP protocol version revision \ + */ +#define AMQP_PROTOCOL_PORT 5672 /**< Default AMQP Port */ +#define AMQP_FRAME_METHOD 1 /**< Constant: FRAME-METHOD */ +#define AMQP_FRAME_HEADER 2 /**< Constant: FRAME-HEADER */ +#define AMQP_FRAME_BODY 3 /**< Constant: FRAME-BODY */ +#define AMQP_FRAME_HEARTBEAT 8 /**< Constant: FRAME-HEARTBEAT */ +#define AMQP_FRAME_MIN_SIZE 4096 /**< Constant: FRAME-MIN-SIZE */ +#define AMQP_FRAME_END 206 /**< Constant: FRAME-END */ +#define AMQP_REPLY_SUCCESS 200 /**< Constant: REPLY-SUCCESS */ +#define AMQP_CONTENT_TOO_LARGE 311 /**< Constant: CONTENT-TOO-LARGE */ +#define AMQP_NO_ROUTE 312 /**< Constant: NO-ROUTE */ +#define AMQP_NO_CONSUMERS 313 /**< Constant: NO-CONSUMERS */ +#define AMQP_ACCESS_REFUSED 403 /**< Constant: ACCESS-REFUSED */ +#define AMQP_NOT_FOUND 404 /**< Constant: NOT-FOUND */ +#define AMQP_RESOURCE_LOCKED 405 /**< Constant: RESOURCE-LOCKED */ +#define AMQP_PRECONDITION_FAILED 406 /**< Constant: PRECONDITION-FAILED */ +#define AMQP_CONNECTION_FORCED 320 /**< Constant: CONNECTION-FORCED */ +#define AMQP_INVALID_PATH 402 /**< Constant: INVALID-PATH */ +#define AMQP_FRAME_ERROR 501 /**< Constant: FRAME-ERROR */ +#define AMQP_SYNTAX_ERROR 502 /**< Constant: SYNTAX-ERROR */ +#define AMQP_COMMAND_INVALID 503 /**< Constant: COMMAND-INVALID */ +#define AMQP_CHANNEL_ERROR 504 /**< Constant: CHANNEL-ERROR */ +#define AMQP_UNEXPECTED_FRAME 505 /**< Constant: UNEXPECTED-FRAME */ +#define AMQP_RESOURCE_ERROR 506 /**< Constant: RESOURCE-ERROR */ +#define AMQP_NOT_ALLOWED 530 /**< Constant: NOT-ALLOWED */ +#define AMQP_NOT_IMPLEMENTED 540 /**< Constant: NOT-IMPLEMENTED */ +#define AMQP_INTERNAL_ERROR 541 /**< Constant: INTERNAL-ERROR */ + +/* Function prototypes. */ + +/** + * Get constant name string from constant + * + * @param [in] constantNumber constant to get the name of + * @returns string describing the constant. String is managed by + * the library and should not be free()'d by the program + */ +AMQP_PUBLIC_FUNCTION +char const *AMQP_CALL amqp_constant_name(int constantNumber); + +/** + * Checks to see if a constant is a hard error + * + * A hard error occurs when something severe enough + * happens that the connection must be closed. + * + * @param [in] constantNumber the error constant + * @returns true if its a hard error, false otherwise + */ +AMQP_PUBLIC_FUNCTION +amqp_boolean_t AMQP_CALL amqp_constant_is_hard_error(int constantNumber); + +/** + * Get method name string from method number + * + * @param [in] methodNumber the method number + * @returns method name string. String is managed by the library + * and should not be freed()'d by the program + */ +AMQP_PUBLIC_FUNCTION +char const *AMQP_CALL amqp_method_name(amqp_method_number_t methodNumber); + +/** + * Check whether a method has content + * + * A method that has content will receive the method frame + * a properties frame, then 1 to N body frames + * + * @param [in] methodNumber the method number + * @returns true if method has content, false otherwise + */ +AMQP_PUBLIC_FUNCTION +amqp_boolean_t AMQP_CALL + amqp_method_has_content(amqp_method_number_t methodNumber); + +/** + * Decodes a method from AMQP wireformat + * + * @param [in] methodNumber the method number for the decoded parameter + * @param [in] pool the memory pool to allocate the decoded method from + * @param [in] encoded the encoded byte string buffer + * @param [out] decoded pointer to the decoded method struct + * @returns 0 on success, an error code otherwise + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_decode_method(amqp_method_number_t methodNumber, + amqp_pool_t *pool, amqp_bytes_t encoded, + void **decoded); + +/** + * Decodes a header frame properties structure from AMQP wireformat + * + * @param [in] class_id the class id for the decoded parameter + * @param [in] pool the memory pool to allocate the decoded properties from + * @param [in] encoded the encoded byte string buffer + * @param [out] decoded pointer to the decoded properties struct + * @returns 0 on success, an error code otherwise + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_decode_properties(uint16_t class_id, amqp_pool_t *pool, + amqp_bytes_t encoded, void **decoded); + +/** + * Encodes a method structure in AMQP wireformat + * + * @param [in] methodNumber the method number for the decoded parameter + * @param [in] decoded the method structure (e.g., amqp_connection_start_t) + * @param [in] encoded an allocated byte buffer for the encoded method + * structure to be written to. If the buffer isn't large enough + * to hold the encoded method, an error code will be returned. + * @returns 0 on success, an error code otherwise. + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_encode_method(amqp_method_number_t methodNumber, + void *decoded, amqp_bytes_t encoded); + +/** + * Encodes a properties structure in AMQP wireformat + * + * @param [in] class_id the class id for the decoded parameter + * @param [in] decoded the properties structure (e.g., amqp_basic_properties_t) + * @param [in] encoded an allocated byte buffer for the encoded properties to + * written to. + * If the buffer isn't large enough to hold the encoded method, an + * an error code will be returned + * @returns 0 on success, an error code otherwise. + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_encode_properties(uint16_t class_id, void *decoded, + amqp_bytes_t encoded); + +/* Method field records. */ + +#define AMQP_CONNECTION_START_METHOD \ + ((amqp_method_number_t)0x000A000A) /**< connection.start method id \ + @internal 10, 10; 655370 */ +/** connection.start method fields */ +typedef struct amqp_connection_start_t_ { + uint8_t version_major; /**< version-major */ + uint8_t version_minor; /**< version-minor */ + amqp_table_t server_properties; /**< server-properties */ + amqp_bytes_t mechanisms; /**< mechanisms */ + amqp_bytes_t locales; /**< locales */ +} amqp_connection_start_t; + +#define AMQP_CONNECTION_START_OK_METHOD \ + ((amqp_method_number_t)0x000A000B) /**< connection.start-ok method id \ + @internal 10, 11; 655371 */ +/** connection.start-ok method fields */ +typedef struct amqp_connection_start_ok_t_ { + amqp_table_t client_properties; /**< client-properties */ + amqp_bytes_t mechanism; /**< mechanism */ + amqp_bytes_t response; /**< response */ + amqp_bytes_t locale; /**< locale */ +} amqp_connection_start_ok_t; + +#define AMQP_CONNECTION_SECURE_METHOD \ + ((amqp_method_number_t)0x000A0014) /**< connection.secure method id \ + @internal 10, 20; 655380 */ +/** connection.secure method fields */ +typedef struct amqp_connection_secure_t_ { + amqp_bytes_t challenge; /**< challenge */ +} amqp_connection_secure_t; + +#define AMQP_CONNECTION_SECURE_OK_METHOD \ + ((amqp_method_number_t)0x000A0015) /**< connection.secure-ok method id \ + @internal 10, 21; 655381 */ +/** connection.secure-ok method fields */ +typedef struct amqp_connection_secure_ok_t_ { + amqp_bytes_t response; /**< response */ +} amqp_connection_secure_ok_t; + +#define AMQP_CONNECTION_TUNE_METHOD \ + ((amqp_method_number_t)0x000A001E) /**< connection.tune method id \ + @internal 10, 30; 655390 */ +/** connection.tune method fields */ +typedef struct amqp_connection_tune_t_ { + uint16_t channel_max; /**< channel-max */ + uint32_t frame_max; /**< frame-max */ + uint16_t heartbeat; /**< heartbeat */ +} amqp_connection_tune_t; + +#define AMQP_CONNECTION_TUNE_OK_METHOD \ + ((amqp_method_number_t)0x000A001F) /**< connection.tune-ok method id \ + @internal 10, 31; 655391 */ +/** connection.tune-ok method fields */ +typedef struct amqp_connection_tune_ok_t_ { + uint16_t channel_max; /**< channel-max */ + uint32_t frame_max; /**< frame-max */ + uint16_t heartbeat; /**< heartbeat */ +} amqp_connection_tune_ok_t; + +#define AMQP_CONNECTION_OPEN_METHOD \ + ((amqp_method_number_t)0x000A0028) /**< connection.open method id \ + @internal 10, 40; 655400 */ +/** connection.open method fields */ +typedef struct amqp_connection_open_t_ { + amqp_bytes_t virtual_host; /**< virtual-host */ + amqp_bytes_t capabilities; /**< capabilities */ + amqp_boolean_t insist; /**< insist */ +} amqp_connection_open_t; + +#define AMQP_CONNECTION_OPEN_OK_METHOD \ + ((amqp_method_number_t)0x000A0029) /**< connection.open-ok method id \ + @internal 10, 41; 655401 */ +/** connection.open-ok method fields */ +typedef struct amqp_connection_open_ok_t_ { + amqp_bytes_t known_hosts; /**< known-hosts */ +} amqp_connection_open_ok_t; + +#define AMQP_CONNECTION_CLOSE_METHOD \ + ((amqp_method_number_t)0x000A0032) /**< connection.close method id \ + @internal 10, 50; 655410 */ +/** connection.close method fields */ +typedef struct amqp_connection_close_t_ { + uint16_t reply_code; /**< reply-code */ + amqp_bytes_t reply_text; /**< reply-text */ + uint16_t class_id; /**< class-id */ + uint16_t method_id; /**< method-id */ +} amqp_connection_close_t; + +#define AMQP_CONNECTION_CLOSE_OK_METHOD \ + ((amqp_method_number_t)0x000A0033) /**< connection.close-ok method id \ + @internal 10, 51; 655411 */ +/** connection.close-ok method fields */ +typedef struct amqp_connection_close_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_connection_close_ok_t; + +#define AMQP_CONNECTION_BLOCKED_METHOD \ + ((amqp_method_number_t)0x000A003C) /**< connection.blocked method id \ + @internal 10, 60; 655420 */ +/** connection.blocked method fields */ +typedef struct amqp_connection_blocked_t_ { + amqp_bytes_t reason; /**< reason */ +} amqp_connection_blocked_t; + +#define AMQP_CONNECTION_UNBLOCKED_METHOD \ + ((amqp_method_number_t)0x000A003D) /**< connection.unblocked method id \ + @internal 10, 61; 655421 */ +/** connection.unblocked method fields */ +typedef struct amqp_connection_unblocked_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_connection_unblocked_t; + +#define AMQP_CHANNEL_OPEN_METHOD \ + ((amqp_method_number_t)0x0014000A) /**< channel.open method id @internal \ + 20, 10; 1310730 */ +/** channel.open method fields */ +typedef struct amqp_channel_open_t_ { + amqp_bytes_t out_of_band; /**< out-of-band */ +} amqp_channel_open_t; + +#define AMQP_CHANNEL_OPEN_OK_METHOD \ + ((amqp_method_number_t)0x0014000B) /**< channel.open-ok method id \ + @internal 20, 11; 1310731 */ +/** channel.open-ok method fields */ +typedef struct amqp_channel_open_ok_t_ { + amqp_bytes_t channel_id; /**< channel-id */ +} amqp_channel_open_ok_t; + +#define AMQP_CHANNEL_FLOW_METHOD \ + ((amqp_method_number_t)0x00140014) /**< channel.flow method id @internal \ + 20, 20; 1310740 */ +/** channel.flow method fields */ +typedef struct amqp_channel_flow_t_ { + amqp_boolean_t active; /**< active */ +} amqp_channel_flow_t; + +#define AMQP_CHANNEL_FLOW_OK_METHOD \ + ((amqp_method_number_t)0x00140015) /**< channel.flow-ok method id \ + @internal 20, 21; 1310741 */ +/** channel.flow-ok method fields */ +typedef struct amqp_channel_flow_ok_t_ { + amqp_boolean_t active; /**< active */ +} amqp_channel_flow_ok_t; + +#define AMQP_CHANNEL_CLOSE_METHOD \ + ((amqp_method_number_t)0x00140028) /**< channel.close method id @internal \ + 20, 40; 1310760 */ +/** channel.close method fields */ +typedef struct amqp_channel_close_t_ { + uint16_t reply_code; /**< reply-code */ + amqp_bytes_t reply_text; /**< reply-text */ + uint16_t class_id; /**< class-id */ + uint16_t method_id; /**< method-id */ +} amqp_channel_close_t; + +#define AMQP_CHANNEL_CLOSE_OK_METHOD \ + ((amqp_method_number_t)0x00140029) /**< channel.close-ok method id \ + @internal 20, 41; 1310761 */ +/** channel.close-ok method fields */ +typedef struct amqp_channel_close_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_channel_close_ok_t; + +#define AMQP_ACCESS_REQUEST_METHOD \ + ((amqp_method_number_t)0x001E000A) /**< access.request method id @internal \ + 30, 10; 1966090 */ +/** access.request method fields */ +typedef struct amqp_access_request_t_ { + amqp_bytes_t realm; /**< realm */ + amqp_boolean_t exclusive; /**< exclusive */ + amqp_boolean_t passive; /**< passive */ + amqp_boolean_t active; /**< active */ + amqp_boolean_t write; /**< write */ + amqp_boolean_t read; /**< read */ +} amqp_access_request_t; + +#define AMQP_ACCESS_REQUEST_OK_METHOD \ + ((amqp_method_number_t)0x001E000B) /**< access.request-ok method id \ + @internal 30, 11; 1966091 */ +/** access.request-ok method fields */ +typedef struct amqp_access_request_ok_t_ { + uint16_t ticket; /**< ticket */ +} amqp_access_request_ok_t; + +#define AMQP_EXCHANGE_DECLARE_METHOD \ + ((amqp_method_number_t)0x0028000A) /**< exchange.declare method id \ + @internal 40, 10; 2621450 */ +/** exchange.declare method fields */ +typedef struct amqp_exchange_declare_t_ { + uint16_t ticket; /**< ticket */ + amqp_bytes_t exchange; /**< exchange */ + amqp_bytes_t type; /**< type */ + amqp_boolean_t passive; /**< passive */ + amqp_boolean_t durable; /**< durable */ + amqp_boolean_t auto_delete; /**< auto-delete */ + amqp_boolean_t internal; /**< internal */ + amqp_boolean_t nowait; /**< nowait */ + amqp_table_t arguments; /**< arguments */ +} amqp_exchange_declare_t; + +#define AMQP_EXCHANGE_DECLARE_OK_METHOD \ + ((amqp_method_number_t)0x0028000B) /**< exchange.declare-ok method id \ + @internal 40, 11; 2621451 */ +/** exchange.declare-ok method fields */ +typedef struct amqp_exchange_declare_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_exchange_declare_ok_t; + +#define AMQP_EXCHANGE_DELETE_METHOD \ + ((amqp_method_number_t)0x00280014) /**< exchange.delete method id \ + @internal 40, 20; 2621460 */ +/** exchange.delete method fields */ +typedef struct amqp_exchange_delete_t_ { + uint16_t ticket; /**< ticket */ + amqp_bytes_t exchange; /**< exchange */ + amqp_boolean_t if_unused; /**< if-unused */ + amqp_boolean_t nowait; /**< nowait */ +} amqp_exchange_delete_t; + +#define AMQP_EXCHANGE_DELETE_OK_METHOD \ + ((amqp_method_number_t)0x00280015) /**< exchange.delete-ok method id \ + @internal 40, 21; 2621461 */ +/** exchange.delete-ok method fields */ +typedef struct amqp_exchange_delete_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_exchange_delete_ok_t; + +#define AMQP_EXCHANGE_BIND_METHOD \ + ((amqp_method_number_t)0x0028001E) /**< exchange.bind method id @internal \ + 40, 30; 2621470 */ +/** exchange.bind method fields */ +typedef struct amqp_exchange_bind_t_ { + uint16_t ticket; /**< ticket */ + amqp_bytes_t destination; /**< destination */ + amqp_bytes_t source; /**< source */ + amqp_bytes_t routing_key; /**< routing-key */ + amqp_boolean_t nowait; /**< nowait */ + amqp_table_t arguments; /**< arguments */ +} amqp_exchange_bind_t; + +#define AMQP_EXCHANGE_BIND_OK_METHOD \ + ((amqp_method_number_t)0x0028001F) /**< exchange.bind-ok method id \ + @internal 40, 31; 2621471 */ +/** exchange.bind-ok method fields */ +typedef struct amqp_exchange_bind_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_exchange_bind_ok_t; + +#define AMQP_EXCHANGE_UNBIND_METHOD \ + ((amqp_method_number_t)0x00280028) /**< exchange.unbind method id \ + @internal 40, 40; 2621480 */ +/** exchange.unbind method fields */ +typedef struct amqp_exchange_unbind_t_ { + uint16_t ticket; /**< ticket */ + amqp_bytes_t destination; /**< destination */ + amqp_bytes_t source; /**< source */ + amqp_bytes_t routing_key; /**< routing-key */ + amqp_boolean_t nowait; /**< nowait */ + amqp_table_t arguments; /**< arguments */ +} amqp_exchange_unbind_t; + +#define AMQP_EXCHANGE_UNBIND_OK_METHOD \ + ((amqp_method_number_t)0x00280033) /**< exchange.unbind-ok method id \ + @internal 40, 51; 2621491 */ +/** exchange.unbind-ok method fields */ +typedef struct amqp_exchange_unbind_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_exchange_unbind_ok_t; + +#define AMQP_QUEUE_DECLARE_METHOD \ + ((amqp_method_number_t)0x0032000A) /**< queue.declare method id @internal \ + 50, 10; 3276810 */ +/** queue.declare method fields */ +typedef struct amqp_queue_declare_t_ { + uint16_t ticket; /**< ticket */ + amqp_bytes_t queue; /**< queue */ + amqp_boolean_t passive; /**< passive */ + amqp_boolean_t durable; /**< durable */ + amqp_boolean_t exclusive; /**< exclusive */ + amqp_boolean_t auto_delete; /**< auto-delete */ + amqp_boolean_t nowait; /**< nowait */ + amqp_table_t arguments; /**< arguments */ +} amqp_queue_declare_t; + +#define AMQP_QUEUE_DECLARE_OK_METHOD \ + ((amqp_method_number_t)0x0032000B) /**< queue.declare-ok method id \ + @internal 50, 11; 3276811 */ +/** queue.declare-ok method fields */ +typedef struct amqp_queue_declare_ok_t_ { + amqp_bytes_t queue; /**< queue */ + uint32_t message_count; /**< message-count */ + uint32_t consumer_count; /**< consumer-count */ +} amqp_queue_declare_ok_t; + +#define AMQP_QUEUE_BIND_METHOD \ + ((amqp_method_number_t)0x00320014) /**< queue.bind method id @internal 50, \ + 20; 3276820 */ +/** queue.bind method fields */ +typedef struct amqp_queue_bind_t_ { + uint16_t ticket; /**< ticket */ + amqp_bytes_t queue; /**< queue */ + amqp_bytes_t exchange; /**< exchange */ + amqp_bytes_t routing_key; /**< routing-key */ + amqp_boolean_t nowait; /**< nowait */ + amqp_table_t arguments; /**< arguments */ +} amqp_queue_bind_t; + +#define AMQP_QUEUE_BIND_OK_METHOD \ + ((amqp_method_number_t)0x00320015) /**< queue.bind-ok method id @internal \ + 50, 21; 3276821 */ +/** queue.bind-ok method fields */ +typedef struct amqp_queue_bind_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_queue_bind_ok_t; + +#define AMQP_QUEUE_PURGE_METHOD \ + ((amqp_method_number_t)0x0032001E) /**< queue.purge method id @internal \ + 50, 30; 3276830 */ +/** queue.purge method fields */ +typedef struct amqp_queue_purge_t_ { + uint16_t ticket; /**< ticket */ + amqp_bytes_t queue; /**< queue */ + amqp_boolean_t nowait; /**< nowait */ +} amqp_queue_purge_t; + +#define AMQP_QUEUE_PURGE_OK_METHOD \ + ((amqp_method_number_t)0x0032001F) /**< queue.purge-ok method id @internal \ + 50, 31; 3276831 */ +/** queue.purge-ok method fields */ +typedef struct amqp_queue_purge_ok_t_ { + uint32_t message_count; /**< message-count */ +} amqp_queue_purge_ok_t; + +#define AMQP_QUEUE_DELETE_METHOD \ + ((amqp_method_number_t)0x00320028) /**< queue.delete method id @internal \ + 50, 40; 3276840 */ +/** queue.delete method fields */ +typedef struct amqp_queue_delete_t_ { + uint16_t ticket; /**< ticket */ + amqp_bytes_t queue; /**< queue */ + amqp_boolean_t if_unused; /**< if-unused */ + amqp_boolean_t if_empty; /**< if-empty */ + amqp_boolean_t nowait; /**< nowait */ +} amqp_queue_delete_t; + +#define AMQP_QUEUE_DELETE_OK_METHOD \ + ((amqp_method_number_t)0x00320029) /**< queue.delete-ok method id \ + @internal 50, 41; 3276841 */ +/** queue.delete-ok method fields */ +typedef struct amqp_queue_delete_ok_t_ { + uint32_t message_count; /**< message-count */ +} amqp_queue_delete_ok_t; + +#define AMQP_QUEUE_UNBIND_METHOD \ + ((amqp_method_number_t)0x00320032) /**< queue.unbind method id @internal \ + 50, 50; 3276850 */ +/** queue.unbind method fields */ +typedef struct amqp_queue_unbind_t_ { + uint16_t ticket; /**< ticket */ + amqp_bytes_t queue; /**< queue */ + amqp_bytes_t exchange; /**< exchange */ + amqp_bytes_t routing_key; /**< routing-key */ + amqp_table_t arguments; /**< arguments */ +} amqp_queue_unbind_t; + +#define AMQP_QUEUE_UNBIND_OK_METHOD \ + ((amqp_method_number_t)0x00320033) /**< queue.unbind-ok method id \ + @internal 50, 51; 3276851 */ +/** queue.unbind-ok method fields */ +typedef struct amqp_queue_unbind_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_queue_unbind_ok_t; + +#define AMQP_BASIC_QOS_METHOD \ + ((amqp_method_number_t)0x003C000A) /**< basic.qos method id @internal 60, \ + 10; 3932170 */ +/** basic.qos method fields */ +typedef struct amqp_basic_qos_t_ { + uint32_t prefetch_size; /**< prefetch-size */ + uint16_t prefetch_count; /**< prefetch-count */ + amqp_boolean_t global; /**< global */ +} amqp_basic_qos_t; + +#define AMQP_BASIC_QOS_OK_METHOD \ + ((amqp_method_number_t)0x003C000B) /**< basic.qos-ok method id @internal \ + 60, 11; 3932171 */ +/** basic.qos-ok method fields */ +typedef struct amqp_basic_qos_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_basic_qos_ok_t; + +#define AMQP_BASIC_CONSUME_METHOD \ + ((amqp_method_number_t)0x003C0014) /**< basic.consume method id @internal \ + 60, 20; 3932180 */ +/** basic.consume method fields */ +typedef struct amqp_basic_consume_t_ { + uint16_t ticket; /**< ticket */ + amqp_bytes_t queue; /**< queue */ + amqp_bytes_t consumer_tag; /**< consumer-tag */ + amqp_boolean_t no_local; /**< no-local */ + amqp_boolean_t no_ack; /**< no-ack */ + amqp_boolean_t exclusive; /**< exclusive */ + amqp_boolean_t nowait; /**< nowait */ + amqp_table_t arguments; /**< arguments */ +} amqp_basic_consume_t; + +#define AMQP_BASIC_CONSUME_OK_METHOD \ + ((amqp_method_number_t)0x003C0015) /**< basic.consume-ok method id \ + @internal 60, 21; 3932181 */ +/** basic.consume-ok method fields */ +typedef struct amqp_basic_consume_ok_t_ { + amqp_bytes_t consumer_tag; /**< consumer-tag */ +} amqp_basic_consume_ok_t; + +#define AMQP_BASIC_CANCEL_METHOD \ + ((amqp_method_number_t)0x003C001E) /**< basic.cancel method id @internal \ + 60, 30; 3932190 */ +/** basic.cancel method fields */ +typedef struct amqp_basic_cancel_t_ { + amqp_bytes_t consumer_tag; /**< consumer-tag */ + amqp_boolean_t nowait; /**< nowait */ +} amqp_basic_cancel_t; + +#define AMQP_BASIC_CANCEL_OK_METHOD \ + ((amqp_method_number_t)0x003C001F) /**< basic.cancel-ok method id \ + @internal 60, 31; 3932191 */ +/** basic.cancel-ok method fields */ +typedef struct amqp_basic_cancel_ok_t_ { + amqp_bytes_t consumer_tag; /**< consumer-tag */ +} amqp_basic_cancel_ok_t; + +#define AMQP_BASIC_PUBLISH_METHOD \ + ((amqp_method_number_t)0x003C0028) /**< basic.publish method id @internal \ + 60, 40; 3932200 */ +/** basic.publish method fields */ +typedef struct amqp_basic_publish_t_ { + uint16_t ticket; /**< ticket */ + amqp_bytes_t exchange; /**< exchange */ + amqp_bytes_t routing_key; /**< routing-key */ + amqp_boolean_t mandatory; /**< mandatory */ + amqp_boolean_t immediate; /**< immediate */ +} amqp_basic_publish_t; + +#define AMQP_BASIC_RETURN_METHOD \ + ((amqp_method_number_t)0x003C0032) /**< basic.return method id @internal \ + 60, 50; 3932210 */ +/** basic.return method fields */ +typedef struct amqp_basic_return_t_ { + uint16_t reply_code; /**< reply-code */ + amqp_bytes_t reply_text; /**< reply-text */ + amqp_bytes_t exchange; /**< exchange */ + amqp_bytes_t routing_key; /**< routing-key */ +} amqp_basic_return_t; + +#define AMQP_BASIC_DELIVER_METHOD \ + ((amqp_method_number_t)0x003C003C) /**< basic.deliver method id @internal \ + 60, 60; 3932220 */ +/** basic.deliver method fields */ +typedef struct amqp_basic_deliver_t_ { + amqp_bytes_t consumer_tag; /**< consumer-tag */ + uint64_t delivery_tag; /**< delivery-tag */ + amqp_boolean_t redelivered; /**< redelivered */ + amqp_bytes_t exchange; /**< exchange */ + amqp_bytes_t routing_key; /**< routing-key */ +} amqp_basic_deliver_t; + +#define AMQP_BASIC_GET_METHOD \ + ((amqp_method_number_t)0x003C0046) /**< basic.get method id @internal 60, \ + 70; 3932230 */ +/** basic.get method fields */ +typedef struct amqp_basic_get_t_ { + uint16_t ticket; /**< ticket */ + amqp_bytes_t queue; /**< queue */ + amqp_boolean_t no_ack; /**< no-ack */ +} amqp_basic_get_t; + +#define AMQP_BASIC_GET_OK_METHOD \ + ((amqp_method_number_t)0x003C0047) /**< basic.get-ok method id @internal \ + 60, 71; 3932231 */ +/** basic.get-ok method fields */ +typedef struct amqp_basic_get_ok_t_ { + uint64_t delivery_tag; /**< delivery-tag */ + amqp_boolean_t redelivered; /**< redelivered */ + amqp_bytes_t exchange; /**< exchange */ + amqp_bytes_t routing_key; /**< routing-key */ + uint32_t message_count; /**< message-count */ +} amqp_basic_get_ok_t; + +#define AMQP_BASIC_GET_EMPTY_METHOD \ + ((amqp_method_number_t)0x003C0048) /**< basic.get-empty method id \ + @internal 60, 72; 3932232 */ +/** basic.get-empty method fields */ +typedef struct amqp_basic_get_empty_t_ { + amqp_bytes_t cluster_id; /**< cluster-id */ +} amqp_basic_get_empty_t; + +#define AMQP_BASIC_ACK_METHOD \ + ((amqp_method_number_t)0x003C0050) /**< basic.ack method id @internal 60, \ + 80; 3932240 */ +/** basic.ack method fields */ +typedef struct amqp_basic_ack_t_ { + uint64_t delivery_tag; /**< delivery-tag */ + amqp_boolean_t multiple; /**< multiple */ +} amqp_basic_ack_t; + +#define AMQP_BASIC_REJECT_METHOD \ + ((amqp_method_number_t)0x003C005A) /**< basic.reject method id @internal \ + 60, 90; 3932250 */ +/** basic.reject method fields */ +typedef struct amqp_basic_reject_t_ { + uint64_t delivery_tag; /**< delivery-tag */ + amqp_boolean_t requeue; /**< requeue */ +} amqp_basic_reject_t; + +#define AMQP_BASIC_RECOVER_ASYNC_METHOD \ + ((amqp_method_number_t)0x003C0064) /**< basic.recover-async method id \ + @internal 60, 100; 3932260 */ +/** basic.recover-async method fields */ +typedef struct amqp_basic_recover_async_t_ { + amqp_boolean_t requeue; /**< requeue */ +} amqp_basic_recover_async_t; + +#define AMQP_BASIC_RECOVER_METHOD \ + ((amqp_method_number_t)0x003C006E) /**< basic.recover method id @internal \ + 60, 110; 3932270 */ +/** basic.recover method fields */ +typedef struct amqp_basic_recover_t_ { + amqp_boolean_t requeue; /**< requeue */ +} amqp_basic_recover_t; + +#define AMQP_BASIC_RECOVER_OK_METHOD \ + ((amqp_method_number_t)0x003C006F) /**< basic.recover-ok method id \ + @internal 60, 111; 3932271 */ +/** basic.recover-ok method fields */ +typedef struct amqp_basic_recover_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_basic_recover_ok_t; + +#define AMQP_BASIC_NACK_METHOD \ + ((amqp_method_number_t)0x003C0078) /**< basic.nack method id @internal 60, \ + 120; 3932280 */ +/** basic.nack method fields */ +typedef struct amqp_basic_nack_t_ { + uint64_t delivery_tag; /**< delivery-tag */ + amqp_boolean_t multiple; /**< multiple */ + amqp_boolean_t requeue; /**< requeue */ +} amqp_basic_nack_t; + +#define AMQP_TX_SELECT_METHOD \ + ((amqp_method_number_t)0x005A000A) /**< tx.select method id @internal 90, \ + 10; 5898250 */ +/** tx.select method fields */ +typedef struct amqp_tx_select_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_tx_select_t; + +#define AMQP_TX_SELECT_OK_METHOD \ + ((amqp_method_number_t)0x005A000B) /**< tx.select-ok method id @internal \ + 90, 11; 5898251 */ +/** tx.select-ok method fields */ +typedef struct amqp_tx_select_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_tx_select_ok_t; + +#define AMQP_TX_COMMIT_METHOD \ + ((amqp_method_number_t)0x005A0014) /**< tx.commit method id @internal 90, \ + 20; 5898260 */ +/** tx.commit method fields */ +typedef struct amqp_tx_commit_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_tx_commit_t; + +#define AMQP_TX_COMMIT_OK_METHOD \ + ((amqp_method_number_t)0x005A0015) /**< tx.commit-ok method id @internal \ + 90, 21; 5898261 */ +/** tx.commit-ok method fields */ +typedef struct amqp_tx_commit_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_tx_commit_ok_t; + +#define AMQP_TX_ROLLBACK_METHOD \ + ((amqp_method_number_t)0x005A001E) /**< tx.rollback method id @internal \ + 90, 30; 5898270 */ +/** tx.rollback method fields */ +typedef struct amqp_tx_rollback_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_tx_rollback_t; + +#define AMQP_TX_ROLLBACK_OK_METHOD \ + ((amqp_method_number_t)0x005A001F) /**< tx.rollback-ok method id @internal \ + 90, 31; 5898271 */ +/** tx.rollback-ok method fields */ +typedef struct amqp_tx_rollback_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_tx_rollback_ok_t; + +#define AMQP_CONFIRM_SELECT_METHOD \ + ((amqp_method_number_t)0x0055000A) /**< confirm.select method id @internal \ + 85, 10; 5570570 */ +/** confirm.select method fields */ +typedef struct amqp_confirm_select_t_ { + amqp_boolean_t nowait; /**< nowait */ +} amqp_confirm_select_t; + +#define AMQP_CONFIRM_SELECT_OK_METHOD \ + ((amqp_method_number_t)0x0055000B) /**< confirm.select-ok method id \ + @internal 85, 11; 5570571 */ +/** confirm.select-ok method fields */ +typedef struct amqp_confirm_select_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_confirm_select_ok_t; + +/* Class property records. */ +#define AMQP_CONNECTION_CLASS \ + (0x000A) /**< connection class id @internal 10 \ + */ +/** connection class properties */ +typedef struct amqp_connection_properties_t_ { + amqp_flags_t _flags; /**< bit-mask of set fields */ + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_connection_properties_t; + +#define AMQP_CHANNEL_CLASS (0x0014) /**< channel class id @internal 20 */ +/** channel class properties */ +typedef struct amqp_channel_properties_t_ { + amqp_flags_t _flags; /**< bit-mask of set fields */ + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_channel_properties_t; + +#define AMQP_ACCESS_CLASS (0x001E) /**< access class id @internal 30 */ +/** access class properties */ +typedef struct amqp_access_properties_t_ { + amqp_flags_t _flags; /**< bit-mask of set fields */ + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_access_properties_t; + +#define AMQP_EXCHANGE_CLASS (0x0028) /**< exchange class id @internal 40 */ +/** exchange class properties */ +typedef struct amqp_exchange_properties_t_ { + amqp_flags_t _flags; /**< bit-mask of set fields */ + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_exchange_properties_t; + +#define AMQP_QUEUE_CLASS (0x0032) /**< queue class id @internal 50 */ +/** queue class properties */ +typedef struct amqp_queue_properties_t_ { + amqp_flags_t _flags; /**< bit-mask of set fields */ + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_queue_properties_t; + +#define AMQP_BASIC_CLASS (0x003C) /**< basic class id @internal 60 */ +#define AMQP_BASIC_CONTENT_TYPE_FLAG (1 << 15) +#define AMQP_BASIC_CONTENT_ENCODING_FLAG (1 << 14) +#define AMQP_BASIC_HEADERS_FLAG (1 << 13) +#define AMQP_BASIC_DELIVERY_MODE_FLAG (1 << 12) +#define AMQP_BASIC_PRIORITY_FLAG (1 << 11) +#define AMQP_BASIC_CORRELATION_ID_FLAG (1 << 10) +#define AMQP_BASIC_REPLY_TO_FLAG (1 << 9) +#define AMQP_BASIC_EXPIRATION_FLAG (1 << 8) +#define AMQP_BASIC_MESSAGE_ID_FLAG (1 << 7) +#define AMQP_BASIC_TIMESTAMP_FLAG (1 << 6) +#define AMQP_BASIC_TYPE_FLAG (1 << 5) +#define AMQP_BASIC_USER_ID_FLAG (1 << 4) +#define AMQP_BASIC_APP_ID_FLAG (1 << 3) +#define AMQP_BASIC_CLUSTER_ID_FLAG (1 << 2) +/** basic class properties */ +typedef struct amqp_basic_properties_t_ { + amqp_flags_t _flags; /**< bit-mask of set fields */ + amqp_bytes_t content_type; /**< content-type */ + amqp_bytes_t content_encoding; /**< content-encoding */ + amqp_table_t headers; /**< headers */ + uint8_t delivery_mode; /**< delivery-mode */ + uint8_t priority; /**< priority */ + amqp_bytes_t correlation_id; /**< correlation-id */ + amqp_bytes_t reply_to; /**< reply-to */ + amqp_bytes_t expiration; /**< expiration */ + amqp_bytes_t message_id; /**< message-id */ + uint64_t timestamp; /**< timestamp */ + amqp_bytes_t type; /**< type */ + amqp_bytes_t user_id; /**< user-id */ + amqp_bytes_t app_id; /**< app-id */ + amqp_bytes_t cluster_id; /**< cluster-id */ +} amqp_basic_properties_t; + +#define AMQP_TX_CLASS (0x005A) /**< tx class id @internal 90 */ +/** tx class properties */ +typedef struct amqp_tx_properties_t_ { + amqp_flags_t _flags; /**< bit-mask of set fields */ + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_tx_properties_t; + +#define AMQP_CONFIRM_CLASS (0x0055) /**< confirm class id @internal 85 */ +/** confirm class properties */ +typedef struct amqp_confirm_properties_t_ { + amqp_flags_t _flags; /**< bit-mask of set fields */ + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_confirm_properties_t; + +/* API functions for methods */ + +/** + * amqp_channel_open + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @returns amqp_channel_open_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_channel_open_ok_t *AMQP_CALL + amqp_channel_open(amqp_connection_state_t state, amqp_channel_t channel); +/** + * amqp_channel_flow + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] active active + * @returns amqp_channel_flow_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_channel_flow_ok_t *AMQP_CALL + amqp_channel_flow(amqp_connection_state_t state, amqp_channel_t channel, + amqp_boolean_t active); +/** + * amqp_exchange_declare + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] exchange exchange + * @param [in] type type + * @param [in] passive passive + * @param [in] durable durable + * @param [in] auto_delete auto_delete + * @param [in] internal internal + * @param [in] arguments arguments + * @returns amqp_exchange_declare_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_exchange_declare_ok_t *AMQP_CALL amqp_exchange_declare( + amqp_connection_state_t state, amqp_channel_t channel, + amqp_bytes_t exchange, amqp_bytes_t type, amqp_boolean_t passive, + amqp_boolean_t durable, amqp_boolean_t auto_delete, amqp_boolean_t internal, + amqp_table_t arguments); +/** + * amqp_exchange_delete + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] exchange exchange + * @param [in] if_unused if_unused + * @returns amqp_exchange_delete_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_exchange_delete_ok_t *AMQP_CALL + amqp_exchange_delete(amqp_connection_state_t state, amqp_channel_t channel, + amqp_bytes_t exchange, amqp_boolean_t if_unused); +/** + * amqp_exchange_bind + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] destination destination + * @param [in] source source + * @param [in] routing_key routing_key + * @param [in] arguments arguments + * @returns amqp_exchange_bind_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_exchange_bind_ok_t *AMQP_CALL + amqp_exchange_bind(amqp_connection_state_t state, amqp_channel_t channel, + amqp_bytes_t destination, amqp_bytes_t source, + amqp_bytes_t routing_key, amqp_table_t arguments); +/** + * amqp_exchange_unbind + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] destination destination + * @param [in] source source + * @param [in] routing_key routing_key + * @param [in] arguments arguments + * @returns amqp_exchange_unbind_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_exchange_unbind_ok_t *AMQP_CALL + amqp_exchange_unbind(amqp_connection_state_t state, amqp_channel_t channel, + amqp_bytes_t destination, amqp_bytes_t source, + amqp_bytes_t routing_key, amqp_table_t arguments); +/** + * amqp_queue_declare + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] queue queue + * @param [in] passive passive + * @param [in] durable durable + * @param [in] exclusive exclusive + * @param [in] auto_delete auto_delete + * @param [in] arguments arguments + * @returns amqp_queue_declare_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_queue_declare_ok_t *AMQP_CALL amqp_queue_declare( + amqp_connection_state_t state, amqp_channel_t channel, amqp_bytes_t queue, + amqp_boolean_t passive, amqp_boolean_t durable, amqp_boolean_t exclusive, + amqp_boolean_t auto_delete, amqp_table_t arguments); +/** + * amqp_queue_bind + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] queue queue + * @param [in] exchange exchange + * @param [in] routing_key routing_key + * @param [in] arguments arguments + * @returns amqp_queue_bind_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_queue_bind_ok_t *AMQP_CALL amqp_queue_bind( + amqp_connection_state_t state, amqp_channel_t channel, amqp_bytes_t queue, + amqp_bytes_t exchange, amqp_bytes_t routing_key, amqp_table_t arguments); +/** + * amqp_queue_purge + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] queue queue + * @returns amqp_queue_purge_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_queue_purge_ok_t *AMQP_CALL amqp_queue_purge(amqp_connection_state_t state, + amqp_channel_t channel, + amqp_bytes_t queue); +/** + * amqp_queue_delete + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] queue queue + * @param [in] if_unused if_unused + * @param [in] if_empty if_empty + * @returns amqp_queue_delete_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_queue_delete_ok_t *AMQP_CALL amqp_queue_delete( + amqp_connection_state_t state, amqp_channel_t channel, amqp_bytes_t queue, + amqp_boolean_t if_unused, amqp_boolean_t if_empty); +/** + * amqp_queue_unbind + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] queue queue + * @param [in] exchange exchange + * @param [in] routing_key routing_key + * @param [in] arguments arguments + * @returns amqp_queue_unbind_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_queue_unbind_ok_t *AMQP_CALL amqp_queue_unbind( + amqp_connection_state_t state, amqp_channel_t channel, amqp_bytes_t queue, + amqp_bytes_t exchange, amqp_bytes_t routing_key, amqp_table_t arguments); +/** + * amqp_basic_qos + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] prefetch_size prefetch_size + * @param [in] prefetch_count prefetch_count + * @param [in] global global + * @returns amqp_basic_qos_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_basic_qos_ok_t *AMQP_CALL amqp_basic_qos(amqp_connection_state_t state, + amqp_channel_t channel, + uint32_t prefetch_size, + uint16_t prefetch_count, + amqp_boolean_t global); +/** + * amqp_basic_consume + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] queue queue + * @param [in] consumer_tag consumer_tag + * @param [in] no_local no_local + * @param [in] no_ack no_ack + * @param [in] exclusive exclusive + * @param [in] arguments arguments + * @returns amqp_basic_consume_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_basic_consume_ok_t *AMQP_CALL amqp_basic_consume( + amqp_connection_state_t state, amqp_channel_t channel, amqp_bytes_t queue, + amqp_bytes_t consumer_tag, amqp_boolean_t no_local, amqp_boolean_t no_ack, + amqp_boolean_t exclusive, amqp_table_t arguments); +/** + * amqp_basic_cancel + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] consumer_tag consumer_tag + * @returns amqp_basic_cancel_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_basic_cancel_ok_t *AMQP_CALL + amqp_basic_cancel(amqp_connection_state_t state, amqp_channel_t channel, + amqp_bytes_t consumer_tag); +/** + * amqp_basic_recover + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] requeue requeue + * @returns amqp_basic_recover_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_basic_recover_ok_t *AMQP_CALL + amqp_basic_recover(amqp_connection_state_t state, amqp_channel_t channel, + amqp_boolean_t requeue); +/** + * amqp_tx_select + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @returns amqp_tx_select_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_tx_select_ok_t *AMQP_CALL amqp_tx_select(amqp_connection_state_t state, + amqp_channel_t channel); +/** + * amqp_tx_commit + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @returns amqp_tx_commit_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_tx_commit_ok_t *AMQP_CALL amqp_tx_commit(amqp_connection_state_t state, + amqp_channel_t channel); +/** + * amqp_tx_rollback + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @returns amqp_tx_rollback_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_tx_rollback_ok_t *AMQP_CALL amqp_tx_rollback(amqp_connection_state_t state, + amqp_channel_t channel); +/** + * amqp_confirm_select + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @returns amqp_confirm_select_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_confirm_select_ok_t *AMQP_CALL + amqp_confirm_select(amqp_connection_state_t state, amqp_channel_t channel); + +AMQP_END_DECLS + +#endif /* AMQP_FRAMING_H */ diff --git a/ext/librabbitmq/macos/include/amqp_tcp_socket.h b/ext/librabbitmq/macos/include/amqp_tcp_socket.h new file mode 100644 index 000000000..3e9d82f54 --- /dev/null +++ b/ext/librabbitmq/macos/include/amqp_tcp_socket.h @@ -0,0 +1,68 @@ +/** \file */ +/* + * Portions created by Alan Antonuk are Copyright (c) 2013-2014 Alan Antonuk. + * All Rights Reserved. + * + * Portions created by Michael Steinert are Copyright (c) 2012-2013 Michael + * Steinert. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * A TCP socket connection. + */ + +#ifndef AMQP_TCP_SOCKET_H +#define AMQP_TCP_SOCKET_H + +#include + +AMQP_BEGIN_DECLS + +/** + * Create a new TCP socket. + * + * Call amqp_connection_close() to release socket resources. + * + * \return A new socket object or NULL if an error occurred. + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +amqp_socket_t *AMQP_CALL amqp_tcp_socket_new(amqp_connection_state_t state); + +/** + * Assign an open file descriptor to a socket object. + * + * This function must not be used in conjunction with amqp_socket_open(), i.e. + * the socket connection should already be open(2) when this function is + * called. + * + * \param [in,out] self A TCP socket object. + * \param [in] sockfd An open socket descriptor. + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +void AMQP_CALL amqp_tcp_socket_set_sockfd(amqp_socket_t *self, int sockfd); + +AMQP_END_DECLS + +#endif /* AMQP_TCP_SOCKET_H */ diff --git a/ext/librabbitmq/macos/lib/librabbitmq.a b/ext/librabbitmq/macos/lib/librabbitmq.a new file mode 100644 index 0000000000000000000000000000000000000000..f3d27b31dcda47dde6601e85aa5901ff1b3a66d0 GIT binary patch literal 95704 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 |g!EiVi5*iarI=?_M9XGjw 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 Date: Thu, 31 Oct 2019 15:08:59 -0700 Subject: [PATCH 02/10] use std::string instead of const char* in rmq struct --- controller/RabbitMQ.cpp | 5 +++-- controller/RabbitMQ.hpp | 9 +++++---- service/OneService.cpp | 6 +++--- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/controller/RabbitMQ.cpp b/controller/RabbitMQ.cpp index 41ebcc87c..73af1ccd3 100644 --- a/controller/RabbitMQ.cpp +++ b/controller/RabbitMQ.cpp @@ -51,13 +51,14 @@ void RabbitMQ::init() throw std::runtime_error("Can't create socket for RabbitMQ"); } - _status = amqp_socket_open_noblock(_socket, _mqc->host, _mqc->port, &tval); + fprintf(stderr, "RabbitMQ: amqp://%s:%s@%s:%d\n", _mqc->username.c_str(), _mqc->password.c_str(), _mqc->host.c_str(), _mqc->port); + _status = amqp_socket_open_noblock(_socket, _mqc->host.c_str(), _mqc->port, &tval); if (_status) { throw std::runtime_error("Can't connect to RabbitMQ"); } amqp_rpc_reply_t r = amqp_login(_conn, "/", 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, - _mqc->username, _mqc->password); + _mqc->username.c_str(), _mqc->password.c_str()); if (r.reply_type != AMQP_RESPONSE_NORMAL) { throw std::runtime_error("RabbitMQ Login Error"); } diff --git a/controller/RabbitMQ.hpp b/controller/RabbitMQ.hpp index c60af8ecf..4c286288e 100644 --- a/controller/RabbitMQ.hpp +++ b/controller/RabbitMQ.hpp @@ -15,14 +15,15 @@ #define ZT_CONTROLLER_RABBITMQ_HPP #include "DB.hpp" +#include namespace ZeroTier { struct MQConfig { - const char *host; + std::string host; int port; - const char *username; - const char *password; + std::string username; + std::string password; }; } @@ -32,7 +33,7 @@ struct MQConfig { #include #include -#include + namespace ZeroTier { diff --git a/service/OneService.cpp b/service/OneService.cpp index 69b439ae6..18e9240ae 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -990,9 +990,9 @@ public: fprintf(stderr, "Reading RabbitMQ Config\n"); _mqc = new MQConfig; _mqc->port = rmq["port"]; - _mqc->host = OSUtils::jsonString(rmq["host"], "").c_str(); - _mqc->username = OSUtils::jsonString(rmq["username"], "").c_str(); - _mqc->password = OSUtils::jsonString(rmq["password"], "").c_str(); + _mqc->host = OSUtils::jsonString(rmq["host"], ""); + _mqc->username = OSUtils::jsonString(rmq["username"], ""); + _mqc->password = OSUtils::jsonString(rmq["password"], ""); } // Bind to wildcard instead of to specific interfaces (disables full tunnel capability) From 088dab4f04d7ec662b83299a32d7183d5d48a5dc Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Thu, 31 Oct 2019 15:13:20 -0700 Subject: [PATCH 03/10] Let's not print this to the logs --- controller/RabbitMQ.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/controller/RabbitMQ.cpp b/controller/RabbitMQ.cpp index 73af1ccd3..29a331ad2 100644 --- a/controller/RabbitMQ.cpp +++ b/controller/RabbitMQ.cpp @@ -51,7 +51,6 @@ void RabbitMQ::init() throw std::runtime_error("Can't create socket for RabbitMQ"); } - fprintf(stderr, "RabbitMQ: amqp://%s:%s@%s:%d\n", _mqc->username.c_str(), _mqc->password.c_str(), _mqc->host.c_str(), _mqc->port); _status = amqp_socket_open_noblock(_socket, _mqc->host.c_str(), _mqc->port, &tval); if (_status) { throw std::runtime_error("Can't connect to RabbitMQ"); From e1e27eb19d2ff122333e1e9a192a9516335fd087 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Mon, 11 Nov 2019 12:03:49 -0800 Subject: [PATCH 04/10] Bugfix for incorrect port binding of secondary and tertiary ports --- service/OneService.cpp | 56 +++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/service/OneService.cpp b/service/OneService.cpp index 18e9240ae..d2e4957ec 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -678,44 +678,50 @@ public: // than one device behind the same NAT tries to use the same internal // private address port number. Buggy NATs are a running theme. if (_allowSecondaryPort) { - _ports[1] = (_secondaryPort == 0) ? 20000 + ((unsigned int)_node->address() % 45500) : _secondaryPort; - for(int i=0;;++i) { - if (i > 1000) { - _ports[1] = 0; - break; - } else if (++_ports[1] >= 65536) { - _ports[1] = 20000; + if (_secondaryPort) { + _ports[1] = _secondaryPort; + } else { + _ports[1] = 20000 + ((unsigned int)_node->address() % 45500); + for(int i=0;;++i) { + if (i > 1000) { + _ports[1] = 0; + break; + } else if (++_ports[1] >= 65536) { + _ports[1] = 20000; + } + if (_trialBind(_ports[1])) + break; } - if (_trialBind(_ports[1])) - break; } } - #ifdef ZT_USE_MINIUPNPC if (_portMappingEnabled) { // If we're running uPnP/NAT-PMP, bind a *third* port for that. We can't // use the other two ports for that because some NATs do really funky // stuff with ports that are explicitly mapped that breaks things. if (_ports[1]) { - _ports[2] = (_tertiaryPort == 0) ? _ports[1] : _tertiaryPort; - for(int i=0;;++i) { - if (i > 1000) { - _ports[2] = 0; - break; - } else if (++_ports[2] >= 65536) { - _ports[2] = 20000; + if (_tertiaryPort) { + _ports[2] = _tertiaryPort; + } else { + _ports[2] = _ports[1]; + for(int i=0;;++i) { + if (i > 1000) { + _ports[2] = 0; + break; + } else if (++_ports[2] >= 65536) { + _ports[2] = 20000; + } + if (_trialBind(_ports[2])) + break; + } + if (_ports[2]) { + char uniqueName[64]; + OSUtils::ztsnprintf(uniqueName,sizeof(uniqueName),"ZeroTier/%.10llx@%u",_node->address(),_ports[2]); + _portMapper = new PortMapper(_ports[2],uniqueName); } - if (_trialBind(_ports[2])) - break; - } - if (_ports[2]) { - char uniqueName[64]; - OSUtils::ztsnprintf(uniqueName,sizeof(uniqueName),"ZeroTier/%.10llx@%u",_node->address(),_ports[2]); - _portMapper = new PortMapper(_ports[2],uniqueName); } } } -#endif // Delete legacy iddb.d if present (cleanup) OSUtils::rmDashRf((_homePath + ZT_PATH_SEPARATOR_S "iddb.d").c_str()); From b8e70d866a16ef26d782e4a0b074a124c2cb4212 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Tue, 12 Nov 2019 09:46:39 -0800 Subject: [PATCH 05/10] Compile fix for unterminated conditional directive --- service/OneService.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/OneService.cpp b/service/OneService.cpp index d2e4957ec..97ba1a362 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -722,7 +722,7 @@ public: } } } - +#endif // Delete legacy iddb.d if present (cleanup) OSUtils::rmDashRf((_homePath + ZT_PATH_SEPARATOR_S "iddb.d").c_str()); From 86abd31659d385b52d329cfcf8b6e203b8c85a46 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Wed, 13 Nov 2019 12:46:16 -0800 Subject: [PATCH 06/10] fix log line --- controller/PostgreSQL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller/PostgreSQL.cpp b/controller/PostgreSQL.cpp index 08e06ee98..8f8c2785a 100644 --- a/controller/PostgreSQL.cpp +++ b/controller/PostgreSQL.cpp @@ -760,7 +760,7 @@ void PostgreSQL::networksDbWatcher() fprintf(stderr, "ERROR: %s networksDbWatcher should still be running! Exiting Controller.\n", _myAddressStr.c_str()); exit(8); } - fprintf(stderr, "Exited membersDbWatcher\n"); + fprintf(stderr, "Exited networksDbWatcher\n"); } void PostgreSQL::_networksWatcher_Postgres(PGconn *conn) { From dc19deb6c3f23bb3dec7d4141a57b09369138313 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Wed, 13 Nov 2019 12:46:52 -0800 Subject: [PATCH 07/10] . --- .gitignore | 1 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 ++++++++ 2 files changed, 9 insertions(+) create mode 100644 macui/ZeroTier One.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/.gitignore b/.gitignore index 44b5eb56b..62a6c6a17 100755 --- a/.gitignore +++ b/.gitignore @@ -120,3 +120,4 @@ __pycache__ *~ attic/world/*.c25519 attic/world/mkworld +workspace/ diff --git a/macui/ZeroTier One.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/macui/ZeroTier One.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/macui/ZeroTier One.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + From 381f15382c2ec06c77fe2d54a0208010248f935c Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Wed, 20 Nov 2019 13:56:26 -0800 Subject: [PATCH 08/10] Convert central-controller docker build to use a builder subcontainer --- ext/central-controller-docker/Dockerfile | 19 +++++++++++++------ make-linux.mk | 4 ++-- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/ext/central-controller-docker/Dockerfile b/ext/central-controller-docker/Dockerfile index 2fc92e6f9..716390f82 100644 --- a/ext/central-controller-docker/Dockerfile +++ b/ext/central-controller-docker/Dockerfile @@ -1,19 +1,26 @@ # Dockerfile for ZeroTier Central Controllers -FROM centos:7 +FROM centos:7 as builder MAINTAINER Adam Ierymekno , Grant Limberg +ARG git_branch=master + RUN yum update -y RUN yum install -y https://download.postgresql.org/pub/repos/yum/10/redhat/rhel-7-x86_64/pgdg-centos10-10-2.noarch.rpm -RUN yum install -y bash postgresql10 libpqxx-devel - RUN yum -y install epel-release && yum -y update && yum clean all -RUN yum -y install clang jemalloc jemalloc-devel +RUN yum groupinstall -y "Development Tools" +RUN yum install -y bash postgresql10 postgresql10-devel libpqxx-devel glibc-static libstdc++-static clang jemalloc jemalloc-devel +RUN git clone http://git.int.zerotier.com/zerotier/ZeroTierOne.git +RUN if [ "$git_branch" != "master" ]; then cd ZeroTierOne && git checkout -b $git_branch origin/$git_branch; fi +RUN ldconfig +RUN cd ZeroTierOne && make central-controller -ADD zerotier-one /usr/local/bin/zerotier-one +FROM centos:7 + +COPY --from=builder /ZeroTierOne/zerotier-one /usr/local/bin/zerotier-one RUN chmod a+x /usr/local/bin/zerotier-one -ADD docker/main.sh / +ADD ext/central-controller-docker/main.sh / RUN chmod a+x /main.sh ENTRYPOINT /main.sh diff --git a/make-linux.mk b/make-linux.mk index 9fd4f7b95..b31811437 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -334,8 +334,8 @@ docker: FORCE central-controller: FORCE make -j4 LDLIBS="-L/usr/pgsql-10/lib/ -lpq -Lext/librabbitmq/centos_x64/lib/ -lrabbitmq" CXXFLAGS="-I/usr/pgsql-10/include -I./ext/librabbitmq/centos_x64/include -fPIC" DEFS="-DZT_CONTROLLER_USE_LIBPQ -DZT_CONTROLLER" ZT_OFFICIAL=1 ZT_USE_X64_ASM_ED25519=1 one -central-controller-docker: central-controller - docker build -t docker.zerotier.com/zerotier-central/ztcentral-controller:${TIMESTAMP} -f ext/central-controller-docker/Dockerfile . +central-controller-docker: FORCE + docker build -t docker.zerotier.com/zerotier-central/ztcentral-controller:${TIMESTAMP} -f ext/central-controller-docker/Dockerfile --build-arg git_branch=`git name-rev --name-only HEAD` . debug: FORCE make ZT_DEBUG=1 one From e58a0b3efbbd415fa135d16f613127cd4770adfc Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Thu, 21 Nov 2019 14:49:24 -0800 Subject: [PATCH 09/10] build central controller docker images on macOS --- make-mac.mk | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/make-mac.mk b/make-mac.mk index 545dabee8..62df1f6fa 100644 --- a/make-mac.mk +++ b/make-mac.mk @@ -16,6 +16,9 @@ ZT_VERSION_MINOR=$(shell cat version.h | grep -F VERSION_MINOR | cut -d ' ' -f 3 ZT_VERSION_REV=$(shell cat version.h | grep -F VERSION_REVISION | cut -d ' ' -f 3) ZT_VERSION_BUILD=$(shell cat version.h | grep -F VERSION_BUILD | cut -d ' ' -f 3) +# for central controller builds +TIMESTAMP=$(shell date +"%Y%m%d%H%M") + DEFS+=-DZT_BUILD_PLATFORM=$(ZT_BUILD_PLATFORM) -DZT_BUILD_ARCHITECTURE=$(ZT_BUILD_ARCHITECTURE) include objects.mk @@ -140,6 +143,9 @@ official: FORCE make ZT_OFFICIAL_RELEASE=1 macui make ZT_OFFICIAL_RELEASE=1 mac-dist-pkg +central-controller-docker: FORCE + docker build -t docker.zerotier.com/zerotier-central/ztcentral-controller:${TIMESTAMP} -f ext/central-controller-docker/Dockerfile --build-arg git_branch=$(shell git name-rev --name-only HEAD) . + clean: rm -rf MacEthernetTapAgent *.dSYM build-* *.a *.pkg *.dmg *.o node/*.o controller/*.o service/*.o osdep/*.o ext/http-parser/*.o $(CORE_OBJS) $(ONE_OBJS) zerotier-one zerotier-idtool zerotier-selftest zerotier-cli zerotier doc/node_modules macui/build zt1_update_$(ZT_BUILD_PLATFORM)_$(ZT_BUILD_ARCHITECTURE)_* From 54e25084feb1d5994650d3e104c56e8de48ce3f9 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Thu, 21 Nov 2019 14:51:33 -0800 Subject: [PATCH 10/10] re-enable CI on master --- Jenkinsfile | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 88989327e..edb0c69e6 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -40,26 +40,26 @@ parallel 'centos7': { // throw err // } // } -// }, 'macOS': { -// node('macOS') { -// try { -// checkout scm +}, 'macOS': { + node('macOS') { + try { + checkout scm -// stage('Build macOS') { -// sh 'make -f make-mac.mk' -// } + stage('Build macOS') { + sh 'make -f make-mac.mk' + } -// stage('Build macOS UI') { -// sh 'cd macui && xcodebuild -target "ZeroTier One" -configuration Debug' -// } -// } -// catch (err) { -// currentBuild.result = "FAILURE" -// mattermostSend color: '#ff0000', message: "${env.JOB_NAME} broken on macOS (<${env.BUILD_URL}|Open>)" + stage('Build macOS UI') { + sh 'cd macui && xcodebuild -target "ZeroTier One" -configuration Debug' + } + } + catch (err) { + currentBuild.result = "FAILURE" + mattermostSend color: '#ff0000', message: "${env.JOB_NAME} broken on macOS (<${env.BUILD_URL}|Open>)" -// throw err -// } -// } + throw err + } + } // }, 'windows': { // node('windows') { // try {