Beispiel #1
0
static int
noit_lua_module_onload(mtev_image_t *img) {
  int rv;
  lua_State *L;
  lua_module_closure_t *lmc;
  struct module_conf *mc;

  mc = mtev_image_get_userdata(img);

  lmc = lmc_tls_get(img);
  L = lmc->lua_state;
  if(!L) return -1;
  lua_getglobal(L, "require");
  lua_pushstring(L, mc->object);
  rv = lua_pcall(L, 1, 1, 0);
  if(rv) {
    int i;
    mtevL(nlerr, "lua: %s.onload failed\n", mc->object);
    i = lua_gettop(L);
    if(i>0) {
      if(lua_isstring(L, i)) {
        const char *err;
        size_t len;
        err = lua_tolstring(L, i, &len);
        mtevL(nlerr, "lua: %s\n", err);
      }
    }
    lua_pop(L,i);
    return -1;
  }
  lua_pop(L, lua_gettop(L));

  mtev_lua_pushmodule(L, mc->object);
  if(lua_isnil(L, -1)) {
    lua_pop(L, 1);
    mtevL(nlerr, "lua: no such object %s\n", mc->object);
    return -1;
  }
  lua_getfield(L, -1, "onload");
  lua_remove(L, -2);
  if(!lua_isfunction(L, -1)) {
    lua_pop(L, 1);
    /* No onload */
    return 0;
  }
  noit_lua_setup_module(L, (noit_module_t *)img);
  lua_pcall(L, 1, 1, 0);
  if(lua_isnumber(L, -1)) {
    int rv;
    rv = lua_tointeger(L, -1);
    lua_pop(L, 1);
    return rv;
  }
  mtevL(nlerr, "%s.onload must return a integer not %s (%s)\n", mc->object, mtev_lua_type_name(lua_type(L,-1)), lua_tostring(L,-1));
  lua_pop(L,1);
  return -1;
}
Beispiel #2
0
static int
lua_web_handler(mtev_http_rest_closure_t *restc,
                int npats, char **pats) {
  int status, base, rv, mask = 0;
  int complete = 0;
  lua_web_conf_t *conf = the_one_conf;
  lua_module_closure_t *lmc = &conf->lmc;
  mtev_lua_resume_info_t *ri;
  mtev_lua_resume_rest_info_t *ctx = NULL;
  lua_State *L;
  eventer_t conne;
  mtev_http_request *req = mtev_http_session_request(restc->http_ctx);
  mtev_http_response *res = mtev_http_session_response(restc->http_ctx);

  if(!lmc || !conf || !conf->dispatch) {
    goto boom;
  }

  if(mtev_http_request_get_upload(req, NULL) == NULL &&
     mtev_http_request_has_payload(req)) {
    const void *payload = NULL;
    int payload_len = 0;
    payload = rest_get_raw_upload(restc, &mask, &complete, &payload_len);
    if(!complete) return mask;
    mtev_http_request_set_upload(req, (char *)payload, (int64_t)payload_len,
                                 req_payload_free, NULL);
    restc->call_closure_free(restc->call_closure);
    restc->call_closure = NULL;
  }

  if(restc->call_closure == NULL) {
    ri = calloc(1, sizeof(*ri));
    ri->bound_thread = pthread_self();
    ri->context_magic = LUA_REST_INFO_MAGIC;
    ctx = ri->context_data = calloc(1, sizeof(mtev_lua_resume_rest_info_t));
    ctx->restc = restc;
    ri->lmc = lmc;
    lua_getglobal(lmc->lua_state, "mtev_coros");
    ri->coro_state = lua_newthread(lmc->lua_state);
    ri->coro_state_ref = luaL_ref(lmc->lua_state, -2);

    mtev_lua_set_resume_info(lmc->lua_state, ri);

    lua_pop(lmc->lua_state, 1); /* pops mtev_coros */

    restc->call_closure = ri;
    restc->call_closure_free = rest_lua_ctx_free;
  }
  ri = restc->call_closure;
  ctx = ri->context_data;
  ctx->httpcode = 404;

  L = ri->coro_state;

  lua_getglobal(L, "require");
  lua_pushstring(L, conf->dispatch);
  rv = lua_pcall(L, 1, 1, 0);
  if(rv) {
    int i;
    mtevL(mtev_error, "lua: require %s failed\n", conf->dispatch);
    i = lua_gettop(L);
    if(i>0) {
      if(lua_isstring(L, i)) {
        const char *err;
        size_t len;
        err = lua_tolstring(L, i, &len);
        mtevL(mtev_error, "lua: %s\n", err);
      }
    }
    lua_pop(L,i);
    goto boom;
  }
  lua_pop(L, lua_gettop(L));

  mtev_lua_pushmodule(L, conf->dispatch);
  if(lua_isnil(L, -1)) {
    lua_pop(L, 1);
    ctx->err = strdup("no such module");
    goto boom;
  }
  lua_getfield(L, -1, "handler");
  lua_remove(L, -2);
  if(!lua_isfunction(L, -1)) {
    lua_pop(L, 1);
    ctx->err = strdup("no 'handler' function in module");
    goto boom;
  }
  mtev_lua_setup_restc(L, restc);
  mtev_lua_hash_to_table(L, restc->ac->config);

  conne = mtev_http_connection_event(mtev_http_session_connection(restc->http_ctx));
  eventer_remove(conne);
  restc->fastpath = lua_web_restc_fastpath;

  status = lmc->resume(ri, 2);
  if(status == 0) return 0;

  if(mtev_http_response_complete(res) != mtev_true) {
 boom:
    mtev_http_response_standard(restc->http_ctx,
                                (ctx && ctx->httpcode) ? ctx->httpcode : 500,
                                "ERROR", "text/plain");
    if(ctx && ctx->err) mtev_http_response_append(restc->http_ctx, ctx->err, strlen(ctx->err));
    mtev_http_response_end(restc->http_ctx);
  }
  return 0;
}
Beispiel #3
0
static int
lua_general_handler(mtev_dso_generic_t *self) {
  int status, rv;
  lua_general_conf_t *conf = get_config(self);
  lua_module_closure_t *lmc = pthread_getspecific(conf->key);
  mtev_lua_resume_info_t *ri = NULL;
  const char *err = NULL;
  char errbuf[128];
  lua_State *L;

  if(!lmc) mtev_lua_general_init(self);
  lmc = pthread_getspecific(conf->key);
  if(!lmc || !conf || !conf->module || !conf->function) {
    goto boom;
  }
  ri = lua_general_new_resume_info(lmc);
  L = ri->coro_state;

  lua_getglobal(L, "require");
  lua_pushstring(L, conf->module);
  rv = lua_pcall(L, 1, 1, 0);
  if(rv) {
    int i;
    mtevL(nlerr, "lua: require %s failed\n", conf->module);
    mtev_lua_traceback(L);
    i = lua_gettop(L);
    if(i>0) {
      if(lua_isstring(L, i)) {
        const char *err;
        size_t len;
        err = lua_tolstring(L, i, &len);
        mtevL(nlerr, "lua: %s\n", err);
      }
    }
    lua_pop(L,i);
    goto boom;
  }
  lua_pop(L, lua_gettop(L));

  mtev_lua_pushmodule(L, conf->module);
  if(lua_isnil(L, -1)) {
    lua_pop(L, 1);
    snprintf(errbuf, sizeof(errbuf), "no such module: '%s'", conf->module);
    err = errbuf;
    goto boom;
  }
  lua_getfield(L, -1, conf->function);
  lua_remove(L, -2);
  if(!lua_isfunction(L, -1)) {
    lua_pop(L, 1);
    snprintf(errbuf, sizeof(errbuf), "no function '%s' in module '%s'",
             conf->function, conf->module);
    err = errbuf;
    goto boom;
  }

  status = lmc->resume(ri, 0);
  if(status == 0) return 0;
  /* If we've failed, resume has freed ri, so we should just return. */
  mtevL(nlerr, "lua dispatch error: %d\n", status);
  tragic_failure(self);
  return 0;

 boom:
  if(err) mtevL(nlerr, "lua dispatch error: %s\n", err);
  if(ri) lua_general_ctx_free(ri);
  tragic_failure(self);
  return 0;
}