static int server_accept(lua_State *T) { struct ev_io *w; luaL_checktype(T, 1, LUA_TUSERDATA); w = lua_touserdata(T, 1); if (w->fd < 0) return io_closed(T); if (w->data != NULL) return io_busy(T); switch (server__accept(T, w, lua_upvalueindex(1))) { case 1: return 1; case 2: close(w->fd); w->fd= -1; return 2; } w->cb = server_accept_cb; w->data = T; ev_io_start(LEM_ w); lua_settop(T, 1); lua_pushvalue(T, lua_upvalueindex(1)); return lua_yield(T, 2); }
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); }
static int file_seek(lua_State *T) { static const int mode[] = { SEEK_SET, SEEK_CUR, SEEK_END }; static const char *const modenames[] = { "set", "cur", "end", NULL }; struct file *f; int op; lua_Number offset; luaL_checktype(T, 1, LUA_TUSERDATA); op = luaL_checkoption(T, 2, "cur", modenames); offset = luaL_optnumber(T, 3, 0.); f = lua_touserdata(T, 1); f->seek.offset = (off_t)offset; luaL_argcheck(T, (lua_Number)f->seek.offset == offset, 3, "not an integer in proper range"); if (f->fd < 0) return io_closed(T); if (f->T != NULL) return io_busy(T); /* flush input buffer */ lem_inputbuf_init(&f->buf); f->T = T; f->seek.whence = mode[op]; lem_async_do(&f->a, file_seek_work, file_seek_reap); lua_settop(T, 1); return lua_yield(T, 1); }
static int file_readp(lua_State *T) { struct file *f; struct lem_parser *p; int ret; luaL_checktype(T, 1, LUA_TUSERDATA); ret = lua_type(T, 2); if (ret != LUA_TUSERDATA && ret != LUA_TLIGHTUSERDATA) return luaL_argerror(T, 2, "expected userdata"); f = lua_touserdata(T, 1); if (f->fd < 0) return io_closed(T); if (f->T != NULL) return io_busy(T); p = lua_touserdata(T, 2); if (p->init) p->init(T, &f->buf); ret = p->process(T, &f->buf); if (ret > 0) return ret; f->T = T; f->readp.p = p; lem_async_do(&f->a, file_readp_work, file_readp_reap); return lua_yield(T, lua_gettop(T)); }
static int file_close(lua_State *T) { struct file *f; luaL_checktype(T, 1, LUA_TUSERDATA); f = lua_touserdata(T, 1); if (f->fd < 0) return io_closed(T); if (f->T != NULL) return io_busy(T); f->T = T; lem_async_do(&f->a, file_close_work, file_close_reap); lua_settop(T, 1); return lua_yield(T, 1); }
static int stream_setcork(lua_State *T, int state) { struct stream *s; luaL_checktype(T, 1, LUA_TUSERDATA); s = lua_touserdata(T, 1); if (!s->open) return io_closed(T); if (s->w.data != NULL) return io_busy(T); if (setsockopt(s->w.fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(int))) return io_strerror(T, errno); lua_pushboolean(T, 1); return 1; }
static int stream_write(lua_State *T) { struct stream *s; const char *out; size_t out_len; int idx; int i; int top; int ret; luaL_checktype(T, 1, LUA_TUSERDATA); top = lua_gettop(T); idx = 1; do { out = luaL_checklstring(T, ++idx, &out_len); } while (out_len == 0 && idx < top); for (i = idx+1; i <= top; i++) (void)luaL_checkstring(T, i); s = lua_touserdata(T, 1); if (!s->open) return io_closed(T); if (s->w.data != NULL) return io_busy(T); if (out_len == 0) { lua_pushboolean(T, 1); return 1; } s->out = out; s->out_len = out_len; s->idx = idx; ret = stream__write(T, s); if (ret > 0) return ret; s->w.data = T; s->w.cb = stream_write_cb; ev_io_start(LEM_ &s->w); return lua_yield(T, top); }
static int stream_sendfile(lua_State *T) { struct stream *s; struct file *f; off_t size; off_t offset; struct sfhandle *sf; luaL_checktype(T, 1, LUA_TUSERDATA); luaL_checktype(T, 2, LUA_TUSERDATA); size = (off_t)luaL_checknumber(T, 3); offset = (off_t)luaL_optnumber(T, 4, 0); s = lua_touserdata(T, 1); if (!s->open) return io_closed(T); if (s->w.data != NULL) return io_busy(T); f = lua_touserdata(T, 2); if (f->fd < 0) { lua_pushnil(T); lua_pushliteral(T, "file closed"); return 2; } s->w.data = T; sf = lem_xmalloc(sizeof(struct sfhandle)); sf->T = T; sf->s = s; sf->size = size; sf->offset = offset; sf->fd = f->fd; lem_async_do(&sf->a, stream_sendfile_work, stream_sendfile_reap); lua_settop(T, 2); return lua_yield(T, 2); }
static int file_write(lua_State *T) { struct file *f; const char *str; size_t len; int idx; int i; int top; luaL_checktype(T, 1, LUA_TUSERDATA); top = lua_gettop(T); idx = 1; do { str = luaL_checklstring(T, ++idx, &len); } while (len == 0 && idx < top); for (i = idx+1; i <= top; i++) (void)luaL_checkstring(T, i); f = lua_touserdata(T, 1); if (f->fd < 0) return io_closed(T); if (f->T != NULL) return io_busy(T); if (len == 0) { lua_pushboolean(T, 1); return 1; } f->T = T; f->write.str = str; f->write.len = len; f->write.idx = idx; lem_async_do(&f->a, file_write_work, file_write_reap); return lua_yield(T, top); }
static int stream_readp(lua_State *T) { struct stream *s; struct lem_parser *p; int ret; luaL_checktype(T, 1, LUA_TUSERDATA); ret = lua_type(T, 2); if (ret != LUA_TUSERDATA && ret != LUA_TLIGHTUSERDATA) return luaL_argerror(T, 2, "expected userdata"); s = lua_touserdata(T, 1); if (!s->open) return io_closed(T); if (s->r.data != NULL) return io_busy(T); p = lua_touserdata(T, 2); if (p->init) p->init(T, &s->buf); ret = p->process(T, &s->buf); if (ret > 0) return ret; s->p = p; ret = stream__readp(T, s); if (ret > 0) return ret; s->r.data = T; s->r.cb = stream_readp_cb; ev_io_start(LEM_ &s->r); return lua_yield(T, lua_gettop(T)); }
/* * file:lock() method */ static void file_lock_work(struct lem_async *a) { struct file *f = (struct file *)a; struct flock fl = { .l_type = f->lock.type, .l_whence = SEEK_SET, .l_start = f->lock.start, .l_len = f->lock.len, }; if (fcntl(f->fd, F_SETLK, &fl) == -1) f->ret = errno; else f->ret = 0; } static void file_lock_reap(struct lem_async *a) { struct file *f = (struct file *)a; lua_State *T = f->T; f->T = NULL; if (f->ret) { lem_queue(T, io_strerror(T, f->ret)); return; } lua_pushboolean(T, 1); lem_queue(T, 1); } static int file_lock(lua_State *T) { static const short mode[] = { F_RDLCK, F_WRLCK, F_UNLCK }; static const char *const modenames[] = { "r", "w", "u", NULL }; struct file *f; int op; lua_Number start; lua_Number len; luaL_checktype(T, 1, LUA_TUSERDATA); op = luaL_checkoption(T, 2, NULL, modenames); start = luaL_optnumber(T, 3, 0); len = luaL_optnumber(T, 4, 0); f = lua_touserdata(T, 1); f->lock.start = (off_t)start; luaL_argcheck(T, (lua_Number)f->lock.start == start, 3, "not an integer in proper range"); f->lock.len = (off_t)len; luaL_argcheck(T, (lua_Number)f->lock.len == len, 4, "not an integer in proper range"); if (f->fd < 0) return io_closed(T); if (f->T != NULL) return io_busy(T); f->T = T; f->lock.type = mode[op]; lem_async_do(&f->a, file_lock_work, file_lock_reap); lua_settop(T, 1); return lua_yield(T, 1); }