Repository: trafficserver
Updated Branches:
  refs/heads/master bdf84381d -> 68b4d8536


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/68b4d853/plugins/experimental/ts_lua/ts_lua_transform.c
----------------------------------------------------------------------
diff --git a/plugins/experimental/ts_lua/ts_lua_transform.c 
b/plugins/experimental/ts_lua/ts_lua_transform.c
index 3be1932..ce7db9b 100644
--- a/plugins/experimental/ts_lua/ts_lua_transform.c
+++ b/plugins/experimental/ts_lua/ts_lua_transform.c
@@ -20,22 +20,26 @@
 #include "ts_lua_util.h"
 
 
-static int ts_lua_transform_handler(TSCont contp, ts_lua_transform_ctx 
*transform_ctx);
+static int ts_lua_transform_handler(TSCont contp, ts_lua_http_transform_ctx 
*transform_ctx, TSEvent event, int n);
 
 
 int
-ts_lua_transform_entry(TSCont contp, TSEvent event, void *edata ATS_UNUSED)
+ts_lua_transform_entry(TSCont contp, TSEvent ev, void *edata)
 {
+  int n, event;
   TSVIO input_vio;
+  ts_lua_http_transform_ctx *transform_ctx;
 
-  ts_lua_transform_ctx *transform_ctx = (ts_lua_transform_ctx 
*)TSContDataGet(contp);
+  event = (int)ev;
+  transform_ctx = (ts_lua_http_transform_ctx *)TSContDataGet(contp);
 
   if (TSVConnClosedGet(contp)) {
-    TSContDestroy(contp);
-    ts_lua_destroy_transform_ctx(transform_ctx);
+    ts_lua_destroy_http_transform_ctx(transform_ctx);
     return 0;
   }
 
+  n = 0;
+
   switch (event) {
   case TS_EVENT_ERROR:
     input_vio = TSVConnWriteVIOGet(contp);
@@ -46,9 +50,12 @@ ts_lua_transform_entry(TSCont contp, TSEvent event, void 
*edata ATS_UNUSED)
     TSVConnShutdown(TSTransformOutputVConnGet(contp), 0, 1);
     break;
 
+  case TS_LUA_EVENT_COROUTINE_CONT:
+    n = (intptr_t)edata;
+
   case TS_EVENT_VCONN_WRITE_READY:
   default:
-    ts_lua_transform_handler(contp, transform_ctx);
+    ts_lua_transform_handler(contp, transform_ctx, event, n);
     break;
   }
 
@@ -56,61 +63,91 @@ ts_lua_transform_entry(TSCont contp, TSEvent event, void 
*edata ATS_UNUSED)
 }
 
 static int
-ts_lua_transform_handler(TSCont contp, ts_lua_transform_ctx *transform_ctx)
+ts_lua_transform_handler(TSCont contp, ts_lua_http_transform_ctx 
*transform_ctx, TSEvent event, int n)
 {
   TSVConn output_conn;
   TSVIO input_vio;
   TSIOBufferReader input_reader;
   TSIOBufferBlock blk;
-  int64_t towrite, blk_len, upstream_done, avail, left;
+  int64_t toread, towrite, blk_len, upstream_done, input_avail, l;
   const char *start;
   const char *res;
   size_t res_len;
-  int ret, eos;
+  int ret, eos, write_down, rc, top;
+  ts_lua_coroutine *crt;
+  ts_lua_cont_info *ci;
 
   lua_State *L;
   TSMutex mtxp;
 
-  L = transform_ctx->hctx->lua;
-  mtxp = transform_ctx->hctx->mctx->mutexp;
+  ci = &transform_ctx->cinfo;
+  crt = &ci->routine;
+
+  mtxp = crt->mctx->mutexp;
+  L = crt->lua;
 
   output_conn = TSTransformOutputVConnGet(contp);
   input_vio = TSVConnWriteVIOGet(contp);
-  input_reader = TSVIOReaderGet(input_vio);
-
-  if (!transform_ctx->output_buffer) {
-    transform_ctx->output_buffer = TSIOBufferCreate();
-    transform_ctx->output_reader = 
TSIOBufferReaderAlloc(transform_ctx->output_buffer);
-    transform_ctx->output_vio = TSVConnWrite(output_conn, contp, 
transform_ctx->output_reader, INT64_MAX);
-  }
 
   if (!TSVIOBufferGet(input_vio)) {
-    TSVIONBytesSet(transform_ctx->output_vio, transform_ctx->total);
-    TSVIOReenable(transform_ctx->output_vio);
-    return 1;
+    if (transform_ctx->output.vio) {
+      TSVIONBytesSet(transform_ctx->output.vio, transform_ctx->total);
+      TSVIOReenable(transform_ctx->output.vio);
+    }
+    return 0;
   }
 
-  if (transform_ctx->eos) {
-    return 1;
+  input_reader = TSVIOReaderGet(input_vio);
+
+  if (!transform_ctx->output.buffer) {
+    transform_ctx->output.buffer = TSIOBufferCreate();
+    transform_ctx->output.reader = 
TSIOBufferReaderAlloc(transform_ctx->output.buffer);
+
+    transform_ctx->reserved.buffer = TSIOBufferCreate();
+    transform_ctx->reserved.reader = 
TSIOBufferReaderAlloc(transform_ctx->reserved.buffer);
+
+    transform_ctx->upstream_bytes = TSVIONBytesGet(input_vio);
+    transform_ctx->downstream_bytes = INT64_MAX;
   }
 
-  left = towrite = TSVIONTodoGet(input_vio);
+  input_avail = TSIOBufferReaderAvail(input_reader);
   upstream_done = TSVIONDoneGet(input_vio);
-  avail = TSIOBufferReaderAvail(input_reader);
-  eos = 0;
+  toread = TSVIONTodoGet(input_vio);
 
-  if (left <= avail)
+  if (toread <= input_avail) { // upstream finished
     eos = 1;
+  } else {
+    eos = 0;
+  }
 
-  if (towrite > avail)
-    towrite = avail;
+  if (input_avail > 0) {
+    // move to the reserved.buffer
+    TSIOBufferCopy(transform_ctx->reserved.buffer, input_reader, input_avail, 
0);
 
-  TSMutexLock(mtxp);
+    // reset input
+    TSIOBufferReaderConsume(input_reader, input_avail);
+    TSVIONDoneSet(input_vio, upstream_done + input_avail);
+  }
 
-  blk = TSIOBufferReaderStart(input_reader);
+  write_down = 0;
+  towrite = TSIOBufferReaderAvail(transform_ctx->reserved.reader);
+
+  TSMutexLock(mtxp);
+  ts_lua_set_cont_info(L, ci);
 
   do {
-    start = TSIOBufferBlockReadStart(blk, input_reader, &blk_len);
+    if (event == TS_LUA_EVENT_COROUTINE_CONT) {
+      event = 0;
+      goto launch;
+    } else {
+      n = 2;
+    }
+
+    if (towrite == 0)
+      break;
+
+    blk = TSIOBufferReaderStart(transform_ctx->reserved.reader);
+    start = TSIOBufferBlockReadStart(blk, transform_ctx->reserved.reader, 
&blk_len);
 
     lua_pushlightuserdata(L, transform_ctx);
     lua_rawget(L, LUA_GLOBALSINDEX); /* push function */
@@ -118,54 +155,90 @@ ts_lua_transform_handler(TSCont contp, 
ts_lua_transform_ctx *transform_ctx)
     if (towrite > blk_len) {
       lua_pushlstring(L, start, (size_t)blk_len);
       towrite -= blk_len;
+      TSIOBufferReaderConsume(transform_ctx->reserved.reader, blk_len);
     } else {
       lua_pushlstring(L, start, (size_t)towrite);
+      TSIOBufferReaderConsume(transform_ctx->reserved.reader, towrite);
       towrite = 0;
     }
 
     if (!towrite && eos) {
-      lua_pushinteger(L, 1); /* second param, not finish */
+      lua_pushinteger(L, 1); /* second param, data finished */
     } else {
-      lua_pushinteger(L, 0); /* second param, not finish */
+      lua_pushinteger(L, 0); /* second param, data not finish */
     }
 
-    if (lua_pcall(L, 2, 2, 0)) {
-      TSError("lua_pcall failed: %s", lua_tostring(L, -1));
+  launch:
+    rc = lua_resume(L, n);
+    top = lua_gettop(L);
+
+    switch (rc) {
+    case LUA_YIELD: // coroutine yield
+      TSMutexUnlock(mtxp);
+      return 0;
+
+    case 0: // coroutine success
+      if (top == 2) {
+        ret = lua_tointeger(L, -1); /* 0 is not finished, 1 is finished */
+        res = lua_tolstring(L, -2, &res_len);
+      } else { // what hells code are you writing ?
+        ret = 0;
+        res = NULL;
+        res_len = 0;
+      }
+      break;
+
+    default: // coroutine failed
+      ee("lua_resume failed: %s", lua_tostring(L, -1));
+      ret = 1;
+      res = NULL;
+      res_len = 0;
+      break;
     }
 
-    ret = lua_tointeger(L, -1); /* 0 is not finished, 1 is finished */
-    res = lua_tolstring(L, -2, &res_len);
+    if (res && res_len > 0) {
+      if (!transform_ctx->output.vio) {
+        l = transform_ctx->downstream_bytes;
+        if (ret) {
+          l = res_len;
+        }
+
+        transform_ctx->output.vio = TSVConnWrite(output_conn, contp, 
transform_ctx->output.reader, l); // HttpSM go on
+      }
 
-    if (res && res_len) {
-      TSIOBufferWrite(transform_ctx->output_buffer, res, res_len);
+      TSIOBufferWrite(transform_ctx->output.buffer, res, res_len);
       transform_ctx->total += res_len;
+      write_down = 1;
     }
 
-    lua_pop(L, 2);
+    lua_pop(L, top);
 
     if (ret || (eos && !towrite)) { // EOS
       eos = 1;
       break;
     }
 
-    blk = TSIOBufferBlockNext(blk);
-
-  } while (blk && towrite > 0);
+  } while (towrite > 0);
 
   TSMutexUnlock(mtxp);
 
-  TSIOBufferReaderConsume(input_reader, avail);
-  TSVIONDoneSet(input_vio, upstream_done + avail);
+  if (eos && !transform_ctx->output.vio)
+    transform_ctx->output.vio = TSVConnWrite(output_conn, contp, 
transform_ctx->output.reader, 0);
+
+  if (write_down || eos)
+    TSVIOReenable(transform_ctx->output.vio);
 
-  if (eos) {
-    transform_ctx->eos = 1;
-    TSVIONBytesSet(transform_ctx->output_vio, transform_ctx->total);
-    TSVIOReenable(transform_ctx->output_vio);
+  if (toread > input_avail) { // upstream not finished.
+    if (eos) {
+      TSVIONBytesSet(transform_ctx->output.vio, transform_ctx->total);
+      TSContCall(TSVIOContGet(input_vio), TS_EVENT_VCONN_EOS, input_vio);
+    } else {
+      TSContCall(TSVIOContGet(input_vio), TS_EVENT_VCONN_WRITE_READY, 
input_vio);
+    }
+  } else { // upstream is finished.
+    TSVIONBytesSet(transform_ctx->output.vio, transform_ctx->total);
     TSContCall(TSVIOContGet(input_vio), TS_EVENT_VCONN_WRITE_COMPLETE, 
input_vio);
-  } else {
-    TSVIOReenable(transform_ctx->output_vio);
-    TSContCall(TSVIOContGet(input_vio), TS_EVENT_VCONN_WRITE_READY, input_vio);
   }
 
-  return 1;
+  return 0;
 }

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/68b4d853/plugins/experimental/ts_lua/ts_lua_util.c
----------------------------------------------------------------------
diff --git a/plugins/experimental/ts_lua/ts_lua_util.c 
b/plugins/experimental/ts_lua/ts_lua_util.c
index c7833c8..31bf80f 100644
--- a/plugins/experimental/ts_lua/ts_lua_util.c
+++ b/plugins/experimental/ts_lua/ts_lua_util.c
@@ -19,6 +19,7 @@
 
 #include "ts_lua_util.h"
 #include "ts_lua_remap.h"
+#include "ts_lua_constant.h"
 #include "ts_lua_client_request.h"
 #include "ts_lua_server_request.h"
 #include "ts_lua_server_response.h"
@@ -33,6 +34,8 @@
 #include "ts_lua_mgmt.h"
 #include "ts_lua_package.h"
 #include "ts_lua_stat.h"
+#include "ts_lua_fetch.h"
+#include "ts_lua_http_intercept.h"
 
 static lua_State *ts_lua_new_state();
 static void ts_lua_init_registry(lua_State *L);
@@ -261,6 +264,7 @@ ts_lua_inject_ts_api(lua_State *L)
   lua_newtable(L);
 
   ts_lua_inject_remap_api(L);
+  ts_lua_inject_constant_api(L);
 
   ts_lua_inject_client_request_api(L);
   ts_lua_inject_server_request_api(L);
@@ -273,11 +277,13 @@ ts_lua_inject_ts_api(lua_State *L)
   ts_lua_inject_hook_api(L);
 
   ts_lua_inject_http_api(L);
+  ts_lua_inject_intercept_api(L);
   ts_lua_inject_misc_api(L);
   ts_lua_inject_crypto_api(L);
   ts_lua_inject_mgmt_api(L);
   ts_lua_inject_package_api(L);
   ts_lua_inject_stat_api(L);
+  ts_lua_inject_fetch_api(L);
 
   lua_getglobal(L, "package");
   lua_getfield(L, -1, "loaded");
@@ -311,6 +317,28 @@ ts_lua_get_instance_conf(lua_State *L)
 }
 
 void
+ts_lua_set_cont_info(lua_State *L, ts_lua_cont_info *ci)
+{
+  lua_pushliteral(L, "__ts_cont_info");
+  lua_pushlightuserdata(L, ci);
+  lua_rawset(L, LUA_GLOBALSINDEX);
+}
+
+ts_lua_cont_info *
+ts_lua_get_cont_info(lua_State *L)
+{
+  ts_lua_cont_info *ci;
+
+  lua_pushliteral(L, "__ts_cont_info");
+  lua_rawget(L, LUA_GLOBALSINDEX);
+  ci = lua_touserdata(L, -1);
+
+  lua_pop(L, 1); // pop the coroutine out
+
+  return ci;
+}
+
+void
 ts_lua_set_http_ctx(lua_State *L, ts_lua_http_ctx *ctx)
 {
   lua_pushliteral(L, "__ts_http_ctx");
@@ -335,22 +363,19 @@ ts_lua_get_http_ctx(lua_State *L)
 ts_lua_http_ctx *
 ts_lua_create_http_ctx(ts_lua_main_ctx *main_ctx, ts_lua_instance_conf *conf)
 {
-  size_t i, size;
+  ts_lua_coroutine *crt;
   ts_lua_http_ctx *http_ctx;
   lua_State *L;
   lua_State *l;
 
   L = main_ctx->lua;
 
-  size = TS_LUA_MEM_ALIGN(sizeof(ts_lua_http_ctx));
-  http_ctx = TSmalloc(size);
-
-  for (i = 0; i < TS_LUA_ALIGN_COUNT(size); i++) {
-    ((void **)http_ctx)[i] = 0;
-  }
+  http_ctx = TSmalloc(sizeof(ts_lua_http_ctx));
+  memset(http_ctx, 0, sizeof(ts_lua_http_ctx));
 
-  http_ctx->lua = lua_newthread(L);
-  l = http_ctx->lua;
+  // create coroutine for http_ctx
+  crt = &http_ctx->cinfo.routine;
+  l = lua_newthread(L);
 
   lua_pushlightuserdata(L, conf);
   lua_rawget(L, LUA_REGISTRYINDEX);
@@ -366,13 +391,15 @@ ts_lua_create_http_ctx(ts_lua_main_ctx *main_ctx, 
ts_lua_instance_conf *conf)
 
   lua_replace(l, LUA_GLOBALSINDEX);
 
-  http_ctx->ref = luaL_ref(L, LUA_REGISTRYINDEX);
+  // init coroutine
+  crt->ref = luaL_ref(L, LUA_REGISTRYINDEX);
+  crt->lua = l;
+  crt->mctx = main_ctx;
 
-  http_ctx->mctx = main_ctx;
   http_ctx->instance_conf = conf;
 
-  ts_lua_set_http_ctx(http_ctx->lua, http_ctx);
-  ts_lua_create_context_table(http_ctx->lua);
+  ts_lua_set_http_ctx(l, http_ctx);
+  ts_lua_create_context_table(l);
 
   return http_ctx;
 }
@@ -381,9 +408,9 @@ ts_lua_create_http_ctx(ts_lua_main_ctx *main_ctx, 
ts_lua_instance_conf *conf)
 void
 ts_lua_destroy_http_ctx(ts_lua_http_ctx *http_ctx)
 {
-  ts_lua_main_ctx *main_ctx;
+  ts_lua_cont_info *ci;
 
-  main_ctx = http_ctx->mctx;
+  ci = &http_ctx->cinfo;
 
   if (!http_ctx->remap) {
     if (http_ctx->client_request_bufp) {
@@ -413,7 +440,7 @@ ts_lua_destroy_http_ctx(ts_lua_http_ctx *http_ctx)
     TSMBufferDestroy(http_ctx->cached_response_bufp);
   }
 
-  luaL_unref(main_ctx->lua, LUA_REGISTRYINDEX, http_ctx->ref);
+  ts_lua_release_cont_info(ci);
   TSfree(http_ctx);
 }
 
@@ -440,29 +467,40 @@ ts_lua_get_http_intercept_ctx(lua_State *L)
 }
 
 ts_lua_http_intercept_ctx *
-ts_lua_create_http_intercept_ctx(ts_lua_http_ctx *http_ctx)
+ts_lua_create_http_intercept_ctx(lua_State *L, ts_lua_http_ctx *http_ctx, int 
n)
 {
-  size_t i, size;
-  lua_State *L;
+  int i;
+  lua_State *l;
+  ts_lua_cont_info *hci;
+  ts_lua_coroutine *crt;
   ts_lua_http_intercept_ctx *ictx;
 
-  L = http_ctx->lua;
+  hci = &http_ctx->cinfo;
 
-  size = TS_LUA_MEM_ALIGN(sizeof(ts_lua_http_intercept_ctx));
-  ictx = TSmalloc(size);
+  ictx = TSmalloc(sizeof(ts_lua_http_intercept_ctx));
+  memset(ictx, 0, sizeof(ts_lua_http_intercept_ctx));
 
-  for (i = 0; i < TS_LUA_ALIGN_COUNT(size); i++) {
-    ((void **)ictx)[i] = 0;
-  }
+  ictx->hctx = http_ctx;
 
-  ictx->lua = lua_newthread(L);
+  // create lua_thread
+  l = lua_newthread(L);
 
-  ictx->ref = luaL_ref(L, LUA_REGISTRYINDEX);
+  // init the coroutine
+  crt = &ictx->cinfo.routine;
+  crt->mctx = hci->routine.mctx;
+  crt->lua = l;
+  crt->ref = luaL_ref(L, LUA_REGISTRYINDEX);
 
-  ictx->mctx = http_ctx->mctx;
-  ictx->hctx = http_ctx;
+  // Todo: replace the global, context table for crt->lua
 
-  ts_lua_set_http_intercept_ctx(ictx->lua, ictx);
+  // replicate the param
+  for (i = 0; i < n; i++) {
+    lua_pushvalue(L, i + 1);
+  }
+
+  lua_xmove(L, l, n); // move the intercept function and params to the new 
lua_thread
+
+  ts_lua_set_http_intercept_ctx(l, ictx);
 
   return ictx;
 }
@@ -470,240 +508,276 @@ ts_lua_create_http_intercept_ctx(ts_lua_http_ctx 
*http_ctx)
 void
 ts_lua_destroy_http_intercept_ctx(ts_lua_http_intercept_ctx *ictx)
 {
-  ts_lua_main_ctx *main_ctx;
-  struct ict_item *node, *snode;
+  ts_lua_cont_info *ci;
 
-  main_ctx = ictx->mctx;
+  ci = &ictx->cinfo;
 
-  if (ictx->net_vc)
+  if (ictx->net_vc) {
     TSVConnClose(ictx->net_vc);
+  }
 
   TS_LUA_RELEASE_IO_HANDLE((&ictx->input));
   TS_LUA_RELEASE_IO_HANDLE((&ictx->output));
 
-  node = ictx->ict_chain;
+  ts_lua_release_cont_info(ci);
+  TSfree(ictx);
+}
 
-  while (node) {
-    if (node->cleanup)
-      node->cleanup(node);
+void
+ts_lua_set_http_transform_ctx(lua_State *L, ts_lua_http_transform_ctx *tctx)
+{
+  lua_pushliteral(L, "__ts_http_transform_ctx");
+  lua_pushlightuserdata(L, tctx);
+  lua_rawset(L, LUA_GLOBALSINDEX);
+}
 
-    snode = node;
-    node = node->next;
+ts_lua_http_transform_ctx *
+ts_lua_get_http_transform_ctx(lua_State *L)
+{
+  ts_lua_http_transform_ctx *tctx;
 
-    TSfree(snode);
-  }
+  lua_pushliteral(L, "__ts_http_transform_ctx");
+  lua_rawget(L, LUA_GLOBALSINDEX);
+  tctx = lua_touserdata(L, -1);
 
-  luaL_unref(main_ctx->lua, LUA_REGISTRYINDEX, ictx->ref);
-  TSfree(ictx);
-  return;
+  lua_pop(L, 1); // pop the ictx out
+
+  return tctx;
+}
+
+ts_lua_http_transform_ctx *
+ts_lua_create_http_transform_ctx(ts_lua_http_ctx *http_ctx, TSVConn connp)
+{
+  lua_State *L;
+  ts_lua_cont_info *hci;
+  ts_lua_cont_info *ci;
+  ts_lua_coroutine *crt;
+  ts_lua_http_transform_ctx *transform_ctx;
+
+  hci = &http_ctx->cinfo;
+  L = hci->routine.lua;
+
+  transform_ctx = (ts_lua_http_transform_ctx 
*)TSmalloc(sizeof(ts_lua_http_transform_ctx));
+  memset(transform_ctx, 0, sizeof(ts_lua_http_transform_ctx));
+
+  transform_ctx->hctx = http_ctx;
+  TSContDataSet(connp, transform_ctx);
+
+  ci = &transform_ctx->cinfo;
+  ci->contp = connp;
+  ci->mutex = TSContMutexGet((TSCont)http_ctx->txnp);
+
+  crt = &ci->routine;
+  crt->mctx = hci->routine.mctx;
+  crt->lua = lua_newthread(L);
+  crt->ref = luaL_ref(L, LUA_REGISTRYINDEX);
+  ts_lua_set_http_transform_ctx(crt->lua, transform_ctx);
+
+  lua_pushlightuserdata(L, transform_ctx);
+  lua_pushvalue(L, 2);
+  lua_rawset(L, LUA_GLOBALSINDEX); // L[GLOBAL][transform_ctx] = transform 
handler
+
+  return transform_ctx;
 }
 
 void
-ts_lua_destroy_transform_ctx(ts_lua_transform_ctx *transform_ctx)
+ts_lua_destroy_http_transform_ctx(ts_lua_http_transform_ctx *transform_ctx)
 {
+  ts_lua_cont_info *ci;
+
   if (!transform_ctx)
     return;
 
-  if (transform_ctx->output_reader)
-    TSIOBufferReaderFree(transform_ctx->output_reader);
+  ci = &transform_ctx->cinfo;
+
+  TS_LUA_RELEASE_IO_HANDLE((&transform_ctx->output));
+  TS_LUA_RELEASE_IO_HANDLE((&transform_ctx->reserved));
 
-  if (transform_ctx->output_buffer)
-    TSIOBufferDestroy(transform_ctx->output_buffer);
+  ts_lua_release_cont_info(ci);
 
   TSfree(transform_ctx);
 }
 
 int
-ts_lua_http_cont_handler(TSCont contp, TSEvent event, void *edata)
+ts_lua_http_cont_handler(TSCont contp, TSEvent ev, void *edata)
 {
-  TSHttpTxn txnp = (TSHttpTxn)edata;
-  int ret;
-  lua_State *l;
+  TSHttpTxn txnp;
+  int event, ret, rc, n, t;
+  lua_State *L;
   ts_lua_http_ctx *http_ctx;
   ts_lua_main_ctx *main_ctx;
+  ts_lua_cont_info *ci;
+  ts_lua_coroutine *crt;
 
+  event = (int)ev;
   http_ctx = (ts_lua_http_ctx *)TSContDataGet(contp);
-  main_ctx = http_ctx->mctx;
+  ci = &http_ctx->cinfo;
+  crt = &ci->routine;
+
+  main_ctx = crt->mctx;
+  L = crt->lua;
+
+  txnp = http_ctx->txnp;
 
-  ret = 0;
-  l = http_ctx->lua;
+  rc = ret = 0;
 
   TSMutexLock(main_ctx->mutexp);
+  ts_lua_set_cont_info(L, ci);
 
   switch (event) {
   case TS_EVENT_HTTP_POST_REMAP:
 
-    lua_getglobal(l, TS_LUA_FUNCTION_POST_REMAP);
+    lua_getglobal(L, TS_LUA_FUNCTION_POST_REMAP);
 
-    if (lua_type(l, -1) == LUA_TFUNCTION) {
-      if (lua_pcall(l, 0, 1, 0)) {
-        TSError("lua_pcall failed: %s", lua_tostring(l, -1));
-      }
-
-      ret = lua_tointeger(l, -1);
+    if (lua_type(L, -1) == LUA_TFUNCTION) {
+      ret = lua_resume(L, 0);
     }
 
     break;
 
   case TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE:
 
-    lua_getglobal(l, TS_LUA_FUNCTION_CACHE_LOOKUP_COMPLETE);
+    lua_getglobal(L, TS_LUA_FUNCTION_CACHE_LOOKUP_COMPLETE);
 
-    if (lua_type(l, -1) == LUA_TFUNCTION) {
-      if (lua_pcall(l, 0, 1, 0)) {
-        TSError("lua_pcall failed: %s", lua_tostring(l, -1));
-      }
-
-      ret = lua_tointeger(l, -1);
+    if (lua_type(L, -1) == LUA_TFUNCTION) {
+      ret = lua_resume(L, 0);
     }
 
     break;
 
   case TS_EVENT_HTTP_SEND_REQUEST_HDR:
 
-    lua_getglobal(l, TS_LUA_FUNCTION_SEND_REQUEST);
+    lua_getglobal(L, TS_LUA_FUNCTION_SEND_REQUEST);
 
-    if (lua_type(l, -1) == LUA_TFUNCTION) {
-      if (lua_pcall(l, 0, 1, 0)) {
-        TSError("lua_pcall failed: %s", lua_tostring(l, -1));
-      }
-
-      ret = lua_tointeger(l, -1);
+    if (lua_type(L, -1) == LUA_TFUNCTION) {
+      ret = lua_resume(L, 0);
     }
 
     break;
 
   case TS_EVENT_HTTP_READ_RESPONSE_HDR:
 
-    lua_getglobal(l, TS_LUA_FUNCTION_READ_RESPONSE);
+    lua_getglobal(L, TS_LUA_FUNCTION_READ_RESPONSE);
 
-    if (lua_type(l, -1) == LUA_TFUNCTION) {
-      if (lua_pcall(l, 0, 1, 0)) {
-        TSError("lua_pcall failed: %s", lua_tostring(l, -1));
-      }
-
-      ret = lua_tointeger(l, -1);
+    if (lua_type(L, -1) == LUA_TFUNCTION) {
+      ret = lua_resume(L, 0);
     }
 
     break;
 
   case TS_EVENT_HTTP_SEND_RESPONSE_HDR:
 
-    lua_getglobal(l, TS_LUA_FUNCTION_SEND_RESPONSE);
+    lua_getglobal(L, TS_LUA_FUNCTION_SEND_RESPONSE);
 
-    if (lua_type(l, -1) == LUA_TFUNCTION) {
-      if (lua_pcall(l, 0, 1, 0)) {
-        TSError("lua_pcall failed: %s", lua_tostring(l, -1));
-      }
-
-      ret = lua_tointeger(l, -1);
+    if (lua_type(L, -1) == LUA_TFUNCTION) {
+      ret = lua_resume(L, 0);
     }
 
     break;
 
   case TS_EVENT_HTTP_READ_REQUEST_HDR:
 
-    lua_getglobal(l, TS_LUA_FUNCTION_READ_REQUEST);
-    if (lua_type(l, -1) == LUA_TFUNCTION) {
-      if (lua_pcall(l, 0, 1, 0)) {
-        TSError("lua_pcall failed: %s", lua_tostring(l, -1));
-      }
-
-      ret = lua_tointeger(l, -1);
+    lua_getglobal(L, TS_LUA_FUNCTION_READ_REQUEST);
+    if (lua_type(L, -1) == LUA_TFUNCTION) {
+      ret = lua_resume(L, 0);
     }
 
     break;
 
   case TS_EVENT_HTTP_TXN_START:
 
-    lua_getglobal(l, TS_LUA_FUNCTION_TXN_START);
-    if (lua_type(l, -1) == LUA_TFUNCTION) {
-      if (lua_pcall(l, 0, 1, 0)) {
-        TSError("lua_pcall failed: %s", lua_tostring(l, -1));
-      }
-
-      ret = lua_tointeger(l, -1);
+    lua_getglobal(L, TS_LUA_FUNCTION_TXN_START);
+    if (lua_type(L, -1) == LUA_TFUNCTION) {
+      ret = lua_resume(L, 0);
     }
 
     break;
 
   case TS_EVENT_HTTP_PRE_REMAP:
 
-    lua_getglobal(l, TS_LUA_FUNCTION_PRE_REMAP);
-    if (lua_type(l, -1) == LUA_TFUNCTION) {
-      if (lua_pcall(l, 0, 1, 0)) {
-        TSError("lua_pcall failed: %s", lua_tostring(l, -1));
-      }
-
-      ret = lua_tointeger(l, -1);
+    lua_getglobal(L, TS_LUA_FUNCTION_PRE_REMAP);
+    if (lua_type(L, -1) == LUA_TFUNCTION) {
+      ret = lua_resume(L, 0);
     }
 
     break;
 
   case TS_EVENT_HTTP_OS_DNS:
 
-    lua_getglobal(l, TS_LUA_FUNCTION_OS_DNS);
-    if (lua_type(l, -1) == LUA_TFUNCTION) {
-      if (lua_pcall(l, 0, 1, 0)) {
-        TSError("lua_pcall failed: %s", lua_tostring(l, -1));
-      }
-
-      ret = lua_tointeger(l, -1);
+    lua_getglobal(L, TS_LUA_FUNCTION_OS_DNS);
+    if (lua_type(L, -1) == LUA_TFUNCTION) {
+      ret = lua_resume(L, 0);
     }
 
     break;
 
   case TS_EVENT_HTTP_SELECT_ALT:
 
-    lua_getglobal(l, TS_LUA_FUNCTION_SELECT_ALT);
-    if (lua_type(l, -1) == LUA_TFUNCTION) {
-      if (lua_pcall(l, 0, 1, 0)) {
-        TSError("lua_pcall failed: %s", lua_tostring(l, -1));
-      }
-
-      ret = lua_tointeger(l, -1);
+    lua_getglobal(L, TS_LUA_FUNCTION_SELECT_ALT);
+    if (lua_type(L, -1) == LUA_TFUNCTION) {
+      ret = lua_resume(L, 0);
     }
 
     break;
 
   case TS_EVENT_HTTP_READ_CACHE_HDR:
 
-    lua_getglobal(l, TS_LUA_FUNCTION_READ_CACHE);
-    if (lua_type(l, -1) == LUA_TFUNCTION) {
-      if (lua_pcall(l, 0, 1, 0)) {
-        TSError("lua_pcall failed: %s", lua_tostring(l, -1));
-      }
-
-      ret = lua_tointeger(l, -1);
+    lua_getglobal(L, TS_LUA_FUNCTION_READ_CACHE);
+    if (lua_type(L, -1) == LUA_TFUNCTION) {
+      ret = lua_resume(L, 0);
     }
 
     break;
 
   case TS_EVENT_HTTP_TXN_CLOSE:
-    lua_getglobal(l, TS_LUA_FUNCTION_TXN_CLOSE);
-    if (lua_type(l, -1) == LUA_TFUNCTION) {
-      if (lua_pcall(l, 0, 1, 0)) {
-        TSError("lua_pcall failed: %s", lua_tostring(l, -1));
+    lua_getglobal(L, TS_LUA_FUNCTION_TXN_CLOSE);
+    if (lua_type(L, -1) == LUA_TFUNCTION) {
+      if (lua_pcall(L, 0, 1, 0)) {
+        TSError("lua_pcall failed: %s", lua_tostring(L, -1));
       }
-
-      ret = lua_tointeger(l, -1);
     }
 
     ts_lua_destroy_http_ctx(http_ctx);
-    TSContDestroy(contp);
     break;
 
+  case TS_LUA_EVENT_COROUTINE_CONT:
+    n = (intptr_t)edata;
+    ret = lua_resume(L, n);
+
   default:
     break;
   }
 
+  switch (ret) {
+  case 0: // coroutine succeed
+    t = lua_gettop(L);
+    if (t > 0) {
+      rc = lua_tointeger(L, -1);
+      lua_pop(L, 1);
+    }
+    break;
+
+  case LUA_YIELD: // coroutine yield
+    rc = 1;
+    break;
+
+  default: // coroutine failed
+    ee("lua_resume failed: %s", lua_tostring(L, -1));
+    rc = -1;
+    lua_pop(L, 1);
+    break;
+  }
+
   TSMutexUnlock(main_ctx->mutexp);
 
-  if (ret) {
+  if (rc == 0) {
+    TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
+
+  } else if (rc < 0) {
     TSHttpTxnReenable(txnp, TS_EVENT_HTTP_ERROR);
 
   } else {
-    TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
+    // wait for async
   }
 
   return 0;

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/68b4d853/plugins/experimental/ts_lua/ts_lua_util.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ts_lua/ts_lua_util.h 
b/plugins/experimental/ts_lua/ts_lua_util.h
index c2b259c..d8a003b 100644
--- a/plugins/experimental/ts_lua/ts_lua_util.h
+++ b/plugins/experimental/ts_lua/ts_lua_util.h
@@ -36,15 +36,21 @@ int ts_lua_del_instance(ts_lua_instance_conf *conf);
 void ts_lua_set_instance_conf(lua_State *L, ts_lua_instance_conf *conf);
 ts_lua_instance_conf *ts_lua_get_instance_conf(lua_State *L);
 
+void ts_lua_set_cont_info(lua_State *L, ts_lua_cont_info *ci);
+ts_lua_cont_info *ts_lua_get_cont_info(lua_State *L);
+
 void ts_lua_set_http_ctx(lua_State *L, ts_lua_http_ctx *ctx);
 ts_lua_http_ctx *ts_lua_get_http_ctx(lua_State *L);
 
 ts_lua_http_ctx *ts_lua_create_http_ctx(ts_lua_main_ctx *mctx, 
ts_lua_instance_conf *conf);
 void ts_lua_destroy_http_ctx(ts_lua_http_ctx *http_ctx);
 
-void ts_lua_destroy_transform_ctx(ts_lua_transform_ctx *transform_ctx);
+ts_lua_http_transform_ctx *ts_lua_create_http_transform_ctx(ts_lua_http_ctx 
*http_ctx, TSVConn connp);
+void ts_lua_destroy_http_transform_ctx(ts_lua_http_transform_ctx 
*transform_ctx);
+void ts_lua_set_http_transform_ctx(lua_State *L, ts_lua_http_transform_ctx 
*tctx);
+ts_lua_http_transform_ctx *ts_lua_get_http_transform_ctx(lua_State *L);
 
-ts_lua_http_intercept_ctx *ts_lua_create_http_intercept_ctx(ts_lua_http_ctx 
*http_ctx);
+ts_lua_http_intercept_ctx *ts_lua_create_http_intercept_ctx(lua_State *L, 
ts_lua_http_ctx *http_ctx, int n);
 ts_lua_http_intercept_ctx *ts_lua_get_http_intercept_ctx(lua_State *L);
 void ts_lua_destroy_http_intercept_ctx(ts_lua_http_intercept_ctx *ictx);
 

Reply via email to