diff options
Diffstat (limited to 'libs')
26 files changed, 0 insertions, 3721 deletions
diff --git a/libs/fastindex/Makefile b/libs/fastindex/Makefile deleted file mode 100644 index ee1a40ea8..000000000 --- a/libs/fastindex/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -include ../../build/module.mk -include ../../build/config.mk -include ../../build/gccconfig.mk - -%.o: %.c - $(COMPILE) $(LUA_CFLAGS) $(FPIC) -c -o $@ $< - -compile: src/fastindex.o - mkdir -p dist$(LUCI_LIBRARYDIR) - $(LINK) $(SHLIB_FLAGS) -o dist$(LUCI_LIBRARYDIR)/fastindex.so src/fastindex.o $(LUA_SHLIBS) - -clean: - rm -f src/*.o diff --git a/libs/fastindex/src/fastindex.c b/libs/fastindex/src/fastindex.c deleted file mode 100644 index c9c64bf75..000000000 --- a/libs/fastindex/src/fastindex.c +++ /dev/null @@ -1,379 +0,0 @@ -/* - * fastindex - fast lua module indexing plugin - * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation - * - * This program 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. - */ - -#include <sys/types.h> -#include <sys/time.h> -#include <sys/cdefs.h> - -#ifndef _POSIX_C_SOURCE -#define _POSIX_C_SOURCE /* XXX: portability hack for timestamp */ -#endif - -#include <sys/stat.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <stdio.h> -#include <errno.h> -#include <glob.h> - -#include <lualib.h> -#include <lauxlib.h> -#include "list.h" - -#define MODNAME "luci.fastindex" -#define DEFAULT_BUFLEN 1024 - -//#define DEBUG 1 - -#ifdef DEBUG -#define DPRINTF(...) fprintf(stderr, __VA_ARGS__) -#else -#define DPRINTF(...) do {} while (0) -#endif - -/** - * list_for_each_offset - iterate over a list, start with the provided pointer - * @pos: the &struct list_head to use as a loop cursor. - * @head: the head for your list. - */ -#define list_for_each_offset(pos, head, offset) \ - for (pos = (offset)->next; pos != (offset); \ - pos = ((pos->next == (head)) && ((offset) != (head)) ? (head)->next : pos->next)) - -static char *namespace = NULL; - -struct fastindex_entry { - struct list_head list; - time_t timestamp; - int checked; - char *name; -}; - -struct fastindex_pattern { - struct list_head list; - char pattern[]; -}; - -struct fastindex { - lua_State *L; - int checked; - char *func; - struct list_head patterns; - struct list_head *last; - struct list_head entries; - int ofs; - char *buf; - int buflen; -}; - -static inline struct fastindex * -to_fastindex(struct lua_State *L) -{ - struct fastindex *f; - lua_getfield(L, lua_upvalueindex(1), "__data"); - f = lua_touserdata(L, -1); - lua_pop(L, 1); - return f; -} - -static int -fastindex_module(lua_State *L) -{ - const char *s; - s = luaL_checkstring(L, 1); - - if (s) { - if (namespace) - free(namespace); - namespace = strdup(s); - } - - return 0; -} - -static struct fastindex_entry * -find_entry(struct fastindex *f, char *name) -{ - struct list_head *p; - - if (!f->last) - f->last = &f->entries; - - list_for_each_offset(p, &f->entries, f->last) { - struct fastindex_entry *e; - e = container_of(p, struct fastindex_entry, list); - if (!strcmp(e->name, name)) - return e; - } - return NULL; -} - -static struct fastindex_entry * -new_entry(struct fastindex *f, char *name) -{ - struct fastindex_entry *e; - - e = malloc(sizeof(struct fastindex_entry)); - if (!e) - goto error; - - memset(e, 0, sizeof(struct fastindex_entry)); - e->name = strdup(name); - if (!e->name) { - free(e); - goto error; - } - INIT_LIST_HEAD(&e->list); - - return e; - -error: - return NULL; -} - -static void free_entry(struct fastindex_entry *e) -{ - list_del(&e->list); - free(e->name); - free(e); -} - -int bufferwriter(lua_State *L, const void *p, size_t sz, void *ud) -{ - struct fastindex *f = ud; - - while (f->ofs + sz > f->buflen) { - char *b = f->buf; - f->buflen *= 2; - f->buf = realloc(f->buf, f->buflen); - if (!f->buf) { - free(b); - return 1; - } - } - memcpy(f->buf + f->ofs, p, sz); - f->ofs += sz; - return 0; -} - -static void -load_index(struct fastindex *f, struct fastindex_entry *e) -{ - lua_State *L; - - DPRINTF("Loading module: %s\n", e->name); - - if (!f->buf) - f->buf = malloc(f->buflen); - - if (!f->buf) - luaL_error(f->L, "Out of memory!\n"); - - f->ofs = 0; - L = luaL_newstate(); - if (!L) - return; - - namespace = NULL; - luaL_openlibs(L); - lua_pushcfunction(L, fastindex_module); - lua_setfield(L, LUA_GLOBALSINDEX, "module"); - - do { - if (luaL_dofile(L, e->name)) { - DPRINTF("Warning: unable to open module '%s'\n", e->name); - break; - } - - lua_getglobal(L, f->func); - lua_dump(L, bufferwriter, f); - DPRINTF("Got %d bytes\n", f->ofs); - if (f->ofs == 0) - break; - lua_createtable(f->L, (namespace ? 2 : 1), 0); - luaL_loadbuffer(f->L, f->buf, f->ofs, "tmp"); - lua_rawseti(f->L, -2, 1); - if (namespace) { - DPRINTF("Module has namespace '%s'\n", namespace); - lua_pushstring(f->L, namespace); - lua_rawseti(f->L, -2, 2); - free(namespace); - namespace = NULL; - } - lua_setfield(f->L, -2, e->name); - } while (0); - - lua_close(L); -} - - -static int -fastindex_scan(lua_State *L) -{ - struct list_head *tmp, *p; - struct fastindex *f; - glob_t gl; - int i; - int gl_flags = GLOB_NOESCAPE | GLOB_NOSORT | GLOB_MARK; - - f = to_fastindex(L); - f->checked++; - - - if (list_empty(&f->patterns)) - return 0; - - lua_getfield(L, lua_upvalueindex(1), "indexes"); - list_for_each(p, &f->patterns) { - struct fastindex_pattern *pt = container_of(p, struct fastindex_pattern, list); - glob(pt->pattern, gl_flags, NULL, &gl); - gl_flags |= GLOB_APPEND; - } - for (i = 0; i < gl.gl_pathc; i++) { - struct fastindex_entry *e; - struct stat st; - - if (stat(gl.gl_pathv[i], &st)) - continue; - - if ((st.st_mode & S_IFMT) != S_IFREG) - continue; - - e = find_entry(f, gl.gl_pathv[i]); - if (!e) { - e = new_entry(f, gl.gl_pathv[i]); - list_add_tail(&e->list, &f->entries); - } - - e->checked = f->checked; - if ((e->timestamp < st.st_mtime)) { - load_index(f, e); - e->timestamp = st.st_mtime; - } - } - globfree(&gl); - list_for_each_safe(p, tmp, &f->entries) { - struct fastindex_entry *e = container_of(p, struct fastindex_entry, list); - if (e->checked < f->checked) { - lua_pushnil(f->L); - lua_setfield(f->L, -2, e->name); - free_entry(e); - } - } - lua_pop(L, 1); - - return 0; -} - -static int -fastindex_free(lua_State *L) -{ - struct fastindex *f; - struct list_head *p, *tmp; - - f = lua_touserdata(L, -1); - list_for_each_safe(p, tmp, &f->patterns) { - struct fastindex_pattern *pt; - pt = container_of(p, struct fastindex_pattern, list); - list_del(p); - free(pt); - } - list_for_each_safe(p, tmp, &f->entries) { - struct fastindex_entry *e; - e = container_of(p, struct fastindex_entry, list); - free_entry(e); - } - return 0; -} - -static int -fastindex_add(lua_State *L) -{ - struct fastindex_pattern *pt; - struct fastindex *f; - const char *str; - - f = to_fastindex(L); - str = luaL_checkstring(L, 1); - if (!str) - luaL_error(L, "Invalid argument"); - - pt = malloc(sizeof(struct fastindex_pattern) + strlen(str) + 1); - if (!pt) - luaL_error(L, "Out of memory"); - - INIT_LIST_HEAD(&pt->list); - strcpy(pt->pattern, str); - list_add(&pt->list, &f->patterns); - - return 0; -} - -static const luaL_Reg fastindex_m[] = { - { "add", fastindex_add }, - { "scan", fastindex_scan }, - { NULL, NULL } -}; - -static int -fastindex_new(lua_State *L) -{ - struct fastindex *f; - const char *func; - - func = luaL_checkstring(L, 1); - - f = lua_newuserdata(L, sizeof(struct fastindex)); - lua_createtable(L, 0, 2); - lua_pushvalue(L, -1); - lua_setfield(L, -2, "__index"); - lua_pushcfunction(L, fastindex_free); - lua_setfield(L, -2, "__gc"); - lua_pushvalue(L, -1); - lua_setmetatable(L, -3); - lua_pushvalue(L, -2); - lua_setfield(L, -2, "__data"); - lua_createtable(L, 0, 1); - lua_setfield(L, -2, "indexes"); - lua_pushvalue(L, -2); - luaI_openlib(L, NULL, fastindex_m, 1); - - memset(f, 0, sizeof(struct fastindex)); - f->L = L; - f->buflen = DEFAULT_BUFLEN; - INIT_LIST_HEAD(&f->entries); - INIT_LIST_HEAD(&f->patterns); - - f->func = strdup(func); - if (!f->func) { - if (f->func) - free(f->func); - luaL_error(L, "Out of memory\n"); - } - - return 1; -} - -static const luaL_Reg fastindex[] = { - { "new", fastindex_new }, - { NULL, NULL }, -}; - -int -luaopen_luci_fastindex(lua_State *L) -{ - luaL_register(L, MODNAME, fastindex); - return 0; -} diff --git a/libs/fastindex/src/list.h b/libs/fastindex/src/list.h deleted file mode 100644 index 2959a061d..000000000 --- a/libs/fastindex/src/list.h +++ /dev/null @@ -1,601 +0,0 @@ -#ifndef _LINUX_LIST_H -#define _LINUX_LIST_H - -#include <stddef.h> -/** - * container_of - cast a member of a structure out to the containing structure - * @ptr: the pointer to the member. - * @type: the type of the container struct this is embedded in. - * @member: the name of the member within the struct. - * - */ -#ifndef container_of -#define container_of(ptr, type, member) ( \ - (type *)( (char *)ptr - offsetof(type,member) )) -#endif - - -/* - * Simple doubly linked list implementation. - * - * Some of the internal functions ("__xxx") are useful when - * manipulating whole lists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. - */ - -struct list_head { - struct list_head *next, *prev; -}; - -#define LIST_HEAD_INIT(name) { &(name), &(name) } - -#define LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) - -static inline void INIT_LIST_HEAD(struct list_head *list) -{ - list->next = list; - list->prev = list; -} - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_add(struct list_head *new, - struct list_head *prev, - struct list_head *next) -{ - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -/** - * list_add - add a new entry - * @new: new entry to be added - * @head: list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - */ -static inline void list_add(struct list_head *new, struct list_head *head) -{ - __list_add(new, head, head->next); -} - - -/** - * list_add_tail - add a new entry - * @new: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -static inline void list_add_tail(struct list_head *new, struct list_head *head) -{ - __list_add(new, head->prev, head); -} - - -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_del(struct list_head * prev, struct list_head * next) -{ - next->prev = prev; - prev->next = next; -} - -/** - * list_del - deletes entry from list. - * @entry: the element to delete from the list. - * Note: list_empty() on entry does not return true after this, the entry is - * in an undefined state. - */ -static inline void list_del(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - entry->next = NULL; - entry->prev = NULL; -} - -/** - * list_replace - replace old entry by new one - * @old : the element to be replaced - * @new : the new element to insert - * - * If @old was empty, it will be overwritten. - */ -static inline void list_replace(struct list_head *old, - struct list_head *new) -{ - new->next = old->next; - new->next->prev = new; - new->prev = old->prev; - new->prev->next = new; -} - -static inline void list_replace_init(struct list_head *old, - struct list_head *new) -{ - list_replace(old, new); - INIT_LIST_HEAD(old); -} - -/** - * list_del_init - deletes entry from list and reinitialize it. - * @entry: the element to delete from the list. - */ -static inline void list_del_init(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - INIT_LIST_HEAD(entry); -} - -/** - * list_move - delete from one list and add as another's head - * @list: the entry to move - * @head: the head that will precede our entry - */ -static inline void list_move(struct list_head *list, struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add(list, head); -} - -/** - * list_move_tail - delete from one list and add as another's tail - * @list: the entry to move - * @head: the head that will follow our entry - */ -static inline void list_move_tail(struct list_head *list, - struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add_tail(list, head); -} - -/** - * list_is_last - tests whether @list is the last entry in list @head - * @list: the entry to test - * @head: the head of the list - */ -static inline int list_is_last(const struct list_head *list, - const struct list_head *head) -{ - return list->next == head; -} - -/** - * list_empty - tests whether a list is empty - * @head: the list to test. - */ -static inline int list_empty(const struct list_head *head) -{ - return head->next == head; -} - -/** - * list_empty_careful - tests whether a list is empty and not being modified - * @head: the list to test - * - * Description: - * tests whether a list is empty _and_ checks that no other CPU might be - * in the process of modifying either member (next or prev) - * - * NOTE: using list_empty_careful() without synchronization - * can only be safe if the only activity that can happen - * to the list entry is list_del_init(). Eg. it cannot be used - * if another CPU could re-list_add() it. - */ -static inline int list_empty_careful(const struct list_head *head) -{ - struct list_head *next = head->next; - return (next == head) && (next == head->prev); -} - -static inline void __list_splice(struct list_head *list, - struct list_head *head) -{ - struct list_head *first = list->next; - struct list_head *last = list->prev; - struct list_head *at = head->next; - - first->prev = head; - head->next = first; - - last->next = at; - at->prev = last; -} - -/** - * list_splice - join two lists - * @list: the new list to add. - * @head: the place to add it in the first list. - */ -static inline void list_splice(struct list_head *list, struct list_head *head) -{ - if (!list_empty(list)) - __list_splice(list, head); -} - -/** - * list_splice_init - join two lists and reinitialise the emptied list. - * @list: the new list to add. - * @head: the place to add it in the first list. - * - * The list at @list is reinitialised - */ -static inline void list_splice_init(struct list_head *list, - struct list_head *head) -{ - if (!list_empty(list)) { - __list_splice(list, head); - INIT_LIST_HEAD(list); - } -} - -/** - * list_entry - get the struct for this entry - * @ptr: the &struct list_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - */ -#define list_entry(ptr, type, member) \ - container_of(ptr, type, member) - -/** - * list_first_entry - get the first element from a list - * @ptr: the list head to take the element from. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - * - * Note, that list is expected to be not empty. - */ -#define list_first_entry(ptr, type, member) \ - list_entry((ptr)->next, type, member) - -/** - * list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop cursor. - * @head: the head for your list. - */ -#define list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); \ - pos = pos->next) - -/** - * __list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop cursor. - * @head: the head for your list. - * - * This variant differs from list_for_each() in that it's the - * simplest possible list iteration code, no prefetching is done. - * Use this for code that knows the list to be very short (empty - * or 1 entry) most of the time. - */ -#define __list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); pos = pos->next) - -/** - * list_for_each_prev - iterate over a list backwards - * @pos: the &struct list_head to use as a loop cursor. - * @head: the head for your list. - */ -#define list_for_each_prev(pos, head) \ - for (pos = (head)->prev; pos != (head); \ - pos = pos->prev) - -/** - * list_for_each_safe - iterate over a list safe against removal of list entry - * @pos: the &struct list_head to use as a loop cursor. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. - */ -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) - -/** - * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry - * @pos: the &struct list_head to use as a loop cursor. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. - */ -#define list_for_each_prev_safe(pos, n, head) \ - for (pos = (head)->prev, n = pos->prev; \ - pos != (head); \ - pos = n, n = pos->prev) - -/** - * list_for_each_entry - iterate over list of given type - * @pos: the type * to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry(pos, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member)) - -/** - * list_for_each_entry_reverse - iterate backwards over list of given type. - * @pos: the type * to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_reverse(pos, head, member) \ - for (pos = list_entry((head)->prev, typeof(*pos), member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.prev, typeof(*pos), member)) - -/** - * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue() - * @pos: the type * to use as a start point - * @head: the head of the list - * @member: the name of the list_struct within the struct. - * - * Prepares a pos entry for use as a start point in list_for_each_entry_continue(). - */ -#define list_prepare_entry(pos, head, member) \ - ((pos) ? : list_entry(head, typeof(*pos), member)) - -/** - * list_for_each_entry_continue - continue iteration over list of given type - * @pos: the type * to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - * - * Continue to iterate over list of given type, continuing after - * the current position. - */ -#define list_for_each_entry_continue(pos, head, member) \ - for (pos = list_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member)) - -/** - * list_for_each_entry_continue_reverse - iterate backwards from the given point - * @pos: the type * to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - * - * Start to iterate over list of given type backwards, continuing after - * the current position. - */ -#define list_for_each_entry_continue_reverse(pos, head, member) \ - for (pos = list_entry(pos->member.prev, typeof(*pos), member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.prev, typeof(*pos), member)) - -/** - * list_for_each_entry_from - iterate over list of given type from the current point - * @pos: the type * to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - * - * Iterate over list of given type, continuing from current position. - */ -#define list_for_each_entry_from(pos, head, member) \ - for (; &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member)) - -/** - * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry - * @pos: the type * to use as a loop cursor. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_safe(pos, n, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member), \ - n = list_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, typeof(*n), member)) - -/** - * list_for_each_entry_safe_continue - * @pos: the type * to use as a loop cursor. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - * - * Iterate over list of given type, continuing after current point, - * safe against removal of list entry. - */ -#define list_for_each_entry_safe_continue(pos, n, head, member) \ - for (pos = list_entry(pos->member.next, typeof(*pos), member), \ - n = list_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, typeof(*n), member)) - -/** - * list_for_each_entry_safe_from - * @pos: the type * to use as a loop cursor. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - * - * Iterate over list of given type from current point, safe against - * removal of list entry. - */ -#define list_for_each_entry_safe_from(pos, n, head, member) \ - for (n = list_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, typeof(*n), member)) - -/** - * list_for_each_entry_safe_reverse - * @pos: the type * to use as a loop cursor. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - * - * Iterate backwards over list of given type, safe against removal - * of list entry. - */ -#define list_for_each_entry_safe_reverse(pos, n, head, member) \ - for (pos = list_entry((head)->prev, typeof(*pos), member), \ - n = list_entry(pos->member.prev, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.prev, typeof(*n), member)) - -/* - * Double linked lists with a single pointer list head. - * Mostly useful for hash tables where the two pointer list head is - * too wasteful. - * You lose the ability to access the tail in O(1). - */ - -struct hlist_head { - struct hlist_node *first; -}; - -struct hlist_node { - struct hlist_node *next, **pprev; -}; - -#define HLIST_HEAD_INIT { .first = NULL } -#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } -#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) -static inline void INIT_HLIST_NODE(struct hlist_node *h) -{ - h->next = NULL; - h->pprev = NULL; -} - -static inline int hlist_unhashed(const struct hlist_node *h) -{ - return !h->pprev; -} - -static inline int hlist_empty(const struct hlist_head *h) -{ - return !h->first; -} - -static inline void __hlist_del(struct hlist_node *n) -{ - struct hlist_node *next = n->next; - struct hlist_node **pprev = n->pprev; - *pprev = next; - if (next) - next->pprev = pprev; -} - -static inline void hlist_del(struct hlist_node *n) -{ - __hlist_del(n); - n->next = NULL; - n->pprev = NULL; -} - -static inline void hlist_del_init(struct hlist_node *n) -{ - if (!hlist_unhashed(n)) { - __hlist_del(n); - INIT_HLIST_NODE(n); - } -} - - -static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) -{ - struct hlist_node *first = h->first; - n->next = first; - if (first) - first->pprev = &n->next; - h->first = n; - n->pprev = &h->first; -} - - -/* next must be != NULL */ -static inline void hlist_add_before(struct hlist_node *n, - struct hlist_node *next) -{ - n->pprev = next->pprev; - n->next = next; - next->pprev = &n->next; - *(n->pprev) = n; -} - -static inline void hlist_add_after(struct hlist_node *n, - struct hlist_node *next) -{ - next->next = n->next; - n->next = next; - next->pprev = &n->next; - - if(next->next) - next->next->pprev = &next->next; -} - -#define hlist_entry(ptr, type, member) container_of(ptr,type,member) - -#define hlist_for_each(pos, head) \ - for (pos = (head)->first; pos; pos = pos->next) - -#define hlist_for_each_safe(pos, n, head) \ - for (pos = (head)->first; pos; pos = n) - -/** - * hlist_for_each_entry - iterate over list of given type - * @tpos: the type * to use as a loop cursor. - * @pos: the &struct hlist_node to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry(tpos, pos, head, member) \ - for (pos = (head)->first; pos && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = pos->next) - -/** - * hlist_for_each_entry_continue - iterate over a hlist continuing after current point - * @tpos: the type * to use as a loop cursor. - * @pos: the &struct hlist_node to use as a loop cursor. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry_continue(tpos, pos, member) \ - for (pos = (pos)->next; pos && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = pos->next) - -/** - * hlist_for_each_entry_from - iterate over a hlist continuing from current point - * @tpos: the type * to use as a loop cursor. - * @pos: the &struct hlist_node to use as a loop cursor. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry_from(tpos, pos, member) \ - for (; pos && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = pos->next) - -/** - * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry - * @tpos: the type * to use as a loop cursor. - * @pos: the &struct hlist_node to use as a loop cursor. - * @n: another &struct hlist_node to use as temporary storage - * @head: the head for your list. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ - for (pos = (head)->first; \ - pos && ({ n = pos->next; 1; }) && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = n) - -#endif diff --git a/libs/lucid-http/Makefile b/libs/lucid-http/Makefile deleted file mode 100644 index 2bdfad16e..000000000 --- a/libs/lucid-http/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -include ../../build/module.mk -include ../../build/config.mk
\ No newline at end of file diff --git a/libs/lucid-http/docs/OVERVIEW b/libs/lucid-http/docs/OVERVIEW deleted file mode 100644 index 74b499ca9..000000000 --- a/libs/lucid-http/docs/OVERVIEW +++ /dev/null @@ -1,17 +0,0 @@ - LuCId HTTP/1.1 Server Slave - -*** Abstract *** -The LuCId HTTP-Server Slave is an HTTP/1.1 implementation for the LuCId -superserver loosely based on the LuCI HTTP stack. It supports keep-alive, -pipelining, basic authentication, kernel-mode file transfer (sendfile() -through nixio), address and hostname based virtual hosts, custom 404 pages, -E-Tags, conditional headers, directory indexing and partial file transfers. - - -*** Workflow *** -After receiving an incoming connection from LuCId, the slave parses the request -and prepares the environment for the acion handler. After that the virtual host -will be dispatched and the request will be passed on to the respective handler. -The handler will enforce access restrictions if configured and then returns a -status code a set of response headers, as well as a content resource that will -be sent to the user.
\ No newline at end of file diff --git a/libs/lucid-http/luasrc/lucid/http.lua b/libs/lucid-http/luasrc/lucid/http.lua deleted file mode 100644 index 931967c56..000000000 --- a/libs/lucid-http/luasrc/lucid/http.lua +++ /dev/null @@ -1,36 +0,0 @@ ---[[ -LuCI - Lua Configuration Interface - -Copyright 2009 Steven Barth <steven@midlink.org> - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ -]]-- - -local require, ipairs, pcall = require, ipairs, pcall -local srv = require "luci.lucid.http.server" - -module "luci.lucid.http" - ---- Prepare the HTTP-daemon and its associated publishers. --- @param publisher Table of publishers --- @return factory callback or nil, error message -function factory(publisher) - local server = srv.Server() - for _, r in ipairs(publisher) do - local t = r[".type"] - local s, mod = pcall(require, "luci.lucid.http." .. (r[".type"] or "")) - if s and mod then - mod.factory(server, r) - else - return nil, mod - end - end - - return function(...) return server:process(...) end -end
\ No newline at end of file diff --git a/libs/lucid-http/luasrc/lucid/http/DirectoryPublisher.lua b/libs/lucid-http/luasrc/lucid/http/DirectoryPublisher.lua deleted file mode 100644 index 09cade49e..000000000 --- a/libs/lucid-http/luasrc/lucid/http/DirectoryPublisher.lua +++ /dev/null @@ -1,50 +0,0 @@ ---[[ -LuCId HTTP-Slave -(c) 2009 Steven Barth <steven@midlink.org> - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ -]]-- - -local ipairs, require, tostring, type = ipairs, require, tostring, type -local file = require "luci.lucid.http.handler.file" -local srv = require "luci.lucid.http.server" - -module "luci.lucid.http.DirectoryPublisher" - - ---- Prepare a directory publisher and assign it to a given Virtual Host. --- @param server HTTP daemon object --- @param config publisher configuration -function factory(server, config) - config.domain = config.domain or "" - local vhost = server:get_vhosts()[config.domain] - if not vhost then - vhost = srv.VHost() - server:set_vhost(config.domain, vhost) - end - - local handler = file.Simple(config.name, config.physical, config) - if config.read then - for _, r in ipairs(config.read) do - if r:sub(1,1) == ":" then - handler:restrict({interface = r:sub(2)}) - else - handler:restrict({user = r}) - end - end - end - - if type(config.virtual) == "table" then - for _, v in ipairs(config.virtual) do - vhost:set_handler(v, handler) - end - else - vhost:set_handler(config.virtual or "", handler) - end -end diff --git a/libs/lucid-http/luasrc/lucid/http/LuciWebPublisher.lua b/libs/lucid-http/luasrc/lucid/http/LuciWebPublisher.lua deleted file mode 100644 index 5dc70df84..000000000 --- a/libs/lucid-http/luasrc/lucid/http/LuciWebPublisher.lua +++ /dev/null @@ -1,73 +0,0 @@ ---[[ -LuCId HTTP-Slave -(c) 2009 Steven Barth <steven@midlink.org> - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ -]]-- - -local ipairs, pcall, type = ipairs, pcall, type -local luci = require "luci.lucid.http.handler.luci" -local srv = require "luci.lucid.http.server" - - -module "luci.lucid.http.LuciWebPublisher" - - ---- Prepare a LuCI web publisher and assign it to a given Virtual Host. --- @param server HTTP daemon object --- @param config publisher configuration -function factory(server, config) - pcall(function() - require "luci.dispatcher" - require "luci.cbi" - end) - - config.domain = config.domain or "" - local vhost = server:get_vhosts()[config.domain] - if not vhost then - vhost = srv.VHost() - server:set_vhost(config.domain, vhost) - end - - local prefix - if config.physical and #config.physical > 0 then - prefix = {} - for k in config.physical:gmatch("[^/]+") do - if #k > 0 then - prefix[#prefix+1] = k - end - end - end - - local handler = luci.Luci(config.name, prefix) - if config.exec then - for _, r in ipairs(config.exec) do - if r:sub(1,1) == ":" then - handler:restrict({interface = r:sub(2)}) - else - handler:restrict({user = r}) - end - end - end - - local mypath - if type(config.virtual) == "table" then - for _, v in ipairs(config.virtual) do - mypath = mypath or v - vhost:set_handler(v, handler) - end - else - mypath = config.virtual - vhost:set_handler(config.virtual or "", handler) - end - - if config.home then - vhost.default = mypath - end -end diff --git a/libs/lucid-http/luasrc/lucid/http/Redirector.lua b/libs/lucid-http/luasrc/lucid/http/Redirector.lua deleted file mode 100644 index 66a86a7ff..000000000 --- a/libs/lucid-http/luasrc/lucid/http/Redirector.lua +++ /dev/null @@ -1,33 +0,0 @@ ---[[ -LuCId HTTP-Slave -(c) 2009 Steven Barth <steven@midlink.org> - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ -]]-- - -local ipairs = ipairs -local catchall = require "luci.lucid.http.handler.catchall" -local srv = require "luci.lucid.http.server" - -module "luci.lucid.http.Redirector" - ---- Prepare a redirector publisher and assign it to a given Virtual Host. --- @param server HTTP daemon object --- @param config publisher configuration -function factory(server, config) - config.domain = config.domain or "" - local vhost = server:get_vhosts()[config.domain] - if not vhost then - vhost = srv.VHost() - server:set_vhost(config.domain, vhost) - end - - local handler = catchall.Redirect(config.name, config.physical) - vhost:set_handler(config.virtual or "", handler) -end diff --git a/libs/lucid-http/luasrc/lucid/http/handler/catchall.lua b/libs/lucid-http/luasrc/lucid/http/handler/catchall.lua deleted file mode 100644 index 13272d91e..000000000 --- a/libs/lucid-http/luasrc/lucid/http/handler/catchall.lua +++ /dev/null @@ -1,87 +0,0 @@ ---[[ -LuCId HTTP-Slave -(c) 2009 Steven Barth <steven@midlink.org> - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ -]]-- - -local srv = require "luci.lucid.http.server" -local proto = require "luci.http.protocol" -local util = require "luci.util" -local ip = require "luci.ip" -local ipairs = ipairs - ---- Catchall Handler --- @cstyle instance -module "luci.lucid.http.handler.catchall" - ---- Create a Redirect handler. --- @param name Name --- @param target Redirect Target --- @class function --- @return Redirect handler object -Redirect = util.class(srv.Handler) - -function Redirect.__init__(self, name, target) - srv.Handler.__init__(self, name) - self.target = target -end - ---- Handle a GET request. --- @param request Request object --- @return status code, header table, response source -function Redirect.handle_GET(self, request) - local target = self.target - local protocol = request.env.HTTPS and "https://" or "http://" - local server = request.env.SERVER_ADDR - - if request.env.REMOTE_ADDR and not request.env.REMOTE_ADDR:find(":") then - local compare = ip.IPv4(request.env.REMOTE_ADDR) - for _, iface in ipairs(request.server.interfaces) do - if iface.family == "inet" and iface.addr and iface.netmask then - if ip.IPv4(iface.addr, iface.netmask):contains(compare) then - server = iface.addr - break - end - end - end - end - - if server:find(":") then - server = "[" .. server .. "]" - end - - if self.target:sub(1,1) == ":" then - target = protocol .. server .. target - end - - local s, e = target:find("%TARGET%", 1, true) - if s then - local req = protocol .. (request.env.HTTP_HOST or server) - .. request.env.REQUEST_URI - target = target:sub(1, s-1) .. req .. target:sub(e+1) - end - - return 302, { Location = target } -end - ---- Handle a POST request. --- @class function --- @param request Request object --- @return status code, header table, response source -Redirect.handle_POST = Redirect.handle_GET - ---- Handle a HEAD request. --- @class function --- @param request Request object --- @return status code, header table, response source -function Redirect.handle_HEAD(self, request) - local stat, head = self:handle_GET(request) - return stat, head -end diff --git a/libs/lucid-http/luasrc/lucid/http/handler/file.lua b/libs/lucid-http/luasrc/lucid/http/handler/file.lua deleted file mode 100644 index 4f29c8bd2..000000000 --- a/libs/lucid-http/luasrc/lucid/http/handler/file.lua +++ /dev/null @@ -1,272 +0,0 @@ ---[[ - -HTTP server implementation for LuCI - file handler -(c) 2008 Steven Barth <steven@midlink.org> -(c) 2008 Freifunk Leipzig / Jo-Philipp Wich <xm@leipzig.freifunk.net> - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ - -]]-- - -local ipairs, type, tonumber = ipairs, type, tonumber -local os = require "os" -local nixio = require "nixio", require "nixio.util" -local fs = require "nixio.fs" -local util = require "luci.util" -local ltn12 = require "luci.ltn12" -local srv = require "luci.lucid.http.server" -local string = require "string" - -local prot = require "luci.http.protocol" -local date = require "luci.http.protocol.date" -local mime = require "luci.http.protocol.mime" -local cond = require "luci.http.protocol.conditionals" - ---- File system handler --- @cstyle instance -module "luci.lucid.http.handler.file" - ---- Create a simple file system handler. --- @class function --- @param name Name --- @param docroot Physical Document Root --- @param options Options --- @return Simple file system handler object -Simple = util.class(srv.Handler) - -function Simple.__init__(self, name, docroot, options) - srv.Handler.__init__(self, name) - self.docroot = docroot - self.realdocroot = fs.realpath(self.docroot) - - options = options or {} - self.dirlist = not options.noindex - self.error404 = options.error404 -end - ---- Parse a range request. --- @param request Request object --- @param size File size --- @return offset, length, range header or boolean status -function Simple.parse_range(self, request, size) - if not request.headers.Range then - return true - end - - local from, to = request.headers.Range:match("bytes=([0-9]*)-([0-9]*)") - if not (from or to) then - return true - end - - from, to = tonumber(from), tonumber(to) - if not (from or to) then - return true - elseif not from then - from, to = size - to, size - 1 - elseif not to then - to = size - 1 - end - - -- Not satisfiable - if from >= size then - return false - end - - -- Normalize - if to >= size then - to = size - 1 - end - - local range = "bytes " .. from .. "-" .. to .. "/" .. size - return from, (1 + to - from), range -end - ---- Translate path and return file information. --- @param uri Request URI --- @return physical file path, file information -function Simple.getfile(self, uri) - if not self.realdocroot then - self.realdocroot = fs.realpath(self.docroot) - end - local file = fs.realpath(self.docroot .. uri) - if not file or file:sub(1, #self.realdocroot) ~= self.realdocroot then - return uri - end - return file, fs.stat(file) -end - ---- Handle a GET request. --- @param request Request object --- @return status code, header table, response source -function Simple.handle_GET(self, request) - local file, stat = self:getfile(prot.urldecode(request.env.PATH_INFO, true)) - - if stat then - if stat.type == "reg" then - - -- Generate Entity Tag - local etag = cond.mk_etag( stat ) - - -- Check conditionals - local ok, code, hdrs - - ok, code, hdrs = cond.if_modified_since( request, stat ) - if ok then - ok, code, hdrs = cond.if_match( request, stat ) - if ok then - ok, code, hdrs = cond.if_unmodified_since( request, stat ) - if ok then - ok, code, hdrs = cond.if_none_match( request, stat ) - if ok then - local f, err = nixio.open(file) - - if f then - local code = 200 - local o, s, r = self:parse_range(request, stat.size) - - if not o then - return self:failure(416, "Invalid Range") - end - - local headers = { - ["Cache-Control"] = "max-age=29030400", - ["Last-Modified"] = date.to_http( stat.mtime ), - ["Content-Type"] = mime.to_mime( file ), - ["ETag"] = etag, - ["Accept-Ranges"] = "bytes", - } - - if o == true then - s = stat.size - else - code = 206 - headers["Content-Range"] = r - f:seek(o) - end - - headers["Content-Length"] = s - - -- Send Response - return code, headers, srv.IOResource(f, s) - else - return self:failure( 403, err:gsub("^.+: ", "") ) - end - else - return code, hdrs - end - else - return code, hdrs - end - else - return code, hdrs - end - else - return code, hdrs - end - - elseif stat.type == "dir" then - - local ruri = request.env.REQUEST_URI:gsub("/$", "") - local duri = prot.urldecode( ruri, true ) - local root = self.docroot - - -- check for index files - local index_candidates = { - "index.html", "index.htm", "default.html", "default.htm", - "index.txt", "default.txt" - } - - -- try to find an index file and redirect to it - for i, candidate in ipairs( index_candidates ) do - local istat = fs.stat( - root .. "/" .. duri .. "/" .. candidate - ) - - if istat ~= nil and istat.type == "reg" then - return 302, { Location = ruri .. "/" .. candidate } - end - end - - - local html = string.format( - '<?xml version="1.0" encoding="utf-8"?>\n' .. - '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" ' .. - '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n'.. - '<html xmlns="http://www.w3.org/1999/xhtml" ' .. - 'xml:lang="en" lang="en">\n' .. - '<head>\n' .. - '<title>Index of %s/</title>\n' .. - '<style type="text/css">\n' .. - 'body { color:#000000 } ' .. - 'li { border-bottom:1px dotted #CCCCCC; padding:3px } ' .. - 'small { font-size:60%%; color:#333333 } ' .. - 'p { margin:0 }' .. - '\n</style></head><body><h1>Index of %s/</h1><hr /><ul>'.. - '<li><p><a href="%s/../">../</a> ' .. - '<small>(parent directory)</small><br />' .. - '<small></small></li>', - duri, duri, ruri - ) - - local entries = fs.dir( file ) - - if type(entries) == "function" then - for i, e in util.vspairs(nixio.util.consume(entries)) do - local estat = fs.stat( file .. "/" .. e ) - - if estat.type == "dir" then - html = html .. string.format( - '<li><p><a href="%s/%s/">%s/</a> ' .. - '<small>(directory)</small><br />' .. - '<small>Changed: %s</small></li>', - ruri, prot.urlencode( e ), e, - date.to_http( estat.mtime ) - ) - else - html = html .. string.format( - '<li><p><a href="%s/%s">%s</a> ' .. - '<small>(%s)</small><br />' .. - '<small>Size: %i Bytes | ' .. - 'Changed: %s</small></li>', - ruri, prot.urlencode( e ), e, - mime.to_mime( e ), - estat.size, date.to_http( estat.mtime ) - ) - end - end - - html = html .. '</ul><hr /><address>LuCId-HTTPd' .. - '</address></body></html>' - - return 200, { - ["Date"] = date.to_http( os.time() ); - ["Content-Type"] = "text/html; charset=utf-8"; - }, ltn12.source.string(html) - else - return self:failure(403, "Permission denied") - end - else - return self:failure(403, "Unable to transmit " .. stat.type .. " " .. file) - end - else - if self.error404 then - return 302, { Location = self.error404 } - else - return self:failure(404, "No such file: " .. file) - end - end -end - ---- Handle a HEAD request. --- @param request Request object --- @return status code, header table, response source -function Simple.handle_HEAD(self, ...) - local stat, head = self:handle_GET(...) - return stat, head -end diff --git a/libs/lucid-http/luasrc/lucid/http/handler/luci.lua b/libs/lucid-http/luasrc/lucid/http/handler/luci.lua deleted file mode 100644 index b6d92deec..000000000 --- a/libs/lucid-http/luasrc/lucid/http/handler/luci.lua +++ /dev/null @@ -1,113 +0,0 @@ ---[[ -LuCId HTTP-Slave -(c) 2009 Steven Barth <steven@midlink.org> - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ -]]-- - -local dsp = require "luci.dispatcher" -local util = require "luci.util" -local http = require "luci.http" -local ltn12 = require "luci.ltn12" -local srv = require "luci.lucid.http.server" -local coroutine = require "coroutine" -local type = type - ---- LuCI web handler --- @cstyle instance -module "luci.lucid.http.handler.luci" - ---- Create a LuCI web handler. --- @class function --- @param name Name --- @param prefix Dispatching prefix --- @return LuCI web handler object -Luci = util.class(srv.Handler) - -function Luci.__init__(self, name, prefix) - srv.Handler.__init__(self, name) - self.prefix = prefix - dsp.indexcache = "/tmp/luci-indexcache" -end - ---- Handle a HEAD request. --- @param request Request object --- @return status code, header table, response source -function Luci.handle_HEAD(self, ...) - local stat, head = self:handle_GET(...) - return stat, head -end - ---- Handle a POST request. --- @param request Request object --- @return status code, header table, response source -function Luci.handle_POST(self, ...) - return self:handle_GET(...) -end - ---- Handle a GET request. --- @param request Request object --- @return status code, header table, response source -function Luci.handle_GET(self, request, sourcein) - local r = http.Request( - request.env, - sourcein - ) - - local res, id, data1, data2 = true, 0, nil, nil - local headers = {} - local status = 200 - local active = true - - local x = coroutine.create(dsp.httpdispatch) - while not id or id < 3 do - res, id, data1, data2 = coroutine.resume(x, r, self.prefix) - - if not res then - status = 500 - headers["Content-Type"] = "text/plain" - return status, headers, ltn12.source.string(id) - end - - if id == 1 then - status = data1 - elseif id == 2 then - if not headers[data1] then - headers[data1] = data2 - elseif type(headers[data1]) ~= "table" then - headers[data1] = {headers[data1], data2} - else - headers[data1][#headers[data1]+1] = data2 - end - end - end - - if id == 6 then - while (coroutine.resume(x)) do end - return status, headers, srv.IOResource(data1, data2) - end - - local function iter() - local res, id, data = coroutine.resume(x) - if not res then - return nil, id - elseif not id or not active then - return true - elseif id == 5 then - active = false - while (coroutine.resume(x)) do end - return nil - elseif id == 4 then - return data - end - end - - return status, headers, iter -end - diff --git a/libs/lucid-http/luasrc/lucid/http/server.lua b/libs/lucid-http/luasrc/lucid/http/server.lua deleted file mode 100644 index fd5f7cdd8..000000000 --- a/libs/lucid-http/luasrc/lucid/http/server.lua +++ /dev/null @@ -1,600 +0,0 @@ ---[[ -LuCId HTTP-Slave -(c) 2009 Steven Barth <steven@midlink.org> - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ -]]-- - -local ipairs, pairs = ipairs, pairs -local tostring, tonumber = tostring, tonumber -local pcall, assert, type = pcall, assert, type -local set_memory_limit = set_memory_limit - -local os = require "os" -local nixio = require "nixio" -local util = require "luci.util" -local ltn12 = require "luci.ltn12" -local proto = require "luci.http.protocol" -local table = require "table" -local date = require "luci.http.protocol.date" - ---- HTTP Daemon --- @cstyle instance -module "luci.lucid.http.server" - -VERSION = "1.0" - -statusmsg = { - [200] = "OK", - [206] = "Partial Content", - [301] = "Moved Permanently", - [302] = "Found", - [304] = "Not Modified", - [400] = "Bad Request", - [401] = "Unauthorized", - [403] = "Forbidden", - [404] = "Not Found", - [405] = "Method Not Allowed", - [408] = "Request Time-out", - [411] = "Length Required", - [412] = "Precondition Failed", - [416] = "Requested range not satisfiable", - [500] = "Internal Server Error", - [503] = "Server Unavailable", -} - ---- Create a new IO resource response. --- @class function --- @param fd File descriptor --- @param len Length of data --- @return IO resource -IOResource = util.class() - -function IOResource.__init__(self, fd, len) - self.fd, self.len = fd, len -end - - ---- Create a server handler. --- @class function --- @param name Name --- @return Handler -Handler = util.class() - -function Handler.__init__(self, name) - self.name = name or tostring(self) -end - ---- Create a failure reply. --- @param code HTTP status code --- @param msg Status message --- @return status code, header table, response source -function Handler.failure(self, code, msg) - return code, { ["Content-Type"] = "text/plain" }, ltn12.source.string(msg) -end - ---- Add an access restriction. --- @param restriction Restriction specification -function Handler.restrict(self, restriction) - if not self.restrictions then - self.restrictions = {restriction} - else - self.restrictions[#self.restrictions+1] = restriction - end -end - ---- Enforce access restrictions. --- @param request Request object --- @return nil or HTTP statuscode, table of headers, response source -function Handler.checkrestricted(self, request) - if not self.restrictions then - return - end - - local localif, user, pass - - for _, r in ipairs(self.restrictions) do - local stat = true - if stat and r.interface then -- Interface restriction - if not localif then - for _, v in ipairs(request.server.interfaces) do - if v.addr == request.env.SERVER_ADDR then - localif = v.name - break - end - end - end - - if r.interface ~= localif then - stat = false - end - end - - if stat and r.user then -- User restriction - local rh, pwe - if not user then - rh = (request.headers.Authorization or ""):match("Basic (.*)") - rh = rh and nixio.bin.b64decode(rh) or "" - user, pass = rh:match("(.*):(.*)") - pass = pass or "" - end - pwe = nixio.getsp and nixio.getsp(r.user) or nixio.getpw(r.user) - local pwh = (user == r.user) and pwe and (pwe.pwdp or pwe.passwd) - if not pwh or #pwh < 1 or nixio.crypt(pass, pwh) ~= pwh then - stat = false - end - end - - if stat then - request.env.HTTP_AUTH_USER, request.env.HTTP_AUTH_PASS = user, pass - return - end - end - - return 401, { - ["WWW-Authenticate"] = ('Basic realm=%q'):format(self.name), - ["Content-Type"] = 'text/plain' - }, ltn12.source.string("Unauthorized") -end - ---- Process a request. --- @param request Request object --- @param sourcein Request data source --- @return HTTP statuscode, table of headers, response source -function Handler.process(self, request, sourcein) - local stat, code, hdr, sourceout - - local stat, code, msg = self:checkrestricted(request) - if stat then -- Access Denied - return stat, code, msg - end - - -- Detect request Method - local hname = "handle_" .. request.env.REQUEST_METHOD - if self[hname] then - -- Run the handler - stat, code, hdr, sourceout = pcall(self[hname], self, request, sourcein) - - -- Check for any errors - if not stat then - return self:failure(500, code) - end - else - return self:failure(405, statusmsg[405]) - end - - return code, hdr, sourceout -end - - ---- Create a Virtual Host. --- @class function --- @return Virtual Host -VHost = util.class() - -function VHost.__init__(self) - self.handlers = {} -end - ---- Process a request and invoke the appropriate handler. --- @param request Request object --- @param ... Additional parameters passed to the handler --- @return HTTP statuscode, table of headers, response source -function VHost.process(self, request, ...) - local handler - local hlen = -1 - local uri = request.env.SCRIPT_NAME - local sc = ("/"):byte() - - -- SCRIPT_NAME - request.env.SCRIPT_NAME = "" - - -- Call URI part - request.env.PATH_INFO = uri - - if self.default and uri == "/" then - return 302, {Location = self.default} - end - - for k, h in pairs(self.handlers) do - if #k > hlen then - if uri == k or (uri:sub(1, #k) == k and uri:byte(#k+1) == sc) then - handler = h - hlen = #k - request.env.SCRIPT_NAME = k - request.env.PATH_INFO = uri:sub(#k+1) - end - end - end - - if handler then - return handler:process(request, ...) - else - return 404, nil, ltn12.source.string("No such handler") - end -end - ---- Get a list of registered handlers. --- @return Table of handlers -function VHost.get_handlers(self) - return self.handlers -end - ---- Register handler with a given URI prefix. --- @oaram match URI prefix --- @param handler Handler object -function VHost.set_handler(self, match, handler) - self.handlers[match] = handler -end - --- Remap IPv6-IPv4-compatibility addresses back to IPv4 addresses. -local function remapipv6(adr) - local map = "::ffff:" - if adr:sub(1, #map) == map then - return adr:sub(#map+1) - else - return adr - end -end - --- Create a source that decodes chunked-encoded data from a socket. -local function chunksource(sock, buffer) - buffer = buffer or "" - return function() - local output - local _, endp, count = buffer:find("^([0-9a-fA-F]+);?.-\r\n") - while not count and #buffer <= 1024 do - local newblock, code = sock:recv(1024 - #buffer) - if not newblock then - return nil, code - end - buffer = buffer .. newblock - _, endp, count = buffer:find("^([0-9a-fA-F]+);?.-\r\n") - end - count = tonumber(count, 16) - if not count then - return nil, -1, "invalid encoding" - elseif count == 0 then - return nil - elseif count + 2 <= #buffer - endp then - output = buffer:sub(endp+1, endp+count) - buffer = buffer:sub(endp+count+3) - return output - else - output = buffer:sub(endp+1, endp+count) - buffer = "" - if count - #output > 0 then - local remain, code = sock:recvall(count-#output) - if not remain then - return nil, code - end - output = output .. remain - count, code = sock:recvall(2) - else - count, code = sock:recvall(count+2-#buffer+endp) - end - if not count then - return nil, code - end - return output - end - end -end - --- Create a sink that chunk-encodes data and writes it on a given socket. -local function chunksink(sock) - return function(chunk, err) - if not chunk then - return sock:writeall("0\r\n\r\n") - else - return sock:writeall(("%X\r\n%s\r\n"):format(#chunk, tostring(chunk))) - end - end -end - - ---- Create a server object. --- @class function --- @return Server object -Server = util.class() - -function Server.__init__(self) - self.vhosts = {} -end - ---- Get a list of registered virtual hosts. --- @return Table of virtual hosts -function Server.get_vhosts(self) - return self.vhosts -end - ---- Register a virtual host with a given name. --- @param name Hostname --- @param vhost Virtual host object -function Server.set_vhost(self, name, vhost) - self.vhosts[name] = vhost -end - ---- Send a fatal error message to given client and close the connection. --- @param client Client socket --- @param code HTTP status code --- @param msg status message -function Server.error(self, client, code, msg) - hcode = tostring(code) - - client:writeall( "HTTP/1.0 " .. hcode .. " " .. - statusmsg[code] .. "\r\n" ) - client:writeall( "Connection: close\r\n" ) - client:writeall( "Content-Type: text/plain\r\n\r\n" ) - - if msg then - client:writeall( "HTTP-Error " .. code .. ": " .. msg .. "\r\n" ) - end - - client:close() -end - -local hdr2env = { - ["Content-Length"] = "CONTENT_LENGTH", - ["Content-Type"] = "CONTENT_TYPE", - ["Content-type"] = "CONTENT_TYPE", - ["Accept"] = "HTTP_ACCEPT", - ["Accept-Charset"] = "HTTP_ACCEPT_CHARSET", - ["Accept-Encoding"] = "HTTP_ACCEPT_ENCODING", - ["Accept-Language"] = "HTTP_ACCEPT_LANGUAGE", - ["Connection"] = "HTTP_CONNECTION", - ["Cookie"] = "HTTP_COOKIE", - ["Host"] = "HTTP_HOST", - ["Referer"] = "HTTP_REFERER", - ["User-Agent"] = "HTTP_USER_AGENT" -} - ---- Parse the request headers and prepare the environment. --- @param source line-based input source --- @return Request object -function Server.parse_headers(self, source) - local env = {} - local req = {env = env, headers = {}} - local line, err - - repeat -- Ignore empty lines - line, err = source() - if not line then - return nil, err - end - until #line > 0 - - env.REQUEST_METHOD, env.REQUEST_URI, env.SERVER_PROTOCOL = - line:match("^([A-Z]+) ([^ ]+) (HTTP/1%.[01])$") - - if not env.REQUEST_METHOD then - return nil, "invalid magic" - end - - local key, envkey, val - repeat - line, err = source() - if not line then - return nil, err - elseif #line > 0 then - key, val = line:match("^([%w-]+)%s?:%s?(.*)") - if key then - req.headers[key] = val - envkey = hdr2env[key] - if envkey then - env[envkey] = val - end - else - return nil, "invalid header line" - end - else - break - end - until false - - env.SCRIPT_NAME, env.QUERY_STRING = env.REQUEST_URI:match("([^?]*)%??(.*)") - return req -end - ---- Handle a new client connection. --- @param client client socket --- @param env superserver environment -function Server.process(self, client, env) - local sourcein = function() end - local sourcehdr = client:linesource() - local sinkout - local buffer - - local close = false - local stat, code, msg, message, err - - env.config.memlimit = tonumber(env.config.memlimit) - if env.config.memlimit and set_memory_limit then - set_memory_limit(env.config.memlimit) - end - - client:setsockopt("socket", "rcvtimeo", 5) - client:setsockopt("socket", "sndtimeo", 5) - - repeat - -- parse headers - message, err = self:parse_headers(sourcehdr) - - -- any other error - if not message or err then - if err == 11 then -- EAGAIN - break - else - return self:error(client, 400, err) - end - end - - -- Prepare sources and sinks - buffer = sourcehdr(true) - sinkout = client:sink() - message.server = env - - if client:is_tls_socket() then - message.env.HTTPS = "on" - end - - -- Addresses - message.env.REMOTE_ADDR = remapipv6(env.host) - message.env.REMOTE_PORT = env.port - - local srvaddr, srvport = client:getsockname() - message.env.SERVER_ADDR = remapipv6(srvaddr) - message.env.SERVER_PORT = srvport - - -- keep-alive - if message.env.SERVER_PROTOCOL == "HTTP/1.1" then - close = (message.env.HTTP_CONNECTION == "close") - else - close = not message.env.HTTP_CONNECTION - or message.env.HTTP_CONNECTION == "close" - end - - -- Uncomment this to disable keep-alive - close = close or env.config.nokeepalive - - if message.env.REQUEST_METHOD == "GET" - or message.env.REQUEST_METHOD == "HEAD" then - -- Be happy - - elseif message.env.REQUEST_METHOD == "POST" then - -- If we have a HTTP/1.1 client and an Expect: 100-continue header - -- respond with HTTP 100 Continue message - if message.env.SERVER_PROTOCOL == "HTTP/1.1" - and message.headers.Expect == '100-continue' then - client:writeall("HTTP/1.1 100 Continue\r\n\r\n") - end - - if message.headers['Transfer-Encoding'] and - message.headers['Transfer-Encoding'] ~= "identity" then - sourcein = chunksource(client, buffer) - buffer = nil - elseif message.env.CONTENT_LENGTH then - local len = tonumber(message.env.CONTENT_LENGTH) - if #buffer >= len then - sourcein = ltn12.source.string(buffer:sub(1, len)) - buffer = buffer:sub(len+1) - else - sourcein = ltn12.source.cat( - ltn12.source.string(buffer), - client:blocksource(nil, len - #buffer) - ) - end - else - return self:error(client, 411, statusmsg[411]) - end - - close = true - else - return self:error(client, 405, statusmsg[405]) - end - - - local host = self.vhosts[message.env.HTTP_HOST] or self.vhosts[""] - if not host then - return self:error(client, 404, "No virtual host found") - end - - local code, headers, sourceout = host:process(message, sourcein) - headers = headers or {} - - -- Post process response - if sourceout then - if util.instanceof(sourceout, IOResource) then - if not headers["Content-Length"] then - headers["Content-Length"] = sourceout.len - end - end - if not headers["Content-Length"] and not close then - if message.env.SERVER_PROTOCOL == "HTTP/1.1" then - headers["Transfer-Encoding"] = "chunked" - sinkout = chunksink(client) - else - close = true - end - end - elseif message.env.REQUEST_METHOD ~= "HEAD" then - headers["Content-Length"] = 0 - end - - if close then - headers["Connection"] = "close" - else - headers["Connection"] = "Keep-Alive" - headers["Keep-Alive"] = "timeout=5, max=50" - end - - headers["Date"] = date.to_http(os.time()) - local header = { - message.env.SERVER_PROTOCOL .. " " .. tostring(code) .. " " - .. statusmsg[code], - "Server: LuCId-HTTPd/" .. VERSION - } - - - for k, v in pairs(headers) do - if type(v) == "table" then - for _, h in ipairs(v) do - header[#header+1] = k .. ": " .. h - end - else - header[#header+1] = k .. ": " .. v - end - end - - header[#header+1] = "" - header[#header+1] = "" - - -- Output - stat, code, msg = client:writeall(table.concat(header, "\r\n")) - - if sourceout and stat then - local closefd - if util.instanceof(sourceout, IOResource) then - if not headers["Transfer-Encoding"] then - stat, code, msg = sourceout.fd:copyz(client, sourceout.len) - closefd = sourceout.fd - sourceout = nil - else - closefd = sourceout.fd - sourceout = sourceout.fd:blocksource(nil, sourceout.len) - end - end - - if sourceout then - stat, msg = ltn12.pump.all(sourceout, sinkout) - end - - if closefd then - closefd:close() - end - end - - - -- Write errors - if not stat then - if msg then - nixio.syslog("err", "Error sending data to " .. env.host .. - ": " .. msg .. "\n") - end - break - end - - if buffer then - sourcehdr(buffer) - end - until close - - client:shutdown() - client:close() -end diff --git a/libs/lucid-rpc/Makefile b/libs/lucid-rpc/Makefile deleted file mode 100644 index f7fac7740..000000000 --- a/libs/lucid-rpc/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -include ../../build/config.mk -include ../../build/module.mk diff --git a/libs/lucid-rpc/docs/OVERVIEW b/libs/lucid-rpc/docs/OVERVIEW deleted file mode 100644 index 9da870065..000000000 --- a/libs/lucid-rpc/docs/OVERVIEW +++ /dev/null @@ -1,19 +0,0 @@ - LuCId JSON-RPC Server Slave - -*** Abstract *** -The LuCId JSON-RPC server slave implements the JSON-RPC 1.0 and 2.0 protocol -to allow efficient light-weight remote procedure calling. -It provides notification support and several unofficial protocol extensions such -as: - * Close notifications - * Raw TCP switching to transfer BLOBs efficiently - * Client notification - - -*** Workflow *** -After receiving an incoming connection from LuCId, the slave analyses the -request and passes it to the matching handler. The handler will enforce -access restriction and deserialize the payload data and invokes the assigned -Lua function in a protected way. In case of a success the handler will serialize -the response and send it to the client - otherwise a detailed error message -will be returned.
\ No newline at end of file diff --git a/libs/lucid-rpc/luasrc/lucid/rpc.lua b/libs/lucid-rpc/luasrc/lucid/rpc.lua deleted file mode 100644 index 417e57214..000000000 --- a/libs/lucid-rpc/luasrc/lucid/rpc.lua +++ /dev/null @@ -1,51 +0,0 @@ ---[[ -LuCI - Lua Development Framework - -Copyright 2009 Steven Barth <steven@midlink.org> - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ -]] - -local require, ipairs, pcall = require, ipairs, pcall -local srv = require "luci.lucid.rpc.server" - -module "luci.lucid.rpc" - ---- Prepare the RPC-daemon and its associated publishers. --- @param publisher Table of publishers --- @return factory callback or nil, error message -function factory(publisher) - local root = srv.Module() - local server = srv.Server(root) - - for _, r in ipairs(publisher) do - for _, m in ipairs(r.export) do - local s, mod = pcall(require, r.namespace .. "." .. m) - if s and mod then - local module = mod._factory() - - if r.exec then - for _, x in ipairs(r.exec) do - if x:sub(1,1) == ":" then - module:restrict({interface = x:sub(2)}) - else - module:restrict({user = x}) - end - end - end - - root:add(m, module) - else - return nil, mod - end - end - end - - return function(...) return server:process(...) end -end
\ No newline at end of file diff --git a/libs/lucid-rpc/luasrc/lucid/rpc/ruci.lua b/libs/lucid-rpc/luasrc/lucid/rpc/ruci.lua deleted file mode 100644 index f0910c7f0..000000000 --- a/libs/lucid-rpc/luasrc/lucid/rpc/ruci.lua +++ /dev/null @@ -1,85 +0,0 @@ ---[[ -LuCIRPCd -(c) 2009 Steven Barth <steven@midlink.org> - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ -]]-- -local uci = require "luci.model.uci" -local tostring, getmetatable, pairs = tostring, getmetatable, pairs -local error, type = error, type -local nixio = require "nixio" -local srv = require "luci.lucid.rpc.server" - ---- Remote UCI functions. -module "luci.lucid.rpc.ruci" - --- Prepare the remote UCI functions. -function _factory() - local m = srv.Module("Remote UCI API") - - for k, v in pairs(_M) do - if type(v) == "function" and v ~= _factory then - m:add(k, srv.Method.extended(v)) - end - end - - return m -end - --- Get the associate RUCI instance. -local function getinst(session, name) - return session.ruci and session.ruci[name] -end - --- Set a new RUCI instance. -local function setinst(session, obj) - session.ruci = session.ruci or {} - local name = tostring(obj):match("0x([a-z0-9]+)") - session.ruci[name] = obj - return name -end - - -local Cursor = getmetatable(uci.cursor()) - -for name, func in pairs(Cursor) do - _M[name] = function(session, inst, ...) - inst = getinst(session, inst) - return inst[name](inst, ...) - end -end - ---- Generate a new RUCI cursor. --- @param session Session object --- @param ... Parameters passed to the UCI constructor --- @return RUCI instance -function cursor(session, ...) - return setinst(session, uci.cursor(...)) -end - ---- Generate a new RUCI state cursor. --- @param session Session object --- @param ... Parameters passed to the UCI constructor --- @return RUCI instance -function cursor_state(session, ...) - return setinst(session, uci.cursor_state(...)) -end - ---- Custom foreach function. --- @param session Session object --- @param inst RUCI instance --- @param config UCI config --- @param sectiontype UCI sectiontype --- @return section data -function foreach(session, inst, config, sectiontype) - local inst = getinst(session, inst) - local secs = {} - inst:foreach(config, sectiontype, function(s) secs[#secs+1] = s end) - return secs -end
\ No newline at end of file diff --git a/libs/lucid-rpc/luasrc/lucid/rpc/server.lua b/libs/lucid-rpc/luasrc/lucid/rpc/server.lua deleted file mode 100644 index 18b004d8b..000000000 --- a/libs/lucid-rpc/luasrc/lucid/rpc/server.lua +++ /dev/null @@ -1,338 +0,0 @@ ---[[ -LuCI - Lua Development Framework - -Copyright 2009 Steven Barth <steven@midlink.org> - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ -]] - -local ipairs, pairs = ipairs, pairs -local tostring, tonumber = tostring, tonumber -local pcall, assert, type, unpack = pcall, assert, type, unpack - -local nixio = require "nixio" -local json = require "luci.json" -local util = require "luci.util" -local table = require "table" -local ltn12 = require "luci.ltn12" - ---- RPC daemom. --- @cstyle instance -module "luci.lucid.rpc.server" - -RQLIMIT = 32 * nixio.const.buffersize -VERSION = "1.0" - -ERRNO_PARSE = -32700 -ERRNO_INVALID = -32600 -ERRNO_UNKNOWN = -32001 -ERRNO_TIMEOUT = -32000 -ERRNO_NOTFOUND = -32601 -ERRNO_NOACCESS = -32002 -ERRNO_INTERNAL = -32603 -ERRNO_NOSUPPORT = -32003 - -ERRMSG = { - [ERRNO_PARSE] = "Parse error.", - [ERRNO_INVALID] = "Invalid request.", - [ERRNO_TIMEOUT] = "Connection timeout.", - [ERRNO_UNKNOWN] = "Unknown error.", - [ERRNO_NOTFOUND] = "Method not found.", - [ERRNO_NOACCESS] = "Access denied.", - [ERRNO_INTERNAL] = "Internal error.", - [ERRNO_NOSUPPORT] = "Operation not supported." -} - - ---- Create an RPC method wrapper. --- @class function --- @param method Lua function --- @param description Method description --- @return Wrapped RPC method -Method = util.class() - ---- Create an extended wrapped RPC method. --- @class function --- @param method Lua function --- @param description Method description --- @return Wrapped RPC method -function Method.extended(...) - local m = Method(...) - m.call = m.xcall - return m -end - -function Method.__init__(self, method, description) - self.description = description - self.method = method -end - ---- Extended call the associated function. --- @param session Session storage --- @param argv Request parameters --- @return function call response -function Method.xcall(self, session, argv) - return self.method(session, unpack(argv)) -end - ---- Standard call the associated function. --- @param session Session storage --- @param argv Request parameters --- @return function call response -function Method.call(self, session, argv) - return self.method(unpack(argv)) -end - ---- Process a given request and create a JSON response. --- @param session Session storage --- @param request Requested method --- @param argv Request parameters -function Method.process(self, session, request, argv) - local stat, result = pcall(self.call, self, session, argv) - - if stat then - return { result=result } - else - return { error={ - code=ERRNO_UNKNOWN, - message=ERRMSG[ERRNO_UNKNOWN], - data=result - } } - end -end - --- Remap IPv6-IPv4-compatibility addresses to IPv4 addresses -local function remapipv6(adr) - local map = "::ffff:" - if adr:sub(1, #map) == map then - return adr:sub(#map+1) - else - return adr - end -end - - ---- Create an RPC module. --- @class function --- @param description Method description --- @return RPC module -Module = util.class() - -function Module.__init__(self, description) - self.description = description - self.handler = {} -end - ---- Add a handler. --- @param k key --- @param v handler -function Module.add(self, k, v) - self.handler[k] = v -end - ---- Add an access restriction. --- @param restriction Restriction specification -function Module.restrict(self, restriction) - if not self.restrictions then - self.restrictions = {restriction} - else - self.restrictions[#self.restrictions+1] = restriction - end -end - ---- Enforce access restrictions. --- @param request Request object --- @return nil or HTTP statuscode, table of headers, response source -function Module.checkrestricted(self, session, request, argv) - if not self.restrictions then - return - end - - for _, r in ipairs(self.restrictions) do - local stat = true - if stat and r.interface then -- Interface restriction - if not session.localif then - for _, v in ipairs(session.env.interfaces) do - if v.addr == session.localaddr then - session.localif = v.name - break - end - end - end - - if r.interface ~= session.localif then - stat = false - end - end - - if stat and r.user and session.user ~= r.user then -- User restriction - stat = false - end - - if stat then - return - end - end - - return {error={code=ERRNO_NOACCESS, message=ERRMSG[ERRNO_NOACCESS]}} -end - ---- Register a handler, submodule or function. --- @param m entity --- @param descr description --- @return Module (self) -function Module.register(self, m, descr) - descr = descr or {} - for k, v in pairs(m) do - if util.instanceof(v, Method) then - self.handler[k] = v - elseif type(v) == "table" then - self.handler[k] = Module() - self.handler[k]:register(v, descr[k]) - elseif type(v) == "function" then - self.handler[k] = Method(v, descr[k]) - end - end - return self -end - ---- Process a request. --- @param session Session storage --- @param request Request object --- @param argv Request parameters --- @return JSON response object -function Module.process(self, session, request, argv) - local first, last = request:match("^([^.]+).?(.*)$") - - local stat = self:checkrestricted(session, request, argv) - if stat then -- Access Denied - return stat - end - - local hndl = first and self.handler[first] - if not hndl then - return {error={code=ERRNO_NOTFOUND, message=ERRMSG[ERRNO_NOTFOUND]}} - end - - session.chain[#session.chain+1] = self - return hndl:process(session, last, argv) -end - - ---- Create a server object. --- @class function --- @param root Root module --- @return Server object -Server = util.class() - -function Server.__init__(self, root) - self.root = root -end - ---- Get the associated root module. --- @return Root module -function Server.get_root(self) - return self.root -end - ---- Set a new root module. --- @param root Root module -function Server.set_root(self, root) - self.root = root -end - ---- Create a JSON reply. --- @param jsonrpc JSON-RPC version --- @param id Message id --- @param res Result --- @param err Error --- @reutrn JSON response source -function Server.reply(self, jsonrpc, id, res, err) - id = id or json.null - - -- 1.0 compatibility - if jsonrpc ~= "2.0" then - jsonrpc = nil - res = res or json.null - err = err or json.null - end - - return json.Encoder( - {id=id, result=res, error=err, jsonrpc=jsonrpc}, BUFSIZE - ):source() -end - ---- Handle a new client connection. --- @param client client socket --- @param env superserver environment -function Server.process(self, client, env) - local decoder - local sinkout = client:sink() - client:setopt("socket", "sndtimeo", 90) - client:setopt("socket", "rcvtimeo", 90) - - local close = false - local session = {server = self, chain = {}, client = client, env = env, - localaddr = remapipv6(client:getsockname())} - local req, stat, response, result, cb - - repeat - local oldchunk = decoder and decoder.chunk - decoder = json.ActiveDecoder(client:blocksource(nil, RQLIMIT)) - decoder.chunk = oldchunk - - result, response, cb = nil, nil, nil - - -- Read one request - stat, req = pcall(decoder.get, decoder) - - if stat then - if type(req) == "table" and type(req.method) == "string" - and (not req.params or type(req.params) == "table") then - req.params = req.params or {} - result, cb = self.root:process(session, req.method, req.params) - if type(result) == "table" then - if req.id ~= nil then - response = self:reply(req.jsonrpc, req.id, - result.result, result.error) - end - close = result.close - else - if req.id ~= nil then - response = self:reply(req.jsonrpc, req.id, nil, - {code=ERRNO_INTERNAL, message=ERRMSG[ERRNO_INTERNAL]}) - end - end - else - response = self:reply(req.jsonrpc, req.id, - nil, {code=ERRNO_INVALID, message=ERRMSG[ERRNO_INVALID]}) - end - else - if nixio.errno() ~= nixio.const.EAGAIN then - response = self:reply("2.0", nil, - nil, {code=ERRNO_PARSE, message=ERRMSG[ERRNO_PARSE]}) - --[[else - response = self:reply("2.0", nil, - nil, {code=ERRNO_TIMEOUT, message=ERRMSG_TIMEOUT})]] - end - close = true - end - - if response then - ltn12.pump.all(response, sinkout) - end - - if cb then - close = cb(client, session, self) or close - end - until close - - client:shutdown() - client:close() -end diff --git a/libs/lucid-rpc/luasrc/lucid/rpc/system.lua b/libs/lucid-rpc/luasrc/lucid/rpc/system.lua deleted file mode 100644 index cf3aa6abe..000000000 --- a/libs/lucid-rpc/luasrc/lucid/rpc/system.lua +++ /dev/null @@ -1,101 +0,0 @@ ---[[ -LuCI - Lua Development Framework - -Copyright 2009 Steven Barth <steven@midlink.org> - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ -]] - -local type, ipairs = type, ipairs -local srv = require "luci.lucid.rpc.server" -local nixio = require "nixio" -local lucid = require "luci.lucid" - ---- Internal system functions. -module "luci.lucid.rpc.system" - --- Prepare the RPC module. -function _factory() - local mod = srv.Module("System functions"):register({ - echo = echo, - void = void, - multicall = srv.Method.extended(multicall), - authenticate = srv.Method.extended(authenticate) - }) - mod.checkrestricted = function(self, session, request, ...) - if request ~= "authenticate" then - return srv.Module.checkrestricted(self, session, request, ...) - end - end - return mod -end - ---- Simple echo test function. --- @param object to be echoed object --- @return echo object -function echo(object) - return object -end - ---- Simple void test function. -function void() - -end - ---- Accumulate different requests and execute them. --- @param session Session object --- @param ... --- @return overall response object -function multicall(session, ...) - local server, responses, response = session.server, {}, nil - for k, req in ipairs({...}) do - response = nil - if type(req) == "table" and type(req.method) == "string" - and (not req.params or type(req.params) == "table") then - req.params = req.params or {} - result = server.root:process(session, req.method, req.params) - if type(result) == "table" then - if req.id ~= nil then - response = {jsonrpc=req.jsonrpc, id=req.id, - result=result.result, error=result.error} - end - else - if req.id ~= nil then - response = {jsonrpc=req.jsonrpc, id=req.id, - result=nil, error={code=srv.ERRNO_INTERNAL, - message=srv.ERRMSG[ERRNO_INTERNAL]}} - end - end - end - responses[k] = response - end - return responses -end - ---- Create or use a new authentication token. --- @param session Session object --- @param type Authentication type --- @param entity Authentication enttity (username) --- @param key Authentication key (password) --- @return boolean status -function authenticate(session, type, entity, key) - if not type then - session.user = nil - return true - elseif type == "plain" then - local pwe = nixio.getsp and nixio.getsp(entity) or nixio.getpw(entity) - local pwh = pwe and (pwe.pwdp or pwe.passwd) - if not pwh or #pwh < 1 or nixio.crypt(key, pwh) ~= pwh then - return nil - else - session.user = entity - return true - end - end -end
\ No newline at end of file diff --git a/libs/lucid/Makefile b/libs/lucid/Makefile deleted file mode 100644 index f7fac7740..000000000 --- a/libs/lucid/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -include ../../build/config.mk -include ../../build/module.mk diff --git a/libs/lucid/docs/OVERVIEW b/libs/lucid/docs/OVERVIEW deleted file mode 100644 index ca742ddd6..000000000 --- a/libs/lucid/docs/OVERVIEW +++ /dev/null @@ -1,75 +0,0 @@ - LuCId Network Superserver in Lua - -*** Abstract *** -LuCId is a network superserver written in Lua based on the nixio POSIX library. -It supports IPv4, IPv6, TLS, asynchronous and synchronous IO and can be extended -to handle any kind of IO events on file descriptors. LuCId is also able to -generate RSA private keys and self-signed certificates on demand if the px5g -keymaster library is available. Both nixio and px5g are libraries created -by the LuCI developers. - - -*** Configuration *** -LuCId uses the UCI Universal Configuration Interface as configuration backend. - -There are 4 types of configuration sections and one named section defined: -The main section of type "lucid" defines the basic framework parameters of LuCId -These include: - * pollinterval: Internal polling interval - * threadlimit: Overall maximum number of child processes - * daemonize: Whether to daemonize at startup - * debug: Whether to enable debug output in syslog - - -The "tcpserver" section type provides the framework for TCP servers: -Parameters: - * entrypoint: Lua module entrypoint (provides a prepare_daemon function) - -The "daemon" sections define instances of servers. -Parameters may include: - * slave: Server slave - * publisher: Publishers to be served by this daemon - * enabled: Flag (0/1) whether this daemon should be started - * address: List of ports / addresses to be bound too, if applicable - * encryption: Flag (disabled/enabled) whether to enforce encryption - * tls: Reference to the TLS configuration section to use - -The "...Publisher" sections define services to be published through daemons. -Publishers definitions should be daemon and protocol independent whenever -possible. Publishers should also implement access restrictions for certain -network interfaces and for specified UNIX user accounts. -Publishers usually define but are not required to use the following Parameters: - * name: Published Name - * physical: Physical source path - * virtual: Virtual resource path - * domain: Any kind of domain or realm specification - * read: ACL containing entities allowed to read the given resource - * write: -"- - * exec: -"- - -The "tls" sections describe TLS security specifications for TCP servers. -Parameters: - * key: Private Key file - * cert: Certificate file - * type: Type of certificate and key files (pem, asn1) - * generate: Flag (0/1) to determine whether LuCId should generate - keys and self-signed certificates if the certificate is not available and - the px5g RSA Keymaster is available - - - -*** Workflow *** -In the preparation phase LuCId loads its configuration using the specification -given above and prepares its servers, daemons and publishers. It also allocates -resources such as binding sockets or preparing encryption credentials. -If everything could be setup correctly LuCId will daemonize - if requested. If -any errors occur in the preparation phase, LuCId will write to the system logger -and exit. - -After daemonizing the main process is responsible for keeping a list of -file descriptors that LuCId is polling regularly to handle incoming data events. -Data events are for example new TCP connection attempts which could cause the -superserver to fork a new process and invoke a registered handler. - -Whenever a sub-process is about to be generate LuCId checks if given resource -limits are still met.
\ No newline at end of file diff --git a/libs/lucid/hostfiles/etc/config/lucid b/libs/lucid/hostfiles/etc/config/lucid deleted file mode 100644 index a88835cdd..000000000 --- a/libs/lucid/hostfiles/etc/config/lucid +++ /dev/null @@ -1,75 +0,0 @@ -config lucid main - option pollinterval 15000 - option daemon 1 - option debug 1 - list supports tcpserver - list supports server - -config DirectoryPublisher webroot - option name 'Webserver Share' - option physical host/www - option virtual '' - option domain '' - -config LuciWebPublisher luciweb - option name 'LuCI Webapplication' - option physical '' - list virtual /luci - option domain '' - option home 1 - -config RPCPublisher mainrpc - option namespace 'luci.lucid.rpc' - list export system - list export ruci - list exec ':lo' - list exec 'root' - -config tcpserver httpd - option entrypoint "luci.lucid.http" - list supports DirectoryPublisher - list supports LuciWebPublisher - -config tcpserver rpcd - option entrypoint "luci.lucid.rpc" - list supports RPCPublisher - -config daemon http - option slave httpd - list address 8080 - list publisher webroot - list publisher luciweb - option enabled 1 - -config daemon https - option slave httpd - list address 4443 - list publisher webroot - list publisher luciweb - option enabled 1 - option encryption enable - option tls sdk_tls - -config tls sdk_tls - option generate 1 - option key /tmp/lucid-tls.key - option cert /tmp/lucid-tls.cert - option type asn1 - -config daemon rpc - option slave rpcd - list address 12900 - list publisher mainrpc - option enabled 1 - -config 'daemon' 'splashr' - option 'slave' 'httpd' - list 'address' '8082' - list 'publisher' 'splashredir' - option 'enabled' '1' - -config 'Redirector' 'splashredir' - option 'name' 'Splashd' - option 'virtual' '/' - option 'physical' ':80/luci/splash' - diff --git a/libs/lucid/luasrc/lucid.lua b/libs/lucid/luasrc/lucid.lua deleted file mode 100644 index 38b34fde9..000000000 --- a/libs/lucid/luasrc/lucid.lua +++ /dev/null @@ -1,348 +0,0 @@ ---[[ -LuCI - Lua Development Framework - -Copyright 2009 Steven Barth <steven@midlink.org> - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ -]] - -local nixio = require "nixio" -local table = require "table" -local uci = require "luci.model.uci" -local os = require "os" -local io = require "io" - -local pairs, require, pcall, assert, type = pairs, require, pcall, assert, type -local ipairs, tonumber, collectgarbage = ipairs, tonumber, collectgarbage - - -module "luci.lucid" - -local slaves = {} -local pollt = {} -local tickt = {} -local tpids = {} -local tcount = 0 -local ifaddrs = nixio.getifaddrs() - -cursor = uci.cursor() -state = uci.cursor_state() -UCINAME = "lucid" - -local cursor = cursor -local state = state -local UCINAME = UCINAME -local SSTATE = "/tmp/.lucid_store" - - ---- Starts a new LuCId superprocess. -function start() - state:revert(UCINAME, "main") - - prepare() - - local detach = cursor:get(UCINAME, "main", "daemonize") - if detach == "1" then - local stat, code, msg = daemonize() - if not stat then - nixio.syslog("crit", "Unable to detach process: " .. msg .. "\n") - ox.exit(2) - end - end - - state:set(UCINAME, "main", "pid", nixio.getpid()) - state:save(UCINAME) - - run() -end - ---- Returns the PID of the currently active LuCId process. -function running() - local pid = tonumber(state:get(UCINAME, "main", "pid")) - return pid and nixio.kill(pid, 0) and pid -end - ---- Stops any running LuCId superprocess. -function stop() - local pid = tonumber(state:get(UCINAME, "main", "pid")) - if pid then - return nixio.kill(pid, nixio.const.SIGTERM) - end - return false -end - ---- Prepares the slaves, daemons and publishers, allocate resources. -function prepare() - local debug = tonumber((cursor:get(UCINAME, "main", "debug"))) - - nixio.openlog("lucid", "pid", "perror") - if debug ~= 1 then - nixio.setlogmask("warning") - end - - cursor:foreach(UCINAME, "daemon", function(config) - if config.enabled ~= "1" then - return - end - - local key = config[".name"] - if not config.slave then - nixio.syslog("crit", "Daemon "..key.." is missing a slave\n") - os.exit(1) - else - nixio.syslog("info", "Initializing daemon " .. key) - end - - state:revert(UCINAME, key) - - local daemon, code, err = prepare_daemon(config) - if daemon then - state:set(UCINAME, key, "status", "started") - nixio.syslog("info", "Prepared daemon " .. key) - else - state:set(UCINAME, key, "status", "error") - state:set(UCINAME, key, "error", err) - nixio.syslog("err", "Failed to initialize daemon "..key..": ".. - err .. "\n") - end - end) -end - ---- Run the superprocess if prepared before. --- This main function of LuCId will wait for events on given file descriptors. -function run() - local pollint = tonumber((cursor:get(UCINAME, "main", "pollinterval"))) - local threadlimit = tonumber((cursor:get(UCINAME, "main", "threadlimit"))) - - while true do - local stat, code = nixio.poll(pollt, pollint) - - if stat and stat > 0 then - local ok = false - for _, polle in ipairs(pollt) do - if polle.revents ~= 0 and polle.handler then - ok = ok or polle.handler(polle) - end - end - if not ok then - -- Avoid high CPU usage if thread limit is reached - nixio.nanosleep(0, 100000000) - end - elseif stat == 0 then - ifaddrs = nixio.getifaddrs() - end - - for _, cb in ipairs(tickt) do - cb() - end - - local pid, stat, code = nixio.wait(-1, "nohang") - while pid and pid > 0 do - nixio.syslog("info", "Buried thread: " .. pid) - if tpids[pid] then - tcount = tcount - 1 - if tpids[pid] ~= true then - tpids[pid](pid, stat, code) - end - tpids[pid] = nil - end - pid, stat, code = nixio.wait(-1, "nohang") - end - end -end - ---- Add a file descriptor for the main loop and associate handler functions. --- @param polle Table containing: {fd = FILE DESCRIPTOR, events = POLL EVENTS, --- handler = EVENT HANDLER CALLBACK} --- @see unregister_pollfd --- @return boolean status -function register_pollfd(polle) - pollt[#pollt+1] = polle - return true -end - ---- Unregister a file desciptor and associate handler from the main loop. --- @param polle Poll descriptor --- @see register_pollfd --- @return boolean status -function unregister_pollfd(polle) - for k, v in ipairs(pollt) do - if v == polle then - table.remove(pollt, k) - return true - end - end - return false -end - ---- Close all registered file descriptors from main loop. --- This is useful for forked child processes. -function close_pollfds() - for k, v in ipairs(pollt) do - if v.fd and v.fd.close then - v.fd:close() - end - end -end - ---- Register a tick function that will be called at each cycle of the main loop. --- @param cb Callback --- @see unregister_tick --- @return boolean status -function register_tick(cb) - tickt[#tickt+1] = cb - return true -end - ---- Unregister a tick function from the main loop. --- @param cb Callback --- @see register_tick --- @return boolean status -function unregister_tick(cb) - for k, v in ipairs(tickt) do - if v == cb then - table.remove(tickt, k) - return true - end - end - return false -end - ---- Tests whether a given number of processes can be created. --- @oaram num Processes to be created --- @return boolean status -function try_process(num) - local threadlimit = tonumber((cursor:get(UCINAME, "main", "threadlimit"))) - return not threadlimit or (threadlimit - tcount) >= (num or 1) -end - ---- Create a new child process from a Lua function and assign a destructor. --- @param threadcb main function of the new process --- @param waitcb destructor callback --- @return process identifier or nil, error code, error message -function create_process(threadcb, waitcb) - local threadlimit = tonumber(cursor:get(UCINAME, "main", "threadlimit")) - if threadlimit and tcount >= threadlimit then - nixio.syslog("warning", "Cannot create thread: process limit reached") - return nil - else - collectgarbage("collect") - end - local pid, code, err = nixio.fork() - if pid and pid ~= 0 then - nixio.syslog("info", "Created thread: " .. pid) - tpids[pid] = waitcb or true - tcount = tcount + 1 - elseif pid == 0 then - local code = threadcb() - os.exit(code) - else - nixio.syslog("err", "Unable to fork(): " .. err) - end - return pid, code, err -end - ---- Prepare a daemon from a given configuration table. --- @param config Configuration data. --- @return boolean status or nil, error code, error message -function prepare_daemon(config) - nixio.syslog("info", "Preparing daemon " .. config[".name"]) - local modname = cursor:get(UCINAME, config.slave) - if not modname then - return nil, -1, "invalid slave" - end - - local stat, module = pcall(require, _NAME .. "." .. modname) - if not stat or not module.prepare_daemon then - return nil, -2, "slave type not supported" - end - - config.slave = prepare_slave(config.slave) - - return module.prepare_daemon(config, _M) -end - ---- Prepare a slave. --- @param name slave name --- @return table containing slave module and configuration or nil, error message -function prepare_slave(name) - local slave = slaves[name] - if not slave then - local config = cursor:get_all(UCINAME, name) - - local stat, module = pcall(require, config and config.entrypoint) - if stat then - slave = {module = module, config = config} - end - end - - if slave then - return slave - else - return nil, module - end -end - ---- Return a list of available network interfaces on the host. --- @return table returned by nixio.getifaddrs() -function get_interfaces() - return ifaddrs -end - ---- Revoke process privileges. --- @param user new user name or uid --- @param group new group name or gid --- @return boolean status or nil, error code, error message -function revoke_privileges(user, group) - if nixio.getuid() == 0 then - return nixio.setgid(group) and nixio.setuid(user) - end -end - ---- Return a secure UCI cursor. --- @return UCI cursor -function securestate() - local stat = nixio.fs.stat(SSTATE) or {} - local uid = nixio.getuid() - if stat.type ~= "dir" or (stat.modedec % 100) ~= 0 or stat.uid ~= uid then - nixio.fs.remover(SSTATE) - if not nixio.fs.mkdir(SSTATE, 700) then - local errno = nixio.errno() - nixio.syslog("err", "Integrity check on secure state failed!") - return nil, errno, nixio.perror(errno) - end - end - - return uci.cursor(nil, SSTATE) -end - ---- Daemonize the process. --- @return boolean status or nil, error code, error message -function daemonize() - if nixio.getppid() == 1 then - return - end - - local pid, code, msg = nixio.fork() - if not pid then - return nil, code, msg - elseif pid > 0 then - os.exit(0) - end - - nixio.setsid() - nixio.chdir("/") - - local devnull = nixio.open("/dev/null", nixio.open_flags("rdwr")) - nixio.dup(devnull, nixio.stdin) - nixio.dup(devnull, nixio.stdout) - nixio.dup(devnull, nixio.stderr) - - return true -end diff --git a/libs/lucid/luasrc/lucid/tcpserver.lua b/libs/lucid/luasrc/lucid/tcpserver.lua deleted file mode 100644 index 266ea29e4..000000000 --- a/libs/lucid/luasrc/lucid/tcpserver.lua +++ /dev/null @@ -1,254 +0,0 @@ ---[[ -LuCI - Lua Development Framework - -Copyright 2009 Steven Barth <steven@midlink.org> - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ -]] - -local os = require "os" -local fs = require "nixio.fs" -local nixio = require "nixio" -local lucid = require "luci.lucid" - -local ipairs, type, require, setmetatable = ipairs, type, require, setmetatable -local pairs, print, tostring, unpack = pairs, print, tostring, unpack -local pcall = pcall - -module "luci.lucid.tcpserver" - -local cursor = lucid.cursor -local UCINAME = lucid.UCINAME - -local tcpsockets = {} - ---- Prepare a daemon and allocate its resources. (superserver callback) --- @param config configuration table --- @param server LuCId basemodule --- @return binary data -function prepare_daemon(config, server) - nixio.syslog("info", "Preparing TCP-Daemon " .. config[".name"]) - if type(config.address) ~= "table" then - config.address = {config.address} - end - - local sockets, socket, code, err = {} - local sopts = {reuseaddr = 1} - for _, addr in ipairs(config.address) do - local host, port = addr:match("(.-):?([^:]*)") - if not host then - nixio.syslog("err", "Invalid address: " .. addr) - return nil, -5, "invalid address format" - elseif #host == 0 then - host = nil - end - socket, code, err = prepare_socket(config.family, host, port, sopts) - if socket then - sockets[#sockets+1] = socket - end - end - - nixio.syslog("info", "Sockets bound for " .. config[".name"]) - - if #sockets < 1 then - return nil, -6, "no sockets bound" - end - - nixio.syslog("info", "Preparing publishers for " .. config[".name"]) - - local publisher = {} - for k, pname in ipairs(config.publisher) do - local pdata = cursor:get_all(UCINAME, pname) - if pdata then - publisher[#publisher+1] = pdata - else - nixio.syslog("err", "Publisher " .. pname .. " not found") - end - end - - nixio.syslog("info", "Preparing TLS for " .. config[".name"]) - - local tls = prepare_tls(config.tls) - if not tls and config.encryption == "enable" then - for _, s in ipairs(sockets) do - s:close() - end - return nil, -4, "Encryption requested, but no TLS context given" - end - - nixio.syslog("info", "Invoking daemon factory for " .. config[".name"]) - local handler, err = config.slave.module.factory(publisher, config) - if not handler then - for _, s in ipairs(sockets) do - s:close() - end - return nil, -3, err - else - local pollin = nixio.poll_flags("in") - for _, s in ipairs(sockets) do - server.register_pollfd({ - fd = s, - events = pollin, - revents = 0, - handler = accept, - accept = handler, - config = config, - publisher = publisher, - tls = tls - }) - end - return true - end -end - ---- Accept a new TCP connection. (server callback) --- @param polle Poll descriptor --- @return handler process id or nil, error code, error message -function accept(polle) - if not lucid.try_process() then - return false - end - local socket, host, port = polle.fd:accept() - if not socket then - return nixio.syslog("warning", "accept() failed: " .. port) - end - - socket:setblocking(true) - - local function thread() - lucid.close_pollfds() - local inst = setmetatable({ - host = host, port = port, interfaces = lucid.get_interfaces() - }, {__index = polle}) - if polle.config.encryption then - socket = polle.tls:create(socket) - if not socket:accept() then - socket:close() - return nixio.syslog("warning", "TLS handshake failed: " .. host) - end - end - - return polle.accept(socket, inst) - end - - local stat = {lucid.create_process(thread)} - socket:close() - return unpack(stat) -end - ---- Prepare a TCP server socket. --- @param family protocol family ["inetany", "inet6", "inet"] --- @param host host --- @param port port --- @param opts table of socket options --- @param backlog socket backlog --- @return socket, final socket family -function prepare_socket(family, host, port, opts, backlog) - nixio.syslog("info", "Preparing socket for port " .. port) - backlog = backlog or 1024 - family = family or "inetany" - opts = opts or {} - - local inetany = family == "inetany" - family = inetany and "inet6" or family - - local socket, code, err = nixio.socket(family, "stream") - if not socket and inetany then - family = "inet" - socket, code, err = nixio.socket(family, "stream") - end - - if not socket then - return nil, code, err - end - - for k, v in pairs(opts) do - socket:setsockopt("socket", k, v) - end - - local stat, code, err = socket:bind(host, port) - if not stat then - return nil, code, err - end - - stat, code, err = socket:listen(backlog) - if not stat then - return nil, code, err - end - - socket:setblocking(false) - - return socket, family -end - ---- Prepare a TLS server context and load keys and certificates. --- May invoke px5g to create keys and certificate on demand if available. --- @param tlskey TLS configuration identifier --- @return TLS server conext or nil -function prepare_tls(tlskey) - local tls - if nixio.tls and tlskey and cursor:get(UCINAME, tlskey) then - tls = nixio.tls("server") - - local make = cursor:get(UCINAME, tlskey, "generate") == "1" - local key = cursor:get(UCINAME, tlskey, "key") - local xtype = make and "asn1" or cursor:get(UCINAME, tlskey, "type") - local cert = cursor:get(UCINAME, tlskey, "cert") - local ciphers = cursor:get(UCINAME, tlskey, "ciphers") - - if make and (not fs.access(key) or not fs.access(cert)) then - local CN = cursor:get(UCINAME, tlskey, "CN") - local O = cursor:get(UCINAME, tlskey, "O") - local bits = 2048 - - local data = { - CN = CN or nixio.uname().nodename, - O = not O and "LuCId Keymaster" or #O > 0 and O - } - - local stat, px5g = pcall(require, "px5g") - if not stat then - return nixio.syslog("err", "Unable to load PX5G Keymaster") - end - - nixio.syslog("warning", "PX5G: Generating private key") - local rk = px5g.genkey(bits) - local keyfile = nixio.open(key, "w", 600) - if not rk or not keyfile or not keyfile:writeall(rk:asn1()) then - return nixio.syslog("err", "Unable to generate private key") - end - keyfile:close() - - nixio.syslog("warning", "PX5G: Generating self-signed certificate") - if not fs.writefile(cert, rk:create_selfsigned(data, - os.time(), os.time() + 3600 * 24 * 366 * 15)) then - return nixio.syslog("err", "Unable to generate certificate") - end - end - - if cert then - if not tls:set_cert(cert, xtype) then - nixio.syslog("err", "Unable to load certificate: " .. cert) - end - end - if key then - if not tls:set_key(key, xtype) then - nixio.syslog("err", "Unable to load private key: " .. key) - end - end - - if ciphers then - if type(ciphers) == "table" then - ciphers = table.concat(ciphers, ":") - end - tls:set_ciphers(ciphers) - end - end - return tls -end diff --git a/libs/lucid/root/etc/config/lucid b/libs/lucid/root/etc/config/lucid deleted file mode 100644 index 07c32c16c..000000000 --- a/libs/lucid/root/etc/config/lucid +++ /dev/null @@ -1,52 +0,0 @@ -config lucid main - option pollinterval 15000 - option threadlimit 10 - option daemonize 1 - option debug 0 - list supports tcpserver - list supports server - -config DirectoryPublisher webroot - option name 'Webserver Share' - option physical /www - option virtual '' - option domain '' - -config LuciWebPublisher luciweb - option name 'LuCI Webapplication' - option physical '' - option home 1 - list virtual /luci - list virtual /cgi-bin/luci - option domain '' - -config tcpserver httpd - option entrypoint "luci.lucid.http" - list supports DirectoryPublisher - list supports LuciWebPublisher - -config daemon http - option slave httpd - list address 80 - list publisher webroot - list publisher luciweb - option nokeepalive 1 - option memlimit 1572864 - option enabled 1 - -config daemon https - option slave httpd - list address 443 - list publisher webroot - list publisher luciweb - option nokeepalive 1 - option memlimit 1572864 - option enabled 1 - option tls maincert - option encryption enable - -config tls maincert - option key /etc/nixio/rsa_main.der - option cert /etc/nixio/cert_main.der - option type asn1 - option generate 1 diff --git a/libs/lucid/root/etc/init.d/lucid b/libs/lucid/root/etc/init.d/lucid deleted file mode 100755 index 1b2b04ed4..000000000 --- a/libs/lucid/root/etc/init.d/lucid +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/sh /etc/rc.common -PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin -NAME=lucid -DESC="LuCId superserver" -START=49 - -test -x $DAEMON || exit 0 -set -e - -start() { - echo -n "Starting $DESC: $NAME" - lua -lluci.lucid -e 'luci.lucid.start()' - echo "." -} - -stop() { - echo -n "Stopping $DESC: $NAME" - lua -lluci.lucid -e 'luci.lucid.stop()' - echo "." -} - -restart() { - # echo -n "Restarting $DESC: $NAME... " - # start-stop-daemon -K -s HUP -q -x $DAEMON - # echo "done." - stop - sleep 3 - start -} - -reload() { - # - # If the daemon can reload its config files on the fly - # for example by sending it SIGHUP, do it here. - # - # If the daemon responds to changes in its config file - # directly anyway, make this a do-nothing entry. - # - # echo -n "Reloading $DESC configuration... " - # start-stop-daemon -K -s 1 -q -x $DAEMON - # echo "done." - restart -} |