+static char *camqp_bytes_cstring (amqp_bytes_t *in) /* {{{ */
+{
+ char *ret;
+
+ if ((in == NULL) || (in->bytes == NULL))
+ return (NULL);
+
+ ret = malloc (in->len + 1);
+ if (ret == NULL)
+ return (NULL);
+
+ memcpy (ret, in->bytes, in->len);
+ ret[in->len] = 0;
+
+ return (ret);
+} /* }}} char *camqp_bytes_cstring */
+
+static _Bool camqp_is_error (camqp_config_t *conf) /* {{{ */
+{
+ amqp_rpc_reply_t r;
+
+ r = amqp_get_rpc_reply (conf->connection);
+ if (r.reply_type == AMQP_RESPONSE_NORMAL)
+ return (0);
+
+ return (1);
+} /* }}} _Bool camqp_is_error */
+
+static char *camqp_strerror (camqp_config_t *conf, /* {{{ */
+ char *buffer, size_t buffer_size)
+{
+ amqp_rpc_reply_t r;
+
+ r = amqp_get_rpc_reply (conf->connection);
+ switch (r.reply_type)
+ {
+ case AMQP_RESPONSE_NORMAL:
+ sstrncpy (buffer, "Success", sizeof (buffer));
+ break;
+
+ case AMQP_RESPONSE_NONE:
+ sstrncpy (buffer, "Missing RPC reply type", sizeof (buffer));
+ break;
+
+ case AMQP_RESPONSE_LIBRARY_EXCEPTION:
+#if HAVE_AMQP_RPC_REPLY_T_LIBRARY_ERRNO
+ if (r.library_errno)
+ return (sstrerror (r.library_errno, buffer, buffer_size));
+#else
+ if (r.library_error)
+ return (sstrerror (r.library_error, buffer, buffer_size));
+#endif
+ else
+ sstrncpy (buffer, "End of stream", sizeof (buffer));
+ break;
+
+ case AMQP_RESPONSE_SERVER_EXCEPTION:
+ if (r.reply.id == AMQP_CONNECTION_CLOSE_METHOD)
+ {
+ amqp_connection_close_t *m = r.reply.decoded;
+ char *tmp = camqp_bytes_cstring (&m->reply_text);
+ ssnprintf (buffer, buffer_size, "Server connection error %d: %s",
+ m->reply_code, tmp);
+ sfree (tmp);
+ }
+ else if (r.reply.id == AMQP_CHANNEL_CLOSE_METHOD)
+ {
+ amqp_channel_close_t *m = r.reply.decoded;
+ char *tmp = camqp_bytes_cstring (&m->reply_text);
+ ssnprintf (buffer, buffer_size, "Server channel error %d: %s",
+ m->reply_code, tmp);
+ sfree (tmp);
+ }
+ else
+ {
+ ssnprintf (buffer, buffer_size, "Server error method %#"PRIx32,
+ r.reply.id);
+ }
+ break;
+
+ default:
+ ssnprintf (buffer, buffer_size, "Unknown reply type %i",
+ (int) r.reply_type);
+ }
+
+ return (buffer);
+} /* }}} char *camqp_strerror */
+
+#if HAVE_AMQP_RPC_REPLY_T_LIBRARY_ERRNO
+static int camqp_create_exchange (camqp_config_t *conf) /* {{{ */
+{
+ amqp_exchange_declare_ok_t *ed_ret;
+
+ if (conf->exchange_type == NULL)
+ return (0);
+
+ ed_ret = amqp_exchange_declare (conf->connection,
+ /* channel = */ CAMQP_CHANNEL,
+ /* exchange = */ amqp_cstring_bytes (conf->exchange),
+ /* type = */ amqp_cstring_bytes (conf->exchange_type),
+ /* passive = */ 0,
+ /* durable = */ 0,
+ /* auto_delete = */ 1,
+ /* arguments = */ AMQP_EMPTY_TABLE);
+ if ((ed_ret == NULL) && camqp_is_error (conf))
+ {
+ char errbuf[1024];
+ ERROR ("amqp plugin: amqp_exchange_declare failed: %s",
+ camqp_strerror (conf, errbuf, sizeof (errbuf)));
+ camqp_close_connection (conf);
+ return (-1);
+ }
+
+ INFO ("amqp plugin: Successfully created exchange \"%s\" "
+ "with type \"%s\".",
+ conf->exchange, conf->exchange_type);
+
+ return (0);
+} /* }}} int camqp_create_exchange */
+#else
+static int camqp_create_exchange (camqp_config_t *conf) /* {{{ */
+{
+ amqp_exchange_declare_ok_t *ed_ret;
+ amqp_table_t argument_table;
+ struct amqp_table_entry_t_ argument_table_entries[1];
+
+ if (conf->exchange_type == NULL)
+ return (0);
+
+ /* Valid arguments: "auto_delete", "internal" */
+ argument_table.num_entries = STATIC_ARRAY_SIZE (argument_table_entries);
+ argument_table.entries = argument_table_entries;
+ argument_table_entries[0].key = amqp_cstring_bytes ("auto_delete");
+ argument_table_entries[0].value.kind = AMQP_FIELD_KIND_BOOLEAN;
+ argument_table_entries[0].value.value.boolean = 1;
+
+ ed_ret = amqp_exchange_declare (conf->connection,
+ /* channel = */ CAMQP_CHANNEL,
+ /* exchange = */ amqp_cstring_bytes (conf->exchange),
+ /* type = */ amqp_cstring_bytes (conf->exchange_type),
+ /* passive = */ 0,
+ /* durable = */ 0,
+ /* arguments = */ argument_table);
+ if ((ed_ret == NULL) && camqp_is_error (conf))
+ {
+ char errbuf[1024];
+ ERROR ("amqp plugin: amqp_exchange_declare failed: %s",
+ camqp_strerror (conf, errbuf, sizeof (errbuf)));
+ camqp_close_connection (conf);
+ return (-1);
+ }
+
+ INFO ("amqp plugin: Successfully created exchange \"%s\" "
+ "with type \"%s\".",
+ conf->exchange, conf->exchange_type);
+
+ return (0);
+} /* }}} int camqp_create_exchange */
+#endif
+
+static int camqp_setup_queue (camqp_config_t *conf) /* {{{ */
+{
+ amqp_queue_declare_ok_t *qd_ret;
+ amqp_basic_consume_ok_t *cm_ret;
+
+ qd_ret = amqp_queue_declare (conf->connection,
+ /* channel = */ CAMQP_CHANNEL,
+ /* queue = */ (conf->queue != NULL)
+ ? amqp_cstring_bytes (conf->queue)
+ : AMQP_EMPTY_BYTES,
+ /* passive = */ 0,
+ /* durable = */ 0,
+ /* exclusive = */ 0,
+ /* auto_delete = */ 1,
+ /* arguments = */ AMQP_EMPTY_TABLE);
+ if (qd_ret == NULL)
+ {
+ ERROR ("amqp plugin: amqp_queue_declare failed.");
+ camqp_close_connection (conf);
+ return (-1);
+ }
+
+ if (conf->queue == NULL)
+ {
+ conf->queue = camqp_bytes_cstring (&qd_ret->queue);
+ if (conf->queue == NULL)
+ {
+ ERROR ("amqp plugin: camqp_bytes_cstring failed.");
+ camqp_close_connection (conf);
+ return (-1);
+ }
+
+ INFO ("amqp plugin: Created queue \"%s\".", conf->queue);
+ }
+ DEBUG ("amqp plugin: Successfully created queue \"%s\".", conf->queue);
+
+ /* bind to an exchange */
+ if (conf->exchange != NULL)
+ {
+ amqp_queue_bind_ok_t *qb_ret;
+
+ assert (conf->queue != NULL);
+ qb_ret = amqp_queue_bind (conf->connection,
+ /* channel = */ CAMQP_CHANNEL,
+ /* queue = */ amqp_cstring_bytes (conf->queue),
+ /* exchange = */ amqp_cstring_bytes (conf->exchange),
+ /* routing_key = */ (conf->routing_key != NULL)
+ ? amqp_cstring_bytes (conf->routing_key)
+ : AMQP_EMPTY_BYTES,
+ /* arguments = */ AMQP_EMPTY_TABLE);
+ if ((qb_ret == NULL) && camqp_is_error (conf))
+ {
+ char errbuf[1024];
+ ERROR ("amqp plugin: amqp_queue_bind failed: %s",
+ camqp_strerror (conf, errbuf, sizeof (errbuf)));
+ camqp_close_connection (conf);
+ return (-1);
+ }
+
+ DEBUG ("amqp plugin: Successfully bound queue \"%s\" to exchange \"%s\".",
+ conf->queue, conf->exchange);
+ } /* if (conf->exchange != NULL) */
+
+ cm_ret = amqp_basic_consume (conf->connection,
+ /* channel = */ CAMQP_CHANNEL,
+ /* queue = */ amqp_cstring_bytes (conf->queue),
+ /* consumer_tag = */ AMQP_EMPTY_BYTES,
+ /* no_local = */ 0,
+ /* no_ack = */ 1,
+ /* exclusive = */ 0,
+ /* arguments = */ AMQP_EMPTY_TABLE
+ );
+ if ((cm_ret == NULL) && camqp_is_error (conf))
+ {
+ char errbuf[1024];
+ ERROR ("amqp plugin: amqp_basic_consume failed: %s",
+ camqp_strerror (conf, errbuf, sizeof (errbuf)));
+ camqp_close_connection (conf);
+ return (-1);
+ }
+
+ return (0);
+} /* }}} int camqp_setup_queue */
+