From a4f9323b1550715446453c6015a4e2df48f98855 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Wed, 30 Mar 2011 01:13:17 +0000 Subject: moved to new names (rhnop-client and server) diff --git a/nopcollect/conf.lua b/nopcollect/conf.lua deleted file mode 100644 index eb1cd29..0000000 --- a/nopcollect/conf.lua +++ /dev/null @@ -1,33 +0,0 @@ --- --- rhnop --- --- Copyright (C) 2011 Christian Pointner --- --- This file is part of rhnop. --- --- rhnop is free software: you can redistribute it and/or modify --- it under the terms of the GNU General Public License as published by --- the Free Software Foundation, either version 3 of the License, or --- any later version. --- --- rhnop is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU General Public License for more details. --- --- You should have received a copy of the GNU General Public License --- along with rhnop. If not, see . --- - -local conf = {} - -local file = assert(io.open("nopcollect.conf", "r")) -for line in file:lines() do - local k,v = string.match(line, "^([^=#]+)=(.*)$") - if k and v and v ~= "" then - conf[k] = v - end -end -file:close() - -return conf diff --git a/nopcollect/nopcollect b/nopcollect/nopcollect deleted file mode 100755 index 04560e2..0000000 --- a/nopcollect/nopcollect +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/lua --- --- rhnop --- --- Copyright (C) 2011 Christian Pointner --- --- This file is part of rhnop. --- --- rhnop is free software: you can redistribute it and/or modify --- it under the terms of the GNU General Public License as published by --- the Free Software Foundation, either version 3 of the License, or --- any later version. --- --- rhnop is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU General Public License for more details. --- --- You should have received a copy of the GNU General Public License --- along with rhnop. If not, see . --- --- --- send now and next cart# and length to nopsyncd --- this script should be called by the now/next macro cart --- the arguments should be: now# nowlen next# nextlen --- - -require "socket" - -conf = require "conf" - --- connect to server (reconnect after error) -local sock = assert(socket.tcp()) - -local ret, err = sock:connect(conf.host, conf.port) -if ret == nil then - print(err) - return 1 -end - -print "connection established" - --- TODO: load all info we don't have yet - -while true do - local timestamp = sock:receive('*l') - -- TODO: check if connection is closed - print("received: '" .. timestamp .. "'") - - -- TODO: check if we already fetched that timestamp - -- TODO: fetch info for the timestamp and insert it into local db -end -sock:close() -return 0 diff --git a/nopcollect/nopcollect.conf b/nopcollect/nopcollect.conf deleted file mode 100644 index 18316fb..0000000 --- a/nopcollect/nopcollect.conf +++ /dev/null @@ -1,8 +0,0 @@ -host=127.0.0.1 -port=2345 - -db=nop -#db_host=127.0.0.1 -#db_port=3306 -db_user= -db_pwd= diff --git a/noprml/noprml b/noprml/noprml deleted file mode 100755 index 31e8ab7..0000000 --- a/noprml/noprml +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/lua --- --- rhnop --- --- Copyright (C) 2011 Christian Pointner --- --- This file is part of rhnop. --- --- rhnop is free software: you can redistribute it and/or modify --- it under the terms of the GNU General Public License as published by --- the Free Software Foundation, either version 3 of the License, or --- any later version. --- --- rhnop is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU General Public License for more details. --- --- You should have received a copy of the GNU General Public License --- along with rhnop. If not, see . --- --- --- send now and next cart# and length to nopsyncd --- this script should be called by the now/next macro cart --- the arguments should be: now# nowlen next# nextlen --- - -local queue_name = "/rhnop" - -mq = require "mq" - --- reading timestamp (milliseconds since epoch) -local p = assert(io.popen("/bin/date --utc '+%s %N'" , 'r')) -local time = assert(p:read('*l')) -p:close() -local s, ns = assert(string.match(time, "([0-9]+) ([0-9]+)")) -local timestamp = s*1000 + math.floor(ns/1000000) - --- check arguments -if #arg < 4 then - io.stderr:write("too few parameters\n") - os.exit(1) -end - --- open message queue -local q, err = mq.create(queue_name, "wo") -if q == nil then - io.stderr:write("creation of message queue failed: " .. err .. "\n") - os.exit(1) -end - --- send out message to nopsyncd -local result, err = mq.send(q, timestamp .. " " .. arg[1] .. " " .. arg[2] .. " " .. arg[3] .. " " .. arg[4], 0) -if result == nil then - io.stderr:write("sending message failed: " .. err .. "\n") - os.exit(2) -end - -mq.close(q) diff --git a/nopsyncd/Makefile b/nopsyncd/Makefile deleted file mode 100644 index a540d77..0000000 --- a/nopsyncd/Makefile +++ /dev/null @@ -1,91 +0,0 @@ -## -## rhnop -## -## Copyright (C) 2011 Christian Pointner -## -## This file is part of rhnop. -## -## rhnop is free software: you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published by -## the Free Software Foundation, either version 3 of the License, or -## any later version. -## -## rhnop is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with rhnop. If not, see . -## - -ifneq ($(MAKECMDGOALS),distclean) -include include.mk -endif - -EXECUTABLE := nopsyncd - -C_OBJS := l_pipe.o \ - nopsyncd.o - -C_SRCS := $(C_OBJS:%.o=%.c) - -.PHONY: clean distclean install install-bin install-etc uninstall remove purge - -all: $(EXECUTABLE) - -%.d: %.c - @set -e; rm -f $@; \ - $(CC) -MM $(CFLAGS) $< > $@.$$$$; \ - sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ - rm -f $@.$$$$; echo '(re)building $@' - -ifneq ($(MAKECMDGOALS),distclean) --include $(C_SRCS:%.c=%.d) -endif - -$(EXECUTABLE): $(C_OBJS) - $(CC) $(C_OBJS) -o $@ $(LDFLAGS) - -%.o: %.c - $(CC) $(CFLAGS) -c $< - -strip: $(EXECUTABLE) - $(STRIP) -s $(EXECUTABLE) - - -distclean: clean - find . -name *.o -exec rm -f {} \; - find . -name "*.\~*" -exec rm -rf {} \; - rm -f include.mk - -clean: - rm -f *.o - rm -f *.d - rm -f *.d.* - rm -f $(EXECUTABLE) - -INSTALL_TARGETS := install-bin install-etc -REMOVE_TARGETS := remove-bin remove-etc - -install: all $(INSTALL_TARGETS) - -install-bin: $(EXECUTABLE) - $(INSTALL) -d $(DESTDIR)$(BINDIR) - $(INSTALL) -m 755 $(EXECUTABLE) $(DESTDIR)$(BINDIR) - -install-etc: - $(INSTALL) -d $(DESTDIR)$(ETCDIR)/$(EXECUTABLE) - -uninstall: remove - -remove: $(REMOVE_TARGETS) - -remove-bin: - rm -f $(DESTDIR)$(BINDIR)/$(EXECUTABLE) - -remove-etc: - rm -f $(DESTDIR)$(ETCDIR)/init.d/$(EXECUTABLE) - -purge: remove - rm -rf $(DESTDIR)$(ETCDIR)/$(EXECUTABLE)/ diff --git a/nopsyncd/conf.lua b/nopsyncd/conf.lua deleted file mode 100644 index 83257b5..0000000 --- a/nopsyncd/conf.lua +++ /dev/null @@ -1,33 +0,0 @@ --- --- rhnop --- --- Copyright (C) 2011 Christian Pointner --- --- This file is part of rhnop. --- --- rhnop is free software: you can redistribute it and/or modify --- it under the terms of the GNU General Public License as published by --- the Free Software Foundation, either version 3 of the License, or --- any later version. --- --- rhnop is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU General Public License for more details. --- --- You should have received a copy of the GNU General Public License --- along with rhnop. If not, see . --- - -local conf = {} - -local file = assert(io.open("nopsyncd.conf", "r")) -for line in file:lines() do - local k,v = string.match(line, "^([^=#]+)=(.*)$") - if k and v and v ~= "" then - conf[k] = v - end -end -file:close() - -return conf diff --git a/nopsyncd/configure b/nopsyncd/configure deleted file mode 100755 index 30145f2..0000000 --- a/nopsyncd/configure +++ /dev/null @@ -1,190 +0,0 @@ -#!/bin/sh -# -# rhnop -# -# Copyright (C) 2011 Christian Pointner -# -# This file is part of rhnop. -# -# rhnop is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# any later version. -# -# rhnop is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with rhnop. If not, see . -# - -TARGET=`uname -s` -EBUILD_COMPAT=0 - -CFLAGS='-g -O2' -LDFLAGS='-g -Wall -O2 -lpthread' - -LUA_DIR='' -LUA='' - -PREFIX='/usr/local' -BINDIR='' -ETCDIR='' - -print_usage() { - echo "configure --help print this" - echo " --target= build target i.e. Linux (default: autodetect)" - echo " --prefix= the installation prefix (default: /usr/local)" - echo " --bindir= the path to the bin directory (default: $PREFIX/bin)" - echo " --sysconfdir= the path to the system configuration directory (default: $PREFIX/etc)" - echo " --with-lua= use this lua tree instead of system default" -} - -for arg -do - case $arg in - --target=*) - TARGET=${arg#--target=} - ;; - --prefix=*) - PREFIX=${arg#--prefix=} - ;; - --bindir=*) - BINDIR=${arg#--bindir=} - ;; - --sysconfdir=*) - ETCDIR=${arg#--sysconfdir=} - ;; - --with-lua=*) - LUA_DIR=${arg#--with-lua=} - ;; - --ebuild-compat) - EBUILD_COMPAT=1 - ;; - --help) - print_usage - exit 0 - ;; - *) - ERRORS="$ERRORS $arg" - ;; - esac -done - -if [ -n "$ERRORS" ] && [ $EBUILD_COMPAT -ne 1 ]; then - for error in $ERRORS; do - echo "Unknown argument: $error" - done - - print_usage - exit 1 -fi - -rm -f include.mk -case $TARGET in - Linux) - LDFLAGS=$LDFLAGS' -ldl' - ;; - *) - echo "platform not supported" - exit 1; - ;; -esac - - -test_lua_version() -{ - LUA_VERSION=`cat $1 | grep "#define LUA_VERSION[ ]" | cut -f2- | tr -d '"' | sed -e 's/Lua \([0-9][0-9.]*\)/\1/'` - LUA_VERSION_NUM=`cat $1 | grep "#define LUA_VERSION_NUM" | awk '{ print $3 }'` - LUA_RELEASE=`cat $1 | grep "#define LUA_RELEASE[ ]" | cut -f2-` - - if [ $LUA_VERSION_NUM -ge 501 ]; then - return 1; - else - return 0; - fi -} - -if [ -z "$LUA_DIR" ]; then - for prefix in /usr /usr/local; do - if [ -e $prefix/include/lua.h ]; then - test_lua_version $prefix/include/lua.h - if [ $? -eq 1 ]; then - echo "using Lua $LUA_VERSION ($LUA_RELEASE) found at $prefix/include" - CFLAGS="$CFLAGS -I'$prefix/include'" - LDFLAGS="$LDFLAGS -L'$prefix/lib' -llua" - LUA=$prefix/lua - LUAC=$prefix/luac - break - fi - else - for dir in `ls -d $prefix/include/lua* 2> /dev/null`; do - if [ -e $dir/lua.h ]; then - test_lua_version $dir/lua.h - if [ $? -eq 1 ]; then - echo "using Lua $LUA_VERSION ($LUA_RELEASE) found at $dir" - CFLAGS="$CFLAGS -I$dir" - if [ -x "$prefix/bin/lua$LUA_VERSION" ]; then - LDFLAGS="$LDFLAGS -L'$prefix/lib' -llua$LUA_VERSION" - LUA=$prefix/bin/lua$LUA_VERSION - LUAC=$prefix/bin/luac$LUA_VERSION - elif [ -x "$prefix/bin/lua-$LUA_VERSION" ]; then - LDFLAGS="$LDFLAGS -L'$prefix/lib' -llua-$LUA_VERSION" - LUA=$prefix/bin/lua-$LUA_VERSION - LUAC=$prefix/bin/luac-$LUA_VERSION - else - echo "ERROR: found lua.h at $dir/lua.h but no matching lua and luac" - return 1 - fi - break - fi - fi - done - if [ -n "$LUAC" ]; then - break - fi - fi - done - - if [ -z "$LUAC" ]; then - echo "ERROR: no suitable lua found .. please install lua 5.1 or higher or use --with-lua" - return 1 - fi - -else - CFLAGS="$CFLAGS -I'$LUA_DIR/include'" - LDFLAGS="$LDFLAGS '$LUA_DIR/lib/liblua.a'" - LUA=$LUA_DIR/bin/lua - LUAC=$LUA_DIR/bin/luac -fi - -if [ -z "$BINDIR" ]; then - BINDIR=$PREFIX/bin -fi - -if [ -z "$ETCDIR" ]; then - ETCDIR=$PREFIX/etc -fi - -cat > include.mk < - * - * This file is part of rhnop. - * - * rhnop is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * rhnop is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with rhnop. If not, see . - */ - -#include -#include - -#include -#include -#include - -#include "l_pipe.h" - -static int pipefds_[2]; - -int pipe_init() -{ - return pipe(pipefds_); -} - -void pipe_close() -{ - close(pipefds_[0]); - close(pipefds_[1]); -} - -static int l_pipe_signal(lua_State *L) -{ - size_t len = 0, written = 0; - const char* data = luaL_checklstring(L, 1, &len); - len++; // also send trailing zero - - int ret = 0; - for(;;) { - ret = write(pipefds_[1], &(data[written]), len - written); - if(!ret) continue; - if(ret == -1 && (errno == EAGAIN || errno == EINTR)) continue; - - written += ret; - if(written == len) break; - - break; - } - - lua_pushinteger(L, ret); - return 1; -} - -static int l_pipe_getfd(lua_State *L) -{ - if(!lua_istable(L, -1)) - luaL_error(L, "can't retreive pipe fd"); - - lua_pushliteral(L, "fd"); - lua_gettable(L, -2); - return 1; -} - -static int l_pipe_dirty(lua_State *L) -{ - lua_pushboolean(L, 0); - return 1; -} - -static int l_pipe_getreadfd(lua_State *L) -{ - lua_newtable(L); - lua_pushliteral(L, "fd"); - lua_pushinteger(L, pipefds_[0]); - lua_settable(L, -3); - lua_pushliteral(L, "getfd"); - lua_pushcfunction(L, l_pipe_getfd); - lua_settable(L, -3); - lua_pushliteral(L, "dirty"); - lua_pushcfunction(L, l_pipe_dirty); - lua_settable(L, -3); - return 1; -} - -static int l_pipe_consume(lua_State *L) -{ - char data[17]; // 17 should be sufficient - size_t len = 0; - - int ret = 0; - for(;;) { - ret = read(pipefds_[0], &(data[len]), 1); - if(ret == 0) break; - if(ret == -1 && (errno == EAGAIN || errno == EINTR)) continue; - - if(data[len] == 0) - break; - - len += ret; - if(len >= sizeof(data)) { - ret = 0; - break; - } - } - - if(ret) - lua_pushstring(L, data); - else - lua_pushnil(L); - - return 1; -} - -static const struct luaL_reg pipe_funcs [] = { - { "signal", l_pipe_signal }, - { "getreadfd", l_pipe_getreadfd }, - { "consume", l_pipe_consume }, - { NULL, NULL } -}; - -LUALIB_API int luaopen_pipe(lua_State *L) -{ - luaL_register(L, LUA_PIPELIBNAME, pipe_funcs); - return 1; -} diff --git a/nopsyncd/l_pipe.h b/nopsyncd/l_pipe.h deleted file mode 100644 index b67244b..0000000 --- a/nopsyncd/l_pipe.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * rhnop - * - * Copyright (C) 2011 Christian Pointner - * - * This file is part of rhnop. - * - * rhnop is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * rhnop is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with rhnop. If not, see . - */ - -#ifndef NOPSYNCD_l_pipe_h_INCLUDED -#define NOPSYNCD_l_pipe_h_INCLUDED - -#include - -int pipe_init(); -void pipe_close(); - -#define LUA_PIPELIBNAME "pipe" -LUALIB_API int luaopen_pipe(lua_State *L); - -#endif diff --git a/nopsyncd/nopsyncd.c b/nopsyncd/nopsyncd.c deleted file mode 100644 index 63bef7f..0000000 --- a/nopsyncd/nopsyncd.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * rhnop - * - * Copyright (C) 2011 Christian Pointner - * - * This file is part of rhnop. - * - * rhnop is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * rhnop is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with rhnop. If not, see . - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "l_pipe.h" - -#define LUA_MAIN_LOOP_FUNC "main_loop" - -static const luaL_Reg nopsyncd_lualibs[] = { - {"", luaopen_base}, - {LUA_LOADLIBNAME, luaopen_package}, - {LUA_TABLIBNAME, luaopen_table}, - {LUA_STRLIBNAME, luaopen_string}, - {LUA_MATHLIBNAME, luaopen_math}, - {LUA_MATHLIBNAME, luaopen_io}, - {LUA_MATHLIBNAME, luaopen_os}, - {LUA_MATHLIBNAME, luaopen_pipe}, - {NULL, NULL} -}; - -int init_main_loop(lua_State *L, const char* filename) -{ - const luaL_Reg *lib = nopsyncd_lualibs; - for (; lib->func; lib++) { - lua_pushcfunction(L, lib->func); - lua_pushstring(L, lib->name); - lua_call(L, 1, 0); - } - - int ret = luaL_loadfile(L, filename); - if(ret) { - const char* err_str = luaL_checkstring(L, -1); - switch(ret) { - case LUA_ERRSYNTAX: fprintf(stderr, "luaL_loadfile() syntax error: %s\n", err_str); break; - case LUA_ERRMEM: fprintf(stderr, "luaL_loadfile() malloc error: %s\n", err_str); break; - case LUA_ERRFILE: fprintf(stderr, "lauL_loadfile() error: %s\n", err_str); break; - default: fprintf(stderr, "luaL_loadfile() unknown error: %s\n", err_str); break; - } - return -1; - } - - ret = lua_pcall(L, 0, 0, 0); - if(ret) { - const char* err_str = luaL_checkstring(L, -1); - switch(ret) { - case LUA_ERRRUN: fprintf(stderr, "lua_pcall() runtime error: %s\n", err_str); break; - case LUA_ERRMEM: fprintf(stderr, "lua_pcall() malloc error: %s\n", err_str); break; - case LUA_ERRERR: fprintf(stderr, "lua_pcall() error at error handler function: %s\n", err_str); break; - } - return -1; - } - - return 0; -} - -int call_main_loop(lua_State* L, const char* filename) -{ - lua_getglobal(L, LUA_MAIN_LOOP_FUNC); - if(!lua_isfunction(L, -1)) { - fprintf(stderr, "there is no function '%s' at file '%s'\n", LUA_MAIN_LOOP_FUNC, filename); - return -1; - }; - - int ret = lua_pcall(L, 0, 1, 0); - if(ret) { - const char* err_str = luaL_checkstring(L, -1); - switch(ret) { - case LUA_ERRRUN: fprintf(stderr, "lua_pcall(%s:%s) runtime error: %s\n", filename, LUA_MAIN_LOOP_FUNC, err_str); break; - case LUA_ERRMEM: fprintf(stderr, "lua_pcall(%s:%s) malloc error: %s\n", filename, LUA_MAIN_LOOP_FUNC, err_str); break; - case LUA_ERRERR: fprintf(stderr, "lua_pcall(%s:%s) error at error handler function: %s\n", filename, LUA_MAIN_LOOP_FUNC, err_str); break; - } - return -1; - } - - ret = lua_tointeger(L, 1); - return ret; -} - -void* main_loop(void* file) -{ - if(!file) - pthread_exit(NULL); - - - lua_State *L; - L = luaL_newstate(); - if(!L) { - fprintf(stderr, "error creating lua state\n"); - pthread_exit(NULL); - } - - int ret = init_main_loop(L, (char*)file); - if(!ret) - ret = call_main_loop(L, (char*)file); - - printf("%s returned with %d\n", (char*)file, ret); - - lua_close(L); - - /* this should bring down the other thread as well - at least this is true for the tcp-server thread */ - pipe_close(); - - pthread_exit(NULL); -} - -int main(int argc, char* argv[]) -{ - printf("starting nopsyncd...\n"); - - pthread_t qlistener, tcpserver; - - int ret = pipe_init(); - if(ret) { - fprintf(stderr, "Error creating pipe: %s\n", strerror(errno)); - return 1; - } - - ret = pthread_create(&qlistener, NULL, main_loop, "qlistener.lua"); - if(ret) { - fprintf(stderr, "Error creating qlistener thread (code: %d)\n", ret); - return 1; - } - pthread_detach(qlistener); /* can't kill this thread so don't join to it */ - - ret = pthread_create(&tcpserver, NULL, main_loop, "tcpserver.lua"); - if(ret) { - fprintf(stderr, "Error creating qlistener thread (code: %d)\n", ret); - return 1; - } - -/* this thread can't be cancelled so don't wait for it */ -/* pthread_join(qlistener, NULL); */ - pthread_join(tcpserver, NULL); - - printf("stopping nopsyncd.\n"); - return 0; -} diff --git a/nopsyncd/nopsyncd.conf b/nopsyncd/nopsyncd.conf deleted file mode 100644 index 0338cb6..0000000 --- a/nopsyncd/nopsyncd.conf +++ /dev/null @@ -1,15 +0,0 @@ -queue_name=/rhnop -tcp_host=* -tcp_port=2345 - -rddb_db=rivendell -rddb_host=127.0.0.1 -#rddb_port=3306 -rddb_user= -rddb_pwd= - -playlog_db=rhnop -playlog_host=127.0.0.1 -#playlog_port=3306 -playlog_user= -playlog_pwd= diff --git a/nopsyncd/playlog.lua b/nopsyncd/playlog.lua deleted file mode 100644 index 37b9ea6..0000000 --- a/nopsyncd/playlog.lua +++ /dev/null @@ -1,90 +0,0 @@ --- --- rhnop --- --- Copyright (C) 2011 Christian Pointner --- --- This file is part of rhnop. --- --- rhnop is free software: you can redistribute it and/or modify --- it under the terms of the GNU General Public License as published by --- the Free Software Foundation, either version 3 of the License, or --- any later version. --- --- rhnop is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU General Public License for more details. --- --- You should have received a copy of the GNU General Public License --- along with rhnop. If not, see . --- - -require "luasql.mysql" - --- CREATE DATABASE rhnop --- GRANT select,insert,update ON rhnop.* TO 'nopsyncd' IDENTIFIED BY '123456'; --- CREATE TABLE IF NOT EXISTS now (timestamp VARCHAR(16) PRIMARY KEY NOT NULL, cart INT NOT NULL, len INT, showtitle VARCHAR(255), title VARCHAR(255), artist VARCHAR(255), album VARCHAR(255), ismusic BOOLEAN) - -conf = require "conf" - -local playlog = {} - -function playlog:init() - local err - - self.env, err = luasql.mysql() - if self.env == nil then - return nil, err - end - - self.con, err = self.env:connect(conf.playlog_db, conf.playlog_user, conf.playlog_pwd, conf.playlog_host, conf.playlog_port) - if self.con == nil then - return nil, err - end - - local ret, err = self.con:setautocommit(true) - if ret == nil then - return nil, err - end - - return true -end - -function playlog:getLastCart() - local cur, err = self.con:execute("SELECT cart FROM now WHERE timestamp = (SELECT MAX(timestamp) FROM now)") - if cur == nil then - return nil, err - end - - local cart = cur:fetch() - if cart == nil then cart = 0 end - return cart -end - -function playlog:insertNowMusic(timestamp, cart, len, title, artist, album) - cart = tonumber(cart) - len = tonumber(len) - if cart < 400000 or cart > 450000 then - poolnum = 0 - else - poolnum = math.floor(cart/1000) - 399 - end - local cur, err = self.con:execute("INSERT into now VALUES(" .. self.con:escape(timestamp) .. ", " .. cart .. ", " .. len .. ", 'Musikpool " .. poolnum .. "', '" .. self.con:escape(title) .. "', '" .. self.con:escape(artist) .."', '" .. self.con:escape(album) .. "', 1)") - if cur == nil then - return nil, err - end - - return true -end - -function playlog:close() - if self.con then - self.con:close() - end - - if self.env then - self.env:close() - end -end - -return playlog diff --git a/nopsyncd/qlistener.lua b/nopsyncd/qlistener.lua deleted file mode 100755 index 8f2c0e2..0000000 --- a/nopsyncd/qlistener.lua +++ /dev/null @@ -1,89 +0,0 @@ --- --- rhnop --- --- Copyright (C) 2011 Christian Pointner --- --- This file is part of rhnop. --- --- rhnop is free software: you can redistribute it and/or modify --- it under the terms of the GNU General Public License as published by --- the Free Software Foundation, either version 3 of the License, or --- any later version. --- --- rhnop is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU General Public License for more details. --- --- You should have received a copy of the GNU General Public License --- along with rhnop. If not, see . --- - -local last_cart = nil - -mq = require "mq" -playlog = require "playlog" -rddb = require "rddb" -conf = require "conf" - -function handle_now(timestamp, nowcart, nowlen) - local results, err = rddb:getCartInfo(nowcart); - if results == nil then - io.stderr:write("can't fetch cart info: " .. err .. "\n") - else --- print(timestamp .. " Info: '" .. results.TITLE .. "' von '" .. results.ARTIST .. "' aus '" .. results.ALBUM .. "'") - local ret, err = playlog:insertNowMusic(timestamp, nowcart, nowlen, results.TITLE, results.ARTIST, results.ALBUM) - if ret == nil then - io.stderr:write("can't insert music info: " .. err .. "\n") - else - pipe.signal(timestamp) - end - end -end - -function handle_message(msg) - local timestamp, nowcart, nowlen, nextcart, nextlen = string.match(msg, "^(%d+) (%d+) (%d+) (%d+) (%d+)$"); - if not timestamp or not nowcart or not nowlen or not nextcart or not nextlen then - io.stderr:write("ignoring malformed message\n") - else - -- TODO better sanity checks: is now info new or just next? - if last_cart ~= nowcart then - last_cart = nowcart - handle_now(timestamp, nowcart, nowlen) - end - -- TODO handle next info - end -end - -function main_loop() - local q, err = mq.create(conf.queue_name, "ro") - if q == nil then - io.stderr:write("creation of message queue failed: " .. err .. "\n") - os.exit(1) - end - - local ret, err = playlog:init() - if ret == nil then - io.stderr:write("creation of playlog failed: " .. err .. "\n") - os.exit(1) - end - last_cart = assert(playlog:getLastCart()) - - local ret, err = rddb:init() - if ret == nil then - io.stderr:write("opening rivendell db failed: " .. err .. "\n") - playlog:close() - os.exit(1) - end - - while true do - local msg, prio = mq.receive(q) - if msg == nil then - io.stderr:write("recv error: " .. prio .. "\n") - rddb:close() - playlog:close() - os.exit(2) - end - handle_message(msg) - end -end \ No newline at end of file diff --git a/nopsyncd/rddb.lua b/nopsyncd/rddb.lua deleted file mode 100644 index c8037a9..0000000 --- a/nopsyncd/rddb.lua +++ /dev/null @@ -1,75 +0,0 @@ --- --- rhnop --- --- Copyright (C) 2011 Christian Pointner --- --- This file is part of rhnop. --- --- rhnop is free software: you can redistribute it and/or modify --- it under the terms of the GNU General Public License as published by --- the Free Software Foundation, either version 3 of the License, or --- any later version. --- --- rhnop is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU General Public License for more details. --- --- You should have received a copy of the GNU General Public License --- along with rhnop. If not, see . --- - -require "luasql.mysql" - -conf = require "conf" - -local rddb = {} - -function rddb:init() - local err - - self.env, err = luasql.mysql() - if self.env == nil then - return nil, err - end - - self.con, err = self.env:connect(conf.rddb_db, conf.rddb_user, conf.rddb_pwd, conf.rddb_host, conf.rddb_port) - if self.con == nil then - return nil, err - end - - return true -end - -function rddb:getCartInfo(cartnum) - local cur, err = self.con:execute("select TITLE,ARTIST,ALBUM from CART where NUMBER = " .. self.con:escape(cartnum)); - if cur == nil then - return nil, err - end - - if cur:numrows() ~= 1 then - return nil, "nothing found in rivendell db" - end - - local results = {} - results, err = cur:fetch(results, "a") - cur:close() - - if results.TITLE == nil then results.TITLE = "" end - if results.ARTIST == nil then results.ARTIST = "" end - if results.ALBUM == nil then results.ALBUM = "" end - - return results, err -end - -function rddb:close() - if self.con then - self.con:close() - end - - if self.env then - self.env:close() - end -end - -return rddb diff --git a/nopsyncd/tcpserver.lua b/nopsyncd/tcpserver.lua deleted file mode 100755 index bd945b6..0000000 --- a/nopsyncd/tcpserver.lua +++ /dev/null @@ -1,128 +0,0 @@ --- --- rhnop --- --- Copyright (C) 2011 Christian Pointner --- --- This file is part of rhnop. --- --- rhnop is free software: you can redistribute it and/or modify --- it under the terms of the GNU General Public License as published by --- the Free Software Foundation, either version 3 of the License, or --- any later version. --- --- rhnop is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU General Public License for more details. --- --- You should have received a copy of the GNU General Public License --- along with rhnop. If not, see . --- - -require "socket" - -conf = require "conf" - -function init_server() - local server = assert(socket.tcp()) - - assert(server:setoption('reuseaddr', true)) - assert(server:bind(conf.tcp_host, conf.tcp_port)) - assert(server:listen(5)) - - return server -end - -local clients = {} - -function add_client(hdl) - -- print("new client(" .. hdl:getfd() .. ") from " .. hdl:getpeername()) - local client = {} - client.buffer = "" - client.hdl = hdl - client.getfd = function() return hdl:getfd() end - client.dirty = function() return hdl:dirty() end - table.insert(clients, client) -end - -function remove_client(c) - local idx = 0 - for idx, client in ipairs(clients) do - if client == c then - break - end - end - - -- print("removing client(" .. c.hdl:getfd() .. ")") - c.hdl:close() - table.remove(clients, idx) -end - -function cleanup_clients() - for _, client in ipairs(clients) do - client:close() - end -end - -function clients_get_writeables() - local fds = {} - - for _, client in ipairs(clients) do - if client.buffer ~= "" then - table.insert(fds, client) - end - end - - return fds -end - -function clients_senddata(timestamp) - for _, client in ipairs(clients) do - client.buffer = client.buffer .. timestamp .. "\n" - end -end - -function main_loop() - local pipefd = pipe.getreadfd() - - server = init_server() - while true do - local readables, writeables, err = socket.select({ pipefd , server , unpack(clients) } , clients_get_writeables()) - if err then - print("select returned with error: " .. err) - return -1 - else - for _, input in ipairs(readables) do - if input == pipefd then - local timestamp = pipe.consume() - if timestamp == nil then - return 2 - end - -- print("pipe was signaled with timestamp: " .. timestamp) - clients_senddata(timestamp) - elseif input == server then - local client = assert(server:accept()) - add_client(client) - else - if input.hdl then - -- receive is insanely stupid, therefore we must always read one byte only - local _, err = input.hdl:receive(1) - if err then - remove_client(input) - end - end - end - end - - for _, output in ipairs(writeables) do - local ret = assert(output.hdl:send(output.buffer)) - output.buffer = string.sub(output.buffer, ret+1) - end - end - end - - server:close() - cleanup_clients() - - return 0 -end diff --git a/rhnop-client/conf.lua b/rhnop-client/conf.lua new file mode 100644 index 0000000..eb1cd29 --- /dev/null +++ b/rhnop-client/conf.lua @@ -0,0 +1,33 @@ +-- +-- rhnop +-- +-- Copyright (C) 2011 Christian Pointner +-- +-- This file is part of rhnop. +-- +-- rhnop is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- any later version. +-- +-- rhnop is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with rhnop. If not, see . +-- + +local conf = {} + +local file = assert(io.open("nopcollect.conf", "r")) +for line in file:lines() do + local k,v = string.match(line, "^([^=#]+)=(.*)$") + if k and v and v ~= "" then + conf[k] = v + end +end +file:close() + +return conf diff --git a/rhnop-client/nopcollect b/rhnop-client/nopcollect new file mode 100755 index 0000000..04560e2 --- /dev/null +++ b/rhnop-client/nopcollect @@ -0,0 +1,54 @@ +#!/usr/bin/lua +-- +-- rhnop +-- +-- Copyright (C) 2011 Christian Pointner +-- +-- This file is part of rhnop. +-- +-- rhnop is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- any later version. +-- +-- rhnop is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with rhnop. If not, see . +-- +-- +-- send now and next cart# and length to nopsyncd +-- this script should be called by the now/next macro cart +-- the arguments should be: now# nowlen next# nextlen +-- + +require "socket" + +conf = require "conf" + +-- connect to server (reconnect after error) +local sock = assert(socket.tcp()) + +local ret, err = sock:connect(conf.host, conf.port) +if ret == nil then + print(err) + return 1 +end + +print "connection established" + +-- TODO: load all info we don't have yet + +while true do + local timestamp = sock:receive('*l') + -- TODO: check if connection is closed + print("received: '" .. timestamp .. "'") + + -- TODO: check if we already fetched that timestamp + -- TODO: fetch info for the timestamp and insert it into local db +end +sock:close() +return 0 diff --git a/rhnop-client/nopcollect.conf b/rhnop-client/nopcollect.conf new file mode 100644 index 0000000..18316fb --- /dev/null +++ b/rhnop-client/nopcollect.conf @@ -0,0 +1,8 @@ +host=127.0.0.1 +port=2345 + +db=nop +#db_host=127.0.0.1 +#db_port=3306 +db_user= +db_pwd= diff --git a/rhnop-server/Makefile b/rhnop-server/Makefile new file mode 100644 index 0000000..a540d77 --- /dev/null +++ b/rhnop-server/Makefile @@ -0,0 +1,91 @@ +## +## rhnop +## +## Copyright (C) 2011 Christian Pointner +## +## This file is part of rhnop. +## +## rhnop is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## any later version. +## +## rhnop is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with rhnop. If not, see . +## + +ifneq ($(MAKECMDGOALS),distclean) +include include.mk +endif + +EXECUTABLE := nopsyncd + +C_OBJS := l_pipe.o \ + nopsyncd.o + +C_SRCS := $(C_OBJS:%.o=%.c) + +.PHONY: clean distclean install install-bin install-etc uninstall remove purge + +all: $(EXECUTABLE) + +%.d: %.c + @set -e; rm -f $@; \ + $(CC) -MM $(CFLAGS) $< > $@.$$$$; \ + sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ + rm -f $@.$$$$; echo '(re)building $@' + +ifneq ($(MAKECMDGOALS),distclean) +-include $(C_SRCS:%.c=%.d) +endif + +$(EXECUTABLE): $(C_OBJS) + $(CC) $(C_OBJS) -o $@ $(LDFLAGS) + +%.o: %.c + $(CC) $(CFLAGS) -c $< + +strip: $(EXECUTABLE) + $(STRIP) -s $(EXECUTABLE) + + +distclean: clean + find . -name *.o -exec rm -f {} \; + find . -name "*.\~*" -exec rm -rf {} \; + rm -f include.mk + +clean: + rm -f *.o + rm -f *.d + rm -f *.d.* + rm -f $(EXECUTABLE) + +INSTALL_TARGETS := install-bin install-etc +REMOVE_TARGETS := remove-bin remove-etc + +install: all $(INSTALL_TARGETS) + +install-bin: $(EXECUTABLE) + $(INSTALL) -d $(DESTDIR)$(BINDIR) + $(INSTALL) -m 755 $(EXECUTABLE) $(DESTDIR)$(BINDIR) + +install-etc: + $(INSTALL) -d $(DESTDIR)$(ETCDIR)/$(EXECUTABLE) + +uninstall: remove + +remove: $(REMOVE_TARGETS) + +remove-bin: + rm -f $(DESTDIR)$(BINDIR)/$(EXECUTABLE) + +remove-etc: + rm -f $(DESTDIR)$(ETCDIR)/init.d/$(EXECUTABLE) + +purge: remove + rm -rf $(DESTDIR)$(ETCDIR)/$(EXECUTABLE)/ diff --git a/rhnop-server/conf.lua b/rhnop-server/conf.lua new file mode 100644 index 0000000..83257b5 --- /dev/null +++ b/rhnop-server/conf.lua @@ -0,0 +1,33 @@ +-- +-- rhnop +-- +-- Copyright (C) 2011 Christian Pointner +-- +-- This file is part of rhnop. +-- +-- rhnop is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- any later version. +-- +-- rhnop is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with rhnop. If not, see . +-- + +local conf = {} + +local file = assert(io.open("nopsyncd.conf", "r")) +for line in file:lines() do + local k,v = string.match(line, "^([^=#]+)=(.*)$") + if k and v and v ~= "" then + conf[k] = v + end +end +file:close() + +return conf diff --git a/rhnop-server/configure b/rhnop-server/configure new file mode 100755 index 0000000..30145f2 --- /dev/null +++ b/rhnop-server/configure @@ -0,0 +1,190 @@ +#!/bin/sh +# +# rhnop +# +# Copyright (C) 2011 Christian Pointner +# +# This file is part of rhnop. +# +# rhnop is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# any later version. +# +# rhnop is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with rhnop. If not, see . +# + +TARGET=`uname -s` +EBUILD_COMPAT=0 + +CFLAGS='-g -O2' +LDFLAGS='-g -Wall -O2 -lpthread' + +LUA_DIR='' +LUA='' + +PREFIX='/usr/local' +BINDIR='' +ETCDIR='' + +print_usage() { + echo "configure --help print this" + echo " --target= build target i.e. Linux (default: autodetect)" + echo " --prefix= the installation prefix (default: /usr/local)" + echo " --bindir= the path to the bin directory (default: $PREFIX/bin)" + echo " --sysconfdir= the path to the system configuration directory (default: $PREFIX/etc)" + echo " --with-lua= use this lua tree instead of system default" +} + +for arg +do + case $arg in + --target=*) + TARGET=${arg#--target=} + ;; + --prefix=*) + PREFIX=${arg#--prefix=} + ;; + --bindir=*) + BINDIR=${arg#--bindir=} + ;; + --sysconfdir=*) + ETCDIR=${arg#--sysconfdir=} + ;; + --with-lua=*) + LUA_DIR=${arg#--with-lua=} + ;; + --ebuild-compat) + EBUILD_COMPAT=1 + ;; + --help) + print_usage + exit 0 + ;; + *) + ERRORS="$ERRORS $arg" + ;; + esac +done + +if [ -n "$ERRORS" ] && [ $EBUILD_COMPAT -ne 1 ]; then + for error in $ERRORS; do + echo "Unknown argument: $error" + done + + print_usage + exit 1 +fi + +rm -f include.mk +case $TARGET in + Linux) + LDFLAGS=$LDFLAGS' -ldl' + ;; + *) + echo "platform not supported" + exit 1; + ;; +esac + + +test_lua_version() +{ + LUA_VERSION=`cat $1 | grep "#define LUA_VERSION[ ]" | cut -f2- | tr -d '"' | sed -e 's/Lua \([0-9][0-9.]*\)/\1/'` + LUA_VERSION_NUM=`cat $1 | grep "#define LUA_VERSION_NUM" | awk '{ print $3 }'` + LUA_RELEASE=`cat $1 | grep "#define LUA_RELEASE[ ]" | cut -f2-` + + if [ $LUA_VERSION_NUM -ge 501 ]; then + return 1; + else + return 0; + fi +} + +if [ -z "$LUA_DIR" ]; then + for prefix in /usr /usr/local; do + if [ -e $prefix/include/lua.h ]; then + test_lua_version $prefix/include/lua.h + if [ $? -eq 1 ]; then + echo "using Lua $LUA_VERSION ($LUA_RELEASE) found at $prefix/include" + CFLAGS="$CFLAGS -I'$prefix/include'" + LDFLAGS="$LDFLAGS -L'$prefix/lib' -llua" + LUA=$prefix/lua + LUAC=$prefix/luac + break + fi + else + for dir in `ls -d $prefix/include/lua* 2> /dev/null`; do + if [ -e $dir/lua.h ]; then + test_lua_version $dir/lua.h + if [ $? -eq 1 ]; then + echo "using Lua $LUA_VERSION ($LUA_RELEASE) found at $dir" + CFLAGS="$CFLAGS -I$dir" + if [ -x "$prefix/bin/lua$LUA_VERSION" ]; then + LDFLAGS="$LDFLAGS -L'$prefix/lib' -llua$LUA_VERSION" + LUA=$prefix/bin/lua$LUA_VERSION + LUAC=$prefix/bin/luac$LUA_VERSION + elif [ -x "$prefix/bin/lua-$LUA_VERSION" ]; then + LDFLAGS="$LDFLAGS -L'$prefix/lib' -llua-$LUA_VERSION" + LUA=$prefix/bin/lua-$LUA_VERSION + LUAC=$prefix/bin/luac-$LUA_VERSION + else + echo "ERROR: found lua.h at $dir/lua.h but no matching lua and luac" + return 1 + fi + break + fi + fi + done + if [ -n "$LUAC" ]; then + break + fi + fi + done + + if [ -z "$LUAC" ]; then + echo "ERROR: no suitable lua found .. please install lua 5.1 or higher or use --with-lua" + return 1 + fi + +else + CFLAGS="$CFLAGS -I'$LUA_DIR/include'" + LDFLAGS="$LDFLAGS '$LUA_DIR/lib/liblua.a'" + LUA=$LUA_DIR/bin/lua + LUAC=$LUA_DIR/bin/luac +fi + +if [ -z "$BINDIR" ]; then + BINDIR=$PREFIX/bin +fi + +if [ -z "$ETCDIR" ]; then + ETCDIR=$PREFIX/etc +fi + +cat > include.mk < + * + * This file is part of rhnop. + * + * rhnop is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * rhnop is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with rhnop. If not, see . + */ + +#include +#include + +#include +#include +#include + +#include "l_pipe.h" + +static int pipefds_[2]; + +int pipe_init() +{ + return pipe(pipefds_); +} + +void pipe_close() +{ + close(pipefds_[0]); + close(pipefds_[1]); +} + +static int l_pipe_signal(lua_State *L) +{ + size_t len = 0, written = 0; + const char* data = luaL_checklstring(L, 1, &len); + len++; // also send trailing zero + + int ret = 0; + for(;;) { + ret = write(pipefds_[1], &(data[written]), len - written); + if(!ret) continue; + if(ret == -1 && (errno == EAGAIN || errno == EINTR)) continue; + + written += ret; + if(written == len) break; + + break; + } + + lua_pushinteger(L, ret); + return 1; +} + +static int l_pipe_getfd(lua_State *L) +{ + if(!lua_istable(L, -1)) + luaL_error(L, "can't retreive pipe fd"); + + lua_pushliteral(L, "fd"); + lua_gettable(L, -2); + return 1; +} + +static int l_pipe_dirty(lua_State *L) +{ + lua_pushboolean(L, 0); + return 1; +} + +static int l_pipe_getreadfd(lua_State *L) +{ + lua_newtable(L); + lua_pushliteral(L, "fd"); + lua_pushinteger(L, pipefds_[0]); + lua_settable(L, -3); + lua_pushliteral(L, "getfd"); + lua_pushcfunction(L, l_pipe_getfd); + lua_settable(L, -3); + lua_pushliteral(L, "dirty"); + lua_pushcfunction(L, l_pipe_dirty); + lua_settable(L, -3); + return 1; +} + +static int l_pipe_consume(lua_State *L) +{ + char data[17]; // 17 should be sufficient + size_t len = 0; + + int ret = 0; + for(;;) { + ret = read(pipefds_[0], &(data[len]), 1); + if(ret == 0) break; + if(ret == -1 && (errno == EAGAIN || errno == EINTR)) continue; + + if(data[len] == 0) + break; + + len += ret; + if(len >= sizeof(data)) { + ret = 0; + break; + } + } + + if(ret) + lua_pushstring(L, data); + else + lua_pushnil(L); + + return 1; +} + +static const struct luaL_reg pipe_funcs [] = { + { "signal", l_pipe_signal }, + { "getreadfd", l_pipe_getreadfd }, + { "consume", l_pipe_consume }, + { NULL, NULL } +}; + +LUALIB_API int luaopen_pipe(lua_State *L) +{ + luaL_register(L, LUA_PIPELIBNAME, pipe_funcs); + return 1; +} diff --git a/rhnop-server/l_pipe.h b/rhnop-server/l_pipe.h new file mode 100644 index 0000000..b67244b --- /dev/null +++ b/rhnop-server/l_pipe.h @@ -0,0 +1,33 @@ +/* + * rhnop + * + * Copyright (C) 2011 Christian Pointner + * + * This file is part of rhnop. + * + * rhnop is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * rhnop is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with rhnop. If not, see . + */ + +#ifndef NOPSYNCD_l_pipe_h_INCLUDED +#define NOPSYNCD_l_pipe_h_INCLUDED + +#include + +int pipe_init(); +void pipe_close(); + +#define LUA_PIPELIBNAME "pipe" +LUALIB_API int luaopen_pipe(lua_State *L); + +#endif diff --git a/rhnop-server/noprml b/rhnop-server/noprml new file mode 100755 index 0000000..31e8ab7 --- /dev/null +++ b/rhnop-server/noprml @@ -0,0 +1,59 @@ +#!/usr/bin/lua +-- +-- rhnop +-- +-- Copyright (C) 2011 Christian Pointner +-- +-- This file is part of rhnop. +-- +-- rhnop is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- any later version. +-- +-- rhnop is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with rhnop. If not, see . +-- +-- +-- send now and next cart# and length to nopsyncd +-- this script should be called by the now/next macro cart +-- the arguments should be: now# nowlen next# nextlen +-- + +local queue_name = "/rhnop" + +mq = require "mq" + +-- reading timestamp (milliseconds since epoch) +local p = assert(io.popen("/bin/date --utc '+%s %N'" , 'r')) +local time = assert(p:read('*l')) +p:close() +local s, ns = assert(string.match(time, "([0-9]+) ([0-9]+)")) +local timestamp = s*1000 + math.floor(ns/1000000) + +-- check arguments +if #arg < 4 then + io.stderr:write("too few parameters\n") + os.exit(1) +end + +-- open message queue +local q, err = mq.create(queue_name, "wo") +if q == nil then + io.stderr:write("creation of message queue failed: " .. err .. "\n") + os.exit(1) +end + +-- send out message to nopsyncd +local result, err = mq.send(q, timestamp .. " " .. arg[1] .. " " .. arg[2] .. " " .. arg[3] .. " " .. arg[4], 0) +if result == nil then + io.stderr:write("sending message failed: " .. err .. "\n") + os.exit(2) +end + +mq.close(q) diff --git a/rhnop-server/nopsyncd.c b/rhnop-server/nopsyncd.c new file mode 100644 index 0000000..63bef7f --- /dev/null +++ b/rhnop-server/nopsyncd.c @@ -0,0 +1,165 @@ +/* + * rhnop + * + * Copyright (C) 2011 Christian Pointner + * + * This file is part of rhnop. + * + * rhnop is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * rhnop is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with rhnop. If not, see . + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "l_pipe.h" + +#define LUA_MAIN_LOOP_FUNC "main_loop" + +static const luaL_Reg nopsyncd_lualibs[] = { + {"", luaopen_base}, + {LUA_LOADLIBNAME, luaopen_package}, + {LUA_TABLIBNAME, luaopen_table}, + {LUA_STRLIBNAME, luaopen_string}, + {LUA_MATHLIBNAME, luaopen_math}, + {LUA_MATHLIBNAME, luaopen_io}, + {LUA_MATHLIBNAME, luaopen_os}, + {LUA_MATHLIBNAME, luaopen_pipe}, + {NULL, NULL} +}; + +int init_main_loop(lua_State *L, const char* filename) +{ + const luaL_Reg *lib = nopsyncd_lualibs; + for (; lib->func; lib++) { + lua_pushcfunction(L, lib->func); + lua_pushstring(L, lib->name); + lua_call(L, 1, 0); + } + + int ret = luaL_loadfile(L, filename); + if(ret) { + const char* err_str = luaL_checkstring(L, -1); + switch(ret) { + case LUA_ERRSYNTAX: fprintf(stderr, "luaL_loadfile() syntax error: %s\n", err_str); break; + case LUA_ERRMEM: fprintf(stderr, "luaL_loadfile() malloc error: %s\n", err_str); break; + case LUA_ERRFILE: fprintf(stderr, "lauL_loadfile() error: %s\n", err_str); break; + default: fprintf(stderr, "luaL_loadfile() unknown error: %s\n", err_str); break; + } + return -1; + } + + ret = lua_pcall(L, 0, 0, 0); + if(ret) { + const char* err_str = luaL_checkstring(L, -1); + switch(ret) { + case LUA_ERRRUN: fprintf(stderr, "lua_pcall() runtime error: %s\n", err_str); break; + case LUA_ERRMEM: fprintf(stderr, "lua_pcall() malloc error: %s\n", err_str); break; + case LUA_ERRERR: fprintf(stderr, "lua_pcall() error at error handler function: %s\n", err_str); break; + } + return -1; + } + + return 0; +} + +int call_main_loop(lua_State* L, const char* filename) +{ + lua_getglobal(L, LUA_MAIN_LOOP_FUNC); + if(!lua_isfunction(L, -1)) { + fprintf(stderr, "there is no function '%s' at file '%s'\n", LUA_MAIN_LOOP_FUNC, filename); + return -1; + }; + + int ret = lua_pcall(L, 0, 1, 0); + if(ret) { + const char* err_str = luaL_checkstring(L, -1); + switch(ret) { + case LUA_ERRRUN: fprintf(stderr, "lua_pcall(%s:%s) runtime error: %s\n", filename, LUA_MAIN_LOOP_FUNC, err_str); break; + case LUA_ERRMEM: fprintf(stderr, "lua_pcall(%s:%s) malloc error: %s\n", filename, LUA_MAIN_LOOP_FUNC, err_str); break; + case LUA_ERRERR: fprintf(stderr, "lua_pcall(%s:%s) error at error handler function: %s\n", filename, LUA_MAIN_LOOP_FUNC, err_str); break; + } + return -1; + } + + ret = lua_tointeger(L, 1); + return ret; +} + +void* main_loop(void* file) +{ + if(!file) + pthread_exit(NULL); + + + lua_State *L; + L = luaL_newstate(); + if(!L) { + fprintf(stderr, "error creating lua state\n"); + pthread_exit(NULL); + } + + int ret = init_main_loop(L, (char*)file); + if(!ret) + ret = call_main_loop(L, (char*)file); + + printf("%s returned with %d\n", (char*)file, ret); + + lua_close(L); + + /* this should bring down the other thread as well + at least this is true for the tcp-server thread */ + pipe_close(); + + pthread_exit(NULL); +} + +int main(int argc, char* argv[]) +{ + printf("starting nopsyncd...\n"); + + pthread_t qlistener, tcpserver; + + int ret = pipe_init(); + if(ret) { + fprintf(stderr, "Error creating pipe: %s\n", strerror(errno)); + return 1; + } + + ret = pthread_create(&qlistener, NULL, main_loop, "qlistener.lua"); + if(ret) { + fprintf(stderr, "Error creating qlistener thread (code: %d)\n", ret); + return 1; + } + pthread_detach(qlistener); /* can't kill this thread so don't join to it */ + + ret = pthread_create(&tcpserver, NULL, main_loop, "tcpserver.lua"); + if(ret) { + fprintf(stderr, "Error creating qlistener thread (code: %d)\n", ret); + return 1; + } + +/* this thread can't be cancelled so don't wait for it */ +/* pthread_join(qlistener, NULL); */ + pthread_join(tcpserver, NULL); + + printf("stopping nopsyncd.\n"); + return 0; +} diff --git a/rhnop-server/nopsyncd.conf b/rhnop-server/nopsyncd.conf new file mode 100644 index 0000000..0338cb6 --- /dev/null +++ b/rhnop-server/nopsyncd.conf @@ -0,0 +1,15 @@ +queue_name=/rhnop +tcp_host=* +tcp_port=2345 + +rddb_db=rivendell +rddb_host=127.0.0.1 +#rddb_port=3306 +rddb_user= +rddb_pwd= + +playlog_db=rhnop +playlog_host=127.0.0.1 +#playlog_port=3306 +playlog_user= +playlog_pwd= diff --git a/rhnop-server/playlog.lua b/rhnop-server/playlog.lua new file mode 100644 index 0000000..37b9ea6 --- /dev/null +++ b/rhnop-server/playlog.lua @@ -0,0 +1,90 @@ +-- +-- rhnop +-- +-- Copyright (C) 2011 Christian Pointner +-- +-- This file is part of rhnop. +-- +-- rhnop is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- any later version. +-- +-- rhnop is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with rhnop. If not, see . +-- + +require "luasql.mysql" + +-- CREATE DATABASE rhnop +-- GRANT select,insert,update ON rhnop.* TO 'nopsyncd' IDENTIFIED BY '123456'; +-- CREATE TABLE IF NOT EXISTS now (timestamp VARCHAR(16) PRIMARY KEY NOT NULL, cart INT NOT NULL, len INT, showtitle VARCHAR(255), title VARCHAR(255), artist VARCHAR(255), album VARCHAR(255), ismusic BOOLEAN) + +conf = require "conf" + +local playlog = {} + +function playlog:init() + local err + + self.env, err = luasql.mysql() + if self.env == nil then + return nil, err + end + + self.con, err = self.env:connect(conf.playlog_db, conf.playlog_user, conf.playlog_pwd, conf.playlog_host, conf.playlog_port) + if self.con == nil then + return nil, err + end + + local ret, err = self.con:setautocommit(true) + if ret == nil then + return nil, err + end + + return true +end + +function playlog:getLastCart() + local cur, err = self.con:execute("SELECT cart FROM now WHERE timestamp = (SELECT MAX(timestamp) FROM now)") + if cur == nil then + return nil, err + end + + local cart = cur:fetch() + if cart == nil then cart = 0 end + return cart +end + +function playlog:insertNowMusic(timestamp, cart, len, title, artist, album) + cart = tonumber(cart) + len = tonumber(len) + if cart < 400000 or cart > 450000 then + poolnum = 0 + else + poolnum = math.floor(cart/1000) - 399 + end + local cur, err = self.con:execute("INSERT into now VALUES(" .. self.con:escape(timestamp) .. ", " .. cart .. ", " .. len .. ", 'Musikpool " .. poolnum .. "', '" .. self.con:escape(title) .. "', '" .. self.con:escape(artist) .."', '" .. self.con:escape(album) .. "', 1)") + if cur == nil then + return nil, err + end + + return true +end + +function playlog:close() + if self.con then + self.con:close() + end + + if self.env then + self.env:close() + end +end + +return playlog diff --git a/rhnop-server/qlistener.lua b/rhnop-server/qlistener.lua new file mode 100755 index 0000000..8f2c0e2 --- /dev/null +++ b/rhnop-server/qlistener.lua @@ -0,0 +1,89 @@ +-- +-- rhnop +-- +-- Copyright (C) 2011 Christian Pointner +-- +-- This file is part of rhnop. +-- +-- rhnop is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- any later version. +-- +-- rhnop is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with rhnop. If not, see . +-- + +local last_cart = nil + +mq = require "mq" +playlog = require "playlog" +rddb = require "rddb" +conf = require "conf" + +function handle_now(timestamp, nowcart, nowlen) + local results, err = rddb:getCartInfo(nowcart); + if results == nil then + io.stderr:write("can't fetch cart info: " .. err .. "\n") + else +-- print(timestamp .. " Info: '" .. results.TITLE .. "' von '" .. results.ARTIST .. "' aus '" .. results.ALBUM .. "'") + local ret, err = playlog:insertNowMusic(timestamp, nowcart, nowlen, results.TITLE, results.ARTIST, results.ALBUM) + if ret == nil then + io.stderr:write("can't insert music info: " .. err .. "\n") + else + pipe.signal(timestamp) + end + end +end + +function handle_message(msg) + local timestamp, nowcart, nowlen, nextcart, nextlen = string.match(msg, "^(%d+) (%d+) (%d+) (%d+) (%d+)$"); + if not timestamp or not nowcart or not nowlen or not nextcart or not nextlen then + io.stderr:write("ignoring malformed message\n") + else + -- TODO better sanity checks: is now info new or just next? + if last_cart ~= nowcart then + last_cart = nowcart + handle_now(timestamp, nowcart, nowlen) + end + -- TODO handle next info + end +end + +function main_loop() + local q, err = mq.create(conf.queue_name, "ro") + if q == nil then + io.stderr:write("creation of message queue failed: " .. err .. "\n") + os.exit(1) + end + + local ret, err = playlog:init() + if ret == nil then + io.stderr:write("creation of playlog failed: " .. err .. "\n") + os.exit(1) + end + last_cart = assert(playlog:getLastCart()) + + local ret, err = rddb:init() + if ret == nil then + io.stderr:write("opening rivendell db failed: " .. err .. "\n") + playlog:close() + os.exit(1) + end + + while true do + local msg, prio = mq.receive(q) + if msg == nil then + io.stderr:write("recv error: " .. prio .. "\n") + rddb:close() + playlog:close() + os.exit(2) + end + handle_message(msg) + end +end \ No newline at end of file diff --git a/rhnop-server/rddb.lua b/rhnop-server/rddb.lua new file mode 100644 index 0000000..c8037a9 --- /dev/null +++ b/rhnop-server/rddb.lua @@ -0,0 +1,75 @@ +-- +-- rhnop +-- +-- Copyright (C) 2011 Christian Pointner +-- +-- This file is part of rhnop. +-- +-- rhnop is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- any later version. +-- +-- rhnop is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with rhnop. If not, see . +-- + +require "luasql.mysql" + +conf = require "conf" + +local rddb = {} + +function rddb:init() + local err + + self.env, err = luasql.mysql() + if self.env == nil then + return nil, err + end + + self.con, err = self.env:connect(conf.rddb_db, conf.rddb_user, conf.rddb_pwd, conf.rddb_host, conf.rddb_port) + if self.con == nil then + return nil, err + end + + return true +end + +function rddb:getCartInfo(cartnum) + local cur, err = self.con:execute("select TITLE,ARTIST,ALBUM from CART where NUMBER = " .. self.con:escape(cartnum)); + if cur == nil then + return nil, err + end + + if cur:numrows() ~= 1 then + return nil, "nothing found in rivendell db" + end + + local results = {} + results, err = cur:fetch(results, "a") + cur:close() + + if results.TITLE == nil then results.TITLE = "" end + if results.ARTIST == nil then results.ARTIST = "" end + if results.ALBUM == nil then results.ALBUM = "" end + + return results, err +end + +function rddb:close() + if self.con then + self.con:close() + end + + if self.env then + self.env:close() + end +end + +return rddb diff --git a/rhnop-server/tcpserver.lua b/rhnop-server/tcpserver.lua new file mode 100755 index 0000000..bd945b6 --- /dev/null +++ b/rhnop-server/tcpserver.lua @@ -0,0 +1,128 @@ +-- +-- rhnop +-- +-- Copyright (C) 2011 Christian Pointner +-- +-- This file is part of rhnop. +-- +-- rhnop is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- any later version. +-- +-- rhnop is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with rhnop. If not, see . +-- + +require "socket" + +conf = require "conf" + +function init_server() + local server = assert(socket.tcp()) + + assert(server:setoption('reuseaddr', true)) + assert(server:bind(conf.tcp_host, conf.tcp_port)) + assert(server:listen(5)) + + return server +end + +local clients = {} + +function add_client(hdl) + -- print("new client(" .. hdl:getfd() .. ") from " .. hdl:getpeername()) + local client = {} + client.buffer = "" + client.hdl = hdl + client.getfd = function() return hdl:getfd() end + client.dirty = function() return hdl:dirty() end + table.insert(clients, client) +end + +function remove_client(c) + local idx = 0 + for idx, client in ipairs(clients) do + if client == c then + break + end + end + + -- print("removing client(" .. c.hdl:getfd() .. ")") + c.hdl:close() + table.remove(clients, idx) +end + +function cleanup_clients() + for _, client in ipairs(clients) do + client:close() + end +end + +function clients_get_writeables() + local fds = {} + + for _, client in ipairs(clients) do + if client.buffer ~= "" then + table.insert(fds, client) + end + end + + return fds +end + +function clients_senddata(timestamp) + for _, client in ipairs(clients) do + client.buffer = client.buffer .. timestamp .. "\n" + end +end + +function main_loop() + local pipefd = pipe.getreadfd() + + server = init_server() + while true do + local readables, writeables, err = socket.select({ pipefd , server , unpack(clients) } , clients_get_writeables()) + if err then + print("select returned with error: " .. err) + return -1 + else + for _, input in ipairs(readables) do + if input == pipefd then + local timestamp = pipe.consume() + if timestamp == nil then + return 2 + end + -- print("pipe was signaled with timestamp: " .. timestamp) + clients_senddata(timestamp) + elseif input == server then + local client = assert(server:accept()) + add_client(client) + else + if input.hdl then + -- receive is insanely stupid, therefore we must always read one byte only + local _, err = input.hdl:receive(1) + if err then + remove_client(input) + end + end + end + end + + for _, output in ipairs(writeables) do + local ret = assert(output.hdl:send(output.buffer)) + output.buffer = string.sub(output.buffer, ret+1) + end + end + end + + server:close() + cleanup_clients() + + return 0 +end -- cgit v0.10.2