moonbridge

annotate moonbridge_io.c @ 80:1a0346580e6d

Blocking :write(...) and :flush(...) methods in I/O library
author jbe
date Mon Apr 06 01:35:23 2015 +0200 (2015-04-06)
parents 22dbb9d09f02
children e1aec772a6ab
rev   line source
jbe@79 1
jbe@79 2 #include <stdlib.h>
jbe@79 3 #include <unistd.h>
jbe@79 4 #include <stdint.h>
jbe@79 5 #include <errno.h>
jbe@79 6 #include <string.h>
jbe@79 7 #include <stdio.h>
jbe@79 8 #include <time.h>
jbe@79 9 #include <sys/time.h>
jbe@79 10 #include <sys/socket.h>
jbe@79 11 #include <sys/select.h>
jbe@79 12
jbe@79 13 #include <lua.h>
jbe@79 14 #include <lauxlib.h>
jbe@79 15 #include <lualib.h>
jbe@79 16
jbe@80 17 #define MOONBR_IO_MAXSTRERRORLEN 80
jbe@80 18 #define MOONBR_IO_WRITEBUFLEN 4096
jbe@80 19
jbe@80 20 #define moonbr_io_errmsg() \
jbe@80 21 char errmsg[MOONBR_IO_MAXSTRERRORLEN]; \
jbe@80 22 strerror_r(errno, errmsg, MOONBR_IO_MAXSTRERRORLEN)
jbe@80 23
jbe@80 24
jbe@79 25 #define MOONBR_IO_HANDLE_MT_REGKEY "moonbridge_io_handle"
jbe@79 26 #define MOONBR_IO_HANDLE_PUBLIC_MT_REGKEY "moonbridge_io_handle_public"
jbe@79 27
jbe@79 28 typedef struct {
jbe@79 29 int fd;
jbe@80 30 int writecnt;
jbe@80 31 char writebuf[MOONBR_IO_WRITEBUFLEN];
jbe@79 32 } moonbr_io_handle_t;
jbe@79 33
jbe@80 34 static int moonbr_io_close(lua_State *L) {
jbe@80 35 moonbr_io_handle_t *handle;
jbe@80 36 handle = luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY);
jbe@80 37 if (handle->fd < 0) luaL_error(L, "Attempt to close a closed I/O handle");
jbe@80 38 if (close(handle->fd)) {
jbe@80 39 handle->fd = -1;
jbe@80 40 moonbr_io_errmsg();
jbe@80 41 lua_pushnil(L);
jbe@80 42 lua_pushstring(L, errmsg);
jbe@80 43 return 2;
jbe@80 44 }
jbe@80 45 handle->fd = -1;
jbe@80 46 lua_pushboolean(L, 1);
jbe@80 47 return 1;
jbe@80 48 }
jbe@80 49
jbe@80 50 static int moonbr_io_write(lua_State *L) {
jbe@80 51 moonbr_io_handle_t *handle;
jbe@80 52 int i, top;
jbe@80 53 const char *str;
jbe@80 54 size_t strlen;
jbe@80 55 size_t written;
jbe@80 56 ssize_t result;
jbe@80 57 handle = luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY);
jbe@80 58 if (handle->writecnt < 0) {
jbe@80 59 lua_pushnil(L);
jbe@80 60 lua_pushliteral(L, "Previous write error");
jbe@80 61 return 2;
jbe@80 62 }
jbe@80 63 top = lua_gettop(L);
jbe@80 64 for (i=2; i<=top; i++) {
jbe@80 65 str = luaL_checklstring(L, i, &strlen);
jbe@80 66 while (strlen) {
jbe@80 67 if (strlen < MOONBR_IO_WRITEBUFLEN - handle->writecnt) {
jbe@80 68 memcpy(handle->writebuf + handle->writecnt, str, strlen);
jbe@80 69 handle->writecnt += strlen;
jbe@80 70 break;
jbe@80 71 } else {
jbe@80 72 written = 0;
jbe@80 73 memcpy(handle->writebuf + handle->writecnt, str, MOONBR_IO_WRITEBUFLEN - handle->writecnt);
jbe@80 74 while (written < MOONBR_IO_WRITEBUFLEN) {
jbe@80 75 result = write(handle->fd, handle->writebuf + written, MOONBR_IO_WRITEBUFLEN - written);
jbe@80 76 if (result < 0) {
jbe@80 77 if (errno != EINTR) {
jbe@80 78 moonbr_io_errmsg();
jbe@80 79 handle->writecnt = -1;
jbe@80 80 lua_pushnil(L);
jbe@80 81 lua_pushstring(L, errmsg);
jbe@80 82 return 2;
jbe@80 83 }
jbe@80 84 } else {
jbe@80 85 written += result;
jbe@80 86 }
jbe@80 87 }
jbe@80 88 str += MOONBR_IO_WRITEBUFLEN - handle->writecnt;
jbe@80 89 strlen -= MOONBR_IO_WRITEBUFLEN - handle->writecnt;
jbe@80 90 handle->writecnt = 0;
jbe@80 91 }
jbe@80 92 }
jbe@80 93 }
jbe@80 94 lua_settop(L, 1);
jbe@80 95 return 1;
jbe@80 96 }
jbe@80 97
jbe@80 98 static int moonbr_io_flush(lua_State *L) {
jbe@80 99 moonbr_io_handle_t *handle;
jbe@80 100 size_t written;
jbe@80 101 ssize_t result;
jbe@80 102 handle = luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY);
jbe@80 103 if (handle->writecnt < 0) {
jbe@80 104 lua_pushnil(L);
jbe@80 105 lua_pushliteral(L, "Previous write error");
jbe@80 106 return 2;
jbe@80 107 }
jbe@80 108 written = 0;
jbe@80 109 while (written < handle->writecnt) {
jbe@80 110 result = write(handle->fd, handle->writebuf + written, handle->writecnt - written);
jbe@80 111 if (result < 0) {
jbe@80 112 if (errno != EINTR) {
jbe@80 113 moonbr_io_errmsg();
jbe@80 114 handle->writecnt = -1;
jbe@80 115 lua_pushnil(L);
jbe@80 116 lua_pushstring(L, errmsg);
jbe@80 117 return 2;
jbe@80 118 }
jbe@80 119 } else {
jbe@80 120 written += result;
jbe@80 121 }
jbe@80 122 }
jbe@80 123 handle->writecnt = 0;
jbe@80 124 lua_settop(L, 1);
jbe@80 125 return 1;
jbe@80 126 }
jbe@80 127
jbe@80 128 void moonbr_io_pushhandle(lua_State *L, int fd, int gc_idx) {
jbe@79 129 moonbr_io_handle_t *handle;
jbe@79 130 handle = lua_newuserdata(L, sizeof(moonbr_io_handle_t));
jbe@79 131 handle->fd = fd;
jbe@80 132 handle->writecnt = 0;
jbe@79 133 luaL_getmetatable(L, MOONBR_IO_HANDLE_MT_REGKEY);
jbe@79 134 lua_setmetatable(L, -2);
jbe@79 135 lua_newtable(L); // uservalue
jbe@80 136 if (gc_idx) lua_pushvalue(L, gc_idx);
jbe@80 137 else lua_pushcfunction(L, moonbr_io_close);
jbe@80 138 lua_setfield(L, -2, "gc");
jbe@79 139 lua_newtable(L); // public
jbe@79 140 luaL_getmetatable(L, MOONBR_IO_HANDLE_PUBLIC_MT_REGKEY);
jbe@79 141 lua_setmetatable(L, -2);
jbe@79 142 lua_setfield(L, -2, "public");
jbe@79 143 lua_setuservalue(L, -2);
jbe@79 144 }
jbe@79 145
jbe@79 146 static int moonbr_io_handleindex(lua_State *L) {
jbe@80 147 luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY);
jbe@79 148 lua_getuservalue(L, 1);
jbe@79 149 lua_getfield(L, -1, "public");
jbe@79 150 lua_pushvalue(L, 2);
jbe@79 151 lua_gettable(L, -2);
jbe@79 152 return 1;
jbe@79 153 }
jbe@79 154
jbe@79 155 static int moonbr_io_handlenewindex(lua_State *L) {
jbe@80 156 luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY);
jbe@79 157 lua_getuservalue(L, 1);
jbe@79 158 lua_getfield(L, -1, "public");
jbe@79 159 lua_pushvalue(L, 2);
jbe@79 160 lua_pushvalue(L, 3);
jbe@79 161 lua_settable(L, -3);
jbe@79 162 return 0;
jbe@79 163 }
jbe@79 164
jbe@80 165 static int moonbr_io_handlegc(lua_State *L) {
jbe@80 166 moonbr_io_handle_t *handle;
jbe@80 167 handle = luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY);
jbe@80 168 if (handle->fd >= 0) {
jbe@80 169 lua_getuservalue(L, 1);
jbe@80 170 lua_getfield(L, -1, "gc");
jbe@80 171 lua_pushvalue(L, 1);
jbe@80 172 lua_call(L, 1, 0);
jbe@80 173 }
jbe@80 174 return 0;
jbe@80 175 }
jbe@80 176
jbe@79 177 static int moonbr_io_getdummy(lua_State *L) {
jbe@80 178 moonbr_io_pushhandle(L, 2, 0);
jbe@79 179 return 1;
jbe@79 180 }
jbe@79 181
jbe@79 182 static const struct luaL_Reg moonbr_io_handle_methods[] = {
jbe@80 183 {"close", moonbr_io_close},
jbe@80 184 {"write", moonbr_io_write},
jbe@80 185 {"flush", moonbr_io_flush},
jbe@79 186 {NULL, NULL}
jbe@79 187 };
jbe@79 188
jbe@79 189 static const struct luaL_Reg moonbr_io_handle_metamethods[] = {
jbe@79 190 {"__index", moonbr_io_handleindex},
jbe@79 191 {"__newindex", moonbr_io_handlenewindex},
jbe@80 192 {"__gc", moonbr_io_handlegc},
jbe@79 193 {NULL, NULL}
jbe@79 194 };
jbe@79 195
jbe@79 196 static const struct luaL_Reg moonbr_io_module_funcs[] = {
jbe@79 197 {"getdummy", moonbr_io_getdummy},
jbe@79 198 {NULL, NULL}
jbe@79 199 };
jbe@79 200
jbe@79 201 int luaopen_moonbridge_io(lua_State *L) {
jbe@79 202
jbe@80 203 lua_newtable(L); // module
jbe@80 204
jbe@79 205 lua_newtable(L); // public metatable
jbe@79 206 lua_newtable(L); // handle methods
jbe@79 207 luaL_setfuncs(L, moonbr_io_handle_methods, 0);
jbe@80 208 lua_pushvalue(L, -1);
jbe@80 209 lua_setfield(L, -4, "handle");
jbe@79 210 lua_setfield(L, -2, "__index");
jbe@79 211 lua_setfield(L, LUA_REGISTRYINDEX, MOONBR_IO_HANDLE_PUBLIC_MT_REGKEY);
jbe@79 212
jbe@79 213 lua_newtable(L); // handle metatable
jbe@79 214 luaL_setfuncs(L, moonbr_io_handle_metamethods, 0);
jbe@79 215 lua_setfield(L, LUA_REGISTRYINDEX, MOONBR_IO_HANDLE_MT_REGKEY);
jbe@79 216
jbe@79 217 luaL_setfuncs(L, moonbr_io_module_funcs, 0);
jbe@79 218 return 1;
jbe@79 219
jbe@79 220 }
jbe@79 221

Impressum / About Us