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
|