Ejemplo n.º 1
0
int
ts_http_fetcher_callback_sm(http_fetcher *fch, TSEvent event)
{
    if (fch->deleted && !fch->ref) {
        ts_http_fetcher_release(fch);
        return -1;
    }

    if (event == TS_FETCH_EVENT_BODY_QUIET)
        return 0;

    fch->ref++;

    if (fch->flags & TS_FETCH_FLAG_USE_NEW_LOCK)
        TSMutexLock(TSContMutexGet(fch->contp));

    TSContCall(fch->contp, event, fch);

    if (fch->flags & TS_FETCH_FLAG_USE_NEW_LOCK)
        TSMutexUnlock(TSContMutexGet(fch->contp));

    fch->ref--;

    if (fch->deleted && !fch->ref) {
        ts_http_fetcher_release(fch);
        return -1;
    }

    return 0;
}
Ejemplo n.º 2
0
http_fetcher *
ts_http_fetcher_create(TSCont contp, struct sockaddr *addr, int flags)
{
    http_fetcher    *fch;

    fch = (http_fetcher*)TSmalloc(sizeof(http_fetcher));

    fch->flags = flags;
    fch->contp = contp;
    fch->aip = *addr;

    if (flags & TS_FLAG_FETCH_USE_NEW_LOCK) {
        fch->mutexp = TSMutexCreate();
    } else {
        fch->mutexp = TSContMutexGet(contp);
    }

    fch->req_buffer = TSIOBufferCreate();
    fch->req_reader = TSIOBufferReaderAlloc(fch->req_buffer);

    /* initialize */
    fch->http_vc = NULL;
    fch->read_vio = NULL;
    fch->write_vio = NULL;
    fch->method = 0;

    fch->http_parser = NULL;
    fch->hdr_bufp = NULL;
    fch->hdr_loc = NULL;
    fch->hdr_buffer = NULL;
    fch->hdr_reader = NULL;
    fch->resp_buffer = NULL;
    fch->resp_reader = NULL;
    fch->body_buffer = NULL;
    fch->body_reader = NULL;
    fch->flow_buffer = NULL;
    fch->flow_reader = NULL;

    fch->fetch_contp = NULL;
    fch->action = NULL;

    fch->resp_cl = -1;
    fch->resp_already = 0;
    fch->post_cl = 0;
    fch->post_already = 0;

    fch->ctx = NULL;
    fch->status_code = 0;
    fch->ref = 0;

    fch->header_done = 0;
    fch->body_done = 0;
    fch->deleted = 0;
    fch->chunked = 0;
    fch->error = 0;
    fch->launched = 0;
    fch->stopped = 0;

    return fch;
}
Ejemplo n.º 3
0
TSRemapStatus
TSRemapDoRemap(void* ih, TSHttpTxn rh, TSRemapRequestInfo *rri)
{
    int                         ret;
    uint64_t                    req_id;
    TSCont                      contp;
    lua_State                   *L;
    ts_lua_main_ctx             *main_ctx;
    ts_lua_http_ctx             *http_ctx;
    ts_lua_cont_info            *ci;
    ts_lua_instance_conf        *instance_conf;

    instance_conf = (ts_lua_instance_conf*)ih;
    req_id = __sync_fetch_and_add(&ts_lua_http_next_id, 1);

    main_ctx = &ts_lua_main_ctx_array[req_id%TS_LUA_MAX_STATE_COUNT];

    TSMutexLock(main_ctx->mutexp);

    http_ctx = ts_lua_create_http_ctx(main_ctx, instance_conf);

    http_ctx->txnp = rh;
    http_ctx->client_request_bufp = rri->requestBufp;
    http_ctx->client_request_hdrp = rri->requestHdrp;
    http_ctx->client_request_url = rri->requestUrl;
    http_ctx->rri = rri;

    ci = &http_ctx->cinfo;
    L = ci->routine.lua;

    contp = TSContCreate(ts_lua_http_cont_handler, NULL);
    TSContDataSet(contp, http_ctx);

    ci->contp = contp;
    ci->mutex = TSContMutexGet((TSCont)rh);

    // push do_remap function on the stack, and no async operation should exist here.
    lua_getglobal(L, TS_LUA_FUNCTION_REMAP);

    if (lua_pcall(L, 0, 1, 0) != 0) {
        ee("lua_pcall failed: %s", lua_tostring(L, -1));
        ret = TSREMAP_NO_REMAP;

    } else {
        ret = lua_tointeger(L, -1);
    }

    lua_pop(L, 1);      // pop the result

    if (http_ctx->hooks > 0) {
        TSMutexUnlock(main_ctx->mutexp);
        TSHttpTxnHookAdd(rh, TS_HTTP_TXN_CLOSE_HOOK, contp);

    } else {
        ts_lua_destroy_http_ctx(http_ctx);
        TSMutexUnlock(main_ctx->mutexp);
    }

    return ret;
}
Ejemplo n.º 4
0
int
ts_http_fetcher_callback_sm(http_fetcher *fch, TSEvent event)
{
    if (fch->deleted && !fch->ref) {
        ts_http_fetcher_release(fch);
        return -1;
    }

    if (event == TS_EVENT_FETCH_BODY_QUIET || fch->stopped) {
        return 0;

    } else if (event != TS_EVENT_FETCH_HEADER_DONE &&
               event != TS_EVENT_FETCH_BODY_READY &&
               event != TS_EVENT_FETCH_BODY_QUIET) {

        fch->stopped = 1;
    }

    fch->ref++;

    if (fch->flags & TS_FLAG_FETCH_USE_NEW_LOCK)
        TSMutexLock(TSContMutexGet(fch->contp));

    TSContCall(fch->contp, event, fch);

    if (fch->flags & TS_FLAG_FETCH_USE_NEW_LOCK)
        TSMutexUnlock(TSContMutexGet(fch->contp));

    fch->ref--;

    if (fch->deleted && !fch->ref) {
        ts_http_fetcher_release(fch);
        return -1;
    }

    return 0;
}
static int
config_handler(TSCont cont, TSEvent event, void *edata)
{
  plugin_state_t *pstate;
  invalidate_t *i, *iptr;
  TSCont free_cont;
  bool updated;
  TSMutex mutex;

  mutex = TSContMutexGet(cont);
  TSMutexLock(mutex);

  TSDebug(LOG_PREFIX, "In config Handler");
  pstate = (plugin_state_t *)TSContDataGet(cont);
  i      = copy_config(pstate->invalidate_list);

  updated = prune_config(&i);
  updated = load_config(pstate, &i) || updated;

  if (updated) {
    list_config(pstate, i);
    iptr = __sync_val_compare_and_swap(&(pstate->invalidate_list), pstate->invalidate_list, i);

    if (iptr) {
      free_cont = TSContCreate(free_handler, TSMutexCreate());
      TSContDataSet(free_cont, (void *)iptr);
      TSContScheduleOnPool(free_cont, FREE_TMOUT, TS_THREAD_POOL_TASK);
    }
  } else {
    TSDebug(LOG_PREFIX, "No Changes");
    if (i) {
      free_invalidate_t_list(i);
    }
  }

  TSMutexUnlock(mutex);

  // Don't reschedule for TS_EVENT_MGMT_UPDATE
  if (event == TS_EVENT_TIMEOUT) {
    TSContScheduleOnPool(cont, CONFIG_TMOUT, TS_THREAD_POOL_TASK);
  }
  return 0;
}
Ejemplo n.º 6
0
static int
ts_lua_sleep(lua_State * L)
{
  int sec;
  TSAction action;
  TSCont contp;
  ts_lua_http_intercept_item *node;
  ts_lua_http_intercept_ctx *ictx;

  ictx = ts_lua_get_http_intercept_ctx(L);
  sec = luaL_checknumber(L, 1);

  contp = TSContCreate(ts_lua_sleep_handler, TSContMutexGet(ictx->contp));
  action = TSContSchedule(contp, sec * 1000, TS_THREAD_POOL_DEFAULT);

  node = (ts_lua_http_intercept_item *) TSmalloc(sizeof(ts_lua_http_intercept_item));
  TS_LUA_ADD_INTERCEPT_ITEM(ictx, node, contp, ts_lua_sleep_cleanup, action);
  TSContDataSet(contp, node);

  return lua_yield(L, 0);
}
Ejemplo n.º 7
0
/*-------------------------------------------------------------------------
  transform_handler
  Handler for all events received during the transformation process

  Input:
    contp      continuation for the current transaction
    event      event received
    data       pointer on optional data
  Output :
  Return Value:
  -------------------------------------------------------------------------*/
static int
transform_handler(TSCont contp, TSEvent event, void *edata)
{
  TSVIO input_vio;
  ContData *data;
  int state, retval;

  /* This section will be called by both TS internal
     and the thread. Protect it with a mutex to avoid
     concurrent calls. */

  /* Handle TryLock result */
  if (TSMutexLockTry(TSContMutexGet(contp)) != TS_SUCCESS) {
    TSCont c = TSContCreate(trylock_handler, NULL);
    TryLockData *d = TSmalloc(sizeof(TryLockData));

    d->contp = contp;
    d->event = event;
    TSContDataSet(c, d);
    TSContSchedule(c, 10, TS_THREAD_POOL_DEFAULT);
    return 1;
  }

  data = TSContDataGet(contp);
  TSAssert(data->magic == MAGIC_ALIVE);

  state = data->state;

  /* Check to see if the transformation has been closed */
  retval = TSVConnClosedGet(contp);
  if (retval) {
    /* If the thread is still executing its job, we don't want to destroy
       the continuation right away as the thread will call us back
       on this continuation. */
    if (state == STATE_READ_PSI) {
      TSContSchedule(contp, 10, TS_THREAD_POOL_DEFAULT);
    } else {
      TSMutexUnlock(TSContMutexGet(contp));
      cont_data_destroy(TSContDataGet(contp));
      TSContDestroy(contp);
      return 1;
    }
  } else {
    switch (event) {
    case TS_EVENT_ERROR:
      input_vio = TSVConnWriteVIOGet(contp);
      TSContCall(TSVIOContGet(input_vio), TS_EVENT_ERROR, input_vio);
      break;

    case TS_EVENT_VCONN_WRITE_COMPLETE:
      TSVConnShutdown(TSTransformOutputVConnGet(contp), 0, 1);
      break;

    case TS_EVENT_VCONN_WRITE_READY:
      /* downstream vconnection is done reading data we've write into it.
         let's read some more data from upstream if we're in read state. */
      if (state == STATE_READ_DATA) {
        handle_transform(contp);
      }
      break;

    case TS_EVENT_IMMEDIATE:
      if (state == STATE_READ_DATA) {
        /* upstream vconnection signals some more data ready to be read
           let's try to transform some more data */
        handle_transform(contp);
      } else if (state == STATE_DUMP_PSI) {
        /* The thread scheduled an event on our continuation to let us
           know it has completed its job
           Let's dump the include content to the output vconnection */
        dump_psi(contp);
        wake_up_streams(contp);
      }
      break;

    default:
      TSAssert(!"Unexpected event");
      break;
    }
  }

  TSMutexUnlock(TSContMutexGet(contp));
  return 1;
}
Ejemplo n.º 8
0
/*-------------------------------------------------------------------------
  psi_include
  Read file to include. Copy its content into an iobuffer.

  This is the function doing blocking calls and called by the plugin's threads

  Input:
    data      continuation for the current transaction
  Output :
    data->psi_buffer  contains the file content
    data->psi_sucess  0 if include failed, 1 if success
  Return Value:
    0  if failure
    1  if success
  -------------------------------------------------------------------------*/
static int
psi_include(TSCont contp, void *edata)
{
#define BUFFER_SIZE 1024
  ContData *data;
  TSFile filep;
  char buf[BUFFER_SIZE];
  char inc_file[PSI_PATH_MAX_SIZE + PSI_FILENAME_MAX_SIZE];

  /* We manipulate plugin continuation data from a separate thread.
     Grab mutex to avoid concurrent access */
  TSMutexLock(TSContMutexGet(contp));
  data = TSContDataGet(contp);
  TSAssert(data->magic == MAGIC_ALIVE);

  if (!data->psi_buffer) {
    data->psi_buffer = TSIOBufferCreate();
    data->psi_reader = TSIOBufferReaderAlloc(data->psi_buffer);
  }

  /* For security reason, we do not allow to include files that are
     not in the directory <plugin_path>/include.
     Also include file cannot contain any path. */
  sprintf(inc_file, "%s/%s", psi_directory, _basename(data->psi_filename));

  /* Read the include file and copy content into iobuffer */
  if ((filep = TSfopen(inc_file, "r")) != NULL) {
    TSDebug(DBG_TAG, "Reading include file %s", inc_file);

    while (TSfgets(filep, buf, BUFFER_SIZE) != NULL) {
      TSIOBufferBlock block;
      int64_t len, avail, ndone, ntodo, towrite;
      char *ptr_block;

      len = strlen(buf);
      ndone = 0;
      ntodo = len;
      while (ntodo > 0) {
        /* TSIOBufferStart allocates more blocks if required */
        block = TSIOBufferStart(data->psi_buffer);
        ptr_block = TSIOBufferBlockWriteStart(block, &avail);
        towrite = MIN(ntodo, avail);

        memcpy(ptr_block, buf + ndone, towrite);
        TSIOBufferProduce(data->psi_buffer, towrite);
        ntodo -= towrite;
        ndone += towrite;
      }
    }
    TSfclose(filep);
    data->psi_success = 1;
    if (log) {
      TSTextLogObjectWrite(log, "Successfully included file: %s", inc_file);
    }
  } else {
    data->psi_success = 0;
    if (log) {
      TSTextLogObjectWrite(log, "Failed to include file: %s", inc_file);
    }
  }

  /* Change state and schedule an event EVENT_IMMEDIATE on the plugin continuation
     to let it know we're done. */

  /* Note: if the blocking call was not in the transformation state (i.e. in
     TS_HTTP_READ_REQUEST_HDR, TS_HTTP_OS_DNS and so on...) we could
     use TSHttpTxnReenable to wake up the transaction instead of sending an event. */

  TSContSchedule(contp, 0, TS_THREAD_POOL_DEFAULT);
  data->psi_success = 0;
  data->state = STATE_READ_DATA;
  TSMutexUnlock(TSContMutexGet(contp));

  return 0;
}
Ejemplo n.º 9
0
static void ironbee_plugin_txn_start(TSCont contp, TSHttpTxn txnp)
{
    assert(contp != NULL);
    assert(txnp != NULL);

    /* start of Request */
    /* First req on a connection, we set up conn stuff */
    ib_status_t  rc;
    ib_engine_t *ib = NULL;
    TSCont mycont;
    tsib_ssn_ctx *ssndata;
    tsib_txn_ctx *txndata;

    ssndata = TSContDataGet(contp);

    if (ssndata->iconn == NULL) {
        rc = tsib_manager_engine_acquire(&ib);
        if (rc == IB_DECLINED) {
            /* OK, this means the manager is disabled deliberately,
             * but otherwise all's well.  So this TXN
             * gets processed without intervention from Ironbee
             * and is invisble when our SSN_CLOSE hook runs.
             */
            TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
            TSDebug("ironbee", "Decline from engine manager");
            return;
        }
        else if (rc != IB_OK) {
            TSError("[ironbee] Failed to acquire engine: %s",
                    ib_status_to_string(rc));
            goto noib_error;
        }
        if (ib != NULL) {
            rc = ib_conn_create(ib, &ssndata->iconn, contp);
            if (rc != IB_OK) {
                TSError("[ironbee] ib_conn_create: %s",
                        ib_status_to_string(rc));
                tsib_manager_engine_release(ib);
                goto noib_error;
            }

            /* In the normal case, release the engine when the
             * connection's memory pool is destroyed */
            rc = ib_mm_register_cleanup(ssndata->iconn->mm,
                                        cleanup_ib_connection,
                                        ib);
            if (rc != IB_OK) {
                TSError("[ironbee] ib_mm_register_cleanup: %s",
                        ib_status_to_string(rc));
                tsib_manager_engine_release(ib);
                goto noib_error;
            }

            TSDebug("ironbee", "CONN CREATE: conn=%p", ssndata->iconn);
            ssndata->txnp = txnp;
            ssndata->txn_count = ssndata->closing = 0;

            rc = ironbee_conn_init(ssndata);
            if (rc != IB_OK) {
                TSError("[ironbee] ironbee_conn_init: %s",
                        ib_status_to_string(rc));
                goto noib_error;
            }

            TSContDataSet(contp, ssndata);
            TSDebug("ironbee",
                    "ironbee_plugin: ib_state_notify_conn_opened()");
            rc = ib_state_notify_conn_opened(ib, ssndata->iconn);
            if (rc != IB_OK) {
                TSError("[ironbee] Failed to notify connection opened: %s",
                        ib_status_to_string(rc));
            }
        }
        else {
            /* Use TSError where there's no ib or tx */
            TSError("Ironbee: No ironbee engine!");
            goto noib_error;
        }
    }

    /* create a txn cont (request ctx) and tx */
    txndata = TSmalloc(sizeof(*txndata));
    memset(txndata, 0, sizeof(*txndata));
    txndata->ssn = ssndata;
    txndata->txnp = txnp;

    rc = ib_tx_create(&txndata->tx, ssndata->iconn, txndata);
    if (rc != IB_OK) {
        TSError("[ironbee] Failed to create tx: %d", rc);
        tsib_manager_engine_release(ib);
        TSfree(txndata);
        goto noib_error;
    }

    ++ssndata->txn_count;

    ib_log_debug_tx(txndata->tx,
                    "TX CREATE: conn=%p tx=%p id=%s txn_count=%d",
                    ssndata->iconn, txndata->tx, txndata->tx->id,
                    txndata->ssn->txn_count);

    mycont = TSContCreate(ironbee_plugin, TSContMutexGet(contp));
    TSContDataSet(mycont, txndata);

    TSHttpTxnHookAdd(txnp, TS_HTTP_TXN_CLOSE_HOOK, mycont);

    /* Hook to process responses */
    TSHttpTxnHookAdd(txnp, TS_HTTP_READ_RESPONSE_HDR_HOOK, mycont);

    /* Hook to process requests */
    TSHttpTxnHookAdd(txnp, TS_HTTP_PRE_REMAP_HOOK, mycont);

    /* Hook to process request headers when sent to the server. */
    TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_REQUEST_HDR_HOOK, mycont);

    /* Create continuations for input and output filtering
     * to give them txn lifetime.
     */
    txndata->in_data_cont = TSTransformCreate(in_data_event, txnp);
    TSContDataSet(txndata->in_data_cont, txndata);

    txndata->out_data_cont = TSTransformCreate(out_data_event, txnp);
    TSContDataSet(txndata->out_data_cont, txndata);

    TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
    return;

noib_error:

    /* NULL txndata signals this to SEND_RESPONSE */
    TSContDataSet(contp, NULL);

    TSError("[ironbee] Internal error initialising for transaction");
    TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, contp);

    /* FIXME: check this.
     * Purpose is to ensure contp doesn't leak, but may not be right
     */
    TSHttpTxnHookAdd(txnp, TS_HTTP_TXN_CLOSE_HOOK, contp);

    TSHttpTxnReenable(txnp, TS_EVENT_HTTP_ERROR);
    return;
}
Ejemplo n.º 10
0
static int
globalHookHandler(TSCont contp, TSEvent event ATS_UNUSED, void *edata)
{
    TSHttpTxn txnp = (TSHttpTxn)edata;

    TSMBuffer bufp;
    TSMLoc hdr_loc;
    TSMLoc url_loc;

    int ret;
    uint64_t req_id;
    TSCont txn_contp;

    lua_State *l;

    ts_lua_main_ctx *main_ctx;
    ts_lua_http_ctx *http_ctx;
    ts_lua_cont_info *ci;

    ts_lua_instance_conf *conf = (ts_lua_instance_conf *)TSContDataGet(contp);

    req_id = __sync_fetch_and_add(&ts_lua_g_http_next_id, 1);

    main_ctx = &ts_lua_g_main_ctx_array[req_id % TS_LUA_MAX_STATE_COUNT];

    TSDebug(TS_LUA_DEBUG_TAG, "[%s] req_id: %" PRId64, __FUNCTION__, req_id);
    TSMutexLock(main_ctx->mutexp);

    http_ctx           = ts_lua_create_http_ctx(main_ctx, conf);
    http_ctx->txnp     = txnp;
    http_ctx->rri      = NULL;
    http_ctx->has_hook = 0;

    if (!http_ctx->client_request_bufp) {
        if (TSHttpTxnClientReqGet(txnp, &bufp, &hdr_loc) == TS_SUCCESS) {
            http_ctx->client_request_bufp = bufp;
            http_ctx->client_request_hdrp = hdr_loc;

            if (TSHttpHdrUrlGet(bufp, hdr_loc, &url_loc) == TS_SUCCESS) {
                http_ctx->client_request_url = url_loc;
            }
        }
    }

    if (!http_ctx->client_request_hdrp) {
        ts_lua_destroy_http_ctx(http_ctx);
        TSMutexUnlock(main_ctx->mutexp);

        TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
        return 0;
    }

    txn_contp = TSContCreate(ts_lua_http_cont_handler, NULL);
    TSContDataSet(txn_contp, http_ctx);

    ci        = &http_ctx->cinfo;
    ci->contp = txn_contp;
    ci->mutex = TSContMutexGet((TSCont)txnp);

    l = ci->routine.lua;

    switch (event) {
    case TS_EVENT_HTTP_READ_REQUEST_HDR:
        lua_getglobal(l, TS_LUA_FUNCTION_G_READ_REQUEST);
        break;

    case TS_EVENT_HTTP_SEND_REQUEST_HDR:
        lua_getglobal(l, TS_LUA_FUNCTION_G_SEND_REQUEST);
        break;

    case TS_EVENT_HTTP_READ_RESPONSE_HDR:
        lua_getglobal(l, TS_LUA_FUNCTION_G_READ_RESPONSE);
        break;

    case TS_EVENT_HTTP_SEND_RESPONSE_HDR:
        // client response can be changed within a transaction
        // (e.g. due to the follow redirect feature). So, clearing the pointers
        // to allow API(s) to fetch the pointers again when it re-enters the hook
        if (http_ctx->client_response_hdrp != NULL) {
            TSHandleMLocRelease(http_ctx->client_response_bufp, TS_NULL_MLOC, http_ctx->client_response_hdrp);
            http_ctx->client_response_hdrp = NULL;
        }
        lua_getglobal(l, TS_LUA_FUNCTION_G_SEND_RESPONSE);
        break;

    case TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE:
        lua_getglobal(l, TS_LUA_FUNCTION_G_CACHE_LOOKUP_COMPLETE);
        break;

    case TS_EVENT_HTTP_TXN_START:
        lua_getglobal(l, TS_LUA_FUNCTION_G_TXN_START);
        break;

    case TS_EVENT_HTTP_PRE_REMAP:
        lua_getglobal(l, TS_LUA_FUNCTION_G_PRE_REMAP);
        break;

    case TS_EVENT_HTTP_POST_REMAP:
        lua_getglobal(l, TS_LUA_FUNCTION_G_POST_REMAP);
        break;

    case TS_EVENT_HTTP_SELECT_ALT:
        lua_getglobal(l, TS_LUA_FUNCTION_G_SELECT_ALT);
        break;

    case TS_EVENT_HTTP_OS_DNS:
        lua_getglobal(l, TS_LUA_FUNCTION_G_OS_DNS);
        break;

    case TS_EVENT_HTTP_READ_CACHE_HDR:
        lua_getglobal(l, TS_LUA_FUNCTION_G_READ_CACHE);
        break;

    case TS_EVENT_HTTP_TXN_CLOSE:
        lua_getglobal(l, TS_LUA_FUNCTION_G_TXN_CLOSE);
        break;

    default:
        ts_lua_destroy_http_ctx(http_ctx);
        TSMutexUnlock(main_ctx->mutexp);
        TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
        return 0;
    }

    if (lua_type(l, -1) != LUA_TFUNCTION) {
        lua_pop(l, 1);
        ts_lua_destroy_http_ctx(http_ctx);
        TSMutexUnlock(main_ctx->mutexp);

        TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
        return 0;
    }

    ts_lua_set_cont_info(l, NULL);

    if (lua_pcall(l, 0, 1, 0) != 0) {
        TSError("[ts_lua] lua_pcall failed: %s", lua_tostring(l, -1));
    }

    ret = lua_tointeger(l, -1);
    lua_pop(l, 1);

    if (http_ctx->has_hook) {
        // add a hook to release resources for context
        TSDebug(TS_LUA_DEBUG_TAG, "[%s] has txn hook -> adding txn close hook handler to release resources", __FUNCTION__);
        TSHttpTxnHookAdd(txnp, TS_HTTP_TXN_CLOSE_HOOK, txn_contp);
    } else {
        TSDebug(TS_LUA_DEBUG_TAG, "[%s] no txn hook -> release resources now", __FUNCTION__);
        ts_lua_destroy_http_ctx(http_ctx);
    }

    TSMutexUnlock(main_ctx->mutexp);

    if (ret) {
        TSHttpTxnReenable(txnp, TS_EVENT_HTTP_ERROR);
    } else {
        TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
    }

    return 0;
}
Ejemplo n.º 11
0
static TSRemapStatus
ts_lua_remap_plugin_init(void *ih, TSHttpTxn rh, TSRemapRequestInfo *rri)
{
    int ret;
    uint64_t req_id;

    TSCont contp;
    lua_State *L;

    ts_lua_main_ctx *main_ctx;
    ts_lua_http_ctx *http_ctx;
    ts_lua_cont_info *ci;

    ts_lua_instance_conf *instance_conf;

    int remap     = (rri == NULL ? 0 : 1);
    instance_conf = (ts_lua_instance_conf *)ih;
    req_id        = __sync_fetch_and_add(&ts_lua_http_next_id, 1);

    main_ctx = &ts_lua_main_ctx_array[req_id % TS_LUA_MAX_STATE_COUNT];

    TSMutexLock(main_ctx->mutexp);

    http_ctx = ts_lua_create_http_ctx(main_ctx, instance_conf);

    http_ctx->txnp     = rh;
    http_ctx->has_hook = 0;
    http_ctx->rri      = rri;
    if (rri != NULL) {
        http_ctx->client_request_bufp = rri->requestBufp;
        http_ctx->client_request_hdrp = rri->requestHdrp;
        http_ctx->client_request_url  = rri->requestUrl;
    }

    ci = &http_ctx->cinfo;
    L  = ci->routine.lua;

    contp = TSContCreate(ts_lua_http_cont_handler, NULL);
    TSContDataSet(contp, http_ctx);

    ci->contp = contp;
    ci->mutex = TSContMutexGet((TSCont)rh);

    lua_getglobal(L, (remap ? TS_LUA_FUNCTION_REMAP : TS_LUA_FUNCTION_OS_RESPONSE));
    if (lua_type(L, -1) != LUA_TFUNCTION) {
        TSMutexUnlock(main_ctx->mutexp);
        return TSREMAP_NO_REMAP;
    }

    ts_lua_set_cont_info(L, NULL);
    if (lua_pcall(L, 0, 1, 0) != 0) {
        TSError("[ts_lua] lua_pcall failed: %s", lua_tostring(L, -1));
        ret = TSREMAP_NO_REMAP;

    } else {
        ret = lua_tointeger(L, -1);
    }

    lua_pop(L, 1);

    if (http_ctx->has_hook) {
        TSDebug(TS_LUA_DEBUG_TAG, "[%s] has txn hook -> adding txn close hook handler to release resources", __FUNCTION__);
        TSHttpTxnHookAdd(rh, TS_HTTP_TXN_CLOSE_HOOK, contp);
    } else {
        TSDebug(TS_LUA_DEBUG_TAG, "[%s] no txn hook -> release resources now", __FUNCTION__);
        ts_lua_destroy_http_ctx(http_ctx);
    }

    TSMutexUnlock(main_ctx->mutexp);

    return ret;
}