Updated Branches:
  refs/heads/lua_config [created] f3830380f

First whack a lua in core.

Wraps records, ssl_multicert and remap UrlRewrite.cc stuff.


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/c2ca0dca
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/c2ca0dca
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/c2ca0dca

Branch: refs/heads/lua_config
Commit: c2ca0dca541bf98608a1ec998a7c258bffaabb29
Parents: 36db28d
Author: Theo Schlossnagle <[email protected]>
Authored: Fri Oct 18 16:58:02 2013 -0700
Committer: Theo Schlossnagle <[email protected]>
Committed: Fri Oct 18 16:58:02 2013 -0700

----------------------------------------------------------------------
 configure.ac                   |   8 +-
 iocore/net/SSLUtils.cc         |  40 +++
 proxy/Main.cc                  |   3 +
 proxy/Makefile.am              |  16 +-
 proxy/http/remap/UrlRewrite.cc | 528 ++++++++++++++++++++++++++++++++++++
 proxy/http/remap/UrlRewrite.h  |   4 +
 proxy/luaConfig.cc             | 340 +++++++++++++++++++++++
 proxy/luaConfig.h              |  92 +++++++
 8 files changed, 1023 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/c2ca0dca/configure.ac
----------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index 8023755..c8beec0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1379,6 +1379,12 @@ no)
   ;;
 esac
 
+AS_IF([ test "x${enable_lua_support}" = "xno"], [
+  AC_MSG_ERROR([lua required but not found])
+  ], [
+  ])
+
+TS_ADDTO(CPPFLAGS, [$LUA_CFLAGS])
 AC_SUBST(LUA_CFLAGS)
 AC_SUBST(LUA_LIBS)
 AC_MSG_CHECKING([whether to enable Lua support])
@@ -1389,7 +1395,7 @@ AC_MSG_RESULT([$enable_lua_support])
 # On Darwin LuaJIT requires magic link options, otherwise it will crash in 
luaL_openlibs() at startup. See
 # http://luajit.org/install.html.
 case $host_os in
-  darwin)
+  darwin*)
     if test "x${enable_lua_support}" = "xLuaJIT"; then
       LUA_LUAJIT_LDFLAGS="-Wl,-pagezero_size,10000 -Wl,-image_base,100000000"
     fi

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/c2ca0dca/iocore/net/SSLUtils.cc
----------------------------------------------------------------------
diff --git a/iocore/net/SSLUtils.cc b/iocore/net/SSLUtils.cc
index 8c4b888..f2455f4 100644
--- a/iocore/net/SSLUtils.cc
+++ b/iocore/net/SSLUtils.cc
@@ -23,6 +23,8 @@
 #include "libts.h"
 #include "I_Layout.h"
 #include "P_Net.h"
+#include "luaConfig.h"
+#include "lua.hpp"
 
 #include <openssl/err.h>
 #include <openssl/bio.h>
@@ -632,6 +634,39 @@ ssl_extract_certificate(
   return true;
 }
 
+static int
+SSLUtils_lua_ssl_store_ssl_context(lua_State *L) {
+  const SSLConfigParams * params;
+  SSLCertLookup * lookup;
+  xptr<char> dest_ip, ssl_key_name, ssl_ca_name, ssl_cert_name;
+  params = (const SSLConfigParams *) lua_touserdata(L, lua_upvalueindex(1));
+  lookup = (SSLCertLookup *) lua_touserdata(L, lua_upvalueindex(2));
+#define LUAGETF(name) do { \
+  lua_getfield(L,-1,#name); \
+  name = (char *)lua_tostring(L,1); \
+  lua_pop(L,1); \
+} while(0)
+  LUAGETF(dest_ip);
+  LUAGETF(ssl_key_name);
+  LUAGETF(ssl_ca_name);
+  LUAGETF(ssl_cert_name);
+  if(!ssl_store_ssl_context(params, lookup, dest_ip, ssl_cert_name, 
ssl_ca_name, ssl_key_name))
+    lua_pushboolean(L,0);
+  else
+    lua_pushboolean(L,1);
+  return 1;
+}
+
+void
+SSLUtils_lua_ssl_context(
+    lua_State *             L,
+    const SSLConfigParams * params,
+    SSLCertLookup *         lookup) {
+  lua_pushlightuserdata(L, (void *)params);
+  lua_pushlightuserdata(L, (void *)lookup);
+  lua_pushcclosure(L, SSLUtils_lua_ssl_store_ssl_context, 2);
+}
+
 bool
 SSLParseCertificateConfiguration(
     const SSLConfigParams * params,
@@ -702,6 +737,11 @@ SSLParseCertificateConfiguration(
     line = tokLine(NULL, &tok_state);
   }
 
+ 
+  lua_State *L = globalLuaConfig.getL(); 
+  SSLUtils_lua_ssl_context(L, params, lookup);
+  globalLuaConfig.call(L, "config_ssl", 1);
+
   // We *must* have a default context even if it can't possibly work. The 
default context is used to
   // bootstrap the SSL handshake so that we can subsequently do the SNI lookup 
to switch to the real
   // context.

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/c2ca0dca/proxy/Main.cc
----------------------------------------------------------------------
diff --git a/proxy/Main.cc b/proxy/Main.cc
index 2d34d5c..c9156d5 100644
--- a/proxy/Main.cc
+++ b/proxy/Main.cc
@@ -89,6 +89,7 @@ extern "C" int plock(int);
 #include "XmlUtils.h"
 #include "I_Tasks.h"
 #include "InkAPIInternal.h"
+#include "luaConfig.h"
 
 #include <ts/ink_cap.h>
 
@@ -363,6 +364,8 @@ initialize_process_manager()
     LibRecordsConfigInit();
     RecordsConfigOverrideFromEnvironment();
   }
+
+  luaConfigInit();
   //
   // Start up manager
   //

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/c2ca0dca/proxy/Makefile.am
----------------------------------------------------------------------
diff --git a/proxy/Makefile.am b/proxy/Makefile.am
index 2565100..34a9557 100644
--- a/proxy/Makefile.am
+++ b/proxy/Makefile.am
@@ -52,7 +52,8 @@ AM_CPPFLAGS = \
   -I$(srcdir)/api/ts \
   -I. \
   -I./api/ts \
-  -I$(top_srcdir)/lib
+  -I$(top_srcdir)/lib \
+  $(LUA_CFLAGS)
 
 noinst_HEADERS = \
   ConfigParse.h \
@@ -103,6 +104,8 @@ traffic_server_SOURCES = \
   InkXml.h \
   IPAllow.cc \
   IPAllow.h \
+  luaConfig.cc \
+  luaConfig.h \
   Main.cc \
   Main.h \
   ParentSelection.cc \
@@ -136,7 +139,7 @@ if BUILD_TESTS
     RegressionSM.cc
 endif
 
-traffic_server_LDFLAGS = @EXTRA_CXX_LDFLAGS@ @LIBTOOL_LINK_FLAGS@
+traffic_server_LDFLAGS = @LUA_LUAJIT_LDFLAGS@ @EXTRA_CXX_LDFLAGS@ 
@LIBTOOL_LINK_FLAGS@
 traffic_server_LDADD = \
   http/libhttp.a \
   http/remap/libhttp_remap.a \
@@ -161,6 +164,7 @@ traffic_server_LDADD = \
   $(top_builddir)/iocore/eventsystem/libinkevent.a \
   $(which_libts) \
   @hwloc_LIBS@ \
+  @LUA_LIBS@ \
   @LIBPCRE@ \
   @LIBSSL@ \
   @LIBTCL@ \
@@ -173,10 +177,6 @@ traffic_server_LDADD = \
   @LIBPROFILER@ \
   -lm
 
-if BUILD_LUA_SUPPORT
-traffic_server_LDFLAGS += @LUA_LUAJIT_LDFLAGS@
-endif
-
 traffic_logcat_SOURCES = \
   logcat.cc \
   signals.cc \
@@ -238,9 +238,10 @@ traffic_sac_SOURCES = \
   InkAPI.cc \
   FetchSM.cc \
   InkIOCoreAPI.cc \
+  luaConfig.cc \
   InkXml.cc
 
-traffic_sac_LDFLAGS = @EXTRA_CXX_LDFLAGS@ @LIBTOOL_LINK_FLAGS@
+traffic_sac_LDFLAGS = @LUA_LUAJIT_LDFLAGS@ @EXTRA_CXX_LDFLAGS@ 
@LIBTOOL_LINK_FLAGS@
 traffic_sac_LDADD = \
   http/libhttp.a \
   http/remap/libhttp_remap.a \
@@ -262,6 +263,7 @@ traffic_sac_LDADD = \
   $(top_builddir)/iocore/eventsystem/libinkevent.a \
   $(top_builddir)/lib/records/librecprocess.a \
   $(top_builddir)/lib/ts/libtsutil.la \
+  @LUA_LIBS@ \
   @LIBRESOLV@ @LIBPCRE@ @LIBSSL@ @LIBTCL@ \
   @LIBEXPAT@ @LIBDEMANGLE@ @LIBZ@ @LIBLZMA@ @LIBPROFILER@ -lm
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/c2ca0dca/proxy/http/remap/UrlRewrite.cc
----------------------------------------------------------------------
diff --git a/proxy/http/remap/UrlRewrite.cc b/proxy/http/remap/UrlRewrite.cc
index f88df84..442ba0c 100644
--- a/proxy/http/remap/UrlRewrite.cc
+++ b/proxy/http/remap/UrlRewrite.cc
@@ -32,6 +32,7 @@
 #include "Tokenizer.h"
 #include "api/ts/remap.h"
 #include "UrlMappingPathIndex.h"
+#include "luaConfig.h"
 
 #include "ink_string.h"
 #include "ink_cap.h"
@@ -1040,6 +1041,527 @@ UrlRewrite::_addToStore(MappingsStore &store, 
url_mapping *new_mapping, RegexMap
   return retval;
 }
 
+struct luabuilder_crutch {
+  int line; // fake line number for ordering
+  UrlRewrite *urlrewrite;
+  BUILD_TABLE_INFO *bti;
+};
+
+static int
+UrlRewrite_lua_filterstuff(lua_State *L) {
+  int startN = 0;
+  bool flg;
+  const char *func;
+  const char *filtername;
+  struct luabuilder_crutch *lbc;
+  acl_filter_rule *rp, **rpp;
+
+  lbc = (struct luabuilder_crutch *)lua_touserdata(L, lua_upvalueindex(1));
+  func = lua_tostring(L, lua_upvalueindex(2));
+
+  // we were called as a method
+  if(lua_gettop(L) > 0 && lua_isuserdata(L,1)) startN++;
+
+  if(lua_gettop(L) < (startN+1) || !lua_isstring(L,(startN+1)))
+    luaL_error(L, "filter function require a filter name");
+  filtername = lua_tostring(L,(startN+1));
+
+  if(!strcmp(func, "deletefilter")) {
+    acl_filter_rule::delete_byname(&lbc->bti->rules_list, filtername);
+    return 0;
+  }
+  else if(!strcmp(func, "activatefilter")) {
+    if ((rp = acl_filter_rule::find_byname(lbc->bti->rules_list, filtername)) 
== NULL)
+      luaL_error(L, "Undefined filter \"%s\" in directive \"%s\"", filtername, 
func);
+    acl_filter_rule::requeue_in_active_list(&lbc->bti->rules_list, rp);
+    return 0;
+  }
+  else if(!strcmp(func, "deactivatefilter")) {
+    if ((rp = acl_filter_rule::find_byname(lbc->bti->rules_list, filtername)) 
== NULL)
+      luaL_error(L, "Undefined filter \"%s\" in directive \"%s\"", filtername, 
func);
+    acl_filter_rule::requeue_in_passive_list(&lbc->bti->rules_list, rp);
+    return 0;
+  }
+  else if(!strcmp(func, "definefilter")) {
+    const char *cstr = NULL;
+    int argc = 0;
+    char *argv[256];
+    char errStrBuf[1024];
+
+    if(lua_gettop(L) != (startN+2) || !lua_istable(L,(startN+2)))
+      luaL_error(L, "Invalid arguments to UrlRewrite:definefilter");
+
+    lua_pushnil(L); /* first key */
+    while (lua_next(L, (startN+2)) != 0) {
+      char pbuf[512];
+      if(lua_istable(L,-1)) {
+         lua_pushnil(L);
+         while (lua_next(L, -2) != 0) {
+           snprintf(pbuf, sizeof(pbuf), "%s=%s", lua_tostring(L,-4), 
lua_tostring(L,-1));
+           argv[argc++] = ats_strdup(pbuf);
+           lua_pop(L,1);
+         }
+      }
+      else {
+        snprintf(pbuf, sizeof(pbuf), "%s=%s", lua_tostring(L,-2), 
lua_tostring(L,-1));
+        argv[argc++] = ats_strdup(pbuf);
+      }
+      if(argc >= 256) luaL_error(L, "too many arguments to definefilter");
+      lua_pop(L, 1);
+    }
+    if(argc == 0) luaL_error(L, "filter require arguments");
+
+    flg = ((rp = acl_filter_rule::find_byname(lbc->bti->rules_list, 
filtername)) == NULL) ? true : false;
+    // coverity[alloc_arg]
+    if ((cstr = validate_filter_args(&rp, argv, argc, errStrBuf, 
sizeof(errStrBuf))) == NULL && rp) {
+      if (flg) {                  // new filter - add to list
+        Debug("url_rewrite", "[parse_directive] new rule \"%s\" was created", 
filtername);
+        for (rpp = &lbc->bti->rules_list; *rpp; rpp = &((*rpp)->next));
+        (*rpp = rp)->name(filtername);
+      }
+      Debug("url_rewrite", "[parse_directive] %d argument(s) were added to 
rule \"%s\"", argc, filtername);
+      rp->add_argv(argc, argv);       // store string arguments for future 
processing
+    }
+    for(;argc>0;argc--) ats_free(argv[argc-1]);
+    if(cstr) luaL_error(L, "filter issue: %s", cstr);
+    return 0;
+  }
+  luaL_error(L, "filter helper encountered impossible upvalue: %s\n", func);
+  return 0;
+}
+
+int
+UrlRewrite::lua_mapstuff(lua_State *L) {
+  int startN = 0, i = 0, argc = 0, nargs;
+  char *argv[256];
+  const char *errStr;
+  char *tag = NULL;
+  struct luabuilder_crutch *lbc;
+  char errStrBuf[1024];
+  bool alarm_already = false;
+
+  // Vars to build the mapping
+  const char *fromScheme, *toScheme;
+  int fromSchemeLen, toSchemeLen;
+  const char *fromHost, *toHost;
+  int fromHostLen, toHostLen;
+  char *map_from = NULL, *map_from_start;
+  char *map_to = NULL, *map_to_start;
+  const char *tmp;              // Appease the DEC compiler
+  char *fromHost_lower = NULL;
+  char *fromHost_lower_ptr = NULL;
+  char fromHost_lower_buf[1024];
+  url_mapping *new_mapping = NULL;
+  mapping_type maptype = FORWARD_MAP;
+  referer_info *ri;
+  int origLength;
+  int length;
+  int rparse;
+
+  RegexMapping* reg_map;
+  bool is_cur_mapping_regex;
+  bool add_result;
+
+  lbc = (struct luabuilder_crutch *)lua_touserdata(L, lua_upvalueindex(1));
+  maptype = (mapping_type)lua_tointeger(L, lua_upvalueindex(2));
+  is_cur_mapping_regex = (bool)lua_toboolean(L, lua_upvalueindex(3));
+
+  // we were called as a method
+  nargs = lua_gettop(L);
+  if(nargs > 0 && lua_isuserdata(L,1)) startN++;
+
+  if(nargs < (startN+2)) luaL_error(L, "wrong number of argument to mapping");
+  if(!lua_isstring(L, (startN+1)) || !lua_isstring(L, (startN+2)))
+    luaL_error(L, "mapping requires to and from");
+
+  // bump our fake line number...
+  lbc->line++;
+
+  // process parameters
+
+  // loop through and create paramstrings
+  for(i=startN+2;i<=nargs;i++) {
+    char pbuf[512];
+    if(lua_istable(L,i)) {
+      lua_pushnil(L);  /* first key */
+      while (lua_next(L, i) != 0) {
+         if(lua_istable(L,-1)) {
+           lua_pushnil(L);
+           while (lua_next(L, -2) != 0) {
+             // internal tables use that outside table's key
+             if(lua_isboolean(L,-1) && lua_toboolean(L,-1))
+               snprintf(pbuf, sizeof(pbuf), "%s", lua_tostring(L,-4));
+             else
+               snprintf(pbuf, sizeof(pbuf), "%s=%s", lua_tostring(L,-4), 
lua_tostring(L,-1));
+             argv[argc++] = ats_strdup(pbuf);
+             lua_pop(L,1);
+             if(argc >= 256) {
+               errStr = "too many arguments to mapping";
+               goto LUA_MAP_ERROR;
+             }
+           }
+         }
+         else {
+           if(lua_isboolean(L,-1) && lua_toboolean(L,-1))
+             snprintf(pbuf, sizeof(pbuf), "%s", lua_tostring(L,-2));
+           else
+             snprintf(pbuf, sizeof(pbuf), "%s=%s", lua_tostring(L,-2), 
lua_tostring(L,-1));
+           argv[argc++] = ats_strdup(pbuf);
+         }
+         lua_pop(L, 1);
+         if(argc >= 256) {
+           errStr = "too many arguments to mapping";
+           goto LUA_MAP_ERROR;
+         }
+      }
+    }
+  }
+
+  lbc->bti->remap_optflg = check_remap_option(argv, argc); 
+  // if FORWARD_MAP and @map_with_referer is set, we need tup update
+  if(maptype == FORWARD_MAP &&
+     (lbc->bti->remap_optflg & REMAP_OPTFLG_MAP_WITH_REFERER))
+    maptype = FORWARD_MAP_REFERER;
+   
+  new_mapping = NEW(new url_mapping(lbc->line));  // use line # for rank for 
now
+
+  // apply filter rules if we have to
+  if ((errStr = process_filter_opt(new_mapping, lbc->bti, errStrBuf, 
sizeof(errStrBuf))) != NULL)
+    goto LUA_MAP_ERROR;
+
+  new_mapping->map_id = 0;
+  if ((lbc->bti->remap_optflg & REMAP_OPTFLG_MAP_ID) != 0) {
+    int idx = 0;
+    char *c;
+    int ret = check_remap_option(argv, argc, REMAP_OPTFLG_MAP_ID, &idx);
+    if (ret & REMAP_OPTFLG_MAP_ID) {
+      c = strchr(argv[idx], (int) '=');
+      new_mapping->map_id = (unsigned int) atoi(++c);
+    }
+  }
+
+  map_from = ats_strdup(lua_tostring(L,(startN+1)));
+  length = UrlWhack(map_from, &origLength);
+
+  if ((tmp = (map_from_start = map_from)) != NULL && length > 2 && tmp[length 
- 1] == '/' && tmp[length - 2] == '/') {
+    new_mapping->unique = true;
+    length -= 2;
+  }
+
+  new_mapping->fromURL.create(NULL);
+  rparse = new_mapping->fromURL.parse_no_path_component_breakdown(tmp, length);
+
+  map_from_start[origLength] = '\0';  // Unwhack
+
+  if (rparse != PARSE_DONE) {
+    errStr = "Malformed From URL";
+    goto LUA_MAP_ERROR;
+  }
+
+  map_to = ats_strdup(lua_tostring(L,(startN+2)));
+  length = UrlWhack(map_to, &origLength);
+  map_to_start = map_to;
+  tmp = map_to;
+
+  new_mapping->toUrl.create(NULL);
+  rparse = new_mapping->toUrl.parse_no_path_component_breakdown(tmp, length);
+  map_to_start[origLength] = '\0';    // Unwhack
+
+  if (rparse != PARSE_DONE) {
+    errStr = "Malformed From URL";
+    goto LUA_MAP_ERROR;
+  }
+
+  fromScheme = new_mapping->fromURL.scheme_get(&fromSchemeLen);
+  if (fromScheme == NULL || fromSchemeLen == 0) {
+    new_mapping->fromURL.scheme_set(URL_SCHEME_HTTP, URL_LEN_HTTP);
+    fromScheme = new_mapping->fromURL.scheme_get(&fromSchemeLen);
+    new_mapping->wildcard_from_scheme = true;
+  }
+  toScheme = new_mapping->toUrl.scheme_get(&toSchemeLen);
+
+  if ((fromScheme != URL_SCHEME_HTTP && fromScheme != URL_SCHEME_HTTPS &&
+       fromScheme != URL_SCHEME_FILE &&
+       fromScheme != URL_SCHEME_TUNNEL) ||
+      (toScheme != URL_SCHEME_HTTP && toScheme != URL_SCHEME_HTTPS &&
+       toScheme != URL_SCHEME_TUNNEL)) {
+    errStr = "Only http, https, and tunnel remappings are supported";
+    goto LUA_MAP_ERROR;
+  }
+
+  if(lua_isstring(L,(startN+3))) {
+    tag = ats_strdup(lua_tostring(L,(startN+3)));
+    if (maptype == FORWARD_MAP_REFERER) {
+      int j;
+      new_mapping->filter_redirect_url = ats_strdup(tag);
+      if (!strcasecmp(tag, "<default>") || !strcasecmp(tag, "default") ||
+          !strcasecmp(tag, "<default_redirect_url>") || !strcasecmp(tag, 
"default_redirect_url"))
+        new_mapping->default_redirect_url = true;
+      new_mapping->redir_chunk_list = 
redirect_tag_str::parse_format_redirect_url(tag);
+
+      j = startN+4;
+      while(lua_isstring(L,j) && j<=nargs) j++;
+      for (; j > (startN + 3); j--) {
+        char refinfo_error_buf[1024];
+        bool refinfo_error = false;
+
+        ri = NEW(new referer_info((char *) lua_tostring(L,j), &refinfo_error, 
refinfo_error_buf,
+                                  sizeof(refinfo_error_buf)));
+        if (refinfo_error) {
+          snprintf(errStrBuf, sizeof(errStrBuf), "%s Incorrect Referer regular 
expression \"%s\" - %s",
+                   modulePrefix, lua_tostring(L,j), refinfo_error_buf);
+          SignalError(errStrBuf, alarm_already);
+          delete ri;
+          ri = 0;
+        }
+
+        if (ri && ri->negative) {
+          if (ri->any) {
+            new_mapping->optional_referer = true;   /* referer header is 
optional */
+            delete ri;
+            ri = 0;
+          } else {
+            new_mapping->negative_referer = true;   /* we have negative 
referer in list */
+          }
+        }
+        if (ri) {
+          ri->next = new_mapping->referer_list;
+          new_mapping->referer_list = ri;
+        }
+      }
+    } else {
+      new_mapping->tag = ats_strdup(lua_tostring(L,(startN+3)));
+    }
+  }
+
+  fromHost = new_mapping->fromURL.host_get(&fromHostLen);
+  if (fromHost == NULL || fromHostLen <= 0) {
+    if (maptype == FORWARD_MAP || maptype == FORWARD_MAP_REFERER || maptype == 
FORWARD_MAP_WITH_RECV_PORT) {
+      if (*map_from_start != '/') {
+        errStr = "Relative remappings must begin with a /";
+        goto LUA_MAP_ERROR;
+      } else {
+        fromHost = "";
+        fromHostLen = 0;
+      }
+    } else {
+      errStr = "Remap source in reverse mappings requires a hostname";
+      goto LUA_MAP_ERROR;
+    }
+  }
+
+  toHost = new_mapping->toUrl.host_get(&toHostLen);
+  if (toHost == NULL || toHostLen <= 0) {
+    errStr = "The remap destinations require a hostname";
+    goto LUA_MAP_ERROR;
+  }
+
+  if (unlikely(fromHostLen >= (int) sizeof(fromHost_lower_buf))) {
+    fromHost_lower = (fromHost_lower_ptr = (char *)ats_malloc(fromHostLen + 
1));
+  } else {
+    fromHost_lower = &fromHost_lower_buf[0];
+  }
+  memcpy(fromHost_lower, fromHost, fromHostLen);
+  fromHost_lower[fromHostLen] = 0;
+  LowerCaseStr(fromHost_lower);
+
+  new_mapping->fromURL.host_set(fromHost_lower, fromHostLen);
+
+  reg_map = NULL;
+  if (is_cur_mapping_regex) {
+    reg_map = NEW(new RegexMapping);
+    if (!_processRegexMappingConfig(fromHost_lower, new_mapping, reg_map)) {
+      errStr = "Could not process regex mapping config line";
+      goto LUA_MAP_ERROR;
+    }
+    Debug("url_rewrite_regex", "Configured regex rule for host [%s]", 
fromHost_lower);
+  }
+
+  if ((maptype == FORWARD_MAP || maptype == FORWARD_MAP_REFERER || maptype == 
FORWARD_MAP_WITH_RECV_PORT) &&
+      fromScheme == URL_SCHEME_TUNNEL && (fromHost_lower[0]<'0' || 
fromHost_lower[0]> '9')) {
+    addrinfo* ai_records; // returned records.
+    ip_text_buffer ipb; // buffer for address string conversion.
+    if (0 == getaddrinfo(fromHost_lower, 0, 0, &ai_records)) {
+      for ( addrinfo* ai_spot = ai_records ; ai_spot ; ai_spot = 
ai_spot->ai_next) {
+        if (ats_is_ip(ai_spot->ai_addr) &&
+            !ats_is_ip_any(ai_spot->ai_addr)) {
+          url_mapping *u_mapping;
+
+          ats_ip_ntop(ai_spot->ai_addr, ipb, sizeof ipb);
+          u_mapping = NEW(new url_mapping);
+          u_mapping->fromURL.create(NULL);
+          u_mapping->fromURL.copy(&new_mapping->fromURL);
+          u_mapping->fromURL.host_set(ipb, strlen(ipb));
+          u_mapping->toUrl.create(NULL);
+          u_mapping->toUrl.copy(&new_mapping->toUrl);
+          if (lua_isstring(L,(startN+3)))
+            u_mapping->tag = ats_strdup(lua_tostring(L,(startN+3)));
+          bool insert_result = (maptype != FORWARD_MAP_WITH_RECV_PORT) ? 
+            TableInsert(forward_mappings.hash_lookup, u_mapping, ipb) :
+            TableInsert(forward_mappings_with_recv_port.hash_lookup, 
u_mapping, ipb);
+          if (!insert_result) {
+            errStr = "Unable to add mapping rule to lookup table";
+            goto LUA_MAP_ERROR;
+          }
+          (maptype != FORWARD_MAP_WITH_RECV_PORT) ? ++num_rules_forward : 
++num_rules_forward_with_recv_port;
+          SetHomePageRedirectFlag(u_mapping, u_mapping->toUrl);
+        }
+      }
+      freeaddrinfo(ai_records);
+    }
+  }
+
+  if ((lbc->bti->remap_optflg & REMAP_OPTFLG_PLUGIN) != 0 && (maptype == 
FORWARD_MAP || maptype == FORWARD_MAP_REFERER ||
+                                                              maptype == 
FORWARD_MAP_WITH_RECV_PORT)) {
+    int tok_count;
+    if ((check_remap_option(argv, argc, REMAP_OPTFLG_PLUGIN, &tok_count) & 
REMAP_OPTFLG_PLUGIN) != 0) {
+      int plugin_found_at = 0;
+      int jump_to_argc = 0;
+
+      // this loads the first plugin
+      if (load_remap_plugin(argv, argc, new_mapping, errStrBuf, 
sizeof(errStrBuf), 0, &plugin_found_at)) {
+        Debug("remap_plugin", "Remap plugin load error - %s", errStrBuf[0] ? 
errStrBuf : "Unknown error");
+        errStr = errStrBuf;
+        goto LUA_MAP_ERROR;
+      }
+      //this loads any subsequent plugins (if present)
+      while (plugin_found_at) {
+        jump_to_argc += plugin_found_at;
+        if (load_remap_plugin(argv, argc, new_mapping, errStrBuf, 
sizeof(errStrBuf), jump_to_argc, &plugin_found_at)) {
+          Debug("remap_plugin", "Remap plugin load error - %s", errStrBuf[0] ? 
errStrBuf : "Unknown error");
+          errStr = errStrBuf;
+          goto LUA_MAP_ERROR;
+        }
+      }
+    }
+  }
+
+  // Now add the mapping to appropriate container
+  add_result = false;
+  switch (maptype) {
+  case FORWARD_MAP:
+  case FORWARD_MAP_REFERER:
+    if ((add_result = _addToStore(forward_mappings, new_mapping, reg_map, 
fromHost_lower,
+                                  is_cur_mapping_regex, num_rules_forward)) == 
true) {
+      // @todo: is this applicable to regex mapping too?
+      SetHomePageRedirectFlag(new_mapping, new_mapping->toUrl);
+    }
+    break;
+  case REVERSE_MAP:
+    add_result = _addToStore(reverse_mappings, new_mapping, reg_map, 
fromHost_lower,
+                             is_cur_mapping_regex, num_rules_reverse);
+    new_mapping->homePageRedirect = false;
+    break;
+  case PERMANENT_REDIRECT:
+    add_result = _addToStore(permanent_redirects, new_mapping, reg_map, 
fromHost_lower,
+                             is_cur_mapping_regex, 
num_rules_redirect_permanent);
+    break;
+  case TEMPORARY_REDIRECT:
+    add_result = _addToStore(temporary_redirects, new_mapping, reg_map, 
fromHost_lower,
+                             is_cur_mapping_regex, 
num_rules_redirect_temporary);
+    break;
+  case FORWARD_MAP_WITH_RECV_PORT:
+    add_result = _addToStore(forward_mappings_with_recv_port, new_mapping, 
reg_map, fromHost_lower,
+                             is_cur_mapping_regex, 
num_rules_forward_with_recv_port);
+    break;
+  default:
+    // 'default' required to avoid compiler warning; unsupported map
+    // type would have been dealt with much before this
+    break;
+  }
+  if (!add_result) {
+    errStr = "Unable to add mapping rule to lookup table";
+    goto LUA_MAP_ERROR;
+  }
+
+  fromHost_lower_ptr = (char *)ats_free_null(fromHost_lower_ptr);
+
+  errStr = NULL;
+ LUA_MAP_ERROR:
+  if(map_from) ats_free(map_from);
+  if(map_to) ats_free(map_to);
+  if(tag) ats_free(tag);
+  for(;argc>0;argc--) ats_free(argv[argc-1]);
+  if(errStr) luaL_error(L, errStr);
+  return 0;
+}
+
+static int
+UrlRewrite_lua_mapstuff(lua_State *L) {
+  struct luabuilder_crutch *lbc;
+  lbc = (struct luabuilder_crutch *)lua_touserdata(L, lua_upvalueindex(1));
+  return lbc->urlrewrite->lua_mapstuff(L);
+}
+
+static int
+UrlRewrite_lua_index_func(lua_State *L) {
+  bool is_cur_mapping_regex;
+  bool should_domap;
+  mapping_type maptype = FORWARD_MAP;
+  const char *func;
+  const char *mapfunc;
+  struct luabuilder_crutch *lbc;
+  lbc = (struct luabuilder_crutch *)lua_touserdata(L,1);
+  func = lua_tostring(L,2);
+  if(!strcmp(func,"definefilter") ||
+     !strcmp(func,"deletefilter") ||
+     !strcmp(func,"activatefilter") ||
+     !strcmp(func,"deactivatefilter")) {
+    lua_pushlightuserdata(L, lbc);
+    lua_pushstring(L, func);
+    lua_pushcclosure(L, UrlRewrite_lua_filterstuff, 2);
+    return 1;
+  }
+
+  mapfunc = func;
+  should_domap = true;
+  is_cur_mapping_regex = (strncasecmp("regex_", mapfunc, 6) == 0);
+  if(is_cur_mapping_regex) mapfunc += 6;
+  if (!strcasecmp("reverse_map", mapfunc)) maptype = REVERSE_MAP;
+  else if (!strcasecmp("map", mapfunc)) maptype = FORWARD_MAP; // update late 
for optflg
+  else if (!strcasecmp("redirect", mapfunc)) maptype = PERMANENT_REDIRECT;
+  else if (!strcasecmp("redirect_temporary", mapfunc)) maptype = 
TEMPORARY_REDIRECT;
+  else if (!strcasecmp("map_with_referer", mapfunc)) maptype = 
FORWARD_MAP_REFERER;
+  else if (!strcasecmp("map_with_recv_port", mapfunc)) maptype = 
FORWARD_MAP_WITH_RECV_PORT;
+  else if (is_cur_mapping_regex) luaL_error(L, "ats.UrlRewite doen't have a 
method '%s'", mapfunc);
+  else should_domap = false;
+
+  if(should_domap) {
+    lua_pushlightuserdata(L, lbc);
+    lua_pushinteger(L, maptype);
+    lua_pushboolean(L, is_cur_mapping_regex);
+    lua_pushcclosure(L, UrlRewrite_lua_mapstuff, 3);
+    return 1;
+  }
+
+  luaL_error(L, "ats.UrlRewite doen't have a method '%s'", func);
+  return 0;
+}
+
+void UrlRewrite::luaopen(lua_State *L) {
+  luaL_newmetatable(L, "ats.UrlRewrite");
+  lua_pushcclosure(L, UrlRewrite_lua_index_func, 0);
+  lua_setfield(L, -2, "__index");
+}
+/**
+  Runs lua to finiah building
+
+  @return zero on success and non-zero on failure.
+
+*/
+int
+UrlRewrite::loadLua(BUILD_TABLE_INFO *bti)
+{
+  lua_State *L = globalLuaConfig.getL();
+  struct luabuilder_crutch lbc;
+  lbc.urlrewrite = this;
+  lbc.bti = bti;
+  lua_pushlightuserdata(L, (void *)&lbc);
+  luaL_getmetatable(L, "ats.UrlRewrite");
+  lua_setmetatable(L, -2);
+  return globalLuaConfig.call(L, "config_remap", 1);
+}
+
 /**
   Reads the configuration file and creates a new hash table.
 
@@ -1500,6 +2022,12 @@ UrlRewrite::BuildTable()
   clear_xstr_array(bti.argv, sizeof(bti.argv) / sizeof(char *));
   bti.paramc = (bti.argc = 0);
 
+  if(loadLua(&bti)) {
+    Warning("Could not add rules via lua");
+    SignalError("Could not add rules via lua", alarm_already);
+    return 2;
+  }
+
   // Add the mapping for backdoor urls if enabled.
   // This needs to be before the default PAC mapping for ""
   // since this is more specific

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/c2ca0dca/proxy/http/remap/UrlRewrite.h
----------------------------------------------------------------------
diff --git a/proxy/http/remap/UrlRewrite.h b/proxy/http/remap/UrlRewrite.h
index a74c4af..b76bb4e 100644
--- a/proxy/http/remap/UrlRewrite.h
+++ b/proxy/http/remap/UrlRewrite.h
@@ -26,6 +26,7 @@
 
 #include "UrlMapping.h"
 #include "HttpTransact.h"
+#include "lua.hpp"
 
 #ifdef HAVE_PCRE_PCRE_H
 #include <pcre/pcre.h>
@@ -74,8 +75,10 @@ public:
   void SetReverseFlag(int flag);
   void Print();
   bool is_valid() const { return _valid; };
+  int lua_mapstuff(lua_State *L);
 //  private:
 
+  static void luaopen(lua_State *L);
   static const int MAX_REGEX_SUBS = 10;
 
   struct RegexMapping
@@ -115,6 +118,7 @@ public:
   url_mapping *SetupPacMapping();       // manager proxy-autconfig mapping
   url_mapping *SetupBackdoorMapping();
   void PrintStore(MappingsStore &store);
+  int loadLua(BUILD_TABLE_INFO *);
 
   void DestroyStore(MappingsStore &store)
   {

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/c2ca0dca/proxy/luaConfig.cc
----------------------------------------------------------------------
diff --git a/proxy/luaConfig.cc b/proxy/luaConfig.cc
new file mode 100644
index 0000000..626b40d
--- /dev/null
+++ b/proxy/luaConfig.cc
@@ -0,0 +1,340 @@
+/** @file
+
+  A brief file description
+
+  @section license License
+
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you 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
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+ */
+
+#include "libts.h"
+#include "luaConfig.h"
+#include "I_Layout.h"
+#include "I_RecDefs.h"
+#include "I_RecCore.h"
+#include "P_RecCore.h"
+#include "UrlRewrite.h"
+
+luaConfig globalLuaConfig("tsconfig");
+
+static int
+tsrec_newindex_func(lua_State *L) {
+  luaL_error(L, "cannot assign to ats.config_t, invoked instead");
+  return 0;
+}
+
+static int
+tsrec_index_func(lua_State *L) {
+  const char *opath = NULL;
+  char path[1024];
+  assert(lua_gettop(L) == 2);
+  if(!strcmp(lua_tostring(L,2),"_path")) return 0;
+  lua_pushvalue(L,2);
+  lua_rawget(L,1);
+  if(lua_istable(L,-1)) return 1;
+  lua_pop(L,1);
+
+  lua_pushstring(L,"_path");
+  lua_rawget(L,1);
+  if(lua_isstring(L,-1)) opath = lua_tostring(L,-1);
+  if(opath == NULL) snprintf(path, sizeof(path), "%s", lua_tostring(L,2));
+  else snprintf(path, sizeof(path), "%s.%s", opath, lua_tostring(L,2));
+
+  lua_newtable(L);
+  lua_pushstring(L, path);
+  lua_setfield(L, -2, "_path");
+
+  luaL_getmetatable(L, "ats.config_t");
+  lua_setmetatable(L, -2);
+
+  lua_pushvalue(L,2); /* requested name */
+  lua_pushvalue(L,-2);
+  lua_rawset(L,1);
+  return 1;
+}
+
+static int
+tsrec_next_record(lua_State *L) {
+  RecRecord *r = NULL;
+  int *idx, i, num_records, upidx;
+  upidx = lua_upvalueindex(1);
+  idx = (int *)lua_touserdata(L,upidx);
+  i = *idx;
+
+  ink_mutex_acquire(&g_rec_config_lock);
+
+  num_records = g_num_records;
+  for (; i < num_records; i++) {
+    r = &(g_records[i]);
+    if (REC_TYPE_IS_CONFIG(r->rec_type))
+      break;
+    r = NULL;
+  }
+  if(r != NULL) rec_mutex_acquire(&(r->lock));
+  ink_mutex_release(&g_rec_config_lock);
+  *idx = i+1;
+
+  if(r != NULL) {
+    lua_newtable(L);
+    lua_pushstring(L, r->name);
+    lua_setfield(L, -2, "_path");
+  
+    luaL_getmetatable(L, "ats.config_t");
+    lua_setmetatable(L, -2);
+    rec_mutex_release(&(r->lock));
+    return 1;
+  }
+  return 0;
+}
+
+static int
+tsrec_dispatch_method(lua_State *L, const char *bpath, const char *method) {
+  if(!strcmp(method, "name")) {
+    lua_pushstring(L, bpath);
+    return 1;
+  }
+  else if(!strcmp(method, "list")) {
+    int *idx = (int *)lua_newuserdata(L, sizeof(int));
+    *idx = 0;
+    lua_pushcclosure(L, tsrec_next_record, 1);
+    return 1;
+  }
+  luaL_error(L, "unknown method call: %s", method);
+  return 0;
+}
+
+static int
+tsrec_call_func(lua_State *L) {
+  RecT rec_type;
+  RecDataT data_type;
+  const char *opath = NULL;
+  int nargs = lua_gettop(L);
+  lua_pushstring(L,"_path");
+  lua_rawget(L,1);
+  opath = lua_tostring(L,-1);
+  lua_pop(L,1);
+
+  if(lua_istable(L,2)) {
+    const char *bpath;
+    lua_pushstring(L,"_path");
+    lua_rawget(L,2);
+    bpath = lua_tostring(L,-1);
+    if(bpath == NULL) return tsrec_dispatch_method(L,"",opath);
+    int blen = strlen(bpath);
+    lua_pop(L,1);
+    if(blen > strlen(opath) ||
+       strncmp(bpath, opath, blen) ||
+       opath[blen] != '.') {
+      luaL_error(L, "impossible method call: %s", opath + blen + 1);
+    }
+    return tsrec_dispatch_method(L,bpath,opath + blen + 1);
+  }
+
+  if(RecGetRecordType(opath, &rec_type))
+    luaL_error(L, "Could not find record type '%s'", opath);
+  if(RecGetRecordDataType(opath, &data_type))
+    luaL_error(L, "Could not find record data type '%s'", opath);
+  if(nargs == 1) {
+    /* return the value */
+    switch(data_type) {
+      case RECD_INT:
+        RecInt v_int;
+        RecGetRecordInt(opath, &v_int);
+        lua_pushinteger(L,v_int);
+        return 1;
+        break;
+      case RECD_FLOAT:
+        RecFloat v_float;
+        RecGetRecordFloat(opath, &v_float);
+        lua_pushnumber(L,v_float);
+        return 1;
+        break;
+      case RECD_STRING:
+        RecString v_string;
+        RecGetRecordString_Xmalloc(opath, &v_string);
+        lua_pushstring(L, v_string);
+        ats_free(v_string);
+        return 1;
+        break;
+      case RECD_COUNTER:
+        RecCounter v_counter;
+        RecGetRecordCounter(opath, &v_counter);
+        lua_pushinteger(L,v_counter);
+        return 1;
+        break;
+      default:
+        luaL_error(L, "Unknown type of record: %s", opath);
+        break;
+    }
+    return 0;
+  }
+
+  switch(data_type) {
+    case RECD_INT:
+      RecSetRecordInt(opath, (RecInt)luaL_checkint(L,2));
+      break;
+    case RECD_FLOAT:
+      RecSetRecordFloat(opath, (RecFloat)luaL_checknumber(L,2));
+      break;
+    case RECD_STRING:
+      RecSetRecordString(opath, (const RecString)lua_tostring(L,2));
+      break;
+    case RECD_COUNTER:
+      RecSetRecordCounter(opath, (RecCounter)luaL_checklong(L,2));
+      break;
+    default:
+      luaL_error(L, "Unknown type of record: %s", opath);
+      break;
+  }
+  return 0;
+}
+
+static int
+lua_ats_log(lua_State *L) {
+  int type = lua_tointeger(L, lua_upvalueindex(1));
+  switch(type) {
+    case 0: Error("%s", lua_tostring(L,1)); break;
+    case 1: Warning("%s", lua_tostring(L,1)); break;
+    case 2: Note("%s", lua_tostring(L,1)); break;
+    case 3: Status("%s", lua_tostring(L,1)); break;
+    case 4: Emergency("%s", lua_tostring(L,1)); break;
+    case 5: Fatal("%s", lua_tostring(L,1)); break;
+    case 6: Debug(lua_tostring(L,1), "%s", lua_tostring(L,2)); break;
+    default:
+      luaL_error(L, "unknown internal log type");
+      break;
+  }
+  return 0;
+}
+void luaopen_ats(lua_State *L) {
+  luaL_newmetatable(L, "ats.config_t");
+  lua_pushcclosure(L, tsrec_index_func, 0);
+  lua_setfield(L, -2, "__index");
+  lua_pushcclosure(L, tsrec_newindex_func, 0);
+  lua_setfield(L, -2, "__newindex");
+  lua_pushcclosure(L, tsrec_call_func, 0);
+  lua_setfield(L, -2, "__call");
+
+  lua_newtable(L);
+  lua_setglobal(L, "ats");
+  lua_getglobal(L, "ats");
+
+  /* config */
+  lua_newtable(L);
+  luaL_getmetatable(L, "ats.config_t");
+  lua_setmetatable(L, -2);
+  lua_setfield(L, -2, "config");
+ 
+  lua_newtable(L); 
+#define mkLog(id,name) do { \
+  lua_pushinteger(L,id); \
+  lua_pushcclosure(L, lua_ats_log, 1); \
+  lua_setfield(L, -2, #name); \
+} while(0)
+  mkLog(0,error);
+  mkLog(1,warning);
+  mkLog(2,note);
+  mkLog(3,status);
+  mkLog(4,emergency);
+  mkLog(5,fatal);
+  mkLog(6,debug);
+  lua_setfield(L, -2, "log");
+}
+
+void luaConfig::records() {
+  int rv;
+  lua_State *L = getL();
+  lua_getglobal(L, "tsconfig");
+  lua_getfield(L, -1, "config");
+  if(lua_isnil(L,-1)) {
+    lua_pop(L,1);
+    return;
+  }
+  rv = lua_pcall(L, 0, 1, 0);
+  if(rv != 0) {
+    ink_error("tsconfig.config() failed: %s\n", lua_tostring(L,-1));
+  }
+  lua_pop(L,1);
+}
+
+void drop_lua_state_holder(void *vls) {
+  struct luaConfigStateHolder *state_holder = (struct luaConfigStateHolder 
*)vls;
+  lua_close(state_holder->states[0]);
+  lua_close(state_holder->states[1]);
+}
+
+void luaConfig::boot() {
+  assert(state_holder.states[0] == NULL);
+  assert(state_holder.states[1] == NULL);
+  char system_config_directory[PATH_NAME_MAX + 1]; // Layout->sysconfdir
+  ink_strlcpy(system_config_directory, Layout::get()->sysconfdir, 
PATH_NAME_MAX);
+
+  char config_file_path[PATH_NAME_MAX];
+  config_file_path[0] = '\0';
+  ink_strlcpy(config_file_path, system_config_directory, 
sizeof(config_file_path));
+  ink_strlcat(config_file_path, "/?.lua", sizeof(config_file_path));
+  setL(0, open(config_file_path, config_module));
+  setL(1, open(config_file_path, config_module));
+}
+
+lua_State *luaConfig::open(const char *config_file_path, const char *module) {
+  lua_State *L = luaL_newstate();
+  if(L == NULL) {
+    printf("[TrafficServer] failed to initialized lua.\n");
+    exit(1);
+  }
+  luaL_openlibs(L);
+
+  lua_getglobal(L, "package");
+  lua_pushstring(L, config_file_path);
+  lua_setfield(L, -2, "path");
+  lua_pop(L,1);
+
+  luaopen_ats(L);
+  UrlRewrite::luaopen(L);
+  lua_getglobal(L,"require");
+  lua_pushstring(L,module);
+  if(lua_pcall(L,1,1,0) != 0) {
+    printf("[TrafficServer] failed to run lua config '%s'\n%s", 
config_file_path,
+           lua_tostring(L,-1));
+    exit(1);
+  }
+  lua_pop(L, lua_gettop(L));
+  return L;
+}
+
+int
+luaConfig::call(lua_State *L, const char *method, int nargs) {
+  lua_getglobal(L, "tsconfig");
+  lua_getfield(L, -1, method);
+  if(lua_isnil(L,-1)) {
+    lua_pop(L,2);
+    return -1;
+  }
+  lua_remove(L,-2);
+  lua_insert(L, 0 - (nargs+1));
+  if(lua_pcall(L, nargs, 0, 0) != 0) {
+    Error("lua call(%s) failed: %s\n", method, lua_tostring(L,-1));
+    return -1;
+  }
+  return 0;
+}
+
+void luaConfigInit() {
+  globalLuaConfig.boot();
+  globalLuaConfig.records();
+}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/c2ca0dca/proxy/luaConfig.h
----------------------------------------------------------------------
diff --git a/proxy/luaConfig.h b/proxy/luaConfig.h
new file mode 100644
index 0000000..28e0576
--- /dev/null
+++ b/proxy/luaConfig.h
@@ -0,0 +1,92 @@
+/** @file
+
+  A brief file description
+
+  @section license License
+
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you 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
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+ */
+
+#if !defined (_luaConfig_h_)
+#define _luaConfig_h_
+
+#include "ink_apidefs.h"
+#include "lua.hpp"
+
+/////////////////////////////////////////////////////////////
+//
+// class luaConfig
+//
+/////////////////////////////////////////////////////////////
+
+void luaConfigInit();
+void drop_lua_state_holder(void *);
+
+struct luaConfigStateHolder {
+public:
+  luaConfigStateHolder() : active(0), uses_remaining(0) {
+    states[0] = states[1] = NULL;
+  }
+  lua_State *states[2];
+  int     active;
+  int64_t uses_remaining;
+};
+
+class luaConfig
+{
+public:
+  luaConfig(const char *mod) : config_module(mod) {
+    ink_thread_key_create(&state_key, drop_lua_state_holder);
+  }
+  void boot();
+  void records();
+  inline lua_State *getL() { return getL(-1); }
+  int call(lua_State *, const char *method, int nargs);
+  inline int call(const char *method, int nargs) {
+    return call(getL(), method, nargs);
+  }
+
+private:
+  lua_State *open(const char *path, const char *module);
+  inline void setL(int which, lua_State *L) {
+    assert(which >= 0 && which < 2);
+    struct luaConfigStateHolder *state_holder;
+    state_holder = (struct luaConfigStateHolder 
*)ink_thread_getspecific(state_key);
+    if(state_holder == NULL) {
+      state_holder = new struct luaConfigStateHolder();
+      ink_thread_setspecific(state_key, (void *)state_holder);
+    }
+    state_holder->states[which] = L;
+  }
+  inline lua_State *getL(int which) {
+    assert(which >= -1 && which < 2);
+    struct luaConfigStateHolder *state_holder;
+    state_holder = (struct luaConfigStateHolder 
*)ink_thread_getspecific(state_key);
+    if(state_holder == NULL) {
+      state_holder = new struct luaConfigStateHolder();
+      ink_thread_setspecific(state_key, (void *)state_holder);
+    }
+    return state_holder->states[(which < 0) ? state_holder->active : which];
+  }
+  ink_thread_key state_key;
+  const char *config_module;
+  struct luaConfigStateHolder state_holder;
+};
+
+extern luaConfig globalLuaConfig;
+
+#endif /* _luaConfig_h_ */

Reply via email to