mirror of
https://github.com/owntracks/recorder.git
synced 2026-08-23 11:26:16 +00:00
New feature: Lua hooks
This commit is contained in:
@@ -19,6 +19,13 @@ CFLAGS += -DGHASHPREC=$(GHASHPREC)
|
||||
ifeq ($(HAVE_PING),yes)
|
||||
CFLAGS += -DHAVE_PING=1
|
||||
endif
|
||||
|
||||
ifeq ($(WITH_LUA),yes)
|
||||
CFLAGS += -DWITH_LUA=1 $(LUA_CFLAGS)
|
||||
LIBS += $(LUA_LIBS)
|
||||
OTR_OBJS += hooks.o
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_KILL),yes)
|
||||
CFLAGS += -DHAVE_KILL=1
|
||||
endif
|
||||
@@ -60,7 +67,7 @@ ocat: ocat.o $(OTR_OBJS)
|
||||
$(CC) $(CFLAGS) -o ocat ocat.o $(OTR_OBJS) $(LIBS)
|
||||
|
||||
|
||||
ot-recorder.o: ot-recorder.c storage.h util.h Makefile geo.h udata.h json.h http.h gcache.h config.mk
|
||||
ot-recorder.o: ot-recorder.c storage.h util.h Makefile geo.h udata.h json.h http.h gcache.h config.mk hooks.h
|
||||
geo.o: geo.h geo.c udata.h Makefile config.mk
|
||||
geohash.o: geohash.h geohash.c udata.h Makefile config.mk
|
||||
base64.o: base64.h base64.c
|
||||
@@ -71,6 +78,7 @@ util.o: util.c util.h Makefile config.mk
|
||||
mongoose.o: mongoose.c mongoose.h
|
||||
ocat.o: ocat.c storage.h util.h config.mk version.h
|
||||
storage.o: storage.c storage.h util.h gcache.h config.mk
|
||||
hooks.o: hooks.c udata.h hooks.h util.h version.h
|
||||
|
||||
|
||||
clean:
|
||||
|
||||
@@ -224,6 +224,7 @@ You will require:
|
||||
* [libmosquitto](http://mosquitto.org)
|
||||
* [libCurl](http://curl.haxx.se/libcurl/)
|
||||
* [lmdb](http://symas.com/mdb) included
|
||||
* Optionally [Lua](http://lua.org)
|
||||
|
||||
Obtain and download the software, either [as a package, if available](https://packagecloud.io/owntracks/ot-recorder), via [our Homebrew Tap](https://github.com/owntracks/homebrew-recorder) on Mac OS X, directly as a clone of the repository, or as a [tar ball](https://github.com/owntracks/recorder/releases) which you unpack. Copy the included `config.mk.in` file to `config.mk` and edit that. You specify the features or tweaks you need. (The file is commented.) Pay particular attention to the installation directory and the value of the _store_ (`STORAGEDEFAULT`): that is where the recorder will store its files. `DOCROOT` is the root of the directory from which the _recorder_'s HTTP server will serve files.
|
||||
|
||||
@@ -417,6 +418,73 @@ curl 'http://127.0.0.1:8083/api/0/kill?user=ngin&device=ojo'
|
||||
```
|
||||
The response contains a list of removed `.rec` files, and file system operations are logged to syslog.
|
||||
|
||||
## Lua hook
|
||||
|
||||
If _recorder_ is compiled with Lua support, a Lua script you provide is launched at startup. Lua is _a powerful, fast, lightweight, embeddable scripting language_. You can use this to process location publishes in any way you desire: your imagination (and Lua-scripting knowhow) set the limits. Some examples:
|
||||
|
||||
* insert publishes into a database of your choice
|
||||
* switch on the coffee machine when your OwnTracks device reports you're entering home (but see also [mqttwarn](http://jpmens.net/2014/02/17/introducing-mqttwarn-a-pluggable-mqtt-notifier/)
|
||||
* write a file with data in a format of your choice (see `etc/example.lua`)
|
||||
|
||||
Run the _recorder_ with the path to your Lua script specified in its `--lua-script` option (there is no default). If the script cannot be loaded (e.g. because it cannot be read or contains syntax errors), the _recorder_ unloads Lua and continues *without* your script.
|
||||
|
||||
Your Lua program is automatically provided with a table which contains the following members:
|
||||
|
||||
* `otr.version` is a read-only string with the _recorder_ version (example: `"0.3.2"`)
|
||||
* `otr.log()` is a function which takes a string which is logged to syslog at the _recorder_'s facility and log level INFO.
|
||||
* `otr.strftime(fmt, t)` is a function which takes a format string (see `strftime(3)`) and an integer number of seconds and returns a string with the formatted UTC time. If `t` is 0 or negative, the current system time is used.
|
||||
|
||||
Your Lua script must provide the following functions:
|
||||
|
||||
### `otr_init`
|
||||
|
||||
This is invoked at start of _recorder_. If the function returns a non-zero value, _recorder_ unloads Lua and disables its processing; i.e. the `hook()` will *not* be invoked on location publishes.
|
||||
|
||||
### `otr_exit`
|
||||
|
||||
This is invoked when the _recorder_ stops, which it doesn't really do unless you CTRL-C it.
|
||||
|
||||
### `otr_hook`
|
||||
|
||||
This function is invoked at every location publish processed by the _recorder_. Your function is passed three arguments:
|
||||
|
||||
1. _topic_ is the topic published to (e.g. `owntracks/jane/phone`)
|
||||
2. _type_ is the type of MQTT message. This is the `_type` in our JSON messages (e.g. `location`) or `"unknown"`.
|
||||
3. _location_ is a [Lua table](http://www.lua.org/pil/2.5.html) (associative array) with all the elements obtained in the JSON message. In the case of _type_ being `location`, we also add country code (`cc`) and the location's address (`addr`) unless reverse-geo lookups have been disabled in _recorder_.
|
||||
|
||||
Assume the following small example Lua script in `example.lua`:
|
||||
|
||||
```lua
|
||||
local file
|
||||
|
||||
function otr_init()
|
||||
otr.log("example.lua starting; writing to /tmp/lua.out")
|
||||
file = io.open("/tmp/lua.out", "a")
|
||||
file:write("written by OwnTracks Recorder version " .. otr.version .. "\n")
|
||||
end
|
||||
|
||||
function otr_hook(topic, _type, data)
|
||||
local timestr = otr.strftime("It is %T in the year %Y", 0)
|
||||
print("L: " .. topic .. " -> " .. _type)
|
||||
file:write(timestr .. " " .. topic .. " lat=" .. data['lat'] .. data['addr'] .. "\n")
|
||||
end
|
||||
```
|
||||
|
||||
When _recorder_ is launched with `--lua-script example.lua` it invokes `otr_init()` which opens a file. Then, for each location received, it calls `otr_hook()` which updates the file.
|
||||
|
||||
Assuming an OwnTracks device publishes this payload
|
||||
|
||||
```json
|
||||
{"cog":-1,"batt":-1,"lon":2.29513,"acc":5,"vel":-1,"vac":-1,"lat":48.85833,"t":"u","tst":1441984413,"alt":0,"_type":"location","tid":"JJ"}
|
||||
```
|
||||
|
||||
the file `/tmp/lua.out` would contain
|
||||
|
||||
```txt
|
||||
written by OwnTracks Recorder version 0.3.0
|
||||
It is 14:10:01 in the year 2015 owntracks/jane/phone lat=48.858339 Avenue Anatole France, 75007 Paris, France
|
||||
```
|
||||
|
||||
#### Environment
|
||||
|
||||
The following environment variables control _ocat_'s behaviour:
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 41 KiB |
@@ -8,6 +8,9 @@ HAVE_HTTP ?= yes
|
||||
# Do you want to use reverse-geo caching? (Highly recommended)
|
||||
HAVE_LMDB ?= yes
|
||||
|
||||
# Do you have Lua libraries installed and want the Lua hook integration?
|
||||
WITH_LUA ?= no
|
||||
|
||||
# Do you want support for the `pingping' monitoring feature?
|
||||
HAVE_PING ?= yes
|
||||
|
||||
@@ -51,3 +54,6 @@ APIKEY ?=
|
||||
MOSQUITTO_INC = -I/usr/include
|
||||
MOSQUITTO_LIB = -L/usr/lib
|
||||
MORELIBS = # -lssl
|
||||
|
||||
LUA_CFLAGS =
|
||||
LUA_LIBS = -llua
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
local file
|
||||
|
||||
function otr_init()
|
||||
otr.log("example.lua starting; writing to /tmp/lua.out")
|
||||
file = io.open("/tmp/lua.out", "a")
|
||||
file:write("written by OwnTracks Recorder version " .. otr.version .. "\n")
|
||||
end
|
||||
|
||||
function otr_hook(topic, _type, data)
|
||||
local timestr = otr.strftime("It is %T in the year %Y", 0)
|
||||
print("L: " .. topic .. " -> " .. _type)
|
||||
file:write(timestr .. " " .. topic .. " lat=" .. data['lat'] .. data['addr'] .. "\n")
|
||||
end
|
||||
@@ -0,0 +1,201 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef WITH_LUA
|
||||
# include <stdarg.h>
|
||||
# include <stdint.h>
|
||||
# include "util.h"
|
||||
# include "udata.h"
|
||||
# include "hooks.h"
|
||||
# include "lua.h"
|
||||
# include "lualib.h"
|
||||
# include "lauxlib.h"
|
||||
# include "json.h"
|
||||
# include "version.h"
|
||||
|
||||
static int otr_log(lua_State *lua);
|
||||
static int otr_strftime(lua_State *lua);
|
||||
|
||||
/*
|
||||
* Invoke the function `name' in the Lua script, which _may_ return
|
||||
* an integer that we, in turn, return to caller.
|
||||
*/
|
||||
|
||||
static int l_function(lua_State *L, char *name)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
lua_getglobal(L, name);
|
||||
if (lua_type(L, -1) != LUA_TFUNCTION) {
|
||||
olog(LOG_ERR, "Cannot invoke Lua function %s: %s\n", name, lua_tostring(L, -1));
|
||||
rc = 1;
|
||||
} else {
|
||||
lua_call(L, 0, 1);
|
||||
rc = (int)lua_tonumber(L, -1);
|
||||
}
|
||||
lua_settop(L, 0);
|
||||
return (rc);
|
||||
}
|
||||
|
||||
struct luadata *hooks_init(char *script)
|
||||
{
|
||||
struct luadata *ld;
|
||||
int rc;
|
||||
|
||||
if ((ld = malloc(sizeof(struct luadata))) == NULL)
|
||||
return (NULL);
|
||||
|
||||
ld->script = strdup(script);
|
||||
// ld->L = lua_open();
|
||||
ld->L = luaL_newstate();
|
||||
luaL_openlibs(ld->L);
|
||||
|
||||
/*
|
||||
* Set up a global with some values.
|
||||
*/
|
||||
|
||||
lua_newtable(ld->L);
|
||||
lua_pushstring(ld->L, VERSION);
|
||||
lua_setfield(ld->L, -2, "version");
|
||||
|
||||
// lua_pushstring(ld->L, "/Users/jpm/Auto/projects/on-github/owntracks/recorder/lua");
|
||||
// lua_setfield(ld->L, -2, "luapath");
|
||||
|
||||
lua_pushcfunction(ld->L, otr_log);
|
||||
lua_setfield(ld->L, -2, "log");
|
||||
|
||||
lua_pushcfunction(ld->L, otr_strftime);
|
||||
lua_setfield(ld->L, -2, "strftime");
|
||||
|
||||
lua_setglobal(ld->L, "otr");
|
||||
|
||||
|
||||
olog(LOG_DEBUG, "initializing Lua hooks at %s", script);
|
||||
|
||||
/* Load the Lua script */
|
||||
if (luaL_dofile(ld->L, ld->script)) {
|
||||
olog(LOG_ERR, "Cannot load Lua from %s: %s", ld->script, lua_tostring(ld->L, -1));
|
||||
hooks_exit(ld, "failed to load script");
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
rc = l_function(ld->L, "otr_init");
|
||||
if (rc != 0) {
|
||||
|
||||
/*
|
||||
* After all this work (sigh), the Script has decided we shouldn't use
|
||||
* hooks, so unload the whole Lua stuff and NULL back.
|
||||
*/
|
||||
|
||||
hooks_exit(ld, "otr_init() returned non-zero");
|
||||
ld = NULL;
|
||||
}
|
||||
|
||||
|
||||
return (ld);
|
||||
}
|
||||
|
||||
void hooks_exit(struct luadata *ld, char *reason)
|
||||
{
|
||||
if (ld) {
|
||||
olog(LOG_NOTICE, "unloading Lua: %s", reason);
|
||||
free(ld->script);
|
||||
lua_close(ld->L);
|
||||
free(ld);
|
||||
}
|
||||
}
|
||||
|
||||
void hooks_hook(struct udata *ud, char *topic, JsonNode *fullo)
|
||||
{
|
||||
struct luadata *ld = ud->luadata;
|
||||
char *_type = "unknown";
|
||||
JsonNode *j;
|
||||
|
||||
lua_getglobal(ld->L, "otr_hook");
|
||||
if (lua_type(ld->L, -1) != LUA_TFUNCTION) {
|
||||
olog(LOG_NOTICE, "cannot invoke otr_hook in Lua script");
|
||||
return;
|
||||
}
|
||||
|
||||
lua_pushstring(ld->L, topic); /* arg1: topic */
|
||||
|
||||
if ((j = json_find_member(fullo, "_type")) != NULL) {
|
||||
if (j->tag == JSON_STRING)
|
||||
_type = j->string_;
|
||||
}
|
||||
|
||||
lua_pushstring(ld->L, _type); /* arg2: record type */
|
||||
|
||||
lua_newtable(ld->L); /* arg3: table */
|
||||
json_foreach(j, fullo) {
|
||||
lua_pushstring(ld->L, j->key); /* table key */
|
||||
if (j->tag == JSON_STRING) {
|
||||
lua_pushstring(ld->L, j->string_);
|
||||
} else if (j->tag == JSON_NUMBER) {
|
||||
lua_pushnumber(ld->L, j->number_);
|
||||
} else if (j->tag == JSON_NULL) {
|
||||
lua_pushnil(ld->L);
|
||||
} else if (j->tag == JSON_BOOL) {
|
||||
lua_pushboolean(ld->L, j->bool_);
|
||||
}
|
||||
lua_rawset(ld->L, -3);
|
||||
|
||||
}
|
||||
|
||||
/* Invoke `hook' function in Lua with our args */
|
||||
if (lua_pcall(ld->L, 3, 1, 0)) {
|
||||
olog(LOG_ERR, "Failed to run script: %s", lua_tostring(ld->L, -1));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// rc = (int)lua_tonumber(ld->L, -1);
|
||||
// printf("C: FILTER returns %d\n", rc);
|
||||
}
|
||||
|
||||
/*
|
||||
* --- Here come the functions we provide to Lua scripts.
|
||||
*/
|
||||
|
||||
static int otr_log(lua_State *lua)
|
||||
{
|
||||
const char *str;
|
||||
|
||||
if (lua_gettop(lua) >= 1) {
|
||||
str = lua_tostring(lua, 1);
|
||||
olog(LOG_INFO, "%s", str);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* otr.strftime(format, seconds)
|
||||
* Perform a strtime(3) for Lua with the specified format and
|
||||
* seconds, and return the string result to Lua. As a special
|
||||
* case, if `seconds' is negative, use current time.
|
||||
*/
|
||||
|
||||
static int otr_strftime(lua_State *lua)
|
||||
{
|
||||
const char *fmt;
|
||||
long secs;
|
||||
struct tm *tm;
|
||||
char buf[BUFSIZ];
|
||||
|
||||
if (lua_gettop(lua) >= 1) {
|
||||
fmt = lua_tostring(lua, 1);
|
||||
if ((secs = lua_tonumber(lua, 2)) < 1)
|
||||
secs = time(0);
|
||||
|
||||
if ((tm = gmtime(&secs)) != NULL) {
|
||||
strftime(buf, sizeof(buf), fmt, tm);
|
||||
|
||||
lua_pushstring(lua, buf);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
#endif /* WITH_LUA */
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef HOOKS_H_INCLUDED
|
||||
# define HOOKS_H_INCLUDED
|
||||
|
||||
#ifdef WITH_LUA
|
||||
# include "lua.h"
|
||||
|
||||
|
||||
struct luadata {
|
||||
char *script; /* Path to Lua script in --lua-script */
|
||||
lua_State *L; /* The Lua machine */
|
||||
};
|
||||
|
||||
struct luadata *hooks_init(char *luascript);
|
||||
void hooks_exit(struct luadata *, char *reason);
|
||||
void hooks_hook(struct udata *ud, char *topic, JsonNode *obj);
|
||||
|
||||
#endif /* WITH_LUA */
|
||||
|
||||
#endif
|
||||
@@ -173,6 +173,9 @@ void print_versioninfo()
|
||||
#ifdef HAVE_LMDB
|
||||
printf("\tHAVE_LMDB = yes\n");
|
||||
#endif
|
||||
#ifdef WITH_LUA
|
||||
printf("\tWITH_LUA = yes\n");
|
||||
#endif
|
||||
#ifdef HAVE_HTTP
|
||||
printf("\tHAVE_HTTP = yes\n");
|
||||
#endif
|
||||
|
||||
+79
-38
@@ -45,6 +45,9 @@
|
||||
#ifdef HAVE_HTTP
|
||||
# include "http.h"
|
||||
#endif
|
||||
#ifdef WITH_LUA
|
||||
# include "hooks.h"
|
||||
#endif
|
||||
|
||||
|
||||
#define SSL_VERIFY_PEER (1)
|
||||
@@ -357,7 +360,7 @@ JsonNode *csv(char *payload, char *tid, char *t, double *lat, double *lon, long
|
||||
|
||||
void on_message(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *m)
|
||||
{
|
||||
JsonNode *json;
|
||||
JsonNode *json, *fullo, *geo = NULL;
|
||||
char tid[BUFSIZ], t[BUFSIZ], *p;
|
||||
double lat, lon;
|
||||
long tst;
|
||||
@@ -510,7 +513,7 @@ void on_message(struct mosquitto *mosq, void *userdata, const struct mosquitto_m
|
||||
|
||||
cached = FALSE;
|
||||
if (ud->revgeo == TRUE) {
|
||||
JsonNode *geo, *j;
|
||||
JsonNode *j;
|
||||
|
||||
if ((geo = gcache_json_get(ud->gc, utstring_body(ghash))) != NULL) {
|
||||
/* Habemus cached data */
|
||||
@@ -523,11 +526,9 @@ void on_message(struct mosquitto *mosq, void *userdata, const struct mosquitto_m
|
||||
if ((j = json_find_member(geo, "addr")) != NULL) {
|
||||
utstring_printf(addr, "%s", j->string_);
|
||||
}
|
||||
json_delete(geo);
|
||||
} else {
|
||||
if ((geo = revgeo(lat, lon, addr, cc)) != NULL) {
|
||||
gcache_json_put(ud->gc, utstring_body(ghash), geo);
|
||||
json_delete(geo);
|
||||
} else {
|
||||
/* We didn't obtain reverse Geo, maybe because of over
|
||||
* quota; make a note of the missing geohash */
|
||||
@@ -551,45 +552,51 @@ void on_message(struct mosquitto *mosq, void *userdata, const struct mosquitto_m
|
||||
* We have exactly three topic parts (owntracks/user/device), and valid JSON.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Create a new location object containing all the bits and
|
||||
* pieces we need and push that into connected Websockets.
|
||||
* and/or into Lua hooks.
|
||||
*/
|
||||
|
||||
fullo = json_mkobject();
|
||||
json_copy_to_object(fullo, json, TRUE);
|
||||
|
||||
if (geo != NULL) {
|
||||
json_copy_to_object(fullo, geo, FALSE);
|
||||
json_delete(geo);
|
||||
}
|
||||
|
||||
/*
|
||||
* I need a unique "key" in the Websocket clients to keep track
|
||||
* of which device is being updated; use topic.
|
||||
*/
|
||||
|
||||
json_append_member(fullo, "topic", json_mkstring(m->topic));
|
||||
|
||||
/*
|
||||
* We have to know which user/device this is for in order to
|
||||
* determine whether a connected Websocket client is authorized
|
||||
* to see this. Add user/device
|
||||
*/
|
||||
|
||||
json_append_member(fullo, "user", json_mkstring(utstring_body(username)));
|
||||
json_append_member(fullo, "device", json_mkstring(utstring_body(device)));
|
||||
|
||||
#ifdef HAVE_HTTP
|
||||
if (ud->mgserver && !pingping) {
|
||||
|
||||
/*
|
||||
* Create a new location object containing all the bits and
|
||||
* pieces we need and push that into connected Websockets.
|
||||
* TODO: clean up
|
||||
*/
|
||||
|
||||
JsonNode *geo, *wso = json_mkobject();
|
||||
|
||||
json_copy_to_object(wso, json, TRUE);
|
||||
|
||||
if ((geo = gcache_json_get(ud->gc, utstring_body(ghash))) != NULL) {
|
||||
json_copy_to_object(wso, geo, FALSE);
|
||||
json_delete(geo);
|
||||
}
|
||||
|
||||
/*
|
||||
* I need a unique "key" in the Websocket clients to keep track
|
||||
* of which device is being updated; use topic.
|
||||
*/
|
||||
|
||||
json_append_member(wso, "topic", json_mkstring(m->topic));
|
||||
|
||||
/*
|
||||
* We have to know which user/device this is for in order to
|
||||
* determine whether a connected Websocket client is authorized
|
||||
* to see this. Add user/device
|
||||
*/
|
||||
|
||||
json_append_member(wso, "user", json_mkstring(utstring_body(username)));
|
||||
json_append_member(wso, "device", json_mkstring(utstring_body(device)));
|
||||
|
||||
http_ws_push_json(ud->mgserver, wso);
|
||||
json_delete(wso);
|
||||
http_ws_push_json(ud->mgserver, fullo);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_LUA
|
||||
if (ud->luadata && !pingping) {
|
||||
hooks_hook(ud, m->topic, fullo);
|
||||
}
|
||||
#endif
|
||||
json_delete(fullo);
|
||||
|
||||
|
||||
if ((jsonstring = json_stringify(json, NULL)) != NULL) {
|
||||
char *js;
|
||||
@@ -685,8 +692,7 @@ void on_disconnect(struct mosquitto *mosq, void *userdata, int reason)
|
||||
static void catcher(int sig)
|
||||
{
|
||||
fprintf(stderr, "Going down on signal %d\n", sig);
|
||||
|
||||
exit(1);
|
||||
run = 0;
|
||||
}
|
||||
|
||||
void usage(char *prog)
|
||||
@@ -707,6 +713,9 @@ void usage(char *prog)
|
||||
printf(" --http-host <host> HTTP addr to bind to (localhost)\n");
|
||||
printf(" --http-port <port> -A HTTP port (8083); 0 to disable HTTP\n");
|
||||
printf(" --doc-root <directory> document root (%s)\n", DOCROOT);
|
||||
#endif
|
||||
#ifdef WITH_LUA
|
||||
printf(" --lua-script <script.lua> path to Lua script. If unset, no Lua hooks\n");
|
||||
#endif
|
||||
printf(" --precision ghash precision (dflt: %d)\n", GHASHPREC);
|
||||
printf(" --hosted use OwnTracks Hosted\n");
|
||||
@@ -732,6 +741,9 @@ int main(int argc, char **argv)
|
||||
struct mosquitto *mosq = NULL;
|
||||
char err[1024], *p, *username, *password, *cafile, *device;
|
||||
char *hostname = "localhost", *logfacility = "local0";
|
||||
#ifdef WITH_LUA
|
||||
char *luascript = NULL;
|
||||
#endif
|
||||
int port = 1883;
|
||||
int rc, i, ch, hosted = FALSE;
|
||||
static struct udata udata, *ud = &udata;
|
||||
@@ -755,6 +767,9 @@ int main(int argc, char **argv)
|
||||
#ifdef HAVE_HTTP
|
||||
udata.mgserver = NULL;
|
||||
#endif
|
||||
#ifdef WITH_LUA
|
||||
udata.luadata = NULL;
|
||||
#endif
|
||||
|
||||
if ((p = getenv("OTR_HOST")) != NULL) {
|
||||
hostname = strdup(p);
|
||||
@@ -790,6 +805,9 @@ int main(int argc, char **argv)
|
||||
{ "logfacility", required_argument, 0, 4},
|
||||
{ "precision", required_argument, 0, 5},
|
||||
{ "hosted", no_argument, 0, 6},
|
||||
#ifdef WITH_LUA
|
||||
{ "lua-script", required_argument, 0, 7},
|
||||
#endif
|
||||
#ifdef HAVE_HTTP
|
||||
{ "http-host", required_argument, 0, 3},
|
||||
{ "http-port", required_argument, 0, 'A'},
|
||||
@@ -804,6 +822,12 @@ int main(int argc, char **argv)
|
||||
break;
|
||||
|
||||
switch (ch) {
|
||||
#ifdef WITH_LUA
|
||||
case 7:
|
||||
/* FIXME: check existence of script file */
|
||||
luascript = strdup(optarg);
|
||||
break;
|
||||
#endif
|
||||
case 6:
|
||||
hosted = TRUE;
|
||||
break;
|
||||
@@ -911,6 +935,18 @@ int main(int argc, char **argv)
|
||||
|
||||
openlog("ot-recorder", LOG_PID | LOG_PERROR, syslog_facility_code(logfacility));
|
||||
|
||||
#ifdef WITH_LUA
|
||||
/*
|
||||
* If option for lua-script has not been given, ignore all hooks.
|
||||
*/
|
||||
|
||||
if (luascript) {
|
||||
if ((udata.luadata = hooks_init(luascript)) == NULL)
|
||||
olog(LOG_NOTICE, "proceeding sans Lua");
|
||||
free(luascript);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_HTTP
|
||||
if (http_port) {
|
||||
if (!is_directory(doc_root)) {
|
||||
@@ -946,6 +982,7 @@ int main(int argc, char **argv)
|
||||
|
||||
|
||||
signal(SIGINT, catcher);
|
||||
signal(SIGTERM, catcher);
|
||||
|
||||
mosq = mosquitto_new(utstring_body(clientid), CLEAN_SESSION, (void *)&udata);
|
||||
if (!mosq) {
|
||||
@@ -1059,6 +1096,10 @@ int main(int argc, char **argv)
|
||||
#ifdef HAVE_HTTP
|
||||
mg_destroy_server(&udata.mgserver);
|
||||
#endif
|
||||
|
||||
#ifdef WITH_LUA
|
||||
hooks_exit(ud->luadata, "recorder stops");
|
||||
#endif
|
||||
mosquitto_disconnect(mosq);
|
||||
|
||||
mosquitto_destroy(mosq);
|
||||
|
||||
Reference in New Issue
Block a user