aboutsummaryrefslogtreecommitdiffstats
path: root/v3/glougloud
diff options
context:
space:
mode:
authorLaurent Ghigonis <laurent@p1sec.com>2013-09-15 22:16:31 +0200
committerLaurent Ghigonis <laurent@p1sec.com>2013-09-15 22:16:31 +0200
commita9ba061bd111ea8e133666dc3a8cd2ac0f7c522e (patch)
treeafd98cce26385a01c5655c357286c2acd9fb6c4f /v3/glougloud
parentwork on modules (diff)
downloadglouglou-a9ba061bd111ea8e133666dc3a8cd2ac0f7c522e.tar.xz
glouglou-a9ba061bd111ea8e133666dc3a8cd2ac0f7c522e.zip
modviz && redis notifications
Diffstat (limited to 'v3/glougloud')
-rw-r--r--v3/glougloud/Makefile6
-rw-r--r--v3/glougloud/glougloud.c2
-rw-r--r--v3/glougloud/glougloud.h58
-rw-r--r--v3/glougloud/glougloud_internal.h35
-rw-r--r--v3/glougloud/glougloud_mod_net/Makefile22
-rw-r--r--v3/glougloud/glougloud_mod_net/glougloud_mod_net.c41
-rw-r--r--v3/glougloud/glougloud_modules.h22
-rw-r--r--v3/glougloud/probes.c26
-rw-r--r--v3/glougloud/redis.c2
-rw-r--r--v3/glougloud/viz.c168
10 files changed, 258 insertions, 124 deletions
diff --git a/v3/glougloud/Makefile b/v3/glougloud/Makefile
index 8cf198b..b0e5233 100644
--- a/v3/glougloud/Makefile
+++ b/v3/glougloud/Makefile
@@ -1,4 +1,5 @@
PROG = glougloud
+HEADERS = glougloud.h
SOURCES = glougloud.c probes.c redis.c viz.c
OBJECTS = $(SOURCES:.c=.o)
CFLAGS+=-Wall -g
@@ -9,11 +10,13 @@ GLOUGLOUD_HOME = "/var/lib/glougloud"
GLOUGLOUD_CHROOT = "$(GLOUGLOUD_HOME)/chroot"
PREFIX=/usr/local
+INCLUDEDIR=$(PREFIX)/include
BINDIR=$(PREFIX)/sbin
all:
make $(OBJECTS)
$(CC) $(OBJECTS) -o $(PROG) $(LDFLAGS)
+ make -C glougloud_mod_net/
install: $(PROG)
@echo "creating 2 users: $(USER_PROBES), $(USER_VIZ)"
@@ -34,7 +37,10 @@ install: $(PROG)
@echo done
@echo "installation of $(PROG)"
mkdir -p $(BINDIR)
+ mkdir -p $(INCLUDEDIR)
install -m 0755 $(PROG) $(BINDIR)
+ install -m 0644 $(HEADERS) $(INCLUDEDIR)
+ make -C glougloud_mod_net/ install
clean:
rm -f $(PROG) $(OBJECTS) *~
diff --git a/v3/glougloud/glougloud.c b/v3/glougloud/glougloud.c
index 8942d94..b6efc36 100644
--- a/v3/glougloud/glougloud.c
+++ b/v3/glougloud/glougloud.c
@@ -7,7 +7,7 @@
#include <event.h>
#include <libglouglou.h>
-#include "glougloud.h"
+#include "glougloud_internal.h"
struct event_base *ev_base;
diff --git a/v3/glougloud/glougloud.h b/v3/glougloud/glougloud.h
index 468c341..618db9e 100644
--- a/v3/glougloud/glougloud.h
+++ b/v3/glougloud/glougloud.h
@@ -1,16 +1,15 @@
-/* glougloud internal */
+/*
+ * Public header for glougloud and glougloud modules
+ * (both probes and viz modules)
+ */
-#include <dnet.h>
-#include <event.h>
-#include <hiredis/hiredis.h>
-#include <hiredis/async.h>
-
-#define GLOUGLOUD_VERSION 3
+#if defined(__OpenBSD__)
+#include <sys/queue.h>
+#else
+#include <bsd/sys/queue.h>
+#endif
-#define GLOUGLOUD_USER_PROBES "_ggdprobe"
-#define GLOUGLOUD_USER_VIZ "_ggdviz"
-#define GLOUGLOUD_LOGFILE "/var/log/glougloud.log"
-#define GLOUGLOUD_MOD_PATH "/lib/glougloud/modules/"
+#include <dnet.h>
struct glougloud {
int daemonize;
@@ -31,22 +30,29 @@ struct glougloud {
} viz;
};
-/* redis.c */
-
-int redis_init(struct glougloud *);
-void redis_shutdown(void);
-
-redisAsyncContext *redis_connect(struct event_base *,
- void (*cb_connect)(const redisAsyncContext *, int),
- void (*cb_disconnect)(const redisAsyncContext *, int));
-void redis_disconnect(redisAsyncContext *);
+enum ggdviz_cli_type {
+ GGDVIZ_CLI_TCP = 0,
+ GGDVIZ_CLI_WS = 1
+};
-/* probes.c */
+struct ggdviz_cli {
+ LIST_ENTRY(ggdviz_cli) entry;
+ int id;
+ enum ggdviz_cli_type type;
+ union {
+ struct {
+ struct bufferevent *bev;
+ struct addr addr;
+ } tcp;
+ };
+};
-int probes_init(struct glougloud *);
-void probes_shutdown(void);
+struct ggdprobe_cli {
+ LIST_ENTRY(ggprobe_cli) entry;
+ int id;
+};
-/* viz.c */
+struct ggdmodviz_conf {
+ int id;
+};
-int viz_init(struct glougloud *);
-void viz_shutdown(void);
diff --git a/v3/glougloud/glougloud_internal.h b/v3/glougloud/glougloud_internal.h
new file mode 100644
index 0000000..9d83a43
--- /dev/null
+++ b/v3/glougloud/glougloud_internal.h
@@ -0,0 +1,35 @@
+/* glougloud internal */
+
+#include <dnet.h>
+#include <event.h>
+#include <hiredis/hiredis.h>
+#include <hiredis/async.h>
+
+#define GLOUGLOUD_VERSION 3
+
+#define GLOUGLOUD_USER_PROBES "_ggdprobe"
+#define GLOUGLOUD_USER_VIZ "_ggdviz"
+#define GLOUGLOUD_LOGFILE "/var/log/glougloud.log"
+#define GLOUGLOUD_MOD_PATH "/modules/"
+
+#include "glougloud.h"
+
+/* redis.c */
+
+int redis_init(struct glougloud *);
+void redis_shutdown(void);
+
+redisAsyncContext *redis_connect(struct event_base *,
+ void (*cb_connect)(const redisAsyncContext *, int),
+ void (*cb_disconnect)(const redisAsyncContext *, int));
+void redis_disconnect(redisAsyncContext *);
+
+/* probes.c */
+
+int probes_init(struct glougloud *);
+void probes_shutdown(void);
+
+/* viz.c */
+
+int viz_init(struct glougloud *);
+void viz_shutdown(void);
diff --git a/v3/glougloud/glougloud_mod_net/Makefile b/v3/glougloud/glougloud_mod_net/Makefile
new file mode 100644
index 0000000..8bdcf2f
--- /dev/null
+++ b/v3/glougloud/glougloud_mod_net/Makefile
@@ -0,0 +1,22 @@
+#CFLAGS += -Wall -O2 -fPIC -shared -g
+CFLAGS += -Wall -O0 -fPIC -shared -g
+
+LIBDIR=/var/lib/glougloud/chroot/modules/
+LIBNAME=glougloud_mod_net
+
+TARGET = ${LIBNAME}.so
+SOURCES = glougloud_mod_net.c
+OBJECTS = $(SOURCES:.c=.o)
+
+all: $(TARGET)
+
+$(TARGET): $(OBJECTS)
+ $(CC) $(CFLAGS) -o $(TARGET) $(OBJECTS)
+
+install:
+ @echo "installation of $(LIBNAME)"
+ mkdir -p $(LIBDIR)
+ install -m 0644 $(TARGET) $(LIBDIR)
+
+clean:
+ rm -f $(TARGET) $(OBJECTS)
diff --git a/v3/glougloud/glougloud_mod_net/glougloud_mod_net.c b/v3/glougloud/glougloud_mod_net/glougloud_mod_net.c
index ec6d93c..758767b 100644
--- a/v3/glougloud/glougloud_mod_net/glougloud_mod_net.c
+++ b/v3/glougloud/glougloud_mod_net/glougloud_mod_net.c
@@ -1,26 +1,51 @@
#include <glougloud.h>
-char *
-ggdmodviz_text_get(struct glougloud_cli *cli, char *op, char *target)
+#include <libglouglou.h>
+
+#define GLOUGLOUD_MOD_NET_ID 1
+
+struct ggdmodviz_conf *
+ggdmodviz_init(struct glougloud *ggd)
{
+ struct ggdmodviz_conf *mod;
+
+ log_debug("glougloud_mod_net: viz init");
+ mod = xcalloc(1, sizeof(struct ggdmodviz_conf));
+ mod->id = GLOUGLOUD_MOD_NET_ID;
+
+ return mod;
}
-void *
-ggdmodviz_netstream_get(struct glougloud_cli *cli, char *notification)
+char *
+ggdmodviz_text_get(struct ggdviz_cli *cli, char *op, char *target)
{
+ log_debug("glougloud_mod_net:\nop: %s\ntarget: %s");
+ return NULL;
+}
+void *
+ggdmodviz_netstream_get(struct ggdviz_cli *cli, char *notification)
+{
+ return NULL;
}
int
-ggdmodviz_conf_set(struct glougloud_cli *cli, void *conf)
+ggdmodviz_conf_set(struct ggdviz_cli *cli, void *conf)
{
+ return -1;
+}
+int
+ggmodprobe_init(struct glougloud *ggd)
+{
+ log_debug("glougloud_mod_net: probe init");
+ return 0;
}
char *
-ggdmodprobe_redis_get(struct glougloud_probe *prb,
- struct glouglou_packet *pkt)
+ggdmodprobe_redis_get(struct ggdprobe_cli *prb,
+ struct gg_packet *pkt)
{
-
+ return NULL;
}
diff --git a/v3/glougloud/glougloud_modules.h b/v3/glougloud/glougloud_modules.h
deleted file mode 100644
index 732fb08..0000000
--- a/v3/glougloud/glougloud_modules.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Header for glougloud modules
- * (both probes and viz modules)
- */
-
-enum ggdviz_cli_type {
- GGDVIZ_CLI_TCP = 0,
- GGDVIZ_CLI_WS = 1
-};
-
-struct ggdviz_cli {
- LIST_ENTRY(servtcp_cli) entry;
- int id;
- enum ggdviz_cli_type type;
- union {
- struct tcp {
- struct bufferevent *bev;
- struct addr addr;
- };
- }
-};
-
diff --git a/v3/glougloud/probes.c b/v3/glougloud/probes.c
index f282f39..a744c98 100644
--- a/v3/glougloud/probes.c
+++ b/v3/glougloud/probes.c
@@ -2,12 +2,20 @@
#include <libglouglou.h>
-#include "glougloud.h"
+#include "glougloud_internal.h"
+
+struct modprobe {
+ LIST_ENTRY(mod) entry;
+ void *handle;
+ char *name;
+ int id;
+ char (*ggdmodprobe_redis_get)(struct ggdprobe_cli *prb, struct gg_packet *pkt);
+};
struct glougloud_probes {
int pid;
struct event_base *evb;
- struct modules *mods;
+ LIST_HEAD(, modprobe) mods;
redisAsyncContext *rc;
struct gg_server *server;
};
@@ -49,6 +57,12 @@ prb_handle_packet(struct gg_server *srv, struct gg_user *usr, struct gg_packet *
return 0;
}
+static int
+_modules_load(void)
+{
+ return 0;
+}
+
int
probes_init(struct glougloud *ggd) {
_ggd = ggd;
@@ -60,7 +74,9 @@ probes_init(struct glougloud *ggd) {
droppriv(GLOUGLOUD_USER_PROBES, 1, NULL);
_probes->evb = event_base_new();
- _probes->mods = modules_load(GLOUGLOUD_MOD_PATH, NULL);
+
+ if (_modules_load() < 0)
+ goto err;
_probes->rc = redis_connect(_probes->evb, cb_connect, cb_disconnect);
if (_probes->rc->err)
@@ -79,6 +95,10 @@ probes_init(struct glougloud *ggd) {
gg_server_stop(_probes->server);
return 0;
+
+err:
+ probes_shutdown();
+ return -1;
}
void
diff --git a/v3/glougloud/redis.c b/v3/glougloud/redis.c
index 12f531a..b786057 100644
--- a/v3/glougloud/redis.c
+++ b/v3/glougloud/redis.c
@@ -8,7 +8,7 @@
#include <libglouglou.h>
-#include "glougloud.h"
+#include "glougloud_internal.h"
struct glougloud_redis {
int pid;
diff --git a/v3/glougloud/viz.c b/v3/glougloud/viz.c
index c8265ba..35a14ab 100644
--- a/v3/glougloud/viz.c
+++ b/v3/glougloud/viz.c
@@ -7,15 +7,26 @@
#include <event2/listener.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
+#include <dirent.h>
+#include <dlfcn.h>
-#include "glougloud.h"
+#include "glougloud_internal.h"
#define MSG_WELCOME "Welcome to glougloud\n"
+struct ggdmodviz {
+ LIST_ENTRY(ggdmodviz) entry;
+ void *handle;
+ char *name;
+ struct ggdmodviz_conf *conf;
+ struct ggdmodviz_conf *(*ggdmodviz_init)(struct glougloud *);
+ char *(*ggdmodviz_text_get)(struct ggdviz_cli *, char *, char *);
+};
+
struct glougloud_viz {
int pid;
struct event_base *evb;
- struct modules *mods;
+ LIST_HEAD(, ggdmodviz) mods;
redisAsyncContext *rc;
/* clients list */
LIST_HEAD(, ggdviz_cli) clients;
@@ -27,48 +38,82 @@ struct glougloud_viz {
} servtcp;
};
-struct modviz_dl {
- int id;
- char (*ggdmodviz_text_get)(struct glougloud_cli *, char *);
-};
-
struct glougloud *_ggd;
struct glougloud_viz *_viz;
-void *
-_modules_cb_dlsym(void *handle)
-{
- struct modviz_dl *dl = NULL;
- void *sym;
-
- dl = xcalloc(1, sizeof(struct modviz_dl));
- if (!(sym = dlsym(handle, "glougloud_module_id")))
- goto err;
- dl->id = *((uint *)sym);
- dlerror(); // clear errors
- if (!(sym = dlsym(handle, "ggdmodviz_text_get")))
- goto err;
- dl->ggdmodviz_text_get = sym;
- dlerror(); // clear errors
-
- return dl;
-err:
- if (dl)
- free(dl);
- return NULL;
-}
-
-int
+static int
_modules_load(void)
{
- _viz->evb = event_base_new();
- _viz->mods = modules_load(GLOUGLOUD_MOD_PATH, _modules_cb_dlsym);
+ struct ggdmodviz *mod;
+ DIR *d = NULL;
+ struct dirent *ent;
+ int n;
+ void *handle, *sym;
+ char path[MAXPATHLEN];
+ char *dir;
+ struct ggdmodviz_conf *modconf;
+ struct ggdmodviz_conf *(*fn_ggdmodviz_init)(struct glougloud *);
+ char *(*fn_ggdmodviz_text_get)(struct ggdviz_cli *, char *, char *);
+
+ dir = GLOUGLOUD_MOD_PATH;
+ d = opendir(dir);
+ if (!d)
+ goto err;
+ while ((ent = readdir(d))) {
+ n = strnlen(ent->d_name, sizeof(ent->d_name));
+ if (!n || n < 2 || (ent->d_name[0] == '.'))
+ continue;
+ log_debug("viz: module %s to load", ent->d_name);
+ snprintf(path, sizeof(path), "%s/%s", dir, ent->d_name);
+ handle = dlopen(path, RTLD_LAZY);
+ log_tmp("m 1");
+ if (!handle)
+ continue;
+ dlerror(); // clear errors
+
+ log_tmp("m 2");
+ if (!(sym = dlsym(handle, "ggdmodviz_init")))
+ continue;
+ fn_ggdmodviz_init = sym;
+ dlerror(); // clear errors
+
+ log_tmp("m 3");
+ if (!(sym = dlsym(handle, "ggdmodviz_text_get")))
+ continue;
+ fn_ggdmodviz_text_get = sym;
+ dlerror(); // clear errors
+
+ log_tmp("m 4");
+ modconf = fn_ggdmodviz_init(_ggd);
+ if (!modconf)
+ continue;
+
+ log_tmp("m 5");
+ mod = xcalloc(1, sizeof(struct ggdmodviz));
+ mod->handle = handle;
+ mod->name = strdup(ent->d_name);
+ mod->conf = modconf;
+ mod->ggdmodviz_init = fn_ggdmodviz_init;
+ mod->ggdmodviz_text_get = fn_ggdmodviz_text_get;
+ LIST_INSERT_HEAD(&_viz->mods, mod, entry);
+
+ log_debug("viz: module %s done, id %d", mod->name, mod->conf->id);
+ }
+ closedir(d);
return 0;
+
+err:
+ log_warn("viz: modules load failed");
+ if (d)
+ closedir(d);
+ return -1;
}
/*
- * XXX notify modules
+ * Redis notification callback
+ *
+ * algo to notify modules:
* notif = extract reply->str
* foreach module
* if ! module match dbname
@@ -81,38 +126,32 @@ static void
_redis_cb_notification(redisAsyncContext *c, void *r, void *privdata)
{
redisReply *reply;
- struct mod *m;
- char *ntf_type, *ntf_pattern, *ntf_event, *ntf_target, *ntf_event_type, *ntf_op;
- uint ntf_db;
- int i;
+ struct ggdviz_cli *cli;
+ struct ggdmodviz *m;
+ char *ntf_type, *ntf_pattern, *ntf_event_type, *ntf_op, *ntf_target;
+ int ntf_db, res;
reply = r;
if (!reply)
return;
-
- notification = reply->str;
- i = sscanf(reply->str, "\"%s\",\"%s\",\"%s\",\"%s\",
- &ntf_type, &ntf_pattern, &ntf_event, &ntf_target);
- if (i <= 3) {
- log_notice("viz: error parsing redis notification !");
- return;
- }
- i = sscanf(ntf_event, "__%s@%d__:%s",
- &ntf_event_type, &ntf_db, &ntf_op);
- if (i <= 3) {
- log_notice("viz: error parsing redis notification event type !");
- return;
- }
+ log_debug("viz: _redis_cb_notification: %s", reply->str);
+ res = parse_redis_keyspace_notification(reply->str,
+ &ntf_type, &ntf_pattern, &ntf_event_type, &ntf_db, &ntf_op, &ntf_target);
+ if (res < 0) {
+ log_info("viz: could not parse redis keyspace notification (%d) !\n"
+ "Notification was: %s", res, reply->str);
+ return;
+ }
LIST_FOREACH(m, &_viz->mods, entry) {
- if (m->dl->id != ntf_id)
+ if (m->conf->id != ntf_db)
continue;
LIST_FOREACH(cli, &_viz->clients, entry) {
- m->dl->ggdmodviz_text_get(cli, ntf_op, ntf_target);
+ if (cli->type == GGDVIZ_CLI_TCP)
+ m->ggdmodviz_text_get(cli, ntf_op, ntf_target);
}
}
-
log_debug("viz: redis cb_notification: %s", reply->str);
}
@@ -152,12 +191,13 @@ _redis_connect(void)
void
_redis_disconnect(void)
{
- redis_disconnect(_viz->rc);
+ if (_viz->rc)
+ redis_disconnect(_viz->rc);
_viz->rc = NULL;
}
-struct servtcp_cli *
+struct ggdviz_cli *
_servtcp_cli_add(struct sockaddr *sa, struct bufferevent *bev)
{
struct ggdviz_cli *cli;
@@ -171,7 +211,7 @@ _servtcp_cli_add(struct sockaddr *sa, struct bufferevent *bev)
LIST_INSERT_HEAD(&_viz->clients, cli, entry);
log_debug("viz: _servtcp_cli_add, cli %d %s",
- cli->id, addr_ntoa(&cli->addr));
+ cli->id, addr_ntoa(&cli->tcp.addr));
bufferevent_write(bev, MSG_WELCOME, strlen(MSG_WELCOME));
return cli;
@@ -180,7 +220,7 @@ _servtcp_cli_add(struct sockaddr *sa, struct bufferevent *bev)
void
_servtcp_cli_del(struct ggdviz_cli *cli)
{
- bufferevent_free(cli->bev);
+ bufferevent_free(cli->tcp.bev);
LIST_REMOVE(cli, entry);
_viz->clients_count--;
free(cli);
@@ -198,7 +238,7 @@ _servtcp_cb_read(struct bufferevent *bev, void *user_data)
buf = bufferevent_get_input(bev);
line = evbuffer_readln(buf, &len, EVBUFFER_EOL_CRLF);
log_debug("viz: _servtcp_cb_read, cli %d %s, len %d: %s",
- cli->id, addr_ntoa(&cli->addr), len, line);
+ cli->id, addr_ntoa(&cli->tcp.addr), len, line);
}
static void
@@ -264,7 +304,7 @@ _servtcp_start(void)
void
_servtcp_stop(void)
{
- struct servtcp_cli *cli, *clitmp;
+ struct ggdviz_cli *cli, *clitmp;
if (_viz->servtcp.listener)
evconnlistener_free(_viz->servtcp.listener);
@@ -286,6 +326,7 @@ viz_init(struct glougloud *ggd)
setprocname("viz");
droppriv(GLOUGLOUD_USER_VIZ, 1, NULL);
+ _viz->evb = event_base_new();
if (_modules_load() < 0)
goto err;
if (_redis_connect() < 0)
@@ -295,11 +336,12 @@ viz_init(struct glougloud *ggd)
event_base_dispatch(_viz->evb);
- return 0;
+ exit(0);
err:
viz_shutdown();
- return -1;
+ log_fatal("viz error");
+ exit(-1); /* UNREACHED */
}
void