blob: ac420754bd0757e12daea1b67c0cc8ef0b2295c3 [file] [log] [blame]
/*
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 "ts/ts.h"
#include "ts/remap.h"
#include "ink_defs.h"
#include "lapi.h"
#include "lutil.h"
#include "state.h"
#include <unistd.h>
#include <pthread.h>
static pthread_mutex_t PluginInstanceLock = PTHREAD_MUTEX_INITIALIZER;
static TSRemapStatus
LuaPluginRemap(lua_State * lua, TSHttpTxn txn, TSRemapRequestInfo * rri)
{
LuaRemapRequest * rq;
lua_getglobal(lua, "remap");
if (lua_isnil(lua, -1)) {
// No "remap" callback, better continue.
return TSREMAP_NO_REMAP;
}
LuaLogDebug("handling request %p on thread 0x%llx", rri, (unsigned long long)pthread_self());
// XXX We can also cache the RemapRequestInfo in the Lua state. We we just need to reset
// the rri pointer and status.
rq = LuaPushRemapRequestInfo(lua, txn, rri);
if (lua_pcall(lua, 1, 0, 0) != 0) {
LuaLogDebug("remap failed: %s", lua_tostring(lua, -1));
lua_pop(lua, 1);
return TSREMAP_ERROR;
}
// XXX can we guarantee that rq has not been garbage collected?
return rq->status;
}
TSReturnCode
TSRemapInit(TSRemapInterface * /* api_info ATS_UNUSED */, char * /* errbuf ATS_UNUSED */,
int /* errbuf_size ATS_UNUSED */)
{
LuaLogDebug("loading lua plugin");
// Allocate a TSHttpTxn argument index for handling per-transaction hooks.
TSReleaseAssert(TSHttpArgIndexReserve("lua", "lua", &LuaHttpArgIndex) == TS_SUCCESS);
return TS_SUCCESS;
}
TSReturnCode
TSRemapNewInstance(int argc, char * argv[], void ** ih, char * /* errbuf ATS_UNUSED */, int /* errsz ATS_UNUSED */)
{
instanceid_t instanceid;
pthread_mutex_lock(&PluginInstanceLock);
// Register a new Lua plugin instance, skipping the first two arguments (which are the remap URLs).
instanceid = LuaPluginRegister((unsigned)argc - 2, (const char **)argv + 2);
*ih = (void *)(intptr_t)instanceid;
pthread_mutex_unlock(&PluginInstanceLock);
LuaLogDebug("created Lua remap instance %u", instanceid);
return TS_SUCCESS;
}
void
TSRemapDeleteInstance(void * ih)
{
instanceid_t instanceid = (intptr_t)ih;
pthread_mutex_lock(&PluginInstanceLock);
LuaPluginUnregister(instanceid);
pthread_mutex_unlock(&PluginInstanceLock);
}
TSRemapStatus
TSRemapDoRemap(void * ih, TSHttpTxn txn, TSRemapRequestInfo * rri)
{
ScopedLuaState lstate((intptr_t)ih);
TSReleaseAssert(lstate);
return LuaPluginRemap(lstate->lua, txn, rri);
}