Page Menu
Home
DevCentral
Search
Configure Global Search
Log In
Files
F10813758
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
18 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/Makefile b/Makefile
index 914e223..6f189a8 100644
--- a/Makefile
+++ b/Makefile
@@ -1,46 +1,47 @@
MAJOR_VERSION=0
VERSION=0.1.0
TCL_INCLUDE=/usr/include/tcl8.6
RABBITMQ_INCLUDE=/usr/include
INCLUDES=-I$(TCL_INCLUDE) -I$(RABBITMQ_INCLUDE)
LIBS=-ltcl8.6
#CCOPTS=-DUSE_TCL_STUBS=1
CC=clang ${CCOPTS} ${INCLUDES} ${LIBS}
RM=rm -f
# Main targets
all: print-banner build/rabbitmq.so
clean:
$(RM) core build/*.o build/*.so build/*.so.${VERSION}
# Dev targets
lint:
arc lint --apply-patches
demo:
rlwrap tclsh
rebuild: clean lint all demo
# Helpers
print-banner:
@cat doc/banner
@date
# Files targets
build/rabbitmq.so: build/rabbitmq.o
${CC} -shared -Wl,-soname,rabbitmq.so.${MAJOR_VERSION} -o build/rabbitmq.so.${VERSION} build/*.o
cd build && ln -s rabbitmq.so.${VERSION} rabbitmq.so
build/rabbitmq.o:
mkdir -p build
+ ${CC} -c -fPIC utils/netutils.c -o build/netutils.o
${CC} -c -fPIC rabbitmq-tcl.c -o build/rabbitmq.o
diff --git a/rabbitmq-tcl.c b/rabbitmq-tcl.c
index 5b2e575..0471dba 100644
--- a/rabbitmq-tcl.c
+++ b/rabbitmq-tcl.c
@@ -1,215 +1,249 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* ___ __ \_____ ___ /____ /____(_)_ /___ |/ /_ __ \
* __ /_/ / __ `/_ __ \_ __ \_ /_ __/_ /|_/ /_ / / /
* _ _, _// /_/ /_ /_/ / /_/ / / / /_ _ / / / / /_/ /
* /_/ |_| \__,_/ /_.___//_.___//_/ \__/ /_/ /_/ \___\_\
* _____________________
* 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>
/* TODO: include librabbitmq */
#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 */
} brokerConnections[MQ_COMMANDS_AMOUNT];
/* -------------------------------------------------------------
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_VERSION);
return versionString;
}
/* -------------------------------------------------------------
TCL commands
mq
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/**
* mq command
*
* @param[in] connectionNumber The connection offset (0 for mq, 1 for mq1, …)
* @param[out] tclInterpreter The interpreter in which to create new command
* @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, char **argv) {
if (argc <= 1) {
return mq_usage(tclInterpreter);
}
int connectionNumber = (int)clientData;
if (strcmp(argv[1], "connect") == 0) {
return mq_connect(connectionNumber, tclInterpreter, argc - 2, argv + 2);
} else if (strcmp(argv[1], "disconnect") == 0) {
return mq_disconnect(connectionNumber, tclInterpreter);
} else if (strcmp(argv[1], "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) {
Tcl_SetResult(tclInterpreter, "Usage: mq <connect|disconnect|version>",
TCL_STATIC);
return TCL_ERROR;
}
/**
* mq version
*
* @param[out] tclInterpreter The interpreter in which to create new command
* @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 in which to create new command
* @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,
char **argv) {
+ char *host, *user, *pass, *vhost;
+ int port;
+
if (brokerConnections[connectionNumber].connected == 1) {
Tcl_SetResult(tclInterpreter, "Already connected.", TCL_STATIC);
return TCL_ERROR;
}
+ // Connection parameters
+
+ if (argc > 0 && argv[0]) {
+ host = get_host(argv[0], BROKER_HOST);
+ port = get_port(argv[0], BROKER_PORT);
+ } else {
+ host = BROKER_HOST;
+ port = BROKER_PORT;
+ }
+ if (argc > 1 && argv[1]) {
+ user = argv[1];
+ } else {
+ user = BROKER_USER;
+ }
+ if (argc > 2 && argv[2]) {
+ pass = argv[2];
+ } else {
+ pass = BROKER_PASS;
+ }
+ if (argc > 3 && argv[3]) {
+ vhost = argv[3];
+ } else {
+ vhost = BROKER_VHOST;
+ }
+
+ char *debugInformation = malloc(256 * sizeof(char));
+ //"Connecting to amqp://%s:%s@%s:%d"
+ sprintf(debugInformation, "Connecting to amqp://%s:%s@%s:%d", user, pass,
+ host, port);
+ Tcl_SetResult(tclInterpreter, debugInformation, TCL_STATIC);
+
if (0) {
Tcl_SetResult(tclInterpreter, "Can't connect to the broker.",
TCL_STATIC);
return TCL_ERROR;
}
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 in which to create new command
* @return TCL_OK on success, TCL_ERROR if not connected
*/
int mq_disconnect(int connectionNumber, Tcl_Interp *tclInterpreter) {
if (brokerConnections[connectionNumber].connected == 0) {
Tcl_SetResult(tclInterpreter, "not connected", TCL_STATIC);
return TCL_ERROR;
}
brokerConnections[connectionNumber].connected = 0;
return TCL_OK;
}
/* -------------------------------------------------------------
TCL initialisation code
Creation of the mq and mq2-10 commands.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifdef WINDOWS
extern __declspec(dllexport) int mq_init(Tcl_Interp *tclInterpreter);
#else
extern int mq_init(Tcl_Interp *tclInterpreter);
#endif
/**
* Initializes the library and provide mq commands
*
* @param[out] tclInterpreter The current TCL interpreter to provide command to
* @return TCL_OK on success; otherwise, TCL_ERROR
*/
int Rabbitmq_Init(Tcl_Interp *tclInterpreter) {
int i, result;
char commandName[10];
// TCL requirements and stubs
if (Tcl_PkgRequire(tclInterpreter, "Tcl", TCL_VERSION, 0) == NULL) {
if (TCL_VERSION[0] == '7') {
if (Tcl_PkgRequire(tclInterpreter, "Tcl", "8.0", 0) == NULL) {
return TCL_ERROR;
}
}
}
#if USE_TCL_STUBS
if (Tcl_InitStubs(tclInterpreter, "8.1", 0) == NULL) {
return TCL_ERROR;
}
#endif
// Creates mq annd mq1-mq10 commands
for (i = 0; i <= MQ_COMMANDS_AMOUNT; i++) {
if (i == 0) {
strcpy(commandName, "mq");
} else {
sprintf(commandName, "mq%d", i);
}
Tcl_CreateCommand(tclInterpreter, commandName, mq_command,
(ClientData)i, (Tcl_CmdDeleteProc *)NULL);
brokerConnections[i].connected = 0;
}
// Provides a TCL package
result = Tcl_PkgProvide(tclInterpreter, "rabbitmq", RABBITMQ_TCL_VERSION);
if (result == TCL_ERROR) {
return TCL_ERROR;
}
return TCL_OK;
}
diff --git a/rabbitmq-tcl.h b/rabbitmq-tcl.h
index 9ebbd4a..e585f8f 100644
--- a/rabbitmq-tcl.h
+++ b/rabbitmq-tcl.h
@@ -1,37 +1,43 @@
/* -------------------------------------------------------------
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
------------------------------------------------------------- */
+/* -------------------------------------------------------------
+ Functions from utils/
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+#include "utils/netutils.h"
+
/* -------------------------------------------------------------
Functions explicit declaration (by alphabetical order)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
char *get_version_string();
static int mq_command(ClientData clientData, Tcl_Interp *tclInterpreter,
int argc, char **argv);
int mq_connect(int connectionNumber, Tcl_Interp *tclInterpreter, int argc,
char **argv);
int mq_disconnect(int connectionNumber, Tcl_Interp *tclInterpreter);
int Rabbitmq_Init(Tcl_Interp *tclInterpreter);
int mq_usage(Tcl_Interp *tclInterpreter);
int mq_version(Tcl_Interp *tclInterpreter);
diff --git a/utils/netutils.c b/utils/netutils.c
new file mode 100644
index 0000000..70d3188
--- /dev/null
+++ b/utils/netutils.c
@@ -0,0 +1,80 @@
+/* -------------------------------------------------------------
+ RabbitMQ TCL - Configuration
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ ___ __ \_____ ___ /____ /____(_)_ /___ |/ /_ __ \
+ __ /_/ / __ `/_ __ \_ __ \_ /_ __/_ /|_/ /_ / / /
+ _ _, _// /_/ /_ /_/ / /_/ / / / /_ _ / / / / /_/ /
+ /_/ |_| \__,_/ /_.___//_.___//_/ \__/ /_/ /_/ \___\_\
+ _____________________
+ 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: netutils.c
+ Created: 2015-12-08
+ Licence: BSD-2-Clause
+ ------------------------------------------------------------- */
+
+#include <stdlib.h>
+#include <string.h>
+#include "strpos.h"
+
+/* -------------------------------------------------------------
+ Parse host:port expression helper functions
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+/**
+ * Gets host from a host:port expression
+ *
+ * @param[in] expression the host:port expression
+ * @return the hostname
+ */
+char *get_host(const char *expression, const char *defaultHost) {
+ char *host = malloc(1024 * sizeof(char));
+ int pos;
+
+ pos = strpos(expression, ":");
+ if (pos == STR_NOT_FOUND) {
+ strcpy(host, expression);
+ } else if (pos == 0) {
+ strcpy(host, defaultHost); //Handle ":5000" case
+ } else {
+ strncpy(host, expression, pos);
+ host[pos] = '\0';
+ }
+
+ return host;
+}
+
+/**
+ * Gets port from a host:port expression
+ *
+ * @param[in] expression the host:port expression
+ * @param[in] defaultPort the default port if omitted
+ * @return the hostname
+ */
+int get_port(const char *expression, int defaultPort) {
+ int port;
+ int pos;
+
+ pos = strpos(expression, ":");
+ if (pos == STR_NOT_FOUND) {
+ return defaultPort;
+ }
+
+ expression += pos + 1;
+ port = atoi(expression);
+ if (port <= 0 || port > 65535) {
+ // mq connect server: should use default port instead of 0
+ // We ignore gracefully any other error
+ return defaultPort;
+ }
+
+ return port;
+}
diff --git a/rabbitmq-tcl.h b/utils/netutils.h
similarity index 70%
copy from rabbitmq-tcl.h
copy to utils/netutils.h
index 9ebbd4a..cc6b918 100644
--- a/rabbitmq-tcl.h
+++ b/utils/netutils.h
@@ -1,37 +1,29 @@
/* -------------------------------------------------------------
- RabbitMQ TCL - Header
+ RabbitMQ TCL - Header for netutils
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
___ __ \_____ ___ /____ /____(_)_ /___ |/ /_ __ \
__ /_/ / __ `/_ __ \_ __ \_ /_ __/_ /|_/ /_ / / /
_ _, _// /_/ /_ /_/ / /_/ / / / /_ _ / / / / /_/ /
/_/ |_| \__,_/ /_.___//_.___//_/ \__/ /_/ /_/ \___\_\
_____________________
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
+ Filename: netutils.h
+ Created: 2015-12-09
Licence: BSD-2-Clause
------------------------------------------------------------- */
/* -------------------------------------------------------------
Functions explicit declaration (by alphabetical order)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-char *get_version_string();
-
-static int mq_command(ClientData clientData, Tcl_Interp *tclInterpreter,
- int argc, char **argv);
-int mq_connect(int connectionNumber, Tcl_Interp *tclInterpreter, int argc,
- char **argv);
-int mq_disconnect(int connectionNumber, Tcl_Interp *tclInterpreter);
-int Rabbitmq_Init(Tcl_Interp *tclInterpreter);
-int mq_usage(Tcl_Interp *tclInterpreter);
-int mq_version(Tcl_Interp *tclInterpreter);
+char *get_host(const char *expression, const char *defaultHost);
+int get_port(const char *expression, int defaultPort);
diff --git a/rabbitmq-tcl.h b/utils/strpos.h
similarity index 61%
copy from rabbitmq-tcl.h
copy to utils/strpos.h
index 9ebbd4a..0176bab 100644
--- a/rabbitmq-tcl.h
+++ b/utils/strpos.h
@@ -1,37 +1,51 @@
/* -------------------------------------------------------------
- RabbitMQ TCL - Header
+ RabbitMQ TCL - String utilities
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
___ __ \_____ ___ /____ /____(_)_ /___ |/ /_ __ \
__ /_/ / __ `/_ __ \_ __ \_ /_ __/_ /|_/ /_ / / /
_ _, _// /_/ /_ /_/ / /_/ / / / /_ _ / / / / /_/ /
/_/ |_| \__,_/ /_.___//_.___//_/ \__/ /_/ /_/ \___\_\
_____________________
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
+ Filename: strpos.h
Created: 2015-12-08
Licence: BSD-2-Clause
------------------------------------------------------------- */
+#include <string.h>
+
+/* -------------------------------------------------------------
+ Magic constants
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+#define STR_NOT_FOUND -1
+
/* -------------------------------------------------------------
- Functions explicit declaration (by alphabetical order)
+ Common string functions: strpos
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-char *get_version_string();
+/**
+ * Finds the position of the first occurrence of a substring in a string
+ *
+ * @param[in] haystack The string to search in
+ * @param[in] needle The string to search
+ * @return The position of where the needle exists, or STR_NOT_FOUND
+ */
+int strpos(const char *haystack, const char *needle) {
+ // http://stackoverflow.com/a/7655509/1930997 - snippet by Miere
+ char *p = strstr(haystack, needle);
+
+ if (p)
+ return p - haystack;
-static int mq_command(ClientData clientData, Tcl_Interp *tclInterpreter,
- int argc, char **argv);
-int mq_connect(int connectionNumber, Tcl_Interp *tclInterpreter, int argc,
- char **argv);
-int mq_disconnect(int connectionNumber, Tcl_Interp *tclInterpreter);
-int Rabbitmq_Init(Tcl_Interp *tclInterpreter);
-int mq_usage(Tcl_Interp *tclInterpreter);
-int mq_version(Tcl_Interp *tclInterpreter);
+ return STR_NOT_FOUND;
+}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Jul 29, 14:16 (1 d, 6 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2853031
Default Alt Text
(18 KB)
Attached To
Mode
rRABBITMQTCL RabbitMQ TCL extension
Attached
Detach File
Event Timeline
Log In to Comment