degesch: replace degesch.connect with async.dial
Halfway there, looks much saner.
This commit is contained in:
		
							
								
								
									
										275
									
								
								degesch.c
									
									
									
									
									
								
							
							
						
						
									
										275
									
								
								degesch.c
									
									
									
									
									
								
							@@ -9580,149 +9580,6 @@ lua_plugin_push_connection (struct lua_plugin *plugin, int socket_fd)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// 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)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	lua_connector_discard (luaL_checkudata (L, 1, XLUA_CONNECTOR_METATABLE));
 | 
					 | 
				
			||||||
	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;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// TODO: use the hostname for SNI once TLS is implemented
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (self->ref_on_success != LUA_REFNIL)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		lua_State *L = self->plugin->L;
 | 
					 | 
				
			||||||
		lua_rawgeti (L, LUA_REGISTRYINDEX, self->ref_on_success);
 | 
					 | 
				
			||||||
		struct lua_connection *connection =
 | 
					 | 
				
			||||||
			lua_plugin_push_connection (self->plugin, socket);  // 1: connection
 | 
					 | 
				
			||||||
		lua_pushstring (L, hostname);                           // 2: hostname
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		struct error *e = NULL;
 | 
					 | 
				
			||||||
		if (!lua_plugin_call (self->plugin, 2, 0, &e))
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			lua_plugin_log_error (self->plugin, "connector on_success", e);
 | 
					 | 
				
			||||||
			// The connection has placed itself in the cache
 | 
					 | 
				
			||||||
			lua_connection_discard (connection);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	lua_connector_discard (self);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
lua_connector_on_failure (void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct lua_connector *self = user_data;
 | 
					 | 
				
			||||||
	if (self->ref_on_error != LUA_REFNIL)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		lua_State *L = self->plugin->L;
 | 
					 | 
				
			||||||
		lua_rawgeti (L, LUA_REGISTRYINDEX, self->ref_on_error);
 | 
					 | 
				
			||||||
		lua_pushstring (L, self->last_error);  // 1: error string
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		struct error *e = NULL;
 | 
					 | 
				
			||||||
		if (!lua_plugin_call (self->plugin, 1, 0, &e))
 | 
					 | 
				
			||||||
			lua_plugin_log_error (self->plugin, "connector on_error", 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;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	(void) lua_plugin_check_field (L, 3, "on_success", LUA_TFUNCTION, true);
 | 
					 | 
				
			||||||
	self->ref_on_success = luaL_ref (L, LUA_REGISTRYINDEX);
 | 
					 | 
				
			||||||
	(void) lua_plugin_check_field (L, 3, "on_error",   LUA_TFUNCTION, true);
 | 
					 | 
				
			||||||
	self->ref_on_error   = luaL_ref (L, LUA_REGISTRYINDEX);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	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;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// The script can create as many wait channels as wanted.  They only actually
 | 
					// The script can create as many wait channels as wanted.  They only actually
 | 
				
			||||||
// do anything once they get yielded to the main lua_resume() call.
 | 
					// do anything once they get yielded to the main lua_resume() call.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -9978,6 +9835,127 @@ lua_plugin_push_wait_timer (struct lua_plugin *plugin, lua_State *L,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct lua_wait_dial
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct lua_wait_channel super;      ///< The structure we're deriving
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct lua_plugin *plugin;          ///< The plugin we belong to
 | 
				
			||||||
 | 
						struct connector connector;         ///< Connector object
 | 
				
			||||||
 | 
						bool active;                        ///< Whether the connector is alive
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct lua_connection *connection;  ///< Established connection
 | 
				
			||||||
 | 
						char *hostname;                     ///< Target hostname
 | 
				
			||||||
 | 
						char *last_error;                   ///< Connecting error, if any
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool
 | 
				
			||||||
 | 
					lua_wait_dial_check (struct lua_wait_channel *wchannel)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct lua_wait_dial *self =
 | 
				
			||||||
 | 
							CONTAINER_OF (wchannel, struct lua_wait_dial, super);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						lua_State *L = self->super.task->thread;
 | 
				
			||||||
 | 
						if (self->connection)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							// FIXME: this way the connection can leak, it shouldn't stay in cache
 | 
				
			||||||
 | 
							//   automatically all the time but clean itself up on GC
 | 
				
			||||||
 | 
							lua_cache_get (L, self->connection);
 | 
				
			||||||
 | 
							lua_pushstring (L, self->hostname);
 | 
				
			||||||
 | 
							self->connection = NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (self->last_error)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							lua_pushnil (L);
 | 
				
			||||||
 | 
							lua_pushnil (L);
 | 
				
			||||||
 | 
							lua_pushstring (L, self->last_error);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					lua_wait_dial_cancel (struct lua_wait_dial *self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (self->active)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							connector_free (&self->connector);
 | 
				
			||||||
 | 
							self->active = false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					lua_wait_dial_cleanup (struct lua_wait_channel *wchannel)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct lua_wait_dial *self =
 | 
				
			||||||
 | 
							CONTAINER_OF (wchannel, struct lua_wait_dial, super);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						lua_wait_dial_cancel (self);
 | 
				
			||||||
 | 
						if (self->connection)
 | 
				
			||||||
 | 
							lua_connection_discard (self->connection);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free (self->hostname);
 | 
				
			||||||
 | 
						free (self->last_error);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					lua_wait_dial_on_connected (void *user_data, int socket, const char *hostname)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct lua_wait_dial *self = user_data;
 | 
				
			||||||
 | 
						if (self->super.task)
 | 
				
			||||||
 | 
							lua_task_wakeup (self->super.task);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						self->connection = lua_plugin_push_connection (self->plugin, socket);
 | 
				
			||||||
 | 
						// TODO: use the hostname for SNI once TLS is implemented
 | 
				
			||||||
 | 
						self->hostname = xstrdup (hostname);
 | 
				
			||||||
 | 
						lua_wait_dial_cancel (self);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					lua_wait_dial_on_failure (void *user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct lua_wait_dial *self = user_data;
 | 
				
			||||||
 | 
						if (self->super.task)
 | 
				
			||||||
 | 
							lua_task_wakeup (self->super.task);
 | 
				
			||||||
 | 
						lua_wait_dial_cancel (self);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					lua_wait_dial_on_error (void *user_data, const char *error)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct lua_wait_dial *self = user_data;
 | 
				
			||||||
 | 
						free (self->last_error);
 | 
				
			||||||
 | 
						self->last_error = xstrdup (error);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					lua_plugin_push_wait_dial (struct lua_plugin *plugin, lua_State *L,
 | 
				
			||||||
 | 
						const char *host, const char *service)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct lua_wait_dial *self = lua_newuserdata (L, sizeof *self);
 | 
				
			||||||
 | 
						luaL_setmetatable (L, XLUA_WCHANNEL_METATABLE);
 | 
				
			||||||
 | 
						memset (self, 0, sizeof *self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						self->super.check = lua_wait_dial_check;
 | 
				
			||||||
 | 
						self->super.cleanup = lua_wait_dial_cleanup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct connector *connector = &self->connector;
 | 
				
			||||||
 | 
						connector_init (connector, &plugin->ctx->poller);
 | 
				
			||||||
 | 
						connector_add_target (connector, host, service);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						connector->on_connected  = lua_wait_dial_on_connected;
 | 
				
			||||||
 | 
						connector->on_connecting = NULL;
 | 
				
			||||||
 | 
						connector->on_error      = lua_wait_dial_on_error;
 | 
				
			||||||
 | 
						connector->on_failure    = lua_wait_dial_on_failure;
 | 
				
			||||||
 | 
						connector->user_data     = self;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						self->plugin = plugin;
 | 
				
			||||||
 | 
						self->active = true;
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
lua_async_go (lua_State *L)
 | 
					lua_async_go (lua_State *L)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -10017,10 +9995,19 @@ lua_async_timer_ms (lua_State *L)
 | 
				
			|||||||
	return lua_plugin_push_wait_timer (plugin, L, timeout);
 | 
						return lua_plugin_push_wait_timer (plugin, L, timeout);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					lua_async_dial (lua_State *L)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct lua_plugin *plugin = lua_touserdata (L, lua_upvalueindex (1));
 | 
				
			||||||
 | 
						return lua_plugin_push_wait_dial (plugin, L,
 | 
				
			||||||
 | 
							luaL_checkstring (L, 1), luaL_checkstring (L, 2));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static luaL_Reg lua_async_library[] =
 | 
					static luaL_Reg lua_async_library[] =
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	{ "go",       lua_async_go       },
 | 
						{ "go",       lua_async_go       },
 | 
				
			||||||
	{ "timer_ms", lua_async_timer_ms },
 | 
						{ "timer_ms", lua_async_timer_ms },
 | 
				
			||||||
 | 
						{ "dial",     lua_async_dial     },
 | 
				
			||||||
	{ NULL,       NULL               },
 | 
						{ NULL,       NULL               },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -10050,7 +10037,6 @@ static luaL_Reg lua_plugin_library[] =
 | 
				
			|||||||
	{ "hook_prompt",     lua_plugin_hook_prompt     },
 | 
						{ "hook_prompt",     lua_plugin_hook_prompt     },
 | 
				
			||||||
	{ "hook_completion", lua_plugin_hook_completion },
 | 
						{ "hook_completion", lua_plugin_hook_completion },
 | 
				
			||||||
	{ "setup_config",    lua_plugin_setup_config    },
 | 
						{ "setup_config",    lua_plugin_setup_config    },
 | 
				
			||||||
	{ "connect",         lua_plugin_connect         },
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// And these are methods:
 | 
						// And these are methods:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -10332,7 +10318,6 @@ lua_plugin_load (struct app_context *ctx, const char *filename,
 | 
				
			|||||||
	lua_plugin_reg_weak (L, &lua_server_info,          lua_server_table);
 | 
						lua_plugin_reg_weak (L, &lua_server_info,          lua_server_table);
 | 
				
			||||||
	lua_plugin_reg_meta (L, XLUA_SCHEMA_METATABLE,     lua_schema_table);
 | 
						lua_plugin_reg_meta (L, XLUA_SCHEMA_METATABLE,     lua_schema_table);
 | 
				
			||||||
	lua_plugin_reg_meta (L, XLUA_CONNECTION_METATABLE, lua_connection_table);
 | 
						lua_plugin_reg_meta (L, XLUA_CONNECTION_METATABLE, lua_connection_table);
 | 
				
			||||||
	lua_plugin_reg_meta (L, XLUA_CONNECTOR_METATABLE,  lua_connector_table);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	lua_plugin_reg_meta (L, XLUA_TASK_METATABLE,       lua_task_table);
 | 
						lua_plugin_reg_meta (L, XLUA_TASK_METATABLE,       lua_task_table);
 | 
				
			||||||
	lua_plugin_reg_meta (L, XLUA_WCHANNEL_METATABLE,   lua_wchannel_table);
 | 
						lua_plugin_reg_meta (L, XLUA_WCHANNEL_METATABLE,   lua_wchannel_table);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -118,24 +118,23 @@ end
 | 
				
			|||||||
local running
 | 
					local running
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- Initiate a connection to last.fm servers
 | 
					-- Initiate a connection to last.fm servers
 | 
				
			||||||
 | 
					async, await = degesch.async, coroutine.yield
 | 
				
			||||||
local make_request = function (buffer, action)
 | 
					local make_request = function (buffer, action)
 | 
				
			||||||
	if not user or not api_key then
 | 
						if not user or not api_key then
 | 
				
			||||||
		report_error (buffer, "configuration is incomplete")
 | 
							report_error (buffer, "configuration is incomplete")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if running then running.abort () end
 | 
						if running then running:cancel () end
 | 
				
			||||||
 | 
						running = async.go (function ()
 | 
				
			||||||
	running = degesch.connect ("ws.audioscrobbler.com", 80, {
 | 
							local c, host, e = await (async.dial ("ws.audioscrobbler.com", 80))
 | 
				
			||||||
		on_success = function (c, host)
 | 
							if e then
 | 
				
			||||||
			on_connected (buffer, c, host, action)
 | 
					 | 
				
			||||||
			running = nil
 | 
					 | 
				
			||||||
		end,
 | 
					 | 
				
			||||||
		on_error   = function (e)
 | 
					 | 
				
			||||||
			report_error (buffer, e)
 | 
								report_error (buffer, e)
 | 
				
			||||||
			running = nil
 | 
							else
 | 
				
			||||||
 | 
								on_connected (buffer, c, host, action)
 | 
				
			||||||
		end
 | 
							end
 | 
				
			||||||
	})
 | 
							running = nil
 | 
				
			||||||
 | 
						end)
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user