degesch: Lua: halfplement a connector wrapper
You can't do anything reasonable with the socket now.
This commit is contained in:
parent
00a1bdc707
commit
e1c7b8dcaf
242
degesch.c
242
degesch.c
|
@ -7877,7 +7877,7 @@ lua_schema_item_gc (lua_State *L)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static luaL_Reg lua_schema_item_table[] =
|
static luaL_Reg lua_schema_table[] =
|
||||||
{
|
{
|
||||||
{ "__gc", lua_schema_item_gc },
|
{ "__gc", lua_schema_item_gc },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
|
@ -8117,12 +8117,242 @@ lua_plugin_setup_config (lua_State *L)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
|
/// Identifier for the Lua metatable
|
||||||
|
#define XLUA_CONNECTION_METATABLE "connection"
|
||||||
|
|
||||||
|
struct lua_connection
|
||||||
|
{
|
||||||
|
struct lua_plugin *plugin; ///< The plugin we belong to
|
||||||
|
struct poller_fd socket_event; ///< Socket is ready
|
||||||
|
int socket_fd; ///< Underlying connected socket
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
lua_connection_close (lua_State *L)
|
||||||
|
{
|
||||||
|
struct lua_connection *self =
|
||||||
|
luaL_checkudata (L, 1, XLUA_CONNECTION_METATABLE);
|
||||||
|
|
||||||
|
if (self->socket_fd != -1)
|
||||||
|
{
|
||||||
|
poller_fd_reset (&self->socket_event);
|
||||||
|
xclose (self->socket_fd);
|
||||||
|
self->socket_fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connection is dead, we don't need to hold onto any resources anymore
|
||||||
|
lua_cache_invalidate (L, self);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static luaL_Reg lua_connection_table[] =
|
||||||
|
{
|
||||||
|
{ "close", lua_connection_close },
|
||||||
|
{ "__gc", lua_connection_close },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
|
static void
|
||||||
|
lua_connection_on_ready (const struct pollfd *pfd, struct lua_connection *self)
|
||||||
|
{
|
||||||
|
// TODO: handle the event, invoke on_data, on_close, on_error from
|
||||||
|
// our associated uservalue table as needed
|
||||||
|
lua_cache_invalidate (self->plugin->L, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct lua_connection *
|
||||||
|
lua_plugin_push_connection (struct lua_plugin *plugin, int socket_fd)
|
||||||
|
{
|
||||||
|
lua_State *L = plugin->L;
|
||||||
|
|
||||||
|
struct lua_connection *self = lua_newuserdata (L, sizeof *self);
|
||||||
|
luaL_setmetatable (L, XLUA_CONNECTION_METATABLE);
|
||||||
|
memset (self, 0, sizeof *self);
|
||||||
|
self->plugin = plugin;
|
||||||
|
|
||||||
|
poller_fd_init (&self->socket_event, &plugin->ctx->poller,
|
||||||
|
(self->socket_fd = socket_fd));
|
||||||
|
self->socket_event.dispatcher = (poller_fd_fn) lua_connection_on_ready;
|
||||||
|
self->socket_event.user_data = self;
|
||||||
|
poller_fd_set (&self->socket_event, POLLIN);
|
||||||
|
|
||||||
|
// Make sure the connection doesn't get garbage collected and return it
|
||||||
|
lua_cache_store (L, self, -1);
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
|
/// Identifier for the Lua metatable
|
||||||
|
#define XLUA_CONNECTOR_METATABLE "connector"
|
||||||
|
|
||||||
|
struct lua_connector
|
||||||
|
{
|
||||||
|
struct lua_plugin *plugin; ///< The plugin we belong to
|
||||||
|
struct connector connector; ///< Connector object
|
||||||
|
bool active; ///< Whether the connector is alive
|
||||||
|
|
||||||
|
int ref_on_success; ///< Reference to "on_success" callback
|
||||||
|
int ref_on_error; ///< Reference to "on_error" callback
|
||||||
|
|
||||||
|
char *last_error; ///< Connecting error, if any
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
lua_connector_discard (struct lua_connector *self)
|
||||||
|
{
|
||||||
|
if (self->active)
|
||||||
|
{
|
||||||
|
connector_free (&self->connector);
|
||||||
|
self->active = false;
|
||||||
|
|
||||||
|
luaL_unref (self->plugin->L, LUA_REGISTRYINDEX, self->ref_on_success);
|
||||||
|
luaL_unref (self->plugin->L, LUA_REGISTRYINDEX, self->ref_on_error);
|
||||||
|
self->ref_on_success = LUA_REFNIL;
|
||||||
|
self->ref_on_error = LUA_REFNIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
free (self->last_error);
|
||||||
|
self->last_error = NULL;
|
||||||
|
|
||||||
|
lua_cache_invalidate (self->plugin->L, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
lua_connector_abort (lua_State *L)
|
||||||
|
{
|
||||||
|
struct lua_connector *self =
|
||||||
|
luaL_checkudata (L, 1, XLUA_CONNECTOR_METATABLE);
|
||||||
|
lua_connector_discard (self);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static luaL_Reg lua_connector_table[] =
|
||||||
|
{
|
||||||
|
{ "abort", lua_connector_abort },
|
||||||
|
{ "__gc", lua_connector_abort },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
|
static void
|
||||||
|
lua_connector_on_connected (void *user_data, int socket, const char *hostname)
|
||||||
|
{
|
||||||
|
struct lua_connector *self = user_data;
|
||||||
|
struct lua_plugin *plugin = self->plugin;
|
||||||
|
lua_State *L = plugin->L;
|
||||||
|
|
||||||
|
// TODO: use this for SNI once TLS is implemented
|
||||||
|
(void) hostname;
|
||||||
|
|
||||||
|
if (self->ref_on_success != LUA_REFNIL)
|
||||||
|
{
|
||||||
|
lua_pushcfunction (L, lua_plugin_error_handler);
|
||||||
|
|
||||||
|
lua_rawgeti (L, LUA_REGISTRYINDEX, self->ref_on_success);
|
||||||
|
lua_plugin_push_connection (plugin, socket); // 1: connection
|
||||||
|
|
||||||
|
if (lua_pcall (L, 1, 0, -3))
|
||||||
|
{
|
||||||
|
struct error *e = NULL;
|
||||||
|
(void) lua_plugin_process_error (plugin, lua_tostring (L, -1), &e);
|
||||||
|
lua_pop (L, 1);
|
||||||
|
|
||||||
|
log_global_error (plugin->ctx, "Lua: plugin \"#s\": #s: #s",
|
||||||
|
plugin->super.name, "connector on_success", e->message);
|
||||||
|
error_free (e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lua_connector_discard (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
lua_connector_on_failure (void *user_data)
|
||||||
|
{
|
||||||
|
struct lua_connector *self = user_data;
|
||||||
|
struct lua_plugin *plugin = self->plugin;
|
||||||
|
lua_State *L = plugin->L;
|
||||||
|
|
||||||
|
if (self->ref_on_error != LUA_REFNIL)
|
||||||
|
{
|
||||||
|
lua_pushcfunction (L, lua_plugin_error_handler);
|
||||||
|
|
||||||
|
lua_rawgeti (L, LUA_REGISTRYINDEX, self->ref_on_error);
|
||||||
|
lua_pushstring (L, self->last_error); // 1: error string
|
||||||
|
|
||||||
|
if (lua_pcall (L, 1, 0, -3))
|
||||||
|
{
|
||||||
|
struct error *e = NULL;
|
||||||
|
(void) lua_plugin_process_error (plugin, lua_tostring (L, -1), &e);
|
||||||
|
lua_pop (L, 1);
|
||||||
|
|
||||||
|
log_global_error (plugin->ctx, "Lua: plugin \"#s\": #s: #s",
|
||||||
|
plugin->super.name, "connector on_error", e->message);
|
||||||
|
error_free (e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lua_connector_discard (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
lua_connector_on_error (void *user_data, const char *error)
|
||||||
|
{
|
||||||
|
struct lua_connector *self = user_data;
|
||||||
|
free (self->last_error);
|
||||||
|
self->last_error = xstrdup (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
lua_plugin_connect (lua_State *L)
|
||||||
|
{
|
||||||
|
struct lua_plugin *plugin = lua_touserdata (L, lua_upvalueindex (1));
|
||||||
|
const char *host = luaL_checkstring (L, 1);
|
||||||
|
const char *service = luaL_checkstring (L, 2);
|
||||||
|
luaL_checktype (L, 3, LUA_TTABLE);
|
||||||
|
|
||||||
|
struct lua_connector *self = lua_newuserdata (L, sizeof *self);
|
||||||
|
luaL_setmetatable (L, XLUA_CONNECTOR_METATABLE);
|
||||||
|
memset (self, 0, sizeof *self);
|
||||||
|
|
||||||
|
self->plugin = plugin;
|
||||||
|
self->ref_on_success = LUA_REFNIL;
|
||||||
|
self->ref_on_error = LUA_REFNIL;
|
||||||
|
|
||||||
|
if (lua_plugin_check_field (L, 3, "on_success", LUA_TFUNCTION, true))
|
||||||
|
self->ref_on_success = luaL_ref (L, -1);
|
||||||
|
if (lua_plugin_check_field (L, 3, "on_error", LUA_TFUNCTION, true))
|
||||||
|
self->ref_on_error = luaL_ref (L, -1);
|
||||||
|
|
||||||
|
lua_pop (L, 2);
|
||||||
|
|
||||||
|
struct app_context *ctx = plugin->ctx;
|
||||||
|
struct connector *connector = &self->connector;
|
||||||
|
connector_init (connector, &ctx->poller);
|
||||||
|
connector_add_target (connector, host, service);
|
||||||
|
|
||||||
|
connector->on_connected = lua_connector_on_connected;
|
||||||
|
connector->on_connecting = NULL;
|
||||||
|
connector->on_error = lua_connector_on_error;
|
||||||
|
connector->on_failure = lua_connector_on_failure;
|
||||||
|
connector->user_data = self;
|
||||||
|
|
||||||
|
self->active = true;
|
||||||
|
lua_cache_store (L, self, -1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static luaL_Reg lua_plugin_library[] =
|
static luaL_Reg lua_plugin_library[] =
|
||||||
{
|
{
|
||||||
{ "hook_input", lua_plugin_hook_input },
|
{ "hook_input", lua_plugin_hook_input },
|
||||||
{ "hook_irc", lua_plugin_hook_irc },
|
{ "hook_irc", lua_plugin_hook_irc },
|
||||||
{ "hook_timer", lua_plugin_hook_timer },
|
{ "hook_timer", lua_plugin_hook_timer },
|
||||||
{ "setup_config", lua_plugin_setup_config },
|
{ "setup_config", lua_plugin_setup_config },
|
||||||
|
{ "connect", lua_plugin_connect },
|
||||||
{ NULL, NULL },
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -8250,10 +8480,12 @@ lua_plugin_load (struct app_context *ctx, const char *filename,
|
||||||
lua_setglobal (L, PROGRAM_NAME);
|
lua_setglobal (L, PROGRAM_NAME);
|
||||||
|
|
||||||
// Create metatables for our objects
|
// Create metatables for our objects
|
||||||
lua_plugin_create_meta (L, XLUA_HOOK_METATABLE, lua_hook_table);
|
lua_plugin_create_meta (L, XLUA_HOOK_METATABLE, lua_hook_table);
|
||||||
lua_plugin_create_meta (L, XLUA_BUFFER_METATABLE, lua_buffer_table);
|
lua_plugin_create_meta (L, XLUA_BUFFER_METATABLE, lua_buffer_table);
|
||||||
lua_plugin_create_meta (L, XLUA_SERVER_METATABLE, lua_server_table);
|
lua_plugin_create_meta (L, XLUA_SERVER_METATABLE, lua_server_table);
|
||||||
lua_plugin_create_meta (L, XLUA_SCHEMA_METATABLE, lua_schema_item_table);
|
lua_plugin_create_meta (L, XLUA_SCHEMA_METATABLE, lua_schema_table);
|
||||||
|
lua_plugin_create_meta (L, XLUA_CONNECTION_METATABLE, lua_connection_table);
|
||||||
|
lua_plugin_create_meta (L, XLUA_CONNECTOR_METATABLE, lua_connector_table);
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
if (!(ret = luaL_loadfile (L, filename))
|
if (!(ret = luaL_loadfile (L, filename))
|
||||||
|
|
Loading…
Reference in New Issue