Commits

Daniel Poelzleithner committed fa0af8f

ported hand written lua wrappers to new infrastructure
more work on node setup

Comments (0)

Files changed (5)

.pida-metadata/project.json

 {
-  "targets":[],
+  "targets":[
+    {
+      "name":"make",
+      "actions":[
+        {
+          "type":"external",
+          "options":{},
+          "value":""
+        }
+      ]
+    }
+  ],
   "options":{
     "name":"dssd"
   }
     option 'wait_timeout' 3600
     option 'merge_strategy' 'network_plus_local'
 
-config 'mapping' 'mapping'
-    option 'dns' '00:5 01:2'
-    option 'conf' '00:10 01:4'
-    option 'files' '02:3'
+config 'mapping' 'dns'
+    option 'server' 'basic'
+	option 'basic' 'basic'
+    list mappings '00:5'
+    list mappings '01:2'
+
+config 'mapping' 'conf'
+    list mappings '00:10'
+    list mappings '01:4'
+
+config 'mapping' 'files'
+    list mappings '02:3'
+
+config 'mapping' 'berlin_files'
+    option 'city' '000001'
+    list mappings '02:3'
 
 config 'backend' 'static'
-    option enabled 'on'
+    option 'enabled' 'on'
     list 'ip4' '127.0.0.1:2344'
 
 config 'plugin' 'dns'
-    option enabled 'on'
-    option port '54'
+    option 'enabled' 'on'
+    option 'port' '54'
+
 #include <dnet/packet.h>
 #include <dnet/interface.h>
 
+#include "dssd.h"
+
 #define DNET_CONF_COMMENT	'#'
 #define DNET_CONF_DELIM		'='
 #define DNET_CONF_ADDR_DELIM	':'
 	return 0;
 }
 
+void dssd_log(int mask, char *format, ...) {
+        char *buffer = malloc(301);
+        va_list args;
+
+        va_start(args, format);
+        vsnprintf(buffer, 300, format, args);
+        va_end(args);
+        dnet_common_log(dssd_log_priv, mask, buffer);
+        free(buffer);
+}
+
+
 void dnet_common_log(void *priv, uint32_t mask, const char *msg)
 {
 	char str[64];
 #include <lualib.h>
 #include <lauxlib.h>
 #include <pthread.h>
+#include <string.h>
+#include <netinet/in.h>
 
+#include <lauxlib.h>
 
-static int dssd_add_node(lua_State *L)
+/*
+#include "dnet/core.h"
+#include "dnet/packet.h"
+#include "dnet/interface.h"
+*/
+#include "dnet/packet.h"
+#include "dnet/interface.h"
+#include "dssd.h"
+
+#define DNET_META "dnet"
+#define DNET_META_CONFIG "dnet_config"
+#define DNET_META_NODE "dnet_node"
+//#define DNET_META_IO "dnet_io_control"
+
+#define DNET_PUSH_CONSTANT(x) \
+	lua_pushinteger(L, x); \
+	lua_setfield(L, -2, #x);
+
+#define DNET_PUSH_CONSTANT2(x,n) \
+	lua_pushinteger(L, x); \
+	lua_setfield(L, -2, "n");
+
+
+//typedef struct dnet_config dnet_config;
+//typedef struct dnet_node dnet_node;
+
+typedef unsigned char dnet_id[DNET_ID_SIZE];
+
+static struct dnet_config to_dnet_config (lua_State *L, int index)
+{
+  struct dnet_config *dc = (struct dnet_config *)lua_touserdata(L, index);
+  if (dc == NULL) luaL_typerror(L, index, DNET_META_CONFIG);
+  return *dc;
+}
+
+static struct dnet_config *check_dnet_config (lua_State *L, int index)
+{
+  struct dnet_config *dcp;
+  luaL_checktype(L, index, LUA_TUSERDATA);
+  dcp = (struct dnet_config*)luaL_checkudata(L, index, DNET_META_CONFIG);
+
+  if (dcp == NULL) luaL_typerror(L, index, DNET_META_CONFIG);
+  return dcp;
+}
+
+
+static struct dnet_node *check_dnet_node (lua_State *L, int index)
+{
+  struct dnet_node *dcp;
+  luaL_checktype(L, index, LUA_TUSERDATA);
+  dcp = (struct dnet_node *)luaL_checkudata(L, index, DNET_META_NODE);
+
+  if (dcp == NULL) luaL_typerror(L, index, DNET_META_NODE);
+  return dcp;
+}
+
+const char bin2hex_map[16] = {
+'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+};
+
+static int bin2hex(lua_State *L) {
+	size_t len, lenout, i;
+	luaL_checktype(L, -1, LUA_TSTRING);
+	const unsigned char *data = (unsigned char*)lua_tolstring(L, -1, &len);
+
+	if (len == 0) {
+		lua_pushvalue(L, -1);
+		return 1;
+	}
+
+	lenout = len * 2;
+	luaL_argcheck(L, lenout > len, 1, "size overflow");
+
+	char *out = malloc(lenout);
+	if (!out) {
+		return luaL_error(L, "out of mem");
+	}
+
+	for (i=0; i < len; i++) {
+		out[2*i]   = bin2hex_map[(data[i] & 0xf0) >> 4];
+		out[2*i+1] = bin2hex_map[(data[i] & 0x0f)];
+	}
+
+	lua_pushlstring(L, out, lenout);
+	free(out);
+
+	return 1;
+}
+
+static int hex2bin(lua_State *L) {
+	size_t len, lenout, i;
+	const char *data = luaL_checklstring(L, -1, &len);
+
+	if (len == 0) {
+		lua_pushvalue(L, -1);
+		return 1;
+	} else if (len % 2) {
+        return luaL_error(L, "wrong value");
+	}
+
+	lenout = len / 2;
+	char *out = malloc(lenout);
+	if (!out) {
+		return luaL_error(L, "out of mem");
+	}
+
+	for (i=0; i < lenout; i++) {
+		char c = data[2*i];
+		if (c >= '0' && c <= '9') {
+			out[i] = (c - '0') << 4;
+		} else if (c >= 'a' && c <= 'f') {
+			out[i] = (c - 'a' + 10) << 4;
+		} else if (data[2*i] >= 'A' && c <= 'F') {
+			out[i] = (c - 'A' + 10) << 4;
+		} else {
+			free(out);
+            return luaL_error(L, "wrong value");
+		}
+
+		c = data[2*i+1];
+		if (c >= '0' && c <= '9') {
+			out[i] += c - '0';
+		} else if (c >= 'a' && c <= 'f') {
+			out[i] += c - 'a' + 10;
+		} else if (c >= 'A' && c <= 'F') {
+			out[i] += c - 'A' + 10;
+		} else {
+			free(out);
+            return luaL_error(L, "wrong value");
+		}
+	}
+
+	lua_pushlstring(L, out, lenout);
+	free(out);
+
+	return 1;
+}
+
+
+#if DEBUG
+
+static char *bin2hexs(const char *str, size_t len, size_t max) {
+	size_t lenout, i;
+    lenout = (len * 2) + 1;
+    if (len > max) {
+        lenout = (2 * max)+1;
+        len = max;
+    }
+	if (len == 0) {
+		return NULL;
+	}
+
+	char *out = malloc(lenout);
+	memset(out, 0, lenout);
+
+	for (i=0; i < len; i++) {
+		out[2*i]   = bin2hex_map[(str[i] & 0xf0) >> 4];
+		out[2*i+1] = bin2hex_map[(str[i] & 0x0f)];
+	}
+    out[lenout] = 0;
+	return out;
+}
+
+static void stackDump (lua_State *L, int hex) {
+      int i=lua_gettop(L);
+      char *dst;
+      printf(" ----------------  Stack Dump ----------------\n" );
+      while(  i > 0  ) {
+        int t = lua_type(L, i);
+        switch (t) {
+          case LUA_TSTRING:
+            if(hex)
+                dst = bin2hexs(lua_tostring(L, i), lua_objlen(L, i), 30);
+            else
+                dst = strdup(lua_tostring(L, i));
+            printf("%d: str `%s'\n", i, dst);
+            free(dst);
+          break;
+          case LUA_TBOOLEAN:
+            printf("%d: bool %s\n",i,lua_toboolean(L, i) ? "true" : "false");
+          break;
+          case LUA_TNUMBER:
+            printf("%d: num %g\n",  i, lua_tonumber(L, i));
+         break;
+         default: printf("%d: %s %s\n", i, lua_typename(L, t), lua_tostring (L, i)); break;
+        }
+       i--;
+      }
+     printf("--------------- Stack Dump Finished ---------------\n" );
+}
+
+#endif
+
+
+
+static int dnetL_config_new(lua_State *L)
 {
     // test for optional options trough tables
-    const char *addr = luaL_checkstring(L, 1);
+    struct dnet_config *dc = (struct dnet_config *)lua_newuserdata(L, sizeof(struct dnet_config));
+    memset(dc, 0, sizeof(struct dnet_config));
+    //memset(dc->id, 1, sizeof(DNET_ID_SIZE));
+    luaL_getmetatable(L, DNET_META_CONFIG);
+    lua_setmetatable(L, -2);
+    return 1;
+}
+
+
+
+const char dnet__bin2hex[16] = {
+'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+};
+
+char *id_to_hexstring(unsigned char *id[DNET_ID_SIZE]) {
+    /*
+    convert a dnet_config id into hex to be passed into
+    lua.
+    */
+    size_t i;
+    char *rv = malloc(DNET_ID_SIZE*2+1);
+    memset(rv, 0, DNET_ID_SIZE*2+1);
+    for(i = 0; i < DNET_ID_SIZE; i++) {
+        rv[2*i]   = dnet__bin2hex[(*id[i] & 0xf0) >> 4];
+        rv[2*i+1] = dnet__bin2hex[(*id[i] & 0x0f)];
+    }
+    return rv;
+
+}
+
+int hexstring_to_id(char *hex, dnet_id *id) {
+    /*
+    convert a dnet_config id into hex to be passed into
+    lua.
+    */
+	size_t len, lenout, i;
+    dnet_id tmp;
     
+    //out = (dnet_id)malloc(sizeof(dnet_id));
+
+    //memset(&out, 0, sizeof(dnet_id));
+
+    len = strlen(hex);
+
+	if (len == 0) {
+		return -1;
+	} else if (len % 2) {
+        return -2;
+	} else if (len != DNET_ID_SIZE*2) {
+        return -3;
+    }
+
+	lenout = len / 2;
+
+	for (i=0; i < lenout; i++) {
+		char c = hex[2*i];
+
+		if (c >= '0' && c <= '9') {
+			tmp[i] = (c - '0') << 4;
+		} else if (c >= 'a' && c <= 'f') {
+			tmp[i] = (c - 'a' + 10) << 4;
+		} else if (c >= 'A' && c <= 'F') {
+			tmp[i] = (c - 'A' + 10) << 4;
+		} else {
+            return -4;
+		}
+
+		c = hex[2*i+1];
+		if (c >= '0' && c <= '9') {
+			tmp[i] += c - '0';
+		} else if (c >= 'a' && c <= 'f') {
+			tmp[i] += c - 'a' + 10;
+		} else if (c >= 'A' && c <= 'F') {
+			tmp[i] += c - 'A' + 10;
+		} else {
+            return -3;
+		}
+	}
+
+    memcpy(id, &tmp, sizeof(dnet_id));
+
+	return 0;
+}
+
+
+/****************************************************
+ *  dnet_node
+ ***************************************************/
+
+
+
+static int dnetL_config_create_node(lua_State *L)
+{
+    // test for optional options trough tables
+    struct dnet_config *dc = check_dnet_config(L, -1);
+    struct dnet_node *dn = (struct dnet_node *)lua_newuserdata(L, sizeof(void *));
+    //memset(dc->id, 1, sizeof(DNET_ID_SIZE));
+    luaL_getmetatable(L, DNET_META_NODE);
+    lua_setmetatable(L, -2);
+    dn = dnet_node_create(dc);
+    return 1;
+}
+
+static int dnetL_node_add_state(lua_State *L)
+{
+    // test for optional options trough tables
+    struct dnet_node *dn = check_dnet_node(L, -2);
+    struct dnet_config *dc = check_dnet_config(L, -1);
+
+    lua_pushinteger(L, dnet_add_state(dn, dc));
+    return 1;
+}
+
+static int dnetL_node_join(lua_State *L)
+{
+    // test for optional options trough tables
+    struct dnet_node *dn = check_dnet_node(L, -1);
+
+    lua_pushinteger(L, (lua_Integer)dnet_join(dn));
+    return 1;
+}
+
+
+
+/****************************************************
+ *  dnet_config
+ ***************************************************/
+
+
+static int dnetL_config_newindex(lua_State *L)
+{
+    // test for optional options trough tables
+    struct dnet_config *dc = check_dnet_config(L, -3);
+    const char *key = luaL_checkstring(L, -2);
+    int nid;
+    char *str = NULL;
+
+	if (!strcmp(key, "id")) {
+        //lua_pushstring(L, id_to_hexstring(dc.id));
+        str = (char *)luaL_checkstring(L, -1);
+        //hexstring_to_id(str, (unsigned char id[DNET_ID_SIZE])&dc)
+        if(!str)
+            return luaL_argerror(L, 1,
+                "wrong value"
+            );
+        nid = hexstring_to_id(str, &dc->id);
+        if(nid)
+            return luaL_argerror(L, 1,
+                "invalid hex string"
+            );
+        return 1;
+	} else if (!strcmp(key, "sock_type")) {
+       dc->sock_type = luaL_checkinteger (L, -1);
+	} else if (!strcmp(key, "proto")) {
+       dc->proto = luaL_checkinteger (L, -1);
+	} else if (!strcmp(key, "family")) {
+       dc->family = luaL_checkinteger (L, -1);
+	} else if (!strcmp(key, "addr")) {
+        if(lua_isnil (L, -1)) 
+            memset(&dc->addr, 0, 1);
+        else {
+            str = (char *)luaL_checkstring (L, -1);
+            if(strlen(str) > DNET_MAX_ADDRLEN)
+                return luaL_argerror(L, 1,
+                    "value to long"
+                );
+            memset(&dc->addr, 0, DNET_MAX_ADDRLEN);
+            memcpy(&dc->addr, str, strlen(str));
+        }
+	} else if (!strcmp(key, "port")) {
+        if(lua_isnil (L, -1)) 
+            memset(&dc->port, 0, DNET_MAX_PORTLEN);
+        else {
+            str = (char *)luaL_checkstring (L, -1);
+            if(strlen(str) > DNET_MAX_PORTLEN)
+                return luaL_argerror(L, 1,
+                    "value to long"
+                );
+            memset(&dc->port, 0, DNET_MAX_PORTLEN);
+            memcpy(&dc->port, str, strlen(str));
+        }
+	} else if (!strcmp(key, "wait_timeout")) {
+        dc->wait_timeout = luaL_checkinteger (L, -1);
+	} else if (!strcmp(key, "join")) {
+        dc->join = luaL_checkinteger (L, -1);
+	} else if (!strcmp(key, "log_mask")) {
+        dc->log_mask = luaL_checkinteger (L, -1);
+	} else if (!strcmp(key, "io_thread_num")) {
+        dc->io_thread_num = luaL_checkinteger (L, -1);
+	} else if (!strcmp(key, "hash_size")) {
+        dc->hash_size = luaL_checkinteger (L, -1);
+	} else if (!strcmp(key, "max_pending")) {
+        dc->max_pending = luaL_checkinteger (L, -1);
+	} else {
+		return luaL_argerror(L, 1,
+		 "supported values: id"
+		);
+	}
+
     return 0;
 }
 
+static int dnetL_config_index(lua_State *L)
+{
+    // test for optional options trough tables
+    struct dnet_config *dc = check_dnet_config(L, -2);
+    const char *key = luaL_checkstring(L, -1);
 
-static const luaL_reg dssd_meta[] = {
-  {"add_node",    dssd_add_node},
+	if (!strcmp(key, "id")) {
+        lua_pushstring(L, id_to_hexstring(&dc->id));
+	} else if (!strcmp(key, "sock_type")) {
+        lua_pushinteger(L, dc->sock_type);
+	} else if (!strcmp(key, "proto")) {
+        lua_pushinteger(L, dc->proto);
+	} else if (!strcmp(key, "family")) {
+        lua_pushinteger(L, dc->family);
+	} else if (!strcmp(key, "addr")) {
+        lua_pushstring(L, (const char *)&dc->addr);
+	} else if (!strcmp(key, "port")) {
+        lua_pushstring(L, (const char *)&dc->port);
+	} else if (!strcmp(key, "wait_timeout")) {
+        lua_pushinteger(L, dc->wait_timeout);
+	} else if (!strcmp(key, "join")) {
+        lua_pushinteger(L, dc->join);
+	} else if (!strcmp(key, "log_mask")) {
+        lua_pushinteger(L, dc->log_mask);
+	} else if (!strcmp(key, "io_thread_num")) {
+        lua_pushinteger(L, dc->io_thread_num);
+	} else if (!strcmp(key, "hash_size")) {
+        lua_pushinteger(L, dc->hash_size);
+	} else if (!strcmp(key, "max_pending")) {
+        lua_pushinteger(L, dc->max_pending);
+	} else if (!strcmp(key, "create_node")) {
+        lua_pushcfunction (L, dnetL_config_create_node);
+	} else {
+		return luaL_argerror(L, 1,
+		 "supported values: id"
+		);
+	}
+
+    return 1;
+}
+
+// 	} else if (!strcmp(key, "give_up_control")) {
+//         lua_pushcfunction (L, dnetL_config_);
+// int dnet_give_up_control(struct dnet_node *n);
+
+
+// generate print functions for objects
+#define make_dnet_str(FNC, LOG) static int FNC (lua_State *L) \
+{ \
+  lua_pushfstring(L, "%s: %p", #LOG, lua_touserdata(L, 1)); \
+  return 1; \
+}
+
+make_dnet_str(dnetL_config_tostring, struct dnet_config)
+make_dnet_str(dnetL_node_tostring, struct dnet_config)
+make_dnet_str(dnetL_io_tostring, dnet_ioctrl)
+
+#undef make_dnet_str
+
+
+static int dnetL_config_gc(lua_State *L)
+{
+    struct dnet_config *dc = check_dnet_config(L, -2);
+
+    return 0;
+}
+
+static int dnetL_node_gc(lua_State *L)
+{
+    struct dnet_node *dn = check_dnet_node(L, -1);
+    if (dn != NULL)
+        dnet_node_destroy(dn);
+    return 0;
+}
+
+/*****************************************
+ * static functions
+ *****************************************/
+
+static int dnetL_id_cmp(lua_State *L)
+{
+    
+    dnet_id id1, id2;
+    char *sid1 = (char *)luaL_checkstring(L, 1);
+    char *sid2 = (char *)luaL_checkstring(L, 2);
+
+    if(hexstring_to_id(sid1, &id1) ||
+       hexstring_to_id(sid2, &id2))
+		return luaL_argerror(L, 1,
+		 "invalid data"
+		);
+    
+    lua_pushinteger(L, dnet_id_cmp(&id1, &id2));
+    return 1;
+}
+
+
+static const luaL_reg dnetL_node_methods[] = {
+//    {"__gc", dnetL_node_gc}, FIXME: causes crashes
+    {"__tostring", dnetL_node_tostring},
+    {"add_state", dnetL_node_add_state},
+    {"join", dnetL_node_join},
+    {"destroy", dnetL_node_gc},
+    {0,0}
+};
+
+static const luaL_reg dnetL_config_methods[] = {
+//  {"create_node",    dnet_config_create_node},
+    {"__index",    dnetL_config_index},
+    {"__newindex",    dnetL_config_newindex},
+    {"__tostring", dnetL_config_tostring},
+    {"__gc",       dnetL_config_gc},
+    {0,0}
+};
+
+
+static const luaL_reg dnetL_meta[] = {
+  {"new_config",    dnetL_config_new},
+  {"id_cmp",        dnetL_id_cmp},
   {0, 0}
 };
 
 
-void *start_dssd (void *dummy)
+
+int luaopen_libdnet_lua (lua_State *L)
 {
-    lua_State *L = luaL_newstate();
 
-    luaL_newmetatable(L, "dssd");
+    luaL_newmetatable(L, DNET_META);
+
+	lua_pushvalue(L, -1);
+	lua_setfield(L, -2, "__index");
+
+	luaL_register(L, "dnet", dnetL_meta);
+
+
+    luaL_newmetatable(L, DNET_META_CONFIG);
+	luaL_register(L, NULL, dnetL_config_methods);
+//	lua_setfield(L, -2, "__index");
+	lua_pop(L, 1);
+
+
+    luaL_newmetatable(L, DNET_META_NODE);
+	luaL_register(L, NULL, dnetL_node_methods);
+    lua_pushvalue(L, -1);
+	lua_setfield(L, -2, "__index");
+    lua_pop(L, 1);
+
+	lua_pushliteral(L, VERSION);
+	lua_setfield(L, -2, "version");
+    
+	lua_pushinteger(L, DNET_ID_SIZE);
+	lua_setfield(L, -2, "id_size");
+
+
+	lua_pushinteger(L, DNET_LOG_NOTICE);
+	lua_setfield(L, -2, "LOG_NOTICE");
+	lua_pushinteger(L, DNET_LOG_INFO);
+	lua_setfield(L, -2, "LOG_INFO");
+	lua_pushinteger(L, DNET_LOG_TRANS);
+	lua_setfield(L, -2, "LOG_TRANS");
+	lua_pushinteger(L, DNET_LOG_ERROR);
+	lua_setfield(L, -2, "LOG_ERROR");
+	lua_pushinteger(L, DNET_LOG_DSA);
+	lua_setfield(L, -2, "LOG_DSA");
+
+
+    // push some usefull constants
+
+
+	lua_remove(L, -2);
+
+    //lua_remove(L, -1);
+
+	return 1;
+
+
+#if 0
+  luaL_openlib(L, DNET_META, dnet_methods, 0);  /* create methods table,
+                                                add it to the globals */
+  luaL_newmetatable(L, DNET_META);        /* create metatable for Image,
+                                         add it to the Lua registry */
+  luaL_openlib(L, 0, dnet_meta, 0);  /* fill metatable */
+
+  lua_pushliteral(L, "__index");
+  lua_pushvalue(L, -3);               /* dup methods table*/
+  lua_rawset(L, -3);                  /* metatable.__index = methods */
+  lua_pushliteral(L, "__metatable");
+  lua_pushvalue(L, -3);               /* dup methods table*/
+  lua_rawset(L, -3);                  /* hide metatable:
+                                         metatable.__metatable = methods */
+  lua_pop(L, 1);                      /* drop metatable */
+  return 1;                           /* return methods on the stack */
+#endif
+}
+
+
+void *start_lua_thread (void *ptr)
+{
+    struct lua_thread_param *param = ptr;
+    lua_State *L = param->lua_state;
+    
+    luaopen_libdnet_lua(L);
+    
+/*    luaL_newmetatable(L, "dssd");
 
 	lua_pushvalue(L, -1);
 	lua_setfield(L, -2, "__index");
 	lua_remove(L, -2);
 
     //lua_remove(L, -1);
-    luaL_dofile(L, "backends/main.lua");
-    
+*/
+    dssd_log(DNET_LOG_NOTICE, "run: %s\n", param->lua_file);
+    if(luaL_dofile(L, param->lua_file)) {
+        dssd_log(DNET_LOG_ERROR, "error running %s: %s\n", param->lua_file, 
+                 luaL_checkstring(L, -1));
+        stackDump(L, 0);
+        }
+    free(param);
 	return NULL;
 }
 
 
-pthread_t *start_lua_thread() {
+int start_lua_threads() {
     //pthread_create(pthread_t *thread, const pthread_attr_t *attr,
     //void *(*start_routine)(void*), void *arg);
-    pthread_t *tr = malloc(sizeof(pthread_t));
-    pthread_create(tr, NULL, start_dssd, NULL);
-    return tr;
+    int rv;
+	struct list_head *p;
+	struct uci_basic_config *cfg;
+	struct uci_plugins_config *plugin;
+    struct uci_backend_config *backend;
+    struct lua_thread_param *param;
+
+	list_for_each(p, &dssd_config_backend) {
+        backend = list_entry(p, struct uci_backend_config, list);
+        dssd_log(DNET_LOG_INFO, "load backend: %s\n", backend->name);
+        backend->thread = malloc(sizeof(pthread_t));
+        param = malloc(sizeof(struct lua_thread_param));
+        param->lua_state = luaL_newstate();
+        param->lua_file = strdup(backend->name);
+        rv = pthread_create(backend->thread, NULL, start_lua_thread, param);
+        if(rv)
+            dssd_fatal("can't start lua thread: %d", rv);
+    
+    }
 }
 }
 
 static int
+dssd_init_mapping(struct uci_map *map, void *section, struct uci_section *s)
+{
+	struct uci_mapping *m = section;
+
+	INIT_LIST_HEAD(&m->list);
+	m->name = s->e.name;
+	return 0;
+}
+
+static int
+dssd_add_mapping(struct uci_map *map, void *section)
+{
+	struct uci_mapping *m = section;
+    printf("add mapping %s %p\n", m->name, m->server);
+	if (m->server)
+		list_add(&m->list, &m->server->mapping);
+
+	return 0;
+}
+
+static int
 dssd_add_basic(struct uci_map *map, void *section)
 {
 	struct uci_basic_config *cfg = section;
 
 
 static struct uci_sectionmap dssd_basic_config;
+static struct uci_sectionmap dssd_mapping_config;
 //static struct uci_sectionmap dssd_plugins_config;
 
 static struct basic_optmap dssd_basic_config_options[] = {
 			.name = "thread_num",
 		}
 	},
+// 		.map = {
+// 			UCIMAP_OPTION(struct uci_network, aliases),
+// 			.type = UCIMAP_LIST | UCIMAP_SECTION,
+// 			.data.sm = &network_alias
+// 		}
+	{
+		.map = {
+			UCIMAP_OPTION(struct uci_basic_config, mappings),
+			.type = UCIMAP_LIST | UCIMAP_SECTION,
+			.data.sm = &dssd_mapping_config
+		}
+	}
 };
 
 
 };
 #endif
 
+static struct uci_optmap dssd_mapping_options[] = {
+	{
+		UCIMAP_OPTION(struct uci_mapping, server),
+        .name = "server",
+		.type = UCIMAP_SECTION,
+		.data.sm = &dssd_basic_config
+	}
+};
+
+
+static struct uci_sectionmap dssd_mapping_config = {
+	UCIMAP_SECTION(struct uci_mapping, map),
+	.type = "mapping",
+	.options = dssd_mapping_options,
+	.init = dssd_init_mapping,
+	.add = dssd_add_mapping,
+	.n_options = ARRAY_SIZE(dssd_mapping_options),
+};
+
+
 static struct uci_sectionmap dssd_basic_config = {
 	UCIMAP_SECTION(struct uci_basic_config, map),
 	.type = "basic",
 	.options_size = sizeof(struct backend_optmap)
 };
 
+
+
 /*
 static struct plugins_optmap dssd_plugin_config = {
 	UCIMAP_SECTION(struct uci_plugins_config, map),
 	&dssd_basic_config,
 	&dssd_plugin_config,
     &dssd_backends_config,
+    &dssd_mapping_config,
 };
 
 struct uci_map dssd_map = {
 	struct uci_basic_config *cfg;
 	struct uci_plugins_config *plugin;
     struct uci_backend_config *backend;
+    struct uci_mapping *mapping;
+    int i;
 
 
 	list_for_each(p, &dssd_config) {
             cfg->wait_timeout,
             0,
             cfg->thread_num);
+        printf("map: %d\n", cfg->mappings->n_items);
+		for (i = 0; i < cfg->mappings->n_items; i++) {
+			mapping = cfg->mappings->item[i].section;
+            printf("jo\n");
+			//printf("%s\n", mapping->name);
+		}
+
 	}
+    
+
 	list_for_each(p, &dssd_config_backend) {
 		backend = list_entry(p, struct uci_backend_config, list);
 		printf("Backend %s: %s\n",