Page MenuHomeDevCentral

No OneTemporary

diff --git a/README.md b/README.md
index 37ed926..cfbd97a 100644
--- a/README.md
+++ b/README.md
@@ -1,67 +1,80 @@
# RabbitMQ TCL
This library is a wrapper around [rabbitmq-c](https://github.com/alanxz/rabbitmq-c).
It exposes the C functions allowing to interact with a RabbitMQ server in TCL.
Work in progress, not yet ready for production or a for a technical preview.
## User starting guide
### Installation
```
git clone https://github.com/dereckson/rabbitmq-tcl.git
cd rabbitmq-tcl
make
```
### How to use it?
**To load the library:**
```
load rabbitmq.so
```
**You'll then got a mq command to interact with your broker:**
```
mq connect [broker.domain.tld[:port]] [username] [password] [vhost]
mq disconnect
```
**To publish a message:**
```
mq publish <target> [-key <routing key>] [-mandatory] [-immediate] <message>
```
The target could be directly an exchange name, or use the following syntax:
`[-exchange <exchange name>] [-queue <queue name>]`
+**To get a message:**
+
+The prefered way is asynchronously.
+
+But you can also use the synchronous basic.get implementation:
+
+```
+mq get <queue> [-noack]
+```
+
+Currently, basic.ack isn't implemented, so add -noack if you don't want the
+broker send again the same messages at the next session.
+
### Multiple connections
If you need to use more than one connectionn, you've also aliases mq1 to mq10:
```
mq3 connect
mq3 disconnect
```
## Misc
### Acknowledgment
* Alan Antonuk, rabbitmq-c maintainer
* Fastbase, which provides [fbsql](http://www.fastbase.co.nz/fbsql/fbsql.c),
which is used as the model and starting point for this library.
### Colophon
This work has been created for Nasqueron, to allow their operations and
infrastructure TCL code to interact to our message broker.
**Editors used:** vim, Cloud9
**Tools used:** Arcanist, clang-format
**Compiler:** clang/llvm
diff --git a/src/rabbitmq-tcl.c b/src/rabbitmq-tcl.c
index 9eb3880..9d8d828 100644
--- a/src/rabbitmq-tcl.c
+++ b/src/rabbitmq-tcl.c
@@ -1,547 +1,648 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* ___ __ \_____ ___ /____ /____(_)_ /___ |/ /_ __ \
* __ /_/ / __ `/_ __ \_ __ \_ /_ __/_ /|_/ /_ / / /
* _ _, _// /_/ /_ /_/ / /_/ / / / /_ _ / / / / /_/ /
* /_/ |_| \__,_/ /_.___//_.___//_/ \__/ /_/ /_/ \___\_\
* _____________________
* RabbitMQ C AMQP client library TCL wrapper ___ __/_ ____/__ /
* TCL module to connect to AMQP brokers. __ / _ / __ /
* _ / / /___ _ /___
* (c) 2015, Nasqueron, some rights reserved. /_/ \____/ /_____/
* Released under BSD-2-Clause license.
*
* Provides a TCL rabbitmq.so module to get a 'mq' TCL command.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <stdlib.h>
#include <string.h>
#include <tcl.h>
#include <amqp_tcp_socket.h>
#include <amqp.h>
#include <amqp_framing.h>
#include "config.h"
#include "version.h"
#include "rabbitmq-tcl.h"
/* -------------------------------------------------------------
Broker connections
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/**
* Represents a connection with the broker, and stores properties.
*/
struct broker_connection {
int connected; /* 0 if disconnected, 1 if connected */
amqp_connection_state_t connection;
} brokerConnections[MQ_COMMANDS_AMOUNT];
/**
* Represents the client data information for a command.
*/
struct command_context {
int commandNumber;
};
/* -------------------------------------------------------------
Helper functions
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/**
* Gets product version string
*
* @return The product name and version
*/
char *get_version_string() {
char *versionString = malloc(256 * sizeof(char));
sprintf(versionString, "%s %s", RABBITMQ_TCL_PRODUCT_NAME,
RABBITMQ_TCL_PRODUCT_VERSION);
return versionString;
}
/**
* Determines if the specified connection slot is currently connected
*
* @param connectionNumber the number of the connection to check
* @return 1 if connected, 0 if disconnected
*/
int is_mq_connected(int connectionNumber) {
return brokerConnections[connectionNumber].connected;
}
+/**
+ * Determines if the connection will probably be non blocking
+ *
+ * @return 1 if the operation should be non blocking ; 0 on block
+ */
+int amqp_will_be_non_blocking_operation(amqp_connection_state_t connection) {
+ // See
+ // http://lists.rabbitmq.com/pipermail/rabbitmq-discuss/2012-February/018188.html
+ return amqp_frames_enqueued(connection) || amqp_data_in_buffer(connection);
+
+ // TODO: at the stage, we can try a third solution: run amqp_get_sockfd()
+ // to get the socket descriptor, then call select() or poll().
+ // If the socket can be read, we can return true.
+}
+
/**
* Prints an error message as command result and notify TCL an error occured.
*
* @param[out] tclInterpreter The interpreter in which to set result
* @param[in] error The error message
* @return TCL_ERROR
*/
int tcl_error(Tcl_Interp *tclInterpreter, char *error) {
Tcl_SetResult(tclInterpreter, error, TCL_STATIC);
return TCL_ERROR;
}
/**
* Gets a broker error
*
* @param[in] connection The AMQP connection
* @param[out] rcpReply The AMQP RPC reply
* @return 1 if an error occured, 0 if not
*/
int amqp_get_error(amqp_connection_state_t connection,
amqp_rpc_reply_t *rpcReply) {
amqp_rpc_reply_t reply = amqp_get_rpc_reply(connection);
rpcReply = &reply;
return reply.reply_type != AMQP_RESPONSE_NORMAL;
}
/**
* Determines the AMQP error from the server RPC reply, prints an error message
* based on this error and the specified context, then notify TCL an error
*occured.
*
* @param[out] tclInterpreter The interpreter in which to set result
* @param[in] errorContext The context of the error message, typically what were
*done at the moment of the error
* @param[in] rcpReply The AMQP RPC reply
* @return TCL_ERROR
*/
int tcl_amqp_error(Tcl_Interp *tclInterpreter, const char *errorContext,
- amqp_rpc_reply_t rpcReply) {
+ amqp_rpc_reply_t rpcReply, int connectionNumber) {
char *error;
if (rpcReply.reply_type == AMQP_RESPONSE_NORMAL) {
// Not an error
return TCL_OK;
}
error = malloc(1024 * sizeof(char));
if (rpcReply.reply_type == AMQP_RESPONSE_NONE) {
sprintf(error, "%s a broker error occurred, but with an unexpected RPC "
"reply type. Please report this bug as issue.",
errorContext);
} else if (rpcReply.reply_type == AMQP_RESPONSE_LIBRARY_EXCEPTION) {
sprintf(error, "%s %s", errorContext,
amqp_error_string2(rpcReply.library_error));
} else if (rpcReply.reply_type == AMQP_RESPONSE_SERVER_EXCEPTION) {
if (rpcReply.reply.id == AMQP_CONNECTION_CLOSE_METHOD) {
amqp_connection_close_t *m =
(amqp_connection_close_t *)rpcReply.reply.decoded;
sprintf(error,
"%s a server connection error %d occurred, message: %.*s",
errorContext, m->reply_code, (int)m->reply_text.len,
(char *)m->reply_text.bytes);
+ // Marks the connection as disconnected
+ brokerConnections[connectionNumber].connected = 0;
} else if (rpcReply.reply.id == AMQP_CHANNEL_CLOSE_METHOD) {
amqp_channel_close_t *m =
(amqp_channel_close_t *)rpcReply.reply.decoded;
sprintf(error, "%s a server channel error %d occurred: %.*s",
errorContext, m->reply_code, (int)m->reply_text.len,
(char *)m->reply_text.bytes);
+ // Marks the connection as disconnected
+ brokerConnections[connectionNumber].connected = 0;
} else {
sprintf(error,
"%s an unknown server error occurred, method id 0x%08X",
errorContext, rpcReply.reply.id);
}
}
return tcl_error(tclInterpreter, error);
}
/* -------------------------------------------------------------
TCL commands
mq
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/**
* mq command
*
* @param[in] connectionNumber The connection offset (0 for mq, 1 for mq1, …)
* @param[out] tclInterpreter The interpreter calling this function
* @param[in] argc The amount of command arguments
* @param[in] argv The command arguments
* @return TCL_OK, TCL_ERROR, TCL_RETURN, TCL_BREAK or TCL_CONTINUE
*/
static int mq_command(ClientData clientData, Tcl_Interp *tclInterpreter,
int argc, Tcl_Obj *const argv[]) {
int connectionNumber;
char *command;
struct command_context *context;
if (argc <= 1) {
return mq_usage(tclInterpreter);
}
context = clientData;
connectionNumber = context->commandNumber;
command = Tcl_GetString(argv[1]);
if (strcmp(command, "connect") == 0) {
return mq_connect(connectionNumber, tclInterpreter, argc - 2, argv + 2);
} else if (strcmp(command, "disconnect") == 0) {
return mq_disconnect(connectionNumber, tclInterpreter);
+ } else if (strcmp(command, "get") == 0) {
+ return mq_get(connectionNumber, tclInterpreter, argc - 2, argv + 2);
} else if (strcmp(command, "publish") == 0) {
return mq_publish(connectionNumber, tclInterpreter, argc - 2, argv + 2);
} else if (strcmp(command, "version") == 0) {
return mq_version(tclInterpreter);
} else {
return mq_usage(tclInterpreter);
}
}
/**
* mq [not existing command] usage output
*
* @param[out] tclInterpreter The interpreter to send command result to
*/
int mq_usage(Tcl_Interp *tclInterpreter) {
- return tcl_error(tclInterpreter,
- "Usage: mq <connect|disconnect|publish|version>");
+ return tcl_error(
+ tclInterpreter,
+ "Usage: mq <connect|disconnect|get|publish|version>");
}
/**
* mq version
*
* @param[out] tclInterpreter The interpreter calling this function
* @return TCL_OK
*/
int mq_version(Tcl_Interp *tclInterpreter) {
Tcl_SetResult(tclInterpreter, get_version_string(), TCL_STATIC);
return TCL_OK;
}
/**
* mq connect
*
* @param[in] connectionNumber The connection offset (0 for mq, 1 for mq1, …)
* @param[out] tclInterpreter The interpreter calling this function
* @param[in] argc The amount of command arguments
* @param[in] argv The command arguments
* @return TCL_OK on success, TCL_ERROR if already connected or can't connect
*/
int mq_connect(int connectionNumber, Tcl_Interp *tclInterpreter, int argc,
Tcl_Obj *const argv[]) {
char *host, *hostPortExpression, *user, *pass, *vhost;
int port, status;
amqp_connection_state_t conn;
amqp_socket_t *socket;
amqp_rpc_reply_t result;
// We don't allow to reconnect without first used mq disconnect
if (is_mq_connected(connectionNumber)) {
return tcl_error(tclInterpreter, "Already connected.");
}
// Connection parameters
if (argc > 0 && argv[0]) {
hostPortExpression = Tcl_GetString(argv[0]);
host = get_host(hostPortExpression, BROKER_HOST);
port = get_port(hostPortExpression, BROKER_PORT);
} else {
host = BROKER_HOST;
port = BROKER_PORT;
}
if (argc > 1 && argv[1]) {
user = Tcl_GetString(argv[1]);
} else {
user = BROKER_USER;
}
if (argc > 2 && argv[2]) {
pass = Tcl_GetString(argv[2]);
} else {
pass = BROKER_PASS;
}
if (argc > 3 && argv[3]) {
vhost = Tcl_GetString(argv[3]);
} else {
vhost = BROKER_VHOST;
}
// Opens a TCP connection to the broker
conn = amqp_new_connection();
socket = amqp_tcp_socket_new(conn);
if (!socket) {
return tcl_error(tclInterpreter, "Can't create TCP socket.");
}
status = amqp_socket_open(socket, host, port);
if (status) {
return tcl_error(tclInterpreter, "Can't connect to the broker.");
}
// Logins to the broker
// No heartbeat, unlimited channels, 128K (131072) frame size
result = amqp_login(conn, vhost, 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, user,
pass);
if (result.reply_type != AMQP_RESPONSE_NORMAL) {
return tcl_error(tclInterpreter, "Can't login to the broker.");
}
// Opens a first channel
amqp_channel_open(conn, 1);
if (amqp_get_error(conn, &result)) {
- return tcl_amqp_error(tclInterpreter, "Can't open a channel:", result);
+ return tcl_amqp_error(tclInterpreter, "Can't open a channel:", result,
+ connectionNumber);
}
// We're connected. All is good.
brokerConnections[connectionNumber].connection = conn;
brokerConnections[connectionNumber].connected = 1;
return TCL_OK;
}
/**
* mq disconnect
*
* @param[in] connectionNumber The connection offset (0 for mq, 1 for mq1, …)
* @param[out] tclInterpreter The interpreter calling this function
* @return TCL_OK on success, TCL_ERROR if not connected
*/
int mq_disconnect(int connectionNumber, Tcl_Interp *tclInterpreter) {
amqp_rpc_reply_t result;
if (!is_mq_connected(connectionNumber)) {
return tcl_error(tclInterpreter, "Not connected.");
}
// We mark early as disconnected, to allow to recycle the slot
// event if an error occurs during disconnect.
brokerConnections[connectionNumber].connected = 0;
amqp_connection_state_t conn =
brokerConnections[connectionNumber].connection;
result = amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS);
if (result.reply_type != AMQP_RESPONSE_NORMAL) {
return tcl_amqp_error(tclInterpreter,
- "An error occured closing channel:", result);
+ "An error occured closing channel:", result,
+ connectionNumber);
}
result = amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
if (result.reply_type != AMQP_RESPONSE_NORMAL) {
return tcl_amqp_error(tclInterpreter,
- "An error occured closing connection:", result);
+ "An error occured closing connection:", result,
+ connectionNumber);
}
amqp_destroy_connection(conn);
return TCL_OK;
}
+/**
+ * mq get <queue> [-noack]
+ */
+int mq_get(int connectionNumber, Tcl_Interp *tclInterpreter, int argc,
+ Tcl_Obj *const argv[]) {
+ char *queue;
+ char *argument;
+ char *error;
+ char *messageBody;
+ amqp_boolean_t noAck = 0;
+
+ amqp_connection_state_t conn;
+ amqp_rpc_reply_t result;
+ amqp_message_t message;
+
+ // Parses arguments
+ if (argc == 0) {
+ return tcl_error(tclInterpreter, "Required queue missing.");
+ }
+ queue = Tcl_GetString(argv[0]);
+
+ if (argc > 1) {
+ argument = Tcl_GetString(argv[1]);
+ if (strcmp(argument, "-noack") == 0) {
+ noAck = 1;
+ } else {
+ error = malloc(1024 * sizeof(char));
+ sprintf(error, "Unknown argument: %s", argument);
+ return tcl_error(tclInterpreter, error);
+ }
+ }
+ if (argc > 2) {
+ return tcl_error(tclInterpreter, "Too many arguments.");
+ }
+
+ // Ensures we're connected
+ if (!is_mq_connected(connectionNumber)) {
+ return tcl_error(tclInterpreter, "Not connected.");
+ }
+ conn = brokerConnections[connectionNumber].connection;
+
+ // Gets message from specified queue (basic.get operation)
+ result = amqp_basic_get(conn, 1, amqp_cstring_bytes(queue), noAck);
+ if (amqp_get_error(conn, &result)) {
+ return tcl_amqp_error(tclInterpreter, "Can't get message from queue:",
+ result, connectionNumber);
+ }
+
+ if (!amqp_will_be_non_blocking_operation(conn)) {
+ // We can't assert the operation will be non blocking
+ return TCL_OK;
+ }
+
+ result = amqp_read_message(conn, 1, &message, 0);
+ if (amqp_get_error(conn, &result)) {
+ return tcl_amqp_error(tclInterpreter, "Can't read message:", result,
+ connectionNumber);
+ }
+
+ if (&message && &(message.body)) {
+ messageBody = malloc(message.body.len + 1024);
+ sprintf(messageBody, "%.*s", (int)message.body.len,
+ (char *)message.body.bytes);
+
+ // Cleans up
+ amqp_destroy_message(&message);
+ amqp_maybe_release_buffers(conn);
+ }
+
+ // TCL return
+ Tcl_SetResult(tclInterpreter, messageBody, TCL_STATIC);
+
+ return TCL_OK;
+}
+
/**
*
* mq publish <target> [-key <routing key>] [-mandatory] [-immediate] <message>
*
* The target could be: <exchange>, -exchange <exchange> or -queue <queue>
*
* @param[in] connectionNumber The connection offset (0 for mq, 1 for mq1, …)
* @param[out] tclInterpreter The interpreter calling this function
* @param[in] argc The amount of command arguments
* @param[in] argv The command arguments
* @return TCL_OK on success, TCL_ERROR if already connected or can't connect
*/
int mq_publish(int connectionNumber, Tcl_Interp *tclInterpreter, int argc,
Tcl_Obj *const argv[]) {
int i;
amqp_connection_state_t conn;
amqp_rpc_reply_t result;
char *argument, *exchange, *routingKey, *content;
int contentParsed = 0;
int targetParsed = 0;
int routingKeyParsed = 0;
int mustRouteToQueue = 0; // -mandatory
int mustImmediatelyDeliverToConsumer = 0; // -immediate
// Parses arguments
for (i = 0; i < argc; i++) {
argument = Tcl_GetString(argv[i]);
if (strcmp(argument, "-key") == 0) {
if (argc < i + 2) {
return tcl_error(tclInterpreter,
"Required routing key argument missing.");
}
routingKey = Tcl_GetString(argv[++i]);
routingKeyParsed = 1;
} else if (strcmp(argument, "-mandatory") == 0) {
mustRouteToQueue = 1;
} else if (strcmp(argument, "-immediate") == 0) {
mustImmediatelyDeliverToConsumer = 1;
} else if (strcmp(argument, "-exchange") == 0) {
if (argc < i + 2) {
return tcl_error(tclInterpreter,
"Required exchange argument missing.");
}
exchange = Tcl_GetString(argv[++i]);
targetParsed = 1;
} else if (strcmp(argument, "-queue") == 0) {
if (argc < i + 2) {
return tcl_error(tclInterpreter,
"Required queue argument missing.");
}
exchange = BROKER_DEFAULT_EXCHANGE;
routingKey = Tcl_GetString(argv[++i]);
targetParsed = 1;
routingKeyParsed = 1;
} else if (i == 0) {
exchange = Tcl_GetString(argv[0]);
targetParsed = 1;
} else {
content = Tcl_GetString(argv[i]);
contentParsed = 1;
}
}
if (!routingKeyParsed) {
routingKey = BROKER_DEFAULT_ROUTING_KEY;
}
// Throws error when we haven't enough information (what and where)
if (!targetParsed) {
return tcl_error(tclInterpreter, "Required message target missing.");
}
if (!contentParsed) {
return tcl_error(tclInterpreter,
"Required message content argument missing.");
}
// Ensures we're connected
if (!is_mq_connected(connectionNumber)) {
return tcl_error(tclInterpreter, "Not connected.");
}
// Sends the message and checks the result
conn = brokerConnections[connectionNumber].connection;
amqp_basic_publish(conn, 1, amqp_cstring_bytes(exchange),
amqp_cstring_bytes(routingKey), mustRouteToQueue,
mustImmediatelyDeliverToConsumer, NULL,
amqp_cstring_bytes(content));
if (amqp_get_error(conn, &result)) {
- return tcl_amqp_error(tclInterpreter, "Can't publish message:", result);
+ return tcl_amqp_error(tclInterpreter, "Can't publish message:", result,
+ connectionNumber);
}
#ifdef DEBUG
char *debugMessage = malloc(1024 * sizeof(char) + sizeof(content));
sprintf(
debugMessage,
"Message published to exchange '%s', routing key '%s'. Content: '%s'.",
exchange, routingKey, content);
Tcl_SetResult(tclInterpreter, debugMessage, TCL_STATIC);
#endif
return TCL_OK;
}
/* -------------------------------------------------------------
TCL initialisation code
Creation of the mq and mq2-10 commands.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifdef WINDOWS
extern __declspec(dllexport) int Rabbitmq_Init(Tcl_Interp *tclInterpreter);
#else
extern int Rabbitmq_Init(Tcl_Interp *tclInterpreter);
#endif
/**
* Determines TCL environment is correct and initiliazes stubs if needed
*
* @param[out] tclInterpreter The current TCL interpreter
* @return 1 on success; otherwise, 0
*/
int tcl_init(Tcl_Interp *tclInterpreter) {
// This extension requires TCL 8.0+
if (Tcl_PkgRequire(tclInterpreter, "Tcl", TCL_VERSION, 0) == NULL) {
if (TCL_VERSION[0] == '7') {
if (Tcl_PkgRequire(tclInterpreter, "Tcl", "8.0", 0) == NULL) {
return 0;
}
}
}
#if USE_TCL_STUBS
// Initializes stubs (requires TCL 8.1+)
if (Tcl_InitStubs(tclInterpreter, "8.1", 0) == NULL) {
return 0;
}
#endif
return 1;
}
/**
* Gets command context
*
* @param commandNumber The command number (3 for mq3)
* @return the command context
*/
ClientData get_mq_command_context(int commandNumber) {
struct command_context *context = malloc(sizeof(int));
context->commandNumber = commandNumber;
return context;
}
/**
* Creates TCL commands
*
* @param[out] tclInterpreter The current TCL interpreter
*/
void tcl_create_commands(Tcl_Interp *tclInterpreter) {
int i;
char commandName[10];
// Creates mq and mq1-mq10 commands
for (i = 0; i <= MQ_COMMANDS_AMOUNT; i++) {
if (i == 0) {
strcpy(commandName, "mq");
} else {
sprintf(commandName, "mq%d", i);
}
Tcl_CreateObjCommand(tclInterpreter, commandName, mq_command,
get_mq_command_context(i),
(Tcl_CmdDeleteProc *)NULL);
brokerConnections[i].connected = 0;
}
}
/**
* Provides TCL package
*
* @param[out] tclInterpreter The current TCL interpreter
*/
int tcl_provide_package(Tcl_Interp *tclInterpreter) {
int result;
result = Tcl_PkgProvide(tclInterpreter, RABBITMQ_TCL_PACKAGE_NAME,
RABBITMQ_TCL_PACKAGE_VERSION);
return (result != TCL_ERROR);
}
/**
* Initializes the library and provide mq commands
*
* @param[out] tclInterpreter The current TCL interpreter to provide commands to
* @return TCL_OK on success; otherwise, TCL_ERROR
*/
int Rabbitmq_Init(Tcl_Interp *tclInterpreter) {
if (!tcl_init(tclInterpreter)) {
return TCL_ERROR;
}
tcl_create_commands(tclInterpreter);
if (!tcl_provide_package(tclInterpreter)) {
return TCL_ERROR;
}
return TCL_OK;
}
diff --git a/src/rabbitmq-tcl.h b/src/rabbitmq-tcl.h
index 8748d84..1016c37 100644
--- a/src/rabbitmq-tcl.h
+++ b/src/rabbitmq-tcl.h
@@ -1,54 +1,59 @@
/* -------------------------------------------------------------
RabbitMQ TCL - Header
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
___ __ \_____ ___ /____ /____(_)_ /___ |/ /_ __ \
__ /_/ / __ `/_ __ \_ __ \_ /_ __/_ /|_/ /_ / / /
_ _, _// /_/ /_ /_/ / /_/ / / / /_ _ / / / / /_/ /
/_/ |_| \__,_/ /_.___//_.___//_/ \__/ /_/ /_/ \___\_\
_____________________
RabbitMQ C AMQP client library TCL wrapper ___ __/_ ____/__ /
TCL module to connect to AMQP brokers. __ / _ / __ /
_ / / /___ _ /___
(c) 2015, Nasqueron, some rights reserved. /_/ \____/ /_____/
Released under BSD-2-Clause license.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Software: RabbitMQ TCL
Author: Sébastien Santoro aka Dereckson
Filename: rabbitmq-tcl.h
Created: 2015-12-08
Licence: BSD-2-Clause
------------------------------------------------------------- */
+#include <amqp.h>
#include <tcl.h>
/* -------------------------------------------------------------
Functions from utils/
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "utils/netutils.h"
/* -------------------------------------------------------------
Functions explicit declaration (by alphabetical order)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+int amqp_will_be_non_blocking_operation(amqp_connection_state_t connection);
+
ClientData get_mq_command_context(int commandNumber);
char *get_version_string();
static int mq_command(ClientData clientData, Tcl_Interp *tclInterpreter,
int argc, Tcl_Obj *const argv[]);
int mq_connect(int connectionNumber, Tcl_Interp *tclInterpreter, int argc,
Tcl_Obj *const argv[]);
int mq_disconnect(int connectionNumber, Tcl_Interp *tclInterpreter);
+int mq_get(int connectionNumber, Tcl_Interp *tclInterpreter, int argc,
+ Tcl_Obj *const argv[]);
int mq_publish(int connectionNumber, Tcl_Interp *tclInterpreter, int argc,
Tcl_Obj *const argv[]);
int mq_usage(Tcl_Interp *tclInterpreter);
int mq_version(Tcl_Interp *tclInterpreter);
int Rabbitmq_Init(Tcl_Interp *tclInterpreter);
void tcl_create_commands(Tcl_Interp *tclInterpreter);
int tcl_error(Tcl_Interp *tclInterpreter, char *error);
int tcl_init(Tcl_Interp *tclInterpreter);
int tcl_provide_package(Tcl_Interp *tclInterpreter);

File Metadata

Mime Type
text/x-diff
Expires
Thu, Sep 18, 08:22 (18 h, 47 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2990247
Default Alt Text
(26 KB)

Event Timeline