Esempio n. 1
0
File: server.c Progetto: esmil/lem
static int
server_close(lua_State *T)
{
	struct ev_io *w;
	int ret;

	luaL_checktype(T, 1, LUA_TUSERDATA);
	w = lua_touserdata(T, 1);
	if (w->fd < 0)
		return io_closed(T);

	if (w->data != NULL) {
		lem_debug("interrupting listen");
		ev_io_stop(LEM_ w);
		lua_pushnil(w->data);
		lua_pushliteral(w->data, "interrupted");
		lem_queue(w->data, 2);
		w->data = NULL;
	}

	lem_debug("closing server..");

	ret = close(w->fd);
	w->fd = -1;
	if (ret)
		return io_strerror(T, errno);

	lua_pushboolean(T, 1);
	return 1;
}
Esempio n. 2
0
static void
stmt_step_reap(struct lem_async *a)
{
	struct db *db = (struct db *)a;
	lua_State *T = db->T;
	sqlite3_stmt *stmt = db->req.prep.stmt;
	int ret;

	switch (db->ret) {
	case SQLITE_ROW:
		lem_debug("SQLITE_ROW");
		pushrow(T, stmt);
		ret = 1;
		break;

	case SQLITE_DONE:
		lem_debug("SQLITE_DONE");
		(void)sqlite3_reset(stmt);
		(void)sqlite3_clear_bindings(stmt);
		lua_pushboolean(T, 1);
		ret = 1;
		break;

	default:
		lem_debug("Ack!");
		lua_pushnil(T);
		lua_pushstring(T, sqlite3_errmsg(db->handle));
		ret = 2;
	}

	lem_queue(T, ret);
	db->T = NULL;
}
Esempio n. 3
0
File: stream.c Progetto: esmil/lem
/*
 * stream:write() method
 */
static int
stream__write(lua_State *T, struct stream *s)
{
	ssize_t bytes;
	int err;

	while ((bytes = write(s->w.fd, s->out, s->out_len)) > 0) {
		lem_debug("wrote %ld bytes to fd %d", bytes, s->w.fd);
		s->out += bytes;
		s->out_len -= bytes;
		while (s->out_len == 0) {
			if (s->idx == lua_gettop(T)) {
				lua_pushboolean(T, 1);
				return 1;
			}
			s->out = lua_tolstring(T, ++s->idx, &s->out_len);
		}
	}
	err = errno;
	lem_debug("wrote %ld bytes to fd %d", bytes, s->w.fd);

	if (bytes < 0 && (err == EAGAIN || err == EINTR))
		return 0;

	s->open = 0;
	close(s->w.fd);

	if (bytes == 0 || err == ECONNRESET || err == EPIPE)
		return io_closed(T);

	return io_strerror(T, err);
}
Esempio n. 4
0
static void
db_open_reap(struct lem_async *a)
{
	struct db *db = (struct db *)a;
	lua_State *T = db->T;
	int ret;

	if (db->handle == NULL) {
		lem_debug("db->handle == NULL");
		lua_pushnil(T);
		lua_pushliteral(T, "out of memory");
		db_unref(db);
		ret = 2;
	} else if (db->ret != SQLITE_OK) {
		lem_debug("db->ret != SQLITE_OK");
		lua_pushnil(T);
		lua_pushstring(T, sqlite3_errmsg(db->handle));
		db_unref(db);
		ret = 2;
	} else {
		struct box *box = lua_newuserdata(T, sizeof(struct box));

		lem_debug("Success!");
		box->db = db;

		/* set metatable */
		lua_pushvalue(T, 2);
		lua_setmetatable(T, -2);

		ret = 1;
	}

	lem_queue(T, ret);
	db->T = NULL;
}
Esempio n. 5
0
static void
defer_enable(struct pa_defer_event *ev, int b)
{
	if (b) {
		lem_debug("starting");
		ev_idle_start(LEM_ &ev->w);
	} else {
		lem_debug("stopping");
		ev_idle_stop(LEM_ &ev->w);
	}
}
Esempio n. 6
0
File: stream.c Progetto: esmil/lem
static void
stream_sendfile_work(struct lem_async *a)
{
	struct sfhandle *sf = (struct sfhandle *)a;
	struct stream *s = sf->s;

	/* make socket blocking */
	if (fcntl(s->w.fd, F_SETFL, 0) == -1) {
		sf->ret = errno;
		return;
	}

#ifdef __FreeBSD__
	off_t written;
	int ret = sendfile(sf->fd, s->w.fd,
			sf->offset, sf->size,
			NULL, &written, SF_SYNC);
	if (ret == 0) {
		sf->ret = 0;
		sf->size = written;
	} else
		sf->ret = errno;
	lem_debug("wrote = %ld bytes", written);
#else
#ifdef __APPLE__
	int ret = sendfile(sf->fd, s->w.fd,
			sf->offset, &sf->size,
			NULL, 0);
	if (ret == 0)
		sf->ret = 0;
	else
		sf->ret = errno;
	lem_debug("wrote = %lld bytes", sf->size);
#else
	ssize_t ret = sendfile(s->w.fd, sf->fd,
			&sf->offset, sf->size);
	if (ret >= 0) {
		sf->ret = 0;
		sf->size = ret;
	} else
		sf->ret = errno;
	lem_debug("wrote = %ld bytes", ret);
#endif
#endif

	/* make socket non-blocking again */
	if (fcntl(s->w.fd, F_SETFL, O_NONBLOCK) == -1) {
		sf->ret = errno;
		return;
	}
}
Esempio n. 7
0
static struct pa_io_event *
io_new(pa_mainloop_api *a, int fd, pa_io_event_flags_t events,
		pa_io_event_cb_t cb, void *userdata)
{
	struct pa_io_event *ev = lem_xmalloc(sizeof(struct pa_io_event));
	int revents = 0;

	(void)a;
	lem_debug("flags = %d", events);

	if (events & PA_IO_EVENT_INPUT)
		revents |= EV_READ;
	if (events & PA_IO_EVENT_OUTPUT)
		revents |= EV_WRITE;
	if (events & PA_IO_EVENT_HANGUP)
		revents |= EV_READ;

	ev_io_init(&ev->w, io_handler, fd, revents);
	ev->w.data = userdata;
	ev->cb = cb;
	ev->destroy = NULL;

	if (revents)
		ev_io_start(LEM_ &ev->w);
	return ev;
}
Esempio n. 8
0
static DBusHandlerResult
signal_handler(lua_State *S, DBusMessage *msg)
{
	lua_State *T;
	const char *path = dbus_message_get_path(msg);
	const char *interface = dbus_message_get_interface(msg);
	const char *member = dbus_message_get_member(msg);

	lem_debug("received signal\n  %s\n  %s\n  %s(%s)",
	          path, interface, member,
	          dbus_message_get_signature(msg));

	/* NOTE: this magic string representation of an
	 * incoming signal must match the one in the Lua code */
	lua_pushfstring(S, "%s\n%s\n%s",
	                path      ? path      : "",
	                interface ? interface : "",
	                member    ? member    : "");

	lua_rawget(S, LEM_DBUS_SIGNAL_TABLE);
	if (lua_type(S, -1) != LUA_TFUNCTION) {
		lua_settop(S, LEM_DBUS_TOP);
		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
	}

	/* create new thread */
	T = lem_newthread();
	lua_xmove(S, T, 1);

	lem_queue(T, lem_dbus_push_arguments(T, msg));

	return DBUS_HANDLER_RESULT_HANDLED;
}
Esempio n. 9
0
static void
loop_quit(pa_mainloop_api *a, int retval)
{
	(void)a;
	(void)retval;
	lem_debug("Hmm.. pulseaudio wants us to quit with retval %d", retval);
}
Esempio n. 10
0
static void
timeout_toggle(DBusTimeout *timeout, void *data)
{
	struct timeout *t;

	(void)data;

	lem_debug("timeout = %p, interval = %d, enabled = %s",
	          (void *)timeout,
	          dbus_timeout_get_interval(timeout),
	          dbus_timeout_get_enabled(timeout) ? "true" : "false");

	t = dbus_timeout_get_data(timeout);
	if (dbus_timeout_get_enabled(timeout)) {
		ev_tstamp interval =
			((ev_tstamp)dbus_timeout_get_interval(timeout))/1000.0;

		if (ev_is_active(&t->ev))
			ev_timer_stop(EV_G_ &t->ev);

		ev_timer_set(&t->ev, interval, interval);
		ev_timer_start(EV_G_ &t->ev);
	} else
		ev_timer_stop(EV_G_ &t->ev);
}
Esempio n. 11
0
File: server.c Progetto: esmil/lem
static int
server_autospawn(lua_State *T)
{
	struct ev_io *w;

	luaL_checktype(T, 1, LUA_TUSERDATA);
	luaL_checktype(T, 2, LUA_TFUNCTION);

	w = lua_touserdata(T, 1);
	if (w->fd < 0)
		return io_closed(T);
	if (w->data != NULL)
		return io_busy(T);

	w->cb = server_autospawn_cb;
	w->data = T;
	ev_io_start(LEM_ w);

	lem_debug("yielding");

	/* yield server object, function and metatable*/
	lua_settop(T, 2);
	lua_pushvalue(T, lua_upvalueindex(1));
	return lua_yield(T, 3);
}
Esempio n. 12
0
/*
 * Bus:close()
 *
 * argument 1: bus object
 */
static int
bus_close(lua_State *T)
{
	struct bus_object *obj;

	luaL_checktype(T, 1, LUA_TUSERDATA);
	obj = lua_touserdata(T, 1);
	if (obj->conn == NULL) {
		lua_pushnil(T);
		lua_pushliteral(T, "closed");
		return 2;
	}

	lem_debug("closing DBus connection");

	dbus_connection_close(obj->conn);
	dbus_connection_unref(obj->conn);
	obj->conn = NULL;

	lua_getfenv(T, 1);

	lua_pushnil(T);
	lua_rawseti(T, -2, 1);
	lua_pushnil(T);
	lua_rawseti(T, -2, 2);

	lua_pushboolean(T, 1);
	return 1;
}
Esempio n. 13
0
static void
time_handler(EV_P_ struct ev_timer *w, int revents)
{
	struct pa_time_event *ev = (struct pa_time_event *)w;

	(void)revents;
	lem_debug("callback..");
	ev->cb(&loop_api, ev, &ev->tv, ev->w.data);
}
Esempio n. 14
0
static void
time_free(pa_time_event *ev)
{
	lem_debug("freeing event %p", ev);
	ev_timer_stop(LEM_ &ev->w);
	if (ev->destroy)
		ev->destroy(&loop_api, ev, ev->w.data);
	free(ev);
}
Esempio n. 15
0
static void
defer_free(struct pa_defer_event *ev)
{
	lem_debug("freeing event %p", ev);
	if (ev->destroy)
		ev->destroy(&loop_api, ev, ev->w.data);
	ev_idle_stop(LEM_ &ev->w);
	free(ev);
}
Esempio n. 16
0
File: lem.c Progetto: halfd/lem
void
lem_queue(lua_State *T, int nargs)
{
	struct lem_runqueue_slot *slot;

	assert(T != NULL);
	lem_debug("enqueueing thread with %d argument%s",
	              nargs, nargs == 1 ? "" : "s");

	if (rq.first == rq.last)
		ev_idle_start(LEM_ &rq.w);

	slot = &rq.queue[rq.last];
	slot->T = T;
	slot->nargs = nargs;

	rq.last++;
	rq.last &= rq.mask;
	if (rq.first == rq.last) {
		unsigned int i;
		unsigned int j;
		struct lem_runqueue_slot *new_queue;

		lem_debug("expanding queue to %u slots", 2*(rq.mask + 1));
		new_queue = lem_xmalloc(2*(rq.mask + 1)
				* sizeof(struct lem_runqueue_slot));

		i = 0;
		j = rq.first;
		do {
			new_queue[i] = rq.queue[j];

			i++;
			j++;
			j &= rq.mask;
		} while (j != rq.first);

		free(rq.queue);
		rq.queue = new_queue;
		rq.first = 0;
		rq.last = i;
		rq.mask = 2*rq.mask + 1;
	}
}
Esempio n. 17
0
/*
 * Proxy:parse()
 *
 * upvalue 1: Method
 * upvalue 2: Signal
 *
 * argument 1: proxy
 * argument 2: xml string
 */
EXPORT int
lem_dbus_proxy_parse(lua_State *L)
{
	XML_Parser p;
	struct parsedata pd;
	const char *xml;

	/* drop extra arguments */
	lua_settop(L, 2);

	/* get the xml string */
	xml = luaL_checkstring(L, 2);

	/* put the object name on the stack */
	lua_getfield(L, 1, "object");
	if (lua_isnil(L, 3))
		return luaL_argerror(L, 2, "no object set in the proxy");

	/* create parser and initialise it */
	p = XML_ParserCreate("UTF-8");
	if (!p) {
		lua_pushnil(L);
		lua_pushliteral(L, "out of memory");
		return 2;
	}

	pd.L = L;
	pd.level = 0;
	pd.interface = 0;
	pd.type = 0;
	pd.signature[0] = '\0';
	pd.result[0] = '\0';
	pd.sig_next = pd.signature;
	pd.res_next = pd.result;

	XML_SetUserData(p, &pd);
	XML_SetElementHandler(p, start_element_handler,
	                      end_element_handler);

	/* now parse the xml document inserting methods as we go */
	if (!XML_Parse(p, xml, strlen(xml), 1)) {
		lem_debug("parse error at line %d:\n%s\n",
		          (int)XML_GetCurrentLineNumber(p),
		          XML_ErrorString(XML_GetErrorCode(p)));
		lua_pushnil(L);
		lua_pushliteral(L, "error parsing introspection data");
		return 2;
	}

	/* free the parser */
	XML_ParserFree(p);

	/* return true */
	lua_pushboolean(L, 1);
	return 1;
}
Esempio n. 18
0
/*
 * Defer Events
 */
static void
defer_handler(EV_P_ struct ev_idle *w, int revents)
{
	struct pa_defer_event *ev = (struct pa_defer_event *)w;

	(void)revents;
	lem_debug("callback..");

	ev->cb(&loop_api, ev, ev->w.data);
}
Esempio n. 19
0
File: stream.c Progetto: esmil/lem
/*
 * stream:readp() method
 */
static int
stream__readp(lua_State *T, struct stream *s)
{
	ssize_t bytes;
	int ret;
	int err;
	enum lem_preason res;

	while ((bytes = read(s->r.fd, s->buf.buf + s->buf.end,
					LEM_INPUTBUF_SIZE - s->buf.end)) > 0) {
		lem_debug("read %ld bytes from %d", bytes, s->r.fd);

		s->buf.end += bytes;

		ret = s->p->process(T, &s->buf);
		if (ret > 0)
			return ret;
	}
	err = errno;
	lem_debug("read %ld bytes from %d", bytes, s->r.fd);

	if (bytes < 0 && (err == EAGAIN || err == EINTR))
		return 0;

	if (bytes == 0 || err == ECONNRESET || err == EPIPE)
		res = LEM_PCLOSED;
	else
		res = LEM_PERROR;

	s->open = 0;
	close(s->r.fd);

	if (s->p->destroy && (ret = s->p->destroy(T, &s->buf, res)) > 0)
		return ret;

	lua_settop(T, 0);
	if (res == LEM_PCLOSED)
		return io_closed(T);

	return io_strerror(T, err);
}
Esempio n. 20
0
static void
db_unref(struct db *db)
{
	db->refs--;
	if (db->refs)
		return;

	lem_debug("db->refs = %d, freeing", db->refs);

	(void)sqlite3_close(db->handle);
	free(db);
}
Esempio n. 21
0
static void
db_exec_prepare_reap(struct lem_async *a)
{
	struct db *db = (struct db *)a;
	lua_State *T = db->T;
	int ret;

	if (db->ret != SQLITE_OK) {
		lem_debug("db->ret != SQLITE_OK");
		lua_pushnil(T);
		lua_pushstring(T, sqlite3_errmsg(db->handle));
		ret = 2;
		goto out;
	}

	lem_debug("db->ret == SQLITE_OK");
	if (db->req.prep.stmt == NULL) {
		lem_debug("db->req.prep.stmt == NULL");
		lua_pushboolean(T, 1);
		ret = 1;
		goto out;
	}

	if (lua_gettop(T) > 1 && bindtable(T, db->req.prep.stmt)) {
		(void)sqlite3_finalize(db->req.prep.stmt);
		lua_pushnil(T);
		lua_insert(T, -2);
		ret = 2;
		goto out;
	}

	db->a.work = db_step_work;
	db->a.reap = db_exec_step_reap;
	lem_async_run(&db->a);
	return;
out:
	lem_queue(T, ret);
	db->T = NULL;
}
Esempio n. 22
0
static DBusHandlerResult
method_call_handler(lua_State *S, DBusMessage *msg)
{
	lua_State *T;
	struct message_object *m;
	const char *path = dbus_message_get_path(msg);
	const char *interface = dbus_message_get_interface(msg);
	const char *member = dbus_message_get_member(msg);

	lem_debug("received call\n  %s\n  %s\n  %s(%s)",
	          path, interface, member,
		  dbus_message_get_signature(msg));

	lua_pushstring(S, path ? path : "");
	lua_rawget(S, LEM_DBUS_OBJECT_TABLE);
	if (lua_type(S, -1) != LUA_TTABLE) {
		lua_settop(S, LEM_DBUS_TOP);
		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
	}

	lua_pushfstring(S, "%s.%s",
	                interface ? interface : "",
	                member    ? member    : "");
	lua_rawget(S, -2);
	if (lua_type(S, -1) != LUA_TFUNCTION) {
		lua_settop(S, LEM_DBUS_TOP);
		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
	}

	/* create new thread */
	T = lem_newthread();
	lua_pushvalue(S, LEM_DBUS_BUS_OBJECT);
	lua_xmove(S, T, 2);
	lua_settop(S, LEM_DBUS_TOP);

	/* push the send_reply function */
	m = lua_newuserdata(T, sizeof(struct message_object));
	m->msg = msg;
	dbus_message_ref(msg);

	/* set metatable */
	lua_pushvalue(S, LEM_DBUS_MESSAGE_META);
	lua_xmove(S, T, 1);
	lua_setmetatable(T, -2);

	lua_pushcclosure(T, message_reply, 2);

	lem_queue(T, lem_dbus_push_arguments(T, msg) + 1);

	return DBUS_HANDLER_RESULT_HANDLED;
}
Esempio n. 23
0
/*
 * Bus:send_signal()
 *
 * argument 1: bus object
 * argument 2: path
 * argument 3: interface
 * argument 4: name
 * argument 5: signature (optional)
 * ...
 */
static int
bus_send_signal(lua_State *T)
{
	DBusConnection *conn;
	const char *path;
	const char *interface;
	const char *name;
	const char *signature;
	DBusMessage *msg;

	luaL_checktype(T, 1, LUA_TUSERDATA);
	path      = luaL_checkstring(T, 2);
	interface = luaL_checkstring(T, 3);
	name      = luaL_checkstring(T, 4);
	signature = luaL_optstring(T, 5, NULL);

	conn = bus_unbox(T, 1);
	if (conn == NULL) {
		lua_pushnil(T);
		lua_pushliteral(T, "closed");
		return 2;
	}

	if (interface && interface[0] == '\0')
		interface = NULL;

	lem_debug("%s, %s, %s", path, interface ? interface : "(no interface)", name);

	msg = dbus_message_new_signal(path, interface, name);
	if (msg == NULL)
		goto oom;

	if (signature && signature[0] != '\0' &&
	    lem_dbus_add_arguments(T, 6, signature, msg))
		return luaL_error(T, "%s", lua_tostring(T, -1));

	if (!dbus_connection_send(conn, msg, NULL))
		goto oom;

	dbus_message_unref(msg);
	lua_pushboolean(T, 1);
	return 1;

oom:
	if (msg)
		dbus_message_unref(msg);
	lua_pushnil(T);
	lua_pushliteral(T, "out of memory");
	return 2;
}
Esempio n. 24
0
/*
 * DBus.__gc()
 *
 * argument 1: bus object
 */
static int
bus_gc(lua_State *T)
{
	DBusConnection *conn = bus_unbox(T, 1);

	lem_debug("collecting DBus connection");

	if (conn) {
		dbus_connection_close(conn);
		dbus_connection_unref(conn);
	}

	return 0;
}
Esempio n. 25
0
static void
time_restart(pa_time_event *ev, const struct timeval *tv)
{
	ev_tstamp timeout = timeval_to_stamp(tv);

	lem_debug("resetting to %f seconds", timeout - ev_now(LEM));

	ev->tv.tv_sec = tv->tv_sec;
	ev->tv.tv_usec = tv->tv_usec;

	ev_timer_stop(LEM_ &ev->w);
	ev_timer_set(&ev->w, timeout - ev_now(LEM), 0);
	ev_timer_start(LEM_ &ev->w);
}
Esempio n. 26
0
static void
db_prepare_reap(struct lem_async *a)
{
	struct db *db = (struct db *)a;
	lua_State *T = db->T;
	int ret;

	if (db->ret != SQLITE_OK) {
		lem_debug("db->ret != SQLITE_OK");
		lua_pushnil(T);
		lua_pushstring(T, sqlite3_errmsg(db->handle));
		ret = 2;
		db_unref(db);
	} else if (db->req.prep.stmt == NULL) {
		lem_debug("db->req.prep.stmt == NULL");
		lua_pushnil(T);
		lua_pushliteral(T, "nosql");
		ret = 2;
		db_unref(db);
	} else {
		struct stmt *stmt = lua_newuserdata(T, sizeof(struct stmt));

		lem_debug("Success!");
		stmt->handle = db->req.prep.stmt;
		stmt->db = db;

		/* set metatable */
		lua_pushvalue(T, 3);
		lua_setmetatable(T, -2);

		ret = 1;
	}

	lem_queue(T, ret);
	db->T = NULL;
}
Esempio n. 27
0
/*
 * IO Events
 */
static void
io_handler(EV_P_ ev_io *w, int revents)
{
	struct pa_io_event *ev = (struct pa_io_event *)w;
	pa_io_event_flags_t events = PA_IO_EVENT_NULL;

	if (revents & EV_READ)
		events |= PA_IO_EVENT_INPUT;
	if (revents & EV_WRITE)
		events |= PA_IO_EVENT_OUTPUT;
	if (revents & EV_ERROR)
		events |= PA_IO_EVENT_ERROR;

	lem_debug("flags = %d", events);
	ev->cb(&loop_api, ev, ev->w.fd, events, ev->w.data);
}
Esempio n. 28
0
File: file.c Progetto: halfd/lem
static int
file_gc(lua_State *T)
{
	struct file *f = lua_touserdata(T, 1);

	lem_debug("collecting %p, fd = %d", f, f->fd);
	if (f->fd >= 0) {
		struct file_gc *gc = lem_xmalloc(sizeof(struct file_gc));

		gc->fd = f->fd;
		f->fd = -1;
		lem_async_do(&gc->a, file_gc_work, NULL);
	}

	return 0;
}
Esempio n. 29
0
static void
timeout_remove(DBusTimeout *timeout, void *data)
{
	struct timeout *t;

	(void)data;

	lem_debug("timeout = %p, interval = %d, enabled = %s",
	          (void *)timeout,
	          dbus_timeout_get_interval(timeout),
	          dbus_timeout_get_enabled(timeout) ? "true" : "false");

	t = dbus_timeout_get_data(timeout);
	ev_timer_stop(EV_G_ &t->ev);
	free(t);
}
Esempio n. 30
0
static struct pa_defer_event *
defer_new(pa_mainloop_api *a, pa_defer_event_cb_t cb, void *userdata)
{
	struct pa_defer_event *ev = lem_xmalloc(sizeof(struct pa_defer_event));

	(void)a;
	lem_debug("new defer %p", ev);

	ev_idle_init(&ev->w, defer_handler);
	ev->w.data = userdata;
	ev->cb = cb;
	ev->destroy = NULL;

	ev_idle_start(LEM_ &ev->w);
	return ev;
}