Page MenuHomeDevCentral

No OneTemporary

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

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)

Event Timeline