diff options
author | Hisham Muhammad <hisham@gobolinux.org> | 2025-03-04 02:19:37 -0300 |
---|---|---|
committer | Hisham Muhammad <hisham@gobolinux.org> | 2025-03-10 10:51:04 -0300 |
commit | cc887b9b25571e9ce0afa0cd5e4a4a2cbf130d3a (patch) | |
tree | 44b6e247a28934361ff979d32f677832a1d281a8 | |
parent | 9e162d9e980f7e17c0ea41e0cd29173d01ada330 (diff) | |
download | luarocks-cc887b9b25571e9ce0afa0cd5e4a4a2cbf130d3a.tar.gz luarocks-cc887b9b25571e9ce0afa0cd5e4a4a2cbf130d3a.tar.bz2 luarocks-cc887b9b25571e9ce0afa0cd5e4a4a2cbf130d3a.zip |
[wip] vendor in dependencies
140 files changed, 23142 insertions, 0 deletions
diff --git a/vendor/lua-bz2/LICENSE b/vendor/lua-bz2/LICENSE new file mode 100644 index 00000000..cc1b14dc --- /dev/null +++ b/vendor/lua-bz2/LICENSE | |||
@@ -0,0 +1,13 @@ | |||
1 | Copyright (c) 2008, Evan Klitzke <evan@eklitzke.org> | ||
2 | |||
3 | Permission to use, copy, modify, and/or distribute this software for any | ||
4 | purpose with or without fee is hereby granted, provided that the above | ||
5 | copyright notice and this permission notice appear in all copies. | ||
6 | |||
7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
diff --git a/vendor/lua-bz2/README b/vendor/lua-bz2/README new file mode 100644 index 00000000..a5361ad6 --- /dev/null +++ b/vendor/lua-bz2/README | |||
@@ -0,0 +1,27 @@ | |||
1 | A Lua binding to Julian Seward's libbzip2. | ||
2 | |||
3 | Current maintainer: harningt@gmail.com | ||
4 | Previous maintainer: evan@yelp.com | ||
5 | |||
6 | This software is released under a BSD-style license (to be exact, the ISC | ||
7 | license). The full license can be found in the LICENSE file included with this | ||
8 | source code. | ||
9 | |||
10 | Requirements: | ||
11 | * libbzip2 | ||
12 | * Lua >= 5.1 | ||
13 | |||
14 | Tested Operating Systems: | ||
15 | * Mac OSX 10.5 | ||
16 | * Linux | ||
17 | * Ubuntu | ||
18 | * Gentoo | ||
19 | |||
20 | Patches to make this work fully on Windows and other OSes are welcome. | ||
21 | |||
22 | More information about Lua: http://www.lua.org/ | ||
23 | More information about bzip2: http://www.bzip.org/ | ||
24 | |||
25 | Current Repository Details | ||
26 | Project : https://github.com/harningt/lua-bz2/tree | ||
27 | Public Git : git://github.com/harningt/lua-bz2.git | ||
diff --git a/vendor/lua-bz2/bz2/ltn12.lua b/vendor/lua-bz2/bz2/ltn12.lua new file mode 100644 index 00000000..d2da675d --- /dev/null +++ b/vendor/lua-bz2/bz2/ltn12.lua | |||
@@ -0,0 +1,93 @@ | |||
1 | local _M = {} | ||
2 | local bz2 = require("bz2") | ||
3 | |||
4 | _M.filter = {} | ||
5 | _M.source = {} | ||
6 | _M.sink = {} | ||
7 | |||
8 | local function buildProcessor(filter, err) | ||
9 | if not filter then | ||
10 | return nil, err | ||
11 | end | ||
12 | return function(chunk) | ||
13 | if not filter then | ||
14 | return nil, "closed" | ||
15 | end | ||
16 | -- Skip empty chunks due to unexpected 'flushing' | ||
17 | if chunk and #chunk == 0 then | ||
18 | return "" | ||
19 | end | ||
20 | -- On nil, update closes the stream out as ltn12 expects | ||
21 | local ret, err = filter:update(chunk) | ||
22 | if not chunk then | ||
23 | filter:close() | ||
24 | filter = nil | ||
25 | end | ||
26 | if not ret then | ||
27 | return nil, err | ||
28 | end | ||
29 | return ret | ||
30 | end | ||
31 | |||
32 | end | ||
33 | |||
34 | function _M.filter.compress(blockSize100k, verbosity, workFactor) | ||
35 | return buildProcessor(bz2.initCompress(blockSize100k, verbosity, workFactor)) | ||
36 | end | ||
37 | |||
38 | function _M.filter.decompress(verbosity, small) | ||
39 | return buildProcessor(bz2.initDecompress(verbosity, small)) | ||
40 | end | ||
41 | |||
42 | function _M.sink.file(name, blockSize100k, verbosity, workFactor) | ||
43 | local writer, err = bz2.openWrite(name, blockSize100k, verbosity, workFactor) | ||
44 | if not writer then | ||
45 | return nil, err | ||
46 | end | ||
47 | return function(data) | ||
48 | if not writer then | ||
49 | return nil, "closed" | ||
50 | end | ||
51 | if not data then | ||
52 | writer:close() | ||
53 | writer = nil | ||
54 | return | ||
55 | end | ||
56 | if #data == 0 then | ||
57 | return 1 | ||
58 | end | ||
59 | local ret, err = writer:write(data) | ||
60 | if not ret then | ||
61 | return nil, err | ||
62 | end | ||
63 | return 1 | ||
64 | end | ||
65 | end | ||
66 | |||
67 | function _M.source.file(name, verbosity, small) | ||
68 | local reader, err = bz2.openRead(name, verbosity, small) | ||
69 | if not reader then | ||
70 | return nil, err | ||
71 | end | ||
72 | return function() | ||
73 | if not reader then | ||
74 | return | ||
75 | end | ||
76 | local ret, err = reader:read(true) | ||
77 | if ret and #ret == 0 then | ||
78 | reader:close() | ||
79 | reader = nil | ||
80 | return | ||
81 | end | ||
82 | if not ret then | ||
83 | return nil, err | ||
84 | end | ||
85 | if err then | ||
86 | reader:close() | ||
87 | reader = nil | ||
88 | end | ||
89 | return ret | ||
90 | end | ||
91 | end | ||
92 | |||
93 | return _M | ||
diff --git a/vendor/lua-bz2/compat-5.3.c b/vendor/lua-bz2/compat-5.3.c new file mode 100644 index 00000000..42b0a4bb --- /dev/null +++ b/vendor/lua-bz2/compat-5.3.c | |||
@@ -0,0 +1,948 @@ | |||
1 | #include <stddef.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <string.h> | ||
4 | #include <ctype.h> | ||
5 | #include <errno.h> | ||
6 | #include <stdio.h> | ||
7 | #include "compat-5.3.h" | ||
8 | |||
9 | /* don't compile it again if it already is included via compat53.h */ | ||
10 | #ifndef COMPAT53_C_ | ||
11 | #define COMPAT53_C_ | ||
12 | |||
13 | |||
14 | |||
15 | /* definitions for Lua 5.1 only */ | ||
16 | #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 | ||
17 | |||
18 | #ifndef COMPAT53_FOPEN_NO_LOCK | ||
19 | # if defined(_MSC_VER) | ||
20 | # define COMPAT53_FOPEN_NO_LOCK 1 | ||
21 | # else /* otherwise */ | ||
22 | # define COMPAT53_FOPEN_NO_LOCK 0 | ||
23 | # endif /* VC++ only so far */ | ||
24 | #endif /* No-lock fopen_s usage if possible */ | ||
25 | |||
26 | #if defined(_MSC_VER) && COMPAT53_FOPEN_NO_LOCK | ||
27 | # include <share.h> | ||
28 | #endif /* VC++ _fsopen for share-allowed file read */ | ||
29 | |||
30 | #ifndef COMPAT53_HAVE_STRERROR_R | ||
31 | # if (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || \ | ||
32 | (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600) || \ | ||
33 | defined(__APPLE__) | ||
34 | # define COMPAT53_HAVE_STRERROR_R 1 | ||
35 | # else /* none of the defines matched: define to 0 */ | ||
36 | # define COMPAT53_HAVE_STRERROR_R 0 | ||
37 | # endif /* have strerror_r of some form */ | ||
38 | #endif /* strerror_r */ | ||
39 | |||
40 | #ifndef COMPAT53_HAVE_STRERROR_S | ||
41 | # if defined(_MSC_VER) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \ | ||
42 | defined(__STDC_LIB_EXT1__) && __STDC_LIB_EXT1__) | ||
43 | # define COMPAT53_HAVE_STRERROR_S 1 | ||
44 | # else /* not VC++ or C11 */ | ||
45 | # define COMPAT53_HAVE_STRERROR_S 0 | ||
46 | # endif /* strerror_s from VC++ or C11 */ | ||
47 | #endif /* strerror_s */ | ||
48 | |||
49 | #ifndef COMPAT53_LUA_FILE_BUFFER_SIZE | ||
50 | # define COMPAT53_LUA_FILE_BUFFER_SIZE 4096 | ||
51 | #endif /* Lua File Buffer Size */ | ||
52 | |||
53 | |||
54 | static char* compat53_strerror (int en, char* buff, size_t sz) { | ||
55 | #if COMPAT53_HAVE_STRERROR_R | ||
56 | /* use strerror_r here, because it's available on these specific platforms */ | ||
57 | if (sz > 0) { | ||
58 | buff[0] = '\0'; | ||
59 | /* we don't care whether the GNU version or the XSI version is used: */ | ||
60 | if (strerror_r(en, buff, sz)) { | ||
61 | /* Yes, we really DO want to ignore the return value! | ||
62 | * GCC makes that extra hard, not even a (void) cast will do. */ | ||
63 | } | ||
64 | if (buff[0] == '\0') { | ||
65 | /* Buffer is unchanged, so we probably have called GNU strerror_r which | ||
66 | * returned a static constant string. Chances are that strerror will | ||
67 | * return the same static constant string and therefore be thread-safe. */ | ||
68 | return strerror(en); | ||
69 | } | ||
70 | } | ||
71 | return buff; /* sz is 0 *or* strerror_r wrote into the buffer */ | ||
72 | #elif COMPAT53_HAVE_STRERROR_S | ||
73 | /* for MSVC and other C11 implementations, use strerror_s since it's | ||
74 | * provided by default by the libraries */ | ||
75 | strerror_s(buff, sz, en); | ||
76 | return buff; | ||
77 | #else | ||
78 | /* fallback, but strerror is not guaranteed to be threadsafe due to modifying | ||
79 | * errno itself and some impls not locking a static buffer for it ... but most | ||
80 | * known systems have threadsafe errno: this might only change if the locale | ||
81 | * is changed out from under someone while this function is being called */ | ||
82 | (void)buff; | ||
83 | (void)sz; | ||
84 | return strerror(en); | ||
85 | #endif | ||
86 | } | ||
87 | |||
88 | |||
89 | COMPAT53_API int lua_absindex (lua_State *L, int i) { | ||
90 | if (i < 0 && i > LUA_REGISTRYINDEX) | ||
91 | i += lua_gettop(L) + 1; | ||
92 | return i; | ||
93 | } | ||
94 | |||
95 | |||
96 | static void compat53_call_lua (lua_State *L, char const code[], size_t len, | ||
97 | int nargs, int nret) { | ||
98 | lua_rawgetp(L, LUA_REGISTRYINDEX, (void*)code); | ||
99 | if (lua_type(L, -1) != LUA_TFUNCTION) { | ||
100 | lua_pop(L, 1); | ||
101 | if (luaL_loadbuffer(L, code, len, "=none")) | ||
102 | lua_error(L); | ||
103 | lua_pushvalue(L, -1); | ||
104 | lua_rawsetp(L, LUA_REGISTRYINDEX, (void*)code); | ||
105 | } | ||
106 | lua_insert(L, -nargs-1); | ||
107 | lua_call(L, nargs, nret); | ||
108 | } | ||
109 | |||
110 | |||
111 | static const char compat53_arith_code[] = | ||
112 | "local op,a,b=...\n" | ||
113 | "if op==0 then return a+b\n" | ||
114 | "elseif op==1 then return a-b\n" | ||
115 | "elseif op==2 then return a*b\n" | ||
116 | "elseif op==3 then return a/b\n" | ||
117 | "elseif op==4 then return a%b\n" | ||
118 | "elseif op==5 then return a^b\n" | ||
119 | "elseif op==6 then return -a\n" | ||
120 | "end\n"; | ||
121 | |||
122 | COMPAT53_API void lua_arith (lua_State *L, int op) { | ||
123 | if (op < LUA_OPADD || op > LUA_OPUNM) | ||
124 | luaL_error(L, "invalid 'op' argument for lua_arith"); | ||
125 | luaL_checkstack(L, 5, "not enough stack slots"); | ||
126 | if (op == LUA_OPUNM) | ||
127 | lua_pushvalue(L, -1); | ||
128 | lua_pushnumber(L, op); | ||
129 | lua_insert(L, -3); | ||
130 | compat53_call_lua(L, compat53_arith_code, | ||
131 | sizeof(compat53_arith_code)-1, 3, 1); | ||
132 | } | ||
133 | |||
134 | |||
135 | static const char compat53_compare_code[] = | ||
136 | "local a,b=...\n" | ||
137 | "return a<=b\n"; | ||
138 | |||
139 | COMPAT53_API int lua_compare (lua_State *L, int idx1, int idx2, int op) { | ||
140 | int result = 0; | ||
141 | switch (op) { | ||
142 | case LUA_OPEQ: | ||
143 | return lua_equal(L, idx1, idx2); | ||
144 | case LUA_OPLT: | ||
145 | return lua_lessthan(L, idx1, idx2); | ||
146 | case LUA_OPLE: | ||
147 | luaL_checkstack(L, 5, "not enough stack slots"); | ||
148 | idx1 = lua_absindex(L, idx1); | ||
149 | idx2 = lua_absindex(L, idx2); | ||
150 | lua_pushvalue(L, idx1); | ||
151 | lua_pushvalue(L, idx2); | ||
152 | compat53_call_lua(L, compat53_compare_code, | ||
153 | sizeof(compat53_compare_code)-1, 2, 1); | ||
154 | result = lua_toboolean(L, -1); | ||
155 | lua_pop(L, 1); | ||
156 | return result; | ||
157 | default: | ||
158 | luaL_error(L, "invalid 'op' argument for lua_compare"); | ||
159 | } | ||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | |||
164 | COMPAT53_API void lua_copy (lua_State *L, int from, int to) { | ||
165 | int abs_to = lua_absindex(L, to); | ||
166 | luaL_checkstack(L, 1, "not enough stack slots"); | ||
167 | lua_pushvalue(L, from); | ||
168 | lua_replace(L, abs_to); | ||
169 | } | ||
170 | |||
171 | |||
172 | COMPAT53_API void lua_len (lua_State *L, int i) { | ||
173 | switch (lua_type(L, i)) { | ||
174 | case LUA_TSTRING: | ||
175 | lua_pushnumber(L, (lua_Number)lua_objlen(L, i)); | ||
176 | break; | ||
177 | case LUA_TTABLE: | ||
178 | if (!luaL_callmeta(L, i, "__len")) | ||
179 | lua_pushnumber(L, (lua_Number)lua_objlen(L, i)); | ||
180 | break; | ||
181 | case LUA_TUSERDATA: | ||
182 | if (luaL_callmeta(L, i, "__len")) | ||
183 | break; | ||
184 | /* FALLTHROUGH */ | ||
185 | default: | ||
186 | luaL_error(L, "attempt to get length of a %s value", | ||
187 | lua_typename(L, lua_type(L, i))); | ||
188 | } | ||
189 | } | ||
190 | |||
191 | |||
192 | COMPAT53_API int lua_rawgetp (lua_State *L, int i, const void *p) { | ||
193 | int abs_i = lua_absindex(L, i); | ||
194 | lua_pushlightuserdata(L, (void*)p); | ||
195 | lua_rawget(L, abs_i); | ||
196 | return lua_type(L, -1); | ||
197 | } | ||
198 | |||
199 | COMPAT53_API void lua_rawsetp (lua_State *L, int i, const void *p) { | ||
200 | int abs_i = lua_absindex(L, i); | ||
201 | luaL_checkstack(L, 1, "not enough stack slots"); | ||
202 | lua_pushlightuserdata(L, (void*)p); | ||
203 | lua_insert(L, -2); | ||
204 | lua_rawset(L, abs_i); | ||
205 | } | ||
206 | |||
207 | |||
208 | COMPAT53_API lua_Number lua_tonumberx (lua_State *L, int i, int *isnum) { | ||
209 | lua_Number n = lua_tonumber(L, i); | ||
210 | if (isnum != NULL) { | ||
211 | *isnum = (n != 0 || lua_isnumber(L, i)); | ||
212 | } | ||
213 | return n; | ||
214 | } | ||
215 | |||
216 | |||
217 | COMPAT53_API void luaL_checkversion (lua_State *L) { | ||
218 | (void)L; | ||
219 | } | ||
220 | |||
221 | |||
222 | COMPAT53_API void luaL_checkstack (lua_State *L, int sp, const char *msg) { | ||
223 | if (!lua_checkstack(L, sp+LUA_MINSTACK)) { | ||
224 | if (msg != NULL) | ||
225 | luaL_error(L, "stack overflow (%s)", msg); | ||
226 | else { | ||
227 | lua_pushliteral(L, "stack overflow"); | ||
228 | lua_error(L); | ||
229 | } | ||
230 | } | ||
231 | } | ||
232 | |||
233 | |||
234 | COMPAT53_API int luaL_getsubtable (lua_State *L, int i, const char *name) { | ||
235 | int abs_i = lua_absindex(L, i); | ||
236 | luaL_checkstack(L, 3, "not enough stack slots"); | ||
237 | lua_pushstring(L, name); | ||
238 | lua_gettable(L, abs_i); | ||
239 | if (lua_istable(L, -1)) | ||
240 | return 1; | ||
241 | lua_pop(L, 1); | ||
242 | lua_newtable(L); | ||
243 | lua_pushstring(L, name); | ||
244 | lua_pushvalue(L, -2); | ||
245 | lua_settable(L, abs_i); | ||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | |||
250 | COMPAT53_API lua_Integer luaL_len (lua_State *L, int i) { | ||
251 | lua_Integer res = 0; | ||
252 | int isnum = 0; | ||
253 | luaL_checkstack(L, 1, "not enough stack slots"); | ||
254 | lua_len(L, i); | ||
255 | res = lua_tointegerx(L, -1, &isnum); | ||
256 | lua_pop(L, 1); | ||
257 | if (!isnum) | ||
258 | luaL_error(L, "object length is not an integer"); | ||
259 | return res; | ||
260 | } | ||
261 | |||
262 | |||
263 | COMPAT53_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { | ||
264 | luaL_checkstack(L, nup+1, "too many upvalues"); | ||
265 | for (; l->name != NULL; l++) { /* fill the table with given functions */ | ||
266 | int i; | ||
267 | lua_pushstring(L, l->name); | ||
268 | for (i = 0; i < nup; i++) /* copy upvalues to the top */ | ||
269 | lua_pushvalue(L, -(nup + 1)); | ||
270 | lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ | ||
271 | lua_settable(L, -(nup + 3)); /* table must be below the upvalues, the name and the closure */ | ||
272 | } | ||
273 | lua_pop(L, nup); /* remove upvalues */ | ||
274 | } | ||
275 | |||
276 | |||
277 | COMPAT53_API void luaL_setmetatable (lua_State *L, const char *tname) { | ||
278 | luaL_checkstack(L, 1, "not enough stack slots"); | ||
279 | luaL_getmetatable(L, tname); | ||
280 | lua_setmetatable(L, -2); | ||
281 | } | ||
282 | |||
283 | |||
284 | COMPAT53_API void *luaL_testudata (lua_State *L, int i, const char *tname) { | ||
285 | void *p = lua_touserdata(L, i); | ||
286 | luaL_checkstack(L, 2, "not enough stack slots"); | ||
287 | if (p == NULL || !lua_getmetatable(L, i)) | ||
288 | return NULL; | ||
289 | else { | ||
290 | int res = 0; | ||
291 | luaL_getmetatable(L, tname); | ||
292 | res = lua_rawequal(L, -1, -2); | ||
293 | lua_pop(L, 2); | ||
294 | if (!res) | ||
295 | p = NULL; | ||
296 | } | ||
297 | return p; | ||
298 | } | ||
299 | |||
300 | |||
301 | static int compat53_countlevels (lua_State *L) { | ||
302 | lua_Debug ar; | ||
303 | int li = 1, le = 1; | ||
304 | /* find an upper bound */ | ||
305 | while (lua_getstack(L, le, &ar)) { li = le; le *= 2; } | ||
306 | /* do a binary search */ | ||
307 | while (li < le) { | ||
308 | int m = (li + le)/2; | ||
309 | if (lua_getstack(L, m, &ar)) li = m + 1; | ||
310 | else le = m; | ||
311 | } | ||
312 | return le - 1; | ||
313 | } | ||
314 | |||
315 | static int compat53_findfield (lua_State *L, int objidx, int level) { | ||
316 | if (level == 0 || !lua_istable(L, -1)) | ||
317 | return 0; /* not found */ | ||
318 | lua_pushnil(L); /* start 'next' loop */ | ||
319 | while (lua_next(L, -2)) { /* for each pair in table */ | ||
320 | if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ | ||
321 | if (lua_rawequal(L, objidx, -1)) { /* found object? */ | ||
322 | lua_pop(L, 1); /* remove value (but keep name) */ | ||
323 | return 1; | ||
324 | } | ||
325 | else if (compat53_findfield(L, objidx, level - 1)) { /* try recursively */ | ||
326 | lua_remove(L, -2); /* remove table (but keep name) */ | ||
327 | lua_pushliteral(L, "."); | ||
328 | lua_insert(L, -2); /* place '.' between the two names */ | ||
329 | lua_concat(L, 3); | ||
330 | return 1; | ||
331 | } | ||
332 | } | ||
333 | lua_pop(L, 1); /* remove value */ | ||
334 | } | ||
335 | return 0; /* not found */ | ||
336 | } | ||
337 | |||
338 | static int compat53_pushglobalfuncname (lua_State *L, lua_Debug *ar) { | ||
339 | int top = lua_gettop(L); | ||
340 | lua_getinfo(L, "f", ar); /* push function */ | ||
341 | lua_pushvalue(L, LUA_GLOBALSINDEX); | ||
342 | if (compat53_findfield(L, top + 1, 2)) { | ||
343 | lua_copy(L, -1, top + 1); /* move name to proper place */ | ||
344 | lua_pop(L, 2); /* remove pushed values */ | ||
345 | return 1; | ||
346 | } | ||
347 | else { | ||
348 | lua_settop(L, top); /* remove function and global table */ | ||
349 | return 0; | ||
350 | } | ||
351 | } | ||
352 | |||
353 | static void compat53_pushfuncname (lua_State *L, lua_Debug *ar) { | ||
354 | if (*ar->namewhat != '\0') /* is there a name? */ | ||
355 | lua_pushfstring(L, "function " LUA_QS, ar->name); | ||
356 | else if (*ar->what == 'm') /* main? */ | ||
357 | lua_pushliteral(L, "main chunk"); | ||
358 | else if (*ar->what == 'C') { | ||
359 | if (compat53_pushglobalfuncname(L, ar)) { | ||
360 | lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1)); | ||
361 | lua_remove(L, -2); /* remove name */ | ||
362 | } | ||
363 | else | ||
364 | lua_pushliteral(L, "?"); | ||
365 | } | ||
366 | else | ||
367 | lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); | ||
368 | } | ||
369 | |||
370 | #define COMPAT53_LEVELS1 12 /* size of the first part of the stack */ | ||
371 | #define COMPAT53_LEVELS2 10 /* size of the second part of the stack */ | ||
372 | |||
373 | COMPAT53_API void luaL_traceback (lua_State *L, lua_State *L1, | ||
374 | const char *msg, int level) { | ||
375 | lua_Debug ar; | ||
376 | int top = lua_gettop(L); | ||
377 | int numlevels = compat53_countlevels(L1); | ||
378 | int mark = (numlevels > COMPAT53_LEVELS1 + COMPAT53_LEVELS2) ? COMPAT53_LEVELS1 : 0; | ||
379 | if (msg) lua_pushfstring(L, "%s\n", msg); | ||
380 | lua_pushliteral(L, "stack traceback:"); | ||
381 | while (lua_getstack(L1, level++, &ar)) { | ||
382 | if (level == mark) { /* too many levels? */ | ||
383 | lua_pushliteral(L, "\n\t..."); /* add a '...' */ | ||
384 | level = numlevels - COMPAT53_LEVELS2; /* and skip to last ones */ | ||
385 | } | ||
386 | else { | ||
387 | lua_getinfo(L1, "Slnt", &ar); | ||
388 | lua_pushfstring(L, "\n\t%s:", ar.short_src); | ||
389 | if (ar.currentline > 0) | ||
390 | lua_pushfstring(L, "%d:", ar.currentline); | ||
391 | lua_pushliteral(L, " in "); | ||
392 | compat53_pushfuncname(L, &ar); | ||
393 | lua_concat(L, lua_gettop(L) - top); | ||
394 | } | ||
395 | } | ||
396 | lua_concat(L, lua_gettop(L) - top); | ||
397 | } | ||
398 | |||
399 | |||
400 | COMPAT53_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { | ||
401 | const char *serr = NULL; | ||
402 | int en = errno; /* calls to Lua API may change this value */ | ||
403 | char buf[512] = { 0 }; | ||
404 | if (stat) { | ||
405 | lua_pushboolean(L, 1); | ||
406 | return 1; | ||
407 | } | ||
408 | else { | ||
409 | lua_pushnil(L); | ||
410 | serr = compat53_strerror(en, buf, sizeof(buf)); | ||
411 | if (fname) | ||
412 | lua_pushfstring(L, "%s: %s", fname, serr); | ||
413 | else | ||
414 | lua_pushstring(L, serr); | ||
415 | lua_pushnumber(L, (lua_Number)en); | ||
416 | return 3; | ||
417 | } | ||
418 | } | ||
419 | |||
420 | |||
421 | static int compat53_checkmode (lua_State *L, const char *mode, const char *modename, int err) { | ||
422 | if (mode && strchr(mode, modename[0]) == NULL) { | ||
423 | lua_pushfstring(L, "attempt to load a %s chunk (mode is '%s')", modename, mode); | ||
424 | return err; | ||
425 | } | ||
426 | return LUA_OK; | ||
427 | } | ||
428 | |||
429 | |||
430 | typedef struct { | ||
431 | lua_Reader reader; | ||
432 | void *ud; | ||
433 | int has_peeked_data; | ||
434 | const char *peeked_data; | ||
435 | size_t peeked_data_size; | ||
436 | } compat53_reader_data; | ||
437 | |||
438 | |||
439 | static const char *compat53_reader (lua_State *L, void *ud, size_t *size) { | ||
440 | compat53_reader_data *data = (compat53_reader_data *)ud; | ||
441 | if (data->has_peeked_data) { | ||
442 | data->has_peeked_data = 0; | ||
443 | *size = data->peeked_data_size; | ||
444 | return data->peeked_data; | ||
445 | } else | ||
446 | return data->reader(L, data->ud, size); | ||
447 | } | ||
448 | |||
449 | |||
450 | COMPAT53_API int lua_load (lua_State *L, lua_Reader reader, void *data, const char *source, const char *mode) { | ||
451 | int status = LUA_OK; | ||
452 | compat53_reader_data compat53_data = { 0, NULL, 1, 0, 0 }; | ||
453 | compat53_data.reader = reader; | ||
454 | compat53_data.ud = data; | ||
455 | compat53_data.peeked_data = reader(L, data, &(compat53_data.peeked_data_size)); | ||
456 | if (compat53_data.peeked_data && compat53_data.peeked_data_size && | ||
457 | compat53_data.peeked_data[0] == LUA_SIGNATURE[0]) /* binary file? */ | ||
458 | status = compat53_checkmode(L, mode, "binary", LUA_ERRSYNTAX); | ||
459 | else | ||
460 | status = compat53_checkmode(L, mode, "text", LUA_ERRSYNTAX); | ||
461 | if (status != LUA_OK) | ||
462 | return status; | ||
463 | /* we need to call the original 5.1 version of lua_load! */ | ||
464 | #undef lua_load | ||
465 | return lua_load(L, compat53_reader, &compat53_data, source); | ||
466 | #define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53) | ||
467 | } | ||
468 | |||
469 | |||
470 | typedef struct { | ||
471 | int n; /* number of pre-read characters */ | ||
472 | FILE *f; /* file being read */ | ||
473 | char buff[COMPAT53_LUA_FILE_BUFFER_SIZE]; /* area for reading file */ | ||
474 | } compat53_LoadF; | ||
475 | |||
476 | |||
477 | static const char *compat53_getF (lua_State *L, void *ud, size_t *size) { | ||
478 | compat53_LoadF *lf = (compat53_LoadF *)ud; | ||
479 | (void)L; /* not used */ | ||
480 | if (lf->n > 0) { /* are there pre-read characters to be read? */ | ||
481 | *size = lf->n; /* return them (chars already in buffer) */ | ||
482 | lf->n = 0; /* no more pre-read characters */ | ||
483 | } | ||
484 | else { /* read a block from file */ | ||
485 | /* 'fread' can return > 0 *and* set the EOF flag. If next call to | ||
486 | 'compat53_getF' called 'fread', it might still wait for user input. | ||
487 | The next check avoids this problem. */ | ||
488 | if (feof(lf->f)) return NULL; | ||
489 | *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); /* read block */ | ||
490 | } | ||
491 | return lf->buff; | ||
492 | } | ||
493 | |||
494 | |||
495 | static int compat53_errfile (lua_State *L, const char *what, int fnameindex) { | ||
496 | char buf[512] = {0}; | ||
497 | const char *serr = compat53_strerror(errno, buf, sizeof(buf)); | ||
498 | const char *filename = lua_tostring(L, fnameindex) + 1; | ||
499 | lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); | ||
500 | lua_remove(L, fnameindex); | ||
501 | return LUA_ERRFILE; | ||
502 | } | ||
503 | |||
504 | |||
505 | static int compat53_skipBOM (compat53_LoadF *lf) { | ||
506 | const char *p = "\xEF\xBB\xBF"; /* UTF-8 BOM mark */ | ||
507 | int c; | ||
508 | lf->n = 0; | ||
509 | do { | ||
510 | c = getc(lf->f); | ||
511 | if (c == EOF || c != *(const unsigned char *)p++) return c; | ||
512 | lf->buff[lf->n++] = (char)c; /* to be read by the parser */ | ||
513 | } while (*p != '\0'); | ||
514 | lf->n = 0; /* prefix matched; discard it */ | ||
515 | return getc(lf->f); /* return next character */ | ||
516 | } | ||
517 | |||
518 | |||
519 | /* | ||
520 | ** reads the first character of file 'f' and skips an optional BOM mark | ||
521 | ** in its beginning plus its first line if it starts with '#'. Returns | ||
522 | ** true if it skipped the first line. In any case, '*cp' has the | ||
523 | ** first "valid" character of the file (after the optional BOM and | ||
524 | ** a first-line comment). | ||
525 | */ | ||
526 | static int compat53_skipcomment (compat53_LoadF *lf, int *cp) { | ||
527 | int c = *cp = compat53_skipBOM(lf); | ||
528 | if (c == '#') { /* first line is a comment (Unix exec. file)? */ | ||
529 | do { /* skip first line */ | ||
530 | c = getc(lf->f); | ||
531 | } while (c != EOF && c != '\n'); | ||
532 | *cp = getc(lf->f); /* skip end-of-line, if present */ | ||
533 | return 1; /* there was a comment */ | ||
534 | } | ||
535 | else return 0; /* no comment */ | ||
536 | } | ||
537 | |||
538 | |||
539 | COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char *mode) { | ||
540 | compat53_LoadF lf; | ||
541 | int status, readstatus; | ||
542 | int c; | ||
543 | int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ | ||
544 | if (filename == NULL) { | ||
545 | lua_pushliteral(L, "=stdin"); | ||
546 | lf.f = stdin; | ||
547 | } | ||
548 | else { | ||
549 | lua_pushfstring(L, "@%s", filename); | ||
550 | #if defined(_MSC_VER) | ||
551 | /* This code is here to stop a deprecation error that stops builds | ||
552 | * if a certain macro is defined. While normally not caring would | ||
553 | * be best, some header-only libraries and builds can't afford to | ||
554 | * dictate this to the user. A quick check shows that fopen_s this | ||
555 | * goes back to VS 2005, and _fsopen goes back to VS 2003 .NET, | ||
556 | * possibly even before that so we don't need to do any version | ||
557 | * number checks, since this has been there since forever. */ | ||
558 | |||
559 | /* TO USER: if you want the behavior of typical fopen_s/fopen, | ||
560 | * which does lock the file on VC++, define the macro used below to 0 */ | ||
561 | #if COMPAT53_FOPEN_NO_LOCK | ||
562 | lf.f = _fsopen(filename, "r", _SH_DENYNO); /* do not lock the file in any way */ | ||
563 | if (lf.f == NULL) | ||
564 | return compat53_errfile(L, "open", fnameindex); | ||
565 | #else /* use default locking version */ | ||
566 | if (fopen_s(&lf.f, filename, "r") != 0) | ||
567 | return compat53_errfile(L, "open", fnameindex); | ||
568 | #endif /* Locking vs. No-locking fopen variants */ | ||
569 | #else | ||
570 | lf.f = fopen(filename, "r"); /* default stdlib doesn't forcefully lock files here */ | ||
571 | if (lf.f == NULL) return compat53_errfile(L, "open", fnameindex); | ||
572 | #endif | ||
573 | } | ||
574 | if (compat53_skipcomment(&lf, &c)) /* read initial portion */ | ||
575 | lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ | ||
576 | if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ | ||
577 | #if defined(_MSC_VER) | ||
578 | if (freopen_s(&lf.f, filename, "rb", lf.f) != 0) | ||
579 | return compat53_errfile(L, "reopen", fnameindex); | ||
580 | #else | ||
581 | lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ | ||
582 | if (lf.f == NULL) return compat53_errfile(L, "reopen", fnameindex); | ||
583 | #endif | ||
584 | compat53_skipcomment(&lf, &c); /* re-read initial portion */ | ||
585 | } | ||
586 | if (c != EOF) | ||
587 | lf.buff[lf.n++] = (char)c; /* 'c' is the first character of the stream */ | ||
588 | status = lua_load(L, &compat53_getF, &lf, lua_tostring(L, -1), mode); | ||
589 | readstatus = ferror(lf.f); | ||
590 | if (filename) fclose(lf.f); /* close file (even in case of errors) */ | ||
591 | if (readstatus) { | ||
592 | lua_settop(L, fnameindex); /* ignore results from 'lua_load' */ | ||
593 | return compat53_errfile(L, "read", fnameindex); | ||
594 | } | ||
595 | lua_remove(L, fnameindex); | ||
596 | return status; | ||
597 | } | ||
598 | |||
599 | |||
600 | COMPAT53_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode) { | ||
601 | int status = LUA_OK; | ||
602 | if (sz > 0 && buff[0] == LUA_SIGNATURE[0]) { | ||
603 | status = compat53_checkmode(L, mode, "binary", LUA_ERRSYNTAX); | ||
604 | } | ||
605 | else { | ||
606 | status = compat53_checkmode(L, mode, "text", LUA_ERRSYNTAX); | ||
607 | } | ||
608 | if (status != LUA_OK) | ||
609 | return status; | ||
610 | return luaL_loadbuffer(L, buff, sz, name); | ||
611 | } | ||
612 | |||
613 | |||
614 | #if !defined(l_inspectstat) && \ | ||
615 | (defined(unix) || defined(__unix) || defined(__unix__) || \ | ||
616 | defined(__TOS_AIX__) || defined(_SYSTYPE_BSD) || \ | ||
617 | (defined(__APPLE__) && defined(__MACH__))) | ||
618 | /* some form of unix; check feature macros in unistd.h for details */ | ||
619 | # include <unistd.h> | ||
620 | /* check posix version; the relevant include files and macros probably | ||
621 | * were available before 2001, but I'm not sure */ | ||
622 | # if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L | ||
623 | # include <sys/wait.h> | ||
624 | # define l_inspectstat(stat,what) \ | ||
625 | if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \ | ||
626 | else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; } | ||
627 | # endif | ||
628 | #endif | ||
629 | |||
630 | /* provide default (no-op) version */ | ||
631 | #if !defined(l_inspectstat) | ||
632 | # define l_inspectstat(stat,what) ((void)0) | ||
633 | #endif | ||
634 | |||
635 | |||
636 | COMPAT53_API int luaL_execresult (lua_State *L, int stat) { | ||
637 | const char *what = "exit"; | ||
638 | if (stat == -1) | ||
639 | return luaL_fileresult(L, 0, NULL); | ||
640 | else { | ||
641 | l_inspectstat(stat, what); | ||
642 | if (*what == 'e' && stat == 0) | ||
643 | lua_pushboolean(L, 1); | ||
644 | else | ||
645 | lua_pushnil(L); | ||
646 | lua_pushstring(L, what); | ||
647 | lua_pushinteger(L, stat); | ||
648 | return 3; | ||
649 | } | ||
650 | } | ||
651 | |||
652 | |||
653 | COMPAT53_API void luaL_buffinit (lua_State *L, luaL_Buffer_53 *B) { | ||
654 | /* make it crash if used via pointer to a 5.1-style luaL_Buffer */ | ||
655 | B->b.p = NULL; | ||
656 | B->b.L = NULL; | ||
657 | B->b.lvl = 0; | ||
658 | /* reuse the buffer from the 5.1-style luaL_Buffer though! */ | ||
659 | B->ptr = B->b.buffer; | ||
660 | B->capacity = LUAL_BUFFERSIZE; | ||
661 | B->nelems = 0; | ||
662 | B->L2 = L; | ||
663 | } | ||
664 | |||
665 | |||
666 | COMPAT53_API char *luaL_prepbuffsize (luaL_Buffer_53 *B, size_t s) { | ||
667 | if (B->capacity - B->nelems < s) { /* needs to grow */ | ||
668 | char* newptr = NULL; | ||
669 | size_t newcap = B->capacity * 2; | ||
670 | if (newcap - B->nelems < s) | ||
671 | newcap = B->nelems + s; | ||
672 | if (newcap < B->capacity) /* overflow */ | ||
673 | luaL_error(B->L2, "buffer too large"); | ||
674 | newptr = (char*)lua_newuserdata(B->L2, newcap); | ||
675 | memcpy(newptr, B->ptr, B->nelems); | ||
676 | if (B->ptr != B->b.buffer) | ||
677 | lua_replace(B->L2, -2); /* remove old buffer */ | ||
678 | B->ptr = newptr; | ||
679 | B->capacity = newcap; | ||
680 | } | ||
681 | return B->ptr+B->nelems; | ||
682 | } | ||
683 | |||
684 | |||
685 | COMPAT53_API void luaL_addlstring (luaL_Buffer_53 *B, const char *s, size_t l) { | ||
686 | memcpy(luaL_prepbuffsize(B, l), s, l); | ||
687 | luaL_addsize(B, l); | ||
688 | } | ||
689 | |||
690 | |||
691 | COMPAT53_API void luaL_addvalue (luaL_Buffer_53 *B) { | ||
692 | size_t len = 0; | ||
693 | const char *s = lua_tolstring(B->L2, -1, &len); | ||
694 | if (!s) | ||
695 | luaL_error(B->L2, "cannot convert value to string"); | ||
696 | if (B->ptr != B->b.buffer) | ||
697 | lua_insert(B->L2, -2); /* userdata buffer must be at stack top */ | ||
698 | luaL_addlstring(B, s, len); | ||
699 | lua_remove(B->L2, B->ptr != B->b.buffer ? -2 : -1); | ||
700 | } | ||
701 | |||
702 | |||
703 | void luaL_pushresult (luaL_Buffer_53 *B) { | ||
704 | lua_pushlstring(B->L2, B->ptr, B->nelems); | ||
705 | if (B->ptr != B->b.buffer) | ||
706 | lua_replace(B->L2, -2); /* remove userdata buffer */ | ||
707 | } | ||
708 | |||
709 | |||
710 | #endif /* Lua 5.1 */ | ||
711 | |||
712 | |||
713 | |||
714 | /* definitions for Lua 5.1 and Lua 5.2 */ | ||
715 | #if defined( LUA_VERSION_NUM ) && LUA_VERSION_NUM <= 502 | ||
716 | |||
717 | |||
718 | COMPAT53_API int lua_geti (lua_State *L, int index, lua_Integer i) { | ||
719 | index = lua_absindex(L, index); | ||
720 | lua_pushinteger(L, i); | ||
721 | lua_gettable(L, index); | ||
722 | return lua_type(L, -1); | ||
723 | } | ||
724 | |||
725 | |||
726 | #ifndef LUA_EXTRASPACE | ||
727 | #define LUA_EXTRASPACE (sizeof(void*)) | ||
728 | #endif | ||
729 | |||
730 | COMPAT53_API void *lua_getextraspace (lua_State *L) { | ||
731 | int is_main = 0; | ||
732 | void *ptr = NULL; | ||
733 | luaL_checkstack(L, 4, "not enough stack slots available"); | ||
734 | lua_pushliteral(L, "__compat53_extraspace"); | ||
735 | lua_pushvalue(L, -1); | ||
736 | lua_rawget(L, LUA_REGISTRYINDEX); | ||
737 | if (!lua_istable(L, -1)) { | ||
738 | lua_pop(L, 1); | ||
739 | lua_createtable(L, 0, 2); | ||
740 | lua_createtable(L, 0, 1); | ||
741 | lua_pushliteral(L, "k"); | ||
742 | lua_setfield(L, -2, "__mode"); | ||
743 | lua_setmetatable(L, -2); | ||
744 | lua_pushvalue(L, -2); | ||
745 | lua_pushvalue(L, -2); | ||
746 | lua_rawset(L, LUA_REGISTRYINDEX); | ||
747 | } | ||
748 | lua_replace(L, -2); | ||
749 | is_main = lua_pushthread(L); | ||
750 | lua_rawget(L, -2); | ||
751 | ptr = lua_touserdata(L, -1); | ||
752 | if (!ptr) { | ||
753 | lua_pop(L, 1); | ||
754 | ptr = lua_newuserdata(L, LUA_EXTRASPACE); | ||
755 | if (is_main) { | ||
756 | memset(ptr, '\0', LUA_EXTRASPACE); | ||
757 | lua_pushthread(L); | ||
758 | lua_pushvalue(L, -2); | ||
759 | lua_rawset(L, -4); | ||
760 | lua_pushboolean(L, 1); | ||
761 | lua_pushvalue(L, -2); | ||
762 | lua_rawset(L, -4); | ||
763 | } else { | ||
764 | void* mptr = NULL; | ||
765 | lua_pushboolean(L, 1); | ||
766 | lua_rawget(L, -3); | ||
767 | mptr = lua_touserdata(L, -1); | ||
768 | if (mptr) | ||
769 | memcpy(ptr, mptr, LUA_EXTRASPACE); | ||
770 | else | ||
771 | memset(ptr, '\0', LUA_EXTRASPACE); | ||
772 | lua_pop(L, 1); | ||
773 | lua_pushthread(L); | ||
774 | lua_pushvalue(L, -2); | ||
775 | lua_rawset(L, -4); | ||
776 | } | ||
777 | } | ||
778 | lua_pop(L, 2); | ||
779 | return ptr; | ||
780 | } | ||
781 | |||
782 | |||
783 | COMPAT53_API int lua_isinteger (lua_State *L, int index) { | ||
784 | if (lua_type(L, index) == LUA_TNUMBER) { | ||
785 | lua_Number n = lua_tonumber(L, index); | ||
786 | lua_Integer i = lua_tointeger(L, index); | ||
787 | if (i == n) | ||
788 | return 1; | ||
789 | } | ||
790 | return 0; | ||
791 | } | ||
792 | |||
793 | |||
794 | COMPAT53_API lua_Integer lua_tointegerx (lua_State *L, int i, int *isnum) { | ||
795 | int ok = 0; | ||
796 | lua_Number n = lua_tonumberx(L, i, &ok); | ||
797 | if (ok) { | ||
798 | if (n == (lua_Integer)n) { | ||
799 | if (isnum) | ||
800 | *isnum = 1; | ||
801 | return (lua_Integer)n; | ||
802 | } | ||
803 | } | ||
804 | if (isnum) | ||
805 | *isnum = 0; | ||
806 | return 0; | ||
807 | } | ||
808 | |||
809 | |||
810 | static void compat53_reverse (lua_State *L, int a, int b) { | ||
811 | for (; a < b; ++a, --b) { | ||
812 | lua_pushvalue(L, a); | ||
813 | lua_pushvalue(L, b); | ||
814 | lua_replace(L, a); | ||
815 | lua_replace(L, b); | ||
816 | } | ||
817 | } | ||
818 | |||
819 | |||
820 | COMPAT53_API void lua_rotate (lua_State *L, int idx, int n) { | ||
821 | int n_elems = 0; | ||
822 | idx = lua_absindex(L, idx); | ||
823 | n_elems = lua_gettop(L)-idx+1; | ||
824 | if (n < 0) | ||
825 | n += n_elems; | ||
826 | if ( n > 0 && n < n_elems) { | ||
827 | luaL_checkstack(L, 2, "not enough stack slots available"); | ||
828 | n = n_elems - n; | ||
829 | compat53_reverse(L, idx, idx+n-1); | ||
830 | compat53_reverse(L, idx+n, idx+n_elems-1); | ||
831 | compat53_reverse(L, idx, idx+n_elems-1); | ||
832 | } | ||
833 | } | ||
834 | |||
835 | |||
836 | COMPAT53_API void lua_seti (lua_State *L, int index, lua_Integer i) { | ||
837 | luaL_checkstack(L, 1, "not enough stack slots available"); | ||
838 | index = lua_absindex(L, index); | ||
839 | lua_pushinteger(L, i); | ||
840 | lua_insert(L, -2); | ||
841 | lua_settable(L, index); | ||
842 | } | ||
843 | |||
844 | |||
845 | #if !defined(lua_str2number) | ||
846 | # define lua_str2number(s, p) strtod((s), (p)) | ||
847 | #endif | ||
848 | |||
849 | COMPAT53_API size_t lua_stringtonumber (lua_State *L, const char *s) { | ||
850 | char* endptr; | ||
851 | lua_Number n = lua_str2number(s, &endptr); | ||
852 | if (endptr != s) { | ||
853 | while (*endptr != '\0' && isspace((unsigned char)*endptr)) | ||
854 | ++endptr; | ||
855 | if (*endptr == '\0') { | ||
856 | lua_pushnumber(L, n); | ||
857 | return endptr - s + 1; | ||
858 | } | ||
859 | } | ||
860 | return 0; | ||
861 | } | ||
862 | |||
863 | |||
864 | COMPAT53_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { | ||
865 | if (!luaL_callmeta(L, idx, "__tostring")) { | ||
866 | int t = lua_type(L, idx), tt = 0; | ||
867 | char const* name = NULL; | ||
868 | switch (t) { | ||
869 | case LUA_TNIL: | ||
870 | lua_pushliteral(L, "nil"); | ||
871 | break; | ||
872 | case LUA_TSTRING: | ||
873 | case LUA_TNUMBER: | ||
874 | lua_pushvalue(L, idx); | ||
875 | break; | ||
876 | case LUA_TBOOLEAN: | ||
877 | if (lua_toboolean(L, idx)) | ||
878 | lua_pushliteral(L, "true"); | ||
879 | else | ||
880 | lua_pushliteral(L, "false"); | ||
881 | break; | ||
882 | default: | ||
883 | tt = luaL_getmetafield(L, idx, "__name"); | ||
884 | name = (tt == LUA_TSTRING) ? lua_tostring(L, -1) : lua_typename(L, t); | ||
885 | lua_pushfstring(L, "%s: %p", name, lua_topointer(L, idx)); | ||
886 | if (tt != LUA_TNIL) | ||
887 | lua_replace(L, -2); | ||
888 | break; | ||
889 | } | ||
890 | } else { | ||
891 | if (!lua_isstring(L, -1)) | ||
892 | luaL_error(L, "'__tostring' must return a string"); | ||
893 | } | ||
894 | return lua_tolstring(L, -1, len); | ||
895 | } | ||
896 | |||
897 | |||
898 | COMPAT53_API void luaL_requiref (lua_State *L, const char *modname, | ||
899 | lua_CFunction openf, int glb) { | ||
900 | luaL_checkstack(L, 3, "not enough stack slots available"); | ||
901 | luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); | ||
902 | if (lua_getfield(L, -1, modname) == LUA_TNIL) { | ||
903 | lua_pop(L, 1); | ||
904 | lua_pushcfunction(L, openf); | ||
905 | lua_pushstring(L, modname); | ||
906 | lua_call(L, 1, 1); | ||
907 | lua_pushvalue(L, -1); | ||
908 | lua_setfield(L, -3, modname); | ||
909 | } | ||
910 | if (glb) { | ||
911 | lua_pushvalue(L, -1); | ||
912 | lua_setglobal(L, modname); | ||
913 | } | ||
914 | lua_replace(L, -2); | ||
915 | } | ||
916 | |||
917 | |||
918 | #endif /* Lua 5.1 and 5.2 */ | ||
919 | |||
920 | |||
921 | #endif /* COMPAT53_C_ */ | ||
922 | |||
923 | |||
924 | /********************************************************************* | ||
925 | * This file contains parts of Lua 5.2's and Lua 5.3's source code: | ||
926 | * | ||
927 | * Copyright (C) 1994-2014 Lua.org, PUC-Rio. | ||
928 | * | ||
929 | * Permission is hereby granted, free of charge, to any person obtaining | ||
930 | * a copy of this software and associated documentation files (the | ||
931 | * "Software"), to deal in the Software without restriction, including | ||
932 | * without limitation the rights to use, copy, modify, merge, publish, | ||
933 | * distribute, sublicense, and/or sell copies of the Software, and to | ||
934 | * permit persons to whom the Software is furnished to do so, subject to | ||
935 | * the following conditions: | ||
936 | * | ||
937 | * The above copyright notice and this permission notice shall be | ||
938 | * included in all copies or substantial portions of the Software. | ||
939 | * | ||
940 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
941 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
942 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
943 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
944 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
945 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
946 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
947 | *********************************************************************/ | ||
948 | |||
diff --git a/vendor/lua-bz2/compat-5.3.h b/vendor/lua-bz2/compat-5.3.h new file mode 100644 index 00000000..b730a4b8 --- /dev/null +++ b/vendor/lua-bz2/compat-5.3.h | |||
@@ -0,0 +1,424 @@ | |||
1 | #ifndef COMPAT53_H_ | ||
2 | #define COMPAT53_H_ | ||
3 | |||
4 | #include <stddef.h> | ||
5 | #include <limits.h> | ||
6 | #include <string.h> | ||
7 | #if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP) | ||
8 | extern "C" { | ||
9 | #endif | ||
10 | #include <lua.h> | ||
11 | #include <lauxlib.h> | ||
12 | #include <lualib.h> | ||
13 | #if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP) | ||
14 | } | ||
15 | #endif | ||
16 | |||
17 | |||
18 | #undef COMPAT53_INCLUDE_SOURCE | ||
19 | #if defined(COMPAT53_PREFIX) | ||
20 | /* - change the symbol names of functions to avoid linker conflicts | ||
21 | * - compat-5.3.c needs to be compiled (and linked) separately | ||
22 | */ | ||
23 | # if !defined(COMPAT53_API) | ||
24 | # define COMPAT53_API extern | ||
25 | # endif | ||
26 | #else /* COMPAT53_PREFIX */ | ||
27 | /* - make all functions static and include the source. | ||
28 | * - compat-5.3.c doesn't need to be compiled (and linked) separately | ||
29 | */ | ||
30 | # define COMPAT53_PREFIX compat53 | ||
31 | # undef COMPAT53_API | ||
32 | # if defined(__GNUC__) || defined(__clang__) | ||
33 | # define COMPAT53_API __attribute__((__unused__)) static | ||
34 | # else | ||
35 | # define COMPAT53_API static | ||
36 | # endif | ||
37 | # define COMPAT53_INCLUDE_SOURCE | ||
38 | #endif /* COMPAT53_PREFIX */ | ||
39 | |||
40 | #define COMPAT53_CONCAT_HELPER(a, b) a##b | ||
41 | #define COMPAT53_CONCAT(a, b) COMPAT53_CONCAT_HELPER(a, b) | ||
42 | |||
43 | |||
44 | |||
45 | /* declarations for Lua 5.1 */ | ||
46 | #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 | ||
47 | |||
48 | /* XXX not implemented: | ||
49 | * lua_arith (new operators) | ||
50 | * lua_upvalueid | ||
51 | * lua_upvaluejoin | ||
52 | * lua_version | ||
53 | * lua_yieldk | ||
54 | */ | ||
55 | |||
56 | #ifndef LUA_OK | ||
57 | # define LUA_OK 0 | ||
58 | #endif | ||
59 | #ifndef LUA_OPADD | ||
60 | # define LUA_OPADD 0 | ||
61 | #endif | ||
62 | #ifndef LUA_OPSUB | ||
63 | # define LUA_OPSUB 1 | ||
64 | #endif | ||
65 | #ifndef LUA_OPMUL | ||
66 | # define LUA_OPMUL 2 | ||
67 | #endif | ||
68 | #ifndef LUA_OPDIV | ||
69 | # define LUA_OPDIV 3 | ||
70 | #endif | ||
71 | #ifndef LUA_OPMOD | ||
72 | # define LUA_OPMOD 4 | ||
73 | #endif | ||
74 | #ifndef LUA_OPPOW | ||
75 | # define LUA_OPPOW 5 | ||
76 | #endif | ||
77 | #ifndef LUA_OPUNM | ||
78 | # define LUA_OPUNM 6 | ||
79 | #endif | ||
80 | #ifndef LUA_OPEQ | ||
81 | # define LUA_OPEQ 0 | ||
82 | #endif | ||
83 | #ifndef LUA_OPLT | ||
84 | # define LUA_OPLT 1 | ||
85 | #endif | ||
86 | #ifndef LUA_OPLE | ||
87 | # define LUA_OPLE 2 | ||
88 | #endif | ||
89 | |||
90 | /* LuaJIT/Lua 5.1 does not have the updated | ||
91 | * error codes for thread status/function returns (but some patched versions do) | ||
92 | * define it only if it's not found | ||
93 | */ | ||
94 | #if !defined(LUA_ERRGCMM) | ||
95 | /* Use + 2 because in some versions of Lua (Lua 5.1) | ||
96 | * LUA_ERRFILE is defined as (LUA_ERRERR+1) | ||
97 | * so we need to avoid it (LuaJIT might have something at this | ||
98 | * integer value too) | ||
99 | */ | ||
100 | # define LUA_ERRGCMM (LUA_ERRERR + 2) | ||
101 | #endif /* LUA_ERRGCMM define */ | ||
102 | |||
103 | typedef size_t lua_Unsigned; | ||
104 | |||
105 | typedef struct luaL_Buffer_53 { | ||
106 | luaL_Buffer b; /* make incorrect code crash! */ | ||
107 | char *ptr; | ||
108 | size_t nelems; | ||
109 | size_t capacity; | ||
110 | lua_State *L2; | ||
111 | } luaL_Buffer_53; | ||
112 | #define luaL_Buffer luaL_Buffer_53 | ||
113 | |||
114 | /* In PUC-Rio 5.1, userdata is a simple FILE* | ||
115 | * In LuaJIT, it's a struct where the first member is a FILE* | ||
116 | * We can't support the `closef` member | ||
117 | */ | ||
118 | typedef struct luaL_Stream { | ||
119 | FILE *f; | ||
120 | } luaL_Stream; | ||
121 | |||
122 | #define lua_absindex COMPAT53_CONCAT(COMPAT53_PREFIX, _absindex) | ||
123 | COMPAT53_API int lua_absindex (lua_State *L, int i); | ||
124 | |||
125 | #define lua_arith COMPAT53_CONCAT(COMPAT53_PREFIX, _arith) | ||
126 | COMPAT53_API void lua_arith (lua_State *L, int op); | ||
127 | |||
128 | #define lua_compare COMPAT53_CONCAT(COMPAT53_PREFIX, _compare) | ||
129 | COMPAT53_API int lua_compare (lua_State *L, int idx1, int idx2, int op); | ||
130 | |||
131 | #define lua_copy COMPAT53_CONCAT(COMPAT53_PREFIX, _copy) | ||
132 | COMPAT53_API void lua_copy (lua_State *L, int from, int to); | ||
133 | |||
134 | #define lua_getuservalue(L, i) \ | ||
135 | (lua_getfenv((L), (i)), lua_type((L), -1)) | ||
136 | #define lua_setuservalue(L, i) \ | ||
137 | (luaL_checktype((L), -1, LUA_TTABLE), lua_setfenv((L), (i))) | ||
138 | |||
139 | #define lua_len COMPAT53_CONCAT(COMPAT53_PREFIX, _len) | ||
140 | COMPAT53_API void lua_len (lua_State *L, int i); | ||
141 | |||
142 | #define lua_pushstring(L, s) \ | ||
143 | (lua_pushstring((L), (s)), lua_tostring((L), -1)) | ||
144 | |||
145 | #define lua_pushlstring(L, s, len) \ | ||
146 | ((((len) == 0) ? lua_pushlstring((L), "", 0) : lua_pushlstring((L), (s), (len))), lua_tostring((L), -1)) | ||
147 | |||
148 | #ifndef luaL_newlibtable | ||
149 | # define luaL_newlibtable(L, l) \ | ||
150 | (lua_createtable((L), 0, sizeof((l))/sizeof(*(l))-1)) | ||
151 | #endif | ||
152 | #ifndef luaL_newlib | ||
153 | # define luaL_newlib(L, l) \ | ||
154 | (luaL_newlibtable((L), (l)), luaL_register((L), NULL, (l))) | ||
155 | #endif | ||
156 | |||
157 | #define lua_pushglobaltable(L) \ | ||
158 | lua_pushvalue((L), LUA_GLOBALSINDEX) | ||
159 | |||
160 | #define lua_rawgetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawgetp) | ||
161 | COMPAT53_API int lua_rawgetp (lua_State *L, int i, const void *p); | ||
162 | |||
163 | #define lua_rawsetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawsetp) | ||
164 | COMPAT53_API void lua_rawsetp(lua_State *L, int i, const void *p); | ||
165 | |||
166 | #define lua_rawlen(L, i) lua_objlen((L), (i)) | ||
167 | |||
168 | #define lua_tointeger(L, i) lua_tointegerx((L), (i), NULL) | ||
169 | |||
170 | #define lua_tonumberx COMPAT53_CONCAT(COMPAT53_PREFIX, _tonumberx) | ||
171 | COMPAT53_API lua_Number lua_tonumberx (lua_State *L, int i, int *isnum); | ||
172 | |||
173 | #define luaL_checkversion COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkversion) | ||
174 | COMPAT53_API void luaL_checkversion (lua_State *L); | ||
175 | |||
176 | #define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53) | ||
177 | COMPAT53_API int lua_load (lua_State *L, lua_Reader reader, void *data, const char* source, const char* mode); | ||
178 | |||
179 | #define luaL_loadfilex COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadfilex) | ||
180 | COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char *mode); | ||
181 | |||
182 | #define luaL_loadbufferx COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadbufferx) | ||
183 | COMPAT53_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode); | ||
184 | |||
185 | #define luaL_checkstack COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkstack_53) | ||
186 | COMPAT53_API void luaL_checkstack (lua_State *L, int sp, const char *msg); | ||
187 | |||
188 | #define luaL_getsubtable COMPAT53_CONCAT(COMPAT53_PREFIX, L_getsubtable) | ||
189 | COMPAT53_API int luaL_getsubtable (lua_State* L, int i, const char *name); | ||
190 | |||
191 | #define luaL_len COMPAT53_CONCAT(COMPAT53_PREFIX, L_len) | ||
192 | COMPAT53_API lua_Integer luaL_len (lua_State *L, int i); | ||
193 | |||
194 | #define luaL_setfuncs COMPAT53_CONCAT(COMPAT53_PREFIX, L_setfuncs) | ||
195 | COMPAT53_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup); | ||
196 | |||
197 | #define luaL_setmetatable COMPAT53_CONCAT(COMPAT53_PREFIX, L_setmetatable) | ||
198 | COMPAT53_API void luaL_setmetatable (lua_State *L, const char *tname); | ||
199 | |||
200 | #define luaL_testudata COMPAT53_CONCAT(COMPAT53_PREFIX, L_testudata) | ||
201 | COMPAT53_API void *luaL_testudata (lua_State *L, int i, const char *tname); | ||
202 | |||
203 | #define luaL_traceback COMPAT53_CONCAT(COMPAT53_PREFIX, L_traceback) | ||
204 | COMPAT53_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg, int level); | ||
205 | |||
206 | #define luaL_fileresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_fileresult) | ||
207 | COMPAT53_API int luaL_fileresult (lua_State *L, int stat, const char *fname); | ||
208 | |||
209 | #define luaL_execresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_execresult) | ||
210 | COMPAT53_API int luaL_execresult (lua_State *L, int stat); | ||
211 | |||
212 | #define lua_callk(L, na, nr, ctx, cont) \ | ||
213 | ((void)(ctx), (void)(cont), lua_call((L), (na), (nr))) | ||
214 | #define lua_pcallk(L, na, nr, err, ctx, cont) \ | ||
215 | ((void)(ctx), (void)(cont), lua_pcall((L), (na), (nr), (err))) | ||
216 | |||
217 | #define lua_resume(L, from, nargs) \ | ||
218 | ((void)(from), lua_resume((L), (nargs))) | ||
219 | |||
220 | #define luaL_buffinit COMPAT53_CONCAT(COMPAT53_PREFIX, _buffinit_53) | ||
221 | COMPAT53_API void luaL_buffinit (lua_State *L, luaL_Buffer_53 *B); | ||
222 | |||
223 | #define luaL_prepbuffsize COMPAT53_CONCAT(COMPAT53_PREFIX, _prepbufsize_53) | ||
224 | COMPAT53_API char *luaL_prepbuffsize (luaL_Buffer_53 *B, size_t s); | ||
225 | |||
226 | #define luaL_addlstring COMPAT53_CONCAT(COMPAT53_PREFIX, _addlstring_53) | ||
227 | COMPAT53_API void luaL_addlstring (luaL_Buffer_53 *B, const char *s, size_t l); | ||
228 | |||
229 | #define luaL_addvalue COMPAT53_CONCAT(COMPAT53_PREFIX, _addvalue_53) | ||
230 | COMPAT53_API void luaL_addvalue (luaL_Buffer_53 *B); | ||
231 | |||
232 | #define luaL_pushresult COMPAT53_CONCAT(COMPAT53_PREFIX, _pushresult_53) | ||
233 | COMPAT53_API void luaL_pushresult (luaL_Buffer_53 *B); | ||
234 | |||
235 | #undef luaL_buffinitsize | ||
236 | #define luaL_buffinitsize(L, B, s) \ | ||
237 | (luaL_buffinit((L), (B)), luaL_prepbuffsize((B), (s))) | ||
238 | |||
239 | #undef luaL_prepbuffer | ||
240 | #define luaL_prepbuffer(B) \ | ||
241 | luaL_prepbuffsize((B), LUAL_BUFFERSIZE) | ||
242 | |||
243 | #undef luaL_addchar | ||
244 | #define luaL_addchar(B, c) \ | ||
245 | ((void)((B)->nelems < (B)->capacity || luaL_prepbuffsize((B), 1)), \ | ||
246 | ((B)->ptr[(B)->nelems++] = (c))) | ||
247 | |||
248 | #undef luaL_addsize | ||
249 | #define luaL_addsize(B, s) \ | ||
250 | ((B)->nelems += (s)) | ||
251 | |||
252 | #undef luaL_addstring | ||
253 | #define luaL_addstring(B, s) \ | ||
254 | luaL_addlstring((B), (s), strlen((s))) | ||
255 | |||
256 | #undef luaL_pushresultsize | ||
257 | #define luaL_pushresultsize(B, s) \ | ||
258 | (luaL_addsize((B), (s)), luaL_pushresult((B))) | ||
259 | |||
260 | #if defined(LUA_COMPAT_APIINTCASTS) | ||
261 | #define lua_pushunsigned(L, n) \ | ||
262 | lua_pushinteger((L), (lua_Integer)(n)) | ||
263 | #define lua_tounsignedx(L, i, is) \ | ||
264 | ((lua_Unsigned)lua_tointegerx((L), (i), (is))) | ||
265 | #define lua_tounsigned(L, i) \ | ||
266 | lua_tounsignedx((L), (i), NULL) | ||
267 | #define luaL_checkunsigned(L, a) \ | ||
268 | ((lua_Unsigned)luaL_checkinteger((L), (a))) | ||
269 | #define luaL_optunsigned(L, a, d) \ | ||
270 | ((lua_Unsigned)luaL_optinteger((L), (a), (lua_Integer)(d))) | ||
271 | #endif | ||
272 | |||
273 | #endif /* Lua 5.1 only */ | ||
274 | |||
275 | |||
276 | |||
277 | /* declarations for Lua 5.1 and 5.2 */ | ||
278 | #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM <= 502 | ||
279 | |||
280 | typedef int lua_KContext; | ||
281 | |||
282 | typedef int (*lua_KFunction)(lua_State *L, int status, lua_KContext ctx); | ||
283 | |||
284 | #define lua_dump(L, w, d, s) \ | ||
285 | ((void)(s), lua_dump((L), (w), (d))) | ||
286 | |||
287 | #define lua_getfield(L, i, k) \ | ||
288 | (lua_getfield((L), (i), (k)), lua_type((L), -1)) | ||
289 | |||
290 | #define lua_gettable(L, i) \ | ||
291 | (lua_gettable((L), (i)), lua_type((L), -1)) | ||
292 | |||
293 | #define lua_geti COMPAT53_CONCAT(COMPAT53_PREFIX, _geti) | ||
294 | COMPAT53_API int lua_geti (lua_State *L, int index, lua_Integer i); | ||
295 | |||
296 | #define lua_getextraspace COMPAT53_CONCAT(COMPAT53_PREFIX, _getextraspace) | ||
297 | COMPAT53_API void *lua_getextraspace (lua_State *L); | ||
298 | |||
299 | #define lua_isinteger COMPAT53_CONCAT(COMPAT53_PREFIX, _isinteger) | ||
300 | COMPAT53_API int lua_isinteger (lua_State *L, int index); | ||
301 | |||
302 | #define lua_tointegerx COMPAT53_CONCAT(COMPAT53_PREFIX, _tointegerx_53) | ||
303 | COMPAT53_API lua_Integer lua_tointegerx (lua_State *L, int i, int *isnum); | ||
304 | |||
305 | #define lua_numbertointeger(n, p) \ | ||
306 | ((*(p) = (lua_Integer)(n)), 1) | ||
307 | |||
308 | #define lua_rawget(L, i) \ | ||
309 | (lua_rawget((L), (i)), lua_type((L), -1)) | ||
310 | |||
311 | #define lua_rawgeti(L, i, n) \ | ||
312 | (lua_rawgeti((L), (i), (n)), lua_type((L), -1)) | ||
313 | |||
314 | #define lua_rotate COMPAT53_CONCAT(COMPAT53_PREFIX, _rotate) | ||
315 | COMPAT53_API void lua_rotate (lua_State *L, int idx, int n); | ||
316 | |||
317 | #define lua_seti COMPAT53_CONCAT(COMPAT53_PREFIX, _seti) | ||
318 | COMPAT53_API void lua_seti (lua_State *L, int index, lua_Integer i); | ||
319 | |||
320 | #define lua_stringtonumber COMPAT53_CONCAT(COMPAT53_PREFIX, _stringtonumber) | ||
321 | COMPAT53_API size_t lua_stringtonumber (lua_State *L, const char *s); | ||
322 | |||
323 | #define luaL_tolstring COMPAT53_CONCAT(COMPAT53_PREFIX, L_tolstring) | ||
324 | COMPAT53_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len); | ||
325 | |||
326 | #define luaL_getmetafield(L, o, e) \ | ||
327 | (luaL_getmetafield((L), (o), (e)) ? lua_type((L), -1) : LUA_TNIL) | ||
328 | |||
329 | #define luaL_newmetatable(L, tn) \ | ||
330 | (luaL_newmetatable((L), (tn)) ? (lua_pushstring((L), (tn)), lua_setfield((L), -2, "__name"), 1) : 0) | ||
331 | |||
332 | #define luaL_requiref COMPAT53_CONCAT(COMPAT53_PREFIX, L_requiref_53) | ||
333 | COMPAT53_API void luaL_requiref (lua_State *L, const char *modname, | ||
334 | lua_CFunction openf, int glb ); | ||
335 | |||
336 | #endif /* Lua 5.1 and Lua 5.2 */ | ||
337 | |||
338 | |||
339 | |||
340 | /* declarations for Lua 5.2 */ | ||
341 | #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 502 | ||
342 | |||
343 | /* XXX not implemented: | ||
344 | * lua_isyieldable | ||
345 | * lua_arith (new operators) | ||
346 | * lua_pushfstring (new formats) | ||
347 | */ | ||
348 | |||
349 | #define lua_getglobal(L, n) \ | ||
350 | (lua_getglobal((L), (n)), lua_type((L), -1)) | ||
351 | |||
352 | #define lua_getuservalue(L, i) \ | ||
353 | (lua_getuservalue((L), (i)), lua_type((L), -1)) | ||
354 | |||
355 | #define lua_pushlstring(L, s, len) \ | ||
356 | (((len) == 0) ? lua_pushlstring((L), "", 0) : lua_pushlstring((L), (s), (len))) | ||
357 | |||
358 | #define lua_rawgetp(L, i, p) \ | ||
359 | (lua_rawgetp((L), (i), (p)), lua_type((L), -1)) | ||
360 | |||
361 | #define LUA_KFUNCTION(_name) \ | ||
362 | static int (_name)(lua_State *L, int status, lua_KContext ctx); \ | ||
363 | static int (_name ## _52)(lua_State *L) { \ | ||
364 | lua_KContext ctx; \ | ||
365 | int status = lua_getctx(L, &ctx); \ | ||
366 | return (_name)(L, status, ctx); \ | ||
367 | } \ | ||
368 | static int (_name)(lua_State *L, int status, lua_KContext ctx) | ||
369 | |||
370 | #define lua_pcallk(L, na, nr, err, ctx, cont) \ | ||
371 | lua_pcallk((L), (na), (nr), (err), (ctx), cont ## _52) | ||
372 | |||
373 | #define lua_callk(L, na, nr, ctx, cont) \ | ||
374 | lua_callk((L), (na), (nr), (ctx), cont ## _52) | ||
375 | |||
376 | #define lua_yieldk(L, nr, ctx, cont) \ | ||
377 | lua_yieldk((L), (nr), (ctx), cont ## _52) | ||
378 | |||
379 | #ifdef lua_call | ||
380 | # undef lua_call | ||
381 | # define lua_call(L, na, nr) \ | ||
382 | (lua_callk)((L), (na), (nr), 0, NULL) | ||
383 | #endif | ||
384 | |||
385 | #ifdef lua_pcall | ||
386 | # undef lua_pcall | ||
387 | # define lua_pcall(L, na, nr, err) \ | ||
388 | (lua_pcallk)((L), (na), (nr), (err), 0, NULL) | ||
389 | #endif | ||
390 | |||
391 | #ifdef lua_yield | ||
392 | # undef lua_yield | ||
393 | # define lua_yield(L, nr) \ | ||
394 | (lua_yieldk)((L), (nr), 0, NULL) | ||
395 | #endif | ||
396 | |||
397 | #endif /* Lua 5.2 only */ | ||
398 | |||
399 | |||
400 | |||
401 | /* other Lua versions */ | ||
402 | #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501 || LUA_VERSION_NUM > 504 | ||
403 | |||
404 | # error "unsupported Lua version (i.e. not Lua 5.1, 5.2, 5.3, or 5.4)" | ||
405 | |||
406 | #endif /* other Lua versions except 5.1, 5.2, 5.3, and 5.4 */ | ||
407 | |||
408 | |||
409 | |||
410 | /* helper macro for defining continuation functions (for every version | ||
411 | * *except* Lua 5.2) */ | ||
412 | #ifndef LUA_KFUNCTION | ||
413 | #define LUA_KFUNCTION(_name) \ | ||
414 | static int (_name)(lua_State *L, int status, lua_KContext ctx) | ||
415 | #endif | ||
416 | |||
417 | |||
418 | #if defined(COMPAT53_INCLUDE_SOURCE) | ||
419 | # include "compat-5.3.c" | ||
420 | #endif | ||
421 | |||
422 | |||
423 | #endif /* COMPAT53_H_ */ | ||
424 | |||
diff --git a/vendor/lua-bz2/lbz.c b/vendor/lua-bz2/lbz.c new file mode 100644 index 00000000..6e0d66e2 --- /dev/null +++ b/vendor/lua-bz2/lbz.c | |||
@@ -0,0 +1,52 @@ | |||
1 | /* This file implements the Lua binding to libbzip2. | ||
2 | * | ||
3 | * Copyright (c) 2008, Evan Klitzke <evan@eklitzke.org> | ||
4 | * Copyright (c) 2012, Thomas Harning Jr <harningt@gmail.com> | ||
5 | * | ||
6 | * Permission to use, copy, modify, and/or distribute this software for any | ||
7 | * purpose with or without fee is hereby granted, provided that the above | ||
8 | * copyright notice and this permission notice appear in all copies. | ||
9 | * | ||
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
17 | */ | ||
18 | |||
19 | #include <lua.h> | ||
20 | #include <lauxlib.h> | ||
21 | |||
22 | /* This explicit define prevents compat-5.3.h from loading compat-5.3.c */ | ||
23 | #define COMPAT53_PREFIX compat53 | ||
24 | #include "compat-5.3.h" | ||
25 | |||
26 | #include "lbz2_file_reader.h" | ||
27 | #include "lbz2_file_writer.h" | ||
28 | #include "lbz2_stream.h" | ||
29 | |||
30 | static luaL_Reg lbz2_global[] = { | ||
31 | { NULL, NULL } | ||
32 | }; | ||
33 | |||
34 | int luaopen_bz2(lua_State *L) { | ||
35 | luaL_newlib(L, lbz2_global); | ||
36 | |||
37 | lua_pushliteral(L, "bz2"); | ||
38 | lua_setfield(L, -2, "_NAME"); | ||
39 | lua_pushliteral(L, "0.1"); | ||
40 | lua_setfield(L, -2, "_VERSION"); | ||
41 | |||
42 | register_lbz2_file_reader(L); | ||
43 | register_lbz2_file_writer(L); | ||
44 | register_lbz2_stream(L); | ||
45 | |||
46 | #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 | ||
47 | lua_pushvalue(L, -1); | ||
48 | lua_setglobal(L, "bz2"); | ||
49 | #endif | ||
50 | |||
51 | return 1; | ||
52 | } | ||
diff --git a/vendor/lua-bz2/lbz2_common.c b/vendor/lua-bz2/lbz2_common.c new file mode 100644 index 00000000..2aa76cfb --- /dev/null +++ b/vendor/lua-bz2/lbz2_common.c | |||
@@ -0,0 +1,57 @@ | |||
1 | /* This file implements the Lua binding to libbzip2. | ||
2 | * | ||
3 | * Copyright (c) 2008, Evan Klitzke <evan@eklitzke.org> | ||
4 | * Copyright (c) 2012, Thomas Harning Jr <harningt@gmail.com> | ||
5 | * | ||
6 | * Permission to use, copy, modify, and/or distribute this software for any | ||
7 | * purpose with or without fee is hereby granted, provided that the above | ||
8 | * copyright notice and this permission notice appear in all copies. | ||
9 | * | ||
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
17 | */ | ||
18 | |||
19 | |||
20 | #include "lbz2_common.h" | ||
21 | #include <bzlib.h> | ||
22 | |||
23 | |||
24 | const char *lbz2_error(int bzerror) { | ||
25 | switch (bzerror) { | ||
26 | case BZ_OK: | ||
27 | return "OK"; | ||
28 | case BZ_RUN_OK: | ||
29 | return "RUN_OK"; | ||
30 | case BZ_FLUSH_OK: | ||
31 | return "FLUSH_OK"; | ||
32 | case BZ_FINISH_OK: | ||
33 | return "FINISH_OK"; | ||
34 | case BZ_STREAM_END: | ||
35 | return "STREAM_END"; | ||
36 | case BZ_SEQUENCE_ERROR: | ||
37 | return "SEQUENCE_ERROR"; | ||
38 | case BZ_PARAM_ERROR: | ||
39 | return "PARAM_ERROR"; | ||
40 | case BZ_MEM_ERROR: | ||
41 | return "MEM_ERROR"; | ||
42 | case BZ_DATA_ERROR: | ||
43 | return "DATA_ERROR"; | ||
44 | case BZ_DATA_ERROR_MAGIC: | ||
45 | return "DATA_ERROR_MAGIC"; | ||
46 | case BZ_IO_ERROR: | ||
47 | return "IO_ERROR"; | ||
48 | case BZ_UNEXPECTED_EOF: | ||
49 | return "UNEXPECTED_EOF"; | ||
50 | case BZ_OUTBUFF_FULL: | ||
51 | return "OUTBUFF_FULL"; | ||
52 | case BZ_CONFIG_ERROR: | ||
53 | return "CONFIG_ERROR"; | ||
54 | default: | ||
55 | return "UNKNOWN"; | ||
56 | } | ||
57 | } | ||
diff --git a/vendor/lua-bz2/lbz2_common.h b/vendor/lua-bz2/lbz2_common.h new file mode 100644 index 00000000..98e534bf --- /dev/null +++ b/vendor/lua-bz2/lbz2_common.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* This file implements the Lua binding to libbzip2. | ||
2 | * | ||
3 | * Copyright (c) 2008, Evan Klitzke <evan@eklitzke.org> | ||
4 | * Copyright (c) 2012, Thomas Harning Jr <harningt@gmail.com> | ||
5 | * | ||
6 | * Permission to use, copy, modify, and/or distribute this software for any | ||
7 | * purpose with or without fee is hereby granted, provided that the above | ||
8 | * copyright notice and this permission notice appear in all copies. | ||
9 | * | ||
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
17 | */ | ||
18 | |||
19 | |||
20 | #ifndef LBZ2_COMMON_H | ||
21 | #define LBZ2_COMMON_H | ||
22 | |||
23 | const char *lbz2_error(int bzerror); | ||
24 | |||
25 | #endif | ||
diff --git a/vendor/lua-bz2/lbz2_file_reader.c b/vendor/lua-bz2/lbz2_file_reader.c new file mode 100644 index 00000000..c101a1ee --- /dev/null +++ b/vendor/lua-bz2/lbz2_file_reader.c | |||
@@ -0,0 +1,164 @@ | |||
1 | /* This file implements the Lua binding to libbzip2. | ||
2 | * | ||
3 | * Copyright (c) 2008, Evan Klitzke <evan@eklitzke.org> | ||
4 | * Copyright (c) 2012, Thomas Harning Jr <harningt@gmail.com> | ||
5 | * | ||
6 | * Permission to use, copy, modify, and/or distribute this software for any | ||
7 | * purpose with or without fee is hereby granted, provided that the above | ||
8 | * copyright notice and this permission notice appear in all copies. | ||
9 | * | ||
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
17 | */ | ||
18 | |||
19 | #include <bzlib.h> | ||
20 | #include <stdio.h> | ||
21 | #include <stdlib.h> | ||
22 | #include <string.h> | ||
23 | #include <lua.h> | ||
24 | #include <lauxlib.h> | ||
25 | |||
26 | /* This explicit define prevents compat-5.3.h from loading compat-5.3.c */ | ||
27 | #define COMPAT53_PREFIX compat53 | ||
28 | #include "compat-5.3.h" | ||
29 | |||
30 | #include "lbz2_file_reader.h" | ||
31 | #include "lbz2_common.h" | ||
32 | |||
33 | #define LBZ2_FILE_READER_MT "LBZ2_FILE_READER_MT" | ||
34 | |||
35 | typedef struct { | ||
36 | BZFILE *bz_stream; | ||
37 | FILE *f; | ||
38 | } lbz2_file_reader; | ||
39 | |||
40 | static lbz2_file_reader *lbz2_check_file_reader(lua_State *L, int index) { | ||
41 | return (lbz2_file_reader *)luaL_checkudata(L, index, LBZ2_FILE_READER_MT); | ||
42 | } | ||
43 | |||
44 | static int lbz2_file_reader_open(lua_State *L) { | ||
45 | lbz2_file_reader *reader; | ||
46 | int errorCode; | ||
47 | const char *fname = luaL_checkstring(L, 1); | ||
48 | int verbosity = luaL_optinteger(L, 3, 0); | ||
49 | int small = lua_toboolean(L, 4); | ||
50 | |||
51 | reader = lua_newuserdata(L, sizeof(*reader)); | ||
52 | memset(reader, 0, sizeof(*reader)); | ||
53 | |||
54 | luaL_getmetatable(L, LBZ2_FILE_READER_MT); | ||
55 | lua_setmetatable(L, -2); | ||
56 | |||
57 | reader->f = fopen(fname, "rb"); | ||
58 | |||
59 | if (reader->f == NULL) { | ||
60 | return luaL_error(L, "Failed to fopen %s", fname); | ||
61 | } | ||
62 | reader->bz_stream = BZ2_bzReadOpen(&errorCode, reader->f, verbosity, small, NULL, 0); | ||
63 | |||
64 | if (BZ_OK != errorCode) { | ||
65 | fclose(reader->f); | ||
66 | reader->f = NULL; | ||
67 | lua_pushnil(L); | ||
68 | lua_pushstring(L, lbz2_error(errorCode)); | ||
69 | return 2; | ||
70 | } | ||
71 | return 1; | ||
72 | } | ||
73 | |||
74 | static int lbz2_file_reader_close(lua_State *L) { | ||
75 | lbz2_file_reader *reader = lbz2_check_file_reader(L, 1); | ||
76 | int errorCode = BZ_OK; | ||
77 | |||
78 | if (reader->bz_stream) { | ||
79 | BZ2_bzReadClose(&errorCode, reader->bz_stream); | ||
80 | reader->bz_stream = NULL; | ||
81 | } | ||
82 | if (reader->f) { | ||
83 | fclose(reader->f); | ||
84 | reader->f = NULL; | ||
85 | } | ||
86 | |||
87 | lua_pushnil(L); | ||
88 | lua_setmetatable(L, 1); | ||
89 | |||
90 | if (BZ_OK != errorCode) { | ||
91 | lua_pushnil(L); | ||
92 | lua_pushstring(L, lbz2_error(errorCode)); | ||
93 | return 2; | ||
94 | } | ||
95 | lua_pushboolean(L, 1); | ||
96 | return 1; | ||
97 | } | ||
98 | |||
99 | static int lbz2_file_reader_read(lua_State *L) { | ||
100 | lbz2_file_reader *reader = lbz2_check_file_reader(L, 1); | ||
101 | int errorCode = BZ_OK; | ||
102 | int dataLength; | ||
103 | luaL_Buffer B; | ||
104 | /* If passed a boolean, read a single *chunk* */ | ||
105 | if (lua_isboolean(L, 2)) { | ||
106 | dataLength = LUAL_BUFFERSIZE; | ||
107 | } else { | ||
108 | dataLength = luaL_optinteger(L, 2, -1); | ||
109 | } | ||
110 | |||
111 | luaL_buffinit(L, &B); | ||
112 | |||
113 | /* Pull in chunks until all data read */ | ||
114 | while(dataLength > 0 || dataLength == -1) { | ||
115 | char *buf = luaL_prepbuffer(&B); | ||
116 | int nextRead = (dataLength == -1 || dataLength > LUAL_BUFFERSIZE) ? LUAL_BUFFERSIZE : dataLength; | ||
117 | int read = BZ2_bzRead(&errorCode, reader->bz_stream, buf, nextRead); | ||
118 | if (read > 0) { | ||
119 | luaL_addsize(&B, read); | ||
120 | dataLength -= read; | ||
121 | } | ||
122 | if (BZ_OK != errorCode) { | ||
123 | goto handle_error; | ||
124 | } | ||
125 | } | ||
126 | luaL_pushresult(&B); | ||
127 | return 1; | ||
128 | handle_error: | ||
129 | if(BZ_STREAM_END == errorCode) { | ||
130 | luaL_pushresult(&B); | ||
131 | lua_pushboolean(L, 1); | ||
132 | return 2; | ||
133 | } else { | ||
134 | lua_pushnil(L); | ||
135 | lua_pushstring(L, lbz2_error(errorCode)); | ||
136 | return 2; | ||
137 | } | ||
138 | } | ||
139 | |||
140 | static luaL_Reg lbz2_file_reader_ops[] = { | ||
141 | { "read", lbz2_file_reader_read }, | ||
142 | { "close", lbz2_file_reader_close }, | ||
143 | { NULL, NULL } | ||
144 | }; | ||
145 | |||
146 | static luaL_Reg lbz2_file_reader_global[] = { | ||
147 | { "openRead", lbz2_file_reader_open }, | ||
148 | { NULL, NULL } | ||
149 | }; | ||
150 | |||
151 | |||
152 | |||
153 | void register_lbz2_file_reader(lua_State *L) { | ||
154 | luaL_newmetatable(L, LBZ2_FILE_READER_MT); | ||
155 | lua_newtable(L); | ||
156 | luaL_setfuncs(L, lbz2_file_reader_ops, 0); | ||
157 | lua_setfield(L, -2, "__index"); | ||
158 | |||
159 | lua_pushcfunction(L, lbz2_file_reader_close); | ||
160 | lua_setfield(L, -2, "__gc"); | ||
161 | lua_pop(L, 1); | ||
162 | |||
163 | luaL_setfuncs(L, lbz2_file_reader_global, 0); | ||
164 | } | ||
diff --git a/vendor/lua-bz2/lbz2_file_reader.h b/vendor/lua-bz2/lbz2_file_reader.h new file mode 100644 index 00000000..a183329d --- /dev/null +++ b/vendor/lua-bz2/lbz2_file_reader.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* This file implements the Lua binding to libbzip2. | ||
2 | * | ||
3 | * Copyright (c) 2008, Evan Klitzke <evan@eklitzke.org> | ||
4 | * Copyright (c) 2012, Thomas Harning Jr <harningt@gmail.com> | ||
5 | * | ||
6 | * Permission to use, copy, modify, and/or distribute this software for any | ||
7 | * purpose with or without fee is hereby granted, provided that the above | ||
8 | * copyright notice and this permission notice appear in all copies. | ||
9 | * | ||
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
17 | */ | ||
18 | |||
19 | |||
20 | #ifndef LBZ2_FILE_READER_H | ||
21 | #define LBZ2_FILE_READER_H | ||
22 | |||
23 | void register_lbz2_file_reader(lua_State *L); | ||
24 | |||
25 | #endif | ||
diff --git a/vendor/lua-bz2/lbz2_file_writer.c b/vendor/lua-bz2/lbz2_file_writer.c new file mode 100644 index 00000000..f35beca3 --- /dev/null +++ b/vendor/lua-bz2/lbz2_file_writer.c | |||
@@ -0,0 +1,141 @@ | |||
1 | /* This file implements the Lua binding to libbzip2. | ||
2 | * | ||
3 | * Copyright (c) 2008, Evan Klitzke <evan@eklitzke.org> | ||
4 | * Copyright (c) 2012, Thomas Harning Jr <harningt@gmail.com> | ||
5 | * | ||
6 | * Permission to use, copy, modify, and/or distribute this software for any | ||
7 | * purpose with or without fee is hereby granted, provided that the above | ||
8 | * copyright notice and this permission notice appear in all copies. | ||
9 | * | ||
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
17 | */ | ||
18 | |||
19 | #include <bzlib.h> | ||
20 | #include <stdio.h> | ||
21 | #include <stdlib.h> | ||
22 | #include <string.h> | ||
23 | #include <lua.h> | ||
24 | #include <lauxlib.h> | ||
25 | |||
26 | #include <assert.h> | ||
27 | |||
28 | /* This explicit define prevents compat-5.3.h from loading compat-5.3.c */ | ||
29 | #define COMPAT53_PREFIX compat53 | ||
30 | #include "compat-5.3.h" | ||
31 | |||
32 | #include "lbz2_file_writer.h" | ||
33 | #include "lbz2_common.h" | ||
34 | |||
35 | #define LBZ2_FILE_WRITER_MT "LBZ2_FILE_WRITER_MT" | ||
36 | |||
37 | typedef struct { | ||
38 | BZFILE *bz_stream; | ||
39 | FILE *f; | ||
40 | } lbz2_file_writer; | ||
41 | |||
42 | static lbz2_file_writer *lbz2_check_file_writer(lua_State *L, int index) { | ||
43 | return (lbz2_file_writer *)luaL_checkudata(L, index, LBZ2_FILE_WRITER_MT); | ||
44 | } | ||
45 | |||
46 | static int lbz2_file_writer_open(lua_State *L) { | ||
47 | lbz2_file_writer *writer; | ||
48 | int errorCode; | ||
49 | const char *fname = luaL_checkstring(L, 1); | ||
50 | int blockSize100k = luaL_optinteger(L, 2, 9); | ||
51 | int verbosity = luaL_optinteger(L, 3, 0); | ||
52 | int workFactor = luaL_optinteger(L, 4, 0); | ||
53 | |||
54 | writer = lua_newuserdata(L, sizeof(*writer)); | ||
55 | memset(writer, 0, sizeof(*writer)); | ||
56 | |||
57 | luaL_getmetatable(L, LBZ2_FILE_WRITER_MT); | ||
58 | lua_setmetatable(L, -2); | ||
59 | |||
60 | writer->f = fopen(fname, "wb"); | ||
61 | |||
62 | if (writer->f == NULL) { | ||
63 | return luaL_error(L, "Failed to fopen %s", fname); | ||
64 | } | ||
65 | writer->bz_stream = BZ2_bzWriteOpen(&errorCode, writer->f, blockSize100k, verbosity, workFactor); | ||
66 | |||
67 | if (BZ_OK != errorCode) { | ||
68 | fclose(writer->f); | ||
69 | writer->f = NULL; | ||
70 | lua_pushnil(L); | ||
71 | lua_pushstring(L, lbz2_error(errorCode)); | ||
72 | return 2; | ||
73 | } | ||
74 | return 1; | ||
75 | } | ||
76 | |||
77 | static int lbz2_file_writer_close(lua_State *L) { | ||
78 | lbz2_file_writer *writer = lbz2_check_file_writer(L, 1); | ||
79 | int errorCode = BZ_OK; | ||
80 | |||
81 | if (writer->bz_stream) { | ||
82 | BZ2_bzWriteClose(&errorCode, writer->bz_stream, 0, NULL, NULL); | ||
83 | writer->bz_stream = NULL; | ||
84 | } | ||
85 | if (writer->f) { | ||
86 | fclose(writer->f); | ||
87 | writer->f = NULL; | ||
88 | } | ||
89 | |||
90 | lua_pushnil(L); | ||
91 | lua_setmetatable(L, 1); | ||
92 | |||
93 | if (BZ_OK != errorCode) { | ||
94 | lua_pushnil(L); | ||
95 | lua_pushstring(L, lbz2_error(errorCode)); | ||
96 | return 2; | ||
97 | } | ||
98 | lua_pushboolean(L, 1); | ||
99 | return 1; | ||
100 | } | ||
101 | |||
102 | static int lbz2_file_writer_write(lua_State *L) { | ||
103 | lbz2_file_writer *writer = lbz2_check_file_writer(L, 1); | ||
104 | int errorCode = BZ_OK; | ||
105 | size_t dataLength; | ||
106 | const char *data = luaL_checklstring(L, 2, &dataLength); | ||
107 | |||
108 | BZ2_bzWrite(&errorCode, writer->bz_stream, (void *)data, dataLength); | ||
109 | |||
110 | if (BZ_OK != errorCode) { | ||
111 | lua_pushnil(L); | ||
112 | lua_pushstring(L, lbz2_error(errorCode)); | ||
113 | return 2; | ||
114 | } | ||
115 | lua_pushboolean(L, 1); | ||
116 | return 1; | ||
117 | } | ||
118 | |||
119 | static luaL_Reg lbz2_file_writer_ops[] = { | ||
120 | { "write", lbz2_file_writer_write }, | ||
121 | { "close", lbz2_file_writer_close }, | ||
122 | { NULL, NULL } | ||
123 | }; | ||
124 | |||
125 | static luaL_Reg lbz2_file_writer_global[] = { | ||
126 | { "openWrite", lbz2_file_writer_open }, | ||
127 | { NULL, NULL } | ||
128 | }; | ||
129 | |||
130 | void register_lbz2_file_writer(lua_State *L) { | ||
131 | luaL_newmetatable(L, LBZ2_FILE_WRITER_MT); | ||
132 | lua_newtable(L); | ||
133 | luaL_setfuncs(L, lbz2_file_writer_ops, 0); | ||
134 | lua_setfield(L, -2, "__index"); | ||
135 | |||
136 | lua_pushcfunction(L, lbz2_file_writer_close); | ||
137 | lua_setfield(L, -2, "__gc"); | ||
138 | lua_pop(L, 1); | ||
139 | |||
140 | luaL_setfuncs(L, lbz2_file_writer_global, 0); | ||
141 | } | ||
diff --git a/vendor/lua-bz2/lbz2_file_writer.h b/vendor/lua-bz2/lbz2_file_writer.h new file mode 100644 index 00000000..4f2e5e09 --- /dev/null +++ b/vendor/lua-bz2/lbz2_file_writer.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* This file implements the Lua binding to libbzip2. | ||
2 | * | ||
3 | * Copyright (c) 2008, Evan Klitzke <evan@eklitzke.org> | ||
4 | * Copyright (c) 2012, Thomas Harning Jr <harningt@gmail.com> | ||
5 | * | ||
6 | * Permission to use, copy, modify, and/or distribute this software for any | ||
7 | * purpose with or without fee is hereby granted, provided that the above | ||
8 | * copyright notice and this permission notice appear in all copies. | ||
9 | * | ||
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
17 | */ | ||
18 | |||
19 | |||
20 | #ifndef LBZ2_FILE_WRITER_H | ||
21 | #define LBZ2_FILE_WRITER_H | ||
22 | |||
23 | void register_lbz2_file_writer(lua_State *L); | ||
24 | |||
25 | #endif | ||
diff --git a/vendor/lua-bz2/lbz2_stream.c b/vendor/lua-bz2/lbz2_stream.c new file mode 100644 index 00000000..9eb2ab2b --- /dev/null +++ b/vendor/lua-bz2/lbz2_stream.c | |||
@@ -0,0 +1,263 @@ | |||
1 | /* This file implements the Lua binding to libbzip2. | ||
2 | * | ||
3 | * Copyright (c) 2008, Evan Klitzke <evan@eklitzke.org> | ||
4 | * Copyright (c) 2012, Thomas Harning Jr <harningt@gmail.com> | ||
5 | * | ||
6 | * Permission to use, copy, modify, and/or distribute this software for any | ||
7 | * purpose with or without fee is hereby granted, provided that the above | ||
8 | * copyright notice and this permission notice appear in all copies. | ||
9 | * | ||
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
17 | */ | ||
18 | |||
19 | #include <bzlib.h> | ||
20 | #include <stdio.h> | ||
21 | #include <stdlib.h> | ||
22 | #include <string.h> | ||
23 | #include <lua.h> | ||
24 | #include <lauxlib.h> | ||
25 | |||
26 | #include <assert.h> | ||
27 | |||
28 | /* This explicit define prevents compat-5.3.h from loading compat-5.3.c */ | ||
29 | #define COMPAT53_PREFIX compat53 | ||
30 | #include "compat-5.3.h" | ||
31 | |||
32 | #include "lbz2_stream.h" | ||
33 | #include "lbz2_common.h" | ||
34 | |||
35 | #define LBZ2_STREAM_MT "LBZ2_STREAM_MT" | ||
36 | |||
37 | typedef struct { | ||
38 | bz_stream bz_stream; | ||
39 | int isDecompressing; | ||
40 | } lbz2_stream; | ||
41 | |||
42 | static lbz2_stream *lbz2_check_stream(lua_State *L, int index) { | ||
43 | return (lbz2_stream *)luaL_checkudata(L, index, LBZ2_STREAM_MT); | ||
44 | } | ||
45 | |||
46 | static int lbz2_stream_initCompress(lua_State *L) { | ||
47 | lbz2_stream *stream; | ||
48 | int errorCode; | ||
49 | int blockSize100k = luaL_optinteger(L, 1, 9); | ||
50 | int verbosity = luaL_optinteger(L, 2, 0); | ||
51 | int workFactor = luaL_optinteger(L, 3, 0); | ||
52 | |||
53 | stream = lua_newuserdata(L, sizeof(*stream)); | ||
54 | memset(stream, 0, sizeof(*stream)); | ||
55 | |||
56 | stream->isDecompressing = 0; | ||
57 | |||
58 | luaL_getmetatable(L, LBZ2_STREAM_MT); | ||
59 | lua_setmetatable(L, -2); | ||
60 | |||
61 | errorCode = BZ2_bzCompressInit(&stream->bz_stream, blockSize100k, verbosity, workFactor); | ||
62 | |||
63 | if (BZ_OK != errorCode) { | ||
64 | lua_pushnil(L); | ||
65 | lua_pushstring(L, lbz2_error(errorCode)); | ||
66 | return 2; | ||
67 | } | ||
68 | return 1; | ||
69 | } | ||
70 | |||
71 | static int lbz2_stream_initDecompress(lua_State *L) { | ||
72 | lbz2_stream *stream; | ||
73 | int errorCode; | ||
74 | int verbosity = luaL_optinteger(L, 1, 0); | ||
75 | int isSmall = lua_toboolean(L, 2); | ||
76 | |||
77 | stream = lua_newuserdata(L, sizeof(*stream)); | ||
78 | memset(stream, 0, sizeof(*stream)); | ||
79 | |||
80 | stream->isDecompressing = 1; | ||
81 | |||
82 | luaL_getmetatable(L, LBZ2_STREAM_MT); | ||
83 | lua_setmetatable(L, -2); | ||
84 | |||
85 | errorCode = BZ2_bzDecompressInit(&stream->bz_stream, verbosity, isSmall); | ||
86 | |||
87 | if (BZ_OK != errorCode) { | ||
88 | lua_pushnil(L); | ||
89 | lua_pushstring(L, lbz2_error(errorCode)); | ||
90 | return 2; | ||
91 | } | ||
92 | return 1; | ||
93 | } | ||
94 | static int lbz2_stream_close(lua_State *L) { | ||
95 | lbz2_stream *stream = lbz2_check_stream(L, 1); | ||
96 | int errorCode = BZ_OK; | ||
97 | |||
98 | if (stream->bz_stream.state) { | ||
99 | if (stream->isDecompressing) { | ||
100 | errorCode = BZ2_bzDecompressEnd(&stream->bz_stream); | ||
101 | } else { | ||
102 | errorCode = BZ2_bzCompressEnd(&stream->bz_stream); | ||
103 | } | ||
104 | } | ||
105 | |||
106 | lua_pushnil(L); | ||
107 | lua_setmetatable(L, 1); | ||
108 | |||
109 | if (BZ_OK != errorCode) { | ||
110 | lua_pushnil(L); | ||
111 | lua_pushstring(L, lbz2_error(errorCode)); | ||
112 | return 2; | ||
113 | } | ||
114 | lua_pushboolean(L, 1); | ||
115 | return 1; | ||
116 | } | ||
117 | |||
118 | static int lbz2_stream_perform_compress(lua_State *L, lbz2_stream *stream, int action) { | ||
119 | int errorCode = BZ_OK; | ||
120 | luaL_Buffer B; | ||
121 | |||
122 | luaL_buffinit(L, &B); | ||
123 | |||
124 | while (1) { | ||
125 | stream->bz_stream.avail_out = LUAL_BUFFERSIZE; | ||
126 | stream->bz_stream.next_out = luaL_prepbuffer(&B); | ||
127 | errorCode = BZ2_bzCompress(&stream->bz_stream, action); | ||
128 | |||
129 | switch (action) { | ||
130 | case BZ_RUN: | ||
131 | if (BZ_RUN_OK != errorCode) { | ||
132 | goto fail; | ||
133 | } | ||
134 | luaL_addsize(&B, LUAL_BUFFERSIZE - stream->bz_stream.avail_out); | ||
135 | if (stream->bz_stream.avail_in == 0 || stream->bz_stream.avail_out == LUAL_BUFFERSIZE) { | ||
136 | goto complete; | ||
137 | } | ||
138 | break; | ||
139 | case BZ_FLUSH: | ||
140 | if (BZ_FLUSH_OK != errorCode && BZ_RUN_OK != errorCode) { | ||
141 | goto fail; | ||
142 | } | ||
143 | luaL_addsize(&B, LUAL_BUFFERSIZE - stream->bz_stream.avail_out); | ||
144 | if (BZ_RUN_OK == errorCode) { | ||
145 | goto complete; | ||
146 | } | ||
147 | break; | ||
148 | case BZ_FINISH: | ||
149 | if (BZ_FINISH_OK != errorCode && BZ_STREAM_END != errorCode) { | ||
150 | goto fail; | ||
151 | } | ||
152 | luaL_addsize(&B, LUAL_BUFFERSIZE - stream->bz_stream.avail_out); | ||
153 | if (BZ_STREAM_END == errorCode) { | ||
154 | goto complete; | ||
155 | } | ||
156 | } | ||
157 | } | ||
158 | complete: | ||
159 | luaL_pushresult(&B); | ||
160 | return 1; | ||
161 | |||
162 | fail: | ||
163 | lua_pushnil(L); | ||
164 | lua_pushstring(L, lbz2_error(errorCode)); | ||
165 | return 2; | ||
166 | } | ||
167 | |||
168 | static int lbz2_stream_perform_decompress(lua_State *L, lbz2_stream *stream) { | ||
169 | int errorCode = BZ_OK; | ||
170 | luaL_Buffer B; | ||
171 | |||
172 | luaL_buffinit(L, &B); | ||
173 | |||
174 | while (1) { | ||
175 | stream->bz_stream.avail_out = LUAL_BUFFERSIZE; | ||
176 | stream->bz_stream.next_out = luaL_prepbuffer(&B); | ||
177 | errorCode = BZ2_bzDecompress(&stream->bz_stream); | ||
178 | |||
179 | if (BZ_OK != errorCode && BZ_STREAM_END != errorCode) { | ||
180 | goto fail; | ||
181 | } | ||
182 | luaL_addsize(&B, LUAL_BUFFERSIZE - stream->bz_stream.avail_out); | ||
183 | /* Stream over with */ | ||
184 | if (errorCode == BZ_STREAM_END) { | ||
185 | goto completeStream; | ||
186 | } | ||
187 | /* No more bytes left this round */ | ||
188 | if (stream->bz_stream.avail_in == 0 && stream->bz_stream.avail_out == LUAL_BUFFERSIZE) { | ||
189 | goto complete; | ||
190 | } | ||
191 | } | ||
192 | complete: | ||
193 | luaL_pushresult(&B); | ||
194 | return 1; | ||
195 | |||
196 | completeStream: | ||
197 | luaL_pushresult(&B); | ||
198 | /* Report in addition to the data collected, the number of trailing bytes | ||
199 | * still available in the input buffer for other use. */ | ||
200 | lua_pushinteger(L, stream->bz_stream.avail_in); | ||
201 | return 2; | ||
202 | |||
203 | fail: | ||
204 | lua_pushnil(L); | ||
205 | lua_pushstring(L, lbz2_error(errorCode)); | ||
206 | return 2; | ||
207 | } | ||
208 | static int lbz2_stream_update(lua_State *L) { | ||
209 | lbz2_stream *stream = lbz2_check_stream(L, 1); | ||
210 | size_t dataLength; | ||
211 | const char *data = luaL_optlstring(L, 2, NULL, &dataLength); | ||
212 | |||
213 | /* Update the pointers and feed the output buffer while data is available */ | ||
214 | stream->bz_stream.avail_in = dataLength; | ||
215 | /* Cast away const-ness since input data is never altered */ | ||
216 | stream->bz_stream.next_in = (char *)data; | ||
217 | |||
218 | /* For compression, need to specially flag finishing state */ | ||
219 | if (!stream->isDecompressing) { | ||
220 | return lbz2_stream_perform_compress(L, stream, !data ? BZ_FINISH : BZ_RUN); | ||
221 | } else { | ||
222 | return lbz2_stream_perform_decompress(L, stream); | ||
223 | } | ||
224 | } | ||
225 | |||
226 | static int lbz2_stream_flush(lua_State *L) { | ||
227 | lbz2_stream *stream = lbz2_check_stream(L, 1); | ||
228 | if (!stream->isDecompressing) { | ||
229 | return lbz2_stream_perform_compress(L, stream, BZ_FLUSH); | ||
230 | } else { | ||
231 | /* Invalid for decompression */ | ||
232 | lua_pushnil(L); | ||
233 | lua_pushstring(L, lbz2_error(BZ_SEQUENCE_ERROR)); | ||
234 | return 2; | ||
235 | } | ||
236 | } | ||
237 | |||
238 | static luaL_Reg lbz2_stream_ops[] = { | ||
239 | { "update", lbz2_stream_update }, | ||
240 | { "flush", lbz2_stream_flush }, | ||
241 | { "close", lbz2_stream_close }, | ||
242 | { NULL, NULL } | ||
243 | }; | ||
244 | |||
245 | static luaL_Reg lbz2_stream_global[] = { | ||
246 | { "initCompress", lbz2_stream_initCompress }, | ||
247 | { "initDecompress", lbz2_stream_initDecompress }, | ||
248 | { NULL, NULL } | ||
249 | }; | ||
250 | |||
251 | void register_lbz2_stream(lua_State *L) { | ||
252 | luaL_newmetatable(L, LBZ2_STREAM_MT); | ||
253 | lua_newtable(L); | ||
254 | luaL_setfuncs(L, lbz2_stream_ops, 0); | ||
255 | lua_setfield(L, -2, "__index"); | ||
256 | |||
257 | lua_pushcfunction(L, lbz2_stream_close); | ||
258 | lua_setfield(L, -2, "__gc"); | ||
259 | lua_pop(L, 1); | ||
260 | |||
261 | luaL_setfuncs(L, lbz2_stream_global, 0); | ||
262 | } | ||
263 | |||
diff --git a/vendor/lua-bz2/lbz2_stream.h b/vendor/lua-bz2/lbz2_stream.h new file mode 100644 index 00000000..a321ea59 --- /dev/null +++ b/vendor/lua-bz2/lbz2_stream.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* This file implements the Lua binding to libbzip2. | ||
2 | * | ||
3 | * Copyright (c) 2008, Evan Klitzke <evan@eklitzke.org> | ||
4 | * Copyright (c) 2012, Thomas Harning Jr <harningt@gmail.com> | ||
5 | * | ||
6 | * Permission to use, copy, modify, and/or distribute this software for any | ||
7 | * purpose with or without fee is hereby granted, provided that the above | ||
8 | * copyright notice and this permission notice appear in all copies. | ||
9 | * | ||
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
17 | */ | ||
18 | |||
19 | |||
20 | #ifndef LBZ2_STREAM_H | ||
21 | #define LBZ2_STREAM_H | ||
22 | |||
23 | void register_lbz2_stream(lua_State *L); | ||
24 | |||
25 | #endif | ||
diff --git a/vendor/lua-bz2/lua-bz2-0.2.1-1.rockspec b/vendor/lua-bz2/lua-bz2-0.2.1-1.rockspec new file mode 100644 index 00000000..c66770f6 --- /dev/null +++ b/vendor/lua-bz2/lua-bz2-0.2.1-1.rockspec | |||
@@ -0,0 +1,48 @@ | |||
1 | package = "lua-bz2" | ||
2 | version = "0.2.1-1" | ||
3 | source = { | ||
4 | url = "git+ssh://git@github.com/hishamhm/lua-bz2.git", | ||
5 | tag = "0.2.1" | ||
6 | } | ||
7 | description = { | ||
8 | summary = "A Lua binding to Julian Seward's libbzip2", | ||
9 | detailed = [[ | ||
10 | Support for reading and writing .bz2 files | ||
11 | and handling streams compressed in bzip2 format. | ||
12 | ]], | ||
13 | homepage = "https://github.com/hishamhm/lua-bz2", | ||
14 | license = "ISC" | ||
15 | } | ||
16 | external_dependencies = { | ||
17 | BZ2 = { | ||
18 | library = "bz2" | ||
19 | } | ||
20 | } | ||
21 | build = { | ||
22 | type = "builtin", | ||
23 | modules = { | ||
24 | bz2 = { | ||
25 | defines = { | ||
26 | "COMPAT53_PREFIX=compat53" | ||
27 | }, | ||
28 | incdirs = { | ||
29 | "$(BZ2_INCDIR)" | ||
30 | }, | ||
31 | libdirs = { | ||
32 | "$(BZ2_LIBDIR)" | ||
33 | }, | ||
34 | libraries = { | ||
35 | "bz2" | ||
36 | }, | ||
37 | sources = { | ||
38 | "lbz.c", | ||
39 | "lbz2_common.c", | ||
40 | "lbz2_file_reader.c", | ||
41 | "lbz2_file_writer.c", | ||
42 | "lbz2_stream.c", | ||
43 | "compat-5.3.c" | ||
44 | } | ||
45 | }, | ||
46 | ["bz2.ltn12"] = "bz2/ltn12.lua" | ||
47 | } | ||
48 | } | ||
diff --git a/vendor/lua-zlib/.gitattributes b/vendor/lua-zlib/.gitattributes new file mode 100644 index 00000000..54be6288 --- /dev/null +++ b/vendor/lua-zlib/.gitattributes | |||
@@ -0,0 +1 @@ | |||
lua_zlib.c export-subst ident | |||
diff --git a/vendor/lua-zlib/README b/vendor/lua-zlib/README new file mode 100644 index 00000000..c438ee05 --- /dev/null +++ b/vendor/lua-zlib/README | |||
@@ -0,0 +1,163 @@ | |||
1 | ********************************************************************** | ||
2 | * Author : Brian Maher <maherb at brimworks dot com> | ||
3 | * Library : lua_zlib - Lua 5.1 interface to zlib | ||
4 | * | ||
5 | * The MIT License | ||
6 | * | ||
7 | * Copyright (c) 2009 Brian Maher | ||
8 | * | ||
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
10 | * of this software and associated documentation files (the "Software"), to deal | ||
11 | * in the Software without restriction, including without limitation the rights | ||
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
13 | * copies of the Software, and to permit persons to whom the Software is | ||
14 | * furnished to do so, subject to the following conditions: | ||
15 | * | ||
16 | * The above copyright notice and this permission notice shall be included in | ||
17 | * all copies or substantial portions of the Software. | ||
18 | * | ||
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
25 | * THE SOFTWARE. | ||
26 | ********************************************************************** | ||
27 | |||
28 | To use this library, you need zlib, get it here: | ||
29 | http://www.gzip.org/zlib/ | ||
30 | |||
31 | To build this library, you can use CMake and get it here: | ||
32 | http://www.cmake.org/cmake/resources/software.html | ||
33 | |||
34 | ...or you can use GNU Make. | ||
35 | make <platform> | ||
36 | |||
37 | Loading the library: | ||
38 | |||
39 | If you built the library as a loadable package | ||
40 | [local] zlib = require 'zlib' | ||
41 | |||
42 | If you compiled the package statically into your application, call | ||
43 | the function "luaopen_zlib(L)". It will create a table with the zlib | ||
44 | functions and leave it on the stack. | ||
45 | |||
46 | -- zlib functions -- | ||
47 | |||
48 | int major, int minor, int patch = zlib.version() | ||
49 | |||
50 | returns numeric zlib version for the major, minor, and patch | ||
51 | levels of the version dynamically linked in. | ||
52 | |||
53 | function stream = zlib.deflate([ int compression_level ], [ int window_size ]) | ||
54 | |||
55 | If no compression_level is provided uses Z_DEFAULT_COMPRESSION (6), | ||
56 | compression level is a number from 1-9 where zlib.BEST_SPEED is 1 | ||
57 | and zlib.BEST_COMPRESSION is 9. | ||
58 | |||
59 | Returns a "stream" function that compresses (or deflates) all | ||
60 | strings passed in. Specifically, use it as such: | ||
61 | |||
62 | string deflated, bool eof, int bytes_in, int bytes_out = | ||
63 | stream(string input [, 'sync' | 'full' | 'finish']) | ||
64 | |||
65 | Takes input and deflates and returns a portion of it, | ||
66 | optionally forcing a flush. | ||
67 | |||
68 | A 'sync' flush will force all pending output to be flushed to | ||
69 | the return value and the output is aligned on a byte boundary, | ||
70 | so that the decompressor can get all input data available so | ||
71 | far. Flushing may degrade compression for some compression | ||
72 | algorithms and so it should be used only when necessary. | ||
73 | |||
74 | A 'full' flush will flush all output as with 'sync', and the | ||
75 | compression state is reset so that decompression can restart | ||
76 | from this point if previous compressed data has been damaged | ||
77 | or if random access is desired. Using Z_FULL_FLUSH too often | ||
78 | can seriously degrade the compression. | ||
79 | |||
80 | A 'finish' flush will force all pending output to be processed | ||
81 | and results in the stream become unusable. Any future | ||
82 | attempts to print anything other than the empty string will | ||
83 | result in an error that begins with IllegalState. | ||
84 | |||
85 | The eof result is true if 'finish' was specified, otherwise | ||
86 | it is false. | ||
87 | |||
88 | The bytes_in is how many bytes of input have been passed to | ||
89 | stream, and bytes_out is the number of bytes returned in | ||
90 | deflated string chunks. | ||
91 | |||
92 | function stream = zlib.inflate([int windowBits]) | ||
93 | |||
94 | Returns a "stream" function that decompresses (or inflates) all | ||
95 | strings passed in. Optionally specify a windowBits argument | ||
96 | that is passed to inflateInit2(), see zlib.h for details about | ||
97 | this argument. By default, gzip header detection is done, and | ||
98 | the max window size is used. | ||
99 | |||
100 | The "stream" function should be used as such: | ||
101 | |||
102 | string inflated, bool eof, int bytes_in, int bytes_out = | ||
103 | stream(string input) | ||
104 | |||
105 | Takes input and inflates and returns a portion of it. If it | ||
106 | detects the end of a deflation stream, then total will be the | ||
107 | total number of bytes read from input and all future calls to | ||
108 | stream() with a non empty string will result in an error that | ||
109 | begins with IllegalState. | ||
110 | |||
111 | No flush options are provided since the maximal amount of | ||
112 | input is always processed. | ||
113 | |||
114 | eof will be true when the input string is determined to be at | ||
115 | the "end of the file". | ||
116 | |||
117 | The bytes_in is how many bytes of input have been passed to | ||
118 | stream, and bytes_out is the number of bytes returned in | ||
119 | inflated string chunks. | ||
120 | |||
121 | |||
122 | function compute_checksum = zlib.adler32() | ||
123 | function compute_checksum = zlib.crc32() | ||
124 | |||
125 | Create a new checksum computation function using either the | ||
126 | adler32 or crc32 algorithms. This resulting function should be | ||
127 | used as such: | ||
128 | |||
129 | int checksum = compute_checksum(string input | | ||
130 | function compute_checksum) | ||
131 | |||
132 | The compute_checksum function takes as input either a string | ||
133 | that is logically getting appended to or another | ||
134 | compute_checksum function that is logically getting appended. | ||
135 | The result is the updated checksum. | ||
136 | |||
137 | For example, these uses will all result in the same checksum: | ||
138 | |||
139 | -- All in one call: | ||
140 | local csum = zlib.crc32()("one two") | ||
141 | |||
142 | -- Multiple calls: | ||
143 | local compute = zlib.crc32() | ||
144 | compute("one") | ||
145 | assert(csum == compute(" two")) | ||
146 | |||
147 | -- Multiple compute_checksums joined: | ||
148 | local compute1, compute2 = zlib.crc32(), zlib.crc32() | ||
149 | compute1("one") | ||
150 | compute2(" two") | ||
151 | assert(csum == compute1(compute2)) | ||
152 | |||
153 | NOTE: This library ships with an "lzlib" compatibility shim. However, the | ||
154 | following things are not compatible: | ||
155 | |||
156 | * zlib.version() in lzlib returns a string, but this library returns a | ||
157 | numeric tuple (see above). | ||
158 | |||
159 | * zlib.{adler,crc}32() in lzlib returns the {adler,crc}32 initial value, | ||
160 | however if this value is used with calls to adler32 it works in | ||
161 | compatibility mode. | ||
162 | |||
163 | To use this shim add the -DLZLIB_COMPAT compiler flag. \ No newline at end of file | ||
diff --git a/vendor/lua-zlib/lua-zlib-1.1-0.rockspec b/vendor/lua-zlib/lua-zlib-1.1-0.rockspec new file mode 100644 index 00000000..7927d6ce --- /dev/null +++ b/vendor/lua-zlib/lua-zlib-1.1-0.rockspec | |||
@@ -0,0 +1,42 @@ | |||
1 | package = "lua-zlib" | ||
2 | version = "1.2-0" | ||
3 | source = { | ||
4 | url = "git://github.com/brimworks/lua-zlib.git", | ||
5 | tag = "v1.2", | ||
6 | } | ||
7 | description = { | ||
8 | summary = "Simple streaming interface to zlib for Lua.", | ||
9 | detailed = [[ | ||
10 | Simple streaming interface to zlib for Lua. | ||
11 | Consists of two functions: inflate and deflate. | ||
12 | Both functions return "stream functions" (takes a buffer of input and returns a buffer of output). | ||
13 | This project is hosted on github. | ||
14 | ]], | ||
15 | homepage = "https://github.com/brimworks/lua-zlib", | ||
16 | license = "MIT" | ||
17 | } | ||
18 | dependencies = { | ||
19 | "lua >= 5.1, <= 5.3" | ||
20 | } | ||
21 | external_dependencies = { | ||
22 | ZLIB = { | ||
23 | header = "zlib.h" | ||
24 | } | ||
25 | } | ||
26 | |||
27 | build = { | ||
28 | type = "builtin", | ||
29 | modules = { | ||
30 | zlib = { | ||
31 | sources = { "lua_zlib.c" }, | ||
32 | libraries = { "z" }, | ||
33 | defines = { "LZLIB_COMPAT" }, | ||
34 | incdirs = { "$(ZLIB_INCDIR)" }, | ||
35 | } | ||
36 | }, | ||
37 | platforms = { | ||
38 | windows = { modules = { zlib = { libraries = { | ||
39 | "$(ZLIB_LIBDIR)/zlib" -- Must full path to `"zlib"`, or else will cause the `LINK : fatal error LNK1149` | ||
40 | } } } } | ||
41 | } | ||
42 | } | ||
diff --git a/vendor/lua-zlib/lua_zlib.c b/vendor/lua-zlib/lua_zlib.c new file mode 100644 index 00000000..da57e91a --- /dev/null +++ b/vendor/lua-zlib/lua_zlib.c | |||
@@ -0,0 +1,1295 @@ | |||
1 | #include <ctype.h> | ||
2 | #include <lauxlib.h> | ||
3 | #include <lua.h> | ||
4 | #include <stdlib.h> | ||
5 | #include <string.h> | ||
6 | #include <zlib.h> | ||
7 | |||
8 | /* | ||
9 | * ** compatibility with Lua 5.2 | ||
10 | * */ | ||
11 | #if (LUA_VERSION_NUM >= 502) | ||
12 | #undef luaL_register | ||
13 | #define luaL_register(L,n,f) \ | ||
14 | { if ((n) == NULL) luaL_setfuncs(L,f,0); else luaL_newlib(L,f); } | ||
15 | |||
16 | #endif | ||
17 | |||
18 | #if (LUA_VERSION_NUM >= 503) | ||
19 | #undef luaL_optint | ||
20 | #define luaL_optint(L,n,d) ((int)luaL_optinteger(L,(n),(d))) | ||
21 | #endif | ||
22 | |||
23 | #ifdef LZLIB_COMPAT | ||
24 | /**************** lzlib compatibilty **********************************/ | ||
25 | /* Taken from https://raw.githubusercontent.com/LuaDist/lzlib/93b88e931ffa7cd0a52a972b6b26d37628f479f3/lzlib.c */ | ||
26 | |||
27 | /************************************************************************ | ||
28 | * Author : Tiago Dionizio <tiago.dionizio@gmail.com> * | ||
29 | * Library : lzlib - Lua 5 interface to access zlib library functions * | ||
30 | * * | ||
31 | * Permission is hereby granted, free of charge, to any person obtaining * | ||
32 | * a copy of this software and associated documentation files (the * | ||
33 | * "Software"), to deal in the Software without restriction, including * | ||
34 | * without limitation the rights to use, copy, modify, merge, publish, * | ||
35 | * distribute, sublicense, and/or sell copies of the Software, and to * | ||
36 | * permit persons to whom the Software is furnished to do so, subject to * | ||
37 | * the following conditions: * | ||
38 | * * | ||
39 | * The above copyright notice and this permission notice shall be * | ||
40 | * included in all copies or substantial portions of the Software. * | ||
41 | * * | ||
42 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * | ||
43 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * | ||
44 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.* | ||
45 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * | ||
46 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * | ||
47 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * | ||
48 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * | ||
49 | ************************************************************************/ | ||
50 | |||
51 | |||
52 | /* | ||
53 | ** ========================================================================= | ||
54 | ** compile time options wich determine available functionality | ||
55 | ** ========================================================================= | ||
56 | */ | ||
57 | |||
58 | /* TODO | ||
59 | |||
60 | - also call flush on table/userdata when flush function is detected | ||
61 | - remove io_cb check inflate_block if condition | ||
62 | - only set eos when ZSTREAM_END is reached | ||
63 | - check for stream errors to close stream when really needed | ||
64 | |||
65 | */ | ||
66 | |||
67 | |||
68 | /* | ||
69 | ** ========================================================================= | ||
70 | ** zlib stream metamethods | ||
71 | ** ========================================================================= | ||
72 | */ | ||
73 | #define ZSTREAMMETA "zlib:zstream" | ||
74 | |||
75 | #define LZ_ANY -1 | ||
76 | #define LZ_NONE 0 | ||
77 | #define LZ_DEFLATE 1 | ||
78 | #define LZ_INFLATE 2 | ||
79 | |||
80 | #if 0 | ||
81 | #define LZ_BUFFER_SIZE LUAL_BUFFERSIZE | ||
82 | #else | ||
83 | #define LZ_BUFFER_SIZE 8192 | ||
84 | #endif | ||
85 | |||
86 | typedef struct { | ||
87 | /* zlib structures */ | ||
88 | z_stream zstream; | ||
89 | /* stream state. LZ_DEFLATE | LZ_INFLATE */ | ||
90 | int state; | ||
91 | int error; | ||
92 | int peek; | ||
93 | int eos; | ||
94 | /* user callback source for reading/writing */ | ||
95 | int io_cb; | ||
96 | /* input buffer */ | ||
97 | int i_buffer_ref; | ||
98 | size_t i_buffer_pos; | ||
99 | size_t i_buffer_len; | ||
100 | const char *i_buffer; | ||
101 | /* output buffer */ | ||
102 | size_t o_buffer_len; | ||
103 | size_t o_buffer_max; | ||
104 | char o_buffer[LZ_BUFFER_SIZE]; | ||
105 | /* dictionary */ | ||
106 | const Bytef *dictionary; | ||
107 | size_t dictionary_len; | ||
108 | } lz_stream; | ||
109 | |||
110 | |||
111 | /* forward declarations */ | ||
112 | static int lzstream_docompress(lua_State *L, lz_stream *s, int from, int to, int flush); | ||
113 | |||
114 | |||
115 | static lz_stream *lzstream_new(lua_State *L, int src) { | ||
116 | lz_stream *s = (lz_stream*)lua_newuserdata(L, sizeof(lz_stream)); | ||
117 | |||
118 | luaL_getmetatable(L, ZSTREAMMETA); | ||
119 | lua_setmetatable(L, -2); /* set metatable */ | ||
120 | |||
121 | s->state = LZ_NONE; | ||
122 | s->error = Z_OK; | ||
123 | s->eos = 0; | ||
124 | s->io_cb = LUA_REFNIL; | ||
125 | |||
126 | s->i_buffer = NULL; | ||
127 | s->i_buffer_ref = LUA_REFNIL; | ||
128 | s->i_buffer_pos = 0; | ||
129 | s->i_buffer_len = 0; | ||
130 | |||
131 | s->peek = 0; | ||
132 | s->o_buffer_len = 0; | ||
133 | s->o_buffer_max = sizeof(s->o_buffer) / sizeof(s->o_buffer[0]); | ||
134 | |||
135 | s->zstream.zalloc = Z_NULL; | ||
136 | s->zstream.zfree = Z_NULL; | ||
137 | |||
138 | /* prepare source */ | ||
139 | if (lua_isstring(L, src)) { | ||
140 | lua_pushvalue(L, src); | ||
141 | s->i_buffer_ref = luaL_ref(L, LUA_REGISTRYINDEX); | ||
142 | s->i_buffer = lua_tolstring(L, src, &s->i_buffer_len); | ||
143 | } else { | ||
144 | /* table | function | userdata */ | ||
145 | lua_pushvalue(L, src); | ||
146 | s->io_cb = luaL_ref(L, LUA_REGISTRYINDEX); | ||
147 | } | ||
148 | return s; | ||
149 | } | ||
150 | |||
151 | static void lzstream_cleanup(lua_State *L, lz_stream *s) { | ||
152 | if (s && s->state != LZ_NONE) { | ||
153 | if (s->state == LZ_INFLATE) { | ||
154 | inflateEnd(&s->zstream); | ||
155 | } | ||
156 | if (s->state == LZ_DEFLATE) { | ||
157 | deflateEnd(&s->zstream); | ||
158 | } | ||
159 | |||
160 | luaL_unref(L, LUA_REGISTRYINDEX, s->io_cb); | ||
161 | luaL_unref(L, LUA_REGISTRYINDEX, s->i_buffer_ref); | ||
162 | s->state = LZ_NONE; | ||
163 | } | ||
164 | } | ||
165 | |||
166 | /* ====================================================================== */ | ||
167 | |||
168 | static lz_stream *lzstream_get(lua_State *L, int index) { | ||
169 | lz_stream *s = (lz_stream*)luaL_checkudata(L, index, ZSTREAMMETA); | ||
170 | if (s == NULL) luaL_argerror(L, index, "bad zlib stream"); | ||
171 | return s; | ||
172 | } | ||
173 | |||
174 | static lz_stream *lzstream_check(lua_State *L, int index, int state) { | ||
175 | lz_stream *s = lzstream_get(L, index); | ||
176 | if ((state != LZ_ANY && s->state != state) || s->state == LZ_NONE) { | ||
177 | luaL_argerror(L, index, "attempt to use invalid zlib stream"); | ||
178 | } | ||
179 | return s; | ||
180 | } | ||
181 | |||
182 | /* ====================================================================== */ | ||
183 | |||
184 | static int lzstream_tostring(lua_State *L) { | ||
185 | lz_stream *s = (lz_stream*)luaL_checkudata(L, 1, ZSTREAMMETA); | ||
186 | if (s == NULL) luaL_argerror(L, 1, "bad zlib stream"); | ||
187 | |||
188 | if (s->state == LZ_NONE) { | ||
189 | lua_pushstring(L, "zlib stream (closed)"); | ||
190 | } else if (s->state == LZ_DEFLATE) { | ||
191 | lua_pushfstring(L, "zlib deflate stream (%p)", (void*)s); | ||
192 | } else if (s->state == LZ_INFLATE) { | ||
193 | lua_pushfstring(L, "zlib inflate stream (%p)", (void*)s); | ||
194 | } else { | ||
195 | lua_pushfstring(L, "%p", (void*)s); | ||
196 | } | ||
197 | |||
198 | return 1; | ||
199 | } | ||
200 | |||
201 | /* ====================================================================== */ | ||
202 | |||
203 | static int lzstream_gc(lua_State *L) { | ||
204 | lz_stream *s = lzstream_get(L, 1); | ||
205 | lzstream_cleanup(L, s); | ||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | /* ====================================================================== */ | ||
210 | |||
211 | static int lzstream_close(lua_State *L) { | ||
212 | lz_stream *s = lzstream_get(L, 1); | ||
213 | |||
214 | if (s->state == LZ_DEFLATE) { | ||
215 | lua_settop(L, 0); | ||
216 | lua_pushliteral(L, ""); | ||
217 | return lzstream_docompress(L, s, 1, 1, Z_FINISH); | ||
218 | } | ||
219 | |||
220 | lzstream_cleanup(L, s); | ||
221 | lua_pushboolean(L, 1); | ||
222 | return 1; | ||
223 | } | ||
224 | |||
225 | /* ====================================================================== */ | ||
226 | |||
227 | static int lzstream_adler(lua_State *L) { | ||
228 | lz_stream *s = lzstream_check(L, 1, LZ_ANY); | ||
229 | lua_pushnumber(L, s->zstream.adler); | ||
230 | return 1; | ||
231 | } | ||
232 | |||
233 | /* ====================================================================== */ | ||
234 | |||
235 | /* | ||
236 | zlib.deflate( | ||
237 | sink: function | { write: function [, close: function, flush: function] }, | ||
238 | compression level, [Z_DEFAILT_COMPRESSION] | ||
239 | method, [Z_DEFLATED] | ||
240 | windowBits, [15] | ||
241 | memLevel, [8] | ||
242 | strategy, [Z_DEFAULT_STRATEGY] | ||
243 | dictionary: [""] | ||
244 | ) | ||
245 | */ | ||
246 | static int lzlib_deflate(lua_State *L) { | ||
247 | int level, method, windowBits, memLevel, strategy; | ||
248 | lz_stream *s; | ||
249 | const char *dictionary; | ||
250 | size_t dictionary_len; | ||
251 | |||
252 | if (lua_istable(L, 1) || lua_isuserdata(L, 1)) { | ||
253 | /* is there a :write function? */ | ||
254 | lua_getfield(L, 1, "write"); | ||
255 | if (!lua_isfunction(L, -1)) { | ||
256 | luaL_argerror(L, 1, "output parameter does not provide :write function"); | ||
257 | } | ||
258 | lua_pop(L, 1); | ||
259 | } | ||
260 | else if (!lua_isfunction(L, 1)) { | ||
261 | luaL_argerror(L, 1, "output parameter must be a function, table or userdata value"); | ||
262 | } | ||
263 | |||
264 | level = (int) luaL_optinteger(L, 2, Z_DEFAULT_COMPRESSION); | ||
265 | method = (int) luaL_optinteger(L, 3, Z_DEFLATED); | ||
266 | windowBits = (int) luaL_optinteger(L, 4, 15); | ||
267 | memLevel = (int) luaL_optinteger(L, 5, 8); | ||
268 | strategy = (int) luaL_optinteger(L, 6, Z_DEFAULT_STRATEGY); | ||
269 | dictionary = luaL_optlstring(L, 7, NULL, &dictionary_len); | ||
270 | |||
271 | s = lzstream_new(L, 1); | ||
272 | |||
273 | if (deflateInit2(&s->zstream, level, method, windowBits, memLevel, strategy) != Z_OK) { | ||
274 | lua_pushliteral(L, "call to deflateInit2 failed"); | ||
275 | lua_error(L); | ||
276 | } | ||
277 | |||
278 | if (dictionary) { | ||
279 | if (deflateSetDictionary(&s->zstream, (const Bytef *) dictionary, dictionary_len) != Z_OK) { | ||
280 | lua_pushliteral(L, "call to deflateSetDictionnary failed"); | ||
281 | lua_error(L); | ||
282 | } | ||
283 | } | ||
284 | |||
285 | s->state = LZ_DEFLATE; | ||
286 | return 1; | ||
287 | } | ||
288 | |||
289 | /* | ||
290 | zlib.inflate( | ||
291 | source: string | function | { read: function, close: function }, | ||
292 | windowBits: number, [15] | ||
293 | dictionary: [""] | ||
294 | ) | ||
295 | */ | ||
296 | static int lzlib_inflate(lua_State *L) | ||
297 | { | ||
298 | int windowBits; | ||
299 | lz_stream *s; | ||
300 | int have_peek = 0; | ||
301 | const char *dictionary; | ||
302 | size_t dictionary_len; | ||
303 | |||
304 | if (lua_istable(L, 1) || lua_isuserdata(L, 1)) { | ||
305 | /* is there a :read function? */ | ||
306 | lua_getfield(L, 1, "read"); | ||
307 | if (!lua_isfunction(L, -1)) { | ||
308 | luaL_argerror(L, 1, "input parameter does not provide :read function"); | ||
309 | } | ||
310 | lua_pop(L, 1); | ||
311 | /* check for peek function */ | ||
312 | lua_getfield(L, 1, "peek"); | ||
313 | have_peek = lua_isfunction(L, -1); | ||
314 | lua_pop(L, 1); | ||
315 | } | ||
316 | else if (!lua_isstring(L, 1) && !lua_isfunction(L, 1)) { | ||
317 | luaL_argerror(L, 1, "input parameter must be a string, function, table or userdata value"); | ||
318 | } | ||
319 | |||
320 | windowBits = (int) luaL_optinteger(L, 2, 15); | ||
321 | dictionary = luaL_optlstring(L, 3, NULL, &dictionary_len); | ||
322 | |||
323 | s = lzstream_new(L, 1); | ||
324 | |||
325 | if (windowBits > 0 && windowBits < 16) { | ||
326 | windowBits |= 32; | ||
327 | } | ||
328 | |||
329 | if (inflateInit2(&s->zstream, windowBits) != Z_OK) { | ||
330 | lua_pushliteral(L, "call to inflateInit2 failed"); | ||
331 | lua_error(L); | ||
332 | } | ||
333 | |||
334 | if (dictionary) { | ||
335 | s->dictionary = (const Bytef *) dictionary; | ||
336 | s->dictionary_len = dictionary_len; | ||
337 | } | ||
338 | |||
339 | s->peek = have_peek; | ||
340 | s->state = LZ_INFLATE; | ||
341 | return 1; | ||
342 | } | ||
343 | |||
344 | /* ====================================================================== */ | ||
345 | |||
346 | static int lz_pushresult (lua_State *L, lz_stream *s) { | ||
347 | if (s->error == Z_OK) { | ||
348 | lua_pushboolean(L, 1); | ||
349 | return 1; | ||
350 | } else { | ||
351 | lua_pushnil(L); | ||
352 | lua_pushstring(L, zError(s->error)); | ||
353 | lua_pushinteger(L, s->error); | ||
354 | return 3; | ||
355 | } | ||
356 | } | ||
357 | |||
358 | /* | ||
359 | Get block to process: | ||
360 | - top of stack gets | ||
361 | */ | ||
362 | static const char* lzstream_fetch_block(lua_State *L, lz_stream *s, int hint) { | ||
363 | if (s->i_buffer_pos >= s->i_buffer_len) { | ||
364 | luaL_unref(L, LUA_REGISTRYINDEX, s->i_buffer_ref); | ||
365 | s->i_buffer_ref = LUA_NOREF; | ||
366 | s->i_buffer = NULL; | ||
367 | |||
368 | lua_rawgeti(L, LUA_REGISTRYINDEX, s->io_cb); | ||
369 | if (!lua_isnil(L, -1)) { | ||
370 | if (lua_isfunction(L, -1)) { | ||
371 | lua_pushinteger(L, hint); | ||
372 | lua_call(L, 1, 1); | ||
373 | } else { | ||
374 | lua_getfield(L, -1, (s->peek ? "peek" : "read")); | ||
375 | lua_insert(L, -2); | ||
376 | lua_pushinteger(L, hint); | ||
377 | lua_call(L, 2, 1); | ||
378 | } | ||
379 | |||
380 | if (lua_isstring(L, -1)) { | ||
381 | s->i_buffer_pos = 0; | ||
382 | s->i_buffer = lua_tolstring(L, -1, &s->i_buffer_len); | ||
383 | if (s->i_buffer_len > 0) { | ||
384 | s->i_buffer_ref = luaL_ref(L, LUA_REGISTRYINDEX); | ||
385 | } else { | ||
386 | lua_pop(L, 1); | ||
387 | } | ||
388 | } else if (lua_isnil(L, -1)) { | ||
389 | lua_pop(L, 1); | ||
390 | } else { | ||
391 | lua_pushliteral(L, "deflate callback must return string or nil"); | ||
392 | lua_error(L); | ||
393 | } | ||
394 | } else { | ||
395 | lua_pop(L, 1); | ||
396 | } | ||
397 | } | ||
398 | |||
399 | return s->i_buffer; | ||
400 | } | ||
401 | |||
402 | static int lzstream_inflate_block(lua_State *L, lz_stream *s) { | ||
403 | if (lzstream_fetch_block(L, s, LZ_BUFFER_SIZE) || !s->eos) { | ||
404 | int r; | ||
405 | |||
406 | if (s->i_buffer_len == s->i_buffer_pos) { | ||
407 | s->zstream.next_in = NULL; | ||
408 | s->zstream.avail_in = 0; | ||
409 | } else { | ||
410 | s->zstream.next_in = (unsigned char*)(s->i_buffer + s->i_buffer_pos); | ||
411 | s->zstream.avail_in = s->i_buffer_len - s->i_buffer_pos; | ||
412 | } | ||
413 | |||
414 | s->zstream.next_out = (unsigned char*)s->o_buffer + s->o_buffer_len; | ||
415 | s->zstream.avail_out = s->o_buffer_max - s->o_buffer_len; | ||
416 | |||
417 | /* munch some more */ | ||
418 | r = inflate(&s->zstream, Z_SYNC_FLUSH); | ||
419 | |||
420 | if (r == Z_NEED_DICT) { | ||
421 | if (s->dictionary == NULL) { | ||
422 | lua_pushliteral(L, "no inflate dictionary provided"); | ||
423 | lua_error(L); | ||
424 | } | ||
425 | |||
426 | if (inflateSetDictionary(&s->zstream, s->dictionary, s->dictionary_len) != Z_OK) { | ||
427 | lua_pushliteral(L, "call to inflateSetDictionnary failed"); | ||
428 | lua_error(L); | ||
429 | } | ||
430 | |||
431 | r = inflate(&s->zstream, Z_SYNC_FLUSH); | ||
432 | } | ||
433 | |||
434 | if (r != Z_OK && r != Z_STREAM_END && r != Z_BUF_ERROR) { | ||
435 | lzstream_cleanup(L, s); | ||
436 | s->error = r; | ||
437 | #if 1 | ||
438 | lua_pushfstring(L, "failed to decompress [%d]", r); | ||
439 | lua_error(L); | ||
440 | #endif | ||
441 | } | ||
442 | |||
443 | if (r == Z_STREAM_END) { | ||
444 | luaL_unref(L, LUA_REGISTRYINDEX, s->i_buffer_ref); | ||
445 | s->i_buffer_ref = LUA_NOREF; | ||
446 | s->i_buffer = NULL; | ||
447 | |||
448 | s->eos = 1; | ||
449 | } | ||
450 | |||
451 | /* number of processed bytes */ | ||
452 | if (s->peek) { | ||
453 | size_t processed = s->i_buffer_len - s->i_buffer_pos - s->zstream.avail_in; | ||
454 | |||
455 | lua_rawgeti(L, LUA_REGISTRYINDEX, s->io_cb); | ||
456 | lua_getfield(L, -1, "read"); | ||
457 | lua_insert(L, -2); | ||
458 | lua_pushinteger(L, processed); | ||
459 | lua_call(L, 2, 0); | ||
460 | } | ||
461 | |||
462 | s->i_buffer_pos = s->i_buffer_len - s->zstream.avail_in; | ||
463 | s->o_buffer_len = s->o_buffer_max - s->zstream.avail_out; | ||
464 | } | ||
465 | |||
466 | return s->o_buffer_len; | ||
467 | } | ||
468 | |||
469 | /* | ||
470 | ** Remove n bytes from the output buffer. | ||
471 | */ | ||
472 | static void lzstream_remove(lz_stream *s, size_t n) { | ||
473 | memmove(s->o_buffer, s->o_buffer + n, s->o_buffer_len - n); | ||
474 | s->o_buffer_len -= n; | ||
475 | } | ||
476 | |||
477 | /* | ||
478 | ** Copy at most n bytes to buffer b and remove them from the | ||
479 | ** output stream buffer. | ||
480 | */ | ||
481 | static int lzstream_flush_buffer(lua_State *L, lz_stream *s, size_t n, luaL_Buffer *b) { | ||
482 | /* check output */ | ||
483 | if (n > s->o_buffer_len) { | ||
484 | n = s->o_buffer_len; | ||
485 | } | ||
486 | |||
487 | if (n > 0) { | ||
488 | lua_pushlstring(L, s->o_buffer, n); | ||
489 | luaL_addvalue(b); | ||
490 | |||
491 | lzstream_remove(s, n); | ||
492 | } | ||
493 | |||
494 | return n; | ||
495 | } | ||
496 | |||
497 | /* | ||
498 | z:read( | ||
499 | {number | '*l' | '*a'}* | ||
500 | ) | ||
501 | */ | ||
502 | static int lz_test_eof(lua_State *L, lz_stream *s) { | ||
503 | lua_pushlstring(L, NULL, 0); | ||
504 | if (s->o_buffer_len > 0) { | ||
505 | return 1; | ||
506 | } else if (s->eos) { | ||
507 | return 0; | ||
508 | } else { | ||
509 | return lzstream_inflate_block(L, s); | ||
510 | } | ||
511 | } | ||
512 | |||
513 | static int lz_read_line(lua_State *L, lz_stream *s) { | ||
514 | luaL_Buffer b; | ||
515 | size_t l = 0, n; | ||
516 | |||
517 | luaL_buffinit(L, &b); | ||
518 | |||
519 | if (s->o_buffer_len > 0 || !s->eos) do { | ||
520 | char *p = s->o_buffer; | ||
521 | size_t len = s->o_buffer_len; | ||
522 | |||
523 | /* find newline in output buffer */ | ||
524 | for (n = 0; n < len; ++n, ++p) { | ||
525 | if (*p == '\n' || *p == '\r') { | ||
526 | int eat_nl = *p == '\r'; | ||
527 | luaL_addlstring(&b, s->o_buffer, n); | ||
528 | lzstream_remove(s, n+1); | ||
529 | l += n; | ||
530 | |||
531 | if (eat_nl && lzstream_inflate_block(L, s)) { | ||
532 | if (s->o_buffer_len > 0 && *s->o_buffer == '\n') { | ||
533 | lzstream_remove(s, 1); | ||
534 | } | ||
535 | } | ||
536 | |||
537 | luaL_pushresult(&b); | ||
538 | return 1; | ||
539 | } | ||
540 | } | ||
541 | |||
542 | if (len > 0) { | ||
543 | luaL_addlstring(&b, s->o_buffer, len); | ||
544 | lzstream_remove(s, len); | ||
545 | l += len; | ||
546 | } | ||
547 | } while (lzstream_inflate_block(L, s)); | ||
548 | |||
549 | luaL_pushresult(&b); | ||
550 | return l > 0 || !s->eos || s->o_buffer_len > 0; | ||
551 | } | ||
552 | |||
553 | |||
554 | static int lz_read_chars(lua_State *L, lz_stream *s, size_t n) { | ||
555 | size_t len; | ||
556 | luaL_Buffer b; | ||
557 | luaL_buffinit(L, &b); | ||
558 | |||
559 | if (s->o_buffer_len > 0 || !s->eos) do { | ||
560 | size_t rlen = lzstream_flush_buffer(L, s, n, &b); | ||
561 | n -= rlen; | ||
562 | } while (n > 0 && lzstream_inflate_block(L, s)); | ||
563 | |||
564 | luaL_pushresult(&b); | ||
565 | lua_tolstring(L, -1, &len); | ||
566 | return n == 0 || len > 0; | ||
567 | } | ||
568 | |||
569 | static int lzstream_decompress(lua_State *L) { | ||
570 | lz_stream *s = lzstream_check(L, 1, LZ_INFLATE); | ||
571 | int nargs = lua_gettop(L) - 1; | ||
572 | int success; | ||
573 | int n; | ||
574 | if (nargs == 0) { /* no arguments? */ | ||
575 | success = lz_read_line(L, s); | ||
576 | n = 3; /* to return 1 result */ | ||
577 | } | ||
578 | else { /* ensure stack space for all results and for auxlib's buffer */ | ||
579 | luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); | ||
580 | success = 1; | ||
581 | for (n = 2; nargs-- && success; n++) { | ||
582 | if (lua_type(L, n) == LUA_TNUMBER) { | ||
583 | size_t l = (size_t)lua_tointeger(L, n); | ||
584 | success = (l == 0) ? lz_test_eof(L, s) : lz_read_chars(L, s, l); | ||
585 | } | ||
586 | else { | ||
587 | const char *p = lua_tostring(L, n); | ||
588 | luaL_argcheck(L, p && p[0] == '*', n, "invalid option"); | ||
589 | switch (p[1]) { | ||
590 | case 'l': /* line */ | ||
591 | success = lz_read_line(L, s); | ||
592 | break; | ||
593 | case 'a': /* file */ | ||
594 | lz_read_chars(L, s, ~((size_t)0)); /* read MAX_SIZE_T chars */ | ||
595 | success = 1; /* always success */ | ||
596 | break; | ||
597 | default: | ||
598 | return luaL_argerror(L, n, "invalid format"); | ||
599 | } | ||
600 | } | ||
601 | } | ||
602 | } | ||
603 | if (s->error != Z_OK) { | ||
604 | return lz_pushresult(L, s); | ||
605 | } | ||
606 | if (!success) { | ||
607 | lua_pop(L, 1); /* remove last result */ | ||
608 | lua_pushnil(L); /* push nil instead */ | ||
609 | } | ||
610 | return n - 2; | ||
611 | } | ||
612 | |||
613 | |||
614 | static int lzstream_readline(lua_State *L) { | ||
615 | lz_stream *s; | ||
616 | int sucess; | ||
617 | |||
618 | s = lzstream_check(L, lua_upvalueindex(1), LZ_INFLATE); | ||
619 | sucess = lz_read_line(L, s); | ||
620 | |||
621 | if (s->error != Z_OK) { | ||
622 | return lz_pushresult(L, s); | ||
623 | } | ||
624 | |||
625 | if (sucess) { | ||
626 | return 1; | ||
627 | } else { | ||
628 | /* EOF */ | ||
629 | return 0; | ||
630 | } | ||
631 | } | ||
632 | |||
633 | static int lzstream_lines(lua_State *L) { | ||
634 | lzstream_check(L, 1, LZ_INFLATE); | ||
635 | lua_settop(L, 1); | ||
636 | lua_pushcclosure(L, lzstream_readline, 1); | ||
637 | return 1; | ||
638 | } | ||
639 | |||
640 | /* ====================================================================== */ | ||
641 | |||
642 | static int lzstream_docompress(lua_State *L, lz_stream *s, int from, int to, int flush) { | ||
643 | int r, arg; | ||
644 | int self = 0; | ||
645 | size_t b_size = s->o_buffer_max; | ||
646 | unsigned char *b = (unsigned char *)s->o_buffer; | ||
647 | |||
648 | /* number of processed bytes */ | ||
649 | lua_rawgeti(L, LUA_REGISTRYINDEX, s->io_cb); | ||
650 | if (!lua_isfunction(L, -1)) { | ||
651 | self = 1; | ||
652 | lua_getfield(L, -1, "write"); | ||
653 | } | ||
654 | |||
655 | for (arg = from; arg <= to; arg++) { | ||
656 | s->zstream.next_in = (unsigned char*)luaL_checklstring(L, arg, (size_t*)&s->zstream.avail_in); | ||
657 | |||
658 | do { | ||
659 | s->zstream.next_out = b; | ||
660 | s->zstream.avail_out = b_size; | ||
661 | |||
662 | /* bake some more */ | ||
663 | r = deflate(&s->zstream, flush); | ||
664 | if (r != Z_OK && r != Z_STREAM_END && r != Z_BUF_ERROR) { | ||
665 | lzstream_cleanup(L, s); | ||
666 | lua_pushboolean(L, 0); | ||
667 | lua_pushfstring(L, "failed to compress [%d]", r); | ||
668 | return 2; | ||
669 | } | ||
670 | |||
671 | if (s->zstream.avail_out != b_size) { | ||
672 | /* write output */ | ||
673 | lua_pushvalue(L, -1); /* function */ | ||
674 | if (self) lua_pushvalue(L, -3); /* self */ | ||
675 | lua_pushlstring(L, (char*)b, b_size - s->zstream.avail_out); /* data */ | ||
676 | lua_call(L, (self ? 2 : 1), 0); | ||
677 | } | ||
678 | |||
679 | if (r == Z_STREAM_END) { | ||
680 | lzstream_cleanup(L, s); | ||
681 | break; | ||
682 | } | ||
683 | |||
684 | /* process all input */ | ||
685 | } while (s->zstream.avail_in > 0 || s->zstream.avail_out == 0); | ||
686 | } | ||
687 | |||
688 | lua_pushboolean(L, 1); | ||
689 | return 1; | ||
690 | } | ||
691 | |||
692 | static int lzstream_compress(lua_State *L) { | ||
693 | lz_stream *s = lzstream_check(L, 1, LZ_DEFLATE); | ||
694 | return lzstream_docompress(L, s, 2, lua_gettop(L), Z_NO_FLUSH); | ||
695 | } | ||
696 | |||
697 | |||
698 | /* ====================================================================== */ | ||
699 | |||
700 | static int lzstream_flush(lua_State *L) { | ||
701 | static int flush_values[] = { Z_SYNC_FLUSH, Z_FULL_FLUSH, Z_FINISH }; | ||
702 | static const char *const flush_opts[] = { "sync", "full", "finish" }; | ||
703 | |||
704 | lz_stream *s = lzstream_check(L, 1, LZ_DEFLATE); | ||
705 | int flush = luaL_checkoption(L, 2, flush_opts[0], flush_opts); | ||
706 | |||
707 | lua_settop(L, 0); | ||
708 | lua_pushliteral(L, ""); | ||
709 | return lzstream_docompress(L, s, 1, 1, flush_values[flush]); | ||
710 | } | ||
711 | |||
712 | /* ====================================================================== */ | ||
713 | |||
714 | static int lzlib_compress(lua_State *L) { | ||
715 | size_t avail_in; | ||
716 | const char *next_in = luaL_checklstring(L, 1, &avail_in); | ||
717 | int level = (int) luaL_optinteger(L, 2, Z_DEFAULT_COMPRESSION); | ||
718 | int method = (int) luaL_optinteger(L, 3, Z_DEFLATED); | ||
719 | int windowBits = (int) luaL_optinteger(L, 4, 15); | ||
720 | int memLevel = (int) luaL_optinteger(L, 5, 8); | ||
721 | int strategy = (int) luaL_optinteger(L, 6, Z_DEFAULT_STRATEGY); | ||
722 | |||
723 | int ret; | ||
724 | luaL_Buffer b; | ||
725 | z_stream zs; | ||
726 | |||
727 | luaL_buffinit(L, &b); | ||
728 | |||
729 | zs.zalloc = Z_NULL; | ||
730 | zs.zfree = Z_NULL; | ||
731 | |||
732 | zs.next_out = Z_NULL; | ||
733 | zs.avail_out = 0; | ||
734 | zs.next_in = Z_NULL; | ||
735 | zs.avail_in = 0; | ||
736 | |||
737 | ret = deflateInit2(&zs, level, method, windowBits, memLevel, strategy); | ||
738 | |||
739 | if (ret != Z_OK) | ||
740 | { | ||
741 | lua_pushnil(L); | ||
742 | lua_pushnumber(L, ret); | ||
743 | return 2; | ||
744 | } | ||
745 | |||
746 | zs.next_in = (unsigned char*)next_in; | ||
747 | zs.avail_in = avail_in; | ||
748 | |||
749 | for(;;) | ||
750 | { | ||
751 | zs.next_out = (unsigned char*)luaL_prepbuffer(&b); | ||
752 | zs.avail_out = LUAL_BUFFERSIZE; | ||
753 | |||
754 | /* munch some more */ | ||
755 | ret = deflate(&zs, Z_FINISH); | ||
756 | |||
757 | /* push gathered data */ | ||
758 | luaL_addsize(&b, LUAL_BUFFERSIZE - zs.avail_out); | ||
759 | |||
760 | /* done processing? */ | ||
761 | if (ret == Z_STREAM_END) | ||
762 | break; | ||
763 | |||
764 | /* error condition? */ | ||
765 | if (ret != Z_OK) | ||
766 | break; | ||
767 | } | ||
768 | |||
769 | /* cleanup */ | ||
770 | deflateEnd(&zs); | ||
771 | |||
772 | luaL_pushresult(&b); | ||
773 | lua_pushnumber(L, ret); | ||
774 | return 2; | ||
775 | } | ||
776 | |||
777 | /* ====================================================================== */ | ||
778 | |||
779 | static int lzlib_decompress(lua_State *L) | ||
780 | { | ||
781 | size_t avail_in; | ||
782 | const char *next_in = luaL_checklstring(L, 1, &avail_in); | ||
783 | int windowBits = (int) luaL_optinteger(L, 2, 15); | ||
784 | |||
785 | int ret; | ||
786 | luaL_Buffer b; | ||
787 | z_stream zs; | ||
788 | |||
789 | luaL_buffinit(L, &b); | ||
790 | |||
791 | zs.zalloc = Z_NULL; | ||
792 | zs.zfree = Z_NULL; | ||
793 | |||
794 | zs.next_out = Z_NULL; | ||
795 | zs.avail_out = 0; | ||
796 | zs.next_in = Z_NULL; | ||
797 | zs.avail_in = 0; | ||
798 | |||
799 | ret = inflateInit2(&zs, windowBits); | ||
800 | |||
801 | if (ret != Z_OK) { | ||
802 | lua_pushliteral(L, "failed to initialize zstream structures"); | ||
803 | lua_error(L); | ||
804 | } | ||
805 | |||
806 | zs.next_in = (unsigned char*)next_in; | ||
807 | zs.avail_in = avail_in; | ||
808 | |||
809 | for (;;) { | ||
810 | zs.next_out = (unsigned char*)luaL_prepbuffer(&b); | ||
811 | zs.avail_out = LUAL_BUFFERSIZE; | ||
812 | |||
813 | /* bake some more */ | ||
814 | ret = inflate(&zs, Z_FINISH); | ||
815 | |||
816 | /* push gathered data */ | ||
817 | luaL_addsize(&b, LUAL_BUFFERSIZE - zs.avail_out); | ||
818 | |||
819 | /* done processing? */ | ||
820 | if (ret == Z_STREAM_END) | ||
821 | break; | ||
822 | |||
823 | if (ret != Z_OK && ret != Z_BUF_ERROR) { | ||
824 | /* cleanup */ | ||
825 | inflateEnd(&zs); | ||
826 | |||
827 | lua_pushliteral(L, "failed to process zlib stream"); | ||
828 | lua_error(L); | ||
829 | } | ||
830 | } | ||
831 | |||
832 | /* cleanup */ | ||
833 | inflateEnd(&zs); | ||
834 | |||
835 | luaL_pushresult(&b); | ||
836 | return 1; | ||
837 | } | ||
838 | |||
839 | #endif | ||
840 | /**********************************************************************/ | ||
841 | |||
842 | #define DEF_MEM_LEVEL 8 | ||
843 | |||
844 | typedef uLong (*checksum_t) (uLong crc, const Bytef *buf, uInt len); | ||
845 | typedef uLong (*checksum_combine_t)(uLong crc1, uLong crc2, z_off_t len2); | ||
846 | |||
847 | |||
848 | static int lz_deflate(lua_State *L); | ||
849 | static int lz_deflate_delete(lua_State *L); | ||
850 | static int lz_inflate_delete(lua_State *L); | ||
851 | static int lz_inflate(lua_State *L); | ||
852 | static int lz_checksum(lua_State *L); | ||
853 | static int lz_checksum_new(lua_State *L, checksum_t checksum, checksum_combine_t combine); | ||
854 | static int lz_adler32(lua_State *L); | ||
855 | static int lz_crc32(lua_State *L); | ||
856 | |||
857 | static int lz_version(lua_State *L) { | ||
858 | const char* version = zlibVersion(); | ||
859 | int count = strlen(version) + 1; | ||
860 | char* cur = (char*)memcpy(lua_newuserdata(L, count), | ||
861 | version, count); | ||
862 | |||
863 | count = 0; | ||
864 | while ( *cur ) { | ||
865 | char* begin = cur; | ||
866 | /* Find all digits: */ | ||
867 | while ( isdigit(*cur) ) cur++; | ||
868 | if ( begin != cur ) { | ||
869 | int is_end = *cur == '\0'; | ||
870 | *cur = '\0'; | ||
871 | lua_pushnumber(L, atoi(begin)); | ||
872 | count++; | ||
873 | if ( is_end ) break; | ||
874 | cur++; | ||
875 | } | ||
876 | while ( *cur && ! isdigit(*cur) ) cur++; | ||
877 | } | ||
878 | |||
879 | return count; | ||
880 | } | ||
881 | |||
882 | static int lz_assert(lua_State *L, int result, const z_stream* stream, const char* file, int line) { | ||
883 | /* Both of these are "normal" return codes: */ | ||
884 | if ( result == Z_OK || result == Z_STREAM_END ) return result; | ||
885 | switch ( result ) { | ||
886 | case Z_NEED_DICT: | ||
887 | lua_pushfstring(L, "RequiresDictionary: input stream requires a dictionary to be deflated (%s) at %s line %d", | ||
888 | stream->msg, file, line); | ||
889 | break; | ||
890 | case Z_STREAM_ERROR: | ||
891 | lua_pushfstring(L, "InternalError: inconsistent internal zlib stream (%s) at %s line %d", | ||
892 | stream->msg, file, line); | ||
893 | break; | ||
894 | case Z_DATA_ERROR: | ||
895 | lua_pushfstring(L, "InvalidInput: input string does not conform to zlib format or checksum failed at %s line %d", | ||
896 | file, line); | ||
897 | break; | ||
898 | case Z_MEM_ERROR: | ||
899 | lua_pushfstring(L, "OutOfMemory: not enough memory (%s) at %s line %d", | ||
900 | stream->msg, file, line); | ||
901 | break; | ||
902 | case Z_BUF_ERROR: | ||
903 | lua_pushfstring(L, "InternalError: no progress possible (%s) at %s line %d", | ||
904 | stream->msg, file, line); | ||
905 | break; | ||
906 | case Z_VERSION_ERROR: | ||
907 | lua_pushfstring(L, "IncompatibleLibrary: built with version %s, but dynamically linked with version %s (%s) at %s line %d", | ||
908 | ZLIB_VERSION, zlibVersion(), stream->msg, file, line); | ||
909 | break; | ||
910 | default: | ||
911 | lua_pushfstring(L, "ZLibError: unknown code %d (%s) at %s line %d", | ||
912 | result, stream->msg, file, line); | ||
913 | } | ||
914 | lua_error(L); | ||
915 | return result; | ||
916 | } | ||
917 | |||
918 | /** | ||
919 | * @upvalue z_stream - Memory for the z_stream. | ||
920 | * @upvalue remainder - Any remainder from the last deflate call. | ||
921 | * | ||
922 | * @param string - "print" to deflate stream. | ||
923 | * @param int - flush output buffer? Z_SYNC_FLUSH, Z_FULL_FLUSH, or Z_FINISH. | ||
924 | * | ||
925 | * if no params, terminates the stream (as if we got empty string and Z_FINISH). | ||
926 | */ | ||
927 | static int lz_filter_impl(lua_State *L, int (*filter)(z_streamp, int), int (*end)(z_streamp), char* name) { | ||
928 | int flush = Z_NO_FLUSH, result; | ||
929 | z_stream* stream; | ||
930 | luaL_Buffer buff; | ||
931 | size_t avail_in; | ||
932 | |||
933 | if ( filter == deflate ) { | ||
934 | const char *const opts[] = { "none", "sync", "full", "finish", NULL }; | ||
935 | flush = luaL_checkoption(L, 2, opts[0], opts); | ||
936 | if ( flush ) flush++; | ||
937 | /* Z_NO_FLUSH(0) Z_SYNC_FLUSH(2), Z_FULL_FLUSH(3), Z_FINISH (4) */ | ||
938 | |||
939 | /* No arguments or nil, we are terminating the stream: */ | ||
940 | if ( lua_gettop(L) == 0 || lua_isnil(L, 1) ) { | ||
941 | flush = Z_FINISH; | ||
942 | } | ||
943 | } | ||
944 | |||
945 | stream = (z_stream*)lua_touserdata(L, lua_upvalueindex(1)); | ||
946 | if ( stream == NULL ) { | ||
947 | if ( lua_gettop(L) >= 1 && lua_isstring(L, 1) ) { | ||
948 | lua_pushfstring(L, "IllegalState: calling %s function when stream was previously closed", name); | ||
949 | lua_error(L); | ||
950 | } | ||
951 | lua_pushstring(L, ""); | ||
952 | lua_pushboolean(L, 1); | ||
953 | return 2; /* Ignore duplicate calls to "close". */ | ||
954 | } | ||
955 | |||
956 | luaL_buffinit(L, &buff); | ||
957 | |||
958 | if ( lua_gettop(L) > 1 ) lua_pushvalue(L, 1); | ||
959 | |||
960 | if ( lua_isstring(L, lua_upvalueindex(2)) ) { | ||
961 | lua_pushvalue(L, lua_upvalueindex(2)); | ||
962 | if ( lua_gettop(L) > 1 && lua_isstring(L, -2) ) { | ||
963 | lua_concat(L, 2); | ||
964 | } | ||
965 | } | ||
966 | |||
967 | /* Do the actual deflate'ing: */ | ||
968 | if (lua_gettop(L) > 0) { | ||
969 | stream->next_in = (unsigned char*)lua_tolstring(L, -1, &avail_in); | ||
970 | } else { | ||
971 | stream->next_in = NULL; | ||
972 | avail_in = 0; | ||
973 | } | ||
974 | stream->avail_in = avail_in; | ||
975 | |||
976 | if ( ! stream->avail_in && ! flush ) { | ||
977 | /* Passed empty string, make it a noop instead of erroring out. */ | ||
978 | lua_pushstring(L, ""); | ||
979 | lua_pushboolean(L, 0); | ||
980 | lua_pushinteger(L, stream->total_in); | ||
981 | lua_pushinteger(L, stream->total_out); | ||
982 | return 4; | ||
983 | } | ||
984 | |||
985 | do { | ||
986 | stream->next_out = (unsigned char*)luaL_prepbuffer(&buff); | ||
987 | stream->avail_out = LUAL_BUFFERSIZE; | ||
988 | result = filter(stream, flush); | ||
989 | if ( Z_BUF_ERROR != result ) { | ||
990 | /* Ignore Z_BUF_ERROR since that just indicates that we | ||
991 | * need a larger buffer in order to proceed. Thanks to | ||
992 | * Tobias Markmann for finding this bug! | ||
993 | */ | ||
994 | lz_assert(L, result, stream, __FILE__, __LINE__); | ||
995 | } | ||
996 | luaL_addsize(&buff, LUAL_BUFFERSIZE - stream->avail_out); | ||
997 | } while ( stream->avail_out == 0 ); | ||
998 | |||
999 | /* Need to do this before we alter the stack: */ | ||
1000 | luaL_pushresult(&buff); | ||
1001 | |||
1002 | /* Save remainder in lua_upvalueindex(2): */ | ||
1003 | if ( NULL != stream->next_in ) { | ||
1004 | lua_pushlstring(L, (char*)stream->next_in, stream->avail_in); | ||
1005 | lua_replace(L, lua_upvalueindex(2)); | ||
1006 | } | ||
1007 | |||
1008 | /* "close" the stream/remove finalizer: */ | ||
1009 | if ( result == Z_STREAM_END ) { | ||
1010 | /* Clear-out the metatable so end is not called twice: */ | ||
1011 | lua_pushnil(L); | ||
1012 | lua_setmetatable(L, lua_upvalueindex(1)); | ||
1013 | |||
1014 | /* nil the upvalue: */ | ||
1015 | lua_pushnil(L); | ||
1016 | lua_replace(L, lua_upvalueindex(1)); | ||
1017 | |||
1018 | /* Close the stream: */ | ||
1019 | lz_assert(L, end(stream), stream, __FILE__, __LINE__); | ||
1020 | |||
1021 | lua_pushboolean(L, 1); | ||
1022 | } else { | ||
1023 | lua_pushboolean(L, 0); | ||
1024 | } | ||
1025 | lua_pushinteger(L, stream->total_in); | ||
1026 | lua_pushinteger(L, stream->total_out); | ||
1027 | return 4; | ||
1028 | } | ||
1029 | |||
1030 | static void lz_create_deflate_mt(lua_State *L) { | ||
1031 | luaL_newmetatable(L, "lz.deflate.meta"); /* {} */ | ||
1032 | |||
1033 | lua_pushcfunction(L, lz_deflate_delete); | ||
1034 | lua_setfield(L, -2, "__gc"); | ||
1035 | |||
1036 | lua_pop(L, 1); /* <empty> */ | ||
1037 | } | ||
1038 | |||
1039 | static int lz_deflate_new(lua_State *L) { | ||
1040 | int level; | ||
1041 | int window_size; | ||
1042 | int result; | ||
1043 | |||
1044 | #ifdef LZLIB_COMPAT | ||
1045 | if ( lua_istable(L, 1) || lua_isuserdata(L, 1) || lua_isfunction(L, 1) ) { | ||
1046 | return lzlib_deflate(L); | ||
1047 | } | ||
1048 | #endif | ||
1049 | |||
1050 | level = luaL_optint(L, 1, Z_DEFAULT_COMPRESSION); | ||
1051 | window_size = luaL_optint(L, 2, MAX_WBITS); | ||
1052 | |||
1053 | /* Allocate the stream: */ | ||
1054 | z_stream* stream = (z_stream*)lua_newuserdata(L, sizeof(z_stream)); | ||
1055 | |||
1056 | stream->zalloc = Z_NULL; | ||
1057 | stream->zfree = Z_NULL; | ||
1058 | |||
1059 | result = deflateInit2(stream, level, Z_DEFLATED, window_size, | ||
1060 | DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); | ||
1061 | |||
1062 | lz_assert(L, result, stream, __FILE__, __LINE__); | ||
1063 | |||
1064 | /* Don't allow destructor to execute unless deflateInit2 was successful: */ | ||
1065 | luaL_getmetatable(L, "lz.deflate.meta"); | ||
1066 | lua_setmetatable(L, -2); | ||
1067 | |||
1068 | lua_pushnil(L); | ||
1069 | lua_pushcclosure(L, lz_deflate, 2); | ||
1070 | return 1; | ||
1071 | } | ||
1072 | |||
1073 | static int lz_deflate(lua_State *L) { | ||
1074 | return lz_filter_impl(L, deflate, deflateEnd, "deflate"); | ||
1075 | } | ||
1076 | |||
1077 | static int lz_deflate_delete(lua_State *L) { | ||
1078 | z_stream* stream = (z_stream*)lua_touserdata(L, 1); | ||
1079 | |||
1080 | /* Ignore errors. */ | ||
1081 | deflateEnd(stream); | ||
1082 | |||
1083 | return 0; | ||
1084 | } | ||
1085 | |||
1086 | |||
1087 | static void lz_create_inflate_mt(lua_State *L) { | ||
1088 | luaL_newmetatable(L, "lz.inflate.meta"); /* {} */ | ||
1089 | |||
1090 | lua_pushcfunction(L, lz_inflate_delete); | ||
1091 | lua_setfield(L, -2, "__gc"); | ||
1092 | |||
1093 | lua_pop(L, 1); /* <empty> */ | ||
1094 | } | ||
1095 | |||
1096 | static int lz_inflate_new(lua_State *L) { | ||
1097 | /* Allocate the stream */ | ||
1098 | z_stream* stream; | ||
1099 | |||
1100 | #ifdef LZLIB_COMPAT | ||
1101 | int type = lua_type(L, 1); | ||
1102 | if ( type == LUA_TTABLE || type == LUA_TUSERDATA || type == LUA_TFUNCTION || type == LUA_TSTRING ) { | ||
1103 | return lzlib_inflate(L); | ||
1104 | } | ||
1105 | #endif | ||
1106 | |||
1107 | stream = (z_stream*)lua_newuserdata(L, sizeof(z_stream)); | ||
1108 | |||
1109 | /* By default, we will do gzip header detection w/ max window size */ | ||
1110 | int window_size = lua_isnumber(L, 1) ? lua_tointeger(L, 1) : MAX_WBITS + 32; | ||
1111 | |||
1112 | stream->zalloc = Z_NULL; | ||
1113 | stream->zfree = Z_NULL; | ||
1114 | stream->next_in = Z_NULL; | ||
1115 | stream->avail_in = 0; | ||
1116 | |||
1117 | lz_assert(L, inflateInit2(stream, window_size), stream, __FILE__, __LINE__); | ||
1118 | |||
1119 | /* Don't allow destructor to execute unless deflateInit was successful: */ | ||
1120 | luaL_getmetatable(L, "lz.inflate.meta"); | ||
1121 | lua_setmetatable(L, -2); | ||
1122 | |||
1123 | lua_pushnil(L); | ||
1124 | lua_pushcclosure(L, lz_inflate, 2); | ||
1125 | return 1; | ||
1126 | } | ||
1127 | |||
1128 | static int lz_inflate(lua_State *L) { | ||
1129 | return lz_filter_impl(L, inflate, inflateEnd, "inflate"); | ||
1130 | } | ||
1131 | |||
1132 | static int lz_inflate_delete(lua_State *L) { | ||
1133 | z_stream* stream = (z_stream*)lua_touserdata(L, 1); | ||
1134 | |||
1135 | /* Ignore errors: */ | ||
1136 | inflateEnd(stream); | ||
1137 | |||
1138 | return 0; | ||
1139 | } | ||
1140 | |||
1141 | static int lz_checksum(lua_State *L) { | ||
1142 | if ( lua_gettop(L) <= 0 ) { | ||
1143 | lua_pushvalue(L, lua_upvalueindex(3)); | ||
1144 | lua_pushvalue(L, lua_upvalueindex(4)); | ||
1145 | } else if ( lua_isfunction(L, 1) ) { | ||
1146 | checksum_combine_t combine = (checksum_combine_t) | ||
1147 | lua_touserdata(L, lua_upvalueindex(2)); | ||
1148 | |||
1149 | lua_pushvalue(L, 1); | ||
1150 | lua_call(L, 0, 2); | ||
1151 | if ( ! lua_isnumber(L, -2) || ! lua_isnumber(L, -1) ) { | ||
1152 | luaL_argerror(L, 1, "expected function to return two numbers"); | ||
1153 | } | ||
1154 | |||
1155 | /* Calculate and replace the checksum */ | ||
1156 | lua_pushnumber(L, | ||
1157 | combine((uLong)lua_tonumber(L, lua_upvalueindex(3)), | ||
1158 | (uLong)lua_tonumber(L, -2), | ||
1159 | (z_off_t)lua_tonumber(L, -1))); | ||
1160 | lua_pushvalue(L, -1); | ||
1161 | lua_replace(L, lua_upvalueindex(3)); | ||
1162 | |||
1163 | /* Calculate and replace the length */ | ||
1164 | lua_pushnumber(L, | ||
1165 | lua_tonumber(L, lua_upvalueindex(4)) + lua_tonumber(L, -2)); | ||
1166 | lua_pushvalue(L, -1); | ||
1167 | lua_replace(L, lua_upvalueindex(4)); | ||
1168 | } else { | ||
1169 | const Bytef* str; | ||
1170 | size_t len; | ||
1171 | |||
1172 | checksum_t checksum = (checksum_t) | ||
1173 | lua_touserdata(L, lua_upvalueindex(1)); | ||
1174 | str = (const Bytef*)luaL_checklstring(L, 1, &len); | ||
1175 | |||
1176 | /* Calculate and replace the checksum */ | ||
1177 | lua_pushnumber(L, | ||
1178 | checksum((uLong)lua_tonumber(L, lua_upvalueindex(3)), | ||
1179 | str, | ||
1180 | len)); | ||
1181 | lua_pushvalue(L, -1); | ||
1182 | lua_replace(L, lua_upvalueindex(3)); | ||
1183 | |||
1184 | /* Calculate and replace the length */ | ||
1185 | lua_pushnumber(L, | ||
1186 | lua_tonumber(L, lua_upvalueindex(4)) + len); | ||
1187 | lua_pushvalue(L, -1); | ||
1188 | lua_replace(L, lua_upvalueindex(4)); | ||
1189 | } | ||
1190 | return 2; | ||
1191 | } | ||
1192 | |||
1193 | static int lz_checksum_new(lua_State *L, checksum_t checksum, checksum_combine_t combine) { | ||
1194 | lua_pushlightuserdata(L, checksum); | ||
1195 | lua_pushlightuserdata(L, combine); | ||
1196 | lua_pushnumber(L, checksum(0L, Z_NULL, 0)); | ||
1197 | lua_pushnumber(L, 0); | ||
1198 | lua_pushcclosure(L, lz_checksum, 4); | ||
1199 | return 1; | ||
1200 | } | ||
1201 | |||
1202 | static int lz_adler32(lua_State *L) { | ||
1203 | #ifdef LZLIB_COMPAT | ||
1204 | /* lzlib compat*/ | ||
1205 | if ( lua_gettop(L) != 0 ) { | ||
1206 | size_t len; | ||
1207 | int adler; | ||
1208 | const unsigned char* buf; | ||
1209 | if ( lua_isfunction(L, 1) ) { | ||
1210 | adler = adler32(0L, Z_NULL, 0); | ||
1211 | } else { | ||
1212 | adler = (int)luaL_checkinteger(L, 1); | ||
1213 | } | ||
1214 | buf = (unsigned char*)luaL_checklstring(L, 2, &len); | ||
1215 | lua_pushnumber(L, adler32(adler, buf, len)); | ||
1216 | return 1; | ||
1217 | } | ||
1218 | #endif | ||
1219 | return lz_checksum_new(L, adler32, adler32_combine); | ||
1220 | } | ||
1221 | |||
1222 | static int lz_crc32(lua_State *L) { | ||
1223 | #ifdef LZLIB_COMPAT | ||
1224 | /* lzlib compat*/ | ||
1225 | if ( lua_gettop(L) != 0 ) { | ||
1226 | size_t len; | ||
1227 | int crc; | ||
1228 | const unsigned char* buf; | ||
1229 | if ( lua_isfunction(L, 1) ) { | ||
1230 | crc = crc32(0L, Z_NULL, 0); | ||
1231 | } else { | ||
1232 | crc = (int)luaL_checkinteger(L, 1); | ||
1233 | } | ||
1234 | buf = (unsigned char*)luaL_checklstring(L, 2, &len); | ||
1235 | lua_pushnumber(L, crc32(crc, buf, len)); | ||
1236 | return 1; | ||
1237 | } | ||
1238 | #endif | ||
1239 | return lz_checksum_new(L, crc32, crc32_combine); | ||
1240 | } | ||
1241 | |||
1242 | |||
1243 | static const luaL_Reg zlib_functions[] = { | ||
1244 | { "deflate", lz_deflate_new }, | ||
1245 | { "inflate", lz_inflate_new }, | ||
1246 | { "adler32", lz_adler32 }, | ||
1247 | { "crc32", lz_crc32 }, | ||
1248 | #ifdef LZLIB_COMPAT | ||
1249 | { "compress", lzlib_compress }, | ||
1250 | { "decompress", lzlib_decompress }, | ||
1251 | #endif | ||
1252 | { "version", lz_version }, | ||
1253 | { NULL, NULL } | ||
1254 | }; | ||
1255 | |||
1256 | #define SETLITERAL(n,v) (lua_pushliteral(L, n), lua_pushliteral(L, v), lua_settable(L, -3)) | ||
1257 | #define SETINT(n,v) (lua_pushliteral(L, n), lua_pushinteger(L, v), lua_settable(L, -3)) | ||
1258 | |||
1259 | LUALIB_API int luaopen_zlib(lua_State * const L) { | ||
1260 | lz_create_deflate_mt(L); | ||
1261 | lz_create_inflate_mt(L); | ||
1262 | |||
1263 | luaL_register(L, "zlib", zlib_functions); | ||
1264 | |||
1265 | SETINT("BEST_SPEED", Z_BEST_SPEED); | ||
1266 | SETINT("BEST_COMPRESSION", Z_BEST_COMPRESSION); | ||
1267 | |||
1268 | SETLITERAL("_COPYRIGHT", "Copyright (c) 2009-2016 Brian Maher"); | ||
1269 | SETLITERAL("_DESCRIPTION", "Simple streaming interface to the zlib library"); | ||
1270 | SETLITERAL("_VERSION", "lua-zlib $Id$ $Format:%d$"); | ||
1271 | |||
1272 | /* Expose this to lua so we can do a test: */ | ||
1273 | SETINT("_TEST_BUFSIZ", LUAL_BUFFERSIZE); | ||
1274 | |||
1275 | /* lzlib compatibility */ | ||
1276 | #ifdef LZLIB_COMPAT | ||
1277 | SETINT("NO_COMPRESSION", Z_NO_COMPRESSION); | ||
1278 | SETINT("DEFAULT_COMPRESSION", Z_DEFAULT_COMPRESSION); | ||
1279 | SETINT("FILTERED", Z_FILTERED); | ||
1280 | SETINT("HUFFMAN_ONLY", Z_HUFFMAN_ONLY); | ||
1281 | SETINT("RLE", Z_RLE); | ||
1282 | SETINT("FIXED", Z_FIXED); | ||
1283 | SETINT("DEFAULT_STRATEGY", Z_DEFAULT_STRATEGY); | ||
1284 | SETINT("MINIMUM_MEMLEVEL", 1); | ||
1285 | SETINT("MAXIMUM_MEMLEVEL", 9); | ||
1286 | SETINT("DEFAULT_MEMLEVEL", 8); | ||
1287 | SETINT("DEFAULT_WINDOWBITS", 15); | ||
1288 | SETINT("MINIMUM_WINDOWBITS", 8); | ||
1289 | SETINT("MAXIMUM_WINDOWBITS", 15); | ||
1290 | SETINT("GZIP_WINDOWBITS", 16); | ||
1291 | SETINT("RAW_WINDOWBITS", -1); | ||
1292 | #endif | ||
1293 | |||
1294 | return 1; | ||
1295 | } | ||
diff --git a/vendor/luafilesystem/.gitignore b/vendor/luafilesystem/.gitignore new file mode 100644 index 00000000..ddaacd81 --- /dev/null +++ b/vendor/luafilesystem/.gitignore | |||
@@ -0,0 +1,2 @@ | |||
1 | *.so | ||
2 | |||
diff --git a/vendor/luafilesystem/.travis.yml b/vendor/luafilesystem/.travis.yml new file mode 100644 index 00000000..618e48e1 --- /dev/null +++ b/vendor/luafilesystem/.travis.yml | |||
@@ -0,0 +1,34 @@ | |||
1 | language: c | ||
2 | |||
3 | sudo: false | ||
4 | |||
5 | env: | ||
6 | - LUA="lua 5.1" | ||
7 | - LUA="lua 5.2" | ||
8 | - LUA="lua 5.3" | ||
9 | - LUA="luajit 2.1" | ||
10 | |||
11 | before_install: | ||
12 | - pip install --user cpp-coveralls hererocks | ||
13 | - hererocks env --$LUA --luarocks latest | ||
14 | - export PATH="$PWD/env/bin:$PATH" | ||
15 | - luarocks install lua-path | ||
16 | - luarocks install dkjson | ||
17 | - luarocks install luacov | ||
18 | # install luacov-coveralls, but avoid installing luafilesystem | ||
19 | - luarocks install luacov-coveralls --server=https://luarocks.org/dev --deps-mode=none | ||
20 | |||
21 | install: | ||
22 | - luarocks make CFLAGS="-O2 -fPIC -ftest-coverage -fprofile-arcs" LIBFLAG="-shared --coverage" | ||
23 | |||
24 | script: | ||
25 | - lua -lluacov tests/test.lua | ||
26 | |||
27 | after_success: | ||
28 | - coveralls -b . -i src --dump c.report.json | ||
29 | - luacov-coveralls -j c.report.json -v | ||
30 | |||
31 | notifications: | ||
32 | email: | ||
33 | on_success: change | ||
34 | on_failure: always | ||
diff --git a/vendor/luafilesystem/LICENSE b/vendor/luafilesystem/LICENSE new file mode 100644 index 00000000..8475345a --- /dev/null +++ b/vendor/luafilesystem/LICENSE | |||
@@ -0,0 +1,21 @@ | |||
1 | Copyright © 2003-2014 Kepler Project. | ||
2 | |||
3 | Permission is hereby granted, free of charge, to any person | ||
4 | obtaining a copy of this software and associated documentation | ||
5 | files (the "Software"), to deal in the Software without | ||
6 | restriction, including without limitation the rights to use, copy, | ||
7 | modify, merge, publish, distribute, sublicense, and/or sell copies | ||
8 | of the Software, and to permit persons to whom the Software is | ||
9 | furnished to do so, subject to the following conditions: | ||
10 | |||
11 | The above copyright notice and this permission notice shall be | ||
12 | included in all copies or substantial portions of the Software. | ||
13 | |||
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
18 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
19 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
21 | SOFTWARE. | ||
diff --git a/vendor/luafilesystem/README.md b/vendor/luafilesystem/README.md new file mode 100644 index 00000000..d0fd3f29 --- /dev/null +++ b/vendor/luafilesystem/README.md | |||
@@ -0,0 +1,28 @@ | |||
1 | [](LICENSE) | ||
2 | [](https://travis-ci.org/keplerproject/luafilesystem) | ||
3 | [](https://ci.appveyor.com/project/ignacio/luafilesystem) | ||
4 | [](https://coveralls.io/r/keplerproject/luafilesystem) | ||
5 | |||
6 | # LuaFileSystem - File System Library for Lua | ||
7 | |||
8 | Copyright 2003-2020 Kepler Project | ||
9 | |||
10 | https://keplerproject.github.io/luafilesystem | ||
11 | |||
12 | # Description | ||
13 | |||
14 | LuaFileSystem is a Lua library developed to complement the set of functions | ||
15 | related to file systems offered by the standard Lua distribution. | ||
16 | |||
17 | LuaFileSystem offers a portable way to access the underlying directory structure and file attributes. | ||
18 | LuaFileSystem is free software and uses the same license as Lua 5.x (MIT). | ||
19 | |||
20 | # LuaRocks Installation | ||
21 | |||
22 | ``` | ||
23 | luarocks install luafilesystem | ||
24 | ``` | ||
25 | |||
26 | # Documentation | ||
27 | |||
28 | Please check the documentation at doc/us/ for more information. | ||
diff --git a/vendor/luafilesystem/luafilesystem-scm-1.rockspec b/vendor/luafilesystem/luafilesystem-scm-1.rockspec new file mode 100644 index 00000000..71cf19b4 --- /dev/null +++ b/vendor/luafilesystem/luafilesystem-scm-1.rockspec | |||
@@ -0,0 +1,28 @@ | |||
1 | package = "luafilesystem" | ||
2 | version = "scm-1" | ||
3 | source = { | ||
4 | url = "git://github.com/keplerproject/luafilesystem" | ||
5 | } | ||
6 | description = { | ||
7 | summary = "File System Library for the Lua Programming Language", | ||
8 | detailed = [[ | ||
9 | LuaFileSystem is a Lua library developed to complement the set of | ||
10 | functions related to file systems offered by the standard Lua | ||
11 | distribution. LuaFileSystem offers a portable way to access the | ||
12 | underlying directory structure and file attributes. | ||
13 | ]], | ||
14 | license = "MIT/X11" | ||
15 | } | ||
16 | dependencies = { | ||
17 | "lua >= 5.1" | ||
18 | } | ||
19 | build = { | ||
20 | type = "builtin", | ||
21 | modules = { | ||
22 | lfs = "src/lfs.c" | ||
23 | }, | ||
24 | copy_directories = { | ||
25 | "doc", | ||
26 | "tests" | ||
27 | } | ||
28 | } | ||
diff --git a/vendor/luafilesystem/src/.gitignore b/vendor/luafilesystem/src/.gitignore new file mode 100644 index 00000000..9d22eb46 --- /dev/null +++ b/vendor/luafilesystem/src/.gitignore | |||
@@ -0,0 +1,2 @@ | |||
1 | *.o | ||
2 | *.so | ||
diff --git a/vendor/luafilesystem/src/lfs.c b/vendor/luafilesystem/src/lfs.c new file mode 100644 index 00000000..95ab63b4 --- /dev/null +++ b/vendor/luafilesystem/src/lfs.c | |||
@@ -0,0 +1,1182 @@ | |||
1 | /* | ||
2 | ** LuaFileSystem | ||
3 | ** Copyright Kepler Project 2003 - 2020 | ||
4 | ** (http://keplerproject.github.io/luafilesystem) | ||
5 | ** | ||
6 | ** File system manipulation library. | ||
7 | ** This library offers these functions: | ||
8 | ** lfs.attributes (filepath [, attributename | attributetable]) | ||
9 | ** lfs.chdir (path) | ||
10 | ** lfs.currentdir () | ||
11 | ** lfs.dir (path) | ||
12 | ** lfs.link (old, new[, symlink]) | ||
13 | ** lfs.lock (fh, mode) | ||
14 | ** lfs.lock_dir (path) | ||
15 | ** lfs.mkdir (path) | ||
16 | ** lfs.rmdir (path) | ||
17 | ** lfs.setmode (filepath, mode) | ||
18 | ** lfs.symlinkattributes (filepath [, attributename]) | ||
19 | ** lfs.touch (filepath [, atime [, mtime]]) | ||
20 | ** lfs.unlock (fh) | ||
21 | */ | ||
22 | |||
23 | #ifndef LFS_DO_NOT_USE_LARGE_FILE | ||
24 | #ifndef _WIN32 | ||
25 | #ifndef _AIX | ||
26 | #define _FILE_OFFSET_BITS 64 /* Linux, Solaris and HP-UX */ | ||
27 | #else | ||
28 | #define _LARGE_FILES 1 /* AIX */ | ||
29 | #endif | ||
30 | #endif | ||
31 | #endif | ||
32 | |||
33 | #ifdef _WIN32 | ||
34 | #define _WIN32_WINNT 0x600 | ||
35 | #endif | ||
36 | |||
37 | #ifndef LFS_DO_NOT_USE_LARGE_FILE | ||
38 | #define _LARGEFILE64_SOURCE | ||
39 | #endif | ||
40 | |||
41 | #include <errno.h> | ||
42 | #include <stdio.h> | ||
43 | #include <string.h> | ||
44 | #include <stdlib.h> | ||
45 | #include <time.h> | ||
46 | #include <sys/stat.h> | ||
47 | |||
48 | #ifdef _WIN32 | ||
49 | |||
50 | #include <direct.h> | ||
51 | #include <windows.h> | ||
52 | #include <io.h> | ||
53 | #include <sys/locking.h> | ||
54 | |||
55 | #ifdef __BORLANDC__ | ||
56 | #include <utime.h> | ||
57 | #else | ||
58 | #include <sys/utime.h> | ||
59 | #endif | ||
60 | |||
61 | #include <fcntl.h> | ||
62 | |||
63 | /* MAX_PATH seems to be 260. Seems kind of small. Is there a better one? */ | ||
64 | #define LFS_MAXPATHLEN MAX_PATH | ||
65 | |||
66 | #else | ||
67 | |||
68 | #include <unistd.h> | ||
69 | #include <dirent.h> | ||
70 | #include <fcntl.h> | ||
71 | #include <sys/types.h> | ||
72 | #include <utime.h> | ||
73 | #include <sys/param.h> /* for MAXPATHLEN */ | ||
74 | |||
75 | #ifdef MAXPATHLEN | ||
76 | #define LFS_MAXPATHLEN MAXPATHLEN | ||
77 | #else | ||
78 | #include <limits.h> /* for _POSIX_PATH_MAX */ | ||
79 | #define LFS_MAXPATHLEN _POSIX_PATH_MAX | ||
80 | #endif | ||
81 | |||
82 | #endif | ||
83 | |||
84 | #include <lua.h> | ||
85 | #include <lauxlib.h> | ||
86 | #include <lualib.h> | ||
87 | |||
88 | #include "lfs.h" | ||
89 | |||
90 | #define LFS_VERSION "1.8.0" | ||
91 | #define LFS_LIBNAME "lfs" | ||
92 | |||
93 | #if LUA_VERSION_NUM >= 503 /* Lua 5.3+ */ | ||
94 | |||
95 | #ifndef luaL_optlong | ||
96 | #define luaL_optlong luaL_optinteger | ||
97 | #endif | ||
98 | |||
99 | #endif | ||
100 | |||
101 | #if LUA_VERSION_NUM >= 502 | ||
102 | #define new_lib(L, l) (luaL_newlib(L, l)) | ||
103 | #else | ||
104 | #define new_lib(L, l) (lua_newtable(L), luaL_register(L, NULL, l)) | ||
105 | #endif | ||
106 | |||
107 | /* Define 'strerror' for systems that do not implement it */ | ||
108 | #ifdef NO_STRERROR | ||
109 | #define strerror(_) "System unable to describe the error" | ||
110 | #endif | ||
111 | |||
112 | #define DIR_METATABLE "directory metatable" | ||
113 | typedef struct dir_data { | ||
114 | int closed; | ||
115 | #ifdef _WIN32 | ||
116 | intptr_t hFile; | ||
117 | char pattern[MAX_PATH + 1]; | ||
118 | #else | ||
119 | DIR *dir; | ||
120 | #endif | ||
121 | } dir_data; | ||
122 | |||
123 | #define LOCK_METATABLE "lock metatable" | ||
124 | |||
125 | #ifdef _WIN32 | ||
126 | |||
127 | #ifdef __BORLANDC__ | ||
128 | #define lfs_setmode(file, m) (setmode(_fileno(file), m)) | ||
129 | #define STAT_STRUCT struct stati64 | ||
130 | #else | ||
131 | #define lfs_setmode(file, m) (_setmode(_fileno(file), m)) | ||
132 | #define STAT_STRUCT struct _stati64 | ||
133 | #endif | ||
134 | |||
135 | #ifndef _S_IFLNK | ||
136 | #define _S_IFLNK 0x400 | ||
137 | #endif | ||
138 | |||
139 | #ifndef S_ISDIR | ||
140 | #define S_ISDIR(mode) (mode&_S_IFDIR) | ||
141 | #endif | ||
142 | #ifndef S_ISREG | ||
143 | #define S_ISREG(mode) (mode&_S_IFREG) | ||
144 | #endif | ||
145 | #ifndef S_ISLNK | ||
146 | #define S_ISLNK(mode) (mode&_S_IFLNK) | ||
147 | #endif | ||
148 | #ifndef S_ISSOCK | ||
149 | #define S_ISSOCK(mode) (0) | ||
150 | #endif | ||
151 | #ifndef S_ISFIFO | ||
152 | #define S_ISFIFO(mode) (0) | ||
153 | #endif | ||
154 | #ifndef S_ISCHR | ||
155 | #define S_ISCHR(mode) (mode&_S_IFCHR) | ||
156 | #endif | ||
157 | #ifndef S_ISBLK | ||
158 | #define S_ISBLK(mode) (0) | ||
159 | #endif | ||
160 | |||
161 | #define STAT_FUNC _stati64 | ||
162 | #define LSTAT_FUNC lfs_win32_lstat | ||
163 | |||
164 | #else | ||
165 | |||
166 | #define _O_TEXT 0 | ||
167 | #define _O_BINARY 0 | ||
168 | #define lfs_setmode(file, m) ((void)file, (void)m, 0) | ||
169 | #define STAT_STRUCT struct stat | ||
170 | #define STAT_FUNC stat | ||
171 | #define LSTAT_FUNC lstat | ||
172 | |||
173 | #endif | ||
174 | |||
175 | #ifdef _WIN32 | ||
176 | #define lfs_mkdir _mkdir | ||
177 | #else | ||
178 | #define lfs_mkdir(path) (mkdir((path), \ | ||
179 | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH)) | ||
180 | #endif | ||
181 | |||
182 | #ifdef _WIN32 | ||
183 | |||
184 | int lfs_win32_pusherror(lua_State * L) | ||
185 | { | ||
186 | int en = GetLastError(); | ||
187 | lua_pushnil(L); | ||
188 | if (en == ERROR_FILE_EXISTS || en == ERROR_SHARING_VIOLATION) | ||
189 | lua_pushstring(L, "File exists"); | ||
190 | else | ||
191 | lua_pushstring(L, strerror(en)); | ||
192 | return 2; | ||
193 | } | ||
194 | |||
195 | #define TICKS_PER_SECOND 10000000 | ||
196 | #define EPOCH_DIFFERENCE 11644473600LL | ||
197 | time_t windowsToUnixTime(FILETIME ft) | ||
198 | { | ||
199 | ULARGE_INTEGER uli; | ||
200 | uli.LowPart = ft.dwLowDateTime; | ||
201 | uli.HighPart = ft.dwHighDateTime; | ||
202 | return (time_t) (uli.QuadPart / TICKS_PER_SECOND - EPOCH_DIFFERENCE); | ||
203 | } | ||
204 | |||
205 | int lfs_win32_lstat(const char *path, STAT_STRUCT * buffer) | ||
206 | { | ||
207 | WIN32_FILE_ATTRIBUTE_DATA win32buffer; | ||
208 | if (GetFileAttributesEx(path, GetFileExInfoStandard, &win32buffer)) { | ||
209 | if (!(win32buffer.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { | ||
210 | return STAT_FUNC(path, buffer); | ||
211 | } | ||
212 | buffer->st_mode = _S_IFLNK; | ||
213 | buffer->st_dev = 0; | ||
214 | buffer->st_ino = 0; | ||
215 | buffer->st_nlink = 0; | ||
216 | buffer->st_uid = 0; | ||
217 | buffer->st_gid = 0; | ||
218 | buffer->st_rdev = 0; | ||
219 | buffer->st_atime = windowsToUnixTime(win32buffer.ftLastAccessTime); | ||
220 | buffer->st_mtime = windowsToUnixTime(win32buffer.ftLastWriteTime); | ||
221 | buffer->st_ctime = windowsToUnixTime(win32buffer.ftCreationTime); | ||
222 | buffer->st_size = 0; | ||
223 | return 0; | ||
224 | } else { | ||
225 | return 1; | ||
226 | } | ||
227 | } | ||
228 | |||
229 | #endif | ||
230 | |||
231 | /* | ||
232 | ** Utility functions | ||
233 | */ | ||
234 | static int pusherror(lua_State * L, const char *info) | ||
235 | { | ||
236 | lua_pushnil(L); | ||
237 | if (info == NULL) | ||
238 | lua_pushstring(L, strerror(errno)); | ||
239 | else | ||
240 | lua_pushfstring(L, "%s: %s", info, strerror(errno)); | ||
241 | lua_pushinteger(L, errno); | ||
242 | return 3; | ||
243 | } | ||
244 | |||
245 | static int pushresult(lua_State * L, int res, const char *info) | ||
246 | { | ||
247 | if (res == -1) { | ||
248 | return pusherror(L, info); | ||
249 | } else { | ||
250 | lua_pushboolean(L, 1); | ||
251 | return 1; | ||
252 | } | ||
253 | } | ||
254 | |||
255 | |||
256 | /* | ||
257 | ** This function changes the working (current) directory | ||
258 | */ | ||
259 | static int change_dir(lua_State * L) | ||
260 | { | ||
261 | const char *path = luaL_checkstring(L, 1); | ||
262 | if (chdir(path)) { | ||
263 | lua_pushnil(L); | ||
264 | lua_pushfstring(L, "Unable to change working directory to '%s'\n%s\n", | ||
265 | path, chdir_error); | ||
266 | return 2; | ||
267 | } else { | ||
268 | lua_pushboolean(L, 1); | ||
269 | return 1; | ||
270 | } | ||
271 | } | ||
272 | |||
273 | /* | ||
274 | ** This function returns the current directory | ||
275 | ** If unable to get the current directory, it returns nil | ||
276 | ** and a string describing the error | ||
277 | */ | ||
278 | static int get_dir(lua_State * L) | ||
279 | { | ||
280 | #ifdef NO_GETCWD | ||
281 | lua_pushnil(L); | ||
282 | lua_pushstring(L, "Function 'getcwd' not provided by system"); | ||
283 | return 2; | ||
284 | #else | ||
285 | char *path = NULL; | ||
286 | /* Passing (NULL, 0) is not guaranteed to work. | ||
287 | Use a temp buffer and size instead. */ | ||
288 | size_t size = LFS_MAXPATHLEN; /* initial buffer size */ | ||
289 | int result; | ||
290 | while (1) { | ||
291 | char *path2 = realloc(path, size); | ||
292 | if (!path2) { /* failed to allocate */ | ||
293 | result = pusherror(L, "get_dir realloc() failed"); | ||
294 | break; | ||
295 | } | ||
296 | path = path2; | ||
297 | if (getcwd(path, size) != NULL) { | ||
298 | /* success, push the path to the Lua stack */ | ||
299 | lua_pushstring(L, path); | ||
300 | result = 1; | ||
301 | break; | ||
302 | } | ||
303 | if (errno != ERANGE) { /* unexpected error */ | ||
304 | result = pusherror(L, "get_dir getcwd() failed"); | ||
305 | break; | ||
306 | } | ||
307 | /* ERANGE = insufficient buffer capacity, double size and retry */ | ||
308 | size *= 2; | ||
309 | } | ||
310 | free(path); | ||
311 | return result; | ||
312 | #endif | ||
313 | } | ||
314 | |||
315 | /* | ||
316 | ** Check if the given element on the stack is a file and returns it. | ||
317 | */ | ||
318 | static FILE *check_file(lua_State * L, int idx, const char *funcname) | ||
319 | { | ||
320 | #if LUA_VERSION_NUM == 501 | ||
321 | FILE **fh = (FILE **) luaL_checkudata(L, idx, "FILE*"); | ||
322 | if (*fh == NULL) { | ||
323 | luaL_error(L, "%s: closed file", funcname); | ||
324 | return 0; | ||
325 | } else | ||
326 | return *fh; | ||
327 | #elif LUA_VERSION_NUM >= 502 && LUA_VERSION_NUM <= 504 | ||
328 | luaL_Stream *fh = (luaL_Stream *) luaL_checkudata(L, idx, "FILE*"); | ||
329 | if (fh->closef == 0 || fh->f == NULL) { | ||
330 | luaL_error(L, "%s: closed file", funcname); | ||
331 | return 0; | ||
332 | } else | ||
333 | return fh->f; | ||
334 | #else | ||
335 | #error unsupported Lua version | ||
336 | #endif | ||
337 | } | ||
338 | |||
339 | |||
340 | /* | ||
341 | ** | ||
342 | */ | ||
343 | static int _file_lock(lua_State * L, FILE * fh, const char *mode, | ||
344 | const long start, long len, const char *funcname) | ||
345 | { | ||
346 | int code; | ||
347 | #ifdef _WIN32 | ||
348 | /* lkmode valid values are: | ||
349 | LK_LOCK Locks the specified bytes. If the bytes cannot be locked, | ||
350 | the program immediately tries again after 1 second. | ||
351 | If, after 10 attempts, the bytes cannot be locked, | ||
352 | the constant returns an error. | ||
353 | LK_NBLCK Locks the specified bytes. If the bytes cannot be locked, | ||
354 | the constant returns an error. | ||
355 | LK_NBRLCK Same as _LK_NBLCK. | ||
356 | LK_RLCK Same as _LK_LOCK. | ||
357 | LK_UNLCK Unlocks the specified bytes, which must have been | ||
358 | previously locked. | ||
359 | |||
360 | Regions should be locked only briefly and should be unlocked | ||
361 | before closing a file or exiting the program. | ||
362 | |||
363 | http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt__locking.asp | ||
364 | */ | ||
365 | int lkmode; | ||
366 | switch (*mode) { | ||
367 | case 'r': | ||
368 | lkmode = LK_NBLCK; | ||
369 | break; | ||
370 | case 'w': | ||
371 | lkmode = LK_NBLCK; | ||
372 | break; | ||
373 | case 'u': | ||
374 | lkmode = LK_UNLCK; | ||
375 | break; | ||
376 | default: | ||
377 | return luaL_error(L, "%s: invalid mode", funcname); | ||
378 | } | ||
379 | if (!len) { | ||
380 | fseek(fh, 0L, SEEK_END); | ||
381 | len = ftell(fh); | ||
382 | } | ||
383 | fseek(fh, start, SEEK_SET); | ||
384 | #ifdef __BORLANDC__ | ||
385 | code = locking(fileno(fh), lkmode, len); | ||
386 | #else | ||
387 | code = _locking(fileno(fh), lkmode, len); | ||
388 | #endif | ||
389 | #else | ||
390 | struct flock f; | ||
391 | switch (*mode) { | ||
392 | case 'w': | ||
393 | f.l_type = F_WRLCK; | ||
394 | break; | ||
395 | case 'r': | ||
396 | f.l_type = F_RDLCK; | ||
397 | break; | ||
398 | case 'u': | ||
399 | f.l_type = F_UNLCK; | ||
400 | break; | ||
401 | default: | ||
402 | return luaL_error(L, "%s: invalid mode", funcname); | ||
403 | } | ||
404 | f.l_whence = SEEK_SET; | ||
405 | f.l_start = (off_t) start; | ||
406 | f.l_len = (off_t) len; | ||
407 | code = fcntl(fileno(fh), F_SETLK, &f); | ||
408 | #endif | ||
409 | return (code != -1); | ||
410 | } | ||
411 | |||
412 | #ifdef _WIN32 | ||
413 | typedef struct lfs_Lock { | ||
414 | HANDLE fd; | ||
415 | } lfs_Lock; | ||
416 | static int lfs_lock_dir(lua_State * L) | ||
417 | { | ||
418 | size_t pathl; | ||
419 | HANDLE fd; | ||
420 | lfs_Lock *lock; | ||
421 | char *ln; | ||
422 | const char *lockfile = "/lockfile.lfs"; | ||
423 | const char *path = luaL_checklstring(L, 1, &pathl); | ||
424 | ln = (char *) malloc(pathl + strlen(lockfile) + 1); | ||
425 | if (!ln) { | ||
426 | lua_pushnil(L); | ||
427 | lua_pushstring(L, strerror(errno)); | ||
428 | return 2; | ||
429 | } | ||
430 | strcpy(ln, path); | ||
431 | strcat(ln, lockfile); | ||
432 | fd = CreateFile(ln, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, | ||
433 | FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL); | ||
434 | free(ln); | ||
435 | if (fd == INVALID_HANDLE_VALUE) { | ||
436 | return lfs_win32_pusherror(L); | ||
437 | } | ||
438 | lock = (lfs_Lock *) lua_newuserdata(L, sizeof(lfs_Lock)); | ||
439 | lock->fd = fd; | ||
440 | luaL_getmetatable(L, LOCK_METATABLE); | ||
441 | lua_setmetatable(L, -2); | ||
442 | return 1; | ||
443 | } | ||
444 | |||
445 | static int lfs_unlock_dir(lua_State * L) | ||
446 | { | ||
447 | lfs_Lock *lock = (lfs_Lock *) luaL_checkudata(L, 1, LOCK_METATABLE); | ||
448 | if (lock->fd != INVALID_HANDLE_VALUE) { | ||
449 | CloseHandle(lock->fd); | ||
450 | lock->fd = INVALID_HANDLE_VALUE; | ||
451 | } | ||
452 | return 0; | ||
453 | } | ||
454 | #else | ||
455 | typedef struct lfs_Lock { | ||
456 | char *ln; | ||
457 | } lfs_Lock; | ||
458 | static int lfs_lock_dir(lua_State * L) | ||
459 | { | ||
460 | lfs_Lock *lock; | ||
461 | size_t pathl; | ||
462 | char *ln; | ||
463 | const char *lockfile = "/lockfile.lfs"; | ||
464 | const char *path = luaL_checklstring(L, 1, &pathl); | ||
465 | lock = (lfs_Lock *) lua_newuserdata(L, sizeof(lfs_Lock)); | ||
466 | ln = (char *) malloc(pathl + strlen(lockfile) + 1); | ||
467 | if (!ln) { | ||
468 | lua_pushnil(L); | ||
469 | lua_pushstring(L, strerror(errno)); | ||
470 | return 2; | ||
471 | } | ||
472 | strcpy(ln, path); | ||
473 | strcat(ln, lockfile); | ||
474 | if (symlink("lock", ln) == -1) { | ||
475 | free(ln); | ||
476 | lua_pushnil(L); | ||
477 | lua_pushstring(L, strerror(errno)); | ||
478 | return 2; | ||
479 | } | ||
480 | lock->ln = ln; | ||
481 | luaL_getmetatable(L, LOCK_METATABLE); | ||
482 | lua_setmetatable(L, -2); | ||
483 | return 1; | ||
484 | } | ||
485 | |||
486 | static int lfs_unlock_dir(lua_State * L) | ||
487 | { | ||
488 | lfs_Lock *lock = (lfs_Lock *) luaL_checkudata(L, 1, LOCK_METATABLE); | ||
489 | if (lock->ln) { | ||
490 | unlink(lock->ln); | ||
491 | free(lock->ln); | ||
492 | lock->ln = NULL; | ||
493 | } | ||
494 | return 0; | ||
495 | } | ||
496 | #endif | ||
497 | |||
498 | static int lfs_g_setmode(lua_State * L, FILE * f, int arg) | ||
499 | { | ||
500 | static const int mode[] = { _O_BINARY, _O_TEXT }; | ||
501 | static const char *const modenames[] = { "binary", "text", NULL }; | ||
502 | int op = luaL_checkoption(L, arg, NULL, modenames); | ||
503 | int res = lfs_setmode(f, mode[op]); | ||
504 | if (res != -1) { | ||
505 | int i; | ||
506 | lua_pushboolean(L, 1); | ||
507 | for (i = 0; modenames[i] != NULL; i++) { | ||
508 | if (mode[i] == res) { | ||
509 | lua_pushstring(L, modenames[i]); | ||
510 | return 2; | ||
511 | } | ||
512 | } | ||
513 | lua_pushnil(L); | ||
514 | return 2; | ||
515 | } else { | ||
516 | return pusherror(L, NULL); | ||
517 | } | ||
518 | } | ||
519 | |||
520 | static int lfs_f_setmode(lua_State * L) | ||
521 | { | ||
522 | return lfs_g_setmode(L, check_file(L, 1, "setmode"), 2); | ||
523 | } | ||
524 | |||
525 | /* | ||
526 | ** Locks a file. | ||
527 | ** @param #1 File handle. | ||
528 | ** @param #2 String with lock mode ('w'rite, 'r'ead). | ||
529 | ** @param #3 Number with start position (optional). | ||
530 | ** @param #4 Number with length (optional). | ||
531 | */ | ||
532 | static int file_lock(lua_State * L) | ||
533 | { | ||
534 | FILE *fh = check_file(L, 1, "lock"); | ||
535 | const char *mode = luaL_checkstring(L, 2); | ||
536 | const long start = (long) luaL_optinteger(L, 3, 0); | ||
537 | long len = (long) luaL_optinteger(L, 4, 0); | ||
538 | if (_file_lock(L, fh, mode, start, len, "lock")) { | ||
539 | lua_pushboolean(L, 1); | ||
540 | return 1; | ||
541 | } else { | ||
542 | lua_pushnil(L); | ||
543 | lua_pushfstring(L, "%s", strerror(errno)); | ||
544 | return 2; | ||
545 | } | ||
546 | } | ||
547 | |||
548 | |||
549 | /* | ||
550 | ** Unlocks a file. | ||
551 | ** @param #1 File handle. | ||
552 | ** @param #2 Number with start position (optional). | ||
553 | ** @param #3 Number with length (optional). | ||
554 | */ | ||
555 | static int file_unlock(lua_State * L) | ||
556 | { | ||
557 | FILE *fh = check_file(L, 1, "unlock"); | ||
558 | const long start = (long) luaL_optinteger(L, 2, 0); | ||
559 | long len = (long) luaL_optinteger(L, 3, 0); | ||
560 | if (_file_lock(L, fh, "u", start, len, "unlock")) { | ||
561 | lua_pushboolean(L, 1); | ||
562 | return 1; | ||
563 | } else { | ||
564 | lua_pushnil(L); | ||
565 | lua_pushfstring(L, "%s", strerror(errno)); | ||
566 | return 2; | ||
567 | } | ||
568 | } | ||
569 | |||
570 | |||
571 | /* | ||
572 | ** Creates a link. | ||
573 | ** @param #1 Object to link to. | ||
574 | ** @param #2 Name of link. | ||
575 | ** @param #3 True if link is symbolic (optional). | ||
576 | */ | ||
577 | static int make_link(lua_State * L) | ||
578 | { | ||
579 | const char *oldpath = luaL_checkstring(L, 1); | ||
580 | const char *newpath = luaL_checkstring(L, 2); | ||
581 | #ifndef _WIN32 | ||
582 | return pushresult(L, | ||
583 | (lua_toboolean(L, 3) ? symlink : link) (oldpath, | ||
584 | newpath), | ||
585 | NULL); | ||
586 | #else | ||
587 | int symbolic = lua_toboolean(L, 3); | ||
588 | STAT_STRUCT oldpathinfo; | ||
589 | int is_dir = 0; | ||
590 | if (STAT_FUNC(oldpath, &oldpathinfo) == 0) { | ||
591 | is_dir = S_ISDIR(oldpathinfo.st_mode) != 0; | ||
592 | } | ||
593 | if (!symbolic && is_dir) { | ||
594 | lua_pushnil(L); | ||
595 | lua_pushstring(L, | ||
596 | "hard links to directories are not supported on Windows"); | ||
597 | return 2; | ||
598 | } | ||
599 | |||
600 | int result = symbolic ? CreateSymbolicLink(newpath, oldpath, is_dir) | ||
601 | : CreateHardLink(newpath, oldpath, NULL); | ||
602 | |||
603 | if (result) { | ||
604 | return pushresult(L, result, NULL); | ||
605 | } else { | ||
606 | lua_pushnil(L); | ||
607 | lua_pushstring(L, symbolic ? "make_link CreateSymbolicLink() failed" | ||
608 | : "make_link CreateHardLink() failed"); | ||
609 | return 2; | ||
610 | } | ||
611 | #endif | ||
612 | } | ||
613 | |||
614 | |||
615 | /* | ||
616 | ** Creates a directory. | ||
617 | ** @param #1 Directory path. | ||
618 | */ | ||
619 | static int make_dir(lua_State * L) | ||
620 | { | ||
621 | const char *path = luaL_checkstring(L, 1); | ||
622 | return pushresult(L, lfs_mkdir(path), NULL); | ||
623 | } | ||
624 | |||
625 | |||
626 | /* | ||
627 | ** Removes a directory. | ||
628 | ** @param #1 Directory path. | ||
629 | */ | ||
630 | static int remove_dir(lua_State * L) | ||
631 | { | ||
632 | const char *path = luaL_checkstring(L, 1); | ||
633 | return pushresult(L, rmdir(path), NULL); | ||
634 | } | ||
635 | |||
636 | |||
637 | /* | ||
638 | ** Directory iterator | ||
639 | */ | ||
640 | static int dir_iter(lua_State * L) | ||
641 | { | ||
642 | #ifdef _WIN32 | ||
643 | struct _finddata_t c_file; | ||
644 | #else | ||
645 | struct dirent *entry; | ||
646 | #endif | ||
647 | dir_data *d = (dir_data *) luaL_checkudata(L, 1, DIR_METATABLE); | ||
648 | luaL_argcheck(L, d->closed == 0, 1, "closed directory"); | ||
649 | #ifdef _WIN32 | ||
650 | if (d->hFile == 0L) { /* first entry */ | ||
651 | if ((d->hFile = _findfirst(d->pattern, &c_file)) == -1L) { | ||
652 | lua_pushnil(L); | ||
653 | lua_pushstring(L, strerror(errno)); | ||
654 | d->closed = 1; | ||
655 | return 2; | ||
656 | } else { | ||
657 | lua_pushstring(L, c_file.name); | ||
658 | return 1; | ||
659 | } | ||
660 | } else { /* next entry */ | ||
661 | if (_findnext(d->hFile, &c_file) == -1L) { | ||
662 | /* no more entries => close directory */ | ||
663 | _findclose(d->hFile); | ||
664 | d->closed = 1; | ||
665 | return 0; | ||
666 | } else { | ||
667 | lua_pushstring(L, c_file.name); | ||
668 | return 1; | ||
669 | } | ||
670 | } | ||
671 | #else | ||
672 | if ((entry = readdir(d->dir)) != NULL) { | ||
673 | lua_pushstring(L, entry->d_name); | ||
674 | return 1; | ||
675 | } else { | ||
676 | /* no more entries => close directory */ | ||
677 | closedir(d->dir); | ||
678 | d->closed = 1; | ||
679 | return 0; | ||
680 | } | ||
681 | #endif | ||
682 | } | ||
683 | |||
684 | |||
685 | /* | ||
686 | ** Closes directory iterators | ||
687 | */ | ||
688 | static int dir_close(lua_State * L) | ||
689 | { | ||
690 | dir_data *d = (dir_data *) lua_touserdata(L, 1); | ||
691 | #ifdef _WIN32 | ||
692 | if (!d->closed && d->hFile) { | ||
693 | _findclose(d->hFile); | ||
694 | } | ||
695 | #else | ||
696 | if (!d->closed && d->dir) { | ||
697 | closedir(d->dir); | ||
698 | } | ||
699 | #endif | ||
700 | d->closed = 1; | ||
701 | return 0; | ||
702 | } | ||
703 | |||
704 | |||
705 | /* | ||
706 | ** Factory of directory iterators | ||
707 | */ | ||
708 | static int dir_iter_factory(lua_State * L) | ||
709 | { | ||
710 | const char *path = luaL_checkstring(L, 1); | ||
711 | dir_data *d; | ||
712 | lua_pushcfunction(L, dir_iter); | ||
713 | d = (dir_data *) lua_newuserdata(L, sizeof(dir_data)); | ||
714 | luaL_getmetatable(L, DIR_METATABLE); | ||
715 | lua_setmetatable(L, -2); | ||
716 | d->closed = 0; | ||
717 | #ifdef _WIN32 | ||
718 | d->hFile = 0L; | ||
719 | if (strlen(path) > MAX_PATH - 2) | ||
720 | luaL_error(L, "path too long: %s", path); | ||
721 | else | ||
722 | sprintf(d->pattern, "%s/*", path); | ||
723 | #else | ||
724 | d->dir = opendir(path); | ||
725 | if (d->dir == NULL) | ||
726 | luaL_error(L, "cannot open %s: %s", path, strerror(errno)); | ||
727 | #endif | ||
728 | #if LUA_VERSION_NUM >= 504 | ||
729 | lua_pushnil(L); | ||
730 | lua_pushvalue(L, -2); | ||
731 | return 4; | ||
732 | #else | ||
733 | return 2; | ||
734 | #endif | ||
735 | } | ||
736 | |||
737 | |||
738 | /* | ||
739 | ** Creates directory metatable. | ||
740 | */ | ||
741 | static int dir_create_meta(lua_State * L) | ||
742 | { | ||
743 | luaL_newmetatable(L, DIR_METATABLE); | ||
744 | |||
745 | /* Method table */ | ||
746 | lua_newtable(L); | ||
747 | lua_pushcfunction(L, dir_iter); | ||
748 | lua_setfield(L, -2, "next"); | ||
749 | lua_pushcfunction(L, dir_close); | ||
750 | lua_setfield(L, -2, "close"); | ||
751 | |||
752 | /* Metamethods */ | ||
753 | lua_setfield(L, -2, "__index"); | ||
754 | lua_pushcfunction(L, dir_close); | ||
755 | lua_setfield(L, -2, "__gc"); | ||
756 | |||
757 | #if LUA_VERSION_NUM >= 504 | ||
758 | lua_pushcfunction(L, dir_close); | ||
759 | lua_setfield(L, -2, "__close"); | ||
760 | #endif | ||
761 | return 1; | ||
762 | } | ||
763 | |||
764 | |||
765 | /* | ||
766 | ** Creates lock metatable. | ||
767 | */ | ||
768 | static int lock_create_meta(lua_State * L) | ||
769 | { | ||
770 | luaL_newmetatable(L, LOCK_METATABLE); | ||
771 | |||
772 | /* Method table */ | ||
773 | lua_newtable(L); | ||
774 | lua_pushcfunction(L, lfs_unlock_dir); | ||
775 | lua_setfield(L, -2, "free"); | ||
776 | |||
777 | /* Metamethods */ | ||
778 | lua_setfield(L, -2, "__index"); | ||
779 | lua_pushcfunction(L, lfs_unlock_dir); | ||
780 | lua_setfield(L, -2, "__gc"); | ||
781 | return 1; | ||
782 | } | ||
783 | |||
784 | |||
785 | /* | ||
786 | ** Convert the inode protection mode to a string. | ||
787 | */ | ||
788 | #ifdef _WIN32 | ||
789 | static const char *mode2string(unsigned short mode) | ||
790 | { | ||
791 | #else | ||
792 | static const char *mode2string(mode_t mode) | ||
793 | { | ||
794 | #endif | ||
795 | if (S_ISREG(mode)) | ||
796 | return "file"; | ||
797 | else if (S_ISDIR(mode)) | ||
798 | return "directory"; | ||
799 | else if (S_ISLNK(mode)) | ||
800 | return "link"; | ||
801 | else if (S_ISSOCK(mode)) | ||
802 | return "socket"; | ||
803 | else if (S_ISFIFO(mode)) | ||
804 | return "named pipe"; | ||
805 | else if (S_ISCHR(mode)) | ||
806 | return "char device"; | ||
807 | else if (S_ISBLK(mode)) | ||
808 | return "block device"; | ||
809 | else | ||
810 | return "other"; | ||
811 | } | ||
812 | |||
813 | |||
814 | /* | ||
815 | ** Set access time and modification values for a file. | ||
816 | ** @param #1 File path. | ||
817 | ** @param #2 Access time in seconds, current time is used if missing. | ||
818 | ** @param #3 Modification time in seconds, access time is used if missing. | ||
819 | */ | ||
820 | static int file_utime(lua_State * L) | ||
821 | { | ||
822 | const char *file = luaL_checkstring(L, 1); | ||
823 | struct utimbuf utb, *buf; | ||
824 | |||
825 | if (lua_gettop(L) == 1) /* set to current date/time */ | ||
826 | buf = NULL; | ||
827 | else { | ||
828 | utb.actime = (time_t) luaL_optnumber(L, 2, 0); | ||
829 | utb.modtime = (time_t) luaL_optinteger(L, 3, utb.actime); | ||
830 | buf = &utb; | ||
831 | } | ||
832 | |||
833 | return pushresult(L, utime(file, buf), NULL); | ||
834 | } | ||
835 | |||
836 | |||
837 | /* inode protection mode */ | ||
838 | static void push_st_mode(lua_State * L, STAT_STRUCT * info) | ||
839 | { | ||
840 | lua_pushstring(L, mode2string(info->st_mode)); | ||
841 | } | ||
842 | |||
843 | /* device inode resides on */ | ||
844 | static void push_st_dev(lua_State * L, STAT_STRUCT * info) | ||
845 | { | ||
846 | lua_pushinteger(L, (lua_Integer) info->st_dev); | ||
847 | } | ||
848 | |||
849 | /* inode's number */ | ||
850 | static void push_st_ino(lua_State * L, STAT_STRUCT * info) | ||
851 | { | ||
852 | lua_pushinteger(L, (lua_Integer) info->st_ino); | ||
853 | } | ||
854 | |||
855 | /* number of hard links to the file */ | ||
856 | static void push_st_nlink(lua_State * L, STAT_STRUCT * info) | ||
857 | { | ||
858 | lua_pushinteger(L, (lua_Integer) info->st_nlink); | ||
859 | } | ||
860 | |||
861 | /* user-id of owner */ | ||
862 | static void push_st_uid(lua_State * L, STAT_STRUCT * info) | ||
863 | { | ||
864 | lua_pushinteger(L, (lua_Integer) info->st_uid); | ||
865 | } | ||
866 | |||
867 | /* group-id of owner */ | ||
868 | static void push_st_gid(lua_State * L, STAT_STRUCT * info) | ||
869 | { | ||
870 | lua_pushinteger(L, (lua_Integer) info->st_gid); | ||
871 | } | ||
872 | |||
873 | /* device type, for special file inode */ | ||
874 | static void push_st_rdev(lua_State * L, STAT_STRUCT * info) | ||
875 | { | ||
876 | lua_pushinteger(L, (lua_Integer) info->st_rdev); | ||
877 | } | ||
878 | |||
879 | /* time of last access */ | ||
880 | static void push_st_atime(lua_State * L, STAT_STRUCT * info) | ||
881 | { | ||
882 | lua_pushinteger(L, (lua_Integer) info->st_atime); | ||
883 | } | ||
884 | |||
885 | /* time of last data modification */ | ||
886 | static void push_st_mtime(lua_State * L, STAT_STRUCT * info) | ||
887 | { | ||
888 | lua_pushinteger(L, (lua_Integer) info->st_mtime); | ||
889 | } | ||
890 | |||
891 | /* time of last file status change */ | ||
892 | static void push_st_ctime(lua_State * L, STAT_STRUCT * info) | ||
893 | { | ||
894 | lua_pushinteger(L, (lua_Integer) info->st_ctime); | ||
895 | } | ||
896 | |||
897 | /* file size, in bytes */ | ||
898 | static void push_st_size(lua_State * L, STAT_STRUCT * info) | ||
899 | { | ||
900 | lua_pushinteger(L, (lua_Integer) info->st_size); | ||
901 | } | ||
902 | |||
903 | #ifndef _WIN32 | ||
904 | /* blocks allocated for file */ | ||
905 | static void push_st_blocks(lua_State * L, STAT_STRUCT * info) | ||
906 | { | ||
907 | lua_pushinteger(L, (lua_Integer) info->st_blocks); | ||
908 | } | ||
909 | |||
910 | /* optimal file system I/O blocksize */ | ||
911 | static void push_st_blksize(lua_State * L, STAT_STRUCT * info) | ||
912 | { | ||
913 | lua_pushinteger(L, (lua_Integer) info->st_blksize); | ||
914 | } | ||
915 | #endif | ||
916 | |||
917 | /* | ||
918 | ** Convert the inode protection mode to a permission list. | ||
919 | */ | ||
920 | |||
921 | #ifdef _WIN32 | ||
922 | static const char *perm2string(unsigned short mode) | ||
923 | { | ||
924 | static char perms[10] = "---------"; | ||
925 | int i; | ||
926 | for (i = 0; i < 9; i++) | ||
927 | perms[i] = '-'; | ||
928 | if (mode & _S_IREAD) { | ||
929 | perms[0] = 'r'; | ||
930 | perms[3] = 'r'; | ||
931 | perms[6] = 'r'; | ||
932 | } | ||
933 | if (mode & _S_IWRITE) { | ||
934 | perms[1] = 'w'; | ||
935 | perms[4] = 'w'; | ||
936 | perms[7] = 'w'; | ||
937 | } | ||
938 | if (mode & _S_IEXEC) { | ||
939 | perms[2] = 'x'; | ||
940 | perms[5] = 'x'; | ||
941 | perms[8] = 'x'; | ||
942 | } | ||
943 | return perms; | ||
944 | } | ||
945 | #else | ||
946 | static const char *perm2string(mode_t mode) | ||
947 | { | ||
948 | static char perms[10] = "---------"; | ||
949 | int i; | ||
950 | for (i = 0; i < 9; i++) | ||
951 | perms[i] = '-'; | ||
952 | if (mode & S_IRUSR) | ||
953 | perms[0] = 'r'; | ||
954 | if (mode & S_IWUSR) | ||
955 | perms[1] = 'w'; | ||
956 | if (mode & S_IXUSR) | ||
957 | perms[2] = 'x'; | ||
958 | if (mode & S_IRGRP) | ||
959 | perms[3] = 'r'; | ||
960 | if (mode & S_IWGRP) | ||
961 | perms[4] = 'w'; | ||
962 | if (mode & S_IXGRP) | ||
963 | perms[5] = 'x'; | ||
964 | if (mode & S_IROTH) | ||
965 | perms[6] = 'r'; | ||
966 | if (mode & S_IWOTH) | ||
967 | perms[7] = 'w'; | ||
968 | if (mode & S_IXOTH) | ||
969 | perms[8] = 'x'; | ||
970 | return perms; | ||
971 | } | ||
972 | #endif | ||
973 | |||
974 | /* permssions string */ | ||
975 | static void push_st_perm(lua_State * L, STAT_STRUCT * info) | ||
976 | { | ||
977 | lua_pushstring(L, perm2string(info->st_mode)); | ||
978 | } | ||
979 | |||
980 | typedef void (*_push_function)(lua_State * L, STAT_STRUCT * info); | ||
981 | |||
982 | struct _stat_members { | ||
983 | const char *name; | ||
984 | _push_function push; | ||
985 | }; | ||
986 | |||
987 | struct _stat_members members[] = { | ||
988 | { "mode", push_st_mode }, | ||
989 | { "dev", push_st_dev }, | ||
990 | { "ino", push_st_ino }, | ||
991 | { "nlink", push_st_nlink }, | ||
992 | { "uid", push_st_uid }, | ||
993 | { "gid", push_st_gid }, | ||
994 | { "rdev", push_st_rdev }, | ||
995 | { "access", push_st_atime }, | ||
996 | { "modification", push_st_mtime }, | ||
997 | { "change", push_st_ctime }, | ||
998 | { "size", push_st_size }, | ||
999 | { "permissions", push_st_perm }, | ||
1000 | #ifndef _WIN32 | ||
1001 | { "blocks", push_st_blocks }, | ||
1002 | { "blksize", push_st_blksize }, | ||
1003 | #endif | ||
1004 | { NULL, NULL } | ||
1005 | }; | ||
1006 | |||
1007 | /* | ||
1008 | ** Get file or symbolic link information | ||
1009 | */ | ||
1010 | static int _file_info_(lua_State * L, | ||
1011 | int (*st)(const char *, STAT_STRUCT *)) | ||
1012 | { | ||
1013 | STAT_STRUCT info; | ||
1014 | const char *file = luaL_checkstring(L, 1); | ||
1015 | int i; | ||
1016 | |||
1017 | if (st(file, &info)) { | ||
1018 | lua_pushnil(L); | ||
1019 | lua_pushfstring(L, "cannot obtain information from file '%s': %s", | ||
1020 | file, strerror(errno)); | ||
1021 | lua_pushinteger(L, errno); | ||
1022 | return 3; | ||
1023 | } | ||
1024 | if (lua_isstring(L, 2)) { | ||
1025 | const char *member = lua_tostring(L, 2); | ||
1026 | for (i = 0; members[i].name; i++) { | ||
1027 | if (strcmp(members[i].name, member) == 0) { | ||
1028 | /* push member value and return */ | ||
1029 | members[i].push(L, &info); | ||
1030 | return 1; | ||
1031 | } | ||
1032 | } | ||
1033 | /* member not found */ | ||
1034 | return luaL_error(L, "invalid attribute name '%s'", member); | ||
1035 | } | ||
1036 | /* creates a table if none is given, removes extra arguments */ | ||
1037 | lua_settop(L, 2); | ||
1038 | if (!lua_istable(L, 2)) { | ||
1039 | lua_newtable(L); | ||
1040 | } | ||
1041 | /* stores all members in table on top of the stack */ | ||
1042 | for (i = 0; members[i].name; i++) { | ||
1043 | lua_pushstring(L, members[i].name); | ||
1044 | members[i].push(L, &info); | ||
1045 | lua_rawset(L, -3); | ||
1046 | } | ||
1047 | return 1; | ||
1048 | } | ||
1049 | |||
1050 | |||
1051 | /* | ||
1052 | ** Get file information using stat. | ||
1053 | */ | ||
1054 | static int file_info(lua_State * L) | ||
1055 | { | ||
1056 | return _file_info_(L, STAT_FUNC); | ||
1057 | } | ||
1058 | |||
1059 | |||
1060 | /* | ||
1061 | ** Push the symlink target to the top of the stack. | ||
1062 | ** Assumes the file name is at position 1 of the stack. | ||
1063 | ** Returns 1 if successful (with the target on top of the stack), | ||
1064 | ** 0 on failure (with stack unchanged, and errno set). | ||
1065 | */ | ||
1066 | static int push_link_target(lua_State * L) | ||
1067 | { | ||
1068 | const char *file = luaL_checkstring(L, 1); | ||
1069 | #ifdef _WIN32 | ||
1070 | HANDLE h = CreateFile(file, GENERIC_READ, | ||
1071 | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, | ||
1072 | OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | ||
1073 | if (h == INVALID_HANDLE_VALUE) { | ||
1074 | return lfs_win32_pusherror(L); | ||
1075 | } | ||
1076 | #endif | ||
1077 | char *target = NULL; | ||
1078 | int tsize, size = 256; /* size = initial buffer capacity */ | ||
1079 | int ok = 0; | ||
1080 | while (!ok) { | ||
1081 | char *target2 = realloc(target, size); | ||
1082 | if (!target2) { /* failed to allocate */ | ||
1083 | break; | ||
1084 | } | ||
1085 | target = target2; | ||
1086 | #ifdef _WIN32 | ||
1087 | tsize = GetFinalPathNameByHandle(h, target, size, FILE_NAME_OPENED); | ||
1088 | #else | ||
1089 | tsize = readlink(file, target, size); | ||
1090 | #endif | ||
1091 | if (tsize < 0) { /* a readlink() error occurred */ | ||
1092 | break; | ||
1093 | } | ||
1094 | if (tsize < size) { | ||
1095 | #ifdef _WIN32 | ||
1096 | if (tsize > 4 && strncmp(target, "\\\\?\\", 4) == 0) { | ||
1097 | memmove_s(target, tsize - 3, target + 4, tsize - 3); | ||
1098 | tsize -= 4; | ||
1099 | } | ||
1100 | #endif | ||
1101 | ok = 1; | ||
1102 | break; | ||
1103 | } | ||
1104 | /* possibly truncated readlink() result, double size and retry */ | ||
1105 | size *= 2; | ||
1106 | } | ||
1107 | if (ok) { | ||
1108 | target[tsize] = '\0'; | ||
1109 | lua_pushlstring(L, target, tsize); | ||
1110 | } | ||
1111 | #ifdef _WIN32 | ||
1112 | CloseHandle(h); | ||
1113 | #endif | ||
1114 | free(target); | ||
1115 | return ok; | ||
1116 | } | ||
1117 | |||
1118 | /* | ||
1119 | ** Get symbolic link information using lstat. | ||
1120 | */ | ||
1121 | static int link_info(lua_State * L) | ||
1122 | { | ||
1123 | int ret; | ||
1124 | if (lua_isstring(L, 2) && (strcmp(lua_tostring(L, 2), "target") == 0)) { | ||
1125 | int ok = push_link_target(L); | ||
1126 | return ok ? 1 : pusherror(L, "could not obtain link target"); | ||
1127 | } | ||
1128 | ret = _file_info_(L, LSTAT_FUNC); | ||
1129 | if (ret == 1 && lua_type(L, -1) == LUA_TTABLE) { | ||
1130 | int ok = push_link_target(L); | ||
1131 | if (ok) { | ||
1132 | lua_setfield(L, -2, "target"); | ||
1133 | } | ||
1134 | } | ||
1135 | return ret; | ||
1136 | } | ||
1137 | |||
1138 | |||
1139 | /* | ||
1140 | ** Assumes the table is on top of the stack. | ||
1141 | */ | ||
1142 | static void set_info(lua_State * L) | ||
1143 | { | ||
1144 | lua_pushliteral(L, "Copyright (C) 2003-2017 Kepler Project"); | ||
1145 | lua_setfield(L, -2, "_COPYRIGHT"); | ||
1146 | lua_pushliteral(L, | ||
1147 | "LuaFileSystem is a Lua library developed to complement " | ||
1148 | "the set of functions related to file systems offered by " | ||
1149 | "the standard Lua distribution"); | ||
1150 | lua_setfield(L, -2, "_DESCRIPTION"); | ||
1151 | lua_pushliteral(L, "LuaFileSystem " LFS_VERSION); | ||
1152 | lua_setfield(L, -2, "_VERSION"); | ||
1153 | } | ||
1154 | |||
1155 | |||
1156 | static const struct luaL_Reg fslib[] = { | ||
1157 | { "attributes", file_info }, | ||
1158 | { "chdir", change_dir }, | ||
1159 | { "currentdir", get_dir }, | ||
1160 | { "dir", dir_iter_factory }, | ||
1161 | { "link", make_link }, | ||
1162 | { "lock", file_lock }, | ||
1163 | { "mkdir", make_dir }, | ||
1164 | { "rmdir", remove_dir }, | ||
1165 | { "symlinkattributes", link_info }, | ||
1166 | { "setmode", lfs_f_setmode }, | ||
1167 | { "touch", file_utime }, | ||
1168 | { "unlock", file_unlock }, | ||
1169 | { "lock_dir", lfs_lock_dir }, | ||
1170 | { NULL, NULL }, | ||
1171 | }; | ||
1172 | |||
1173 | LFS_EXPORT int luaopen_lfs(lua_State * L) | ||
1174 | { | ||
1175 | dir_create_meta(L); | ||
1176 | lock_create_meta(L); | ||
1177 | new_lib(L, fslib); | ||
1178 | lua_pushvalue(L, -1); | ||
1179 | lua_setglobal(L, LFS_LIBNAME); | ||
1180 | set_info(L); | ||
1181 | return 1; | ||
1182 | } | ||
diff --git a/vendor/luafilesystem/src/lfs.def b/vendor/luafilesystem/src/lfs.def new file mode 100644 index 00000000..bd8c847a --- /dev/null +++ b/vendor/luafilesystem/src/lfs.def | |||
@@ -0,0 +1,4 @@ | |||
1 | LIBRARY lfs.dll | ||
2 | VERSION 1.8 | ||
3 | EXPORTS | ||
4 | luaopen_lfs | ||
diff --git a/vendor/luafilesystem/src/lfs.h b/vendor/luafilesystem/src/lfs.h new file mode 100644 index 00000000..13b60a91 --- /dev/null +++ b/vendor/luafilesystem/src/lfs.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | ** LuaFileSystem | ||
3 | ** Copyright Kepler Project 2003 - 2020 | ||
4 | ** (http://keplerproject.github.io/luafilesystem) | ||
5 | */ | ||
6 | |||
7 | /* Define 'chdir' for systems that do not implement it */ | ||
8 | #ifdef NO_CHDIR | ||
9 | #define chdir(p) (-1) | ||
10 | #define chdir_error "Function 'chdir' not provided by system" | ||
11 | #else | ||
12 | #define chdir_error strerror(errno) | ||
13 | #endif | ||
14 | |||
15 | #ifdef _WIN32 | ||
16 | #define chdir(p) (_chdir(p)) | ||
17 | #define getcwd(d, s) (_getcwd(d, s)) | ||
18 | #define rmdir(p) (_rmdir(p)) | ||
19 | #define LFS_EXPORT __declspec (dllexport) | ||
20 | #ifndef fileno | ||
21 | #define fileno(f) (_fileno(f)) | ||
22 | #endif | ||
23 | #else | ||
24 | #define LFS_EXPORT | ||
25 | #endif | ||
26 | |||
27 | #ifdef __cplusplus | ||
28 | extern "C" { | ||
29 | #endif | ||
30 | |||
31 | LFS_EXPORT int luaopen_lfs(lua_State * L); | ||
32 | |||
33 | #ifdef __cplusplus | ||
34 | } | ||
35 | #endif | ||
diff --git a/vendor/luasec/.gitignore b/vendor/luasec/.gitignore new file mode 100644 index 00000000..355518b2 --- /dev/null +++ b/vendor/luasec/.gitignore | |||
@@ -0,0 +1,3 @@ | |||
1 | /src/*.o | ||
2 | /src/luasocket/*.o | ||
3 | /*.dll | ||
diff --git a/vendor/luasec/CHANGELOG b/vendor/luasec/CHANGELOG new file mode 100644 index 00000000..f7c0a780 --- /dev/null +++ b/vendor/luasec/CHANGELOG | |||
@@ -0,0 +1,257 @@ | |||
1 | -------------------------------------------------------------------------------- | ||
2 | LuaSec 1.3.2 | ||
3 | --------------- | ||
4 | This version includes: | ||
5 | |||
6 | * Fix: place EAI_OVERFLOW inside macro, unbreak build on <10.7 (Sergey Fedorov) | ||
7 | * Fix: Expand workaround for zero errno to OpenSSL 3.0.x (Kim Alvefur) | ||
8 | * Fix: reset block timeout at send or receive (MartinDahlberg) | ||
9 | |||
10 | -------------------------------------------------------------------------------- | ||
11 | LuaSec 1.3.1 | ||
12 | --------------- | ||
13 | This version includes: | ||
14 | |||
15 | * Fix: check if PSK is available | ||
16 | |||
17 | -------------------------------------------------------------------------------- | ||
18 | LuaSec 1.3.0 | ||
19 | --------------- | ||
20 | This version includes: | ||
21 | |||
22 | * Add :getlocalchain() + :getlocalcertificate() to mirror the peer methods (@mwild1) | ||
23 | * Add Pre-Shared Key (PSK) support (@jclab-joseph) | ||
24 | |||
25 | -------------------------------------------------------------------------------- | ||
26 | LuaSec 1.2.0 | ||
27 | --------------- | ||
28 | This version includes: | ||
29 | |||
30 | * Add key material export method | ||
31 | * Backguard compat for openssl on providers, like LTS linuxes | ||
32 | |||
33 | -------------------------------------------------------------------------------- | ||
34 | LuaSec 1.1.0 | ||
35 | --------------- | ||
36 | This version includes: | ||
37 | |||
38 | * Fix missing DANE flag | ||
39 | * Remove unused parameter in https.lua | ||
40 | |||
41 | -------------------------------------------------------------------------------- | ||
42 | LuaSec 1.0.2 | ||
43 | --------------- | ||
44 | This version includes: | ||
45 | |||
46 | * Fix handle SSL_send SYSCALL error without errno | ||
47 | * Fix off by one in cert:validat(notafter) | ||
48 | * Fix meth_get_{sinagure => signature}_name function name | ||
49 | * Fix update the Lua state reference on the selected SSL context after SNI | ||
50 | * Fix ignore SSL_OP_BIT(n) macro and update option.c | ||
51 | |||
52 | -------------------------------------------------------------------------------- | ||
53 | LuaSec 1.0.1 | ||
54 | --------------- | ||
55 | This version includes: | ||
56 | |||
57 | |||
58 | * Fix luaL_buffinit() can use the stack and broke buffer_meth_receive() | ||
59 | |||
60 | -------------------------------------------------------------------------------- | ||
61 | LuaSec 1.0 | ||
62 | --------------- | ||
63 | This version includes: | ||
64 | |||
65 | |||
66 | * Add cert:getsignaturename() | ||
67 | |||
68 | -------------------------------------------------------------------------------- | ||
69 | LuaSec 0.9 | ||
70 | --------------- | ||
71 | This version includes: | ||
72 | |||
73 | |||
74 | * Add DNS-based Authentication of Named Entities (DANE) support | ||
75 | * Add __close() metamethod | ||
76 | * Fix deprecation warnings with OpenSSL 1.1 | ||
77 | * Fix special case listing of TLS 1.3 EC curves | ||
78 | * Fix general_name leak in cert:extensions() | ||
79 | * Fix unexported 'ssl.config' table | ||
80 | * Replace $(LD) with $(CCLD) variable | ||
81 | * Remove multiple definitions of 'ssl_options' variable | ||
82 | * Use tag in git format: v0.9 | ||
83 | |||
84 | -------------------------------------------------------------------------------- | ||
85 | LuaSec 0.8.2 | ||
86 | --------------- | ||
87 | This version includes: | ||
88 | |||
89 | * Fix unexported 'ssl.config' table (backported) | ||
90 | |||
91 | -------------------------------------------------------------------------------- | ||
92 | LuaSec 0.8.1 | ||
93 | --------------- | ||
94 | This version includes: | ||
95 | |||
96 | * Fix general_name leak in cert:extensions() (backported) | ||
97 | |||
98 | -------------------------------------------------------------------------------- | ||
99 | LuaSec 0.8 | ||
100 | --------------- | ||
101 | This version includes: | ||
102 | |||
103 | * Add support to ALPN | ||
104 | * Add support to TLS 1.3 | ||
105 | * Add support to multiple certificates | ||
106 | * Add timeout to https module (https.TIMEOUT) | ||
107 | * Drop support to SSL 3.0 | ||
108 | * Drop support to TLS 1.0 from https module | ||
109 | * Fix invalid reference to Lua state | ||
110 | * Fix memory leak when get certficate extensions | ||
111 | |||
112 | -------------------------------------------------------------------------------- | ||
113 | LuaSec 0.7.2 | ||
114 | --------------- | ||
115 | This version includes: | ||
116 | |||
117 | * Fix unexported 'ssl.config' table (backported) | ||
118 | |||
119 | -------------------------------------------------------------------------------- | ||
120 | LuaSec 0.7.1 | ||
121 | --------------- | ||
122 | This version includes: | ||
123 | |||
124 | * Fix general_name leak in cert:extensions() (backported) | ||
125 | |||
126 | -------------------------------------------------------------------------------- | ||
127 | LuaSec 0.7 | ||
128 | --------------- | ||
129 | LuaSec depends on OpenSSL, and integrates with LuaSocket to make it | ||
130 | easy to add secure connections to any Lua applications or scripts. | ||
131 | |||
132 | Documentation: https://github.com/brunoos/luasec/wiki | ||
133 | |||
134 | This version includes: | ||
135 | |||
136 | * Add support to OpenSSL 1.1.0 | ||
137 | * Add support to elliptic curves list | ||
138 | * Add ssl.config that exports some OpenSSL information | ||
139 | * Add integration with luaossl | ||
140 | |||
141 | -------------------------------------------------------------------------------- | ||
142 | LuaSec 0.6 | ||
143 | ------------ | ||
144 | LuaSec depends on OpenSSL, and integrates with LuaSocket to make it | ||
145 | easy to add secure connections to any Lua applications or scripts. | ||
146 | |||
147 | Documentation: https://github.com/brunoos/luasec/wiki | ||
148 | |||
149 | This version includes: | ||
150 | |||
151 | * Lua 5.2 and 5.3 compatibility | ||
152 | |||
153 | * Context module: | ||
154 | - Add ctx:checkkey() | ||
155 | |||
156 | * SSL module: | ||
157 | - Add conn:sni() and conn:getsniname() | ||
158 | |||
159 | * Context options: | ||
160 | - Add "any" protocol ("sslv23" is deprecated) | ||
161 | |||
162 | * HTTPS module: | ||
163 | - Using "any" protocol without SSLv2/SSLv3, by default | ||
164 | |||
165 | * X509 module: | ||
166 | - Human readable IP address | ||
167 | - Add cert:issued() | ||
168 | - Add cert:pubkey() | ||
169 | |||
170 | * Some bug fixes | ||
171 | |||
172 | |||
173 | => Thanks to everyone who collaborate with LuaSec <= | ||
174 | |||
175 | -------------------------------------------------------------------------------- | ||
176 | LuaSec 0.5 | ||
177 | ------------ | ||
178 | LuaSec depends on OpenSSL, and integrates with LuaSocket to make it | ||
179 | easy to add secure connections to any Lua applications or scripts. | ||
180 | |||
181 | This version includes: | ||
182 | |||
183 | * A new certificate (X509) API, which supports: | ||
184 | - Reading the subject (identity) and issuer of the certificate. | ||
185 | - Reading various X509 extensions, including email and dnsName. | ||
186 | - Converting certificates to and from the standard ASCII PEM | ||
187 | format. | ||
188 | - Generating the fingerprint/digest of a certificate (using SHA1, | ||
189 | SHA256 or SHA512). | ||
190 | - Reading the certificate's expiration, serial number, and other | ||
191 | info. | ||
192 | |||
193 | * The ability to get more detailed information from OpenSSL about | ||
194 | why a certificate failed verification, for each certificate in the | ||
195 | chain. | ||
196 | |||
197 | * Flags to force acceptance of invalid certificates, e.g. to allow | ||
198 | the use of self-signed certificates in a Trust On First Use model. | ||
199 | |||
200 | * Flags to control checking CRLs for certificate revocation status. | ||
201 | |||
202 | * Support for ECDH cipher suites. | ||
203 | |||
204 | * An API to get the TLS 'finished' messages used for SASL channel | ||
205 | binding (e.g. the SCRAM PLUS mechanisms). | ||
206 | |||
207 | The work in this release was undertaken by Kim Alvefur, Paul Aurich, | ||
208 | Tobias Markmann, Bruno Silvestre and Matthew Wild. | ||
209 | |||
210 | -------------------------------------------------------------------------------- | ||
211 | LuaSec 0.4.1 | ||
212 | ------------ | ||
213 | - SSL options updated --- based on OpenSSL 1.0.0d. | ||
214 | - Activate SSL_MODE_RELEASE_BUFFERS by default if it is available. | ||
215 | (thanks Prosody project) | ||
216 | |||
217 | --------------------------------------------------------------------------------- | ||
218 | LuaSec 0.4 | ||
219 | ------------ | ||
220 | - Add option 'no_ticket' (included in OpenSSL 0.9.8f). | ||
221 | - Add HTTPS module. (thanks Tomas Guisasola and Pablo Musa) | ||
222 | |||
223 | -------------------------------------------------------------------------------- | ||
224 | LuaSec 0.3.3 | ||
225 | ------------ | ||
226 | - BUG: Clear the error queue before call I/O functions (see SSL_get_error | ||
227 | manual). | ||
228 | (thanks Matthew Wild) | ||
229 | |||
230 | -------------------------------------------------------------------------------- | ||
231 | LuaSec 0.3.2 | ||
232 | ------------ | ||
233 | - BUG: Windows uses a different way to report socket error. | ||
234 | (thanks Sebastien Perin) | ||
235 | |||
236 | -------------------------------------------------------------------------------- | ||
237 | LuaSec 0.3.1 | ||
238 | ------------ | ||
239 | - BUG: receive("a") returns 'closed' error instead of the content when the | ||
240 | SSL/TLS connection is shut down cleanly. (thanks Matthias Diener) | ||
241 | |||
242 | -------------------------------------------------------------------------------- | ||
243 | LuaSec 0.3 | ||
244 | ---------- | ||
245 | - Add functions ssl.rawcontext() and ssl.rawconnection() | ||
246 | - Add support to encrypted key password. (thanks Norbert Kiesel) | ||
247 | |||
248 | -------------------------------------------------------------------------------- | ||
249 | LuaSec 0.2.1 | ||
250 | ------------ | ||
251 | - 'key' and 'certificate' configurations become optional. (thanks René Rebe) | ||
252 | - Add '_VERSION' variable to module. | ||
253 | |||
254 | -------------------------------------------------------------------------------- | ||
255 | LuaSec 0.2 | ||
256 | ---------- | ||
257 | Initial version | ||
diff --git a/vendor/luasec/INSTALL b/vendor/luasec/INSTALL new file mode 100644 index 00000000..07b94df8 --- /dev/null +++ b/vendor/luasec/INSTALL | |||
@@ -0,0 +1,39 @@ | |||
1 | LuaSec 1.3.2 | ||
2 | ------------ | ||
3 | |||
4 | * OpenSSL options: | ||
5 | |||
6 | By default, this version includes options for OpenSSL 3.0.8 | ||
7 | |||
8 | If you need to generate the options for a different version of OpenSSL: | ||
9 | |||
10 | $ cd src | ||
11 | $ lua options.lua -g /usr/include/openssl/ssl.h > options.c | ||
12 | |||
13 | -------------------------------------------------------------------------------- | ||
14 | |||
15 | * On Linux, BSD, and Mac OS X: | ||
16 | |||
17 | - Edit 'Makefile' | ||
18 | * Inform the path to where install the Lua modules (LUAPATH) and binaries | ||
19 | modules (LUACPATH) | ||
20 | * If Lua or OpenSSL are not in the default path, set the | ||
21 | variables INCDIR and LIBDIR. | ||
22 | * For Mac OS X, set the variable MACOSX_VERSION. | ||
23 | |||
24 | - Use 'make <platform>' to compile | ||
25 | * Platforms: linux, bsd, or macosx | ||
26 | |||
27 | - Use 'make install' to install the modules. | ||
28 | |||
29 | -------------------------------------------------------------------------------- | ||
30 | |||
31 | * On Windows: | ||
32 | |||
33 | - Use the Visual C++ project to compile the library. | ||
34 | |||
35 | - Copy the 'ssl.lua' file to some place in your LUA_PATH. | ||
36 | |||
37 | - Copy the 'ssl.dll' file to some place in your LUA_CPATH. | ||
38 | |||
39 | - Create a directory 'ssl' in your LUA_PATH and copy 'https.lua' to it. | ||
diff --git a/vendor/luasec/LICENSE b/vendor/luasec/LICENSE new file mode 100644 index 00000000..09df9964 --- /dev/null +++ b/vendor/luasec/LICENSE | |||
@@ -0,0 +1,21 @@ | |||
1 | LuaSec 1.3.2 license | ||
2 | Copyright (C) 2006-2023 Bruno Silvestre, UFG | ||
3 | |||
4 | Permission is hereby granted, free of charge, to any person obtaining | ||
5 | a copy of this software and associated documentation files (the | ||
6 | "Software"), to deal in the Software without restriction, including | ||
7 | without limitation the rights to use, copy, modify, merge, publish, | ||
8 | distribute, sublicense, and/or sell copies of the Software, and to | ||
9 | permit persons to whom the Software is furnished to do so, subject to | ||
10 | the following conditions: | ||
11 | |||
12 | The above copyright notice and this permission notice shall be | ||
13 | included in all copies or substantial portions of the Software. | ||
14 | |||
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||
19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
diff --git a/vendor/luasec/README.md b/vendor/luasec/README.md new file mode 100644 index 00000000..afdce4ee --- /dev/null +++ b/vendor/luasec/README.md | |||
@@ -0,0 +1,6 @@ | |||
1 | LuaSec 1.3.2 | ||
2 | =============== | ||
3 | LuaSec depends on OpenSSL, and integrates with LuaSocket to make it | ||
4 | easy to add secure connections to any Lua applications or scripts. | ||
5 | |||
6 | Documentation: https://github.com/brunoos/luasec/wiki | ||
diff --git a/vendor/luasec/luasec-1.3.2-1.rockspec b/vendor/luasec/luasec-1.3.2-1.rockspec new file mode 100644 index 00000000..a6a36d78 --- /dev/null +++ b/vendor/luasec/luasec-1.3.2-1.rockspec | |||
@@ -0,0 +1,105 @@ | |||
1 | package = "LuaSec" | ||
2 | version = "1.3.2-1" | ||
3 | source = { | ||
4 | url = "git+https://github.com/brunoos/luasec", | ||
5 | tag = "v1.3.2", | ||
6 | } | ||
7 | description = { | ||
8 | summary = "A binding for OpenSSL library to provide TLS/SSL communication over LuaSocket.", | ||
9 | detailed = "This version delegates to LuaSocket the TCP connection establishment between the client and server. Then LuaSec uses this connection to start a secure TLS/SSL session.", | ||
10 | homepage = "https://github.com/brunoos/luasec/wiki", | ||
11 | license = "MIT" | ||
12 | } | ||
13 | dependencies = { | ||
14 | "lua >= 5.1", "luasocket" | ||
15 | } | ||
16 | external_dependencies = { | ||
17 | platforms = { | ||
18 | unix = { | ||
19 | OPENSSL = { | ||
20 | header = "openssl/ssl.h", | ||
21 | library = "ssl" | ||
22 | } | ||
23 | }, | ||
24 | windows = { | ||
25 | OPENSSL = { | ||
26 | header = "openssl/ssl.h", | ||
27 | } | ||
28 | }, | ||
29 | } | ||
30 | } | ||
31 | build = { | ||
32 | type = "builtin", | ||
33 | copy_directories = { | ||
34 | "samples" | ||
35 | }, | ||
36 | platforms = { | ||
37 | unix = { | ||
38 | install = { | ||
39 | lib = { | ||
40 | "ssl.so" | ||
41 | }, | ||
42 | lua = { | ||
43 | "src/ssl.lua", ['ssl.https'] = "src/https.lua" | ||
44 | } | ||
45 | }, | ||
46 | modules = { | ||
47 | ssl = { | ||
48 | defines = { | ||
49 | "WITH_LUASOCKET", "LUASOCKET_DEBUG", | ||
50 | }, | ||
51 | incdirs = { | ||
52 | "$(OPENSSL_INCDIR)", "src/", "src/luasocket", | ||
53 | }, | ||
54 | libdirs = { | ||
55 | "$(OPENSSL_LIBDIR)" | ||
56 | }, | ||
57 | libraries = { | ||
58 | "ssl", "crypto" | ||
59 | }, | ||
60 | sources = { | ||
61 | "src/options.c", "src/config.c", "src/ec.c", | ||
62 | "src/x509.c", "src/context.c", "src/ssl.c", | ||
63 | "src/luasocket/buffer.c", "src/luasocket/io.c", | ||
64 | "src/luasocket/timeout.c", "src/luasocket/usocket.c" | ||
65 | } | ||
66 | } | ||
67 | } | ||
68 | }, | ||
69 | windows = { | ||
70 | install = { | ||
71 | lib = { | ||
72 | "ssl.dll" | ||
73 | }, | ||
74 | lua = { | ||
75 | "src/ssl.lua", ['ssl.https'] = "src/https.lua" | ||
76 | } | ||
77 | }, | ||
78 | modules = { | ||
79 | ssl = { | ||
80 | defines = { | ||
81 | "WIN32", "NDEBUG", "_WINDOWS", "_USRDLL", "LSEC_EXPORTS", "BUFFER_DEBUG", "LSEC_API=__declspec(dllexport)", | ||
82 | "WITH_LUASOCKET", "LUASOCKET_DEBUG", | ||
83 | "LUASEC_INET_NTOP", "WINVER=0x0501", "_WIN32_WINNT=0x0501", "NTDDI_VERSION=0x05010300" | ||
84 | }, | ||
85 | libdirs = { | ||
86 | "$(OPENSSL_LIBDIR)", | ||
87 | "$(OPENSSL_BINDIR)", | ||
88 | }, | ||
89 | libraries = { | ||
90 | "libssl", "libcrypto", "ws2_32" | ||
91 | }, | ||
92 | incdirs = { | ||
93 | "$(OPENSSL_INCDIR)", "src/", "src/luasocket" | ||
94 | }, | ||
95 | sources = { | ||
96 | "src/options.c", "src/config.c", "src/ec.c", | ||
97 | "src/x509.c", "src/context.c", "src/ssl.c", | ||
98 | "src/luasocket/buffer.c", "src/luasocket/io.c", | ||
99 | "src/luasocket/timeout.c", "src/luasocket/wsocket.c" | ||
100 | } | ||
101 | } | ||
102 | } | ||
103 | } | ||
104 | } | ||
105 | } | ||
diff --git a/vendor/luasec/src/Makefile b/vendor/luasec/src/Makefile new file mode 100644 index 00000000..9b06a038 --- /dev/null +++ b/vendor/luasec/src/Makefile | |||
@@ -0,0 +1,66 @@ | |||
1 | CMOD=ssl.so | ||
2 | LMOD=ssl.lua | ||
3 | |||
4 | OBJS= \ | ||
5 | options.o \ | ||
6 | x509.o \ | ||
7 | context.o \ | ||
8 | ssl.o \ | ||
9 | config.o \ | ||
10 | ec.o | ||
11 | |||
12 | LIBS=-lssl -lcrypto -lluasocket | ||
13 | |||
14 | WARN=-Wall -pedantic | ||
15 | |||
16 | BSD_CFLAGS=-O2 -fPIC $(WARN) $(INCDIR) $(DEFS) | ||
17 | BSD_LDFLAGS=-O -fPIC -shared $(LIBDIR) | ||
18 | |||
19 | LNX_CFLAGS=-O2 -fPIC $(WARN) $(INCDIR) $(DEFS) | ||
20 | LNX_LDFLAGS=-O -fPIC -shared $(LIBDIR) | ||
21 | |||
22 | MAC_ENV=env MACOSX_DEPLOYMENT_TARGET='$(MACVER)' | ||
23 | MAC_CFLAGS=-O2 -fno-common $(WARN) $(INCDIR) $(DEFS) | ||
24 | MAC_LDFLAGS=-bundle -undefined dynamic_lookup $(LIBDIR) | ||
25 | |||
26 | INSTALL = install | ||
27 | CC ?= cc | ||
28 | CCLD ?= $(MYENV) $(CC) | ||
29 | CFLAGS += $(MYCFLAGS) | ||
30 | LDFLAGS += $(MYLDFLAGS) | ||
31 | |||
32 | .PHONY: all clean install none linux bsd macosx luasocket | ||
33 | |||
34 | all: | ||
35 | |||
36 | install: $(CMOD) $(LMOD) | ||
37 | $(INSTALL) -d $(DESTDIR)$(LUAPATH)/ssl $(DESTDIR)$(LUACPATH) | ||
38 | $(INSTALL) $(CMOD) $(DESTDIR)$(LUACPATH) | ||
39 | $(INSTALL) -m644 $(LMOD) $(DESTDIR)$(LUAPATH) | ||
40 | $(INSTALL) -m644 https.lua $(DESTDIR)$(LUAPATH)/ssl | ||
41 | |||
42 | linux: | ||
43 | @$(MAKE) $(CMOD) MYCFLAGS="$(LNX_CFLAGS)" MYLDFLAGS="$(LNX_LDFLAGS)" EXTRA="$(EXTRA)" | ||
44 | |||
45 | bsd: | ||
46 | @$(MAKE) $(CMOD) MYCFLAGS="$(BSD_CFLAGS)" MYLDFLAGS="$(BSD_LDFLAGS)" EXTRA="$(EXTRA)" | ||
47 | |||
48 | macosx: | ||
49 | @$(MAKE) $(CMOD) MYCFLAGS="$(MAC_CFLAGS)" MYLDFLAGS="$(MAC_LDFLAGS)" MYENV="$(MAC_ENV)" EXTRA="$(EXTRA)" | ||
50 | |||
51 | luasocket: | ||
52 | @cd luasocket && $(MAKE) | ||
53 | |||
54 | $(CMOD): $(EXTRA) $(OBJS) | ||
55 | $(CCLD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) | ||
56 | |||
57 | clean: | ||
58 | cd luasocket && $(MAKE) clean | ||
59 | rm -f $(OBJS) $(CMOD) | ||
60 | |||
61 | options.o: options.h options.c | ||
62 | ec.o: ec.c ec.h | ||
63 | x509.o: x509.c x509.h compat.h | ||
64 | context.o: context.c context.h ec.h compat.h options.h | ||
65 | ssl.o: ssl.c ssl.h context.h x509.h compat.h | ||
66 | config.o: config.c ec.h options.h compat.h | ||
diff --git a/vendor/luasec/src/compat.h b/vendor/luasec/src/compat.h new file mode 100644 index 00000000..9f97e2a6 --- /dev/null +++ b/vendor/luasec/src/compat.h | |||
@@ -0,0 +1,63 @@ | |||
1 | /*-------------------------------------------------------------------------- | ||
2 | * LuaSec 1.3.2 | ||
3 | * | ||
4 | * Copyright (C) 2006-2023 Bruno Silvestre | ||
5 | * | ||
6 | *--------------------------------------------------------------------------*/ | ||
7 | |||
8 | #ifndef LSEC_COMPAT_H | ||
9 | #define LSEC_COMPAT_H | ||
10 | |||
11 | #include <openssl/ssl.h> | ||
12 | |||
13 | //------------------------------------------------------------------------------ | ||
14 | |||
15 | #if defined(_WIN32) | ||
16 | #define LSEC_API __declspec(dllexport) | ||
17 | #else | ||
18 | #define LSEC_API extern | ||
19 | #endif | ||
20 | |||
21 | //------------------------------------------------------------------------------ | ||
22 | |||
23 | #if (LUA_VERSION_NUM == 501) | ||
24 | |||
25 | #define luaL_testudata(L, ud, tname) lsec_testudata(L, ud, tname) | ||
26 | #define setfuncs(L, R) luaL_register(L, NULL, R) | ||
27 | #define lua_rawlen(L, i) lua_objlen(L, i) | ||
28 | |||
29 | #ifndef luaL_newlib | ||
30 | #define luaL_newlib(L, R) do { lua_newtable(L); luaL_register(L, NULL, R); } while(0) | ||
31 | #endif | ||
32 | |||
33 | #else | ||
34 | #define setfuncs(L, R) luaL_setfuncs(L, R, 0) | ||
35 | #endif | ||
36 | |||
37 | //------------------------------------------------------------------------------ | ||
38 | |||
39 | #if (!defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x1010000fL)) | ||
40 | #define LSEC_ENABLE_DANE | ||
41 | #endif | ||
42 | |||
43 | //------------------------------------------------------------------------------ | ||
44 | |||
45 | #if !((defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x2070000fL)) || (OPENSSL_VERSION_NUMBER < 0x1010000fL)) | ||
46 | #define LSEC_API_OPENSSL_1_1_0 | ||
47 | #endif | ||
48 | |||
49 | //------------------------------------------------------------------------------ | ||
50 | |||
51 | #if !defined(LIBRESSL_VERSION_NUMBER) && ((OPENSSL_VERSION_NUMBER & 0xFFFFF000L) == 0x10101000L || (OPENSSL_VERSION_NUMBER & 0xFFFFF000L) == 0x30000000L) | ||
52 | #define LSEC_OPENSSL_ERRNO_BUG | ||
53 | #endif | ||
54 | |||
55 | //------------------------------------------------------------------------------ | ||
56 | |||
57 | #if !defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_NO_PSK) | ||
58 | #define LSEC_ENABLE_PSK | ||
59 | #endif | ||
60 | |||
61 | //------------------------------------------------------------------------------ | ||
62 | |||
63 | #endif | ||
diff --git a/vendor/luasec/src/config.c b/vendor/luasec/src/config.c new file mode 100644 index 00000000..5f0e2c60 --- /dev/null +++ b/vendor/luasec/src/config.c | |||
@@ -0,0 +1,108 @@ | |||
1 | /*-------------------------------------------------------------------------- | ||
2 | * LuaSec 1.3.2 | ||
3 | * | ||
4 | * Copyright (C) 2006-2023 Bruno Silvestre | ||
5 | * | ||
6 | *--------------------------------------------------------------------------*/ | ||
7 | |||
8 | #include "compat.h" | ||
9 | #include "options.h" | ||
10 | #include "ec.h" | ||
11 | |||
12 | /** | ||
13 | * Registre the module. | ||
14 | */ | ||
15 | LSEC_API int luaopen_ssl_config(lua_State *L) | ||
16 | { | ||
17 | lsec_ssl_option_t *opt; | ||
18 | |||
19 | lua_newtable(L); | ||
20 | |||
21 | // Options | ||
22 | lua_pushstring(L, "options"); | ||
23 | lua_newtable(L); | ||
24 | for (opt = lsec_get_ssl_options(); opt->name; opt++) { | ||
25 | lua_pushstring(L, opt->name); | ||
26 | lua_pushboolean(L, 1); | ||
27 | lua_rawset(L, -3); | ||
28 | } | ||
29 | lua_rawset(L, -3); | ||
30 | |||
31 | // Protocols | ||
32 | lua_pushstring(L, "protocols"); | ||
33 | lua_newtable(L); | ||
34 | |||
35 | lua_pushstring(L, "tlsv1"); | ||
36 | lua_pushboolean(L, 1); | ||
37 | lua_rawset(L, -3); | ||
38 | lua_pushstring(L, "tlsv1_1"); | ||
39 | lua_pushboolean(L, 1); | ||
40 | lua_rawset(L, -3); | ||
41 | lua_pushstring(L, "tlsv1_2"); | ||
42 | lua_pushboolean(L, 1); | ||
43 | lua_rawset(L, -3); | ||
44 | #ifdef TLS1_3_VERSION | ||
45 | lua_pushstring(L, "tlsv1_3"); | ||
46 | lua_pushboolean(L, 1); | ||
47 | lua_rawset(L, -3); | ||
48 | #endif | ||
49 | |||
50 | lua_rawset(L, -3); | ||
51 | |||
52 | // Algorithms | ||
53 | lua_pushstring(L, "algorithms"); | ||
54 | lua_newtable(L); | ||
55 | |||
56 | #ifndef OPENSSL_NO_EC | ||
57 | lua_pushstring(L, "ec"); | ||
58 | lua_pushboolean(L, 1); | ||
59 | lua_rawset(L, -3); | ||
60 | #endif | ||
61 | lua_rawset(L, -3); | ||
62 | |||
63 | // Curves | ||
64 | lua_pushstring(L, "curves"); | ||
65 | lsec_get_curves(L); | ||
66 | lua_rawset(L, -3); | ||
67 | |||
68 | // Capabilities | ||
69 | lua_pushstring(L, "capabilities"); | ||
70 | lua_newtable(L); | ||
71 | |||
72 | // ALPN | ||
73 | lua_pushstring(L, "alpn"); | ||
74 | lua_pushboolean(L, 1); | ||
75 | lua_rawset(L, -3); | ||
76 | |||
77 | #ifdef LSEC_ENABLE_PSK | ||
78 | lua_pushstring(L, "psk"); | ||
79 | lua_pushboolean(L, 1); | ||
80 | lua_rawset(L, -3); | ||
81 | #endif | ||
82 | |||
83 | #ifdef LSEC_ENABLE_DANE | ||
84 | // DANE | ||
85 | lua_pushstring(L, "dane"); | ||
86 | #ifdef DANE_FLAG_NO_DANE_EE_NAMECHECKS | ||
87 | lua_createtable(L, 0, 1); | ||
88 | lua_pushstring(L, "no_ee_namechecks"); | ||
89 | lua_pushboolean(L, 1); | ||
90 | lua_rawset(L, -3); | ||
91 | #else | ||
92 | lua_pushboolean(L, 1); | ||
93 | #endif | ||
94 | lua_rawset(L, -3); | ||
95 | #endif | ||
96 | |||
97 | #ifndef OPENSSL_NO_EC | ||
98 | lua_pushstring(L, "curves_list"); | ||
99 | lua_pushboolean(L, 1); | ||
100 | lua_rawset(L, -3); | ||
101 | lua_pushstring(L, "ecdh_auto"); | ||
102 | lua_pushboolean(L, 1); | ||
103 | lua_rawset(L, -3); | ||
104 | #endif | ||
105 | lua_rawset(L, -3); | ||
106 | |||
107 | return 1; | ||
108 | } | ||
diff --git a/vendor/luasec/src/context.c b/vendor/luasec/src/context.c new file mode 100644 index 00000000..881ebb90 --- /dev/null +++ b/vendor/luasec/src/context.c | |||
@@ -0,0 +1,1099 @@ | |||
1 | /*-------------------------------------------------------------------------- | ||
2 | * LuaSec 1.3.2 | ||
3 | * | ||
4 | * Copyright (C) 2014-2023 Kim Alvefur, Paul Aurich, Tobias Markmann, Matthew Wild | ||
5 | * Copyright (C) 2006-2023 Bruno Silvestre | ||
6 | * | ||
7 | *--------------------------------------------------------------------------*/ | ||
8 | |||
9 | #include <string.h> | ||
10 | |||
11 | #if defined(WIN32) | ||
12 | #include <windows.h> | ||
13 | #endif | ||
14 | |||
15 | #include <openssl/ssl.h> | ||
16 | #include <openssl/err.h> | ||
17 | #include <openssl/x509.h> | ||
18 | #include <openssl/x509v3.h> | ||
19 | #include <openssl/x509_vfy.h> | ||
20 | #include <openssl/dh.h> | ||
21 | |||
22 | #include <lua.h> | ||
23 | #include <lauxlib.h> | ||
24 | |||
25 | #include "compat.h" | ||
26 | #include "context.h" | ||
27 | #include "options.h" | ||
28 | |||
29 | #ifndef OPENSSL_NO_EC | ||
30 | #include <openssl/ec.h> | ||
31 | #include "ec.h" | ||
32 | #endif | ||
33 | |||
34 | /*--------------------------- Auxiliary Functions ----------------------------*/ | ||
35 | |||
36 | /** | ||
37 | * Return the context. | ||
38 | */ | ||
39 | static p_context checkctx(lua_State *L, int idx) | ||
40 | { | ||
41 | return (p_context)luaL_checkudata(L, idx, "SSL:Context"); | ||
42 | } | ||
43 | |||
44 | static p_context testctx(lua_State *L, int idx) | ||
45 | { | ||
46 | return (p_context)luaL_testudata(L, idx, "SSL:Context"); | ||
47 | } | ||
48 | |||
49 | /** | ||
50 | * Prepare the SSL options flag. | ||
51 | */ | ||
52 | static int set_option_flag(const char *opt, unsigned long *flag) | ||
53 | { | ||
54 | lsec_ssl_option_t *p; | ||
55 | for (p = lsec_get_ssl_options(); p->name; p++) { | ||
56 | if (!strcmp(opt, p->name)) { | ||
57 | *flag |= p->code; | ||
58 | return 1; | ||
59 | } | ||
60 | } | ||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | #ifndef LSEC_API_OPENSSL_1_1_0 | ||
65 | /** | ||
66 | * Find the protocol. | ||
67 | */ | ||
68 | static const SSL_METHOD* str2method(const char *method, int *vmin, int *vmax) | ||
69 | { | ||
70 | (void)vmin; | ||
71 | (void)vmax; | ||
72 | if (!strcmp(method, "any")) return SSLv23_method(); | ||
73 | if (!strcmp(method, "sslv23")) return SSLv23_method(); // deprecated | ||
74 | if (!strcmp(method, "tlsv1")) return TLSv1_method(); | ||
75 | if (!strcmp(method, "tlsv1_1")) return TLSv1_1_method(); | ||
76 | if (!strcmp(method, "tlsv1_2")) return TLSv1_2_method(); | ||
77 | return NULL; | ||
78 | } | ||
79 | |||
80 | #else | ||
81 | |||
82 | /** | ||
83 | * Find the protocol. | ||
84 | */ | ||
85 | static const SSL_METHOD* str2method(const char *method, int *vmin, int *vmax) | ||
86 | { | ||
87 | if (!strcmp(method, "any") || !strcmp(method, "sslv23")) { // 'sslv23' is deprecated | ||
88 | *vmin = 0; | ||
89 | *vmax = 0; | ||
90 | return TLS_method(); | ||
91 | } | ||
92 | else if (!strcmp(method, "tlsv1")) { | ||
93 | *vmin = TLS1_VERSION; | ||
94 | *vmax = TLS1_VERSION; | ||
95 | return TLS_method(); | ||
96 | } | ||
97 | else if (!strcmp(method, "tlsv1_1")) { | ||
98 | *vmin = TLS1_1_VERSION; | ||
99 | *vmax = TLS1_1_VERSION; | ||
100 | return TLS_method(); | ||
101 | } | ||
102 | else if (!strcmp(method, "tlsv1_2")) { | ||
103 | *vmin = TLS1_2_VERSION; | ||
104 | *vmax = TLS1_2_VERSION; | ||
105 | return TLS_method(); | ||
106 | } | ||
107 | #if defined(TLS1_3_VERSION) | ||
108 | else if (!strcmp(method, "tlsv1_3")) { | ||
109 | *vmin = TLS1_3_VERSION; | ||
110 | *vmax = TLS1_3_VERSION; | ||
111 | return TLS_method(); | ||
112 | } | ||
113 | #endif | ||
114 | return NULL; | ||
115 | } | ||
116 | #endif | ||
117 | |||
118 | /** | ||
119 | * Prepare the SSL handshake verify flag. | ||
120 | */ | ||
121 | static int set_verify_flag(const char *str, int *flag) | ||
122 | { | ||
123 | if (!strcmp(str, "none")) { | ||
124 | *flag |= SSL_VERIFY_NONE; | ||
125 | return 1; | ||
126 | } | ||
127 | if (!strcmp(str, "peer")) { | ||
128 | *flag |= SSL_VERIFY_PEER; | ||
129 | return 1; | ||
130 | } | ||
131 | if (!strcmp(str, "client_once")) { | ||
132 | *flag |= SSL_VERIFY_CLIENT_ONCE; | ||
133 | return 1; | ||
134 | } | ||
135 | if (!strcmp(str, "fail_if_no_peer_cert")) { | ||
136 | *flag |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; | ||
137 | return 1; | ||
138 | } | ||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | /** | ||
143 | * Password callback for reading the private key. | ||
144 | */ | ||
145 | static int passwd_cb(char *buf, int size, int flag, void *udata) | ||
146 | { | ||
147 | lua_State *L = (lua_State*)udata; | ||
148 | switch (lua_type(L, 3)) { | ||
149 | case LUA_TFUNCTION: | ||
150 | lua_pushvalue(L, 3); | ||
151 | lua_call(L, 0, 1); | ||
152 | if (lua_type(L, -1) != LUA_TSTRING) { | ||
153 | lua_pop(L, 1); /* Remove the result from the stack */ | ||
154 | return 0; | ||
155 | } | ||
156 | /* fallback */ | ||
157 | case LUA_TSTRING: | ||
158 | strncpy(buf, lua_tostring(L, -1), size); | ||
159 | lua_pop(L, 1); /* Remove the result from the stack */ | ||
160 | buf[size-1] = '\0'; | ||
161 | return (int)strlen(buf); | ||
162 | } | ||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | /** | ||
167 | * Add an error related to a depth certificate of the chain. | ||
168 | */ | ||
169 | static void add_cert_error(lua_State *L, SSL *ssl, int err, int depth) | ||
170 | { | ||
171 | luaL_getmetatable(L, "SSL:Verify:Registry"); | ||
172 | lua_pushlightuserdata(L, (void*)ssl); | ||
173 | lua_gettable(L, -2); | ||
174 | if (lua_isnil(L, -1)) { | ||
175 | lua_pop(L, 1); | ||
176 | /* Create an error table for this connection */ | ||
177 | lua_newtable(L); | ||
178 | lua_pushlightuserdata(L, (void*)ssl); | ||
179 | lua_pushvalue(L, -2); /* keep the table on stack */ | ||
180 | lua_settable(L, -4); | ||
181 | } | ||
182 | lua_rawgeti(L, -1, depth+1); | ||
183 | /* If the table doesn't exist, create it */ | ||
184 | if (lua_isnil(L, -1)) { | ||
185 | lua_pop(L, 1); /* remove 'nil' from stack */ | ||
186 | lua_newtable(L); | ||
187 | lua_pushvalue(L, -1); /* keep the table on stack */ | ||
188 | lua_rawseti(L, -3, depth+1); | ||
189 | } | ||
190 | lua_pushstring(L, X509_verify_cert_error_string(err)); | ||
191 | lua_rawseti(L, -2, lua_rawlen(L, -2) + 1); | ||
192 | /* Clear the stack */ | ||
193 | lua_pop(L, 3); | ||
194 | } | ||
195 | |||
196 | /** | ||
197 | * Call Lua user function to get the DH key. | ||
198 | */ | ||
199 | static DH *dhparam_cb(SSL *ssl, int is_export, int keylength) | ||
200 | { | ||
201 | BIO *bio; | ||
202 | lua_State *L; | ||
203 | SSL_CTX *ctx = SSL_get_SSL_CTX(ssl); | ||
204 | p_context pctx = (p_context)SSL_CTX_get_app_data(ctx); | ||
205 | |||
206 | L = pctx->L; | ||
207 | |||
208 | /* Get the callback */ | ||
209 | luaL_getmetatable(L, "SSL:DH:Registry"); | ||
210 | lua_pushlightuserdata(L, (void*)ctx); | ||
211 | lua_gettable(L, -2); | ||
212 | |||
213 | /* Invoke the callback */ | ||
214 | lua_pushboolean(L, is_export); | ||
215 | lua_pushnumber(L, keylength); | ||
216 | lua_call(L, 2, 1); | ||
217 | |||
218 | /* Load parameters from returned value */ | ||
219 | if (lua_type(L, -1) != LUA_TSTRING) { | ||
220 | lua_pop(L, 2); /* Remove values from stack */ | ||
221 | return NULL; | ||
222 | } | ||
223 | |||
224 | bio = BIO_new_mem_buf((void*)lua_tostring(L, -1), lua_rawlen(L, -1)); | ||
225 | if (bio) { | ||
226 | pctx->dh_param = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); | ||
227 | BIO_free(bio); | ||
228 | } | ||
229 | |||
230 | lua_pop(L, 2); /* Remove values from stack */ | ||
231 | return pctx->dh_param; | ||
232 | } | ||
233 | |||
234 | /** | ||
235 | * Set the "ignore purpose" before to start verifing the certificate chain. | ||
236 | */ | ||
237 | static int cert_verify_cb(X509_STORE_CTX *x509_ctx, void *ptr) | ||
238 | { | ||
239 | int verify; | ||
240 | lua_State *L; | ||
241 | SSL_CTX *ctx = (SSL_CTX*)ptr; | ||
242 | p_context pctx = (p_context)SSL_CTX_get_app_data(ctx); | ||
243 | |||
244 | L = pctx->L; | ||
245 | |||
246 | /* Get verify flags */ | ||
247 | luaL_getmetatable(L, "SSL:Verify:Registry"); | ||
248 | lua_pushlightuserdata(L, (void*)ctx); | ||
249 | lua_gettable(L, -2); | ||
250 | verify = (int)lua_tonumber(L, -1); | ||
251 | |||
252 | lua_pop(L, 2); /* Remove values from stack */ | ||
253 | |||
254 | if (verify & LSEC_VERIFY_IGNORE_PURPOSE) { | ||
255 | /* Set parameters to ignore the server purpose */ | ||
256 | X509_VERIFY_PARAM *param = X509_STORE_CTX_get0_param(x509_ctx); | ||
257 | if (param) { | ||
258 | X509_VERIFY_PARAM_set_purpose(param, X509_PURPOSE_SSL_SERVER); | ||
259 | X509_VERIFY_PARAM_set_trust(param, X509_TRUST_SSL_SERVER); | ||
260 | } | ||
261 | } | ||
262 | /* Call OpenSSL standard verification function */ | ||
263 | return X509_verify_cert(x509_ctx); | ||
264 | } | ||
265 | |||
266 | /** | ||
267 | * This callback implements the "continue on error" flag and log the errors. | ||
268 | */ | ||
269 | static int verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx) | ||
270 | { | ||
271 | int err; | ||
272 | int verify; | ||
273 | SSL *ssl; | ||
274 | SSL_CTX *ctx; | ||
275 | p_context pctx; | ||
276 | lua_State *L; | ||
277 | |||
278 | /* Short-circuit optimization */ | ||
279 | if (preverify_ok) | ||
280 | return 1; | ||
281 | |||
282 | ssl = X509_STORE_CTX_get_ex_data(x509_ctx, | ||
283 | SSL_get_ex_data_X509_STORE_CTX_idx()); | ||
284 | ctx = SSL_get_SSL_CTX(ssl); | ||
285 | pctx = (p_context)SSL_CTX_get_app_data(ctx); | ||
286 | L = pctx->L; | ||
287 | |||
288 | /* Get verify flags */ | ||
289 | luaL_getmetatable(L, "SSL:Verify:Registry"); | ||
290 | lua_pushlightuserdata(L, (void*)ctx); | ||
291 | lua_gettable(L, -2); | ||
292 | verify = (int)lua_tonumber(L, -1); | ||
293 | |||
294 | lua_pop(L, 2); /* Remove values from stack */ | ||
295 | |||
296 | err = X509_STORE_CTX_get_error(x509_ctx); | ||
297 | if (err != X509_V_OK) | ||
298 | add_cert_error(L, ssl, err, X509_STORE_CTX_get_error_depth(x509_ctx)); | ||
299 | |||
300 | return (verify & LSEC_VERIFY_CONTINUE ? 1 : preverify_ok); | ||
301 | } | ||
302 | |||
303 | /*------------------------------ Lua Functions -------------------------------*/ | ||
304 | |||
305 | /** | ||
306 | * Create a SSL context. | ||
307 | */ | ||
308 | static int create(lua_State *L) | ||
309 | { | ||
310 | p_context ctx; | ||
311 | const char *str_method; | ||
312 | const SSL_METHOD *method; | ||
313 | int vmin, vmax; | ||
314 | |||
315 | str_method = luaL_checkstring(L, 1); | ||
316 | method = str2method(str_method, &vmin, &vmax); | ||
317 | if (!method) { | ||
318 | lua_pushnil(L); | ||
319 | lua_pushfstring(L, "invalid protocol (%s)", str_method); | ||
320 | return 2; | ||
321 | } | ||
322 | ctx = (p_context) lua_newuserdata(L, sizeof(t_context)); | ||
323 | if (!ctx) { | ||
324 | lua_pushnil(L); | ||
325 | lua_pushstring(L, "error creating context"); | ||
326 | return 2; | ||
327 | } | ||
328 | memset(ctx, 0, sizeof(t_context)); | ||
329 | ctx->context = SSL_CTX_new(method); | ||
330 | if (!ctx->context) { | ||
331 | lua_pushnil(L); | ||
332 | lua_pushfstring(L, "error creating context (%s)", | ||
333 | ERR_reason_error_string(ERR_get_error())); | ||
334 | return 2; | ||
335 | } | ||
336 | #ifdef LSEC_API_OPENSSL_1_1_0 | ||
337 | SSL_CTX_set_min_proto_version(ctx->context, vmin); | ||
338 | SSL_CTX_set_max_proto_version(ctx->context, vmax); | ||
339 | #endif | ||
340 | ctx->mode = LSEC_MODE_INVALID; | ||
341 | ctx->L = L; | ||
342 | luaL_getmetatable(L, "SSL:Context"); | ||
343 | lua_setmetatable(L, -2); | ||
344 | |||
345 | /* No session support */ | ||
346 | SSL_CTX_set_session_cache_mode(ctx->context, SSL_SESS_CACHE_OFF); | ||
347 | /* Link LuaSec context with the OpenSSL context */ | ||
348 | SSL_CTX_set_app_data(ctx->context, ctx); | ||
349 | |||
350 | return 1; | ||
351 | } | ||
352 | |||
353 | /** | ||
354 | * Load the trusting certificates. | ||
355 | */ | ||
356 | static int load_locations(lua_State *L) | ||
357 | { | ||
358 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
359 | const char *cafile = luaL_optstring(L, 2, NULL); | ||
360 | const char *capath = luaL_optstring(L, 3, NULL); | ||
361 | if (SSL_CTX_load_verify_locations(ctx, cafile, capath) != 1) { | ||
362 | lua_pushboolean(L, 0); | ||
363 | lua_pushfstring(L, "error loading CA locations (%s)", | ||
364 | ERR_reason_error_string(ERR_get_error())); | ||
365 | return 2; | ||
366 | } | ||
367 | lua_pushboolean(L, 1); | ||
368 | return 1; | ||
369 | } | ||
370 | |||
371 | /** | ||
372 | * Load the certificate file. | ||
373 | */ | ||
374 | static int load_cert(lua_State *L) | ||
375 | { | ||
376 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
377 | const char *filename = luaL_checkstring(L, 2); | ||
378 | if (SSL_CTX_use_certificate_chain_file(ctx, filename) != 1) { | ||
379 | lua_pushboolean(L, 0); | ||
380 | lua_pushfstring(L, "error loading certificate (%s)", | ||
381 | ERR_reason_error_string(ERR_get_error())); | ||
382 | return 2; | ||
383 | } | ||
384 | lua_pushboolean(L, 1); | ||
385 | return 1; | ||
386 | } | ||
387 | |||
388 | /** | ||
389 | * Load the key file -- only in PEM format. | ||
390 | */ | ||
391 | static int load_key(lua_State *L) | ||
392 | { | ||
393 | int ret = 1; | ||
394 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
395 | const char *filename = luaL_checkstring(L, 2); | ||
396 | switch (lua_type(L, 3)) { | ||
397 | case LUA_TSTRING: | ||
398 | case LUA_TFUNCTION: | ||
399 | SSL_CTX_set_default_passwd_cb(ctx, passwd_cb); | ||
400 | SSL_CTX_set_default_passwd_cb_userdata(ctx, L); | ||
401 | /* fallback */ | ||
402 | case LUA_TNIL: | ||
403 | if (SSL_CTX_use_PrivateKey_file(ctx, filename, SSL_FILETYPE_PEM) == 1) | ||
404 | lua_pushboolean(L, 1); | ||
405 | else { | ||
406 | ret = 2; | ||
407 | lua_pushboolean(L, 0); | ||
408 | lua_pushfstring(L, "error loading private key (%s)", | ||
409 | ERR_reason_error_string(ERR_get_error())); | ||
410 | } | ||
411 | SSL_CTX_set_default_passwd_cb(ctx, NULL); | ||
412 | SSL_CTX_set_default_passwd_cb_userdata(ctx, NULL); | ||
413 | break; | ||
414 | default: | ||
415 | lua_pushstring(L, "invalid callback value"); | ||
416 | lua_error(L); | ||
417 | } | ||
418 | return ret; | ||
419 | } | ||
420 | |||
421 | /** | ||
422 | * Check that the certificate public key matches the private key | ||
423 | */ | ||
424 | |||
425 | static int check_key(lua_State *L) | ||
426 | { | ||
427 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
428 | lua_pushboolean(L, SSL_CTX_check_private_key(ctx)); | ||
429 | return 1; | ||
430 | } | ||
431 | |||
432 | /** | ||
433 | * Set the cipher list. | ||
434 | */ | ||
435 | static int set_cipher(lua_State *L) | ||
436 | { | ||
437 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
438 | const char *list = luaL_checkstring(L, 2); | ||
439 | if (SSL_CTX_set_cipher_list(ctx, list) != 1) { | ||
440 | lua_pushboolean(L, 0); | ||
441 | lua_pushfstring(L, "error setting cipher list (%s)", ERR_reason_error_string(ERR_get_error())); | ||
442 | return 2; | ||
443 | } | ||
444 | lua_pushboolean(L, 1); | ||
445 | return 1; | ||
446 | } | ||
447 | |||
448 | /** | ||
449 | * Set the cipher suites. | ||
450 | */ | ||
451 | static int set_ciphersuites(lua_State *L) | ||
452 | { | ||
453 | #if defined(TLS1_3_VERSION) | ||
454 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
455 | const char *list = luaL_checkstring(L, 2); | ||
456 | if (SSL_CTX_set_ciphersuites(ctx, list) != 1) { | ||
457 | lua_pushboolean(L, 0); | ||
458 | lua_pushfstring(L, "error setting cipher list (%s)", ERR_reason_error_string(ERR_get_error())); | ||
459 | return 2; | ||
460 | } | ||
461 | #endif | ||
462 | lua_pushboolean(L, 1); | ||
463 | return 1; | ||
464 | } | ||
465 | |||
466 | /** | ||
467 | * Set the depth for certificate checking. | ||
468 | */ | ||
469 | static int set_depth(lua_State *L) | ||
470 | { | ||
471 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
472 | SSL_CTX_set_verify_depth(ctx, (int)luaL_checkinteger(L, 2)); | ||
473 | lua_pushboolean(L, 1); | ||
474 | return 1; | ||
475 | } | ||
476 | |||
477 | /** | ||
478 | * Set the handshake verify options. | ||
479 | */ | ||
480 | static int set_verify(lua_State *L) | ||
481 | { | ||
482 | int i; | ||
483 | const char *str; | ||
484 | int flag = 0; | ||
485 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
486 | int max = lua_gettop(L); | ||
487 | for (i = 2; i <= max; i++) { | ||
488 | str = luaL_checkstring(L, i); | ||
489 | if (!set_verify_flag(str, &flag)) { | ||
490 | lua_pushboolean(L, 0); | ||
491 | lua_pushfstring(L, "invalid verify option (%s)", str); | ||
492 | return 2; | ||
493 | } | ||
494 | } | ||
495 | if (flag) SSL_CTX_set_verify(ctx, flag, NULL); | ||
496 | lua_pushboolean(L, 1); | ||
497 | return 1; | ||
498 | } | ||
499 | |||
500 | /** | ||
501 | * Set the protocol options. | ||
502 | */ | ||
503 | static int set_options(lua_State *L) | ||
504 | { | ||
505 | int i; | ||
506 | const char *str; | ||
507 | unsigned long flag = 0L; | ||
508 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
509 | int max = lua_gettop(L); | ||
510 | /* any option? */ | ||
511 | if (max > 1) { | ||
512 | for (i = 2; i <= max; i++) { | ||
513 | str = luaL_checkstring(L, i); | ||
514 | if (!set_option_flag(str, &flag)) { | ||
515 | lua_pushboolean(L, 0); | ||
516 | lua_pushfstring(L, "invalid option (%s)", str); | ||
517 | return 2; | ||
518 | } | ||
519 | } | ||
520 | SSL_CTX_set_options(ctx, flag); | ||
521 | } | ||
522 | lua_pushboolean(L, 1); | ||
523 | return 1; | ||
524 | } | ||
525 | |||
526 | /** | ||
527 | * Set the context mode. | ||
528 | */ | ||
529 | static int set_mode(lua_State *L) | ||
530 | { | ||
531 | p_context ctx = checkctx(L, 1); | ||
532 | const char *str = luaL_checkstring(L, 2); | ||
533 | if (!strcmp("server", str)) { | ||
534 | ctx->mode = LSEC_MODE_SERVER; | ||
535 | lua_pushboolean(L, 1); | ||
536 | return 1; | ||
537 | } | ||
538 | if (!strcmp("client", str)) { | ||
539 | ctx->mode = LSEC_MODE_CLIENT; | ||
540 | lua_pushboolean(L, 1); | ||
541 | return 1; | ||
542 | } | ||
543 | lua_pushboolean(L, 0); | ||
544 | lua_pushfstring(L, "invalid mode (%s)", str); | ||
545 | return 1; | ||
546 | } | ||
547 | |||
548 | /** | ||
549 | * Configure DH parameters. | ||
550 | */ | ||
551 | static int set_dhparam(lua_State *L) | ||
552 | { | ||
553 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
554 | SSL_CTX_set_tmp_dh_callback(ctx, dhparam_cb); | ||
555 | |||
556 | /* Save callback */ | ||
557 | luaL_getmetatable(L, "SSL:DH:Registry"); | ||
558 | lua_pushlightuserdata(L, (void*)ctx); | ||
559 | lua_pushvalue(L, 2); | ||
560 | lua_settable(L, -3); | ||
561 | |||
562 | return 0; | ||
563 | } | ||
564 | |||
565 | #if !defined(OPENSSL_NO_EC) | ||
566 | /** | ||
567 | * Set elliptic curve. | ||
568 | */ | ||
569 | static int set_curve(lua_State *L) | ||
570 | { | ||
571 | long ret; | ||
572 | EC_KEY *key = NULL; | ||
573 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
574 | const char *str = luaL_checkstring(L, 2); | ||
575 | |||
576 | SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE); | ||
577 | |||
578 | key = lsec_find_ec_key(L, str); | ||
579 | |||
580 | if (!key) { | ||
581 | lua_pushboolean(L, 0); | ||
582 | lua_pushfstring(L, "elliptic curve '%s' not supported", str); | ||
583 | return 2; | ||
584 | } | ||
585 | |||
586 | ret = SSL_CTX_set_tmp_ecdh(ctx, key); | ||
587 | /* SSL_CTX_set_tmp_ecdh takes its own reference */ | ||
588 | EC_KEY_free(key); | ||
589 | |||
590 | if (!ret) { | ||
591 | lua_pushboolean(L, 0); | ||
592 | lua_pushfstring(L, "error setting elliptic curve (%s)", | ||
593 | ERR_reason_error_string(ERR_get_error())); | ||
594 | return 2; | ||
595 | } | ||
596 | |||
597 | lua_pushboolean(L, 1); | ||
598 | return 1; | ||
599 | } | ||
600 | |||
601 | /** | ||
602 | * Set elliptic curves list. | ||
603 | */ | ||
604 | static int set_curves_list(lua_State *L) | ||
605 | { | ||
606 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
607 | const char *str = luaL_checkstring(L, 2); | ||
608 | |||
609 | SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE); | ||
610 | |||
611 | if (SSL_CTX_set1_curves_list(ctx, str) != 1) { | ||
612 | lua_pushboolean(L, 0); | ||
613 | lua_pushfstring(L, "unknown elliptic curve in \"%s\"", str); | ||
614 | return 2; | ||
615 | } | ||
616 | |||
617 | #if defined(LIBRESSL_VERSION_NUMBER) || !defined(LSEC_API_OPENSSL_1_1_0) | ||
618 | (void)SSL_CTX_set_ecdh_auto(ctx, 1); | ||
619 | #endif | ||
620 | |||
621 | lua_pushboolean(L, 1); | ||
622 | return 1; | ||
623 | } | ||
624 | #endif | ||
625 | |||
626 | /** | ||
627 | * Set the protocols a client should send for ALPN. | ||
628 | */ | ||
629 | static int set_alpn(lua_State *L) | ||
630 | { | ||
631 | long ret; | ||
632 | size_t len; | ||
633 | p_context ctx = checkctx(L, 1); | ||
634 | const char *str = luaL_checklstring(L, 2, &len); | ||
635 | |||
636 | ret = SSL_CTX_set_alpn_protos(ctx->context, (const unsigned char*)str, len); | ||
637 | if (ret) { | ||
638 | lua_pushboolean(L, 0); | ||
639 | lua_pushfstring(L, "error setting ALPN (%s)", ERR_reason_error_string(ERR_get_error())); | ||
640 | return 2; | ||
641 | } | ||
642 | lua_pushboolean(L, 1); | ||
643 | return 1; | ||
644 | } | ||
645 | |||
646 | /** | ||
647 | * This standard callback calls the server's callback in Lua sapce. | ||
648 | * The server has to return a list in wire-format strings. | ||
649 | * This function uses a helper function to match server and client lists. | ||
650 | */ | ||
651 | static int alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen, | ||
652 | const unsigned char *in, unsigned int inlen, void *arg) | ||
653 | { | ||
654 | int ret; | ||
655 | size_t server_len; | ||
656 | const char *server; | ||
657 | p_context ctx = (p_context)arg; | ||
658 | lua_State *L = ctx->L; | ||
659 | |||
660 | luaL_getmetatable(L, "SSL:ALPN:Registry"); | ||
661 | lua_pushlightuserdata(L, (void*)ctx->context); | ||
662 | lua_gettable(L, -2); | ||
663 | |||
664 | lua_pushlstring(L, (const char*)in, inlen); | ||
665 | |||
666 | lua_call(L, 1, 1); | ||
667 | |||
668 | if (!lua_isstring(L, -1)) { | ||
669 | lua_pop(L, 2); | ||
670 | return SSL_TLSEXT_ERR_NOACK; | ||
671 | } | ||
672 | |||
673 | // Protocol list from server in wire-format string | ||
674 | server = luaL_checklstring(L, -1, &server_len); | ||
675 | ret = SSL_select_next_proto((unsigned char**)out, outlen, (const unsigned char*)server, | ||
676 | server_len, in, inlen); | ||
677 | if (ret != OPENSSL_NPN_NEGOTIATED) { | ||
678 | lua_pop(L, 2); | ||
679 | return SSL_TLSEXT_ERR_NOACK; | ||
680 | } | ||
681 | |||
682 | // Copy the result because lua_pop() can collect the pointer | ||
683 | ctx->alpn = malloc(*outlen); | ||
684 | memcpy(ctx->alpn, (void*)*out, *outlen); | ||
685 | *out = (const unsigned char*)ctx->alpn; | ||
686 | |||
687 | lua_pop(L, 2); | ||
688 | |||
689 | return SSL_TLSEXT_ERR_OK; | ||
690 | } | ||
691 | |||
692 | /** | ||
693 | * Set a callback a server can use to select the next protocol with ALPN. | ||
694 | */ | ||
695 | static int set_alpn_cb(lua_State *L) | ||
696 | { | ||
697 | p_context ctx = checkctx(L, 1); | ||
698 | |||
699 | luaL_getmetatable(L, "SSL:ALPN:Registry"); | ||
700 | lua_pushlightuserdata(L, (void*)ctx->context); | ||
701 | lua_pushvalue(L, 2); | ||
702 | lua_settable(L, -3); | ||
703 | |||
704 | SSL_CTX_set_alpn_select_cb(ctx->context, alpn_cb, ctx); | ||
705 | |||
706 | lua_pushboolean(L, 1); | ||
707 | return 1; | ||
708 | } | ||
709 | |||
710 | #if defined(LSEC_ENABLE_PSK) | ||
711 | /** | ||
712 | * Callback to select the PSK. | ||
713 | */ | ||
714 | static unsigned int server_psk_cb(SSL *ssl, const char *identity, unsigned char *psk, | ||
715 | unsigned int max_psk_len) | ||
716 | { | ||
717 | size_t psk_len; | ||
718 | const char *ret_psk; | ||
719 | SSL_CTX *ctx = SSL_get_SSL_CTX(ssl); | ||
720 | p_context pctx = (p_context)SSL_CTX_get_app_data(ctx); | ||
721 | lua_State *L = pctx->L; | ||
722 | |||
723 | luaL_getmetatable(L, "SSL:PSK:Registry"); | ||
724 | lua_pushlightuserdata(L, (void*)pctx->context); | ||
725 | lua_gettable(L, -2); | ||
726 | |||
727 | lua_pushstring(L, identity); | ||
728 | lua_pushinteger(L, max_psk_len); | ||
729 | |||
730 | lua_call(L, 2, 1); | ||
731 | |||
732 | if (!lua_isstring(L, -1)) { | ||
733 | lua_pop(L, 2); | ||
734 | return 0; | ||
735 | } | ||
736 | |||
737 | ret_psk = lua_tolstring(L, -1, &psk_len); | ||
738 | |||
739 | if (psk_len == 0 || psk_len > max_psk_len) | ||
740 | psk_len = 0; | ||
741 | else | ||
742 | memcpy(psk, ret_psk, psk_len); | ||
743 | |||
744 | lua_pop(L, 2); | ||
745 | |||
746 | return psk_len; | ||
747 | } | ||
748 | |||
749 | /** | ||
750 | * Set a PSK callback for server. | ||
751 | */ | ||
752 | static int set_server_psk_cb(lua_State *L) | ||
753 | { | ||
754 | p_context ctx = checkctx(L, 1); | ||
755 | |||
756 | luaL_getmetatable(L, "SSL:PSK:Registry"); | ||
757 | lua_pushlightuserdata(L, (void*)ctx->context); | ||
758 | lua_pushvalue(L, 2); | ||
759 | lua_settable(L, -3); | ||
760 | |||
761 | SSL_CTX_set_psk_server_callback(ctx->context, server_psk_cb); | ||
762 | |||
763 | lua_pushboolean(L, 1); | ||
764 | return 1; | ||
765 | } | ||
766 | |||
767 | /* | ||
768 | * Set the PSK indentity hint. | ||
769 | */ | ||
770 | static int set_psk_identity_hint(lua_State *L) | ||
771 | { | ||
772 | p_context ctx = checkctx(L, 1); | ||
773 | const char *hint = luaL_checkstring(L, 2); | ||
774 | int ret = SSL_CTX_use_psk_identity_hint(ctx->context, hint); | ||
775 | lua_pushboolean(L, ret); | ||
776 | return 1; | ||
777 | } | ||
778 | |||
779 | /* | ||
780 | * Client callback to PSK. | ||
781 | */ | ||
782 | static unsigned int client_psk_cb(SSL *ssl, const char *hint, char *identity, | ||
783 | unsigned int max_identity_len, unsigned char *psk, unsigned int max_psk_len) | ||
784 | { | ||
785 | size_t psk_len; | ||
786 | size_t identity_len; | ||
787 | const char *ret_psk; | ||
788 | const char *ret_identity; | ||
789 | SSL_CTX *ctx = SSL_get_SSL_CTX(ssl); | ||
790 | p_context pctx = (p_context)SSL_CTX_get_app_data(ctx); | ||
791 | lua_State *L = pctx->L; | ||
792 | |||
793 | luaL_getmetatable(L, "SSL:PSK:Registry"); | ||
794 | lua_pushlightuserdata(L, (void*)pctx->context); | ||
795 | lua_gettable(L, -2); | ||
796 | |||
797 | if (hint) | ||
798 | lua_pushstring(L, hint); | ||
799 | else | ||
800 | lua_pushnil(L); | ||
801 | |||
802 | // Leave space to '\0' | ||
803 | lua_pushinteger(L, max_identity_len-1); | ||
804 | lua_pushinteger(L, max_psk_len); | ||
805 | |||
806 | lua_call(L, 3, 2); | ||
807 | |||
808 | if (!lua_isstring(L, -1) || !lua_isstring(L, -2)) { | ||
809 | lua_pop(L, 3); | ||
810 | return 0; | ||
811 | } | ||
812 | |||
813 | ret_identity = lua_tolstring(L, -2, &identity_len); | ||
814 | ret_psk = lua_tolstring(L, -1, &psk_len); | ||
815 | |||
816 | if (identity_len >= max_identity_len || psk_len > max_psk_len) | ||
817 | psk_len = 0; | ||
818 | else { | ||
819 | memcpy(identity, ret_identity, identity_len); | ||
820 | identity[identity_len] = 0; | ||
821 | memcpy(psk, ret_psk, psk_len); | ||
822 | } | ||
823 | |||
824 | lua_pop(L, 3); | ||
825 | |||
826 | return psk_len; | ||
827 | } | ||
828 | |||
829 | /** | ||
830 | * Set a PSK callback for client. | ||
831 | */ | ||
832 | static int set_client_psk_cb(lua_State *L) { | ||
833 | p_context ctx = checkctx(L, 1); | ||
834 | |||
835 | luaL_getmetatable(L, "SSL:PSK:Registry"); | ||
836 | lua_pushlightuserdata(L, (void*)ctx->context); | ||
837 | lua_pushvalue(L, 2); | ||
838 | lua_settable(L, -3); | ||
839 | |||
840 | SSL_CTX_set_psk_client_callback(ctx->context, client_psk_cb); | ||
841 | |||
842 | lua_pushboolean(L, 1); | ||
843 | return 1; | ||
844 | } | ||
845 | #endif | ||
846 | |||
847 | #if defined(LSEC_ENABLE_DANE) | ||
848 | /* | ||
849 | * DANE | ||
850 | */ | ||
851 | static int dane_options[] = { | ||
852 | /* TODO move into options.c | ||
853 | * however this symbol is not from openssl/ssl.h but rather from | ||
854 | * openssl/x509_vfy.h | ||
855 | * */ | ||
856 | #ifdef DANE_FLAG_NO_DANE_EE_NAMECHECKS | ||
857 | DANE_FLAG_NO_DANE_EE_NAMECHECKS, | ||
858 | #endif | ||
859 | 0 | ||
860 | }; | ||
861 | static const char *dane_option_names[] = { | ||
862 | #ifdef DANE_FLAG_NO_DANE_EE_NAMECHECKS | ||
863 | "no_ee_namechecks", | ||
864 | #endif | ||
865 | NULL | ||
866 | }; | ||
867 | |||
868 | static int set_dane(lua_State *L) | ||
869 | { | ||
870 | int ret, i; | ||
871 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
872 | ret = SSL_CTX_dane_enable(ctx); | ||
873 | for (i = 2; ret > 0 && i <= lua_gettop(L); i++) { | ||
874 | ret = SSL_CTX_dane_set_flags(ctx, dane_options[luaL_checkoption(L, i, NULL, dane_option_names)]); | ||
875 | } | ||
876 | lua_pushboolean(L, (ret > 0)); | ||
877 | return 1; | ||
878 | } | ||
879 | #endif | ||
880 | |||
881 | /** | ||
882 | * Package functions | ||
883 | */ | ||
884 | static luaL_Reg funcs[] = { | ||
885 | {"create", create}, | ||
886 | {"locations", load_locations}, | ||
887 | {"loadcert", load_cert}, | ||
888 | {"loadkey", load_key}, | ||
889 | {"checkkey", check_key}, | ||
890 | {"setalpn", set_alpn}, | ||
891 | {"setalpncb", set_alpn_cb}, | ||
892 | {"setcipher", set_cipher}, | ||
893 | {"setciphersuites", set_ciphersuites}, | ||
894 | {"setdepth", set_depth}, | ||
895 | {"setdhparam", set_dhparam}, | ||
896 | {"setverify", set_verify}, | ||
897 | {"setoptions", set_options}, | ||
898 | #if defined(LSEC_ENABLE_PSK) | ||
899 | {"setpskhint", set_psk_identity_hint}, | ||
900 | {"setserverpskcb", set_server_psk_cb}, | ||
901 | {"setclientpskcb", set_client_psk_cb}, | ||
902 | #endif | ||
903 | {"setmode", set_mode}, | ||
904 | #if !defined(OPENSSL_NO_EC) | ||
905 | {"setcurve", set_curve}, | ||
906 | {"setcurveslist", set_curves_list}, | ||
907 | #endif | ||
908 | #if defined(LSEC_ENABLE_DANE) | ||
909 | {"setdane", set_dane}, | ||
910 | #endif | ||
911 | {NULL, NULL} | ||
912 | }; | ||
913 | |||
914 | /*-------------------------------- Metamethods -------------------------------*/ | ||
915 | |||
916 | /** | ||
917 | * Collect SSL context -- GC metamethod. | ||
918 | */ | ||
919 | static int meth_destroy(lua_State *L) | ||
920 | { | ||
921 | p_context ctx = checkctx(L, 1); | ||
922 | if (ctx->context) { | ||
923 | /* Clear registries */ | ||
924 | luaL_getmetatable(L, "SSL:DH:Registry"); | ||
925 | lua_pushlightuserdata(L, (void*)ctx->context); | ||
926 | lua_pushnil(L); | ||
927 | lua_settable(L, -3); | ||
928 | luaL_getmetatable(L, "SSL:Verify:Registry"); | ||
929 | lua_pushlightuserdata(L, (void*)ctx->context); | ||
930 | lua_pushnil(L); | ||
931 | lua_settable(L, -3); | ||
932 | luaL_getmetatable(L, "SSL:ALPN:Registry"); | ||
933 | lua_pushlightuserdata(L, (void*)ctx->context); | ||
934 | lua_pushnil(L); | ||
935 | lua_settable(L, -3); | ||
936 | luaL_getmetatable(L, "SSL:PSK:Registry"); | ||
937 | lua_pushlightuserdata(L, (void*)ctx->context); | ||
938 | lua_pushnil(L); | ||
939 | lua_settable(L, -3); | ||
940 | |||
941 | SSL_CTX_free(ctx->context); | ||
942 | ctx->context = NULL; | ||
943 | } | ||
944 | return 0; | ||
945 | } | ||
946 | |||
947 | /** | ||
948 | * Object information -- tostring metamethod. | ||
949 | */ | ||
950 | static int meth_tostring(lua_State *L) | ||
951 | { | ||
952 | p_context ctx = checkctx(L, 1); | ||
953 | lua_pushfstring(L, "SSL context: %p", ctx); | ||
954 | return 1; | ||
955 | } | ||
956 | |||
957 | /** | ||
958 | * Set extra flags for handshake verification. | ||
959 | */ | ||
960 | static int meth_set_verify_ext(lua_State *L) | ||
961 | { | ||
962 | int i; | ||
963 | const char *str; | ||
964 | int crl_flag = 0; | ||
965 | int lsec_flag = 0; | ||
966 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
967 | int max = lua_gettop(L); | ||
968 | for (i = 2; i <= max; i++) { | ||
969 | str = luaL_checkstring(L, i); | ||
970 | if (!strcmp(str, "lsec_continue")) { | ||
971 | lsec_flag |= LSEC_VERIFY_CONTINUE; | ||
972 | } else if (!strcmp(str, "lsec_ignore_purpose")) { | ||
973 | lsec_flag |= LSEC_VERIFY_IGNORE_PURPOSE; | ||
974 | } else if (!strcmp(str, "crl_check")) { | ||
975 | crl_flag |= X509_V_FLAG_CRL_CHECK; | ||
976 | } else if (!strcmp(str, "crl_check_chain")) { | ||
977 | crl_flag |= X509_V_FLAG_CRL_CHECK_ALL; | ||
978 | } else { | ||
979 | lua_pushboolean(L, 0); | ||
980 | lua_pushfstring(L, "invalid verify option (%s)", str); | ||
981 | return 2; | ||
982 | } | ||
983 | } | ||
984 | /* Set callback? */ | ||
985 | if (lsec_flag) { | ||
986 | SSL_CTX_set_verify(ctx, SSL_CTX_get_verify_mode(ctx), verify_cb); | ||
987 | SSL_CTX_set_cert_verify_callback(ctx, cert_verify_cb, (void*)ctx); | ||
988 | /* Save flag */ | ||
989 | luaL_getmetatable(L, "SSL:Verify:Registry"); | ||
990 | lua_pushlightuserdata(L, (void*)ctx); | ||
991 | lua_pushnumber(L, lsec_flag); | ||
992 | lua_settable(L, -3); | ||
993 | } else { | ||
994 | SSL_CTX_set_verify(ctx, SSL_CTX_get_verify_mode(ctx), NULL); | ||
995 | SSL_CTX_set_cert_verify_callback(ctx, NULL, NULL); | ||
996 | /* Remove flag */ | ||
997 | luaL_getmetatable(L, "SSL:Verify:Registry"); | ||
998 | lua_pushlightuserdata(L, (void*)ctx); | ||
999 | lua_pushnil(L); | ||
1000 | lua_settable(L, -3); | ||
1001 | } | ||
1002 | |||
1003 | /* X509 flag */ | ||
1004 | X509_STORE_set_flags(SSL_CTX_get_cert_store(ctx), crl_flag); | ||
1005 | |||
1006 | /* Ok */ | ||
1007 | lua_pushboolean(L, 1); | ||
1008 | return 1; | ||
1009 | } | ||
1010 | |||
1011 | /** | ||
1012 | * Context metamethods. | ||
1013 | */ | ||
1014 | static luaL_Reg meta[] = { | ||
1015 | {"__close", meth_destroy}, | ||
1016 | {"__gc", meth_destroy}, | ||
1017 | {"__tostring", meth_tostring}, | ||
1018 | {NULL, NULL} | ||
1019 | }; | ||
1020 | |||
1021 | /** | ||
1022 | * Index metamethods. | ||
1023 | */ | ||
1024 | static luaL_Reg meta_index[] = { | ||
1025 | {"setverifyext", meth_set_verify_ext}, | ||
1026 | {NULL, NULL} | ||
1027 | }; | ||
1028 | |||
1029 | |||
1030 | /*----------------------------- Public Functions ---------------------------*/ | ||
1031 | |||
1032 | /** | ||
1033 | * Retrieve the SSL context from the Lua stack. | ||
1034 | */ | ||
1035 | SSL_CTX* lsec_checkcontext(lua_State *L, int idx) | ||
1036 | { | ||
1037 | p_context ctx = checkctx(L, idx); | ||
1038 | return ctx->context; | ||
1039 | } | ||
1040 | |||
1041 | SSL_CTX* lsec_testcontext(lua_State *L, int idx) | ||
1042 | { | ||
1043 | p_context ctx = testctx(L, idx); | ||
1044 | return (ctx) ? ctx->context : NULL; | ||
1045 | } | ||
1046 | |||
1047 | /** | ||
1048 | * Retrieve the mode from the context in the Lua stack. | ||
1049 | */ | ||
1050 | int lsec_getmode(lua_State *L, int idx) | ||
1051 | { | ||
1052 | p_context ctx = checkctx(L, idx); | ||
1053 | return ctx->mode; | ||
1054 | } | ||
1055 | |||
1056 | /*-- Compat - Lua 5.1 --*/ | ||
1057 | #if (LUA_VERSION_NUM == 501) | ||
1058 | |||
1059 | void *lsec_testudata (lua_State *L, int ud, const char *tname) { | ||
1060 | void *p = lua_touserdata(L, ud); | ||
1061 | if (p != NULL) { /* value is a userdata? */ | ||
1062 | if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ | ||
1063 | luaL_getmetatable(L, tname); /* get correct metatable */ | ||
1064 | if (!lua_rawequal(L, -1, -2)) /* not the same? */ | ||
1065 | p = NULL; /* value is a userdata with wrong metatable */ | ||
1066 | lua_pop(L, 2); /* remove both metatables */ | ||
1067 | return p; | ||
1068 | } | ||
1069 | } | ||
1070 | return NULL; /* value is not a userdata with a metatable */ | ||
1071 | } | ||
1072 | |||
1073 | #endif | ||
1074 | |||
1075 | /*------------------------------ Initialization ------------------------------*/ | ||
1076 | |||
1077 | /** | ||
1078 | * Registre the module. | ||
1079 | */ | ||
1080 | LSEC_API int luaopen_ssl_context(lua_State *L) | ||
1081 | { | ||
1082 | luaL_newmetatable(L, "SSL:DH:Registry"); /* Keep all DH callbacks */ | ||
1083 | luaL_newmetatable(L, "SSL:ALPN:Registry"); /* Keep all ALPN callbacks */ | ||
1084 | luaL_newmetatable(L, "SSL:PSK:Registry"); /* Keep all PSK callbacks */ | ||
1085 | luaL_newmetatable(L, "SSL:Verify:Registry"); /* Keep all verify flags */ | ||
1086 | luaL_newmetatable(L, "SSL:Context"); | ||
1087 | setfuncs(L, meta); | ||
1088 | |||
1089 | /* Create __index metamethods for context */ | ||
1090 | luaL_newlib(L, meta_index); | ||
1091 | lua_setfield(L, -2, "__index"); | ||
1092 | |||
1093 | lsec_load_curves(L); | ||
1094 | |||
1095 | /* Return the module */ | ||
1096 | luaL_newlib(L, funcs); | ||
1097 | |||
1098 | return 1; | ||
1099 | } | ||
diff --git a/vendor/luasec/src/context.h b/vendor/luasec/src/context.h new file mode 100644 index 00000000..dd6bd098 --- /dev/null +++ b/vendor/luasec/src/context.h | |||
@@ -0,0 +1,47 @@ | |||
1 | #ifndef LSEC_CONTEXT_H | ||
2 | #define LSEC_CONTEXT_H | ||
3 | |||
4 | /*-------------------------------------------------------------------------- | ||
5 | * LuaSec 1.3.2 | ||
6 | * | ||
7 | * Copyright (C) 2006-2023 Bruno Silvestre | ||
8 | * | ||
9 | *--------------------------------------------------------------------------*/ | ||
10 | |||
11 | #include <lua.h> | ||
12 | #include <openssl/ssl.h> | ||
13 | |||
14 | #include "compat.h" | ||
15 | |||
16 | #define LSEC_MODE_INVALID 0 | ||
17 | #define LSEC_MODE_SERVER 1 | ||
18 | #define LSEC_MODE_CLIENT 2 | ||
19 | |||
20 | #define LSEC_VERIFY_CONTINUE 1 | ||
21 | #define LSEC_VERIFY_IGNORE_PURPOSE 2 | ||
22 | |||
23 | typedef struct t_context_ { | ||
24 | SSL_CTX *context; | ||
25 | lua_State *L; | ||
26 | DH *dh_param; | ||
27 | void *alpn; | ||
28 | int mode; | ||
29 | } t_context; | ||
30 | typedef t_context* p_context; | ||
31 | |||
32 | /* Retrieve the SSL context from the Lua stack */ | ||
33 | SSL_CTX *lsec_checkcontext(lua_State *L, int idx); | ||
34 | SSL_CTX *lsec_testcontext(lua_State *L, int idx); | ||
35 | |||
36 | /* Retrieve the mode from the context in the Lua stack */ | ||
37 | int lsec_getmode(lua_State *L, int idx); | ||
38 | |||
39 | /* Registre the module. */ | ||
40 | LSEC_API int luaopen_ssl_context(lua_State *L); | ||
41 | |||
42 | /* Compat - Lua 5.1 */ | ||
43 | #if (LUA_VERSION_NUM == 501) | ||
44 | void *lsec_testudata (lua_State *L, int ud, const char *tname); | ||
45 | #endif | ||
46 | |||
47 | #endif | ||
diff --git a/vendor/luasec/src/ec.c b/vendor/luasec/src/ec.c new file mode 100644 index 00000000..c7025a55 --- /dev/null +++ b/vendor/luasec/src/ec.c | |||
@@ -0,0 +1,116 @@ | |||
1 | /*-------------------------------------------------------------------------- | ||
2 | * LuaSec 1.3.2 | ||
3 | * | ||
4 | * Copyright (C) 2006-2023 Bruno Silvestre | ||
5 | * | ||
6 | *--------------------------------------------------------------------------*/ | ||
7 | |||
8 | #include <openssl/objects.h> | ||
9 | |||
10 | #include "ec.h" | ||
11 | |||
12 | #ifndef OPENSSL_NO_EC | ||
13 | |||
14 | EC_KEY *lsec_find_ec_key(lua_State *L, const char *str) | ||
15 | { | ||
16 | int nid; | ||
17 | lua_pushstring(L, "SSL:EC:CURVES"); | ||
18 | lua_rawget(L, LUA_REGISTRYINDEX); | ||
19 | lua_pushstring(L, str); | ||
20 | lua_rawget(L, -2); | ||
21 | |||
22 | if (!lua_isnumber(L, -1)) | ||
23 | return NULL; | ||
24 | |||
25 | nid = (int)lua_tonumber(L, -1); | ||
26 | return EC_KEY_new_by_curve_name(nid); | ||
27 | } | ||
28 | |||
29 | void lsec_load_curves(lua_State *L) | ||
30 | { | ||
31 | size_t i; | ||
32 | size_t size; | ||
33 | const char *name; | ||
34 | EC_builtin_curve *curves = NULL; | ||
35 | |||
36 | lua_pushstring(L, "SSL:EC:CURVES"); | ||
37 | lua_newtable(L); | ||
38 | |||
39 | size = EC_get_builtin_curves(NULL, 0); | ||
40 | if (size > 0) { | ||
41 | curves = (EC_builtin_curve*)malloc(sizeof(EC_builtin_curve) * size); | ||
42 | EC_get_builtin_curves(curves, size); | ||
43 | for (i = 0; i < size; i++) { | ||
44 | name = OBJ_nid2sn(curves[i].nid); | ||
45 | if (name != NULL) { | ||
46 | lua_pushstring(L, name); | ||
47 | lua_pushnumber(L, curves[i].nid); | ||
48 | lua_rawset(L, -3); | ||
49 | } | ||
50 | switch (curves[i].nid) { | ||
51 | case NID_X9_62_prime256v1: | ||
52 | lua_pushstring(L, "P-256"); | ||
53 | lua_pushnumber(L, curves[i].nid); | ||
54 | lua_rawset(L, -3); | ||
55 | break; | ||
56 | case NID_secp384r1: | ||
57 | lua_pushstring(L, "P-384"); | ||
58 | lua_pushnumber(L, curves[i].nid); | ||
59 | lua_rawset(L, -3); | ||
60 | break; | ||
61 | case NID_secp521r1: | ||
62 | lua_pushstring(L, "P-521"); | ||
63 | lua_pushnumber(L, curves[i].nid); | ||
64 | lua_rawset(L, -3); | ||
65 | break; | ||
66 | } | ||
67 | } | ||
68 | free(curves); | ||
69 | } | ||
70 | |||
71 | /* These are special so are manually added here */ | ||
72 | #ifdef NID_X25519 | ||
73 | lua_pushstring(L, "X25519"); | ||
74 | lua_pushnumber(L, NID_X25519); | ||
75 | lua_rawset(L, -3); | ||
76 | #endif | ||
77 | |||
78 | #ifdef NID_X448 | ||
79 | lua_pushstring(L, "X448"); | ||
80 | lua_pushnumber(L, NID_X448); | ||
81 | lua_rawset(L, -3); | ||
82 | #endif | ||
83 | |||
84 | lua_rawset(L, LUA_REGISTRYINDEX); | ||
85 | } | ||
86 | |||
87 | void lsec_get_curves(lua_State *L) | ||
88 | { | ||
89 | lua_newtable(L); | ||
90 | |||
91 | lua_pushstring(L, "SSL:EC:CURVES"); | ||
92 | lua_rawget(L, LUA_REGISTRYINDEX); | ||
93 | |||
94 | lua_pushnil(L); | ||
95 | while (lua_next(L, -2) != 0) { | ||
96 | lua_pop(L, 1); | ||
97 | lua_pushvalue(L, -1); | ||
98 | lua_pushboolean(L, 1); | ||
99 | lua_rawset(L, -5); | ||
100 | } | ||
101 | lua_pop(L, 1); | ||
102 | } | ||
103 | |||
104 | #else | ||
105 | |||
106 | void lsec_load_curves(lua_State *L) | ||
107 | { | ||
108 | // do nothing | ||
109 | } | ||
110 | |||
111 | void lsec_get_curves(lua_State *L) | ||
112 | { | ||
113 | lua_newtable(L); | ||
114 | } | ||
115 | |||
116 | #endif | ||
diff --git a/vendor/luasec/src/ec.h b/vendor/luasec/src/ec.h new file mode 100644 index 00000000..16d29360 --- /dev/null +++ b/vendor/luasec/src/ec.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /*-------------------------------------------------------------------------- | ||
2 | * LuaSec 1.3.2 | ||
3 | * | ||
4 | * Copyright (C) 2006-2023 Bruno Silvestre | ||
5 | * | ||
6 | *--------------------------------------------------------------------------*/ | ||
7 | |||
8 | #ifndef LSEC_EC_H | ||
9 | #define LSEC_EC_H | ||
10 | |||
11 | #include <lua.h> | ||
12 | |||
13 | #ifndef OPENSSL_NO_EC | ||
14 | #include <openssl/ec.h> | ||
15 | |||
16 | EC_KEY *lsec_find_ec_key(lua_State *L, const char *str); | ||
17 | #endif | ||
18 | |||
19 | void lsec_get_curves(lua_State *L); | ||
20 | void lsec_load_curves(lua_State *L); | ||
21 | |||
22 | #endif | ||
diff --git a/vendor/luasec/src/https.lua b/vendor/luasec/src/https.lua new file mode 100644 index 00000000..85cef361 --- /dev/null +++ b/vendor/luasec/src/https.lua | |||
@@ -0,0 +1,147 @@ | |||
1 | ---------------------------------------------------------------------------- | ||
2 | -- LuaSec 1.3.2 | ||
3 | -- | ||
4 | -- Copyright (C) 2009-2023 PUC-Rio | ||
5 | -- | ||
6 | -- Author: Pablo Musa | ||
7 | -- Author: Tomas Guisasola | ||
8 | --------------------------------------------------------------------------- | ||
9 | |||
10 | local socket = require("socket") | ||
11 | local ssl = require("ssl") | ||
12 | local ltn12 = require("ltn12") | ||
13 | local http = require("socket.http") | ||
14 | local url = require("socket.url") | ||
15 | |||
16 | local try = socket.try | ||
17 | |||
18 | -- | ||
19 | -- Module | ||
20 | -- | ||
21 | local _M = { | ||
22 | _VERSION = "1.3.2", | ||
23 | _COPYRIGHT = "LuaSec 1.3.2 - Copyright (C) 2009-2023 PUC-Rio", | ||
24 | PORT = 443, | ||
25 | TIMEOUT = 60 | ||
26 | } | ||
27 | |||
28 | -- TLS configuration | ||
29 | local cfg = { | ||
30 | protocol = "any", | ||
31 | options = {"all", "no_sslv2", "no_sslv3", "no_tlsv1"}, | ||
32 | verify = "none", | ||
33 | } | ||
34 | |||
35 | -------------------------------------------------------------------- | ||
36 | -- Auxiliar Functions | ||
37 | -------------------------------------------------------------------- | ||
38 | |||
39 | -- Insert default HTTPS port. | ||
40 | local function default_https_port(u) | ||
41 | return url.build(url.parse(u, {port = _M.PORT})) | ||
42 | end | ||
43 | |||
44 | -- Convert an URL to a table according to Luasocket needs. | ||
45 | local function urlstring_totable(url, body, result_table) | ||
46 | url = { | ||
47 | url = default_https_port(url), | ||
48 | method = body and "POST" or "GET", | ||
49 | sink = ltn12.sink.table(result_table) | ||
50 | } | ||
51 | if body then | ||
52 | url.source = ltn12.source.string(body) | ||
53 | url.headers = { | ||
54 | ["content-length"] = #body, | ||
55 | ["content-type"] = "application/x-www-form-urlencoded", | ||
56 | } | ||
57 | end | ||
58 | return url | ||
59 | end | ||
60 | |||
61 | -- Forward calls to the real connection object. | ||
62 | local function reg(conn) | ||
63 | local mt = getmetatable(conn.sock).__index | ||
64 | for name, method in pairs(mt) do | ||
65 | if type(method) == "function" then | ||
66 | conn[name] = function (self, ...) | ||
67 | return method(self.sock, ...) | ||
68 | end | ||
69 | end | ||
70 | end | ||
71 | end | ||
72 | |||
73 | -- Return a function which performs the SSL/TLS connection. | ||
74 | local function tcp(params) | ||
75 | params = params or {} | ||
76 | -- Default settings | ||
77 | for k, v in pairs(cfg) do | ||
78 | params[k] = params[k] or v | ||
79 | end | ||
80 | -- Force client mode | ||
81 | params.mode = "client" | ||
82 | -- 'create' function for LuaSocket | ||
83 | return function () | ||
84 | local conn = {} | ||
85 | conn.sock = try(socket.tcp()) | ||
86 | local st = getmetatable(conn.sock).__index.settimeout | ||
87 | function conn:settimeout(...) | ||
88 | return st(self.sock, _M.TIMEOUT) | ||
89 | end | ||
90 | -- Replace TCP's connection function | ||
91 | function conn:connect(host, port) | ||
92 | try(self.sock:connect(host, port)) | ||
93 | self.sock = try(ssl.wrap(self.sock, params)) | ||
94 | self.sock:sni(host) | ||
95 | self.sock:settimeout(_M.TIMEOUT) | ||
96 | try(self.sock:dohandshake()) | ||
97 | reg(self) | ||
98 | return 1 | ||
99 | end | ||
100 | return conn | ||
101 | end | ||
102 | end | ||
103 | |||
104 | -------------------------------------------------------------------- | ||
105 | -- Main Function | ||
106 | -------------------------------------------------------------------- | ||
107 | |||
108 | -- Make a HTTP request over secure connection. This function receives | ||
109 | -- the same parameters of LuaSocket's HTTP module (except 'proxy' and | ||
110 | -- 'redirect') plus LuaSec parameters. | ||
111 | -- | ||
112 | -- @param url mandatory (string or table) | ||
113 | -- @param body optional (string) | ||
114 | -- @return (string if url == string or 1), code, headers, status | ||
115 | -- | ||
116 | local function request(url, body) | ||
117 | local result_table = {} | ||
118 | local stringrequest = type(url) == "string" | ||
119 | if stringrequest then | ||
120 | url = urlstring_totable(url, body, result_table) | ||
121 | else | ||
122 | url.url = default_https_port(url.url) | ||
123 | end | ||
124 | if http.PROXY or url.proxy then | ||
125 | return nil, "proxy not supported" | ||
126 | elseif url.redirect then | ||
127 | return nil, "redirect not supported" | ||
128 | elseif url.create then | ||
129 | return nil, "create function not permitted" | ||
130 | end | ||
131 | -- New 'create' function to establish a secure connection | ||
132 | url.create = tcp(url) | ||
133 | local res, code, headers, status = http.request(url) | ||
134 | if res and stringrequest then | ||
135 | return table.concat(result_table), code, headers, status | ||
136 | end | ||
137 | return res, code, headers, status | ||
138 | end | ||
139 | |||
140 | -------------------------------------------------------------------------------- | ||
141 | -- Export module | ||
142 | -- | ||
143 | |||
144 | _M.request = request | ||
145 | _M.tcp = tcp | ||
146 | |||
147 | return _M | ||
diff --git a/vendor/luasec/src/luasocket/LICENSE b/vendor/luasec/src/luasocket/LICENSE new file mode 100644 index 00000000..eadb747b --- /dev/null +++ b/vendor/luasec/src/luasocket/LICENSE | |||
@@ -0,0 +1,21 @@ | |||
1 | LuaSocket 3.0-RC1 license | ||
2 | Copyright (C) 2004-2013 Diego Nehab | ||
3 | |||
4 | Permission is hereby granted, free of charge, to any person obtaining | ||
5 | a copy of this software and associated documentation files (the | ||
6 | "Software"), to deal in the Software without restriction, including | ||
7 | without limitation the rights to use, copy, modify, merge, publish, | ||
8 | distribute, sublicense, and/or sell copies of the Software, and to | ||
9 | permit persons to whom the Software is furnished to do so, subject to | ||
10 | the following conditions: | ||
11 | |||
12 | The above copyright notice and this permission notice shall be | ||
13 | included in all copies or substantial portions of the Software. | ||
14 | |||
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
18 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
19 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
20 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
21 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
diff --git a/vendor/luasec/src/luasocket/Makefile b/vendor/luasec/src/luasocket/Makefile new file mode 100644 index 00000000..b700fb63 --- /dev/null +++ b/vendor/luasec/src/luasocket/Makefile | |||
@@ -0,0 +1,26 @@ | |||
1 | OBJS= \ | ||
2 | io.o \ | ||
3 | buffer.o \ | ||
4 | timeout.o \ | ||
5 | usocket.o | ||
6 | |||
7 | CC ?= cc | ||
8 | CFLAGS += $(MYCFLAGS) -DLUASOCKET_DEBUG | ||
9 | AR ?= ar | ||
10 | RANLIB ?= ranlib | ||
11 | |||
12 | .PHONY: all clean | ||
13 | |||
14 | all: libluasocket.a | ||
15 | |||
16 | libluasocket.a: $(OBJS) | ||
17 | $(AR) rcu $@ $(OBJS) | ||
18 | $(RANLIB) $@ | ||
19 | |||
20 | clean: | ||
21 | rm -f $(OBJS) libluasocket.a | ||
22 | |||
23 | buffer.o: buffer.c buffer.h io.h timeout.h | ||
24 | io.o: io.c io.h timeout.h | ||
25 | timeout.o: timeout.c timeout.h | ||
26 | usocket.o: usocket.c socket.h io.h timeout.h usocket.h | ||
diff --git a/vendor/luasec/src/luasocket/buffer.c b/vendor/luasec/src/luasocket/buffer.c new file mode 100644 index 00000000..0eaac418 --- /dev/null +++ b/vendor/luasec/src/luasocket/buffer.c | |||
@@ -0,0 +1,278 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * Input/Output interface for Lua programs | ||
3 | * LuaSocket toolkit | ||
4 | \*=========================================================================*/ | ||
5 | #include "lua.h" | ||
6 | #include "lauxlib.h" | ||
7 | |||
8 | #include "buffer.h" | ||
9 | |||
10 | /*=========================================================================*\ | ||
11 | * Internal function prototypes | ||
12 | \*=========================================================================*/ | ||
13 | static int recvraw(p_buffer buf, size_t wanted, luaL_Buffer *b); | ||
14 | static int recvline(p_buffer buf, luaL_Buffer *b); | ||
15 | static int recvall(p_buffer buf, luaL_Buffer *b); | ||
16 | static int buffer_get(p_buffer buf, const char **data, size_t *count); | ||
17 | static void buffer_skip(p_buffer buf, size_t count); | ||
18 | static int sendraw(p_buffer buf, const char *data, size_t count, size_t *sent); | ||
19 | |||
20 | /* min and max macros */ | ||
21 | #ifndef MIN | ||
22 | #define MIN(x, y) ((x) < (y) ? x : y) | ||
23 | #endif | ||
24 | #ifndef MAX | ||
25 | #define MAX(x, y) ((x) > (y) ? x : y) | ||
26 | #endif | ||
27 | |||
28 | /*=========================================================================*\ | ||
29 | * Exported functions | ||
30 | \*=========================================================================*/ | ||
31 | /*-------------------------------------------------------------------------*\ | ||
32 | * Initializes module | ||
33 | \*-------------------------------------------------------------------------*/ | ||
34 | int buffer_open(lua_State *L) { | ||
35 | (void) L; | ||
36 | return 0; | ||
37 | } | ||
38 | |||
39 | /*-------------------------------------------------------------------------*\ | ||
40 | * Initializes C structure | ||
41 | \*-------------------------------------------------------------------------*/ | ||
42 | void buffer_init(p_buffer buf, p_io io, p_timeout tm) { | ||
43 | buf->first = buf->last = 0; | ||
44 | buf->io = io; | ||
45 | buf->tm = tm; | ||
46 | buf->received = buf->sent = 0; | ||
47 | buf->birthday = timeout_gettime(); | ||
48 | } | ||
49 | |||
50 | /*-------------------------------------------------------------------------*\ | ||
51 | * object:getstats() interface | ||
52 | \*-------------------------------------------------------------------------*/ | ||
53 | int buffer_meth_getstats(lua_State *L, p_buffer buf) { | ||
54 | lua_pushnumber(L, (lua_Number) buf->received); | ||
55 | lua_pushnumber(L, (lua_Number) buf->sent); | ||
56 | lua_pushnumber(L, timeout_gettime() - buf->birthday); | ||
57 | return 3; | ||
58 | } | ||
59 | |||
60 | /*-------------------------------------------------------------------------*\ | ||
61 | * object:setstats() interface | ||
62 | \*-------------------------------------------------------------------------*/ | ||
63 | int buffer_meth_setstats(lua_State *L, p_buffer buf) { | ||
64 | buf->received = (long) luaL_optnumber(L, 2, (lua_Number) buf->received); | ||
65 | buf->sent = (long) luaL_optnumber(L, 3, (lua_Number) buf->sent); | ||
66 | if (lua_isnumber(L, 4)) buf->birthday = timeout_gettime() - lua_tonumber(L, 4); | ||
67 | lua_pushnumber(L, 1); | ||
68 | return 1; | ||
69 | } | ||
70 | |||
71 | /*-------------------------------------------------------------------------*\ | ||
72 | * object:send() interface | ||
73 | \*-------------------------------------------------------------------------*/ | ||
74 | int buffer_meth_send(lua_State *L, p_buffer buf) { | ||
75 | int top = lua_gettop(L); | ||
76 | int err = IO_DONE; | ||
77 | size_t size = 0, sent = 0; | ||
78 | const char *data = luaL_checklstring(L, 2, &size); | ||
79 | long start = (long) luaL_optnumber(L, 3, 1); | ||
80 | long end = (long) luaL_optnumber(L, 4, -1); | ||
81 | timeout_markstart(buf->tm); | ||
82 | if (start < 0) start = (long) (size+start+1); | ||
83 | if (end < 0) end = (long) (size+end+1); | ||
84 | if (start < 1) start = (long) 1; | ||
85 | if (end > (long) size) end = (long) size; | ||
86 | if (start <= end) err = sendraw(buf, data+start-1, end-start+1, &sent); | ||
87 | /* check if there was an error */ | ||
88 | if (err != IO_DONE) { | ||
89 | lua_pushnil(L); | ||
90 | lua_pushstring(L, buf->io->error(buf->io->ctx, err)); | ||
91 | lua_pushnumber(L, (lua_Number) (sent+start-1)); | ||
92 | } else { | ||
93 | lua_pushnumber(L, (lua_Number) (sent+start-1)); | ||
94 | lua_pushnil(L); | ||
95 | lua_pushnil(L); | ||
96 | } | ||
97 | #ifdef LUASOCKET_DEBUG | ||
98 | /* push time elapsed during operation as the last return value */ | ||
99 | lua_pushnumber(L, timeout_gettime() - timeout_getstart(buf->tm)); | ||
100 | #endif | ||
101 | return lua_gettop(L) - top; | ||
102 | } | ||
103 | |||
104 | /*-------------------------------------------------------------------------*\ | ||
105 | * object:receive() interface | ||
106 | \*-------------------------------------------------------------------------*/ | ||
107 | int buffer_meth_receive(lua_State *L, p_buffer buf) { | ||
108 | luaL_Buffer b; | ||
109 | size_t size; | ||
110 | const char *part; | ||
111 | int err = IO_DONE; | ||
112 | int top = lua_gettop(L); | ||
113 | if (top < 3) { | ||
114 | lua_settop(L, 3); | ||
115 | top = 3; | ||
116 | } | ||
117 | part = luaL_optlstring(L, 3, "", &size); | ||
118 | timeout_markstart(buf->tm); | ||
119 | /* initialize buffer with optional extra prefix | ||
120 | * (useful for concatenating previous partial results) */ | ||
121 | luaL_buffinit(L, &b); | ||
122 | luaL_addlstring(&b, part, size); | ||
123 | /* receive new patterns */ | ||
124 | if (!lua_isnumber(L, 2)) { | ||
125 | const char *p= luaL_optstring(L, 2, "*l"); | ||
126 | if (p[0] == '*' && p[1] == 'l') err = recvline(buf, &b); | ||
127 | else if (p[0] == '*' && p[1] == 'a') err = recvall(buf, &b); | ||
128 | else luaL_argcheck(L, 0, 2, "invalid receive pattern"); | ||
129 | /* get a fixed number of bytes (minus what was already partially | ||
130 | * received) */ | ||
131 | } else { | ||
132 | double n = lua_tonumber(L, 2); | ||
133 | size_t wanted = (size_t) n; | ||
134 | luaL_argcheck(L, n >= 0, 2, "invalid receive pattern"); | ||
135 | if (size == 0 || wanted > size) | ||
136 | err = recvraw(buf, wanted-size, &b); | ||
137 | } | ||
138 | /* check if there was an error */ | ||
139 | if (err != IO_DONE) { | ||
140 | /* we can't push anything in the stack before pushing the | ||
141 | * contents of the buffer. this is the reason for the complication */ | ||
142 | luaL_pushresult(&b); | ||
143 | lua_pushstring(L, buf->io->error(buf->io->ctx, err)); | ||
144 | lua_pushvalue(L, -2); | ||
145 | lua_pushnil(L); | ||
146 | lua_replace(L, -4); | ||
147 | } else { | ||
148 | luaL_pushresult(&b); | ||
149 | lua_pushnil(L); | ||
150 | lua_pushnil(L); | ||
151 | } | ||
152 | #ifdef LUASOCKET_DEBUG | ||
153 | /* push time elapsed during operation as the last return value */ | ||
154 | lua_pushnumber(L, timeout_gettime() - timeout_getstart(buf->tm)); | ||
155 | #endif | ||
156 | return lua_gettop(L) - top; | ||
157 | } | ||
158 | |||
159 | /*-------------------------------------------------------------------------*\ | ||
160 | * Determines if there is any data in the read buffer | ||
161 | \*-------------------------------------------------------------------------*/ | ||
162 | int buffer_isempty(p_buffer buf) { | ||
163 | return buf->first >= buf->last; | ||
164 | } | ||
165 | |||
166 | /*=========================================================================*\ | ||
167 | * Internal functions | ||
168 | \*=========================================================================*/ | ||
169 | /*-------------------------------------------------------------------------*\ | ||
170 | * Sends a block of data (unbuffered) | ||
171 | \*-------------------------------------------------------------------------*/ | ||
172 | #define STEPSIZE 8192 | ||
173 | static int sendraw(p_buffer buf, const char *data, size_t count, size_t *sent) { | ||
174 | p_io io = buf->io; | ||
175 | p_timeout tm = buf->tm; | ||
176 | size_t total = 0; | ||
177 | int err = IO_DONE; | ||
178 | while (total < count && err == IO_DONE) { | ||
179 | size_t done = 0; | ||
180 | size_t step = (count-total <= STEPSIZE)? count-total: STEPSIZE; | ||
181 | err = io->send(io->ctx, data+total, step, &done, tm); | ||
182 | total += done; | ||
183 | } | ||
184 | *sent = total; | ||
185 | buf->sent += total; | ||
186 | return err; | ||
187 | } | ||
188 | |||
189 | /*-------------------------------------------------------------------------*\ | ||
190 | * Reads a fixed number of bytes (buffered) | ||
191 | \*-------------------------------------------------------------------------*/ | ||
192 | static int recvraw(p_buffer buf, size_t wanted, luaL_Buffer *b) { | ||
193 | int err = IO_DONE; | ||
194 | size_t total = 0; | ||
195 | while (err == IO_DONE) { | ||
196 | size_t count; const char *data; | ||
197 | err = buffer_get(buf, &data, &count); | ||
198 | count = MIN(count, wanted - total); | ||
199 | luaL_addlstring(b, data, count); | ||
200 | buffer_skip(buf, count); | ||
201 | total += count; | ||
202 | if (total >= wanted) break; | ||
203 | } | ||
204 | return err; | ||
205 | } | ||
206 | |||
207 | /*-------------------------------------------------------------------------*\ | ||
208 | * Reads everything until the connection is closed (buffered) | ||
209 | \*-------------------------------------------------------------------------*/ | ||
210 | static int recvall(p_buffer buf, luaL_Buffer *b) { | ||
211 | int err = IO_DONE; | ||
212 | size_t total = 0; | ||
213 | while (err == IO_DONE) { | ||
214 | const char *data; size_t count; | ||
215 | err = buffer_get(buf, &data, &count); | ||
216 | total += count; | ||
217 | luaL_addlstring(b, data, count); | ||
218 | buffer_skip(buf, count); | ||
219 | } | ||
220 | if (err == IO_CLOSED) { | ||
221 | if (total > 0) return IO_DONE; | ||
222 | else return IO_CLOSED; | ||
223 | } else return err; | ||
224 | } | ||
225 | |||
226 | /*-------------------------------------------------------------------------*\ | ||
227 | * Reads a line terminated by a CR LF pair or just by a LF. The CR and LF | ||
228 | * are not returned by the function and are discarded from the buffer | ||
229 | \*-------------------------------------------------------------------------*/ | ||
230 | static int recvline(p_buffer buf, luaL_Buffer *b) { | ||
231 | int err = IO_DONE; | ||
232 | while (err == IO_DONE) { | ||
233 | size_t count, pos; const char *data; | ||
234 | err = buffer_get(buf, &data, &count); | ||
235 | pos = 0; | ||
236 | while (pos < count && data[pos] != '\n') { | ||
237 | /* we ignore all \r's */ | ||
238 | if (data[pos] != '\r') luaL_addchar(b, data[pos]); | ||
239 | pos++; | ||
240 | } | ||
241 | if (pos < count) { /* found '\n' */ | ||
242 | buffer_skip(buf, pos+1); /* skip '\n' too */ | ||
243 | break; /* we are done */ | ||
244 | } else /* reached the end of the buffer */ | ||
245 | buffer_skip(buf, pos); | ||
246 | } | ||
247 | return err; | ||
248 | } | ||
249 | |||
250 | /*-------------------------------------------------------------------------*\ | ||
251 | * Skips a given number of bytes from read buffer. No data is read from the | ||
252 | * transport layer | ||
253 | \*-------------------------------------------------------------------------*/ | ||
254 | static void buffer_skip(p_buffer buf, size_t count) { | ||
255 | buf->received += count; | ||
256 | buf->first += count; | ||
257 | if (buffer_isempty(buf)) | ||
258 | buf->first = buf->last = 0; | ||
259 | } | ||
260 | |||
261 | /*-------------------------------------------------------------------------*\ | ||
262 | * Return any data available in buffer, or get more data from transport layer | ||
263 | * if buffer is empty | ||
264 | \*-------------------------------------------------------------------------*/ | ||
265 | static int buffer_get(p_buffer buf, const char **data, size_t *count) { | ||
266 | int err = IO_DONE; | ||
267 | p_io io = buf->io; | ||
268 | p_timeout tm = buf->tm; | ||
269 | if (buffer_isempty(buf)) { | ||
270 | size_t got; | ||
271 | err = io->recv(io->ctx, buf->data, BUF_SIZE, &got, tm); | ||
272 | buf->first = 0; | ||
273 | buf->last = got; | ||
274 | } | ||
275 | *count = buf->last - buf->first; | ||
276 | *data = buf->data + buf->first; | ||
277 | return err; | ||
278 | } | ||
diff --git a/vendor/luasec/src/luasocket/buffer.h b/vendor/luasec/src/luasocket/buffer.h new file mode 100644 index 00000000..1281bb39 --- /dev/null +++ b/vendor/luasec/src/luasocket/buffer.h | |||
@@ -0,0 +1,45 @@ | |||
1 | #ifndef BUF_H | ||
2 | #define BUF_H | ||
3 | /*=========================================================================*\ | ||
4 | * Input/Output interface for Lua programs | ||
5 | * LuaSocket toolkit | ||
6 | * | ||
7 | * Line patterns require buffering. Reading one character at a time involves | ||
8 | * too many system calls and is very slow. This module implements the | ||
9 | * LuaSocket interface for input/output on connected objects, as seen by | ||
10 | * Lua programs. | ||
11 | * | ||
12 | * Input is buffered. Output is *not* buffered because there was no simple | ||
13 | * way of making sure the buffered output data would ever be sent. | ||
14 | * | ||
15 | * The module is built on top of the I/O abstraction defined in io.h and the | ||
16 | * timeout management is done with the timeout.h interface. | ||
17 | \*=========================================================================*/ | ||
18 | #include "lua.h" | ||
19 | |||
20 | #include "io.h" | ||
21 | #include "timeout.h" | ||
22 | |||
23 | /* buffer size in bytes */ | ||
24 | #define BUF_SIZE 8192 | ||
25 | |||
26 | /* buffer control structure */ | ||
27 | typedef struct t_buffer_ { | ||
28 | double birthday; /* throttle support info: creation time, */ | ||
29 | size_t sent, received; /* bytes sent, and bytes received */ | ||
30 | p_io io; /* IO driver used for this buffer */ | ||
31 | p_timeout tm; /* timeout management for this buffer */ | ||
32 | size_t first, last; /* index of first and last bytes of stored data */ | ||
33 | char data[BUF_SIZE]; /* storage space for buffer data */ | ||
34 | } t_buffer; | ||
35 | typedef t_buffer *p_buffer; | ||
36 | |||
37 | int buffer_open(lua_State *L); | ||
38 | void buffer_init(p_buffer buf, p_io io, p_timeout tm); | ||
39 | int buffer_meth_send(lua_State *L, p_buffer buf); | ||
40 | int buffer_meth_receive(lua_State *L, p_buffer buf); | ||
41 | int buffer_meth_getstats(lua_State *L, p_buffer buf); | ||
42 | int buffer_meth_setstats(lua_State *L, p_buffer buf); | ||
43 | int buffer_isempty(p_buffer buf); | ||
44 | |||
45 | #endif /* BUF_H */ | ||
diff --git a/vendor/luasec/src/luasocket/io.c b/vendor/luasec/src/luasocket/io.c new file mode 100644 index 00000000..35f46f78 --- /dev/null +++ b/vendor/luasec/src/luasocket/io.c | |||
@@ -0,0 +1,30 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * Input/Output abstraction | ||
3 | * LuaSocket toolkit | ||
4 | \*=========================================================================*/ | ||
5 | #include "io.h" | ||
6 | |||
7 | /*=========================================================================*\ | ||
8 | * Exported functions | ||
9 | \*=========================================================================*/ | ||
10 | /*-------------------------------------------------------------------------*\ | ||
11 | * Initializes C structure | ||
12 | \*-------------------------------------------------------------------------*/ | ||
13 | void io_init(p_io io, p_send send, p_recv recv, p_error error, void *ctx) { | ||
14 | io->send = send; | ||
15 | io->recv = recv; | ||
16 | io->error = error; | ||
17 | io->ctx = ctx; | ||
18 | } | ||
19 | |||
20 | /*-------------------------------------------------------------------------*\ | ||
21 | * I/O error strings | ||
22 | \*-------------------------------------------------------------------------*/ | ||
23 | const char *io_strerror(int err) { | ||
24 | switch (err) { | ||
25 | case IO_DONE: return NULL; | ||
26 | case IO_CLOSED: return "closed"; | ||
27 | case IO_TIMEOUT: return "timeout"; | ||
28 | default: return "unknown error"; | ||
29 | } | ||
30 | } | ||
diff --git a/vendor/luasec/src/luasocket/io.h b/vendor/luasec/src/luasocket/io.h new file mode 100644 index 00000000..8945e2c0 --- /dev/null +++ b/vendor/luasec/src/luasocket/io.h | |||
@@ -0,0 +1,65 @@ | |||
1 | #ifndef IO_H | ||
2 | #define IO_H | ||
3 | /*=========================================================================*\ | ||
4 | * Input/Output abstraction | ||
5 | * LuaSocket toolkit | ||
6 | * | ||
7 | * This module defines the interface that LuaSocket expects from the | ||
8 | * transport layer for streamed input/output. The idea is that if any | ||
9 | * transport implements this interface, then the buffer.c functions | ||
10 | * automatically work on it. | ||
11 | * | ||
12 | * The module socket.h implements this interface, and thus the module tcp.h | ||
13 | * is very simple. | ||
14 | \*=========================================================================*/ | ||
15 | #include <stdio.h> | ||
16 | #include "lua.h" | ||
17 | |||
18 | #include "timeout.h" | ||
19 | |||
20 | /* IO error codes */ | ||
21 | enum { | ||
22 | IO_DONE = 0, /* operation completed successfully */ | ||
23 | IO_TIMEOUT = -1, /* operation timed out */ | ||
24 | IO_CLOSED = -2, /* the connection has been closed */ | ||
25 | IO_UNKNOWN = -3 | ||
26 | }; | ||
27 | |||
28 | /* interface to error message function */ | ||
29 | typedef const char *(*p_error) ( | ||
30 | void *ctx, /* context needed by send */ | ||
31 | int err /* error code */ | ||
32 | ); | ||
33 | |||
34 | /* interface to send function */ | ||
35 | typedef int (*p_send) ( | ||
36 | void *ctx, /* context needed by send */ | ||
37 | const char *data, /* pointer to buffer with data to send */ | ||
38 | size_t count, /* number of bytes to send from buffer */ | ||
39 | size_t *sent, /* number of bytes sent uppon return */ | ||
40 | p_timeout tm /* timeout control */ | ||
41 | ); | ||
42 | |||
43 | /* interface to recv function */ | ||
44 | typedef int (*p_recv) ( | ||
45 | void *ctx, /* context needed by recv */ | ||
46 | char *data, /* pointer to buffer where data will be written */ | ||
47 | size_t count, /* number of bytes to receive into buffer */ | ||
48 | size_t *got, /* number of bytes received uppon return */ | ||
49 | p_timeout tm /* timeout control */ | ||
50 | ); | ||
51 | |||
52 | /* IO driver definition */ | ||
53 | typedef struct t_io_ { | ||
54 | void *ctx; /* context needed by send/recv */ | ||
55 | p_send send; /* send function pointer */ | ||
56 | p_recv recv; /* receive function pointer */ | ||
57 | p_error error; /* strerror function */ | ||
58 | } t_io; | ||
59 | typedef t_io *p_io; | ||
60 | |||
61 | void io_init(p_io io, p_send send, p_recv recv, p_error error, void *ctx); | ||
62 | const char *io_strerror(int err); | ||
63 | |||
64 | #endif /* IO_H */ | ||
65 | |||
diff --git a/vendor/luasec/src/luasocket/socket.h b/vendor/luasec/src/luasocket/socket.h new file mode 100644 index 00000000..07c20fe3 --- /dev/null +++ b/vendor/luasec/src/luasocket/socket.h | |||
@@ -0,0 +1,78 @@ | |||
1 | #ifndef SOCKET_H | ||
2 | #define SOCKET_H | ||
3 | /*=========================================================================*\ | ||
4 | * Socket compatibilization module | ||
5 | * LuaSocket toolkit | ||
6 | * | ||
7 | * BSD Sockets and WinSock are similar, but there are a few irritating | ||
8 | * differences. Also, not all *nix platforms behave the same. This module | ||
9 | * (and the associated usocket.h and wsocket.h) factor these differences and | ||
10 | * creates a interface compatible with the io.h module. | ||
11 | \*=========================================================================*/ | ||
12 | #include "io.h" | ||
13 | |||
14 | /*=========================================================================*\ | ||
15 | * Platform specific compatibilization | ||
16 | \*=========================================================================*/ | ||
17 | #ifdef _WIN32 | ||
18 | #include "wsocket.h" | ||
19 | #else | ||
20 | #include "usocket.h" | ||
21 | #endif | ||
22 | |||
23 | /*=========================================================================*\ | ||
24 | * The connect and accept functions accept a timeout and their | ||
25 | * implementations are somewhat complicated. We chose to move | ||
26 | * the timeout control into this module for these functions in | ||
27 | * order to simplify the modules that use them. | ||
28 | \*=========================================================================*/ | ||
29 | #include "timeout.h" | ||
30 | |||
31 | /* we are lazy... */ | ||
32 | typedef struct sockaddr SA; | ||
33 | |||
34 | /*=========================================================================*\ | ||
35 | * Functions below implement a comfortable platform independent | ||
36 | * interface to sockets | ||
37 | \*=========================================================================*/ | ||
38 | int socket_open(void); | ||
39 | int socket_close(void); | ||
40 | void socket_destroy(p_socket ps); | ||
41 | void socket_shutdown(p_socket ps, int how); | ||
42 | int socket_sendto(p_socket ps, const char *data, size_t count, | ||
43 | size_t *sent, SA *addr, socklen_t addr_len, p_timeout tm); | ||
44 | int socket_recvfrom(p_socket ps, char *data, size_t count, | ||
45 | size_t *got, SA *addr, socklen_t *addr_len, p_timeout tm); | ||
46 | |||
47 | void socket_setnonblocking(p_socket ps); | ||
48 | void socket_setblocking(p_socket ps); | ||
49 | |||
50 | int socket_waitfd(p_socket ps, int sw, p_timeout tm); | ||
51 | int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, | ||
52 | p_timeout tm); | ||
53 | |||
54 | int socket_connect(p_socket ps, SA *addr, socklen_t addr_len, p_timeout tm); | ||
55 | int socket_create(p_socket ps, int domain, int type, int protocol); | ||
56 | int socket_bind(p_socket ps, SA *addr, socklen_t addr_len); | ||
57 | int socket_listen(p_socket ps, int backlog); | ||
58 | int socket_accept(p_socket ps, p_socket pa, SA *addr, | ||
59 | socklen_t *addr_len, p_timeout tm); | ||
60 | |||
61 | const char *socket_hoststrerror(int err); | ||
62 | const char *socket_gaistrerror(int err); | ||
63 | const char *socket_strerror(int err); | ||
64 | |||
65 | /* these are perfect to use with the io abstraction module | ||
66 | and the buffered input module */ | ||
67 | int socket_send(p_socket ps, const char *data, size_t count, | ||
68 | size_t *sent, p_timeout tm); | ||
69 | int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm); | ||
70 | int socket_write(p_socket ps, const char *data, size_t count, | ||
71 | size_t *sent, p_timeout tm); | ||
72 | int socket_read(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm); | ||
73 | const char *socket_ioerror(p_socket ps, int err); | ||
74 | |||
75 | int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp); | ||
76 | int socket_gethostbyname(const char *addr, struct hostent **hp); | ||
77 | |||
78 | #endif /* SOCKET_H */ | ||
diff --git a/vendor/luasec/src/luasocket/timeout.c b/vendor/luasec/src/luasocket/timeout.c new file mode 100644 index 00000000..94a524be --- /dev/null +++ b/vendor/luasec/src/luasocket/timeout.c | |||
@@ -0,0 +1,220 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * Timeout management functions | ||
3 | * LuaSocket toolkit | ||
4 | \*=========================================================================*/ | ||
5 | #include <stdio.h> | ||
6 | #include <limits.h> | ||
7 | #include <float.h> | ||
8 | |||
9 | #include "lua.h" | ||
10 | #include "lauxlib.h" | ||
11 | |||
12 | #include "timeout.h" | ||
13 | |||
14 | #ifdef _WIN32 | ||
15 | #include <windows.h> | ||
16 | #else | ||
17 | #include <time.h> | ||
18 | #include <sys/time.h> | ||
19 | #endif | ||
20 | |||
21 | /* min and max macros */ | ||
22 | #ifndef MIN | ||
23 | #define MIN(x, y) ((x) < (y) ? x : y) | ||
24 | #endif | ||
25 | #ifndef MAX | ||
26 | #define MAX(x, y) ((x) > (y) ? x : y) | ||
27 | #endif | ||
28 | |||
29 | /*=========================================================================*\ | ||
30 | * Internal function prototypes | ||
31 | \*=========================================================================*/ | ||
32 | static int timeout_lua_gettime(lua_State *L); | ||
33 | static int timeout_lua_sleep(lua_State *L); | ||
34 | |||
35 | static luaL_Reg func[] = { | ||
36 | { "gettime", timeout_lua_gettime }, | ||
37 | { "sleep", timeout_lua_sleep }, | ||
38 | { NULL, NULL } | ||
39 | }; | ||
40 | |||
41 | /*=========================================================================*\ | ||
42 | * Exported functions. | ||
43 | \*=========================================================================*/ | ||
44 | /*-------------------------------------------------------------------------*\ | ||
45 | * Initialize structure | ||
46 | \*-------------------------------------------------------------------------*/ | ||
47 | void timeout_init(p_timeout tm, double block, double total) { | ||
48 | tm->block = block; | ||
49 | tm->total = total; | ||
50 | } | ||
51 | |||
52 | /*-------------------------------------------------------------------------*\ | ||
53 | * Determines how much time we have left for the next system call, | ||
54 | * if the previous call was successful | ||
55 | * Input | ||
56 | * tm: timeout control structure | ||
57 | * Returns | ||
58 | * the number of ms left or -1 if there is no time limit | ||
59 | \*-------------------------------------------------------------------------*/ | ||
60 | double timeout_get(p_timeout tm) { | ||
61 | if (tm->block < 0.0 && tm->total < 0.0) { | ||
62 | return -1; | ||
63 | } else if (tm->block < 0.0) { | ||
64 | double t = tm->total - timeout_gettime() + tm->start; | ||
65 | return MAX(t, 0.0); | ||
66 | } else if (tm->total < 0.0) { | ||
67 | return tm->block; | ||
68 | } else { | ||
69 | double t = tm->total - timeout_gettime() + tm->start; | ||
70 | return MIN(tm->block, MAX(t, 0.0)); | ||
71 | } | ||
72 | } | ||
73 | |||
74 | /*-------------------------------------------------------------------------*\ | ||
75 | * Returns time since start of operation | ||
76 | * Input | ||
77 | * tm: timeout control structure | ||
78 | * Returns | ||
79 | * start field of structure | ||
80 | \*-------------------------------------------------------------------------*/ | ||
81 | double timeout_getstart(p_timeout tm) { | ||
82 | return tm->start; | ||
83 | } | ||
84 | |||
85 | /*-------------------------------------------------------------------------*\ | ||
86 | * Determines how much time we have left for the next system call, | ||
87 | * if the previous call was a failure | ||
88 | * Input | ||
89 | * tm: timeout control structure | ||
90 | * Returns | ||
91 | * the number of ms left or -1 if there is no time limit | ||
92 | \*-------------------------------------------------------------------------*/ | ||
93 | double timeout_getretry(p_timeout tm) { | ||
94 | if (tm->block < 0.0 && tm->total < 0.0) { | ||
95 | return -1; | ||
96 | } else if (tm->block < 0.0) { | ||
97 | double t = tm->total - timeout_gettime() + tm->start; | ||
98 | return MAX(t, 0.0); | ||
99 | } else if (tm->total < 0.0) { | ||
100 | double t = tm->block - timeout_gettime() + tm->start; | ||
101 | return MAX(t, 0.0); | ||
102 | } else { | ||
103 | double t = tm->total - timeout_gettime() + tm->start; | ||
104 | return MIN(tm->block, MAX(t, 0.0)); | ||
105 | } | ||
106 | } | ||
107 | |||
108 | /*-------------------------------------------------------------------------*\ | ||
109 | * Marks the operation start time in structure | ||
110 | * Input | ||
111 | * tm: timeout control structure | ||
112 | \*-------------------------------------------------------------------------*/ | ||
113 | p_timeout timeout_markstart(p_timeout tm) { | ||
114 | tm->start = timeout_gettime(); | ||
115 | return tm; | ||
116 | } | ||
117 | |||
118 | /*-------------------------------------------------------------------------*\ | ||
119 | * Gets time in s, relative to January 1, 1970 (UTC) | ||
120 | * Returns | ||
121 | * time in s. | ||
122 | \*-------------------------------------------------------------------------*/ | ||
123 | #ifdef _WIN32 | ||
124 | double timeout_gettime(void) { | ||
125 | FILETIME ft; | ||
126 | double t; | ||
127 | GetSystemTimeAsFileTime(&ft); | ||
128 | /* Windows file time (time since January 1, 1601 (UTC)) */ | ||
129 | t = ft.dwLowDateTime/1.0e7 + ft.dwHighDateTime*(4294967296.0/1.0e7); | ||
130 | /* convert to Unix Epoch time (time since January 1, 1970 (UTC)) */ | ||
131 | return (t - 11644473600.0); | ||
132 | } | ||
133 | #else | ||
134 | double timeout_gettime(void) { | ||
135 | struct timeval v; | ||
136 | gettimeofday(&v, (struct timezone *) NULL); | ||
137 | /* Unix Epoch time (time since January 1, 1970 (UTC)) */ | ||
138 | return v.tv_sec + v.tv_usec/1.0e6; | ||
139 | } | ||
140 | #endif | ||
141 | |||
142 | /*-------------------------------------------------------------------------*\ | ||
143 | * Initializes module | ||
144 | \*-------------------------------------------------------------------------*/ | ||
145 | int timeout_open(lua_State *L) { | ||
146 | #if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE) | ||
147 | luaL_setfuncs(L, func, 0); | ||
148 | #else | ||
149 | luaL_openlib(L, NULL, func, 0); | ||
150 | #endif | ||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | /*-------------------------------------------------------------------------*\ | ||
155 | * Sets timeout values for IO operations | ||
156 | * Lua Input: base, time [, mode] | ||
157 | * time: time out value in seconds | ||
158 | * mode: "b" for block timeout, "t" for total timeout. (default: b) | ||
159 | \*-------------------------------------------------------------------------*/ | ||
160 | int timeout_meth_settimeout(lua_State *L, p_timeout tm) { | ||
161 | double t = luaL_optnumber(L, 2, -1); | ||
162 | const char *mode = luaL_optstring(L, 3, "b"); | ||
163 | switch (*mode) { | ||
164 | case 'b': | ||
165 | tm->block = t; | ||
166 | break; | ||
167 | case 'r': case 't': | ||
168 | tm->total = t; | ||
169 | break; | ||
170 | default: | ||
171 | luaL_argcheck(L, 0, 3, "invalid timeout mode"); | ||
172 | break; | ||
173 | } | ||
174 | lua_pushnumber(L, 1); | ||
175 | return 1; | ||
176 | } | ||
177 | |||
178 | /*=========================================================================*\ | ||
179 | * Test support functions | ||
180 | \*=========================================================================*/ | ||
181 | /*-------------------------------------------------------------------------*\ | ||
182 | * Returns the time the system has been up, in secconds. | ||
183 | \*-------------------------------------------------------------------------*/ | ||
184 | static int timeout_lua_gettime(lua_State *L) | ||
185 | { | ||
186 | lua_pushnumber(L, timeout_gettime()); | ||
187 | return 1; | ||
188 | } | ||
189 | |||
190 | /*-------------------------------------------------------------------------*\ | ||
191 | * Sleep for n seconds. | ||
192 | \*-------------------------------------------------------------------------*/ | ||
193 | #ifdef _WIN32 | ||
194 | int timeout_lua_sleep(lua_State *L) | ||
195 | { | ||
196 | double n = luaL_checknumber(L, 1); | ||
197 | if (n < 0.0) n = 0.0; | ||
198 | if (n < DBL_MAX/1000.0) n *= 1000.0; | ||
199 | if (n > INT_MAX) n = INT_MAX; | ||
200 | Sleep((int)n); | ||
201 | return 0; | ||
202 | } | ||
203 | #else | ||
204 | int timeout_lua_sleep(lua_State *L) | ||
205 | { | ||
206 | double n = luaL_checknumber(L, 1); | ||
207 | struct timespec t, r; | ||
208 | if (n < 0.0) n = 0.0; | ||
209 | if (n > INT_MAX) n = INT_MAX; | ||
210 | t.tv_sec = (int) n; | ||
211 | n -= t.tv_sec; | ||
212 | t.tv_nsec = (int) (n * 1000000000); | ||
213 | if (t.tv_nsec >= 1000000000) t.tv_nsec = 999999999; | ||
214 | while (nanosleep(&t, &r) != 0) { | ||
215 | t.tv_sec = r.tv_sec; | ||
216 | t.tv_nsec = r.tv_nsec; | ||
217 | } | ||
218 | return 0; | ||
219 | } | ||
220 | #endif | ||
diff --git a/vendor/luasec/src/luasocket/timeout.h b/vendor/luasec/src/luasocket/timeout.h new file mode 100644 index 00000000..4957593b --- /dev/null +++ b/vendor/luasec/src/luasocket/timeout.h | |||
@@ -0,0 +1,28 @@ | |||
1 | #ifndef TIMEOUT_H | ||
2 | #define TIMEOUT_H | ||
3 | /*=========================================================================*\ | ||
4 | * Timeout management functions | ||
5 | * LuaSocket toolkit | ||
6 | \*=========================================================================*/ | ||
7 | #include "lua.h" | ||
8 | |||
9 | /* timeout control structure */ | ||
10 | typedef struct t_timeout_ { | ||
11 | double block; /* maximum time for blocking calls */ | ||
12 | double total; /* total number of milliseconds for operation */ | ||
13 | double start; /* time of start of operation */ | ||
14 | } t_timeout; | ||
15 | typedef t_timeout *p_timeout; | ||
16 | |||
17 | int timeout_open(lua_State *L); | ||
18 | void timeout_init(p_timeout tm, double block, double total); | ||
19 | double timeout_get(p_timeout tm); | ||
20 | double timeout_getretry(p_timeout tm); | ||
21 | p_timeout timeout_markstart(p_timeout tm); | ||
22 | double timeout_getstart(p_timeout tm); | ||
23 | double timeout_gettime(void); | ||
24 | int timeout_meth_settimeout(lua_State *L, p_timeout tm); | ||
25 | |||
26 | #define timeout_iszero(tm) ((tm)->block == 0.0) | ||
27 | |||
28 | #endif /* TIMEOUT_H */ | ||
diff --git a/vendor/luasec/src/luasocket/usocket.c b/vendor/luasec/src/luasocket/usocket.c new file mode 100644 index 00000000..49e618c4 --- /dev/null +++ b/vendor/luasec/src/luasocket/usocket.c | |||
@@ -0,0 +1,441 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * Socket compatibilization module for Unix | ||
3 | * LuaSocket toolkit | ||
4 | * | ||
5 | * The code is now interrupt-safe. | ||
6 | * The penalty of calling select to avoid busy-wait is only paid when | ||
7 | * the I/O call fail in the first place. | ||
8 | \*=========================================================================*/ | ||
9 | #include <string.h> | ||
10 | #include <signal.h> | ||
11 | |||
12 | #include "socket.h" | ||
13 | |||
14 | /*-------------------------------------------------------------------------*\ | ||
15 | * Wait for readable/writable/connected socket with timeout | ||
16 | \*-------------------------------------------------------------------------*/ | ||
17 | #ifndef SOCKET_SELECT | ||
18 | int socket_waitfd(p_socket ps, int sw, p_timeout tm) { | ||
19 | int ret; | ||
20 | struct pollfd pfd; | ||
21 | pfd.fd = *ps; | ||
22 | pfd.events = sw; | ||
23 | pfd.revents = 0; | ||
24 | if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */ | ||
25 | do { | ||
26 | int t = (int)(timeout_getretry(tm)*1e3); | ||
27 | ret = poll(&pfd, 1, t >= 0? t: -1); | ||
28 | } while (ret == -1 && errno == EINTR); | ||
29 | if (ret == -1) return errno; | ||
30 | if (ret == 0) return IO_TIMEOUT; | ||
31 | if (sw == WAITFD_C && (pfd.revents & (POLLIN|POLLERR))) return IO_CLOSED; | ||
32 | return IO_DONE; | ||
33 | } | ||
34 | #else | ||
35 | int socket_waitfd(p_socket ps, int sw, p_timeout tm) { | ||
36 | int ret; | ||
37 | fd_set rfds, wfds, *rp, *wp; | ||
38 | struct timeval tv, *tp; | ||
39 | double t; | ||
40 | if (*ps >= FD_SETSIZE) return EINVAL; | ||
41 | if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */ | ||
42 | do { | ||
43 | /* must set bits within loop, because select may have modified them */ | ||
44 | rp = wp = NULL; | ||
45 | if (sw & WAITFD_R) { FD_ZERO(&rfds); FD_SET(*ps, &rfds); rp = &rfds; } | ||
46 | if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; } | ||
47 | t = timeout_getretry(tm); | ||
48 | tp = NULL; | ||
49 | if (t >= 0.0) { | ||
50 | tv.tv_sec = (int)t; | ||
51 | tv.tv_usec = (int)((t-tv.tv_sec)*1.0e6); | ||
52 | tp = &tv; | ||
53 | } | ||
54 | ret = select(*ps+1, rp, wp, NULL, tp); | ||
55 | } while (ret == -1 && errno == EINTR); | ||
56 | if (ret == -1) return errno; | ||
57 | if (ret == 0) return IO_TIMEOUT; | ||
58 | if (sw == WAITFD_C && FD_ISSET(*ps, &rfds)) return IO_CLOSED; | ||
59 | return IO_DONE; | ||
60 | } | ||
61 | #endif | ||
62 | |||
63 | |||
64 | /*-------------------------------------------------------------------------*\ | ||
65 | * Initializes module | ||
66 | \*-------------------------------------------------------------------------*/ | ||
67 | int socket_open(void) { | ||
68 | /* instals a handler to ignore sigpipe or it will crash us */ | ||
69 | signal(SIGPIPE, SIG_IGN); | ||
70 | return 1; | ||
71 | } | ||
72 | |||
73 | /*-------------------------------------------------------------------------*\ | ||
74 | * Close module | ||
75 | \*-------------------------------------------------------------------------*/ | ||
76 | int socket_close(void) { | ||
77 | return 1; | ||
78 | } | ||
79 | |||
80 | /*-------------------------------------------------------------------------*\ | ||
81 | * Close and inutilize socket | ||
82 | \*-------------------------------------------------------------------------*/ | ||
83 | void socket_destroy(p_socket ps) { | ||
84 | if (*ps != SOCKET_INVALID) { | ||
85 | socket_setblocking(ps); | ||
86 | close(*ps); | ||
87 | *ps = SOCKET_INVALID; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | /*-------------------------------------------------------------------------*\ | ||
92 | * Select with timeout control | ||
93 | \*-------------------------------------------------------------------------*/ | ||
94 | int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, | ||
95 | p_timeout tm) { | ||
96 | int ret; | ||
97 | do { | ||
98 | struct timeval tv; | ||
99 | double t = timeout_getretry(tm); | ||
100 | tv.tv_sec = (int) t; | ||
101 | tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6); | ||
102 | /* timeout = 0 means no wait */ | ||
103 | ret = select(n, rfds, wfds, efds, t >= 0.0 ? &tv: NULL); | ||
104 | } while (ret < 0 && errno == EINTR); | ||
105 | return ret; | ||
106 | } | ||
107 | |||
108 | /*-------------------------------------------------------------------------*\ | ||
109 | * Creates and sets up a socket | ||
110 | \*-------------------------------------------------------------------------*/ | ||
111 | int socket_create(p_socket ps, int domain, int type, int protocol) { | ||
112 | *ps = socket(domain, type, protocol); | ||
113 | if (*ps != SOCKET_INVALID) return IO_DONE; | ||
114 | else return errno; | ||
115 | } | ||
116 | |||
117 | /*-------------------------------------------------------------------------*\ | ||
118 | * Binds or returns error message | ||
119 | \*-------------------------------------------------------------------------*/ | ||
120 | int socket_bind(p_socket ps, SA *addr, socklen_t len) { | ||
121 | int err = IO_DONE; | ||
122 | socket_setblocking(ps); | ||
123 | if (bind(*ps, addr, len) < 0) err = errno; | ||
124 | socket_setnonblocking(ps); | ||
125 | return err; | ||
126 | } | ||
127 | |||
128 | /*-------------------------------------------------------------------------*\ | ||
129 | * | ||
130 | \*-------------------------------------------------------------------------*/ | ||
131 | int socket_listen(p_socket ps, int backlog) { | ||
132 | int err = IO_DONE; | ||
133 | socket_setblocking(ps); | ||
134 | if (listen(*ps, backlog)) err = errno; | ||
135 | socket_setnonblocking(ps); | ||
136 | return err; | ||
137 | } | ||
138 | |||
139 | /*-------------------------------------------------------------------------*\ | ||
140 | * | ||
141 | \*-------------------------------------------------------------------------*/ | ||
142 | void socket_shutdown(p_socket ps, int how) { | ||
143 | socket_setblocking(ps); | ||
144 | shutdown(*ps, how); | ||
145 | socket_setnonblocking(ps); | ||
146 | } | ||
147 | |||
148 | /*-------------------------------------------------------------------------*\ | ||
149 | * Connects or returns error message | ||
150 | \*-------------------------------------------------------------------------*/ | ||
151 | int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) { | ||
152 | int err; | ||
153 | /* avoid calling on closed sockets */ | ||
154 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
155 | /* call connect until done or failed without being interrupted */ | ||
156 | do if (connect(*ps, addr, len) == 0) return IO_DONE; | ||
157 | while ((err = errno) == EINTR); | ||
158 | /* if connection failed immediately, return error code */ | ||
159 | if (err != EINPROGRESS && err != EAGAIN) return err; | ||
160 | /* zero timeout case optimization */ | ||
161 | if (timeout_iszero(tm)) return IO_TIMEOUT; | ||
162 | /* wait until we have the result of the connection attempt or timeout */ | ||
163 | err = socket_waitfd(ps, WAITFD_C, tm); | ||
164 | if (err == IO_CLOSED) { | ||
165 | if (recv(*ps, (char *) &err, 0, 0) == 0) return IO_DONE; | ||
166 | else return errno; | ||
167 | } else return err; | ||
168 | } | ||
169 | |||
170 | /*-------------------------------------------------------------------------*\ | ||
171 | * Accept with timeout | ||
172 | \*-------------------------------------------------------------------------*/ | ||
173 | int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, p_timeout tm) { | ||
174 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
175 | for ( ;; ) { | ||
176 | int err; | ||
177 | if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID) return IO_DONE; | ||
178 | err = errno; | ||
179 | if (err == EINTR) continue; | ||
180 | if (err != EAGAIN && err != ECONNABORTED) return err; | ||
181 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; | ||
182 | } | ||
183 | /* can't reach here */ | ||
184 | return IO_UNKNOWN; | ||
185 | } | ||
186 | |||
187 | /*-------------------------------------------------------------------------*\ | ||
188 | * Send with timeout | ||
189 | \*-------------------------------------------------------------------------*/ | ||
190 | int socket_send(p_socket ps, const char *data, size_t count, | ||
191 | size_t *sent, p_timeout tm) | ||
192 | { | ||
193 | int err; | ||
194 | *sent = 0; | ||
195 | /* avoid making system calls on closed sockets */ | ||
196 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
197 | /* loop until we send something or we give up on error */ | ||
198 | for ( ;; ) { | ||
199 | long put = (long) send(*ps, data, count, 0); | ||
200 | /* if we sent anything, we are done */ | ||
201 | if (put >= 0) { | ||
202 | *sent = put; | ||
203 | return IO_DONE; | ||
204 | } | ||
205 | err = errno; | ||
206 | /* EPIPE means the connection was closed */ | ||
207 | if (err == EPIPE) return IO_CLOSED; | ||
208 | /* we call was interrupted, just try again */ | ||
209 | if (err == EINTR) continue; | ||
210 | /* if failed fatal reason, report error */ | ||
211 | if (err != EAGAIN) return err; | ||
212 | /* wait until we can send something or we timeout */ | ||
213 | if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; | ||
214 | } | ||
215 | /* can't reach here */ | ||
216 | return IO_UNKNOWN; | ||
217 | } | ||
218 | |||
219 | /*-------------------------------------------------------------------------*\ | ||
220 | * Sendto with timeout | ||
221 | \*-------------------------------------------------------------------------*/ | ||
222 | int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, | ||
223 | SA *addr, socklen_t len, p_timeout tm) | ||
224 | { | ||
225 | int err; | ||
226 | *sent = 0; | ||
227 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
228 | for ( ;; ) { | ||
229 | long put = (long) sendto(*ps, data, count, 0, addr, len); | ||
230 | if (put >= 0) { | ||
231 | *sent = put; | ||
232 | return IO_DONE; | ||
233 | } | ||
234 | err = errno; | ||
235 | if (err == EPIPE) return IO_CLOSED; | ||
236 | if (err == EINTR) continue; | ||
237 | if (err != EAGAIN) return err; | ||
238 | if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; | ||
239 | } | ||
240 | return IO_UNKNOWN; | ||
241 | } | ||
242 | |||
243 | /*-------------------------------------------------------------------------*\ | ||
244 | * Receive with timeout | ||
245 | \*-------------------------------------------------------------------------*/ | ||
246 | int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm) { | ||
247 | int err; | ||
248 | *got = 0; | ||
249 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
250 | for ( ;; ) { | ||
251 | long taken = (long) recv(*ps, data, count, 0); | ||
252 | if (taken > 0) { | ||
253 | *got = taken; | ||
254 | return IO_DONE; | ||
255 | } | ||
256 | err = errno; | ||
257 | if (taken == 0) return IO_CLOSED; | ||
258 | if (err == EINTR) continue; | ||
259 | if (err != EAGAIN) return err; | ||
260 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; | ||
261 | } | ||
262 | return IO_UNKNOWN; | ||
263 | } | ||
264 | |||
265 | /*-------------------------------------------------------------------------*\ | ||
266 | * Recvfrom with timeout | ||
267 | \*-------------------------------------------------------------------------*/ | ||
268 | int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, | ||
269 | SA *addr, socklen_t *len, p_timeout tm) { | ||
270 | int err; | ||
271 | *got = 0; | ||
272 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
273 | for ( ;; ) { | ||
274 | long taken = (long) recvfrom(*ps, data, count, 0, addr, len); | ||
275 | if (taken > 0) { | ||
276 | *got = taken; | ||
277 | return IO_DONE; | ||
278 | } | ||
279 | err = errno; | ||
280 | if (taken == 0) return IO_CLOSED; | ||
281 | if (err == EINTR) continue; | ||
282 | if (err != EAGAIN) return err; | ||
283 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; | ||
284 | } | ||
285 | return IO_UNKNOWN; | ||
286 | } | ||
287 | |||
288 | |||
289 | /*-------------------------------------------------------------------------*\ | ||
290 | * Write with timeout | ||
291 | * | ||
292 | * socket_read and socket_write are cut-n-paste of socket_send and socket_recv, | ||
293 | * with send/recv replaced with write/read. We can't just use write/read | ||
294 | * in the socket version, because behaviour when size is zero is different. | ||
295 | \*-------------------------------------------------------------------------*/ | ||
296 | int socket_write(p_socket ps, const char *data, size_t count, | ||
297 | size_t *sent, p_timeout tm) | ||
298 | { | ||
299 | int err; | ||
300 | *sent = 0; | ||
301 | /* avoid making system calls on closed sockets */ | ||
302 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
303 | /* loop until we send something or we give up on error */ | ||
304 | for ( ;; ) { | ||
305 | long put = (long) write(*ps, data, count); | ||
306 | /* if we sent anything, we are done */ | ||
307 | if (put >= 0) { | ||
308 | *sent = put; | ||
309 | return IO_DONE; | ||
310 | } | ||
311 | err = errno; | ||
312 | /* EPIPE means the connection was closed */ | ||
313 | if (err == EPIPE) return IO_CLOSED; | ||
314 | /* we call was interrupted, just try again */ | ||
315 | if (err == EINTR) continue; | ||
316 | /* if failed fatal reason, report error */ | ||
317 | if (err != EAGAIN) return err; | ||
318 | /* wait until we can send something or we timeout */ | ||
319 | if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; | ||
320 | } | ||
321 | /* can't reach here */ | ||
322 | return IO_UNKNOWN; | ||
323 | } | ||
324 | |||
325 | /*-------------------------------------------------------------------------*\ | ||
326 | * Read with timeout | ||
327 | * See note for socket_write | ||
328 | \*-------------------------------------------------------------------------*/ | ||
329 | int socket_read(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm) { | ||
330 | int err; | ||
331 | *got = 0; | ||
332 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
333 | for ( ;; ) { | ||
334 | long taken = (long) read(*ps, data, count); | ||
335 | if (taken > 0) { | ||
336 | *got = taken; | ||
337 | return IO_DONE; | ||
338 | } | ||
339 | err = errno; | ||
340 | if (taken == 0) return IO_CLOSED; | ||
341 | if (err == EINTR) continue; | ||
342 | if (err != EAGAIN) return err; | ||
343 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; | ||
344 | } | ||
345 | return IO_UNKNOWN; | ||
346 | } | ||
347 | |||
348 | /*-------------------------------------------------------------------------*\ | ||
349 | * Put socket into blocking mode | ||
350 | \*-------------------------------------------------------------------------*/ | ||
351 | void socket_setblocking(p_socket ps) { | ||
352 | int flags = fcntl(*ps, F_GETFL, 0); | ||
353 | flags &= (~(O_NONBLOCK)); | ||
354 | fcntl(*ps, F_SETFL, flags); | ||
355 | } | ||
356 | |||
357 | /*-------------------------------------------------------------------------*\ | ||
358 | * Put socket into non-blocking mode | ||
359 | \*-------------------------------------------------------------------------*/ | ||
360 | void socket_setnonblocking(p_socket ps) { | ||
361 | int flags = fcntl(*ps, F_GETFL, 0); | ||
362 | flags |= O_NONBLOCK; | ||
363 | fcntl(*ps, F_SETFL, flags); | ||
364 | } | ||
365 | |||
366 | /*-------------------------------------------------------------------------*\ | ||
367 | * DNS helpers | ||
368 | \*-------------------------------------------------------------------------*/ | ||
369 | int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) { | ||
370 | *hp = gethostbyaddr(addr, len, AF_INET); | ||
371 | if (*hp) return IO_DONE; | ||
372 | else if (h_errno) return h_errno; | ||
373 | else if (errno) return errno; | ||
374 | else return IO_UNKNOWN; | ||
375 | } | ||
376 | |||
377 | int socket_gethostbyname(const char *addr, struct hostent **hp) { | ||
378 | *hp = gethostbyname(addr); | ||
379 | if (*hp) return IO_DONE; | ||
380 | else if (h_errno) return h_errno; | ||
381 | else if (errno) return errno; | ||
382 | else return IO_UNKNOWN; | ||
383 | } | ||
384 | |||
385 | /*-------------------------------------------------------------------------*\ | ||
386 | * Error translation functions | ||
387 | * Make sure important error messages are standard | ||
388 | \*-------------------------------------------------------------------------*/ | ||
389 | const char *socket_hoststrerror(int err) { | ||
390 | if (err <= 0) return io_strerror(err); | ||
391 | switch (err) { | ||
392 | case HOST_NOT_FOUND: return "host not found"; | ||
393 | default: return hstrerror(err); | ||
394 | } | ||
395 | } | ||
396 | |||
397 | const char *socket_strerror(int err) { | ||
398 | if (err <= 0) return io_strerror(err); | ||
399 | switch (err) { | ||
400 | case EADDRINUSE: return "address already in use"; | ||
401 | case EISCONN: return "already connected"; | ||
402 | case EACCES: return "permission denied"; | ||
403 | case ECONNREFUSED: return "connection refused"; | ||
404 | case ECONNABORTED: return "closed"; | ||
405 | case ECONNRESET: return "closed"; | ||
406 | case ETIMEDOUT: return "timeout"; | ||
407 | default: return strerror(err); | ||
408 | } | ||
409 | } | ||
410 | |||
411 | const char *socket_ioerror(p_socket ps, int err) { | ||
412 | (void) ps; | ||
413 | return socket_strerror(err); | ||
414 | } | ||
415 | |||
416 | const char *socket_gaistrerror(int err) { | ||
417 | if (err == 0) return NULL; | ||
418 | switch (err) { | ||
419 | case EAI_AGAIN: return "temporary failure in name resolution"; | ||
420 | case EAI_BADFLAGS: return "invalid value for ai_flags"; | ||
421 | #ifdef EAI_BADHINTS | ||
422 | case EAI_BADHINTS: return "invalid value for hints"; | ||
423 | #endif | ||
424 | case EAI_FAIL: return "non-recoverable failure in name resolution"; | ||
425 | case EAI_FAMILY: return "ai_family not supported"; | ||
426 | case EAI_MEMORY: return "memory allocation failure"; | ||
427 | case EAI_NONAME: | ||
428 | return "host or service not provided, or not known"; | ||
429 | #ifdef EAI_OVERFLOW | ||
430 | case EAI_OVERFLOW: return "argument buffer overflow"; | ||
431 | #endif | ||
432 | #ifdef EAI_PROTOCOL | ||
433 | case EAI_PROTOCOL: return "resolved protocol is unknown"; | ||
434 | #endif | ||
435 | case EAI_SERVICE: return "service not supported for socket type"; | ||
436 | case EAI_SOCKTYPE: return "ai_socktype not supported"; | ||
437 | case EAI_SYSTEM: return strerror(errno); | ||
438 | default: return gai_strerror(err); | ||
439 | } | ||
440 | } | ||
441 | |||
diff --git a/vendor/luasec/src/luasocket/usocket.h b/vendor/luasec/src/luasocket/usocket.h new file mode 100644 index 00000000..ecbcd8e5 --- /dev/null +++ b/vendor/luasec/src/luasocket/usocket.h | |||
@@ -0,0 +1,70 @@ | |||
1 | #ifndef USOCKET_H | ||
2 | #define USOCKET_H | ||
3 | /*=========================================================================*\ | ||
4 | * Socket compatibilization module for Unix | ||
5 | * LuaSocket toolkit | ||
6 | \*=========================================================================*/ | ||
7 | |||
8 | /*=========================================================================*\ | ||
9 | * BSD include files | ||
10 | \*=========================================================================*/ | ||
11 | /* error codes */ | ||
12 | #include <errno.h> | ||
13 | /* close function */ | ||
14 | #include <unistd.h> | ||
15 | /* fnctnl function and associated constants */ | ||
16 | #include <fcntl.h> | ||
17 | /* struct sockaddr */ | ||
18 | #include <sys/types.h> | ||
19 | /* socket function */ | ||
20 | #include <sys/socket.h> | ||
21 | /* struct timeval */ | ||
22 | #include <sys/time.h> | ||
23 | /* gethostbyname and gethostbyaddr functions */ | ||
24 | #include <netdb.h> | ||
25 | /* sigpipe handling */ | ||
26 | #include <signal.h> | ||
27 | /* IP stuff*/ | ||
28 | #include <netinet/in.h> | ||
29 | #include <arpa/inet.h> | ||
30 | /* TCP options (nagle algorithm disable) */ | ||
31 | #include <netinet/tcp.h> | ||
32 | #include <net/if.h> | ||
33 | |||
34 | #ifndef SOCKET_SELECT | ||
35 | #include <sys/poll.h> | ||
36 | #define WAITFD_R POLLIN | ||
37 | #define WAITFD_W POLLOUT | ||
38 | #define WAITFD_C (POLLIN|POLLOUT) | ||
39 | #else | ||
40 | #define WAITFD_R 1 | ||
41 | #define WAITFD_W 2 | ||
42 | #define WAITFD_C (WAITFD_R|WAITFD_W) | ||
43 | #endif | ||
44 | |||
45 | #ifndef SO_REUSEPORT | ||
46 | #define SO_REUSEPORT SO_REUSEADDR | ||
47 | #endif | ||
48 | |||
49 | /* Some platforms use IPV6_JOIN_GROUP instead if | ||
50 | * IPV6_ADD_MEMBERSHIP. The semantics are same, though. */ | ||
51 | #ifndef IPV6_ADD_MEMBERSHIP | ||
52 | #ifdef IPV6_JOIN_GROUP | ||
53 | #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP | ||
54 | #endif /* IPV6_JOIN_GROUP */ | ||
55 | #endif /* !IPV6_ADD_MEMBERSHIP */ | ||
56 | |||
57 | /* Same with IPV6_DROP_MEMBERSHIP / IPV6_LEAVE_GROUP. */ | ||
58 | #ifndef IPV6_DROP_MEMBERSHIP | ||
59 | #ifdef IPV6_LEAVE_GROUP | ||
60 | #define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP | ||
61 | #endif /* IPV6_LEAVE_GROUP */ | ||
62 | #endif /* !IPV6_DROP_MEMBERSHIP */ | ||
63 | |||
64 | typedef int t_socket; | ||
65 | typedef t_socket *p_socket; | ||
66 | typedef struct sockaddr_storage t_sockaddr_storage; | ||
67 | |||
68 | #define SOCKET_INVALID (-1) | ||
69 | |||
70 | #endif /* USOCKET_H */ | ||
diff --git a/vendor/luasec/src/luasocket/wsocket.c b/vendor/luasec/src/luasocket/wsocket.c new file mode 100644 index 00000000..8c7640eb --- /dev/null +++ b/vendor/luasec/src/luasocket/wsocket.c | |||
@@ -0,0 +1,429 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * Socket compatibilization module for Win32 | ||
3 | * LuaSocket toolkit | ||
4 | * | ||
5 | * The penalty of calling select to avoid busy-wait is only paid when | ||
6 | * the I/O call fail in the first place. | ||
7 | \*=========================================================================*/ | ||
8 | #include <string.h> | ||
9 | |||
10 | #include "socket.h" | ||
11 | |||
12 | /* WinSock doesn't have a strerror... */ | ||
13 | static const char *wstrerror(int err); | ||
14 | |||
15 | /*-------------------------------------------------------------------------*\ | ||
16 | * Initializes module | ||
17 | \*-------------------------------------------------------------------------*/ | ||
18 | int socket_open(void) { | ||
19 | WSADATA wsaData; | ||
20 | WORD wVersionRequested = MAKEWORD(2, 0); | ||
21 | int err = WSAStartup(wVersionRequested, &wsaData ); | ||
22 | if (err != 0) return 0; | ||
23 | if ((LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) && | ||
24 | (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)) { | ||
25 | WSACleanup(); | ||
26 | return 0; | ||
27 | } | ||
28 | return 1; | ||
29 | } | ||
30 | |||
31 | /*-------------------------------------------------------------------------*\ | ||
32 | * Close module | ||
33 | \*-------------------------------------------------------------------------*/ | ||
34 | int socket_close(void) { | ||
35 | WSACleanup(); | ||
36 | return 1; | ||
37 | } | ||
38 | |||
39 | /*-------------------------------------------------------------------------*\ | ||
40 | * Wait for readable/writable/connected socket with timeout | ||
41 | \*-------------------------------------------------------------------------*/ | ||
42 | int socket_waitfd(p_socket ps, int sw, p_timeout tm) { | ||
43 | int ret; | ||
44 | fd_set rfds, wfds, efds, *rp = NULL, *wp = NULL, *ep = NULL; | ||
45 | struct timeval tv, *tp = NULL; | ||
46 | double t; | ||
47 | if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */ | ||
48 | if (sw & WAITFD_R) { | ||
49 | FD_ZERO(&rfds); | ||
50 | FD_SET(*ps, &rfds); | ||
51 | rp = &rfds; | ||
52 | } | ||
53 | if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; } | ||
54 | if (sw & WAITFD_C) { FD_ZERO(&efds); FD_SET(*ps, &efds); ep = &efds; } | ||
55 | if ((t = timeout_get(tm)) >= 0.0) { | ||
56 | tv.tv_sec = (int) t; | ||
57 | tv.tv_usec = (int) ((t-tv.tv_sec)*1.0e6); | ||
58 | tp = &tv; | ||
59 | } | ||
60 | ret = select(0, rp, wp, ep, tp); | ||
61 | if (ret == -1) return WSAGetLastError(); | ||
62 | if (ret == 0) return IO_TIMEOUT; | ||
63 | if (sw == WAITFD_C && FD_ISSET(*ps, &efds)) return IO_CLOSED; | ||
64 | return IO_DONE; | ||
65 | } | ||
66 | |||
67 | /*-------------------------------------------------------------------------*\ | ||
68 | * Select with int timeout in ms | ||
69 | \*-------------------------------------------------------------------------*/ | ||
70 | int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, | ||
71 | p_timeout tm) { | ||
72 | struct timeval tv; | ||
73 | double t = timeout_get(tm); | ||
74 | tv.tv_sec = (int) t; | ||
75 | tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6); | ||
76 | if (n <= 0) { | ||
77 | Sleep((DWORD) (1000*t)); | ||
78 | return 0; | ||
79 | } else return select(0, rfds, wfds, efds, t >= 0.0? &tv: NULL); | ||
80 | } | ||
81 | |||
82 | /*-------------------------------------------------------------------------*\ | ||
83 | * Close and inutilize socket | ||
84 | \*-------------------------------------------------------------------------*/ | ||
85 | void socket_destroy(p_socket ps) { | ||
86 | if (*ps != SOCKET_INVALID) { | ||
87 | socket_setblocking(ps); /* close can take a long time on WIN32 */ | ||
88 | closesocket(*ps); | ||
89 | *ps = SOCKET_INVALID; | ||
90 | } | ||
91 | } | ||
92 | |||
93 | /*-------------------------------------------------------------------------*\ | ||
94 | * | ||
95 | \*-------------------------------------------------------------------------*/ | ||
96 | void socket_shutdown(p_socket ps, int how) { | ||
97 | socket_setblocking(ps); | ||
98 | shutdown(*ps, how); | ||
99 | socket_setnonblocking(ps); | ||
100 | } | ||
101 | |||
102 | /*-------------------------------------------------------------------------*\ | ||
103 | * Creates and sets up a socket | ||
104 | \*-------------------------------------------------------------------------*/ | ||
105 | int socket_create(p_socket ps, int domain, int type, int protocol) { | ||
106 | *ps = socket(domain, type, protocol); | ||
107 | if (*ps != SOCKET_INVALID) return IO_DONE; | ||
108 | else return WSAGetLastError(); | ||
109 | } | ||
110 | |||
111 | /*-------------------------------------------------------------------------*\ | ||
112 | * Connects or returns error message | ||
113 | \*-------------------------------------------------------------------------*/ | ||
114 | int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) { | ||
115 | int err; | ||
116 | /* don't call on closed socket */ | ||
117 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
118 | /* ask system to connect */ | ||
119 | if (connect(*ps, addr, len) == 0) return IO_DONE; | ||
120 | /* make sure the system is trying to connect */ | ||
121 | err = WSAGetLastError(); | ||
122 | if (err != WSAEWOULDBLOCK && err != WSAEINPROGRESS) return err; | ||
123 | /* zero timeout case optimization */ | ||
124 | if (timeout_iszero(tm)) return IO_TIMEOUT; | ||
125 | /* we wait until something happens */ | ||
126 | err = socket_waitfd(ps, WAITFD_C, tm); | ||
127 | if (err == IO_CLOSED) { | ||
128 | int len = sizeof(err); | ||
129 | /* give windows time to set the error (yes, disgusting) */ | ||
130 | Sleep(10); | ||
131 | /* find out why we failed */ | ||
132 | getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &len); | ||
133 | /* we KNOW there was an error. if 'why' is 0, we will return | ||
134 | * "unknown error", but it's not really our fault */ | ||
135 | return err > 0? err: IO_UNKNOWN; | ||
136 | } else return err; | ||
137 | |||
138 | } | ||
139 | |||
140 | /*-------------------------------------------------------------------------*\ | ||
141 | * Binds or returns error message | ||
142 | \*-------------------------------------------------------------------------*/ | ||
143 | int socket_bind(p_socket ps, SA *addr, socklen_t len) { | ||
144 | int err = IO_DONE; | ||
145 | socket_setblocking(ps); | ||
146 | if (bind(*ps, addr, len) < 0) err = WSAGetLastError(); | ||
147 | socket_setnonblocking(ps); | ||
148 | return err; | ||
149 | } | ||
150 | |||
151 | /*-------------------------------------------------------------------------*\ | ||
152 | * | ||
153 | \*-------------------------------------------------------------------------*/ | ||
154 | int socket_listen(p_socket ps, int backlog) { | ||
155 | int err = IO_DONE; | ||
156 | socket_setblocking(ps); | ||
157 | if (listen(*ps, backlog) < 0) err = WSAGetLastError(); | ||
158 | socket_setnonblocking(ps); | ||
159 | return err; | ||
160 | } | ||
161 | |||
162 | /*-------------------------------------------------------------------------*\ | ||
163 | * Accept with timeout | ||
164 | \*-------------------------------------------------------------------------*/ | ||
165 | int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, | ||
166 | p_timeout tm) { | ||
167 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
168 | for ( ;; ) { | ||
169 | int err; | ||
170 | /* try to get client socket */ | ||
171 | if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID) return IO_DONE; | ||
172 | /* find out why we failed */ | ||
173 | err = WSAGetLastError(); | ||
174 | /* if we failed because there was no connectoin, keep trying */ | ||
175 | if (err != WSAEWOULDBLOCK && err != WSAECONNABORTED) return err; | ||
176 | /* call select to avoid busy wait */ | ||
177 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; | ||
178 | } | ||
179 | } | ||
180 | |||
181 | /*-------------------------------------------------------------------------*\ | ||
182 | * Send with timeout | ||
183 | * On windows, if you try to send 10MB, the OS will buffer EVERYTHING | ||
184 | * this can take an awful lot of time and we will end up blocked. | ||
185 | * Therefore, whoever calls this function should not pass a huge buffer. | ||
186 | \*-------------------------------------------------------------------------*/ | ||
187 | int socket_send(p_socket ps, const char *data, size_t count, | ||
188 | size_t *sent, p_timeout tm) | ||
189 | { | ||
190 | int err; | ||
191 | *sent = 0; | ||
192 | /* avoid making system calls on closed sockets */ | ||
193 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
194 | /* loop until we send something or we give up on error */ | ||
195 | for ( ;; ) { | ||
196 | /* try to send something */ | ||
197 | int put = send(*ps, data, (int) count, 0); | ||
198 | /* if we sent something, we are done */ | ||
199 | if (put > 0) { | ||
200 | *sent = put; | ||
201 | return IO_DONE; | ||
202 | } | ||
203 | /* deal with failure */ | ||
204 | err = WSAGetLastError(); | ||
205 | /* we can only proceed if there was no serious error */ | ||
206 | if (err != WSAEWOULDBLOCK) return err; | ||
207 | /* avoid busy wait */ | ||
208 | if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; | ||
209 | } | ||
210 | } | ||
211 | |||
212 | /*-------------------------------------------------------------------------*\ | ||
213 | * Sendto with timeout | ||
214 | \*-------------------------------------------------------------------------*/ | ||
215 | int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, | ||
216 | SA *addr, socklen_t len, p_timeout tm) | ||
217 | { | ||
218 | int err; | ||
219 | *sent = 0; | ||
220 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
221 | for ( ;; ) { | ||
222 | int put = sendto(*ps, data, (int) count, 0, addr, len); | ||
223 | if (put > 0) { | ||
224 | *sent = put; | ||
225 | return IO_DONE; | ||
226 | } | ||
227 | err = WSAGetLastError(); | ||
228 | if (err != WSAEWOULDBLOCK) return err; | ||
229 | if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; | ||
230 | } | ||
231 | } | ||
232 | |||
233 | /*-------------------------------------------------------------------------*\ | ||
234 | * Receive with timeout | ||
235 | \*-------------------------------------------------------------------------*/ | ||
236 | int socket_recv(p_socket ps, char *data, size_t count, size_t *got, | ||
237 | p_timeout tm) | ||
238 | { | ||
239 | int err, prev = IO_DONE; | ||
240 | *got = 0; | ||
241 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
242 | for ( ;; ) { | ||
243 | int taken = recv(*ps, data, (int) count, 0); | ||
244 | if (taken > 0) { | ||
245 | *got = taken; | ||
246 | return IO_DONE; | ||
247 | } | ||
248 | if (taken == 0) return IO_CLOSED; | ||
249 | err = WSAGetLastError(); | ||
250 | /* On UDP, a connreset simply means the previous send failed. | ||
251 | * So we try again. | ||
252 | * On TCP, it means our socket is now useless, so the error passes. | ||
253 | * (We will loop again, exiting because the same error will happen) */ | ||
254 | if (err != WSAEWOULDBLOCK) { | ||
255 | if (err != WSAECONNRESET || prev == WSAECONNRESET) return err; | ||
256 | prev = err; | ||
257 | } | ||
258 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; | ||
259 | } | ||
260 | } | ||
261 | |||
262 | /*-------------------------------------------------------------------------*\ | ||
263 | * Recvfrom with timeout | ||
264 | \*-------------------------------------------------------------------------*/ | ||
265 | int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, | ||
266 | SA *addr, socklen_t *len, p_timeout tm) | ||
267 | { | ||
268 | int err, prev = IO_DONE; | ||
269 | *got = 0; | ||
270 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
271 | for ( ;; ) { | ||
272 | int taken = recvfrom(*ps, data, (int) count, 0, addr, len); | ||
273 | if (taken > 0) { | ||
274 | *got = taken; | ||
275 | return IO_DONE; | ||
276 | } | ||
277 | if (taken == 0) return IO_CLOSED; | ||
278 | err = WSAGetLastError(); | ||
279 | /* On UDP, a connreset simply means the previous send failed. | ||
280 | * So we try again. | ||
281 | * On TCP, it means our socket is now useless, so the error passes. | ||
282 | * (We will loop again, exiting because the same error will happen) */ | ||
283 | if (err != WSAEWOULDBLOCK) { | ||
284 | if (err != WSAECONNRESET || prev == WSAECONNRESET) return err; | ||
285 | prev = err; | ||
286 | } | ||
287 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; | ||
288 | } | ||
289 | } | ||
290 | |||
291 | /*-------------------------------------------------------------------------*\ | ||
292 | * Put socket into blocking mode | ||
293 | \*-------------------------------------------------------------------------*/ | ||
294 | void socket_setblocking(p_socket ps) { | ||
295 | u_long argp = 0; | ||
296 | ioctlsocket(*ps, FIONBIO, &argp); | ||
297 | } | ||
298 | |||
299 | /*-------------------------------------------------------------------------*\ | ||
300 | * Put socket into non-blocking mode | ||
301 | \*-------------------------------------------------------------------------*/ | ||
302 | void socket_setnonblocking(p_socket ps) { | ||
303 | u_long argp = 1; | ||
304 | ioctlsocket(*ps, FIONBIO, &argp); | ||
305 | } | ||
306 | |||
307 | /*-------------------------------------------------------------------------*\ | ||
308 | * DNS helpers | ||
309 | \*-------------------------------------------------------------------------*/ | ||
310 | int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) { | ||
311 | *hp = gethostbyaddr(addr, len, AF_INET); | ||
312 | if (*hp) return IO_DONE; | ||
313 | else return WSAGetLastError(); | ||
314 | } | ||
315 | |||
316 | int socket_gethostbyname(const char *addr, struct hostent **hp) { | ||
317 | *hp = gethostbyname(addr); | ||
318 | if (*hp) return IO_DONE; | ||
319 | else return WSAGetLastError(); | ||
320 | } | ||
321 | |||
322 | /*-------------------------------------------------------------------------*\ | ||
323 | * Error translation functions | ||
324 | \*-------------------------------------------------------------------------*/ | ||
325 | const char *socket_hoststrerror(int err) { | ||
326 | if (err <= 0) return io_strerror(err); | ||
327 | switch (err) { | ||
328 | case WSAHOST_NOT_FOUND: return "host not found"; | ||
329 | default: return wstrerror(err); | ||
330 | } | ||
331 | } | ||
332 | |||
333 | const char *socket_strerror(int err) { | ||
334 | if (err <= 0) return io_strerror(err); | ||
335 | switch (err) { | ||
336 | case WSAEADDRINUSE: return "address already in use"; | ||
337 | case WSAECONNREFUSED: return "connection refused"; | ||
338 | case WSAEISCONN: return "already connected"; | ||
339 | case WSAEACCES: return "permission denied"; | ||
340 | case WSAECONNABORTED: return "closed"; | ||
341 | case WSAECONNRESET: return "closed"; | ||
342 | case WSAETIMEDOUT: return "timeout"; | ||
343 | default: return wstrerror(err); | ||
344 | } | ||
345 | } | ||
346 | |||
347 | const char *socket_ioerror(p_socket ps, int err) { | ||
348 | (void) ps; | ||
349 | return socket_strerror(err); | ||
350 | } | ||
351 | |||
352 | static const char *wstrerror(int err) { | ||
353 | switch (err) { | ||
354 | case WSAEINTR: return "Interrupted function call"; | ||
355 | case WSAEACCES: return "Permission denied"; | ||
356 | case WSAEFAULT: return "Bad address"; | ||
357 | case WSAEINVAL: return "Invalid argument"; | ||
358 | case WSAEMFILE: return "Too many open files"; | ||
359 | case WSAEWOULDBLOCK: return "Resource temporarily unavailable"; | ||
360 | case WSAEINPROGRESS: return "Operation now in progress"; | ||
361 | case WSAEALREADY: return "Operation already in progress"; | ||
362 | case WSAENOTSOCK: return "Socket operation on nonsocket"; | ||
363 | case WSAEDESTADDRREQ: return "Destination address required"; | ||
364 | case WSAEMSGSIZE: return "Message too long"; | ||
365 | case WSAEPROTOTYPE: return "Protocol wrong type for socket"; | ||
366 | case WSAENOPROTOOPT: return "Bad protocol option"; | ||
367 | case WSAEPROTONOSUPPORT: return "Protocol not supported"; | ||
368 | case WSAESOCKTNOSUPPORT: return "Socket type not supported"; | ||
369 | case WSAEOPNOTSUPP: return "Operation not supported"; | ||
370 | case WSAEPFNOSUPPORT: return "Protocol family not supported"; | ||
371 | case WSAEAFNOSUPPORT: | ||
372 | return "Address family not supported by protocol family"; | ||
373 | case WSAEADDRINUSE: return "Address already in use"; | ||
374 | case WSAEADDRNOTAVAIL: return "Cannot assign requested address"; | ||
375 | case WSAENETDOWN: return "Network is down"; | ||
376 | case WSAENETUNREACH: return "Network is unreachable"; | ||
377 | case WSAENETRESET: return "Network dropped connection on reset"; | ||
378 | case WSAECONNABORTED: return "Software caused connection abort"; | ||
379 | case WSAECONNRESET: return "Connection reset by peer"; | ||
380 | case WSAENOBUFS: return "No buffer space available"; | ||
381 | case WSAEISCONN: return "Socket is already connected"; | ||
382 | case WSAENOTCONN: return "Socket is not connected"; | ||
383 | case WSAESHUTDOWN: return "Cannot send after socket shutdown"; | ||
384 | case WSAETIMEDOUT: return "Connection timed out"; | ||
385 | case WSAECONNREFUSED: return "Connection refused"; | ||
386 | case WSAEHOSTDOWN: return "Host is down"; | ||
387 | case WSAEHOSTUNREACH: return "No route to host"; | ||
388 | case WSAEPROCLIM: return "Too many processes"; | ||
389 | case WSASYSNOTREADY: return "Network subsystem is unavailable"; | ||
390 | case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range"; | ||
391 | case WSANOTINITIALISED: | ||
392 | return "Successful WSAStartup not yet performed"; | ||
393 | case WSAEDISCON: return "Graceful shutdown in progress"; | ||
394 | case WSAHOST_NOT_FOUND: return "Host not found"; | ||
395 | case WSATRY_AGAIN: return "Nonauthoritative host not found"; | ||
396 | case WSANO_RECOVERY: return "Nonrecoverable name lookup error"; | ||
397 | case WSANO_DATA: return "Valid name, no data record of requested type"; | ||
398 | default: return "Unknown error"; | ||
399 | } | ||
400 | } | ||
401 | |||
402 | const char *socket_gaistrerror(int err) { | ||
403 | if (err == 0) return NULL; | ||
404 | switch (err) { | ||
405 | case EAI_AGAIN: return "temporary failure in name resolution"; | ||
406 | case EAI_BADFLAGS: return "invalid value for ai_flags"; | ||
407 | #ifdef EAI_BADHINTS | ||
408 | case EAI_BADHINTS: return "invalid value for hints"; | ||
409 | #endif | ||
410 | case EAI_FAIL: return "non-recoverable failure in name resolution"; | ||
411 | case EAI_FAMILY: return "ai_family not supported"; | ||
412 | case EAI_MEMORY: return "memory allocation failure"; | ||
413 | case EAI_NONAME: | ||
414 | return "host or service not provided, or not known"; | ||
415 | #ifdef EAI_OVERFLOW | ||
416 | case EAI_OVERFLOW: return "argument buffer overflow"; | ||
417 | #endif | ||
418 | #ifdef EAI_PROTOCOL | ||
419 | case EAI_PROTOCOL: return "resolved protocol is unknown"; | ||
420 | #endif | ||
421 | case EAI_SERVICE: return "service not supported for socket type"; | ||
422 | case EAI_SOCKTYPE: return "ai_socktype not supported"; | ||
423 | #ifdef EAI_SYSTEM | ||
424 | case EAI_SYSTEM: return strerror(errno); | ||
425 | #endif | ||
426 | default: return gai_strerror(err); | ||
427 | } | ||
428 | } | ||
429 | |||
diff --git a/vendor/luasec/src/luasocket/wsocket.h b/vendor/luasec/src/luasocket/wsocket.h new file mode 100644 index 00000000..c5a4b1ce --- /dev/null +++ b/vendor/luasec/src/luasocket/wsocket.h | |||
@@ -0,0 +1,38 @@ | |||
1 | #ifndef WSOCKET_H | ||
2 | #define WSOCKET_H | ||
3 | /*=========================================================================*\ | ||
4 | * Socket compatibilization module for Win32 | ||
5 | * LuaSocket toolkit | ||
6 | \*=========================================================================*/ | ||
7 | |||
8 | /*=========================================================================*\ | ||
9 | * WinSock include files | ||
10 | \*=========================================================================*/ | ||
11 | #include <winsock2.h> | ||
12 | #include <ws2tcpip.h> | ||
13 | |||
14 | typedef int socklen_t; | ||
15 | typedef SOCKADDR_STORAGE t_sockaddr_storage; | ||
16 | typedef SOCKET t_socket; | ||
17 | typedef t_socket *p_socket; | ||
18 | |||
19 | #define WAITFD_R 1 | ||
20 | #define WAITFD_W 2 | ||
21 | #define WAITFD_E 4 | ||
22 | #define WAITFD_C (WAITFD_E|WAITFD_W) | ||
23 | |||
24 | #ifndef IPV6_V6ONLY | ||
25 | #define IPV6_V6ONLY 27 | ||
26 | #endif | ||
27 | |||
28 | #define SOCKET_INVALID (INVALID_SOCKET) | ||
29 | |||
30 | #ifndef SO_REUSEPORT | ||
31 | #define SO_REUSEPORT SO_REUSEADDR | ||
32 | #endif | ||
33 | |||
34 | #ifndef AI_NUMERICSERV | ||
35 | #define AI_NUMERICSERV (0) | ||
36 | #endif | ||
37 | |||
38 | #endif /* WSOCKET_H */ | ||
diff --git a/vendor/luasec/src/options.c b/vendor/luasec/src/options.c new file mode 100644 index 00000000..3d17d6d5 --- /dev/null +++ b/vendor/luasec/src/options.c | |||
@@ -0,0 +1,185 @@ | |||
1 | /*-------------------------------------------------------------------------- | ||
2 | * LuaSec 1.3.2 | ||
3 | * | ||
4 | * Copyright (C) 2006-2023 Bruno Silvestre | ||
5 | * | ||
6 | *--------------------------------------------------------------------------*/ | ||
7 | |||
8 | #include <openssl/ssl.h> | ||
9 | |||
10 | #include "options.h" | ||
11 | |||
12 | /* If you need to generate these options again, see options.lua */ | ||
13 | |||
14 | |||
15 | /* | ||
16 | OpenSSL version: OpenSSL 3.0.8 | ||
17 | */ | ||
18 | |||
19 | static lsec_ssl_option_t ssl_options[] = { | ||
20 | #if defined(SSL_OP_ALL) | ||
21 | {"all", SSL_OP_ALL}, | ||
22 | #endif | ||
23 | #if defined(SSL_OP_ALLOW_CLIENT_RENEGOTIATION) | ||
24 | {"allow_client_renegotiation", SSL_OP_ALLOW_CLIENT_RENEGOTIATION}, | ||
25 | #endif | ||
26 | #if defined(SSL_OP_ALLOW_NO_DHE_KEX) | ||
27 | {"allow_no_dhe_kex", SSL_OP_ALLOW_NO_DHE_KEX}, | ||
28 | #endif | ||
29 | #if defined(SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) | ||
30 | {"allow_unsafe_legacy_renegotiation", SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION}, | ||
31 | #endif | ||
32 | #if defined(SSL_OP_CIPHER_SERVER_PREFERENCE) | ||
33 | {"cipher_server_preference", SSL_OP_CIPHER_SERVER_PREFERENCE}, | ||
34 | #endif | ||
35 | #if defined(SSL_OP_CISCO_ANYCONNECT) | ||
36 | {"cisco_anyconnect", SSL_OP_CISCO_ANYCONNECT}, | ||
37 | #endif | ||
38 | #if defined(SSL_OP_CLEANSE_PLAINTEXT) | ||
39 | {"cleanse_plaintext", SSL_OP_CLEANSE_PLAINTEXT}, | ||
40 | #endif | ||
41 | #if defined(SSL_OP_COOKIE_EXCHANGE) | ||
42 | {"cookie_exchange", SSL_OP_COOKIE_EXCHANGE}, | ||
43 | #endif | ||
44 | #if defined(SSL_OP_CRYPTOPRO_TLSEXT_BUG) | ||
45 | {"cryptopro_tlsext_bug", SSL_OP_CRYPTOPRO_TLSEXT_BUG}, | ||
46 | #endif | ||
47 | #if defined(SSL_OP_DISABLE_TLSEXT_CA_NAMES) | ||
48 | {"disable_tlsext_ca_names", SSL_OP_DISABLE_TLSEXT_CA_NAMES}, | ||
49 | #endif | ||
50 | #if defined(SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) | ||
51 | {"dont_insert_empty_fragments", SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS}, | ||
52 | #endif | ||
53 | #if defined(SSL_OP_ENABLE_KTLS) | ||
54 | {"enable_ktls", SSL_OP_ENABLE_KTLS}, | ||
55 | #endif | ||
56 | #if defined(SSL_OP_ENABLE_MIDDLEBOX_COMPAT) | ||
57 | {"enable_middlebox_compat", SSL_OP_ENABLE_MIDDLEBOX_COMPAT}, | ||
58 | #endif | ||
59 | #if defined(SSL_OP_EPHEMERAL_RSA) | ||
60 | {"ephemeral_rsa", SSL_OP_EPHEMERAL_RSA}, | ||
61 | #endif | ||
62 | #if defined(SSL_OP_IGNORE_UNEXPECTED_EOF) | ||
63 | {"ignore_unexpected_eof", SSL_OP_IGNORE_UNEXPECTED_EOF}, | ||
64 | #endif | ||
65 | #if defined(SSL_OP_LEGACY_SERVER_CONNECT) | ||
66 | {"legacy_server_connect", SSL_OP_LEGACY_SERVER_CONNECT}, | ||
67 | #endif | ||
68 | #if defined(SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER) | ||
69 | {"microsoft_big_sslv3_buffer", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER}, | ||
70 | #endif | ||
71 | #if defined(SSL_OP_MICROSOFT_SESS_ID_BUG) | ||
72 | {"microsoft_sess_id_bug", SSL_OP_MICROSOFT_SESS_ID_BUG}, | ||
73 | #endif | ||
74 | #if defined(SSL_OP_MSIE_SSLV2_RSA_PADDING) | ||
75 | {"msie_sslv2_rsa_padding", SSL_OP_MSIE_SSLV2_RSA_PADDING}, | ||
76 | #endif | ||
77 | #if defined(SSL_OP_NETSCAPE_CA_DN_BUG) | ||
78 | {"netscape_ca_dn_bug", SSL_OP_NETSCAPE_CA_DN_BUG}, | ||
79 | #endif | ||
80 | #if defined(SSL_OP_NETSCAPE_CHALLENGE_BUG) | ||
81 | {"netscape_challenge_bug", SSL_OP_NETSCAPE_CHALLENGE_BUG}, | ||
82 | #endif | ||
83 | #if defined(SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG) | ||
84 | {"netscape_demo_cipher_change_bug", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG}, | ||
85 | #endif | ||
86 | #if defined(SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) | ||
87 | {"netscape_reuse_cipher_change_bug", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG}, | ||
88 | #endif | ||
89 | #if defined(SSL_OP_NO_ANTI_REPLAY) | ||
90 | {"no_anti_replay", SSL_OP_NO_ANTI_REPLAY}, | ||
91 | #endif | ||
92 | #if defined(SSL_OP_NO_COMPRESSION) | ||
93 | {"no_compression", SSL_OP_NO_COMPRESSION}, | ||
94 | #endif | ||
95 | #if defined(SSL_OP_NO_DTLS_MASK) | ||
96 | {"no_dtls_mask", SSL_OP_NO_DTLS_MASK}, | ||
97 | #endif | ||
98 | #if defined(SSL_OP_NO_DTLSv1) | ||
99 | {"no_dtlsv1", SSL_OP_NO_DTLSv1}, | ||
100 | #endif | ||
101 | #if defined(SSL_OP_NO_DTLSv1_2) | ||
102 | {"no_dtlsv1_2", SSL_OP_NO_DTLSv1_2}, | ||
103 | #endif | ||
104 | #if defined(SSL_OP_NO_ENCRYPT_THEN_MAC) | ||
105 | {"no_encrypt_then_mac", SSL_OP_NO_ENCRYPT_THEN_MAC}, | ||
106 | #endif | ||
107 | #if defined(SSL_OP_NO_EXTENDED_MASTER_SECRET) | ||
108 | {"no_extended_master_secret", SSL_OP_NO_EXTENDED_MASTER_SECRET}, | ||
109 | #endif | ||
110 | #if defined(SSL_OP_NO_QUERY_MTU) | ||
111 | {"no_query_mtu", SSL_OP_NO_QUERY_MTU}, | ||
112 | #endif | ||
113 | #if defined(SSL_OP_NO_RENEGOTIATION) | ||
114 | {"no_renegotiation", SSL_OP_NO_RENEGOTIATION}, | ||
115 | #endif | ||
116 | #if defined(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION) | ||
117 | {"no_session_resumption_on_renegotiation", SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION}, | ||
118 | #endif | ||
119 | #if defined(SSL_OP_NO_SSL_MASK) | ||
120 | {"no_ssl_mask", SSL_OP_NO_SSL_MASK}, | ||
121 | #endif | ||
122 | #if defined(SSL_OP_NO_SSLv2) | ||
123 | {"no_sslv2", SSL_OP_NO_SSLv2}, | ||
124 | #endif | ||
125 | #if defined(SSL_OP_NO_SSLv3) | ||
126 | {"no_sslv3", SSL_OP_NO_SSLv3}, | ||
127 | #endif | ||
128 | #if defined(SSL_OP_NO_TICKET) | ||
129 | {"no_ticket", SSL_OP_NO_TICKET}, | ||
130 | #endif | ||
131 | #if defined(SSL_OP_NO_TLSv1) | ||
132 | {"no_tlsv1", SSL_OP_NO_TLSv1}, | ||
133 | #endif | ||
134 | #if defined(SSL_OP_NO_TLSv1_1) | ||
135 | {"no_tlsv1_1", SSL_OP_NO_TLSv1_1}, | ||
136 | #endif | ||
137 | #if defined(SSL_OP_NO_TLSv1_2) | ||
138 | {"no_tlsv1_2", SSL_OP_NO_TLSv1_2}, | ||
139 | #endif | ||
140 | #if defined(SSL_OP_NO_TLSv1_3) | ||
141 | {"no_tlsv1_3", SSL_OP_NO_TLSv1_3}, | ||
142 | #endif | ||
143 | #if defined(SSL_OP_PKCS1_CHECK_1) | ||
144 | {"pkcs1_check_1", SSL_OP_PKCS1_CHECK_1}, | ||
145 | #endif | ||
146 | #if defined(SSL_OP_PKCS1_CHECK_2) | ||
147 | {"pkcs1_check_2", SSL_OP_PKCS1_CHECK_2}, | ||
148 | #endif | ||
149 | #if defined(SSL_OP_PRIORITIZE_CHACHA) | ||
150 | {"prioritize_chacha", SSL_OP_PRIORITIZE_CHACHA}, | ||
151 | #endif | ||
152 | #if defined(SSL_OP_SAFARI_ECDHE_ECDSA_BUG) | ||
153 | {"safari_ecdhe_ecdsa_bug", SSL_OP_SAFARI_ECDHE_ECDSA_BUG}, | ||
154 | #endif | ||
155 | #if defined(SSL_OP_SINGLE_DH_USE) | ||
156 | {"single_dh_use", SSL_OP_SINGLE_DH_USE}, | ||
157 | #endif | ||
158 | #if defined(SSL_OP_SINGLE_ECDH_USE) | ||
159 | {"single_ecdh_use", SSL_OP_SINGLE_ECDH_USE}, | ||
160 | #endif | ||
161 | #if defined(SSL_OP_SSLEAY_080_CLIENT_DH_BUG) | ||
162 | {"ssleay_080_client_dh_bug", SSL_OP_SSLEAY_080_CLIENT_DH_BUG}, | ||
163 | #endif | ||
164 | #if defined(SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG) | ||
165 | {"sslref2_reuse_cert_type_bug", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG}, | ||
166 | #endif | ||
167 | #if defined(SSL_OP_TLSEXT_PADDING) | ||
168 | {"tlsext_padding", SSL_OP_TLSEXT_PADDING}, | ||
169 | #endif | ||
170 | #if defined(SSL_OP_TLS_BLOCK_PADDING_BUG) | ||
171 | {"tls_block_padding_bug", SSL_OP_TLS_BLOCK_PADDING_BUG}, | ||
172 | #endif | ||
173 | #if defined(SSL_OP_TLS_D5_BUG) | ||
174 | {"tls_d5_bug", SSL_OP_TLS_D5_BUG}, | ||
175 | #endif | ||
176 | #if defined(SSL_OP_TLS_ROLLBACK_BUG) | ||
177 | {"tls_rollback_bug", SSL_OP_TLS_ROLLBACK_BUG}, | ||
178 | #endif | ||
179 | {NULL, 0L} | ||
180 | }; | ||
181 | |||
182 | LSEC_API lsec_ssl_option_t* lsec_get_ssl_options() { | ||
183 | return ssl_options; | ||
184 | } | ||
185 | |||
diff --git a/vendor/luasec/src/options.h b/vendor/luasec/src/options.h new file mode 100644 index 00000000..c72d52d0 --- /dev/null +++ b/vendor/luasec/src/options.h | |||
@@ -0,0 +1,22 @@ | |||
1 | #ifndef LSEC_OPTIONS_H | ||
2 | #define LSEC_OPTIONS_H | ||
3 | |||
4 | /*-------------------------------------------------------------------------- | ||
5 | * LuaSec 1.3.2 | ||
6 | * | ||
7 | * Copyright (C) 2006-2023 Bruno Silvestre | ||
8 | * | ||
9 | *--------------------------------------------------------------------------*/ | ||
10 | |||
11 | #include "compat.h" | ||
12 | |||
13 | struct lsec_ssl_option_s { | ||
14 | const char *name; | ||
15 | unsigned long code; | ||
16 | }; | ||
17 | |||
18 | typedef struct lsec_ssl_option_s lsec_ssl_option_t; | ||
19 | |||
20 | LSEC_API lsec_ssl_option_t* lsec_get_ssl_options(); | ||
21 | |||
22 | #endif | ||
diff --git a/vendor/luasec/src/options.lua b/vendor/luasec/src/options.lua new file mode 100644 index 00000000..72428c01 --- /dev/null +++ b/vendor/luasec/src/options.lua | |||
@@ -0,0 +1,93 @@ | |||
1 | local function usage() | ||
2 | print("Usage:") | ||
3 | print("* Generate options of your system:") | ||
4 | print(" lua options.lua -g /path/to/ssl.h [version] > options.c") | ||
5 | print("* Examples:") | ||
6 | print(" lua options.lua -g /usr/include/openssl/ssl.h > options.c\n") | ||
7 | print(" lua options.lua -g /usr/include/openssl/ssl.h \"OpenSSL 1.1.1f\" > options.c\n") | ||
8 | |||
9 | print("* List options of your system:") | ||
10 | print(" lua options.lua -l /path/to/ssl.h\n") | ||
11 | end | ||
12 | |||
13 | -- | ||
14 | local function printf(str, ...) | ||
15 | print(string.format(str, ...)) | ||
16 | end | ||
17 | |||
18 | local function generate(options, version) | ||
19 | print([[ | ||
20 | /*-------------------------------------------------------------------------- | ||
21 | * LuaSec 1.3.2 | ||
22 | * | ||
23 | * Copyright (C) 2006-2023 Bruno Silvestre | ||
24 | * | ||
25 | *--------------------------------------------------------------------------*/ | ||
26 | |||
27 | #include <openssl/ssl.h> | ||
28 | |||
29 | #include "options.h" | ||
30 | |||
31 | /* If you need to generate these options again, see options.lua */ | ||
32 | |||
33 | ]]) | ||
34 | |||
35 | printf([[ | ||
36 | /* | ||
37 | OpenSSL version: %s | ||
38 | */ | ||
39 | ]], version) | ||
40 | |||
41 | print([[static lsec_ssl_option_t ssl_options[] = {]]) | ||
42 | |||
43 | for k, option in ipairs(options) do | ||
44 | local name = string.lower(string.sub(option, 8)) | ||
45 | print(string.format([[#if defined(%s)]], option)) | ||
46 | print(string.format([[ {"%s", %s},]], name, option)) | ||
47 | print([[#endif]]) | ||
48 | end | ||
49 | print([[ {NULL, 0L}]]) | ||
50 | print([[ | ||
51 | }; | ||
52 | |||
53 | LSEC_API lsec_ssl_option_t* lsec_get_ssl_options() { | ||
54 | return ssl_options; | ||
55 | } | ||
56 | ]]) | ||
57 | end | ||
58 | |||
59 | local function loadoptions(file) | ||
60 | local options = {} | ||
61 | local f = assert(io.open(file, "r")) | ||
62 | for line in f:lines() do | ||
63 | local op = string.match(line, "define%s+(SSL_OP_BIT%()") | ||
64 | if not op then | ||
65 | op = string.match(line, "define%s+(SSL_OP_%S+)") | ||
66 | if op then | ||
67 | table.insert(options, op) | ||
68 | end | ||
69 | end | ||
70 | end | ||
71 | table.sort(options, function(a,b) return a<b end) | ||
72 | return options | ||
73 | end | ||
74 | -- | ||
75 | |||
76 | local options | ||
77 | local flag, file, version = ... | ||
78 | |||
79 | version = version or "Unknown" | ||
80 | |||
81 | if not file then | ||
82 | usage() | ||
83 | elseif flag == "-g" then | ||
84 | options = loadoptions(file) | ||
85 | generate(options, version) | ||
86 | elseif flag == "-l" then | ||
87 | options = loadoptions(file) | ||
88 | for k, option in ipairs(options) do | ||
89 | print(option) | ||
90 | end | ||
91 | else | ||
92 | usage() | ||
93 | end | ||
diff --git a/vendor/luasec/src/ssl.c b/vendor/luasec/src/ssl.c new file mode 100644 index 00000000..934bb81b --- /dev/null +++ b/vendor/luasec/src/ssl.c | |||
@@ -0,0 +1,1092 @@ | |||
1 | /*-------------------------------------------------------------------------- | ||
2 | * LuaSec 1.3.2 | ||
3 | * | ||
4 | * Copyright (C) 2014-2023 Kim Alvefur, Paul Aurich, Tobias Markmann, Matthew Wild | ||
5 | * Copyright (C) 2006-2023 Bruno Silvestre | ||
6 | * | ||
7 | *--------------------------------------------------------------------------*/ | ||
8 | |||
9 | #include <errno.h> | ||
10 | #include <string.h> | ||
11 | |||
12 | #if defined(WIN32) | ||
13 | #include <winsock2.h> | ||
14 | #endif | ||
15 | |||
16 | #include <openssl/ssl.h> | ||
17 | #include <openssl/x509v3.h> | ||
18 | #include <openssl/x509_vfy.h> | ||
19 | #include <openssl/err.h> | ||
20 | #include <openssl/dh.h> | ||
21 | |||
22 | #include <lua.h> | ||
23 | #include <lauxlib.h> | ||
24 | |||
25 | #include <luasocket/io.h> | ||
26 | #include <luasocket/buffer.h> | ||
27 | #include <luasocket/timeout.h> | ||
28 | #include <luasocket/socket.h> | ||
29 | |||
30 | #include "x509.h" | ||
31 | #include "context.h" | ||
32 | #include "ssl.h" | ||
33 | |||
34 | |||
35 | #ifndef LSEC_API_OPENSSL_1_1_0 | ||
36 | #define SSL_is_server(s) (s->server) | ||
37 | #define SSL_up_ref(ssl) CRYPTO_add(&(ssl)->references, 1, CRYPTO_LOCK_SSL) | ||
38 | #define X509_up_ref(c) CRYPTO_add(&c->references, 1, CRYPTO_LOCK_X509) | ||
39 | #endif | ||
40 | |||
41 | |||
42 | /** | ||
43 | * Underline socket error. | ||
44 | */ | ||
45 | static int lsec_socket_error() | ||
46 | { | ||
47 | #if defined(WIN32) | ||
48 | return WSAGetLastError(); | ||
49 | #else | ||
50 | #if defined(LSEC_OPENSSL_ERRNO_BUG) | ||
51 | // Bug in OpenSSL | ||
52 | if (errno == 0) | ||
53 | return LSEC_IO_SSL; | ||
54 | #endif | ||
55 | return errno; | ||
56 | #endif | ||
57 | } | ||
58 | |||
59 | /** | ||
60 | * Map error code into string. | ||
61 | */ | ||
62 | static const char *ssl_ioerror(void *ctx, int err) | ||
63 | { | ||
64 | if (err == LSEC_IO_SSL) { | ||
65 | p_ssl ssl = (p_ssl) ctx; | ||
66 | switch(ssl->error) { | ||
67 | case SSL_ERROR_NONE: return "No error"; | ||
68 | case SSL_ERROR_ZERO_RETURN: return "closed"; | ||
69 | case SSL_ERROR_WANT_READ: return "wantread"; | ||
70 | case SSL_ERROR_WANT_WRITE: return "wantwrite"; | ||
71 | case SSL_ERROR_WANT_CONNECT: return "'connect' not completed"; | ||
72 | case SSL_ERROR_WANT_ACCEPT: return "'accept' not completed"; | ||
73 | case SSL_ERROR_WANT_X509_LOOKUP: return "Waiting for callback"; | ||
74 | case SSL_ERROR_SYSCALL: return "System error"; | ||
75 | case SSL_ERROR_SSL: return ERR_reason_error_string(ERR_get_error()); | ||
76 | default: return "Unknown SSL error"; | ||
77 | } | ||
78 | } | ||
79 | return socket_strerror(err); | ||
80 | } | ||
81 | |||
82 | /** | ||
83 | * Close the connection before the GC collect the object. | ||
84 | */ | ||
85 | static int meth_destroy(lua_State *L) | ||
86 | { | ||
87 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
88 | if (ssl->state == LSEC_STATE_CONNECTED) { | ||
89 | socket_setblocking(&ssl->sock); | ||
90 | SSL_shutdown(ssl->ssl); | ||
91 | } | ||
92 | if (ssl->sock != SOCKET_INVALID) { | ||
93 | socket_destroy(&ssl->sock); | ||
94 | } | ||
95 | ssl->state = LSEC_STATE_CLOSED; | ||
96 | if (ssl->ssl) { | ||
97 | /* Clear the registries */ | ||
98 | luaL_getmetatable(L, "SSL:Verify:Registry"); | ||
99 | lua_pushlightuserdata(L, (void*)ssl->ssl); | ||
100 | lua_pushnil(L); | ||
101 | lua_settable(L, -3); | ||
102 | luaL_getmetatable(L, "SSL:SNI:Registry"); | ||
103 | lua_pushlightuserdata(L, (void*)ssl->ssl); | ||
104 | lua_pushnil(L); | ||
105 | lua_settable(L, -3); | ||
106 | /* Destroy the object */ | ||
107 | SSL_free(ssl->ssl); | ||
108 | ssl->ssl = NULL; | ||
109 | } | ||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * Perform the TLS/SSL handshake | ||
115 | */ | ||
116 | static int handshake(p_ssl ssl) | ||
117 | { | ||
118 | int err; | ||
119 | p_timeout tm = timeout_markstart(&ssl->tm); | ||
120 | if (ssl->state == LSEC_STATE_CLOSED) | ||
121 | return IO_CLOSED; | ||
122 | for ( ; ; ) { | ||
123 | ERR_clear_error(); | ||
124 | err = SSL_do_handshake(ssl->ssl); | ||
125 | ssl->error = SSL_get_error(ssl->ssl, err); | ||
126 | switch (ssl->error) { | ||
127 | case SSL_ERROR_NONE: | ||
128 | ssl->state = LSEC_STATE_CONNECTED; | ||
129 | return IO_DONE; | ||
130 | case SSL_ERROR_WANT_READ: | ||
131 | err = socket_waitfd(&ssl->sock, WAITFD_R, tm); | ||
132 | if (err == IO_TIMEOUT) return LSEC_IO_SSL; | ||
133 | if (err != IO_DONE) return err; | ||
134 | break; | ||
135 | case SSL_ERROR_WANT_WRITE: | ||
136 | err = socket_waitfd(&ssl->sock, WAITFD_W, tm); | ||
137 | if (err == IO_TIMEOUT) return LSEC_IO_SSL; | ||
138 | if (err != IO_DONE) return err; | ||
139 | break; | ||
140 | case SSL_ERROR_SYSCALL: | ||
141 | if (ERR_peek_error()) { | ||
142 | ssl->error = SSL_ERROR_SSL; | ||
143 | return LSEC_IO_SSL; | ||
144 | } | ||
145 | if (err == 0) | ||
146 | return IO_CLOSED; | ||
147 | return lsec_socket_error(); | ||
148 | default: | ||
149 | return LSEC_IO_SSL; | ||
150 | } | ||
151 | } | ||
152 | return IO_UNKNOWN; | ||
153 | } | ||
154 | |||
155 | /** | ||
156 | * Send data | ||
157 | */ | ||
158 | static int ssl_send(void *ctx, const char *data, size_t count, size_t *sent, | ||
159 | p_timeout tm) | ||
160 | { | ||
161 | int err; | ||
162 | p_ssl ssl = (p_ssl)ctx; | ||
163 | if (ssl->state != LSEC_STATE_CONNECTED) | ||
164 | return IO_CLOSED; | ||
165 | *sent = 0; | ||
166 | for ( ; ; ) { | ||
167 | ERR_clear_error(); | ||
168 | err = SSL_write(ssl->ssl, data, (int)count); | ||
169 | ssl->error = SSL_get_error(ssl->ssl, err); | ||
170 | switch (ssl->error) { | ||
171 | case SSL_ERROR_NONE: | ||
172 | *sent = err; | ||
173 | return IO_DONE; | ||
174 | case SSL_ERROR_WANT_READ: | ||
175 | err = socket_waitfd(&ssl->sock, WAITFD_R, tm); | ||
176 | if (err == IO_TIMEOUT) return LSEC_IO_SSL; | ||
177 | if (err != IO_DONE) return err; | ||
178 | break; | ||
179 | case SSL_ERROR_WANT_WRITE: | ||
180 | err = socket_waitfd(&ssl->sock, WAITFD_W, tm); | ||
181 | if (err == IO_TIMEOUT) return LSEC_IO_SSL; | ||
182 | if (err != IO_DONE) return err; | ||
183 | break; | ||
184 | case SSL_ERROR_SYSCALL: | ||
185 | if (ERR_peek_error()) { | ||
186 | ssl->error = SSL_ERROR_SSL; | ||
187 | return LSEC_IO_SSL; | ||
188 | } | ||
189 | if (err == 0) | ||
190 | return IO_CLOSED; | ||
191 | return lsec_socket_error(); | ||
192 | default: | ||
193 | return LSEC_IO_SSL; | ||
194 | } | ||
195 | } | ||
196 | return IO_UNKNOWN; | ||
197 | } | ||
198 | |||
199 | /** | ||
200 | * Receive data | ||
201 | */ | ||
202 | static int ssl_recv(void *ctx, char *data, size_t count, size_t *got, | ||
203 | p_timeout tm) | ||
204 | { | ||
205 | int err; | ||
206 | p_ssl ssl = (p_ssl)ctx; | ||
207 | *got = 0; | ||
208 | if (ssl->state != LSEC_STATE_CONNECTED) | ||
209 | return IO_CLOSED; | ||
210 | for ( ; ; ) { | ||
211 | ERR_clear_error(); | ||
212 | err = SSL_read(ssl->ssl, data, (int)count); | ||
213 | ssl->error = SSL_get_error(ssl->ssl, err); | ||
214 | switch (ssl->error) { | ||
215 | case SSL_ERROR_NONE: | ||
216 | *got = err; | ||
217 | return IO_DONE; | ||
218 | case SSL_ERROR_ZERO_RETURN: | ||
219 | return IO_CLOSED; | ||
220 | case SSL_ERROR_WANT_READ: | ||
221 | err = socket_waitfd(&ssl->sock, WAITFD_R, tm); | ||
222 | if (err == IO_TIMEOUT) return LSEC_IO_SSL; | ||
223 | if (err != IO_DONE) return err; | ||
224 | break; | ||
225 | case SSL_ERROR_WANT_WRITE: | ||
226 | err = socket_waitfd(&ssl->sock, WAITFD_W, tm); | ||
227 | if (err == IO_TIMEOUT) return LSEC_IO_SSL; | ||
228 | if (err != IO_DONE) return err; | ||
229 | break; | ||
230 | case SSL_ERROR_SYSCALL: | ||
231 | if (ERR_peek_error()) { | ||
232 | ssl->error = SSL_ERROR_SSL; | ||
233 | return LSEC_IO_SSL; | ||
234 | } | ||
235 | if (err == 0) | ||
236 | return IO_CLOSED; | ||
237 | return lsec_socket_error(); | ||
238 | default: | ||
239 | return LSEC_IO_SSL; | ||
240 | } | ||
241 | } | ||
242 | return IO_UNKNOWN; | ||
243 | } | ||
244 | |||
245 | static SSL_CTX* luaossl_testcontext(lua_State *L, int arg) { | ||
246 | SSL_CTX **ctx = luaL_testudata(L, arg, "SSL_CTX*"); | ||
247 | if (ctx) | ||
248 | return *ctx; | ||
249 | return NULL; | ||
250 | } | ||
251 | |||
252 | static SSL* luaossl_testssl(lua_State *L, int arg) { | ||
253 | SSL **ssl = luaL_testudata(L, arg, "SSL*"); | ||
254 | if (ssl) | ||
255 | return *ssl; | ||
256 | return NULL; | ||
257 | } | ||
258 | |||
259 | /** | ||
260 | * Create a new TLS/SSL object and mark it as new. | ||
261 | */ | ||
262 | static int meth_create(lua_State *L) | ||
263 | { | ||
264 | p_ssl ssl; | ||
265 | int mode; | ||
266 | SSL_CTX *ctx; | ||
267 | |||
268 | lua_settop(L, 1); | ||
269 | |||
270 | ssl = (p_ssl)lua_newuserdata(L, sizeof(t_ssl)); | ||
271 | if (!ssl) { | ||
272 | lua_pushnil(L); | ||
273 | lua_pushstring(L, "error creating SSL object"); | ||
274 | return 2; | ||
275 | } | ||
276 | |||
277 | if ((ctx = lsec_testcontext(L, 1))) { | ||
278 | mode = lsec_getmode(L, 1); | ||
279 | if (mode == LSEC_MODE_INVALID) { | ||
280 | lua_pushnil(L); | ||
281 | lua_pushstring(L, "invalid mode"); | ||
282 | return 2; | ||
283 | } | ||
284 | ssl->ssl = SSL_new(ctx); | ||
285 | if (!ssl->ssl) { | ||
286 | lua_pushnil(L); | ||
287 | lua_pushfstring(L, "error creating SSL object (%s)", | ||
288 | ERR_reason_error_string(ERR_get_error())); | ||
289 | return 2; | ||
290 | } | ||
291 | } else if ((ctx = luaossl_testcontext(L, 1))) { | ||
292 | ssl->ssl = SSL_new(ctx); | ||
293 | if (!ssl->ssl) { | ||
294 | lua_pushnil(L); | ||
295 | lua_pushfstring(L, "error creating SSL object (%s)", | ||
296 | ERR_reason_error_string(ERR_get_error())); | ||
297 | return 2; | ||
298 | } | ||
299 | mode = SSL_is_server(ssl->ssl) ? LSEC_MODE_SERVER : LSEC_MODE_CLIENT; | ||
300 | } else if ((ssl->ssl = luaossl_testssl(L, 1))) { | ||
301 | SSL_up_ref(ssl->ssl); | ||
302 | mode = SSL_is_server(ssl->ssl) ? LSEC_MODE_SERVER : LSEC_MODE_CLIENT; | ||
303 | } else { | ||
304 | return luaL_argerror(L, 1, "invalid context"); | ||
305 | } | ||
306 | ssl->state = LSEC_STATE_NEW; | ||
307 | SSL_set_fd(ssl->ssl, (int)SOCKET_INVALID); | ||
308 | SSL_set_mode(ssl->ssl, SSL_MODE_ENABLE_PARTIAL_WRITE | | ||
309 | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); | ||
310 | SSL_set_mode(ssl->ssl, SSL_MODE_RELEASE_BUFFERS); | ||
311 | if (mode == LSEC_MODE_SERVER) | ||
312 | SSL_set_accept_state(ssl->ssl); | ||
313 | else | ||
314 | SSL_set_connect_state(ssl->ssl); | ||
315 | |||
316 | io_init(&ssl->io, (p_send)ssl_send, (p_recv)ssl_recv, | ||
317 | (p_error) ssl_ioerror, ssl); | ||
318 | timeout_init(&ssl->tm, -1, -1); | ||
319 | buffer_init(&ssl->buf, &ssl->io, &ssl->tm); | ||
320 | |||
321 | luaL_getmetatable(L, "SSL:Connection"); | ||
322 | lua_setmetatable(L, -2); | ||
323 | return 1; | ||
324 | } | ||
325 | |||
326 | /** | ||
327 | * Buffer send function | ||
328 | */ | ||
329 | static int meth_send(lua_State *L) { | ||
330 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
331 | return buffer_meth_send(L, &ssl->buf); | ||
332 | } | ||
333 | |||
334 | /** | ||
335 | * Buffer receive function | ||
336 | */ | ||
337 | static int meth_receive(lua_State *L) { | ||
338 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
339 | return buffer_meth_receive(L, &ssl->buf); | ||
340 | } | ||
341 | |||
342 | /** | ||
343 | * Get the buffer's statistics. | ||
344 | */ | ||
345 | static int meth_getstats(lua_State *L) { | ||
346 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
347 | return buffer_meth_getstats(L, &ssl->buf); | ||
348 | } | ||
349 | |||
350 | /** | ||
351 | * Set the buffer's statistics. | ||
352 | */ | ||
353 | static int meth_setstats(lua_State *L) { | ||
354 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
355 | return buffer_meth_setstats(L, &ssl->buf); | ||
356 | } | ||
357 | |||
358 | /** | ||
359 | * Select support methods | ||
360 | */ | ||
361 | static int meth_getfd(lua_State *L) | ||
362 | { | ||
363 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
364 | lua_pushnumber(L, ssl->sock); | ||
365 | return 1; | ||
366 | } | ||
367 | |||
368 | /** | ||
369 | * Set the TLS/SSL file descriptor. | ||
370 | * Call it *before* the handshake. | ||
371 | */ | ||
372 | static int meth_setfd(lua_State *L) | ||
373 | { | ||
374 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
375 | if (ssl->state != LSEC_STATE_NEW) | ||
376 | luaL_argerror(L, 1, "invalid SSL object state"); | ||
377 | ssl->sock = (t_socket)luaL_checkinteger(L, 2); | ||
378 | socket_setnonblocking(&ssl->sock); | ||
379 | SSL_set_fd(ssl->ssl, (int)ssl->sock); | ||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | /** | ||
384 | * Lua handshake function. | ||
385 | */ | ||
386 | static int meth_handshake(lua_State *L) | ||
387 | { | ||
388 | int err; | ||
389 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
390 | p_context ctx = (p_context)SSL_CTX_get_app_data(SSL_get_SSL_CTX(ssl->ssl)); | ||
391 | ctx->L = L; | ||
392 | err = handshake(ssl); | ||
393 | if (ctx->dh_param) { | ||
394 | DH_free(ctx->dh_param); | ||
395 | ctx->dh_param = NULL; | ||
396 | } | ||
397 | if (ctx->alpn) { | ||
398 | free(ctx->alpn); | ||
399 | ctx->alpn = NULL; | ||
400 | } | ||
401 | if (err == IO_DONE) { | ||
402 | lua_pushboolean(L, 1); | ||
403 | return 1; | ||
404 | } | ||
405 | lua_pushboolean(L, 0); | ||
406 | lua_pushstring(L, ssl_ioerror((void*)ssl, err)); | ||
407 | return 2; | ||
408 | } | ||
409 | |||
410 | /** | ||
411 | * Close the connection. | ||
412 | */ | ||
413 | static int meth_close(lua_State *L) | ||
414 | { | ||
415 | meth_destroy(L); | ||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | /** | ||
420 | * Set timeout. | ||
421 | */ | ||
422 | static int meth_settimeout(lua_State *L) | ||
423 | { | ||
424 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
425 | return timeout_meth_settimeout(L, &ssl->tm); | ||
426 | } | ||
427 | |||
428 | /** | ||
429 | * Check if there is data in the buffer. | ||
430 | */ | ||
431 | static int meth_dirty(lua_State *L) | ||
432 | { | ||
433 | int res = 0; | ||
434 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
435 | if (ssl->state != LSEC_STATE_CLOSED) | ||
436 | res = !buffer_isempty(&ssl->buf) || SSL_pending(ssl->ssl); | ||
437 | lua_pushboolean(L, res); | ||
438 | return 1; | ||
439 | } | ||
440 | |||
441 | /** | ||
442 | * Return the state information about the SSL object. | ||
443 | */ | ||
444 | static int meth_want(lua_State *L) | ||
445 | { | ||
446 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
447 | int code = (ssl->state == LSEC_STATE_CLOSED) | ||
448 | ? SSL_NOTHING | ||
449 | : SSL_want(ssl->ssl); | ||
450 | switch(code) { | ||
451 | case SSL_NOTHING: lua_pushstring(L, "nothing"); break; | ||
452 | case SSL_READING: lua_pushstring(L, "read"); break; | ||
453 | case SSL_WRITING: lua_pushstring(L, "write"); break; | ||
454 | case SSL_X509_LOOKUP: lua_pushstring(L, "x509lookup"); break; | ||
455 | } | ||
456 | return 1; | ||
457 | } | ||
458 | |||
459 | /** | ||
460 | * Return the compression method used. | ||
461 | */ | ||
462 | static int meth_compression(lua_State *L) | ||
463 | { | ||
464 | #ifdef OPENSSL_NO_COMP | ||
465 | const void *comp; | ||
466 | #else | ||
467 | const COMP_METHOD *comp; | ||
468 | #endif | ||
469 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
470 | if (ssl->state != LSEC_STATE_CONNECTED) { | ||
471 | lua_pushnil(L); | ||
472 | lua_pushstring(L, "closed"); | ||
473 | return 2; | ||
474 | } | ||
475 | comp = SSL_get_current_compression(ssl->ssl); | ||
476 | if (comp) | ||
477 | lua_pushstring(L, SSL_COMP_get_name(comp)); | ||
478 | else | ||
479 | lua_pushnil(L); | ||
480 | return 1; | ||
481 | } | ||
482 | |||
483 | /** | ||
484 | * Return the nth certificate of the peer's chain. | ||
485 | */ | ||
486 | static int meth_getpeercertificate(lua_State *L) | ||
487 | { | ||
488 | int n; | ||
489 | X509 *cert; | ||
490 | STACK_OF(X509) *certs; | ||
491 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
492 | if (ssl->state != LSEC_STATE_CONNECTED) { | ||
493 | lua_pushnil(L); | ||
494 | lua_pushstring(L, "closed"); | ||
495 | return 2; | ||
496 | } | ||
497 | /* Default to the first cert */ | ||
498 | n = (int)luaL_optinteger(L, 2, 1); | ||
499 | /* This function is 1-based, but OpenSSL is 0-based */ | ||
500 | --n; | ||
501 | if (n < 0) { | ||
502 | lua_pushnil(L); | ||
503 | lua_pushliteral(L, "invalid certificate index"); | ||
504 | return 2; | ||
505 | } | ||
506 | if (n == 0) { | ||
507 | cert = SSL_get_peer_certificate(ssl->ssl); | ||
508 | if (cert) | ||
509 | lsec_pushx509(L, cert); | ||
510 | else | ||
511 | lua_pushnil(L); | ||
512 | return 1; | ||
513 | } | ||
514 | /* In a server-context, the stack doesn't contain the peer cert, | ||
515 | * so adjust accordingly. | ||
516 | */ | ||
517 | if (SSL_is_server(ssl->ssl)) | ||
518 | --n; | ||
519 | certs = SSL_get_peer_cert_chain(ssl->ssl); | ||
520 | if (n >= sk_X509_num(certs)) { | ||
521 | lua_pushnil(L); | ||
522 | return 1; | ||
523 | } | ||
524 | cert = sk_X509_value(certs, n); | ||
525 | /* Increment the reference counting of the object. */ | ||
526 | /* See SSL_get_peer_certificate() source code. */ | ||
527 | X509_up_ref(cert); | ||
528 | lsec_pushx509(L, cert); | ||
529 | return 1; | ||
530 | } | ||
531 | |||
532 | /** | ||
533 | * Return the nth certificate of the chain sent to our peer. | ||
534 | */ | ||
535 | static int meth_getlocalcertificate(lua_State *L) | ||
536 | { | ||
537 | int n; | ||
538 | X509 *cert; | ||
539 | STACK_OF(X509) *certs; | ||
540 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
541 | if (ssl->state != LSEC_STATE_CONNECTED) { | ||
542 | lua_pushnil(L); | ||
543 | lua_pushstring(L, "closed"); | ||
544 | return 2; | ||
545 | } | ||
546 | /* Default to the first cert */ | ||
547 | n = (int)luaL_optinteger(L, 2, 1); | ||
548 | /* This function is 1-based, but OpenSSL is 0-based */ | ||
549 | --n; | ||
550 | if (n < 0) { | ||
551 | lua_pushnil(L); | ||
552 | lua_pushliteral(L, "invalid certificate index"); | ||
553 | return 2; | ||
554 | } | ||
555 | if (n == 0) { | ||
556 | cert = SSL_get_certificate(ssl->ssl); | ||
557 | if (cert) | ||
558 | lsec_pushx509(L, cert); | ||
559 | else | ||
560 | lua_pushnil(L); | ||
561 | return 1; | ||
562 | } | ||
563 | /* In a server-context, the stack doesn't contain the peer cert, | ||
564 | * so adjust accordingly. | ||
565 | */ | ||
566 | if (SSL_is_server(ssl->ssl)) | ||
567 | --n; | ||
568 | if(SSL_get0_chain_certs(ssl->ssl, &certs) != 1) { | ||
569 | lua_pushnil(L); | ||
570 | } else { | ||
571 | if (n >= sk_X509_num(certs)) { | ||
572 | lua_pushnil(L); | ||
573 | return 1; | ||
574 | } | ||
575 | cert = sk_X509_value(certs, n); | ||
576 | /* Increment the reference counting of the object. */ | ||
577 | /* See SSL_get_peer_certificate() source code. */ | ||
578 | X509_up_ref(cert); | ||
579 | lsec_pushx509(L, cert); | ||
580 | } | ||
581 | return 1; | ||
582 | } | ||
583 | |||
584 | /** | ||
585 | * Return the chain of certificate of the peer. | ||
586 | */ | ||
587 | static int meth_getpeerchain(lua_State *L) | ||
588 | { | ||
589 | int i; | ||
590 | int idx = 1; | ||
591 | int n_certs; | ||
592 | X509 *cert; | ||
593 | STACK_OF(X509) *certs; | ||
594 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
595 | if (ssl->state != LSEC_STATE_CONNECTED) { | ||
596 | lua_pushnil(L); | ||
597 | lua_pushstring(L, "closed"); | ||
598 | return 2; | ||
599 | } | ||
600 | lua_newtable(L); | ||
601 | if (SSL_is_server(ssl->ssl)) { | ||
602 | lsec_pushx509(L, SSL_get_peer_certificate(ssl->ssl)); | ||
603 | lua_rawseti(L, -2, idx++); | ||
604 | } | ||
605 | certs = SSL_get_peer_cert_chain(ssl->ssl); | ||
606 | n_certs = sk_X509_num(certs); | ||
607 | for (i = 0; i < n_certs; i++) { | ||
608 | cert = sk_X509_value(certs, i); | ||
609 | /* Increment the reference counting of the object. */ | ||
610 | /* See SSL_get_peer_certificate() source code. */ | ||
611 | X509_up_ref(cert); | ||
612 | lsec_pushx509(L, cert); | ||
613 | lua_rawseti(L, -2, idx++); | ||
614 | } | ||
615 | return 1; | ||
616 | } | ||
617 | |||
618 | /** | ||
619 | * Return the chain of certificates sent to the peer. | ||
620 | */ | ||
621 | static int meth_getlocalchain(lua_State *L) | ||
622 | { | ||
623 | int i; | ||
624 | int idx = 1; | ||
625 | int n_certs; | ||
626 | X509 *cert; | ||
627 | STACK_OF(X509) *certs; | ||
628 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
629 | if (ssl->state != LSEC_STATE_CONNECTED) { | ||
630 | lua_pushnil(L); | ||
631 | lua_pushstring(L, "closed"); | ||
632 | return 2; | ||
633 | } | ||
634 | lua_newtable(L); | ||
635 | if (SSL_is_server(ssl->ssl)) { | ||
636 | lsec_pushx509(L, SSL_get_certificate(ssl->ssl)); | ||
637 | lua_rawseti(L, -2, idx++); | ||
638 | } | ||
639 | if(SSL_get0_chain_certs(ssl->ssl, &certs)) { | ||
640 | n_certs = sk_X509_num(certs); | ||
641 | for (i = 0; i < n_certs; i++) { | ||
642 | cert = sk_X509_value(certs, i); | ||
643 | /* Increment the reference counting of the object. */ | ||
644 | /* See SSL_get_peer_certificate() source code. */ | ||
645 | X509_up_ref(cert); | ||
646 | lsec_pushx509(L, cert); | ||
647 | lua_rawseti(L, -2, idx++); | ||
648 | } | ||
649 | } | ||
650 | return 1; | ||
651 | } | ||
652 | |||
653 | /** | ||
654 | * Copy the table src to the table dst. | ||
655 | */ | ||
656 | static void copy_error_table(lua_State *L, int src, int dst) | ||
657 | { | ||
658 | lua_pushnil(L); | ||
659 | while (lua_next(L, src) != 0) { | ||
660 | if (lua_istable(L, -1)) { | ||
661 | /* Replace the table with its copy */ | ||
662 | lua_newtable(L); | ||
663 | copy_error_table(L, dst+2, dst+3); | ||
664 | lua_remove(L, dst+2); | ||
665 | } | ||
666 | lua_pushvalue(L, -2); | ||
667 | lua_pushvalue(L, -2); | ||
668 | lua_rawset(L, dst); | ||
669 | /* Remove the value and leave the key */ | ||
670 | lua_pop(L, 1); | ||
671 | } | ||
672 | } | ||
673 | |||
674 | /** | ||
675 | * Return the verification state of the peer chain. | ||
676 | */ | ||
677 | static int meth_getpeerverification(lua_State *L) | ||
678 | { | ||
679 | long err; | ||
680 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
681 | if (ssl->state != LSEC_STATE_CONNECTED) { | ||
682 | lua_pushboolean(L, 0); | ||
683 | lua_pushstring(L, "closed"); | ||
684 | return 2; | ||
685 | } | ||
686 | err = SSL_get_verify_result(ssl->ssl); | ||
687 | if (err == X509_V_OK) { | ||
688 | lua_pushboolean(L, 1); | ||
689 | return 1; | ||
690 | } | ||
691 | luaL_getmetatable(L, "SSL:Verify:Registry"); | ||
692 | lua_pushlightuserdata(L, (void*)ssl->ssl); | ||
693 | lua_gettable(L, -2); | ||
694 | if (lua_isnil(L, -1)) | ||
695 | lua_pushstring(L, X509_verify_cert_error_string(err)); | ||
696 | else { | ||
697 | /* Copy the table of errors to avoid modifications */ | ||
698 | lua_newtable(L); | ||
699 | copy_error_table(L, lua_gettop(L)-1, lua_gettop(L)); | ||
700 | } | ||
701 | lua_pushboolean(L, 0); | ||
702 | lua_pushvalue(L, -2); | ||
703 | return 2; | ||
704 | } | ||
705 | |||
706 | /** | ||
707 | * Get the latest "Finished" message sent out. | ||
708 | */ | ||
709 | static int meth_getfinished(lua_State *L) | ||
710 | { | ||
711 | size_t len = 0; | ||
712 | char *buffer = NULL; | ||
713 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
714 | if (ssl->state != LSEC_STATE_CONNECTED) { | ||
715 | lua_pushnil(L); | ||
716 | lua_pushstring(L, "closed"); | ||
717 | return 2; | ||
718 | } | ||
719 | if ((len = SSL_get_finished(ssl->ssl, NULL, 0)) == 0) | ||
720 | return 0; | ||
721 | buffer = (char*)malloc(len); | ||
722 | if (!buffer) { | ||
723 | lua_pushnil(L); | ||
724 | lua_pushstring(L, "out of memory"); | ||
725 | return 2; | ||
726 | } | ||
727 | SSL_get_finished(ssl->ssl, buffer, len); | ||
728 | lua_pushlstring(L, buffer, len); | ||
729 | free(buffer); | ||
730 | return 1; | ||
731 | } | ||
732 | |||
733 | /** | ||
734 | * Gets the latest "Finished" message received. | ||
735 | */ | ||
736 | static int meth_getpeerfinished(lua_State *L) | ||
737 | { | ||
738 | size_t len = 0; | ||
739 | char *buffer = NULL; | ||
740 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
741 | if (ssl->state != LSEC_STATE_CONNECTED) { | ||
742 | lua_pushnil(L); | ||
743 | lua_pushstring(L, "closed"); | ||
744 | return 0; | ||
745 | } | ||
746 | if ((len = SSL_get_peer_finished(ssl->ssl, NULL, 0)) == 0) | ||
747 | return 0; | ||
748 | buffer = (char*)malloc(len); | ||
749 | if (!buffer) { | ||
750 | lua_pushnil(L); | ||
751 | lua_pushstring(L, "out of memory"); | ||
752 | return 2; | ||
753 | } | ||
754 | SSL_get_peer_finished(ssl->ssl, buffer, len); | ||
755 | lua_pushlstring(L, buffer, len); | ||
756 | free(buffer); | ||
757 | return 1; | ||
758 | } | ||
759 | |||
760 | /** | ||
761 | * Get some shared keying material | ||
762 | */ | ||
763 | static int meth_exportkeyingmaterial(lua_State *L) | ||
764 | { | ||
765 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
766 | |||
767 | if(ssl->state != LSEC_STATE_CONNECTED) { | ||
768 | lua_pushnil(L); | ||
769 | lua_pushstring(L, "closed"); | ||
770 | return 0; | ||
771 | } | ||
772 | |||
773 | size_t llen = 0; | ||
774 | size_t contextlen = 0; | ||
775 | const unsigned char *context = NULL; | ||
776 | const char *label = (const char*)luaL_checklstring(L, 2, &llen); | ||
777 | size_t olen = (size_t)luaL_checkinteger(L, 3); | ||
778 | |||
779 | if (!lua_isnoneornil(L, 4)) | ||
780 | context = (const unsigned char*)luaL_checklstring(L, 4, &contextlen); | ||
781 | |||
782 | /* Temporary buffer memory-managed by Lua itself */ | ||
783 | unsigned char *out = (unsigned char*)lua_newuserdata(L, olen); | ||
784 | |||
785 | if(SSL_export_keying_material(ssl->ssl, out, olen, label, llen, context, contextlen, context != NULL) != 1) { | ||
786 | lua_pushnil(L); | ||
787 | lua_pushstring(L, "error exporting keying material"); | ||
788 | return 2; | ||
789 | } | ||
790 | |||
791 | lua_pushlstring(L, (char*)out, olen); | ||
792 | return 1; | ||
793 | } | ||
794 | |||
795 | /** | ||
796 | * Object information -- tostring metamethod | ||
797 | */ | ||
798 | static int meth_tostring(lua_State *L) | ||
799 | { | ||
800 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
801 | lua_pushfstring(L, "SSL connection: %p%s", ssl, | ||
802 | ssl->state == LSEC_STATE_CLOSED ? " (closed)" : ""); | ||
803 | return 1; | ||
804 | } | ||
805 | |||
806 | /** | ||
807 | * Add a method in the SSL metatable. | ||
808 | */ | ||
809 | static int meth_setmethod(lua_State *L) | ||
810 | { | ||
811 | luaL_getmetatable(L, "SSL:Connection"); | ||
812 | lua_pushstring(L, "__index"); | ||
813 | lua_gettable(L, -2); | ||
814 | lua_pushvalue(L, 1); | ||
815 | lua_pushvalue(L, 2); | ||
816 | lua_settable(L, -3); | ||
817 | return 0; | ||
818 | } | ||
819 | |||
820 | /** | ||
821 | * Return information about the connection. | ||
822 | */ | ||
823 | static int meth_info(lua_State *L) | ||
824 | { | ||
825 | int bits = 0; | ||
826 | int algbits = 0; | ||
827 | char buf[256] = {0}; | ||
828 | const SSL_CIPHER *cipher; | ||
829 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
830 | cipher = SSL_get_current_cipher(ssl->ssl); | ||
831 | if (!cipher) | ||
832 | return 0; | ||
833 | SSL_CIPHER_description(cipher, buf, sizeof(buf)); | ||
834 | bits = SSL_CIPHER_get_bits(cipher, &algbits); | ||
835 | lua_pushstring(L, buf); | ||
836 | lua_pushnumber(L, bits); | ||
837 | lua_pushnumber(L, algbits); | ||
838 | lua_pushstring(L, SSL_get_version(ssl->ssl)); | ||
839 | return 4; | ||
840 | } | ||
841 | |||
842 | static int sni_cb(SSL *ssl, int *ad, void *arg) | ||
843 | { | ||
844 | int strict; | ||
845 | SSL_CTX *newctx = NULL; | ||
846 | SSL_CTX *ctx = SSL_get_SSL_CTX(ssl); | ||
847 | lua_State *L = ((p_context)SSL_CTX_get_app_data(ctx))->L; | ||
848 | const char *name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); | ||
849 | /* No name, use default context */ | ||
850 | if (!name) | ||
851 | return SSL_TLSEXT_ERR_NOACK; | ||
852 | /* Retrieve struct from registry */ | ||
853 | luaL_getmetatable(L, "SSL:SNI:Registry"); | ||
854 | lua_pushlightuserdata(L, (void*)ssl); | ||
855 | lua_gettable(L, -2); | ||
856 | /* Strict search? */ | ||
857 | lua_pushstring(L, "strict"); | ||
858 | lua_gettable(L, -2); | ||
859 | strict = lua_toboolean(L, -1); | ||
860 | lua_pop(L, 1); | ||
861 | /* Search for the name in the map */ | ||
862 | lua_pushstring(L, "map"); | ||
863 | lua_gettable(L, -2); | ||
864 | lua_pushstring(L, name); | ||
865 | lua_gettable(L, -2); | ||
866 | if (lua_isuserdata(L, -1)) | ||
867 | newctx = lsec_checkcontext(L, -1); | ||
868 | lua_pop(L, 4); | ||
869 | /* Found, use this context */ | ||
870 | if (newctx) { | ||
871 | p_context pctx = (p_context)SSL_CTX_get_app_data(newctx); | ||
872 | pctx->L = L; | ||
873 | SSL_set_SSL_CTX(ssl, newctx); | ||
874 | return SSL_TLSEXT_ERR_OK; | ||
875 | } | ||
876 | /* Not found, but use initial context */ | ||
877 | if (!strict) | ||
878 | return SSL_TLSEXT_ERR_OK; | ||
879 | return SSL_TLSEXT_ERR_ALERT_FATAL; | ||
880 | } | ||
881 | |||
882 | static int meth_sni(lua_State *L) | ||
883 | { | ||
884 | int strict; | ||
885 | SSL_CTX *aux; | ||
886 | const char *name; | ||
887 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
888 | SSL_CTX *ctx = SSL_get_SSL_CTX(ssl->ssl); | ||
889 | p_context pctx = (p_context)SSL_CTX_get_app_data(ctx); | ||
890 | if (pctx->mode == LSEC_MODE_CLIENT) { | ||
891 | name = luaL_checkstring(L, 2); | ||
892 | SSL_set_tlsext_host_name(ssl->ssl, name); | ||
893 | return 0; | ||
894 | } else if (pctx->mode == LSEC_MODE_SERVER) { | ||
895 | luaL_checktype(L, 2, LUA_TTABLE); | ||
896 | strict = lua_toboolean(L, 3); | ||
897 | /* Check if the table contains only (string -> context) */ | ||
898 | lua_pushnil(L); | ||
899 | while (lua_next(L, 2)) { | ||
900 | luaL_checkstring(L, -2); | ||
901 | aux = lsec_checkcontext(L, -1); | ||
902 | /* Set callback in every context */ | ||
903 | SSL_CTX_set_tlsext_servername_callback(aux, sni_cb); | ||
904 | /* leave the next key on the stack */ | ||
905 | lua_pop(L, 1); | ||
906 | } | ||
907 | /* Save table in the register */ | ||
908 | luaL_getmetatable(L, "SSL:SNI:Registry"); | ||
909 | lua_pushlightuserdata(L, (void*)ssl->ssl); | ||
910 | lua_newtable(L); | ||
911 | lua_pushstring(L, "map"); | ||
912 | lua_pushvalue(L, 2); | ||
913 | lua_settable(L, -3); | ||
914 | lua_pushstring(L, "strict"); | ||
915 | lua_pushboolean(L, strict); | ||
916 | lua_settable(L, -3); | ||
917 | lua_settable(L, -3); | ||
918 | /* Set callback in the default context */ | ||
919 | SSL_CTX_set_tlsext_servername_callback(ctx, sni_cb); | ||
920 | } | ||
921 | return 0; | ||
922 | } | ||
923 | |||
924 | static int meth_getsniname(lua_State *L) | ||
925 | { | ||
926 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
927 | const char *name = SSL_get_servername(ssl->ssl, TLSEXT_NAMETYPE_host_name); | ||
928 | if (name) | ||
929 | lua_pushstring(L, name); | ||
930 | else | ||
931 | lua_pushnil(L); | ||
932 | return 1; | ||
933 | } | ||
934 | |||
935 | static int meth_getalpn(lua_State *L) | ||
936 | { | ||
937 | unsigned len; | ||
938 | const unsigned char *data; | ||
939 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
940 | SSL_get0_alpn_selected(ssl->ssl, &data, &len); | ||
941 | if (data == NULL && len == 0) | ||
942 | lua_pushnil(L); | ||
943 | else | ||
944 | lua_pushlstring(L, (const char*)data, len); | ||
945 | return 1; | ||
946 | } | ||
947 | |||
948 | static int meth_copyright(lua_State *L) | ||
949 | { | ||
950 | lua_pushstring(L, "LuaSec 1.3.2 - Copyright (C) 2006-2023 Bruno Silvestre, UFG" | ||
951 | #if defined(WITH_LUASOCKET) | ||
952 | "\nLuaSocket 3.0-RC1 - Copyright (C) 2004-2013 Diego Nehab" | ||
953 | #endif | ||
954 | ); | ||
955 | return 1; | ||
956 | } | ||
957 | |||
958 | #if defined(LSEC_ENABLE_DANE) | ||
959 | static int meth_dane(lua_State *L) | ||
960 | { | ||
961 | int ret; | ||
962 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
963 | ret = SSL_dane_enable(ssl->ssl, luaL_checkstring(L, 2)); | ||
964 | lua_pushboolean(L, (ret > 0)); | ||
965 | return 1; | ||
966 | } | ||
967 | |||
968 | static int meth_tlsa(lua_State *L) | ||
969 | { | ||
970 | int ret; | ||
971 | size_t len; | ||
972 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
973 | uint8_t usage = (uint8_t)luaL_checkinteger(L, 2); | ||
974 | uint8_t selector = (uint8_t)luaL_checkinteger(L, 3); | ||
975 | uint8_t mtype = (uint8_t)luaL_checkinteger(L, 4); | ||
976 | unsigned char *data = (unsigned char*)luaL_checklstring(L, 5, &len); | ||
977 | |||
978 | ERR_clear_error(); | ||
979 | ret = SSL_dane_tlsa_add(ssl->ssl, usage, selector, mtype, data, len); | ||
980 | lua_pushboolean(L, (ret > 0)); | ||
981 | |||
982 | return 1; | ||
983 | } | ||
984 | #endif | ||
985 | |||
986 | /*---------------------------------------------------------------------------*/ | ||
987 | |||
988 | /** | ||
989 | * SSL methods | ||
990 | */ | ||
991 | static luaL_Reg methods[] = { | ||
992 | {"close", meth_close}, | ||
993 | {"getalpn", meth_getalpn}, | ||
994 | {"getfd", meth_getfd}, | ||
995 | {"getfinished", meth_getfinished}, | ||
996 | {"getpeercertificate", meth_getpeercertificate}, | ||
997 | {"getlocalcertificate", meth_getlocalcertificate}, | ||
998 | {"getpeerchain", meth_getpeerchain}, | ||
999 | {"getlocalchain", meth_getlocalchain}, | ||
1000 | {"getpeerverification", meth_getpeerverification}, | ||
1001 | {"getpeerfinished", meth_getpeerfinished}, | ||
1002 | {"exportkeyingmaterial",meth_exportkeyingmaterial}, | ||
1003 | {"getsniname", meth_getsniname}, | ||
1004 | {"getstats", meth_getstats}, | ||
1005 | {"setstats", meth_setstats}, | ||
1006 | {"dirty", meth_dirty}, | ||
1007 | {"dohandshake", meth_handshake}, | ||
1008 | {"receive", meth_receive}, | ||
1009 | {"send", meth_send}, | ||
1010 | {"settimeout", meth_settimeout}, | ||
1011 | {"sni", meth_sni}, | ||
1012 | {"want", meth_want}, | ||
1013 | #if defined(LSEC_ENABLE_DANE) | ||
1014 | {"setdane", meth_dane}, | ||
1015 | {"settlsa", meth_tlsa}, | ||
1016 | #endif | ||
1017 | {NULL, NULL} | ||
1018 | }; | ||
1019 | |||
1020 | /** | ||
1021 | * SSL metamethods. | ||
1022 | */ | ||
1023 | static luaL_Reg meta[] = { | ||
1024 | {"__close", meth_destroy}, | ||
1025 | {"__gc", meth_destroy}, | ||
1026 | {"__tostring", meth_tostring}, | ||
1027 | {NULL, NULL} | ||
1028 | }; | ||
1029 | |||
1030 | /** | ||
1031 | * SSL functions. | ||
1032 | */ | ||
1033 | static luaL_Reg funcs[] = { | ||
1034 | {"compression", meth_compression}, | ||
1035 | {"create", meth_create}, | ||
1036 | {"info", meth_info}, | ||
1037 | {"setfd", meth_setfd}, | ||
1038 | {"setmethod", meth_setmethod}, | ||
1039 | {"copyright", meth_copyright}, | ||
1040 | {NULL, NULL} | ||
1041 | }; | ||
1042 | |||
1043 | /** | ||
1044 | * Initialize modules. | ||
1045 | */ | ||
1046 | LSEC_API int luaopen_ssl_core(lua_State *L) | ||
1047 | { | ||
1048 | #ifndef LSEC_API_OPENSSL_1_1_0 | ||
1049 | /* Initialize SSL */ | ||
1050 | if (!SSL_library_init()) { | ||
1051 | lua_pushstring(L, "unable to initialize SSL library"); | ||
1052 | lua_error(L); | ||
1053 | } | ||
1054 | OpenSSL_add_all_algorithms(); | ||
1055 | SSL_load_error_strings(); | ||
1056 | #endif | ||
1057 | |||
1058 | #if defined(WITH_LUASOCKET) | ||
1059 | /* Initialize internal library */ | ||
1060 | socket_open(); | ||
1061 | #endif | ||
1062 | |||
1063 | luaL_newmetatable(L, "SSL:SNI:Registry"); | ||
1064 | |||
1065 | /* Register the functions and tables */ | ||
1066 | luaL_newmetatable(L, "SSL:Connection"); | ||
1067 | setfuncs(L, meta); | ||
1068 | |||
1069 | luaL_newlib(L, methods); | ||
1070 | lua_setfield(L, -2, "__index"); | ||
1071 | |||
1072 | luaL_newlib(L, funcs); | ||
1073 | |||
1074 | lua_pushstring(L, "SOCKET_INVALID"); | ||
1075 | lua_pushinteger(L, SOCKET_INVALID); | ||
1076 | lua_rawset(L, -3); | ||
1077 | |||
1078 | return 1; | ||
1079 | } | ||
1080 | |||
1081 | //------------------------------------------------------------------------------ | ||
1082 | |||
1083 | #if defined(_MSC_VER) | ||
1084 | |||
1085 | /* Empty implementation to allow building with LuaRocks and MS compilers */ | ||
1086 | LSEC_API int luaopen_ssl(lua_State *L) { | ||
1087 | lua_pushstring(L, "you should not call this function"); | ||
1088 | lua_error(L); | ||
1089 | return 0; | ||
1090 | } | ||
1091 | |||
1092 | #endif | ||
diff --git a/vendor/luasec/src/ssl.h b/vendor/luasec/src/ssl.h new file mode 100644 index 00000000..2362ffe5 --- /dev/null +++ b/vendor/luasec/src/ssl.h | |||
@@ -0,0 +1,41 @@ | |||
1 | #ifndef LSEC_SSL_H | ||
2 | #define LSEC_SSL_H | ||
3 | |||
4 | /*-------------------------------------------------------------------------- | ||
5 | * LuaSec 1.3.2 | ||
6 | * | ||
7 | * Copyright (C) 2006-2023 Bruno Silvestre | ||
8 | * | ||
9 | *--------------------------------------------------------------------------*/ | ||
10 | |||
11 | #include <openssl/ssl.h> | ||
12 | #include <lua.h> | ||
13 | |||
14 | #include <luasocket/io.h> | ||
15 | #include <luasocket/buffer.h> | ||
16 | #include <luasocket/timeout.h> | ||
17 | #include <luasocket/socket.h> | ||
18 | |||
19 | #include "compat.h" | ||
20 | #include "context.h" | ||
21 | |||
22 | #define LSEC_STATE_NEW 1 | ||
23 | #define LSEC_STATE_CONNECTED 2 | ||
24 | #define LSEC_STATE_CLOSED 3 | ||
25 | |||
26 | #define LSEC_IO_SSL -100 | ||
27 | |||
28 | typedef struct t_ssl_ { | ||
29 | t_socket sock; | ||
30 | t_io io; | ||
31 | t_buffer buf; | ||
32 | t_timeout tm; | ||
33 | SSL *ssl; | ||
34 | int state; | ||
35 | int error; | ||
36 | } t_ssl; | ||
37 | typedef t_ssl* p_ssl; | ||
38 | |||
39 | LSEC_API int luaopen_ssl_core(lua_State *L); | ||
40 | |||
41 | #endif | ||
diff --git a/vendor/luasec/src/ssl.lua b/vendor/luasec/src/ssl.lua new file mode 100644 index 00000000..e22c047e --- /dev/null +++ b/vendor/luasec/src/ssl.lua | |||
@@ -0,0 +1,313 @@ | |||
1 | ------------------------------------------------------------------------------ | ||
2 | -- LuaSec 1.3.2 | ||
3 | -- | ||
4 | -- Copyright (C) 2006-2023 Bruno Silvestre | ||
5 | -- | ||
6 | ------------------------------------------------------------------------------ | ||
7 | |||
8 | local core = require("ssl.core") | ||
9 | local context = require("ssl.context") | ||
10 | local x509 = require("ssl.x509") | ||
11 | local config = require("ssl.config") | ||
12 | |||
13 | local unpack = table.unpack or unpack | ||
14 | |||
15 | -- We must prevent the contexts to be collected before the connections, | ||
16 | -- otherwise the C registry will be cleared. | ||
17 | local registry = setmetatable({}, {__mode="k"}) | ||
18 | |||
19 | -- | ||
20 | -- | ||
21 | -- | ||
22 | local function optexec(func, param, ctx) | ||
23 | if param then | ||
24 | if type(param) == "table" then | ||
25 | return func(ctx, unpack(param)) | ||
26 | else | ||
27 | return func(ctx, param) | ||
28 | end | ||
29 | end | ||
30 | return true | ||
31 | end | ||
32 | |||
33 | -- | ||
34 | -- Convert an array of strings to wire-format | ||
35 | -- | ||
36 | local function array2wireformat(array) | ||
37 | local str = "" | ||
38 | for k, v in ipairs(array) do | ||
39 | if type(v) ~= "string" then return nil end | ||
40 | local len = #v | ||
41 | if len == 0 then | ||
42 | return nil, "invalid ALPN name (empty string)" | ||
43 | elseif len > 255 then | ||
44 | return nil, "invalid ALPN name (length > 255)" | ||
45 | end | ||
46 | str = str .. string.char(len) .. v | ||
47 | end | ||
48 | if str == "" then return nil, "invalid ALPN list (empty)" end | ||
49 | return str | ||
50 | end | ||
51 | |||
52 | -- | ||
53 | -- Convert wire-string format to array | ||
54 | -- | ||
55 | local function wireformat2array(str) | ||
56 | local i = 1 | ||
57 | local array = {} | ||
58 | while i < #str do | ||
59 | local len = str:byte(i) | ||
60 | array[#array + 1] = str:sub(i + 1, i + len) | ||
61 | i = i + len + 1 | ||
62 | end | ||
63 | return array | ||
64 | end | ||
65 | |||
66 | -- | ||
67 | -- | ||
68 | -- | ||
69 | local function newcontext(cfg) | ||
70 | local succ, msg, ctx | ||
71 | -- Create the context | ||
72 | ctx, msg = context.create(cfg.protocol) | ||
73 | if not ctx then return nil, msg end | ||
74 | -- Mode | ||
75 | succ, msg = context.setmode(ctx, cfg.mode) | ||
76 | if not succ then return nil, msg end | ||
77 | local certificates = cfg.certificates | ||
78 | if not certificates then | ||
79 | certificates = { | ||
80 | { certificate = cfg.certificate, key = cfg.key, password = cfg.password } | ||
81 | } | ||
82 | end | ||
83 | for _, certificate in ipairs(certificates) do | ||
84 | -- Load the key | ||
85 | if certificate.key then | ||
86 | if certificate.password and | ||
87 | type(certificate.password) ~= "function" and | ||
88 | type(certificate.password) ~= "string" | ||
89 | then | ||
90 | return nil, "invalid password type" | ||
91 | end | ||
92 | succ, msg = context.loadkey(ctx, certificate.key, certificate.password) | ||
93 | if not succ then return nil, msg end | ||
94 | end | ||
95 | -- Load the certificate(s) | ||
96 | if certificate.certificate then | ||
97 | succ, msg = context.loadcert(ctx, certificate.certificate) | ||
98 | if not succ then return nil, msg end | ||
99 | if certificate.key and context.checkkey then | ||
100 | succ = context.checkkey(ctx) | ||
101 | if not succ then return nil, "private key does not match public key" end | ||
102 | end | ||
103 | end | ||
104 | end | ||
105 | -- Load the CA certificates | ||
106 | if cfg.cafile or cfg.capath then | ||
107 | succ, msg = context.locations(ctx, cfg.cafile, cfg.capath) | ||
108 | if not succ then return nil, msg end | ||
109 | end | ||
110 | -- Set SSL ciphers | ||
111 | if cfg.ciphers then | ||
112 | succ, msg = context.setcipher(ctx, cfg.ciphers) | ||
113 | if not succ then return nil, msg end | ||
114 | end | ||
115 | -- Set SSL cipher suites | ||
116 | if cfg.ciphersuites then | ||
117 | succ, msg = context.setciphersuites(ctx, cfg.ciphersuites) | ||
118 | if not succ then return nil, msg end | ||
119 | end | ||
120 | -- Set the verification options | ||
121 | succ, msg = optexec(context.setverify, cfg.verify, ctx) | ||
122 | if not succ then return nil, msg end | ||
123 | -- Set SSL options | ||
124 | succ, msg = optexec(context.setoptions, cfg.options, ctx) | ||
125 | if not succ then return nil, msg end | ||
126 | -- Set the depth for certificate verification | ||
127 | if cfg.depth then | ||
128 | succ, msg = context.setdepth(ctx, cfg.depth) | ||
129 | if not succ then return nil, msg end | ||
130 | end | ||
131 | |||
132 | -- NOTE: Setting DH parameters and elliptic curves needs to come after | ||
133 | -- setoptions(), in case the user has specified the single_{dh,ecdh}_use | ||
134 | -- options. | ||
135 | |||
136 | -- Set DH parameters | ||
137 | if cfg.dhparam then | ||
138 | if type(cfg.dhparam) ~= "function" then | ||
139 | return nil, "invalid DH parameter type" | ||
140 | end | ||
141 | context.setdhparam(ctx, cfg.dhparam) | ||
142 | end | ||
143 | |||
144 | -- Set elliptic curves | ||
145 | if (not config.algorithms.ec) and (cfg.curve or cfg.curveslist) then | ||
146 | return false, "elliptic curves not supported" | ||
147 | end | ||
148 | if config.capabilities.curves_list and cfg.curveslist then | ||
149 | succ, msg = context.setcurveslist(ctx, cfg.curveslist) | ||
150 | if not succ then return nil, msg end | ||
151 | elseif cfg.curve then | ||
152 | succ, msg = context.setcurve(ctx, cfg.curve) | ||
153 | if not succ then return nil, msg end | ||
154 | end | ||
155 | |||
156 | -- Set extra verification options | ||
157 | if cfg.verifyext and ctx.setverifyext then | ||
158 | succ, msg = optexec(ctx.setverifyext, cfg.verifyext, ctx) | ||
159 | if not succ then return nil, msg end | ||
160 | end | ||
161 | |||
162 | -- ALPN | ||
163 | if cfg.mode == "server" and cfg.alpn then | ||
164 | if type(cfg.alpn) == "function" then | ||
165 | local alpncb = cfg.alpn | ||
166 | -- This callback function has to return one value only | ||
167 | succ, msg = context.setalpncb(ctx, function(str) | ||
168 | local protocols = alpncb(wireformat2array(str)) | ||
169 | if type(protocols) == "string" then | ||
170 | protocols = { protocols } | ||
171 | elseif type(protocols) ~= "table" then | ||
172 | return nil | ||
173 | end | ||
174 | return (array2wireformat(protocols)) -- use "()" to drop error message | ||
175 | end) | ||
176 | if not succ then return nil, msg end | ||
177 | elseif type(cfg.alpn) == "table" then | ||
178 | local protocols = cfg.alpn | ||
179 | -- check if array is valid before use it | ||
180 | succ, msg = array2wireformat(protocols) | ||
181 | if not succ then return nil, msg end | ||
182 | -- This callback function has to return one value only | ||
183 | succ, msg = context.setalpncb(ctx, function() | ||
184 | return (array2wireformat(protocols)) -- use "()" to drop error message | ||
185 | end) | ||
186 | if not succ then return nil, msg end | ||
187 | else | ||
188 | return nil, "invalid ALPN parameter" | ||
189 | end | ||
190 | elseif cfg.mode == "client" and cfg.alpn then | ||
191 | local alpn | ||
192 | if type(cfg.alpn) == "string" then | ||
193 | alpn, msg = array2wireformat({ cfg.alpn }) | ||
194 | elseif type(cfg.alpn) == "table" then | ||
195 | alpn, msg = array2wireformat(cfg.alpn) | ||
196 | else | ||
197 | return nil, "invalid ALPN parameter" | ||
198 | end | ||
199 | if not alpn then return nil, msg end | ||
200 | succ, msg = context.setalpn(ctx, alpn) | ||
201 | if not succ then return nil, msg end | ||
202 | end | ||
203 | |||
204 | -- PSK | ||
205 | if config.capabilities.psk and cfg.psk then | ||
206 | if cfg.mode == "client" then | ||
207 | if type(cfg.psk) ~= "function" then | ||
208 | return nil, "invalid PSK configuration" | ||
209 | end | ||
210 | succ = context.setclientpskcb(ctx, cfg.psk) | ||
211 | if not succ then return nil, msg end | ||
212 | elseif cfg.mode == "server" then | ||
213 | if type(cfg.psk) == "function" then | ||
214 | succ, msg = context.setserverpskcb(ctx, cfg.psk) | ||
215 | if not succ then return nil, msg end | ||
216 | elseif type(cfg.psk) == "table" then | ||
217 | if type(cfg.psk.hint) == "string" and type(cfg.psk.callback) == "function" then | ||
218 | succ, msg = context.setpskhint(ctx, cfg.psk.hint) | ||
219 | if not succ then return succ, msg end | ||
220 | succ = context.setserverpskcb(ctx, cfg.psk.callback) | ||
221 | if not succ then return succ, msg end | ||
222 | else | ||
223 | return nil, "invalid PSK configuration" | ||
224 | end | ||
225 | else | ||
226 | return nil, "invalid PSK configuration" | ||
227 | end | ||
228 | end | ||
229 | end | ||
230 | |||
231 | if config.capabilities.dane and cfg.dane then | ||
232 | if type(cfg.dane) == "table" then | ||
233 | context.setdane(ctx, unpack(cfg.dane)) | ||
234 | else | ||
235 | context.setdane(ctx) | ||
236 | end | ||
237 | end | ||
238 | |||
239 | return ctx | ||
240 | end | ||
241 | |||
242 | -- | ||
243 | -- | ||
244 | -- | ||
245 | local function wrap(sock, cfg) | ||
246 | local ctx, msg | ||
247 | if type(cfg) == "table" then | ||
248 | ctx, msg = newcontext(cfg) | ||
249 | if not ctx then return nil, msg end | ||
250 | else | ||
251 | ctx = cfg | ||
252 | end | ||
253 | local s, msg = core.create(ctx) | ||
254 | if s then | ||
255 | core.setfd(s, sock:getfd()) | ||
256 | sock:setfd(core.SOCKET_INVALID) | ||
257 | registry[s] = ctx | ||
258 | return s | ||
259 | end | ||
260 | return nil, msg | ||
261 | end | ||
262 | |||
263 | -- | ||
264 | -- Extract connection information. | ||
265 | -- | ||
266 | local function info(ssl, field) | ||
267 | local str, comp, err, protocol | ||
268 | comp, err = core.compression(ssl) | ||
269 | if err then | ||
270 | return comp, err | ||
271 | end | ||
272 | -- Avoid parser | ||
273 | if field == "compression" then | ||
274 | return comp | ||
275 | end | ||
276 | local info = {compression = comp} | ||
277 | str, info.bits, info.algbits, protocol = core.info(ssl) | ||
278 | if str then | ||
279 | info.cipher, info.protocol, info.key, | ||
280 | info.authentication, info.encryption, info.mac = | ||
281 | string.match(str, | ||
282 | "^(%S+)%s+(%S+)%s+Kx=(%S+)%s+Au=(%S+)%s+Enc=(%S+)%s+Mac=(%S+)") | ||
283 | info.export = (string.match(str, "%sexport%s*$") ~= nil) | ||
284 | end | ||
285 | if protocol then | ||
286 | info.protocol = protocol | ||
287 | end | ||
288 | if field then | ||
289 | return info[field] | ||
290 | end | ||
291 | -- Empty? | ||
292 | return ( (next(info)) and info ) | ||
293 | end | ||
294 | |||
295 | -- | ||
296 | -- Set method for SSL connections. | ||
297 | -- | ||
298 | core.setmethod("info", info) | ||
299 | |||
300 | -------------------------------------------------------------------------------- | ||
301 | -- Export module | ||
302 | -- | ||
303 | |||
304 | local _M = { | ||
305 | _VERSION = "1.3.2", | ||
306 | _COPYRIGHT = core.copyright(), | ||
307 | config = config, | ||
308 | loadcertificate = x509.load, | ||
309 | newcontext = newcontext, | ||
310 | wrap = wrap, | ||
311 | } | ||
312 | |||
313 | return _M | ||
diff --git a/vendor/luasec/src/x509.c b/vendor/luasec/src/x509.c new file mode 100644 index 00000000..6833d46f --- /dev/null +++ b/vendor/luasec/src/x509.c | |||
@@ -0,0 +1,750 @@ | |||
1 | /*-------------------------------------------------------------------------- | ||
2 | * LuaSec 1.3.2 | ||
3 | * | ||
4 | * Copyright (C) 2014-2023 Kim Alvefur, Paul Aurich, Tobias Markmann, Matthew Wild | ||
5 | * Copyright (C) 2014-2023 Bruno Silvestre | ||
6 | * | ||
7 | *--------------------------------------------------------------------------*/ | ||
8 | |||
9 | #include <stdio.h> | ||
10 | #include <string.h> | ||
11 | |||
12 | #if defined(WIN32) | ||
13 | #include <ws2tcpip.h> | ||
14 | #include <windows.h> | ||
15 | #else | ||
16 | #include <sys/types.h> | ||
17 | #include <sys/socket.h> | ||
18 | #include <netinet/in.h> | ||
19 | #include <arpa/inet.h> | ||
20 | #endif | ||
21 | |||
22 | #include <openssl/ssl.h> | ||
23 | #include <openssl/x509v3.h> | ||
24 | #include <openssl/evp.h> | ||
25 | #include <openssl/err.h> | ||
26 | #include <openssl/asn1.h> | ||
27 | #include <openssl/bio.h> | ||
28 | #include <openssl/bn.h> | ||
29 | |||
30 | #include <lua.h> | ||
31 | #include <lauxlib.h> | ||
32 | |||
33 | #include "x509.h" | ||
34 | |||
35 | |||
36 | #ifndef LSEC_API_OPENSSL_1_1_0 | ||
37 | #define X509_get0_notBefore X509_get_notBefore | ||
38 | #define X509_get0_notAfter X509_get_notAfter | ||
39 | #define ASN1_STRING_get0_data ASN1_STRING_data | ||
40 | #endif | ||
41 | |||
42 | static const char* hex_tab = "0123456789abcdef"; | ||
43 | |||
44 | /** | ||
45 | * Push the certificate on the stack. | ||
46 | */ | ||
47 | void lsec_pushx509(lua_State* L, X509 *cert) | ||
48 | { | ||
49 | p_x509 cert_obj = (p_x509)lua_newuserdata(L, sizeof(t_x509)); | ||
50 | cert_obj->cert = cert; | ||
51 | cert_obj->encode = LSEC_AI5_STRING; | ||
52 | luaL_getmetatable(L, "SSL:Certificate"); | ||
53 | lua_setmetatable(L, -2); | ||
54 | } | ||
55 | |||
56 | /** | ||
57 | * Return the OpenSSL certificate X509. | ||
58 | */ | ||
59 | X509* lsec_checkx509(lua_State* L, int idx) | ||
60 | { | ||
61 | return ((p_x509)luaL_checkudata(L, idx, "SSL:Certificate"))->cert; | ||
62 | } | ||
63 | |||
64 | /** | ||
65 | * Return LuaSec certificate X509 representation. | ||
66 | */ | ||
67 | p_x509 lsec_checkp_x509(lua_State* L, int idx) | ||
68 | { | ||
69 | return (p_x509)luaL_checkudata(L, idx, "SSL:Certificate"); | ||
70 | } | ||
71 | |||
72 | /*---------------------------------------------------------------------------*/ | ||
73 | |||
74 | #if defined(LUASEC_INET_NTOP) | ||
75 | /* | ||
76 | * For WinXP (SP3), set the following preprocessor macros: | ||
77 | * LUASEC_INET_NTOP | ||
78 | * WINVER=0x0501 | ||
79 | * _WIN32_WINNT=0x0501 | ||
80 | * NTDDI_VERSION=0x05010300 | ||
81 | * | ||
82 | * For IPv6 addresses, you need to add IPv6 Protocol to your interface. | ||
83 | * | ||
84 | */ | ||
85 | static const char *inet_ntop(int af, const char *src, char *dst, socklen_t size) | ||
86 | { | ||
87 | int addrsize; | ||
88 | struct sockaddr *addr; | ||
89 | struct sockaddr_in addr4; | ||
90 | struct sockaddr_in6 addr6; | ||
91 | |||
92 | switch (af) { | ||
93 | case AF_INET: | ||
94 | memset((void*)&addr4, 0, sizeof(addr4)); | ||
95 | addr4.sin_family = AF_INET; | ||
96 | memcpy((void*)&addr4.sin_addr, src, sizeof(struct in_addr)); | ||
97 | addr = (struct sockaddr*)&addr4; | ||
98 | addrsize = sizeof(struct sockaddr_in); | ||
99 | break; | ||
100 | case AF_INET6: | ||
101 | memset((void*)&addr6, 0, sizeof(addr6)); | ||
102 | addr6.sin6_family = AF_INET6; | ||
103 | memcpy((void*)&addr6.sin6_addr, src, sizeof(struct in6_addr)); | ||
104 | addr = (struct sockaddr*)&addr6; | ||
105 | addrsize = sizeof(struct sockaddr_in6); | ||
106 | break; | ||
107 | default: | ||
108 | return NULL; | ||
109 | } | ||
110 | |||
111 | if(getnameinfo(addr, addrsize, dst, size, NULL, 0, NI_NUMERICHOST) != 0) | ||
112 | return NULL; | ||
113 | return dst; | ||
114 | } | ||
115 | #endif | ||
116 | |||
117 | /*---------------------------------------------------------------------------*/ | ||
118 | |||
119 | /** | ||
120 | * Convert the buffer 'in' to hexadecimal. | ||
121 | */ | ||
122 | static void to_hex(const char* in, int length, char* out) | ||
123 | { | ||
124 | int i; | ||
125 | for (i = 0; i < length; i++) { | ||
126 | out[i*2] = hex_tab[(in[i] >> 4) & 0xF]; | ||
127 | out[i*2+1] = hex_tab[(in[i]) & 0xF]; | ||
128 | } | ||
129 | } | ||
130 | |||
131 | /** | ||
132 | * Converts the ASN1_OBJECT into a textual representation and put it | ||
133 | * on the Lua stack. | ||
134 | */ | ||
135 | static void push_asn1_objname(lua_State* L, ASN1_OBJECT *object, int no_name) | ||
136 | { | ||
137 | char buffer[256]; | ||
138 | int len = OBJ_obj2txt(buffer, sizeof(buffer), object, no_name); | ||
139 | len = (len < sizeof(buffer)) ? len : sizeof(buffer); | ||
140 | lua_pushlstring(L, buffer, len); | ||
141 | } | ||
142 | |||
143 | /** | ||
144 | * Push the ASN1 string on the stack. | ||
145 | */ | ||
146 | static void push_asn1_string(lua_State* L, ASN1_STRING *string, int encode) | ||
147 | { | ||
148 | int len; | ||
149 | unsigned char *data; | ||
150 | if (!string) { | ||
151 | lua_pushnil(L); | ||
152 | return; | ||
153 | } | ||
154 | switch (encode) { | ||
155 | case LSEC_AI5_STRING: | ||
156 | lua_pushlstring(L, (char*)ASN1_STRING_get0_data(string), ASN1_STRING_length(string)); | ||
157 | break; | ||
158 | case LSEC_UTF8_STRING: | ||
159 | len = ASN1_STRING_to_UTF8(&data, string); | ||
160 | if (len >= 0) { | ||
161 | lua_pushlstring(L, (char*)data, len); | ||
162 | OPENSSL_free(data); | ||
163 | } | ||
164 | else | ||
165 | lua_pushnil(L); | ||
166 | } | ||
167 | } | ||
168 | |||
169 | /** | ||
170 | * Return a human readable time. | ||
171 | */ | ||
172 | static int push_asn1_time(lua_State *L, const ASN1_UTCTIME *tm) | ||
173 | { | ||
174 | char *tmp; | ||
175 | long size; | ||
176 | BIO *out = BIO_new(BIO_s_mem()); | ||
177 | ASN1_TIME_print(out, tm); | ||
178 | size = BIO_get_mem_data(out, &tmp); | ||
179 | lua_pushlstring(L, tmp, size); | ||
180 | BIO_free(out); | ||
181 | return 1; | ||
182 | } | ||
183 | |||
184 | /** | ||
185 | * Return a human readable IP address. | ||
186 | */ | ||
187 | static void push_asn1_ip(lua_State *L, ASN1_STRING *string) | ||
188 | { | ||
189 | int af; | ||
190 | char dst[INET6_ADDRSTRLEN]; | ||
191 | unsigned char *ip = (unsigned char*)ASN1_STRING_get0_data(string); | ||
192 | switch(ASN1_STRING_length(string)) { | ||
193 | case 4: | ||
194 | af = AF_INET; | ||
195 | break; | ||
196 | case 16: | ||
197 | af = AF_INET6; | ||
198 | break; | ||
199 | default: | ||
200 | lua_pushnil(L); | ||
201 | return; | ||
202 | } | ||
203 | if(inet_ntop(af, ip, dst, INET6_ADDRSTRLEN)) | ||
204 | lua_pushstring(L, dst); | ||
205 | else | ||
206 | lua_pushnil(L); | ||
207 | } | ||
208 | |||
209 | /** | ||
210 | * | ||
211 | */ | ||
212 | static int push_subtable(lua_State* L, int idx) | ||
213 | { | ||
214 | lua_pushvalue(L, -1); | ||
215 | lua_gettable(L, idx-1); | ||
216 | if (lua_isnil(L, -1)) { | ||
217 | lua_pop(L, 1); | ||
218 | lua_newtable(L); | ||
219 | lua_pushvalue(L, -2); | ||
220 | lua_pushvalue(L, -2); | ||
221 | lua_settable(L, idx-3); | ||
222 | lua_replace(L, -2); /* Replace key with table */ | ||
223 | return 1; | ||
224 | } | ||
225 | lua_replace(L, -2); /* Replace key with table */ | ||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | /** | ||
230 | * Retrieve the general names from the object. | ||
231 | */ | ||
232 | static int push_x509_name(lua_State* L, X509_NAME *name, int encode) | ||
233 | { | ||
234 | int i; | ||
235 | int n_entries; | ||
236 | ASN1_OBJECT *object; | ||
237 | X509_NAME_ENTRY *entry; | ||
238 | lua_newtable(L); | ||
239 | n_entries = X509_NAME_entry_count(name); | ||
240 | for (i = 0; i < n_entries; i++) { | ||
241 | entry = X509_NAME_get_entry(name, i); | ||
242 | object = X509_NAME_ENTRY_get_object(entry); | ||
243 | lua_newtable(L); | ||
244 | push_asn1_objname(L, object, 1); | ||
245 | lua_setfield(L, -2, "oid"); | ||
246 | push_asn1_objname(L, object, 0); | ||
247 | lua_setfield(L, -2, "name"); | ||
248 | push_asn1_string(L, X509_NAME_ENTRY_get_data(entry), encode); | ||
249 | lua_setfield(L, -2, "value"); | ||
250 | lua_rawseti(L, -2, i+1); | ||
251 | } | ||
252 | return 1; | ||
253 | } | ||
254 | |||
255 | /*---------------------------------------------------------------------------*/ | ||
256 | |||
257 | /** | ||
258 | * Retrieve the Subject from the certificate. | ||
259 | */ | ||
260 | static int meth_subject(lua_State* L) | ||
261 | { | ||
262 | p_x509 px = lsec_checkp_x509(L, 1); | ||
263 | return push_x509_name(L, X509_get_subject_name(px->cert), px->encode); | ||
264 | } | ||
265 | |||
266 | /** | ||
267 | * Retrieve the Issuer from the certificate. | ||
268 | */ | ||
269 | static int meth_issuer(lua_State* L) | ||
270 | { | ||
271 | p_x509 px = lsec_checkp_x509(L, 1); | ||
272 | return push_x509_name(L, X509_get_issuer_name(px->cert), px->encode); | ||
273 | } | ||
274 | |||
275 | /** | ||
276 | * Retrieve the extensions from the certificate. | ||
277 | */ | ||
278 | int meth_extensions(lua_State* L) | ||
279 | { | ||
280 | int j; | ||
281 | int i = -1; | ||
282 | int n_general_names; | ||
283 | OTHERNAME *otherName; | ||
284 | X509_EXTENSION *extension; | ||
285 | GENERAL_NAME *general_name; | ||
286 | STACK_OF(GENERAL_NAME) *values; | ||
287 | p_x509 px = lsec_checkp_x509(L, 1); | ||
288 | X509 *peer = px->cert; | ||
289 | |||
290 | /* Return (ret) */ | ||
291 | lua_newtable(L); | ||
292 | |||
293 | while ((i = X509_get_ext_by_NID(peer, NID_subject_alt_name, i)) != -1) { | ||
294 | extension = X509_get_ext(peer, i); | ||
295 | if (extension == NULL) | ||
296 | break; | ||
297 | values = X509V3_EXT_d2i(extension); | ||
298 | if (values == NULL) | ||
299 | break; | ||
300 | |||
301 | /* Push ret[oid] */ | ||
302 | push_asn1_objname(L, X509_EXTENSION_get_object(extension), 1); | ||
303 | push_subtable(L, -2); | ||
304 | |||
305 | /* Set ret[oid].name = name */ | ||
306 | push_asn1_objname(L, X509_EXTENSION_get_object(extension), 0); | ||
307 | lua_setfield(L, -2, "name"); | ||
308 | |||
309 | n_general_names = sk_GENERAL_NAME_num(values); | ||
310 | for (j = 0; j < n_general_names; j++) { | ||
311 | general_name = sk_GENERAL_NAME_value(values, j); | ||
312 | switch (general_name->type) { | ||
313 | case GEN_OTHERNAME: | ||
314 | otherName = general_name->d.otherName; | ||
315 | push_asn1_objname(L, otherName->type_id, 1); | ||
316 | if (push_subtable(L, -2)) { | ||
317 | push_asn1_objname(L, otherName->type_id, 0); | ||
318 | lua_setfield(L, -2, "name"); | ||
319 | } | ||
320 | push_asn1_string(L, otherName->value->value.asn1_string, px->encode); | ||
321 | lua_rawseti(L, -2, lua_rawlen(L, -2) + 1); | ||
322 | lua_pop(L, 1); | ||
323 | break; | ||
324 | case GEN_DNS: | ||
325 | lua_pushstring(L, "dNSName"); | ||
326 | push_subtable(L, -2); | ||
327 | push_asn1_string(L, general_name->d.dNSName, px->encode); | ||
328 | lua_rawseti(L, -2, lua_rawlen(L, -2) + 1); | ||
329 | lua_pop(L, 1); | ||
330 | break; | ||
331 | case GEN_EMAIL: | ||
332 | lua_pushstring(L, "rfc822Name"); | ||
333 | push_subtable(L, -2); | ||
334 | push_asn1_string(L, general_name->d.rfc822Name, px->encode); | ||
335 | lua_rawseti(L, -2, lua_rawlen(L, -2) + 1); | ||
336 | lua_pop(L, 1); | ||
337 | break; | ||
338 | case GEN_URI: | ||
339 | lua_pushstring(L, "uniformResourceIdentifier"); | ||
340 | push_subtable(L, -2); | ||
341 | push_asn1_string(L, general_name->d.uniformResourceIdentifier, px->encode); | ||
342 | lua_rawseti(L, -2, lua_rawlen(L, -2)+1); | ||
343 | lua_pop(L, 1); | ||
344 | break; | ||
345 | case GEN_IPADD: | ||
346 | lua_pushstring(L, "iPAddress"); | ||
347 | push_subtable(L, -2); | ||
348 | push_asn1_ip(L, general_name->d.iPAddress); | ||
349 | lua_rawseti(L, -2, lua_rawlen(L, -2)+1); | ||
350 | lua_pop(L, 1); | ||
351 | break; | ||
352 | case GEN_X400: | ||
353 | /* x400Address */ | ||
354 | /* not supported */ | ||
355 | break; | ||
356 | case GEN_DIRNAME: | ||
357 | /* directoryName */ | ||
358 | /* not supported */ | ||
359 | break; | ||
360 | case GEN_EDIPARTY: | ||
361 | /* ediPartyName */ | ||
362 | /* not supported */ | ||
363 | break; | ||
364 | case GEN_RID: | ||
365 | /* registeredID */ | ||
366 | /* not supported */ | ||
367 | break; | ||
368 | } | ||
369 | GENERAL_NAME_free(general_name); | ||
370 | } | ||
371 | sk_GENERAL_NAME_free(values); | ||
372 | lua_pop(L, 1); /* ret[oid] */ | ||
373 | i++; /* Next extension */ | ||
374 | } | ||
375 | return 1; | ||
376 | } | ||
377 | |||
378 | /** | ||
379 | * Convert the certificate to PEM format. | ||
380 | */ | ||
381 | static int meth_pem(lua_State* L) | ||
382 | { | ||
383 | char* data; | ||
384 | long bytes; | ||
385 | X509* cert = lsec_checkx509(L, 1); | ||
386 | BIO *bio = BIO_new(BIO_s_mem()); | ||
387 | if (!PEM_write_bio_X509(bio, cert)) { | ||
388 | lua_pushnil(L); | ||
389 | return 1; | ||
390 | } | ||
391 | bytes = BIO_get_mem_data(bio, &data); | ||
392 | if (bytes > 0) | ||
393 | lua_pushlstring(L, data, bytes); | ||
394 | else | ||
395 | lua_pushnil(L); | ||
396 | BIO_free(bio); | ||
397 | return 1; | ||
398 | } | ||
399 | |||
400 | /** | ||
401 | * Extract public key in PEM format. | ||
402 | */ | ||
403 | static int meth_pubkey(lua_State* L) | ||
404 | { | ||
405 | char* data; | ||
406 | long bytes; | ||
407 | int ret = 1; | ||
408 | X509* cert = lsec_checkx509(L, 1); | ||
409 | BIO *bio = BIO_new(BIO_s_mem()); | ||
410 | EVP_PKEY *pkey = X509_get_pubkey(cert); | ||
411 | if(PEM_write_bio_PUBKEY(bio, pkey)) { | ||
412 | bytes = BIO_get_mem_data(bio, &data); | ||
413 | if (bytes > 0) { | ||
414 | lua_pushlstring(L, data, bytes); | ||
415 | switch(EVP_PKEY_base_id(pkey)) { | ||
416 | case EVP_PKEY_RSA: | ||
417 | lua_pushstring(L, "RSA"); | ||
418 | break; | ||
419 | case EVP_PKEY_DSA: | ||
420 | lua_pushstring(L, "DSA"); | ||
421 | break; | ||
422 | case EVP_PKEY_DH: | ||
423 | lua_pushstring(L, "DH"); | ||
424 | break; | ||
425 | case EVP_PKEY_EC: | ||
426 | lua_pushstring(L, "EC"); | ||
427 | break; | ||
428 | default: | ||
429 | lua_pushstring(L, "Unknown"); | ||
430 | break; | ||
431 | } | ||
432 | lua_pushinteger(L, EVP_PKEY_bits(pkey)); | ||
433 | ret = 3; | ||
434 | } | ||
435 | else | ||
436 | lua_pushnil(L); | ||
437 | } | ||
438 | else | ||
439 | lua_pushnil(L); | ||
440 | /* Cleanup */ | ||
441 | BIO_free(bio); | ||
442 | EVP_PKEY_free(pkey); | ||
443 | return ret; | ||
444 | } | ||
445 | |||
446 | /** | ||
447 | * Compute the fingerprint. | ||
448 | */ | ||
449 | static int meth_digest(lua_State* L) | ||
450 | { | ||
451 | unsigned int bytes; | ||
452 | const EVP_MD *digest = NULL; | ||
453 | unsigned char buffer[EVP_MAX_MD_SIZE]; | ||
454 | char hex_buffer[EVP_MAX_MD_SIZE*2]; | ||
455 | X509 *cert = lsec_checkx509(L, 1); | ||
456 | const char *str = luaL_optstring(L, 2, NULL); | ||
457 | if (!str) | ||
458 | digest = EVP_sha1(); | ||
459 | else { | ||
460 | if (!strcmp(str, "sha1")) | ||
461 | digest = EVP_sha1(); | ||
462 | else if (!strcmp(str, "sha256")) | ||
463 | digest = EVP_sha256(); | ||
464 | else if (!strcmp(str, "sha512")) | ||
465 | digest = EVP_sha512(); | ||
466 | } | ||
467 | if (!digest) { | ||
468 | lua_pushnil(L); | ||
469 | lua_pushfstring(L, "digest algorithm not supported (%s)", str); | ||
470 | return 2; | ||
471 | } | ||
472 | if (!X509_digest(cert, digest, buffer, &bytes)) { | ||
473 | lua_pushnil(L); | ||
474 | lua_pushfstring(L, "error processing the certificate (%s)", | ||
475 | ERR_reason_error_string(ERR_get_error())); | ||
476 | return 2; | ||
477 | } | ||
478 | to_hex((char*)buffer, bytes, hex_buffer); | ||
479 | lua_pushlstring(L, hex_buffer, bytes*2); | ||
480 | return 1; | ||
481 | } | ||
482 | |||
483 | /** | ||
484 | * Check if the certificate is valid in a given time. | ||
485 | */ | ||
486 | static int meth_valid_at(lua_State* L) | ||
487 | { | ||
488 | int nb, na; | ||
489 | X509* cert = lsec_checkx509(L, 1); | ||
490 | time_t time = luaL_checkinteger(L, 2); | ||
491 | nb = X509_cmp_time(X509_get0_notBefore(cert), &time); | ||
492 | time -= 1; | ||
493 | na = X509_cmp_time(X509_get0_notAfter(cert), &time); | ||
494 | lua_pushboolean(L, nb == -1 && na == 1); | ||
495 | return 1; | ||
496 | } | ||
497 | |||
498 | /** | ||
499 | * Return the serial number. | ||
500 | */ | ||
501 | static int meth_serial(lua_State *L) | ||
502 | { | ||
503 | char *tmp; | ||
504 | BIGNUM *bn; | ||
505 | ASN1_INTEGER *serial; | ||
506 | X509* cert = lsec_checkx509(L, 1); | ||
507 | serial = X509_get_serialNumber(cert); | ||
508 | bn = ASN1_INTEGER_to_BN(serial, NULL); | ||
509 | tmp = BN_bn2hex(bn); | ||
510 | lua_pushstring(L, tmp); | ||
511 | BN_free(bn); | ||
512 | OPENSSL_free(tmp); | ||
513 | return 1; | ||
514 | } | ||
515 | |||
516 | /** | ||
517 | * Return not before date. | ||
518 | */ | ||
519 | static int meth_notbefore(lua_State *L) | ||
520 | { | ||
521 | X509* cert = lsec_checkx509(L, 1); | ||
522 | return push_asn1_time(L, X509_get0_notBefore(cert)); | ||
523 | } | ||
524 | |||
525 | /** | ||
526 | * Return not after date. | ||
527 | */ | ||
528 | static int meth_notafter(lua_State *L) | ||
529 | { | ||
530 | X509* cert = lsec_checkx509(L, 1); | ||
531 | return push_asn1_time(L, X509_get0_notAfter(cert)); | ||
532 | } | ||
533 | |||
534 | /** | ||
535 | * Check if this certificate issued some other certificate | ||
536 | */ | ||
537 | static int meth_issued(lua_State* L) | ||
538 | { | ||
539 | int ret, i, len; | ||
540 | |||
541 | X509_STORE_CTX* ctx = NULL; | ||
542 | X509_STORE* root = NULL; | ||
543 | STACK_OF(X509)* chain = NULL; | ||
544 | |||
545 | X509* issuer = lsec_checkx509(L, 1); | ||
546 | X509* subject = lsec_checkx509(L, 2); | ||
547 | X509* cert = NULL; | ||
548 | |||
549 | len = lua_gettop(L); | ||
550 | |||
551 | /* Check that all arguments are certificates */ | ||
552 | |||
553 | for (i = 3; i <= len; i++) { | ||
554 | lsec_checkx509(L, i); | ||
555 | } | ||
556 | |||
557 | /* Before allocating things that require freeing afterwards */ | ||
558 | |||
559 | chain = sk_X509_new_null(); | ||
560 | ctx = X509_STORE_CTX_new(); | ||
561 | root = X509_STORE_new(); | ||
562 | |||
563 | if (ctx == NULL || root == NULL) { | ||
564 | lua_pushnil(L); | ||
565 | lua_pushstring(L, "X509_STORE_new() or X509_STORE_CTX_new() error"); | ||
566 | ret = 2; | ||
567 | goto cleanup; | ||
568 | } | ||
569 | |||
570 | ret = X509_STORE_add_cert(root, issuer); | ||
571 | |||
572 | if(!ret) { | ||
573 | lua_pushnil(L); | ||
574 | lua_pushstring(L, "X509_STORE_add_cert() error"); | ||
575 | ret = 2; | ||
576 | goto cleanup; | ||
577 | } | ||
578 | |||
579 | for (i = 3; i <= len && lua_isuserdata(L, i); i++) { | ||
580 | cert = lsec_checkx509(L, i); | ||
581 | sk_X509_push(chain, cert); | ||
582 | } | ||
583 | |||
584 | ret = X509_STORE_CTX_init(ctx, root, subject, chain); | ||
585 | |||
586 | if(!ret) { | ||
587 | lua_pushnil(L); | ||
588 | lua_pushstring(L, "X509_STORE_CTX_init() error"); | ||
589 | ret = 2; | ||
590 | goto cleanup; | ||
591 | } | ||
592 | |||
593 | /* Actual verification */ | ||
594 | if (X509_verify_cert(ctx) <= 0) { | ||
595 | ret = X509_STORE_CTX_get_error(ctx); | ||
596 | lua_pushnil(L); | ||
597 | lua_pushstring(L, X509_verify_cert_error_string(ret)); | ||
598 | ret = 2; | ||
599 | } else { | ||
600 | lua_pushboolean(L, 1); | ||
601 | ret = 1; | ||
602 | } | ||
603 | |||
604 | cleanup: | ||
605 | |||
606 | if (ctx != NULL) { | ||
607 | X509_STORE_CTX_free(ctx); | ||
608 | } | ||
609 | |||
610 | if (chain != NULL) { | ||
611 | X509_STORE_free(root); | ||
612 | } | ||
613 | |||
614 | sk_X509_free(chain); | ||
615 | |||
616 | return ret; | ||
617 | } | ||
618 | |||
619 | /** | ||
620 | * Collect X509 objects. | ||
621 | */ | ||
622 | static int meth_destroy(lua_State* L) | ||
623 | { | ||
624 | p_x509 px = lsec_checkp_x509(L, 1); | ||
625 | if (px->cert) { | ||
626 | X509_free(px->cert); | ||
627 | px->cert = NULL; | ||
628 | } | ||
629 | return 0; | ||
630 | } | ||
631 | |||
632 | static int meth_tostring(lua_State *L) | ||
633 | { | ||
634 | X509* cert = lsec_checkx509(L, 1); | ||
635 | lua_pushfstring(L, "X509 certificate: %p", cert); | ||
636 | return 1; | ||
637 | } | ||
638 | |||
639 | /** | ||
640 | * Set the encode for ASN.1 string. | ||
641 | */ | ||
642 | static int meth_set_encode(lua_State* L) | ||
643 | { | ||
644 | int succ = 0; | ||
645 | p_x509 px = lsec_checkp_x509(L, 1); | ||
646 | const char *enc = luaL_checkstring(L, 2); | ||
647 | if (strncmp(enc, "ai5", 3) == 0) { | ||
648 | succ = 1; | ||
649 | px->encode = LSEC_AI5_STRING; | ||
650 | } else if (strncmp(enc, "utf8", 4) == 0) { | ||
651 | succ = 1; | ||
652 | px->encode = LSEC_UTF8_STRING; | ||
653 | } | ||
654 | lua_pushboolean(L, succ); | ||
655 | return 1; | ||
656 | } | ||
657 | |||
658 | #if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) | ||
659 | /** | ||
660 | * Get signature name. | ||
661 | */ | ||
662 | static int meth_get_signature_name(lua_State* L) | ||
663 | { | ||
664 | p_x509 px = lsec_checkp_x509(L, 1); | ||
665 | int nid = X509_get_signature_nid(px->cert); | ||
666 | const char *name = OBJ_nid2sn(nid); | ||
667 | if (!name) | ||
668 | lua_pushnil(L); | ||
669 | else | ||
670 | lua_pushstring(L, name); | ||
671 | return 1; | ||
672 | } | ||
673 | #endif | ||
674 | |||
675 | /*---------------------------------------------------------------------------*/ | ||
676 | |||
677 | static int load_cert(lua_State* L) | ||
678 | { | ||
679 | X509 *cert; | ||
680 | size_t bytes; | ||
681 | const char* data; | ||
682 | BIO *bio = BIO_new(BIO_s_mem()); | ||
683 | data = luaL_checklstring(L, 1, &bytes); | ||
684 | BIO_write(bio, data, bytes); | ||
685 | cert = PEM_read_bio_X509(bio, NULL, NULL, NULL); | ||
686 | if (cert) | ||
687 | lsec_pushx509(L, cert); | ||
688 | else | ||
689 | lua_pushnil(L); | ||
690 | BIO_free(bio); | ||
691 | return 1; | ||
692 | } | ||
693 | |||
694 | /*---------------------------------------------------------------------------*/ | ||
695 | |||
696 | /** | ||
697 | * Certificate methods. | ||
698 | */ | ||
699 | static luaL_Reg methods[] = { | ||
700 | {"digest", meth_digest}, | ||
701 | {"setencode", meth_set_encode}, | ||
702 | {"extensions", meth_extensions}, | ||
703 | #if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) | ||
704 | {"getsignaturename", meth_get_signature_name}, | ||
705 | #endif | ||
706 | {"issuer", meth_issuer}, | ||
707 | {"notbefore", meth_notbefore}, | ||
708 | {"notafter", meth_notafter}, | ||
709 | {"issued", meth_issued}, | ||
710 | {"pem", meth_pem}, | ||
711 | {"pubkey", meth_pubkey}, | ||
712 | {"serial", meth_serial}, | ||
713 | {"subject", meth_subject}, | ||
714 | {"validat", meth_valid_at}, | ||
715 | {NULL, NULL} | ||
716 | }; | ||
717 | |||
718 | /** | ||
719 | * X509 metamethods. | ||
720 | */ | ||
721 | static luaL_Reg meta[] = { | ||
722 | {"__close", meth_destroy}, | ||
723 | {"__gc", meth_destroy}, | ||
724 | {"__tostring", meth_tostring}, | ||
725 | {NULL, NULL} | ||
726 | }; | ||
727 | |||
728 | /** | ||
729 | * X509 functions. | ||
730 | */ | ||
731 | static luaL_Reg funcs[] = { | ||
732 | {"load", load_cert}, | ||
733 | {NULL, NULL} | ||
734 | }; | ||
735 | |||
736 | /*--------------------------------------------------------------------------*/ | ||
737 | |||
738 | LSEC_API int luaopen_ssl_x509(lua_State *L) | ||
739 | { | ||
740 | /* Register the functions and tables */ | ||
741 | luaL_newmetatable(L, "SSL:Certificate"); | ||
742 | setfuncs(L, meta); | ||
743 | |||
744 | luaL_newlib(L, methods); | ||
745 | lua_setfield(L, -2, "__index"); | ||
746 | |||
747 | luaL_newlib(L, funcs); | ||
748 | |||
749 | return 1; | ||
750 | } | ||
diff --git a/vendor/luasec/src/x509.h b/vendor/luasec/src/x509.h new file mode 100644 index 00000000..acdbe6c0 --- /dev/null +++ b/vendor/luasec/src/x509.h | |||
@@ -0,0 +1,31 @@ | |||
1 | /*-------------------------------------------------------------------------- | ||
2 | * LuaSec 1.3.2 | ||
3 | * | ||
4 | * Copyright (C) 2014-2023 Kim Alvefur, Paul Aurich, Tobias Markmann, Matthew Wild | ||
5 | * Copyright (C) 2013-2023 Bruno Silvestre | ||
6 | * | ||
7 | *--------------------------------------------------------------------------*/ | ||
8 | |||
9 | #ifndef LSEC_X509_H | ||
10 | #define LSEC_X509_H | ||
11 | |||
12 | #include <openssl/x509v3.h> | ||
13 | #include <lua.h> | ||
14 | |||
15 | #include "compat.h" | ||
16 | |||
17 | /* We do not support UniversalString nor BMPString as ASN.1 String types */ | ||
18 | enum { LSEC_AI5_STRING, LSEC_UTF8_STRING }; | ||
19 | |||
20 | typedef struct t_x509_ { | ||
21 | X509 *cert; | ||
22 | int encode; | ||
23 | } t_x509; | ||
24 | typedef t_x509* p_x509; | ||
25 | |||
26 | void lsec_pushx509(lua_State* L, X509* cert); | ||
27 | X509* lsec_checkx509(lua_State* L, int idx); | ||
28 | |||
29 | LSEC_API int luaopen_ssl_x509(lua_State *L); | ||
30 | |||
31 | #endif | ||
diff --git a/vendor/luasocket/.editorconfig b/vendor/luasocket/.editorconfig new file mode 100644 index 00000000..56ad87df --- /dev/null +++ b/vendor/luasocket/.editorconfig | |||
@@ -0,0 +1,23 @@ | |||
1 | root = true | ||
2 | |||
3 | [*] | ||
4 | end_of_line = lf | ||
5 | insert_final_newline = true | ||
6 | trim_trailing_whitespace = true | ||
7 | charset = utf-8 | ||
8 | |||
9 | [{*.lua,*.rockspec,.luacheckrc}] | ||
10 | indent_style = space | ||
11 | indent_size = 4 | ||
12 | |||
13 | [Makefile] | ||
14 | indent_style = tab | ||
15 | indent_size = 4 | ||
16 | |||
17 | [*.html] | ||
18 | indent_style = space | ||
19 | indent_size = 4 | ||
20 | |||
21 | [*.{c,h}] | ||
22 | indent_style = space | ||
23 | indent_size = 4 | ||
diff --git a/vendor/luasocket/.gitignore b/vendor/luasocket/.gitignore new file mode 100644 index 00000000..9ed661cf --- /dev/null +++ b/vendor/luasocket/.gitignore | |||
@@ -0,0 +1,15 @@ | |||
1 | *.o | ||
2 | *.so | ||
3 | *.so.* | ||
4 | *.obj | ||
5 | *.lib | ||
6 | *.dll* | ||
7 | *.user | ||
8 | *.sdf | ||
9 | Debug | ||
10 | Release | ||
11 | *.manifest | ||
12 | *.swp | ||
13 | *.suo | ||
14 | x64 | ||
15 | |||
diff --git a/vendor/luasocket/.luacheckrc b/vendor/luasocket/.luacheckrc new file mode 100644 index 00000000..8b25dd7a --- /dev/null +++ b/vendor/luasocket/.luacheckrc | |||
@@ -0,0 +1,31 @@ | |||
1 | unused_args = false | ||
2 | redefined = false | ||
3 | max_line_length = false | ||
4 | |||
5 | not_globals = { | ||
6 | "string.len", | ||
7 | "table.getn", | ||
8 | } | ||
9 | |||
10 | include_files = { | ||
11 | "**/*.lua", | ||
12 | "**/*.rockspec", | ||
13 | ".busted", | ||
14 | ".luacheckrc", | ||
15 | } | ||
16 | |||
17 | exclude_files = { | ||
18 | "etc/*.lua", | ||
19 | "etc/**/*.lua", | ||
20 | "test/*.lua", | ||
21 | "test/**/*.lua", | ||
22 | "samples/*.lua", | ||
23 | "samples/**/*.lua", | ||
24 | "gem/*.lua", | ||
25 | "gem/**/*.lua", | ||
26 | -- GH Actions Lua Environment | ||
27 | ".lua", | ||
28 | ".luarocks", | ||
29 | ".install", | ||
30 | } | ||
31 | |||
diff --git a/vendor/luasocket/CHANGELOG.md b/vendor/luasocket/CHANGELOG.md new file mode 100644 index 00000000..3a25186b --- /dev/null +++ b/vendor/luasocket/CHANGELOG.md | |||
@@ -0,0 +1,65 @@ | |||
1 | # Changelog | ||
2 | |||
3 | ## [v3.1.0](https://github.com/lunarmodules/luasocket/releases/v3.1.0) — 2022-07-27 | ||
4 | |||
5 | * Add support for TCP Defer Accept – @Zash | ||
6 | * Add support for TCP Fast Open – @Zash | ||
7 | * Fix Windows (mingw32) builds – @goldenstein64 | ||
8 | * Avoid build warnings on 64-bit Windows – @rpatters1 | ||
9 | |||
10 | ## [v3.0.0](https://github.com/lunarmodules/luasocket/releases/v3.0.0) — 2022-03-25 | ||
11 | |||
12 | The last time LuaSocket had a stable release tag was 14 years ago when 2.0.2 was tagged. | ||
13 | A v3 release candidate was tagged 9 years ago. | ||
14 | Since then it has been downloaded over 3 million times. | ||
15 | Additionally the Git repository regularly gets several hundred clones a day. | ||
16 | But 9 years is a long time and even the release candidate has grown a bit long in the tooth. | ||
17 | Many Linux distros have packaged the current Git HEAD or some specific tested point as dated or otherwise labeled releases. | ||
18 | 256 commits later and having been migrated to the @lunarmodules org namespace on GitHub, please welcome v3. | ||
19 | |||
20 | This release is a "safe-harbor" tag that represents a minimal amount of changes to get a release tagged. | ||
21 | Beyond some CI tooling, very little code has changed since migration to @lunarmodules ([5b18e47..e47d98f](https://github.com/lunarmodules/luasocket/compare/5b18e47..e47d98f?w=1)): | ||
22 | |||
23 | * Lua 5.4.3+ support – @pkulchenko, @Zash | ||
24 | * Cleanup minor issues to get a code linter to pass – @Tieske, @jyoui, @alerque | ||
25 | * Update Visual Studio build rules for Lua 5.1 – @ewestbrook | ||
26 | * Set http transfer-encoding even without content-length – @tokenrove | ||
27 | |||
28 | Prior to migration to @lunarmodules ([v3.0-rc1..5b18e47](https://github.com/lunarmodules/luasocket/compare/v3.0-rc1..5b18e47?w=1)) many things happened of which the author of this changelog is not fully apprised. | ||
29 | Your best bet if it affects your project somehow is to read the commit log & diffs yourself. | ||
30 | |||
31 | ## [v3.0-rc1](https://github.com/lunarmodules/luasocket/releases/v3.0-rc1) — 2013-06-14 | ||
32 | |||
33 | Main changes for LuaSocket 3.0-rc1 are IPv6 support and Lua 5.2 compatibility. | ||
34 | |||
35 | * Added: Compatible with Lua 5.2 | ||
36 | - Note that unless you define LUA_COMPAT_MODULE, package tables will not be exported as globals! | ||
37 | * Added: IPv6 support; | ||
38 | - Socket.connect and socket.bind support IPv6 addresses; | ||
39 | - Getpeername and getsockname support IPv6 addresses, and return the socket family as a third value; | ||
40 | - URL module updated to support IPv6 host names; | ||
41 | - New socket.tcp6 and socket.udp6 functions; | ||
42 | - New socket.dns.getaddrinfo and socket.dns.getnameinfo functions; | ||
43 | * Added: getoption method; | ||
44 | * Fixed: url.unescape was returning additional values; | ||
45 | * Fixed: mime.qp, mime.unqp, mime.b64, and mime.unb64 could mistaking their own stack slots for functions arguments; | ||
46 | * Fixed: Receiving zero-length datagram is now possible; | ||
47 | * Improved: Hidden all internal library symbols; | ||
48 | * Improved: Better error messages; | ||
49 | * Improved: Better documentation of socket options. | ||
50 | * Fixed: manual sample of HTTP authentication now uses correct "authorization" header (Alexandre Ittner); | ||
51 | * Fixed: failure on bind() was destroying the socket (Sam Roberts); | ||
52 | * Fixed: receive() returns immediatelly if prefix can satisfy bytes requested (M Joonas Pihlaja); | ||
53 | * Fixed: multicast didn't work on Windows, or anywhere else for that matter (Herbert Leuwer, Adrian Sietsma); | ||
54 | * Fixed: select() now reports an error when called with more sockets than FD_SETSIZE (Lorenzo Leonini); | ||
55 | * Fixed: manual links to home.html changed to index.html (Robert Hahn); | ||
56 | * Fixed: mime.unb64() would return an empty string on results that started with a null character (Robert Raschke); | ||
57 | * Fixed: HTTP now automatically redirects on 303 and 307 (Jonathan Gray); | ||
58 | * Fixed: calling sleep() with negative numbers could block forever, wasting CPU. Now it returns immediately (MPB); | ||
59 | * Improved: FTP commands are now sent in upper case to help buggy servers (Anders Eurenius); | ||
60 | * Improved: known headers now sent in canonic capitalization to help buggy servers (Joseph Stewart); | ||
61 | * Improved: Clarified tcp:receive() in the manual (MPB); | ||
62 | * Improved: Decent makefiles (LHF). | ||
63 | * Fixed: RFC links in documentation now point to IETF (Cosmin Apreutesei). | ||
64 | |||
65 | ## [v2.0.2](https://github.com/lunarmodules/luasocket/releases/v2.0.2) — 2007-09-11 | ||
diff --git a/vendor/luasocket/FIX b/vendor/luasocket/FIX new file mode 100644 index 00000000..40f30a15 --- /dev/null +++ b/vendor/luasocket/FIX | |||
@@ -0,0 +1,28 @@ | |||
1 | |||
2 | |||
3 | |||
4 | |||
5 | |||
6 | |||
7 | http was preserving old host header during redirects | ||
8 | fix smtp.send hang on source error | ||
9 | add create field to FTP and SMTP and fix HTTP ugliness | ||
10 | clean timeout argument to open functions in SMTP, HTTP and FTP | ||
11 | eliminate globals from namespaces created by module(). | ||
12 | url.absolute was not working when base_url was already parsed | ||
13 | http.request was redirecting even when the location header was empty | ||
14 | tcp{client}:shutdown() was checking for group instead of class. | ||
15 | tcp{client}:send() now returns i+sent-1... | ||
16 | get rid of a = socket.try() in the manual, except for protected cases. replace it with assert. | ||
17 | get rid of "base." kludge in package.loaded | ||
18 | check all "require("http")" etc in the manual. | ||
19 | make sure sock_gethostname.* only return success if the hp is not null! | ||
20 | change 'l' prefix in C libraries to 'c' to avoid clash with LHF libraries | ||
21 | don't forget the declarations in luasocket.h and mime.h!!! | ||
22 | setpeername was using udp{unconnected} | ||
23 | fixed a bug in http.lua that caused some requests to fail (Florian Berger) | ||
24 | fixed a bug in select.c that prevented sockets with descriptor 0 from working (Renato Maia) | ||
25 | fixed a "bug" that caused dns.toip to crash under uLinux | ||
26 | fixed a "bug" that caused a crash in gethostbyname under VMS | ||
27 | DEBUG and VERSION became _DEBUG and _VERSION | ||
28 | send returns the right value if input is "". Alexander Marinov | ||
diff --git a/vendor/luasocket/LICENSE b/vendor/luasocket/LICENSE new file mode 100644 index 00000000..a8ed03ea --- /dev/null +++ b/vendor/luasocket/LICENSE | |||
@@ -0,0 +1,19 @@ | |||
1 | Copyright (C) 2004-2022 Diego Nehab | ||
2 | |||
3 | Permission is hereby granted, free of charge, to any person obtaining a | ||
4 | copy of this software and associated documentation files (the "Software"), | ||
5 | to deal in the Software without restriction, including without limitation | ||
6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
7 | and/or sell copies of the Software, and to permit persons to whom the | ||
8 | Software is furnished to do so, subject to the following conditions: | ||
9 | |||
10 | The above copyright notice and this permission notice shall be included in | ||
11 | all copies or substantial portions of the Software. | ||
12 | |||
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
18 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
19 | DEALINGS IN THE SOFTWARE. | ||
diff --git a/vendor/luasocket/README.md b/vendor/luasocket/README.md new file mode 100644 index 00000000..af722be6 --- /dev/null +++ b/vendor/luasocket/README.md | |||
@@ -0,0 +1,12 @@ | |||
1 | # LuaSocket | ||
2 | |||
3 | |||
4 | [](https://github.com/lunarmodules/luasocket/actions?workflow=Build) | ||
5 | [](https://github.com/lunarmodules/luasocket/actions?workflow=Luacheck) | ||
6 | [](https://github.com/lunarmodules/luasocket/releases) | ||
7 | [](https://luarocks.org/modules/lunarmodules/luasocket) | ||
8 | |||
9 | LuaSocket is a Lua extension library composed of two parts: | ||
10 | |||
11 | 1. a set of C modules that provide support for the TCP and UDP transport layers, and | ||
12 | 2. a set of Lua modules that provide functions commonly needed by applications that deal with the Internet. | ||
diff --git a/vendor/luasocket/TODO b/vendor/luasocket/TODO new file mode 100644 index 00000000..a838fc02 --- /dev/null +++ b/vendor/luasocket/TODO | |||
@@ -0,0 +1,81 @@ | |||
1 | - bizarre default values for getnameinfo should throw error instead! | ||
2 | |||
3 | > It's just too bad it can't talk to gmail - | ||
4 | > reason 1: they absolutely want TLS | ||
5 | > reason 2: unlike all the other SMTP implementations, they | ||
6 | > don't | ||
7 | > tolerate missing < > around adresses | ||
8 | |||
9 | - document the new bind and connect behavior. | ||
10 | - shouldn't we instead make the code compatible to Lua 5.2 | ||
11 | without any compat stuff, and use a compatibility layer to | ||
12 | make it work on 5.1? | ||
13 | - add what's new to manual | ||
14 | - should there be an equivalent to tohostname for IPv6? | ||
15 | - should we add service name resolution as well to getaddrinfo? | ||
16 | - Maybe the sockaddr to presentation conversion should be done with getnameinfo()? | ||
17 | |||
18 | - add http POST sample to manual | ||
19 | people keep asking stupid questions | ||
20 | - documentation of dirty/getfd/setfd is problematic because of portability | ||
21 | same for unix and serial. | ||
22 | what to do about this? add a stronger disclaimer? | ||
23 | - fix makefile with decent defaults? | ||
24 | |||
25 | Done: | ||
26 | |||
27 | - added IPv6 support to getsockname | ||
28 | - simplified getpeername implementation | ||
29 | - added family to return of getsockname and getpeername | ||
30 | and added modification to the manual to describe | ||
31 | |||
32 | - connect and bind try all adresses returned by getaddrinfo | ||
33 | - document headers.lua? | ||
34 | - update copyright date everywhere? | ||
35 | - remove RCSID from files? | ||
36 | - move version to 2.1 rather than 2.1.1? | ||
37 | - fixed url package to support ipv6 hosts | ||
38 | - changed domain to family | ||
39 | - implement getfamily methods. | ||
40 | |||
41 | - remove references to Lua 5.0 from documentation, add 5.2? | ||
42 | - update lua and luasocket version in samples in documentation | ||
43 | - document ipv5_v6only default option being set? | ||
44 | - document tcp6 and udp6 | ||
45 | - document dns.getaddrinfo | ||
46 | - documented zero-sized datagram change? | ||
47 | no. | ||
48 | - document unix socket and serial socket? add raw support? | ||
49 | no. | ||
50 | - document getoption | ||
51 | - merge luaL_typeerror into auxiliar to avoid using luaL prefix? | ||
52 | |||
53 | |||
54 | |||
55 | |||
56 | |||
57 | |||
58 | |||
59 | |||
60 | |||
61 | |||
62 | replace \r\n with \0xD\0xA in everything | ||
63 | New mime support | ||
64 | |||
65 | ftp send should return server replies? | ||
66 | make sure there are no object files in the distribution tarball | ||
67 | http handling of 100-continue, see DB patch | ||
68 | DB ftp.lua bug. | ||
69 | test unix.c to return just a function and works with require"unix" | ||
70 | get rid of setmetatable(, nil) since packages don't need this anymore in 5.1 | ||
71 | compat-5.1 novo | ||
72 | ajeitar pra lua-5.1 | ||
73 | |||
74 | adicionar exemplos de expansão: pipe, local, named pipe | ||
75 | testar os options! | ||
76 | |||
77 | |||
78 | - Thread-unsafe functions to protect | ||
79 | gethostbyname(), gethostbyaddr(), gethostent(), | ||
80 | inet_ntoa(), strerror(), | ||
81 | |||
diff --git a/vendor/luasocket/WISH b/vendor/luasocket/WISH new file mode 100644 index 00000000..e7e9c076 --- /dev/null +++ b/vendor/luasocket/WISH | |||
@@ -0,0 +1,22 @@ | |||
1 | ... as an l-value to get all results of a function call? | ||
2 | at least ...[i] and #... | ||
3 | extend to full tuples? | ||
4 | |||
5 | __and __or __not metamethods | ||
6 | |||
7 | lua_tostring, lua_tonumber, lua_touseradta etc push values in stack | ||
8 | __tostring,__tonumber, __touserdata metamethods are checked | ||
9 | and expected to push an object of correct type on stack | ||
10 | |||
11 | lua_rawtostring, lua_rawtonumber, lua_rawtouserdata don't | ||
12 | push anything on stack, return data of appropriate type, | ||
13 | skip metamethods and throw error if object not of exact type | ||
14 | |||
15 | package.findfile exported | ||
16 | module not polluting the global namespace | ||
17 | |||
18 | coxpcall with a coroutine pool for efficiency (reusing coroutines) | ||
19 | |||
20 | exception mechanism formalized? just like the package system was. | ||
21 | |||
22 | a nice bitlib in the core | ||
diff --git a/vendor/luasocket/logo.ps b/vendor/luasocket/logo.ps new file mode 100644 index 00000000..8b5809ab --- /dev/null +++ b/vendor/luasocket/logo.ps | |||
@@ -0,0 +1,210 @@ | |||
1 | %!PS-Adobe-2.0 EPSF-2.0 | ||
2 | %%Title: Lua logo | ||
3 | %%Creator: lua@tecgraf.puc-rio.br | ||
4 | %%CreationDate: Wed Nov 29 19:04:04 EDT 2000 | ||
5 | %%BoundingBox: -45 0 1035 1080 | ||
6 | %%Pages: 1 | ||
7 | %%EndComments | ||
8 | %%EndProlog | ||
9 | |||
10 | %------------------------------------------------------------------------------ | ||
11 | % | ||
12 | % Copyright (C) 1998-2000. All rights reserved. | ||
13 | % Graphic design by Alexandre Nakonechny (nako@openlink.com.br). | ||
14 | % PostScript programming by the Lua team (lua@tecgraf.puc-rio.br). | ||
15 | % | ||
16 | % Permission is hereby granted, without written agreement and without license | ||
17 | % or royalty fees, to use, copy, and distribute this logo for any purpose, | ||
18 | % including commercial applications, subject to the following conditions: | ||
19 | % | ||
20 | % * The origin of this logo must not be misrepresented; you must not | ||
21 | % claim that you drew the original logo. We recommend that you give credit | ||
22 | % to the graphics designer in all printed matter that includes the logo. | ||
23 | % | ||
24 | % * The only modification you can make is to adapt the orbiting text to | ||
25 | % your product name. | ||
26 | % | ||
27 | % * The logo can be used in any scale as long as the relative proportions | ||
28 | % of its elements are maintained. | ||
29 | % | ||
30 | %------------------------------------------------------------------------------ | ||
31 | |||
32 | /LABEL (tekcoS) def | ||
33 | |||
34 | %-- DO NOT CHANGE ANYTHING BELOW THIS LINE ------------------------------------ | ||
35 | |||
36 | /PLANETCOLOR {0 0 0.5 setrgbcolor} bind def | ||
37 | /HOLECOLOR {1.0 setgray} bind def | ||
38 | /ORBITCOLOR {0.5 setgray} bind def | ||
39 | /LOGOFONT {/Helvetica 0.90} def | ||
40 | /LABELFONT {/Helvetica 0.36} def | ||
41 | |||
42 | %------------------------------------------------------------------------------ | ||
43 | |||
44 | /MOONCOLOR {PLANETCOLOR} bind def | ||
45 | /LOGOCOLOR {HOLECOLOR} bind def | ||
46 | /LABELCOLOR {ORBITCOLOR} bind def | ||
47 | |||
48 | /LABELANGLE 325 def | ||
49 | /LOGO (Lua) def | ||
50 | |||
51 | /DASHANGLE 10 def | ||
52 | /HALFDASHANGLE DASHANGLE 2 div def | ||
53 | |||
54 | % moon radius. planet radius is 1. | ||
55 | /r 1 2 sqrt 2 div sub def | ||
56 | |||
57 | /D {0 360 arc fill} bind def | ||
58 | /F {exch findfont exch scalefont setfont} bind def | ||
59 | |||
60 | % place it nicely on the paper | ||
61 | /RESOLUTION 1024 def | ||
62 | RESOLUTION 2 div dup translate | ||
63 | RESOLUTION 2 div 2 sqrt div dup scale | ||
64 | |||
65 | %-------------------------------------------------------------------- planet -- | ||
66 | PLANETCOLOR | ||
67 | 0 0 1 D | ||
68 | |||
69 | %---------------------------------------------------------------------- hole -- | ||
70 | HOLECOLOR | ||
71 | 1 2 r mul sub dup r D | ||
72 | |||
73 | %---------------------------------------------------------------------- moon -- | ||
74 | MOONCOLOR | ||
75 | 1 1 r D | ||
76 | |||
77 | %---------------------------------------------------------------------- logo -- | ||
78 | LOGOCOLOR | ||
79 | LOGOFONT | ||
80 | F | ||
81 | LOGO stringwidth pop 2 div neg | ||
82 | -0.5 moveto | ||
83 | LOGO show | ||
84 | |||
85 | %------------------------------------------------------------------------------ | ||
86 | % based on code from Blue Book Program 10, on pages 167--169 | ||
87 | % available at ftp://ftp.adobe.com/pub/adobe/displaypostscript/bluebook.shar | ||
88 | |||
89 | % str ptsize centerangle radius outsidecircletext -- | ||
90 | /outsidecircletext { | ||
91 | circtextdict begin | ||
92 | /radius exch def | ||
93 | /centerangle exch def | ||
94 | /ptsize exch def | ||
95 | /str exch def | ||
96 | |||
97 | gsave | ||
98 | str radius ptsize findhalfangle | ||
99 | centerangle | ||
100 | add rotate | ||
101 | str | ||
102 | { /charcode exch def | ||
103 | ( ) dup 0 charcode put outsideplacechar | ||
104 | } forall | ||
105 | |||
106 | grestore | ||
107 | end | ||
108 | } def | ||
109 | |||
110 | % string radius ptsize findhalfangle halfangle | ||
111 | /findhalfangle { | ||
112 | 4 div add | ||
113 | exch | ||
114 | stringwidth pop 2 div | ||
115 | exch | ||
116 | 2 mul 3.1415926535 mul div 360 mul | ||
117 | } def | ||
118 | |||
119 | /circtextdict 16 dict def | ||
120 | circtextdict begin | ||
121 | |||
122 | /outsideplacechar { | ||
123 | /char exch def | ||
124 | /halfangle char radius ptsize findhalfangle def | ||
125 | gsave | ||
126 | halfangle neg rotate | ||
127 | 1.4 0 translate | ||
128 | 90 rotate | ||
129 | char stringwidth pop 2 div neg 0 moveto | ||
130 | char show | ||
131 | grestore | ||
132 | halfangle 2 mul neg rotate | ||
133 | } def | ||
134 | |||
135 | end | ||
136 | |||
137 | %--------------------------------------------------------------------- label -- | ||
138 | LABELFONT | ||
139 | F | ||
140 | |||
141 | /LABELSIZE LABELFONT exch pop def | ||
142 | /LABELRADIUS LABELSIZE 3 div 1 r add sub neg 1.02 mul def | ||
143 | |||
144 | |||
145 | /HALFANGLE | ||
146 | LABEL LABELRADIUS LABELSIZE findhalfangle | ||
147 | HALFDASHANGLE div ceiling HALFDASHANGLE mul | ||
148 | def | ||
149 | |||
150 | /LABELANGLE | ||
151 | 60 LABELANGLE HALFANGLE sub | ||
152 | lt | ||
153 | { | ||
154 | HALFANGLE | ||
155 | HALFANGLE DASHANGLE div floor DASHANGLE mul | ||
156 | eq | ||
157 | {LABELANGLE DASHANGLE div ceiling DASHANGLE mul} | ||
158 | {LABELANGLE HALFDASHANGLE sub DASHANGLE div round DASHANGLE mul HALFDASHANGLE add} | ||
159 | ifelse | ||
160 | } | ||
161 | {HALFANGLE 60 add} | ||
162 | ifelse | ||
163 | def | ||
164 | |||
165 | LABELCOLOR | ||
166 | LABEL | ||
167 | LABELSIZE | ||
168 | LABELANGLE | ||
169 | LABELRADIUS | ||
170 | outsidecircletext | ||
171 | |||
172 | %--------------------------------------------------------------------- orbit -- | ||
173 | ORBITCOLOR | ||
174 | 0.03 setlinewidth | ||
175 | [1 r add 3.1415926535 180 div HALFDASHANGLE mul mul] 0 setdash | ||
176 | newpath | ||
177 | 0 0 | ||
178 | 1 r add | ||
179 | 3 copy | ||
180 | 30 | ||
181 | LABELANGLE HALFANGLE add | ||
182 | arcn | ||
183 | stroke | ||
184 | 60 | ||
185 | LABELANGLE HALFANGLE sub | ||
186 | 2 copy | ||
187 | lt {arc stroke} {4 {pop} repeat} ifelse | ||
188 | |||
189 | %------------------------------------------------------------------ copyright -- | ||
190 | /COPYRIGHT | ||
191 | (Graphic design by A. Nakonechny. Copyright (c) 1998, All rights reserved.) | ||
192 | def | ||
193 | |||
194 | LABELCOLOR | ||
195 | LOGOFONT | ||
196 | 32 div | ||
197 | F | ||
198 | 2 sqrt 0.99 mul | ||
199 | dup | ||
200 | neg | ||
201 | moveto | ||
202 | COPYRIGHT | ||
203 | 90 rotate | ||
204 | %show | ||
205 | |||
206 | %---------------------------------------------------------------------- done -- | ||
207 | showpage | ||
208 | |||
209 | %%Trailer | ||
210 | %%EOF | ||
diff --git a/vendor/luasocket/luasocket-scm-3.rockspec b/vendor/luasocket/luasocket-scm-3.rockspec new file mode 100644 index 00000000..10452510 --- /dev/null +++ b/vendor/luasocket/luasocket-scm-3.rockspec | |||
@@ -0,0 +1,135 @@ | |||
1 | package = "LuaSocket" | ||
2 | version = "scm-3" | ||
3 | source = { | ||
4 | url = "git+https://github.com/lunarmodules/luasocket.git", | ||
5 | branch = "master" | ||
6 | } | ||
7 | description = { | ||
8 | summary = "Network support for the Lua language", | ||
9 | detailed = [[ | ||
10 | LuaSocket is a Lua extension library composed of two parts: a set of C | ||
11 | modules that provide support for the TCP and UDP transport layers, and a | ||
12 | set of Lua modules that provide functions commonly needed by applications | ||
13 | that deal with the Internet. | ||
14 | ]], | ||
15 | homepage = "https://github.com/lunarmodules/luasocket", | ||
16 | license = "MIT" | ||
17 | } | ||
18 | dependencies = { | ||
19 | "lua >= 5.1" | ||
20 | } | ||
21 | |||
22 | local function make_plat(plat) | ||
23 | local defines = { | ||
24 | unix = { | ||
25 | "LUASOCKET_DEBUG" | ||
26 | }, | ||
27 | macosx = { | ||
28 | "LUASOCKET_DEBUG", | ||
29 | "UNIX_HAS_SUN_LEN" | ||
30 | }, | ||
31 | win32 = { | ||
32 | "LUASOCKET_DEBUG", | ||
33 | "NDEBUG" | ||
34 | }, | ||
35 | mingw32 = { | ||
36 | "LUASOCKET_DEBUG", | ||
37 | -- "LUASOCKET_INET_PTON", | ||
38 | "WINVER=0x0501" | ||
39 | } | ||
40 | } | ||
41 | local modules = { | ||
42 | ["socket.core"] = { | ||
43 | sources = { | ||
44 | "src/luasocket.c" | ||
45 | , "src/timeout.c" | ||
46 | , "src/buffer.c" | ||
47 | , "src/io.c" | ||
48 | , "src/auxiliar.c" | ||
49 | , "src/options.c" | ||
50 | , "src/inet.c" | ||
51 | , "src/except.c" | ||
52 | , "src/select.c" | ||
53 | , "src/tcp.c" | ||
54 | , "src/udp.c" | ||
55 | , "src/compat.c" }, | ||
56 | defines = defines[plat], | ||
57 | incdir = "/src" | ||
58 | }, | ||
59 | ["mime.core"] = { | ||
60 | sources = { "src/mime.c", "src/compat.c" }, | ||
61 | defines = defines[plat], | ||
62 | incdir = "/src" | ||
63 | }, | ||
64 | ["socket.http"] = "src/http.lua", | ||
65 | ["socket.url"] = "src/url.lua", | ||
66 | ["socket.tp"] = "src/tp.lua", | ||
67 | ["socket.ftp"] = "src/ftp.lua", | ||
68 | ["socket.headers"] = "src/headers.lua", | ||
69 | ["socket.smtp"] = "src/smtp.lua", | ||
70 | ltn12 = "src/ltn12.lua", | ||
71 | socket = "src/socket.lua", | ||
72 | mime = "src/mime.lua" | ||
73 | } | ||
74 | if plat == "unix" | ||
75 | or plat == "macosx" | ||
76 | or plat == "haiku" | ||
77 | then | ||
78 | modules["socket.core"].sources[#modules["socket.core"].sources+1] = "src/usocket.c" | ||
79 | if plat == "haiku" then | ||
80 | modules["socket.core"].libraries = {"network"} | ||
81 | end | ||
82 | modules["socket.unix"] = { | ||
83 | sources = { | ||
84 | "src/buffer.c" | ||
85 | , "src/compat.c" | ||
86 | , "src/auxiliar.c" | ||
87 | , "src/options.c" | ||
88 | , "src/timeout.c" | ||
89 | , "src/io.c" | ||
90 | , "src/usocket.c" | ||
91 | , "src/unix.c" | ||
92 | , "src/unixdgram.c" | ||
93 | , "src/unixstream.c" }, | ||
94 | defines = defines[plat], | ||
95 | incdir = "/src" | ||
96 | } | ||
97 | modules["socket.serial"] = { | ||
98 | sources = { | ||
99 | "src/buffer.c" | ||
100 | , "src/compat.c" | ||
101 | , "src/auxiliar.c" | ||
102 | , "src/options.c" | ||
103 | , "src/timeout.c" | ||
104 | , "src/io.c" | ||
105 | , "src/usocket.c" | ||
106 | , "src/serial.c" }, | ||
107 | defines = defines[plat], | ||
108 | incdir = "/src" | ||
109 | } | ||
110 | end | ||
111 | if plat == "win32" | ||
112 | or plat == "mingw32" | ||
113 | then | ||
114 | modules["socket.core"].sources[#modules["socket.core"].sources+1] = "src/wsocket.c" | ||
115 | modules["socket.core"].libraries = { "ws2_32" } | ||
116 | modules["socket.core"].libdirs = {} | ||
117 | end | ||
118 | return { modules = modules } | ||
119 | end | ||
120 | |||
121 | build = { | ||
122 | type = "builtin", | ||
123 | platforms = { | ||
124 | unix = make_plat("unix"), | ||
125 | macosx = make_plat("macosx"), | ||
126 | haiku = make_plat("haiku"), | ||
127 | win32 = make_plat("win32"), | ||
128 | mingw32 = make_plat("mingw32") | ||
129 | }, | ||
130 | copy_directories = { | ||
131 | "docs" | ||
132 | , "samples" | ||
133 | , "etc" | ||
134 | , "test" } | ||
135 | } | ||
diff --git a/vendor/luasocket/luasocket.sln b/vendor/luasocket/luasocket.sln new file mode 100644 index 00000000..0e5cdc73 --- /dev/null +++ b/vendor/luasocket/luasocket.sln | |||
@@ -0,0 +1,35 @@ | |||
1 | Microsoft Visual Studio Solution File, Format Version 12.00 | ||
2 | # Visual Studio 2012 | ||
3 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "socket", "socket.vcxproj", "{66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}" | ||
4 | EndProject | ||
5 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mime", "mime.vcxproj", "{128E8BD0-174A-48F0-8771-92B1E8D18713}" | ||
6 | EndProject | ||
7 | Global | ||
8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
9 | Debug|Win32 = Debug|Win32 | ||
10 | Debug|x64 = Debug|x64 | ||
11 | Release|Win32 = Release|Win32 | ||
12 | Release|x64 = Release|x64 | ||
13 | EndGlobalSection | ||
14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
15 | {66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}.Debug|Win32.ActiveCfg = Debug|Win32 | ||
16 | {66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}.Debug|Win32.Build.0 = Debug|Win32 | ||
17 | {66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}.Debug|x64.ActiveCfg = Debug|x64 | ||
18 | {66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}.Debug|x64.Build.0 = Debug|x64 | ||
19 | {66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}.Release|Win32.ActiveCfg = Release|Win32 | ||
20 | {66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}.Release|Win32.Build.0 = Release|Win32 | ||
21 | {66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}.Release|x64.ActiveCfg = Release|x64 | ||
22 | {66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}.Release|x64.Build.0 = Release|x64 | ||
23 | {128E8BD0-174A-48F0-8771-92B1E8D18713}.Debug|Win32.ActiveCfg = Debug|Win32 | ||
24 | {128E8BD0-174A-48F0-8771-92B1E8D18713}.Debug|Win32.Build.0 = Debug|Win32 | ||
25 | {128E8BD0-174A-48F0-8771-92B1E8D18713}.Debug|x64.ActiveCfg = Debug|x64 | ||
26 | {128E8BD0-174A-48F0-8771-92B1E8D18713}.Debug|x64.Build.0 = Debug|x64 | ||
27 | {128E8BD0-174A-48F0-8771-92B1E8D18713}.Release|Win32.ActiveCfg = Release|Win32 | ||
28 | {128E8BD0-174A-48F0-8771-92B1E8D18713}.Release|Win32.Build.0 = Release|Win32 | ||
29 | {128E8BD0-174A-48F0-8771-92B1E8D18713}.Release|x64.ActiveCfg = Release|x64 | ||
30 | {128E8BD0-174A-48F0-8771-92B1E8D18713}.Release|x64.Build.0 = Release|x64 | ||
31 | EndGlobalSection | ||
32 | GlobalSection(SolutionProperties) = preSolution | ||
33 | HideSolutionNode = FALSE | ||
34 | EndGlobalSection | ||
35 | EndGlobal | ||
diff --git a/vendor/luasocket/src/auxiliar.c b/vendor/luasocket/src/auxiliar.c new file mode 100644 index 00000000..93a66a09 --- /dev/null +++ b/vendor/luasocket/src/auxiliar.c | |||
@@ -0,0 +1,154 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * Auxiliar routines for class hierarchy manipulation | ||
3 | * LuaSocket toolkit | ||
4 | \*=========================================================================*/ | ||
5 | #include "luasocket.h" | ||
6 | #include "auxiliar.h" | ||
7 | #include <string.h> | ||
8 | #include <stdio.h> | ||
9 | |||
10 | /*-------------------------------------------------------------------------*\ | ||
11 | * Initializes the module | ||
12 | \*-------------------------------------------------------------------------*/ | ||
13 | int auxiliar_open(lua_State *L) { | ||
14 | (void) L; | ||
15 | return 0; | ||
16 | } | ||
17 | |||
18 | /*-------------------------------------------------------------------------*\ | ||
19 | * Creates a new class with given methods | ||
20 | * Methods whose names start with __ are passed directly to the metatable. | ||
21 | \*-------------------------------------------------------------------------*/ | ||
22 | void auxiliar_newclass(lua_State *L, const char *classname, luaL_Reg *func) { | ||
23 | luaL_newmetatable(L, classname); /* mt */ | ||
24 | /* create __index table to place methods */ | ||
25 | lua_pushstring(L, "__index"); /* mt,"__index" */ | ||
26 | lua_newtable(L); /* mt,"__index",it */ | ||
27 | /* put class name into class metatable */ | ||
28 | lua_pushstring(L, "class"); /* mt,"__index",it,"class" */ | ||
29 | lua_pushstring(L, classname); /* mt,"__index",it,"class",classname */ | ||
30 | lua_rawset(L, -3); /* mt,"__index",it */ | ||
31 | /* pass all methods that start with _ to the metatable, and all others | ||
32 | * to the index table */ | ||
33 | for (; func->name; func++) { /* mt,"__index",it */ | ||
34 | lua_pushstring(L, func->name); | ||
35 | lua_pushcfunction(L, func->func); | ||
36 | lua_rawset(L, func->name[0] == '_' ? -5: -3); | ||
37 | } | ||
38 | lua_rawset(L, -3); /* mt */ | ||
39 | lua_pop(L, 1); | ||
40 | } | ||
41 | |||
42 | /*-------------------------------------------------------------------------*\ | ||
43 | * Prints the value of a class in a nice way | ||
44 | \*-------------------------------------------------------------------------*/ | ||
45 | int auxiliar_tostring(lua_State *L) { | ||
46 | char buf[32]; | ||
47 | if (!lua_getmetatable(L, 1)) goto error; | ||
48 | lua_pushstring(L, "__index"); | ||
49 | lua_gettable(L, -2); | ||
50 | if (!lua_istable(L, -1)) goto error; | ||
51 | lua_pushstring(L, "class"); | ||
52 | lua_gettable(L, -2); | ||
53 | if (!lua_isstring(L, -1)) goto error; | ||
54 | sprintf(buf, "%p", lua_touserdata(L, 1)); | ||
55 | lua_pushfstring(L, "%s: %s", lua_tostring(L, -1), buf); | ||
56 | return 1; | ||
57 | error: | ||
58 | lua_pushstring(L, "invalid object passed to 'auxiliar.c:__tostring'"); | ||
59 | lua_error(L); | ||
60 | return 1; | ||
61 | } | ||
62 | |||
63 | /*-------------------------------------------------------------------------*\ | ||
64 | * Insert class into group | ||
65 | \*-------------------------------------------------------------------------*/ | ||
66 | void auxiliar_add2group(lua_State *L, const char *classname, const char *groupname) { | ||
67 | luaL_getmetatable(L, classname); | ||
68 | lua_pushstring(L, groupname); | ||
69 | lua_pushboolean(L, 1); | ||
70 | lua_rawset(L, -3); | ||
71 | lua_pop(L, 1); | ||
72 | } | ||
73 | |||
74 | /*-------------------------------------------------------------------------*\ | ||
75 | * Make sure argument is a boolean | ||
76 | \*-------------------------------------------------------------------------*/ | ||
77 | int auxiliar_checkboolean(lua_State *L, int objidx) { | ||
78 | if (!lua_isboolean(L, objidx)) | ||
79 | auxiliar_typeerror(L, objidx, lua_typename(L, LUA_TBOOLEAN)); | ||
80 | return lua_toboolean(L, objidx); | ||
81 | } | ||
82 | |||
83 | /*-------------------------------------------------------------------------*\ | ||
84 | * Return userdata pointer if object belongs to a given class, abort with | ||
85 | * error otherwise | ||
86 | \*-------------------------------------------------------------------------*/ | ||
87 | void *auxiliar_checkclass(lua_State *L, const char *classname, int objidx) { | ||
88 | void *data = auxiliar_getclassudata(L, classname, objidx); | ||
89 | if (!data) { | ||
90 | char msg[45]; | ||
91 | sprintf(msg, "%.35s expected", classname); | ||
92 | luaL_argerror(L, objidx, msg); | ||
93 | } | ||
94 | return data; | ||
95 | } | ||
96 | |||
97 | /*-------------------------------------------------------------------------*\ | ||
98 | * Return userdata pointer if object belongs to a given group, abort with | ||
99 | * error otherwise | ||
100 | \*-------------------------------------------------------------------------*/ | ||
101 | void *auxiliar_checkgroup(lua_State *L, const char *groupname, int objidx) { | ||
102 | void *data = auxiliar_getgroupudata(L, groupname, objidx); | ||
103 | if (!data) { | ||
104 | char msg[45]; | ||
105 | sprintf(msg, "%.35s expected", groupname); | ||
106 | luaL_argerror(L, objidx, msg); | ||
107 | } | ||
108 | return data; | ||
109 | } | ||
110 | |||
111 | /*-------------------------------------------------------------------------*\ | ||
112 | * Set object class | ||
113 | \*-------------------------------------------------------------------------*/ | ||
114 | void auxiliar_setclass(lua_State *L, const char *classname, int objidx) { | ||
115 | luaL_getmetatable(L, classname); | ||
116 | if (objidx < 0) objidx--; | ||
117 | lua_setmetatable(L, objidx); | ||
118 | } | ||
119 | |||
120 | /*-------------------------------------------------------------------------*\ | ||
121 | * Get a userdata pointer if object belongs to a given group. Return NULL | ||
122 | * otherwise | ||
123 | \*-------------------------------------------------------------------------*/ | ||
124 | void *auxiliar_getgroupudata(lua_State *L, const char *groupname, int objidx) { | ||
125 | if (!lua_getmetatable(L, objidx)) | ||
126 | return NULL; | ||
127 | lua_pushstring(L, groupname); | ||
128 | lua_rawget(L, -2); | ||
129 | if (lua_isnil(L, -1)) { | ||
130 | lua_pop(L, 2); | ||
131 | return NULL; | ||
132 | } else { | ||
133 | lua_pop(L, 2); | ||
134 | return lua_touserdata(L, objidx); | ||
135 | } | ||
136 | } | ||
137 | |||
138 | /*-------------------------------------------------------------------------*\ | ||
139 | * Get a userdata pointer if object belongs to a given class. Return NULL | ||
140 | * otherwise | ||
141 | \*-------------------------------------------------------------------------*/ | ||
142 | void *auxiliar_getclassudata(lua_State *L, const char *classname, int objidx) { | ||
143 | return luaL_testudata(L, objidx, classname); | ||
144 | } | ||
145 | |||
146 | /*-------------------------------------------------------------------------*\ | ||
147 | * Throws error when argument does not have correct type. | ||
148 | * Used to be part of lauxlib in Lua 5.1, was dropped from 5.2. | ||
149 | \*-------------------------------------------------------------------------*/ | ||
150 | int auxiliar_typeerror (lua_State *L, int narg, const char *tname) { | ||
151 | const char *msg = lua_pushfstring(L, "%s expected, got %s", tname, | ||
152 | luaL_typename(L, narg)); | ||
153 | return luaL_argerror(L, narg, msg); | ||
154 | } | ||
diff --git a/vendor/luasocket/src/auxiliar.h b/vendor/luasocket/src/auxiliar.h new file mode 100644 index 00000000..e8c3ead8 --- /dev/null +++ b/vendor/luasocket/src/auxiliar.h | |||
@@ -0,0 +1,54 @@ | |||
1 | #ifndef AUXILIAR_H | ||
2 | #define AUXILIAR_H | ||
3 | /*=========================================================================*\ | ||
4 | * Auxiliar routines for class hierarchy manipulation | ||
5 | * LuaSocket toolkit (but completely independent of other LuaSocket modules) | ||
6 | * | ||
7 | * A LuaSocket class is a name associated with Lua metatables. A LuaSocket | ||
8 | * group is a name associated with a class. A class can belong to any number | ||
9 | * of groups. This module provides the functionality to: | ||
10 | * | ||
11 | * - create new classes | ||
12 | * - add classes to groups | ||
13 | * - set the class of objects | ||
14 | * - check if an object belongs to a given class or group | ||
15 | * - get the userdata associated to objects | ||
16 | * - print objects in a pretty way | ||
17 | * | ||
18 | * LuaSocket class names follow the convention <module>{<class>}. Modules | ||
19 | * can define any number of classes and groups. The module tcp.c, for | ||
20 | * example, defines the classes tcp{master}, tcp{client} and tcp{server} and | ||
21 | * the groups tcp{client,server} and tcp{any}. Module functions can then | ||
22 | * perform type-checking on their arguments by either class or group. | ||
23 | * | ||
24 | * LuaSocket metatables define the __index metamethod as being a table. This | ||
25 | * table has one field for each method supported by the class, and a field | ||
26 | * "class" with the class name. | ||
27 | * | ||
28 | * The mapping from class name to the corresponding metatable and the | ||
29 | * reverse mapping are done using lauxlib. | ||
30 | \*=========================================================================*/ | ||
31 | |||
32 | #include "luasocket.h" | ||
33 | |||
34 | #ifndef _WIN32 | ||
35 | #pragma GCC visibility push(hidden) | ||
36 | #endif | ||
37 | |||
38 | int auxiliar_open(lua_State *L); | ||
39 | void auxiliar_newclass(lua_State *L, const char *classname, luaL_Reg *func); | ||
40 | int auxiliar_tostring(lua_State *L); | ||
41 | void auxiliar_add2group(lua_State *L, const char *classname, const char *group); | ||
42 | int auxiliar_checkboolean(lua_State *L, int objidx); | ||
43 | void *auxiliar_checkclass(lua_State *L, const char *classname, int objidx); | ||
44 | void *auxiliar_checkgroup(lua_State *L, const char *groupname, int objidx); | ||
45 | void auxiliar_setclass(lua_State *L, const char *classname, int objidx); | ||
46 | void *auxiliar_getgroupudata(lua_State *L, const char *groupname, int objidx); | ||
47 | void *auxiliar_getclassudata(lua_State *L, const char *groupname, int objidx); | ||
48 | int auxiliar_typeerror(lua_State *L, int narg, const char *tname); | ||
49 | |||
50 | #ifndef _WIN32 | ||
51 | #pragma GCC visibility pop | ||
52 | #endif | ||
53 | |||
54 | #endif /* AUXILIAR_H */ | ||
diff --git a/vendor/luasocket/src/buffer.c b/vendor/luasocket/src/buffer.c new file mode 100644 index 00000000..7148be34 --- /dev/null +++ b/vendor/luasocket/src/buffer.c | |||
@@ -0,0 +1,273 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * Input/Output interface for Lua programs | ||
3 | * LuaSocket toolkit | ||
4 | \*=========================================================================*/ | ||
5 | #include "luasocket.h" | ||
6 | #include "buffer.h" | ||
7 | |||
8 | /*=========================================================================*\ | ||
9 | * Internal function prototypes | ||
10 | \*=========================================================================*/ | ||
11 | static int recvraw(p_buffer buf, size_t wanted, luaL_Buffer *b); | ||
12 | static int recvline(p_buffer buf, luaL_Buffer *b); | ||
13 | static int recvall(p_buffer buf, luaL_Buffer *b); | ||
14 | static int buffer_get(p_buffer buf, const char **data, size_t *count); | ||
15 | static void buffer_skip(p_buffer buf, size_t count); | ||
16 | static int sendraw(p_buffer buf, const char *data, size_t count, size_t *sent); | ||
17 | |||
18 | /* min and max macros */ | ||
19 | #ifndef MIN | ||
20 | #define MIN(x, y) ((x) < (y) ? x : y) | ||
21 | #endif | ||
22 | #ifndef MAX | ||
23 | #define MAX(x, y) ((x) > (y) ? x : y) | ||
24 | #endif | ||
25 | |||
26 | /*=========================================================================*\ | ||
27 | * Exported functions | ||
28 | \*=========================================================================*/ | ||
29 | /*-------------------------------------------------------------------------*\ | ||
30 | * Initializes module | ||
31 | \*-------------------------------------------------------------------------*/ | ||
32 | int buffer_open(lua_State *L) { | ||
33 | (void) L; | ||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | /*-------------------------------------------------------------------------*\ | ||
38 | * Initializes C structure | ||
39 | \*-------------------------------------------------------------------------*/ | ||
40 | void buffer_init(p_buffer buf, p_io io, p_timeout tm) { | ||
41 | buf->first = buf->last = 0; | ||
42 | buf->io = io; | ||
43 | buf->tm = tm; | ||
44 | buf->received = buf->sent = 0; | ||
45 | buf->birthday = timeout_gettime(); | ||
46 | } | ||
47 | |||
48 | /*-------------------------------------------------------------------------*\ | ||
49 | * object:getstats() interface | ||
50 | \*-------------------------------------------------------------------------*/ | ||
51 | int buffer_meth_getstats(lua_State *L, p_buffer buf) { | ||
52 | lua_pushnumber(L, (lua_Number) buf->received); | ||
53 | lua_pushnumber(L, (lua_Number) buf->sent); | ||
54 | lua_pushnumber(L, timeout_gettime() - buf->birthday); | ||
55 | return 3; | ||
56 | } | ||
57 | |||
58 | /*-------------------------------------------------------------------------*\ | ||
59 | * object:setstats() interface | ||
60 | \*-------------------------------------------------------------------------*/ | ||
61 | int buffer_meth_setstats(lua_State *L, p_buffer buf) { | ||
62 | buf->received = (long) luaL_optnumber(L, 2, (lua_Number) buf->received); | ||
63 | buf->sent = (long) luaL_optnumber(L, 3, (lua_Number) buf->sent); | ||
64 | if (lua_isnumber(L, 4)) buf->birthday = timeout_gettime() - lua_tonumber(L, 4); | ||
65 | lua_pushnumber(L, 1); | ||
66 | return 1; | ||
67 | } | ||
68 | |||
69 | /*-------------------------------------------------------------------------*\ | ||
70 | * object:send() interface | ||
71 | \*-------------------------------------------------------------------------*/ | ||
72 | int buffer_meth_send(lua_State *L, p_buffer buf) { | ||
73 | int top = lua_gettop(L); | ||
74 | int err = IO_DONE; | ||
75 | size_t size = 0, sent = 0; | ||
76 | const char *data = luaL_checklstring(L, 2, &size); | ||
77 | long start = (long) luaL_optnumber(L, 3, 1); | ||
78 | long end = (long) luaL_optnumber(L, 4, -1); | ||
79 | timeout_markstart(buf->tm); | ||
80 | if (start < 0) start = (long) (size+start+1); | ||
81 | if (end < 0) end = (long) (size+end+1); | ||
82 | if (start < 1) start = (long) 1; | ||
83 | if (end > (long) size) end = (long) size; | ||
84 | if (start <= end) err = sendraw(buf, data+start-1, end-start+1, &sent); | ||
85 | /* check if there was an error */ | ||
86 | if (err != IO_DONE) { | ||
87 | lua_pushnil(L); | ||
88 | lua_pushstring(L, buf->io->error(buf->io->ctx, err)); | ||
89 | lua_pushnumber(L, (lua_Number) (sent+start-1)); | ||
90 | } else { | ||
91 | lua_pushnumber(L, (lua_Number) (sent+start-1)); | ||
92 | lua_pushnil(L); | ||
93 | lua_pushnil(L); | ||
94 | } | ||
95 | #ifdef LUASOCKET_DEBUG | ||
96 | /* push time elapsed during operation as the last return value */ | ||
97 | lua_pushnumber(L, timeout_gettime() - timeout_getstart(buf->tm)); | ||
98 | #endif | ||
99 | return lua_gettop(L) - top; | ||
100 | } | ||
101 | |||
102 | /*-------------------------------------------------------------------------*\ | ||
103 | * object:receive() interface | ||
104 | \*-------------------------------------------------------------------------*/ | ||
105 | int buffer_meth_receive(lua_State *L, p_buffer buf) { | ||
106 | int err = IO_DONE, top; | ||
107 | luaL_Buffer b; | ||
108 | size_t size; | ||
109 | const char *part = luaL_optlstring(L, 3, "", &size); | ||
110 | timeout_markstart(buf->tm); | ||
111 | /* make sure we don't confuse buffer stuff with arguments */ | ||
112 | lua_settop(L, 3); | ||
113 | top = lua_gettop(L); | ||
114 | /* initialize buffer with optional extra prefix | ||
115 | * (useful for concatenating previous partial results) */ | ||
116 | luaL_buffinit(L, &b); | ||
117 | luaL_addlstring(&b, part, size); | ||
118 | /* receive new patterns */ | ||
119 | if (!lua_isnumber(L, 2)) { | ||
120 | const char *p= luaL_optstring(L, 2, "*l"); | ||
121 | if (p[0] == '*' && p[1] == 'l') err = recvline(buf, &b); | ||
122 | else if (p[0] == '*' && p[1] == 'a') err = recvall(buf, &b); | ||
123 | else luaL_argcheck(L, 0, 2, "invalid receive pattern"); | ||
124 | /* get a fixed number of bytes (minus what was already partially | ||
125 | * received) */ | ||
126 | } else { | ||
127 | double n = lua_tonumber(L, 2); | ||
128 | size_t wanted = (size_t) n; | ||
129 | luaL_argcheck(L, n >= 0, 2, "invalid receive pattern"); | ||
130 | if (size == 0 || wanted > size) | ||
131 | err = recvraw(buf, wanted-size, &b); | ||
132 | } | ||
133 | /* check if there was an error */ | ||
134 | if (err != IO_DONE) { | ||
135 | /* we can't push anyting in the stack before pushing the | ||
136 | * contents of the buffer. this is the reason for the complication */ | ||
137 | luaL_pushresult(&b); | ||
138 | lua_pushstring(L, buf->io->error(buf->io->ctx, err)); | ||
139 | lua_pushvalue(L, -2); | ||
140 | lua_pushnil(L); | ||
141 | lua_replace(L, -4); | ||
142 | } else { | ||
143 | luaL_pushresult(&b); | ||
144 | lua_pushnil(L); | ||
145 | lua_pushnil(L); | ||
146 | } | ||
147 | #ifdef LUASOCKET_DEBUG | ||
148 | /* push time elapsed during operation as the last return value */ | ||
149 | lua_pushnumber(L, timeout_gettime() - timeout_getstart(buf->tm)); | ||
150 | #endif | ||
151 | return lua_gettop(L) - top; | ||
152 | } | ||
153 | |||
154 | /*-------------------------------------------------------------------------*\ | ||
155 | * Determines if there is any data in the read buffer | ||
156 | \*-------------------------------------------------------------------------*/ | ||
157 | int buffer_isempty(p_buffer buf) { | ||
158 | return buf->first >= buf->last; | ||
159 | } | ||
160 | |||
161 | /*=========================================================================*\ | ||
162 | * Internal functions | ||
163 | \*=========================================================================*/ | ||
164 | /*-------------------------------------------------------------------------*\ | ||
165 | * Sends a block of data (unbuffered) | ||
166 | \*-------------------------------------------------------------------------*/ | ||
167 | #define STEPSIZE 8192 | ||
168 | static int sendraw(p_buffer buf, const char *data, size_t count, size_t *sent) { | ||
169 | p_io io = buf->io; | ||
170 | p_timeout tm = buf->tm; | ||
171 | size_t total = 0; | ||
172 | int err = IO_DONE; | ||
173 | while (total < count && err == IO_DONE) { | ||
174 | size_t done = 0; | ||
175 | size_t step = (count-total <= STEPSIZE)? count-total: STEPSIZE; | ||
176 | err = io->send(io->ctx, data+total, step, &done, tm); | ||
177 | total += done; | ||
178 | } | ||
179 | *sent = total; | ||
180 | buf->sent += total; | ||
181 | return err; | ||
182 | } | ||
183 | |||
184 | /*-------------------------------------------------------------------------*\ | ||
185 | * Reads a fixed number of bytes (buffered) | ||
186 | \*-------------------------------------------------------------------------*/ | ||
187 | static int recvraw(p_buffer buf, size_t wanted, luaL_Buffer *b) { | ||
188 | int err = IO_DONE; | ||
189 | size_t total = 0; | ||
190 | while (err == IO_DONE) { | ||
191 | size_t count; const char *data; | ||
192 | err = buffer_get(buf, &data, &count); | ||
193 | count = MIN(count, wanted - total); | ||
194 | luaL_addlstring(b, data, count); | ||
195 | buffer_skip(buf, count); | ||
196 | total += count; | ||
197 | if (total >= wanted) break; | ||
198 | } | ||
199 | return err; | ||
200 | } | ||
201 | |||
202 | /*-------------------------------------------------------------------------*\ | ||
203 | * Reads everything until the connection is closed (buffered) | ||
204 | \*-------------------------------------------------------------------------*/ | ||
205 | static int recvall(p_buffer buf, luaL_Buffer *b) { | ||
206 | int err = IO_DONE; | ||
207 | size_t total = 0; | ||
208 | while (err == IO_DONE) { | ||
209 | const char *data; size_t count; | ||
210 | err = buffer_get(buf, &data, &count); | ||
211 | total += count; | ||
212 | luaL_addlstring(b, data, count); | ||
213 | buffer_skip(buf, count); | ||
214 | } | ||
215 | if (err == IO_CLOSED) { | ||
216 | if (total > 0) return IO_DONE; | ||
217 | else return IO_CLOSED; | ||
218 | } else return err; | ||
219 | } | ||
220 | |||
221 | /*-------------------------------------------------------------------------*\ | ||
222 | * Reads a line terminated by a CR LF pair or just by a LF. The CR and LF | ||
223 | * are not returned by the function and are discarded from the buffer | ||
224 | \*-------------------------------------------------------------------------*/ | ||
225 | static int recvline(p_buffer buf, luaL_Buffer *b) { | ||
226 | int err = IO_DONE; | ||
227 | while (err == IO_DONE) { | ||
228 | size_t count, pos; const char *data; | ||
229 | err = buffer_get(buf, &data, &count); | ||
230 | pos = 0; | ||
231 | while (pos < count && data[pos] != '\n') { | ||
232 | /* we ignore all \r's */ | ||
233 | if (data[pos] != '\r') luaL_addchar(b, data[pos]); | ||
234 | pos++; | ||
235 | } | ||
236 | if (pos < count) { /* found '\n' */ | ||
237 | buffer_skip(buf, pos+1); /* skip '\n' too */ | ||
238 | break; /* we are done */ | ||
239 | } else /* reached the end of the buffer */ | ||
240 | buffer_skip(buf, pos); | ||
241 | } | ||
242 | return err; | ||
243 | } | ||
244 | |||
245 | /*-------------------------------------------------------------------------*\ | ||
246 | * Skips a given number of bytes from read buffer. No data is read from the | ||
247 | * transport layer | ||
248 | \*-------------------------------------------------------------------------*/ | ||
249 | static void buffer_skip(p_buffer buf, size_t count) { | ||
250 | buf->received += count; | ||
251 | buf->first += count; | ||
252 | if (buffer_isempty(buf)) | ||
253 | buf->first = buf->last = 0; | ||
254 | } | ||
255 | |||
256 | /*-------------------------------------------------------------------------*\ | ||
257 | * Return any data available in buffer, or get more data from transport layer | ||
258 | * if buffer is empty | ||
259 | \*-------------------------------------------------------------------------*/ | ||
260 | static int buffer_get(p_buffer buf, const char **data, size_t *count) { | ||
261 | int err = IO_DONE; | ||
262 | p_io io = buf->io; | ||
263 | p_timeout tm = buf->tm; | ||
264 | if (buffer_isempty(buf)) { | ||
265 | size_t got; | ||
266 | err = io->recv(io->ctx, buf->data, BUF_SIZE, &got, tm); | ||
267 | buf->first = 0; | ||
268 | buf->last = got; | ||
269 | } | ||
270 | *count = buf->last - buf->first; | ||
271 | *data = buf->data + buf->first; | ||
272 | return err; | ||
273 | } | ||
diff --git a/vendor/luasocket/src/buffer.h b/vendor/luasocket/src/buffer.h new file mode 100644 index 00000000..a0901fcc --- /dev/null +++ b/vendor/luasocket/src/buffer.h | |||
@@ -0,0 +1,52 @@ | |||
1 | #ifndef BUF_H | ||
2 | #define BUF_H | ||
3 | /*=========================================================================*\ | ||
4 | * Input/Output interface for Lua programs | ||
5 | * LuaSocket toolkit | ||
6 | * | ||
7 | * Line patterns require buffering. Reading one character at a time involves | ||
8 | * too many system calls and is very slow. This module implements the | ||
9 | * LuaSocket interface for input/output on connected objects, as seen by | ||
10 | * Lua programs. | ||
11 | * | ||
12 | * Input is buffered. Output is *not* buffered because there was no simple | ||
13 | * way of making sure the buffered output data would ever be sent. | ||
14 | * | ||
15 | * The module is built on top of the I/O abstraction defined in io.h and the | ||
16 | * timeout management is done with the timeout.h interface. | ||
17 | \*=========================================================================*/ | ||
18 | #include "luasocket.h" | ||
19 | #include "io.h" | ||
20 | #include "timeout.h" | ||
21 | |||
22 | /* buffer size in bytes */ | ||
23 | #define BUF_SIZE 8192 | ||
24 | |||
25 | /* buffer control structure */ | ||
26 | typedef struct t_buffer_ { | ||
27 | double birthday; /* throttle support info: creation time, */ | ||
28 | size_t sent, received; /* bytes sent, and bytes received */ | ||
29 | p_io io; /* IO driver used for this buffer */ | ||
30 | p_timeout tm; /* timeout management for this buffer */ | ||
31 | size_t first, last; /* index of first and last bytes of stored data */ | ||
32 | char data[BUF_SIZE]; /* storage space for buffer data */ | ||
33 | } t_buffer; | ||
34 | typedef t_buffer *p_buffer; | ||
35 | |||
36 | #ifndef _WIN32 | ||
37 | #pragma GCC visibility push(hidden) | ||
38 | #endif | ||
39 | |||
40 | int buffer_open(lua_State *L); | ||
41 | void buffer_init(p_buffer buf, p_io io, p_timeout tm); | ||
42 | int buffer_meth_getstats(lua_State *L, p_buffer buf); | ||
43 | int buffer_meth_setstats(lua_State *L, p_buffer buf); | ||
44 | int buffer_meth_send(lua_State *L, p_buffer buf); | ||
45 | int buffer_meth_receive(lua_State *L, p_buffer buf); | ||
46 | int buffer_isempty(p_buffer buf); | ||
47 | |||
48 | #ifndef _WIN32 | ||
49 | #pragma GCC visibility pop | ||
50 | #endif | ||
51 | |||
52 | #endif /* BUF_H */ | ||
diff --git a/vendor/luasocket/src/compat.c b/vendor/luasocket/src/compat.c new file mode 100644 index 00000000..34ffdaf7 --- /dev/null +++ b/vendor/luasocket/src/compat.c | |||
@@ -0,0 +1,39 @@ | |||
1 | #include "luasocket.h" | ||
2 | #include "compat.h" | ||
3 | |||
4 | #if LUA_VERSION_NUM==501 | ||
5 | |||
6 | /* | ||
7 | ** Adapted from Lua 5.2 | ||
8 | */ | ||
9 | void luasocket_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { | ||
10 | luaL_checkstack(L, nup+1, "too many upvalues"); | ||
11 | for (; l->name != NULL; l++) { /* fill the table with given functions */ | ||
12 | int i; | ||
13 | lua_pushstring(L, l->name); | ||
14 | for (i = 0; i < nup; i++) /* copy upvalues to the top */ | ||
15 | lua_pushvalue(L, -(nup+1)); | ||
16 | lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ | ||
17 | lua_settable(L, -(nup + 3)); | ||
18 | } | ||
19 | lua_pop(L, nup); /* remove upvalues */ | ||
20 | } | ||
21 | |||
22 | /* | ||
23 | ** Duplicated from Lua 5.2 | ||
24 | */ | ||
25 | void *luasocket_testudata (lua_State *L, int ud, const char *tname) { | ||
26 | void *p = lua_touserdata(L, ud); | ||
27 | if (p != NULL) { /* value is a userdata? */ | ||
28 | if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ | ||
29 | luaL_getmetatable(L, tname); /* get correct metatable */ | ||
30 | if (!lua_rawequal(L, -1, -2)) /* not the same? */ | ||
31 | p = NULL; /* value is a userdata with wrong metatable */ | ||
32 | lua_pop(L, 2); /* remove both metatables */ | ||
33 | return p; | ||
34 | } | ||
35 | } | ||
36 | return NULL; /* value is not a userdata with a metatable */ | ||
37 | } | ||
38 | |||
39 | #endif | ||
diff --git a/vendor/luasocket/src/compat.h b/vendor/luasocket/src/compat.h new file mode 100644 index 00000000..fa2d7d7c --- /dev/null +++ b/vendor/luasocket/src/compat.h | |||
@@ -0,0 +1,22 @@ | |||
1 | #ifndef COMPAT_H | ||
2 | #define COMPAT_H | ||
3 | |||
4 | #if LUA_VERSION_NUM==501 | ||
5 | |||
6 | #ifndef _WIN32 | ||
7 | #pragma GCC visibility push(hidden) | ||
8 | #endif | ||
9 | |||
10 | void luasocket_setfuncs (lua_State *L, const luaL_Reg *l, int nup); | ||
11 | void *luasocket_testudata ( lua_State *L, int arg, const char *tname); | ||
12 | |||
13 | #ifndef _WIN32 | ||
14 | #pragma GCC visibility pop | ||
15 | #endif | ||
16 | |||
17 | #define luaL_setfuncs luasocket_setfuncs | ||
18 | #define luaL_testudata luasocket_testudata | ||
19 | |||
20 | #endif | ||
21 | |||
22 | #endif | ||
diff --git a/vendor/luasocket/src/except.c b/vendor/luasocket/src/except.c new file mode 100644 index 00000000..9c3317f2 --- /dev/null +++ b/vendor/luasocket/src/except.c | |||
@@ -0,0 +1,129 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * Simple exception support | ||
3 | * LuaSocket toolkit | ||
4 | \*=========================================================================*/ | ||
5 | #include "luasocket.h" | ||
6 | #include "except.h" | ||
7 | #include <stdio.h> | ||
8 | |||
9 | #if LUA_VERSION_NUM < 502 | ||
10 | #define lua_pcallk(L, na, nr, err, ctx, cont) \ | ||
11 | (((void)ctx),((void)cont),lua_pcall(L, na, nr, err)) | ||
12 | #endif | ||
13 | |||
14 | #if LUA_VERSION_NUM < 503 | ||
15 | typedef int lua_KContext; | ||
16 | #endif | ||
17 | |||
18 | /*=========================================================================*\ | ||
19 | * Internal function prototypes. | ||
20 | \*=========================================================================*/ | ||
21 | static int global_protect(lua_State *L); | ||
22 | static int global_newtry(lua_State *L); | ||
23 | static int protected_(lua_State *L); | ||
24 | static int finalize(lua_State *L); | ||
25 | static int do_nothing(lua_State *L); | ||
26 | |||
27 | /* except functions */ | ||
28 | static luaL_Reg func[] = { | ||
29 | {"newtry", global_newtry}, | ||
30 | {"protect", global_protect}, | ||
31 | {NULL, NULL} | ||
32 | }; | ||
33 | |||
34 | /*-------------------------------------------------------------------------*\ | ||
35 | * Try factory | ||
36 | \*-------------------------------------------------------------------------*/ | ||
37 | static void wrap(lua_State *L) { | ||
38 | lua_createtable(L, 1, 0); | ||
39 | lua_pushvalue(L, -2); | ||
40 | lua_rawseti(L, -2, 1); | ||
41 | lua_pushvalue(L, lua_upvalueindex(1)); | ||
42 | lua_setmetatable(L, -2); | ||
43 | } | ||
44 | |||
45 | static int finalize(lua_State *L) { | ||
46 | if (!lua_toboolean(L, 1)) { | ||
47 | lua_pushvalue(L, lua_upvalueindex(2)); | ||
48 | lua_call(L, 0, 0); | ||
49 | lua_settop(L, 2); | ||
50 | wrap(L); | ||
51 | lua_error(L); | ||
52 | return 0; | ||
53 | } else return lua_gettop(L); | ||
54 | } | ||
55 | |||
56 | static int do_nothing(lua_State *L) { | ||
57 | (void) L; | ||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | static int global_newtry(lua_State *L) { | ||
62 | lua_settop(L, 1); | ||
63 | if (lua_isnil(L, 1)) lua_pushcfunction(L, do_nothing); | ||
64 | lua_pushvalue(L, lua_upvalueindex(1)); | ||
65 | lua_insert(L, -2); | ||
66 | lua_pushcclosure(L, finalize, 2); | ||
67 | return 1; | ||
68 | } | ||
69 | |||
70 | /*-------------------------------------------------------------------------*\ | ||
71 | * Protect factory | ||
72 | \*-------------------------------------------------------------------------*/ | ||
73 | static int unwrap(lua_State *L) { | ||
74 | if (lua_istable(L, -1) && lua_getmetatable(L, -1)) { | ||
75 | int r = lua_rawequal(L, -1, lua_upvalueindex(1)); | ||
76 | lua_pop(L, 1); | ||
77 | if (r) { | ||
78 | lua_pushnil(L); | ||
79 | lua_rawgeti(L, -2, 1); | ||
80 | return 1; | ||
81 | } | ||
82 | } | ||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static int protected_finish(lua_State *L, int status, lua_KContext ctx) { | ||
87 | (void)ctx; | ||
88 | if (status != 0 && status != LUA_YIELD) { | ||
89 | if (unwrap(L)) return 2; | ||
90 | else return lua_error(L); | ||
91 | } else return lua_gettop(L); | ||
92 | } | ||
93 | |||
94 | #if LUA_VERSION_NUM == 502 | ||
95 | static int protected_cont(lua_State *L) { | ||
96 | int ctx = 0; | ||
97 | int status = lua_getctx(L, &ctx); | ||
98 | return protected_finish(L, status, ctx); | ||
99 | } | ||
100 | #else | ||
101 | #define protected_cont protected_finish | ||
102 | #endif | ||
103 | |||
104 | static int protected_(lua_State *L) { | ||
105 | int status; | ||
106 | lua_pushvalue(L, lua_upvalueindex(2)); | ||
107 | lua_insert(L, 1); | ||
108 | status = lua_pcallk(L, lua_gettop(L) - 1, LUA_MULTRET, 0, 0, protected_cont); | ||
109 | return protected_finish(L, status, 0); | ||
110 | } | ||
111 | |||
112 | static int global_protect(lua_State *L) { | ||
113 | lua_settop(L, 1); | ||
114 | lua_pushvalue(L, lua_upvalueindex(1)); | ||
115 | lua_insert(L, 1); | ||
116 | lua_pushcclosure(L, protected_, 2); | ||
117 | return 1; | ||
118 | } | ||
119 | |||
120 | /*-------------------------------------------------------------------------*\ | ||
121 | * Init module | ||
122 | \*-------------------------------------------------------------------------*/ | ||
123 | int except_open(lua_State *L) { | ||
124 | lua_newtable(L); /* metatable for wrapped exceptions */ | ||
125 | lua_pushboolean(L, 0); | ||
126 | lua_setfield(L, -2, "__metatable"); | ||
127 | luaL_setfuncs(L, func, 1); | ||
128 | return 0; | ||
129 | } | ||
diff --git a/vendor/luasocket/src/except.h b/vendor/luasocket/src/except.h new file mode 100644 index 00000000..71c31fd4 --- /dev/null +++ b/vendor/luasocket/src/except.h | |||
@@ -0,0 +1,46 @@ | |||
1 | #ifndef EXCEPT_H | ||
2 | #define EXCEPT_H | ||
3 | /*=========================================================================*\ | ||
4 | * Exception control | ||
5 | * LuaSocket toolkit (but completely independent from other modules) | ||
6 | * | ||
7 | * This provides support for simple exceptions in Lua. During the | ||
8 | * development of the HTTP/FTP/SMTP support, it became aparent that | ||
9 | * error checking was taking a substantial amount of the coding. These | ||
10 | * function greatly simplify the task of checking errors. | ||
11 | * | ||
12 | * The main idea is that functions should return nil as their first return | ||
13 | * values when they find an error, and return an error message (or value) | ||
14 | * following nil. In case of success, as long as the first value is not nil, | ||
15 | * the other values don't matter. | ||
16 | * | ||
17 | * The idea is to nest function calls with the "try" function. This function | ||
18 | * checks the first value, and, if it's falsy, wraps the second value in a | ||
19 | * table with metatable and calls "error" on it. Otherwise, it returns all | ||
20 | * values it received. Basically, it works like the Lua "assert" function, | ||
21 | * but it creates errors targeted specifically at "protect". | ||
22 | * | ||
23 | * The "newtry" function is a factory for "try" functions that call a | ||
24 | * finalizer in protected mode before calling "error". | ||
25 | * | ||
26 | * The "protect" function returns a new function that behaves exactly like | ||
27 | * the function it receives, but the new function catches exceptions thrown | ||
28 | * by "try" functions and returns nil followed by the error message instead. | ||
29 | * | ||
30 | * With these three functions, it's easy to write functions that throw | ||
31 | * exceptions on error, but that don't interrupt the user script. | ||
32 | \*=========================================================================*/ | ||
33 | |||
34 | #include "luasocket.h" | ||
35 | |||
36 | #ifndef _WIN32 | ||
37 | #pragma GCC visibility push(hidden) | ||
38 | #endif | ||
39 | |||
40 | int except_open(lua_State *L); | ||
41 | |||
42 | #ifndef _WIN32 | ||
43 | #pragma GCC visibility pop | ||
44 | #endif | ||
45 | |||
46 | #endif | ||
diff --git a/vendor/luasocket/src/ftp.lua b/vendor/luasocket/src/ftp.lua new file mode 100644 index 00000000..0ebc5086 --- /dev/null +++ b/vendor/luasocket/src/ftp.lua | |||
@@ -0,0 +1,329 @@ | |||
1 | ----------------------------------------------------------------------------- | ||
2 | -- FTP support for the Lua language | ||
3 | -- LuaSocket toolkit. | ||
4 | -- Author: Diego Nehab | ||
5 | ----------------------------------------------------------------------------- | ||
6 | |||
7 | ----------------------------------------------------------------------------- | ||
8 | -- Declare module and import dependencies | ||
9 | ----------------------------------------------------------------------------- | ||
10 | local base = _G | ||
11 | local table = require("table") | ||
12 | local string = require("string") | ||
13 | local math = require("math") | ||
14 | local socket = require("socket") | ||
15 | local url = require("socket.url") | ||
16 | local tp = require("socket.tp") | ||
17 | local ltn12 = require("ltn12") | ||
18 | socket.ftp = {} | ||
19 | local _M = socket.ftp | ||
20 | ----------------------------------------------------------------------------- | ||
21 | -- Program constants | ||
22 | ----------------------------------------------------------------------------- | ||
23 | -- timeout in seconds before the program gives up on a connection | ||
24 | _M.TIMEOUT = 60 | ||
25 | -- default port for ftp service | ||
26 | local PORT = 21 | ||
27 | -- this is the default anonymous password. used when no password is | ||
28 | -- provided in url. should be changed to your e-mail. | ||
29 | _M.USER = "ftp" | ||
30 | _M.PASSWORD = "anonymous@anonymous.org" | ||
31 | |||
32 | ----------------------------------------------------------------------------- | ||
33 | -- Low level FTP API | ||
34 | ----------------------------------------------------------------------------- | ||
35 | local metat = { __index = {} } | ||
36 | |||
37 | function _M.open(server, port, create) | ||
38 | local tp = socket.try(tp.connect(server, port or PORT, _M.TIMEOUT, create)) | ||
39 | local f = base.setmetatable({ tp = tp }, metat) | ||
40 | -- make sure everything gets closed in an exception | ||
41 | f.try = socket.newtry(function() f:close() end) | ||
42 | return f | ||
43 | end | ||
44 | |||
45 | function metat.__index:portconnect() | ||
46 | self.try(self.server:settimeout(_M.TIMEOUT)) | ||
47 | self.data = self.try(self.server:accept()) | ||
48 | self.try(self.data:settimeout(_M.TIMEOUT)) | ||
49 | end | ||
50 | |||
51 | function metat.__index:pasvconnect() | ||
52 | self.data = self.try(socket.tcp()) | ||
53 | self.try(self.data:settimeout(_M.TIMEOUT)) | ||
54 | self.try(self.data:connect(self.pasvt.address, self.pasvt.port)) | ||
55 | end | ||
56 | |||
57 | function metat.__index:login(user, password) | ||
58 | self.try(self.tp:command("user", user or _M.USER)) | ||
59 | local code, _ = self.try(self.tp:check{"2..", 331}) | ||
60 | if code == 331 then | ||
61 | self.try(self.tp:command("pass", password or _M.PASSWORD)) | ||
62 | self.try(self.tp:check("2..")) | ||
63 | end | ||
64 | return 1 | ||
65 | end | ||
66 | |||
67 | function metat.__index:pasv() | ||
68 | self.try(self.tp:command("pasv")) | ||
69 | local _, reply = self.try(self.tp:check("2..")) | ||
70 | local pattern = "(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)" | ||
71 | local a, b, c, d, p1, p2 = socket.skip(2, string.find(reply, pattern)) | ||
72 | self.try(a and b and c and d and p1 and p2, reply) | ||
73 | self.pasvt = { | ||
74 | address = string.format("%d.%d.%d.%d", a, b, c, d), | ||
75 | port = p1*256 + p2 | ||
76 | } | ||
77 | if self.server then | ||
78 | self.server:close() | ||
79 | self.server = nil | ||
80 | end | ||
81 | return self.pasvt.address, self.pasvt.port | ||
82 | end | ||
83 | |||
84 | function metat.__index:epsv() | ||
85 | self.try(self.tp:command("epsv")) | ||
86 | local _, reply = self.try(self.tp:check("229")) | ||
87 | local pattern = "%((.)(.-)%1(.-)%1(.-)%1%)" | ||
88 | local _, _, _, port = string.match(reply, pattern) | ||
89 | self.try(port, "invalid epsv response") | ||
90 | self.pasvt = { | ||
91 | address = self.tp:getpeername(), | ||
92 | port = port | ||
93 | } | ||
94 | if self.server then | ||
95 | self.server:close() | ||
96 | self.server = nil | ||
97 | end | ||
98 | return self.pasvt.address, self.pasvt.port | ||
99 | end | ||
100 | |||
101 | |||
102 | function metat.__index:port(address, port) | ||
103 | self.pasvt = nil | ||
104 | if not address then | ||
105 | address = self.try(self.tp:getsockname()) | ||
106 | self.server = self.try(socket.bind(address, 0)) | ||
107 | address, port = self.try(self.server:getsockname()) | ||
108 | self.try(self.server:settimeout(_M.TIMEOUT)) | ||
109 | end | ||
110 | local pl = math.mod(port, 256) | ||
111 | local ph = (port - pl)/256 | ||
112 | local arg = string.gsub(string.format("%s,%d,%d", address, ph, pl), "%.", ",") | ||
113 | self.try(self.tp:command("port", arg)) | ||
114 | self.try(self.tp:check("2..")) | ||
115 | return 1 | ||
116 | end | ||
117 | |||
118 | function metat.__index:eprt(family, address, port) | ||
119 | self.pasvt = nil | ||
120 | if not address then | ||
121 | address = self.try(self.tp:getsockname()) | ||
122 | self.server = self.try(socket.bind(address, 0)) | ||
123 | address, port = self.try(self.server:getsockname()) | ||
124 | self.try(self.server:settimeout(_M.TIMEOUT)) | ||
125 | end | ||
126 | local arg = string.format("|%s|%s|%d|", family, address, port) | ||
127 | self.try(self.tp:command("eprt", arg)) | ||
128 | self.try(self.tp:check("2..")) | ||
129 | return 1 | ||
130 | end | ||
131 | |||
132 | |||
133 | function metat.__index:send(sendt) | ||
134 | self.try(self.pasvt or self.server, "need port or pasv first") | ||
135 | -- if there is a pasvt table, we already sent a PASV command | ||
136 | -- we just get the data connection into self.data | ||
137 | if self.pasvt then self:pasvconnect() end | ||
138 | -- get the transfer argument and command | ||
139 | local argument = sendt.argument or | ||
140 | url.unescape(string.gsub(sendt.path or "", "^[/\\]", "")) | ||
141 | if argument == "" then argument = nil end | ||
142 | local command = sendt.command or "stor" | ||
143 | -- send the transfer command and check the reply | ||
144 | self.try(self.tp:command(command, argument)) | ||
145 | local code, _ = self.try(self.tp:check{"2..", "1.."}) | ||
146 | -- if there is not a pasvt table, then there is a server | ||
147 | -- and we already sent a PORT command | ||
148 | if not self.pasvt then self:portconnect() end | ||
149 | -- get the sink, source and step for the transfer | ||
150 | local step = sendt.step or ltn12.pump.step | ||
151 | local readt = { self.tp } | ||
152 | local checkstep = function(src, snk) | ||
153 | -- check status in control connection while downloading | ||
154 | local readyt = socket.select(readt, nil, 0) | ||
155 | if readyt[tp] then code = self.try(self.tp:check("2..")) end | ||
156 | return step(src, snk) | ||
157 | end | ||
158 | local sink = socket.sink("close-when-done", self.data) | ||
159 | -- transfer all data and check error | ||
160 | self.try(ltn12.pump.all(sendt.source, sink, checkstep)) | ||
161 | if string.find(code, "1..") then self.try(self.tp:check("2..")) end | ||
162 | -- done with data connection | ||
163 | self.data:close() | ||
164 | -- find out how many bytes were sent | ||
165 | local sent = socket.skip(1, self.data:getstats()) | ||
166 | self.data = nil | ||
167 | return sent | ||
168 | end | ||
169 | |||
170 | function metat.__index:receive(recvt) | ||
171 | self.try(self.pasvt or self.server, "need port or pasv first") | ||
172 | if self.pasvt then self:pasvconnect() end | ||
173 | local argument = recvt.argument or | ||
174 | url.unescape(string.gsub(recvt.path or "", "^[/\\]", "")) | ||
175 | if argument == "" then argument = nil end | ||
176 | local command = recvt.command or "retr" | ||
177 | self.try(self.tp:command(command, argument)) | ||
178 | local code,reply = self.try(self.tp:check{"1..", "2.."}) | ||
179 | if (code >= 200) and (code <= 299) then | ||
180 | recvt.sink(reply) | ||
181 | return 1 | ||
182 | end | ||
183 | if not self.pasvt then self:portconnect() end | ||
184 | local source = socket.source("until-closed", self.data) | ||
185 | local step = recvt.step or ltn12.pump.step | ||
186 | self.try(ltn12.pump.all(source, recvt.sink, step)) | ||
187 | if string.find(code, "1..") then self.try(self.tp:check("2..")) end | ||
188 | self.data:close() | ||
189 | self.data = nil | ||
190 | return 1 | ||
191 | end | ||
192 | |||
193 | function metat.__index:cwd(dir) | ||
194 | self.try(self.tp:command("cwd", dir)) | ||
195 | self.try(self.tp:check(250)) | ||
196 | return 1 | ||
197 | end | ||
198 | |||
199 | function metat.__index:type(type) | ||
200 | self.try(self.tp:command("type", type)) | ||
201 | self.try(self.tp:check(200)) | ||
202 | return 1 | ||
203 | end | ||
204 | |||
205 | function metat.__index:greet() | ||
206 | local code = self.try(self.tp:check{"1..", "2.."}) | ||
207 | if string.find(code, "1..") then self.try(self.tp:check("2..")) end | ||
208 | return 1 | ||
209 | end | ||
210 | |||
211 | function metat.__index:quit() | ||
212 | self.try(self.tp:command("quit")) | ||
213 | self.try(self.tp:check("2..")) | ||
214 | return 1 | ||
215 | end | ||
216 | |||
217 | function metat.__index:close() | ||
218 | if self.data then self.data:close() end | ||
219 | if self.server then self.server:close() end | ||
220 | return self.tp:close() | ||
221 | end | ||
222 | |||
223 | ----------------------------------------------------------------------------- | ||
224 | -- High level FTP API | ||
225 | ----------------------------------------------------------------------------- | ||
226 | local function override(t) | ||
227 | if t.url then | ||
228 | local u = url.parse(t.url) | ||
229 | for i,v in base.pairs(t) do | ||
230 | u[i] = v | ||
231 | end | ||
232 | return u | ||
233 | else return t end | ||
234 | end | ||
235 | |||
236 | local function tput(putt) | ||
237 | putt = override(putt) | ||
238 | socket.try(putt.host, "missing hostname") | ||
239 | local f = _M.open(putt.host, putt.port, putt.create) | ||
240 | f:greet() | ||
241 | f:login(putt.user, putt.password) | ||
242 | if putt.type then f:type(putt.type) end | ||
243 | f:epsv() | ||
244 | local sent = f:send(putt) | ||
245 | f:quit() | ||
246 | f:close() | ||
247 | return sent | ||
248 | end | ||
249 | |||
250 | local default = { | ||
251 | path = "/", | ||
252 | scheme = "ftp" | ||
253 | } | ||
254 | |||
255 | local function genericform(u) | ||
256 | local t = socket.try(url.parse(u, default)) | ||
257 | socket.try(t.scheme == "ftp", "wrong scheme '" .. t.scheme .. "'") | ||
258 | socket.try(t.host, "missing hostname") | ||
259 | local pat = "^type=(.)$" | ||
260 | if t.params then | ||
261 | t.type = socket.skip(2, string.find(t.params, pat)) | ||
262 | socket.try(t.type == "a" or t.type == "i", | ||
263 | "invalid type '" .. t.type .. "'") | ||
264 | end | ||
265 | return t | ||
266 | end | ||
267 | |||
268 | _M.genericform = genericform | ||
269 | |||
270 | local function sput(u, body) | ||
271 | local putt = genericform(u) | ||
272 | putt.source = ltn12.source.string(body) | ||
273 | return tput(putt) | ||
274 | end | ||
275 | |||
276 | _M.put = socket.protect(function(putt, body) | ||
277 | if base.type(putt) == "string" then return sput(putt, body) | ||
278 | else return tput(putt) end | ||
279 | end) | ||
280 | |||
281 | local function tget(gett) | ||
282 | gett = override(gett) | ||
283 | socket.try(gett.host, "missing hostname") | ||
284 | local f = _M.open(gett.host, gett.port, gett.create) | ||
285 | f:greet() | ||
286 | f:login(gett.user, gett.password) | ||
287 | if gett.type then f:type(gett.type) end | ||
288 | f:epsv() | ||
289 | f:receive(gett) | ||
290 | f:quit() | ||
291 | return f:close() | ||
292 | end | ||
293 | |||
294 | local function sget(u) | ||
295 | local gett = genericform(u) | ||
296 | local t = {} | ||
297 | gett.sink = ltn12.sink.table(t) | ||
298 | tget(gett) | ||
299 | return table.concat(t) | ||
300 | end | ||
301 | |||
302 | _M.command = socket.protect(function(cmdt) | ||
303 | cmdt = override(cmdt) | ||
304 | socket.try(cmdt.host, "missing hostname") | ||
305 | socket.try(cmdt.command, "missing command") | ||
306 | local f = _M.open(cmdt.host, cmdt.port, cmdt.create) | ||
307 | f:greet() | ||
308 | f:login(cmdt.user, cmdt.password) | ||
309 | if type(cmdt.command) == "table" then | ||
310 | local argument = cmdt.argument or {} | ||
311 | local check = cmdt.check or {} | ||
312 | for i,cmd in ipairs(cmdt.command) do | ||
313 | f.try(f.tp:command(cmd, argument[i])) | ||
314 | if check[i] then f.try(f.tp:check(check[i])) end | ||
315 | end | ||
316 | else | ||
317 | f.try(f.tp:command(cmdt.command, cmdt.argument)) | ||
318 | if cmdt.check then f.try(f.tp:check(cmdt.check)) end | ||
319 | end | ||
320 | f:quit() | ||
321 | return f:close() | ||
322 | end) | ||
323 | |||
324 | _M.get = socket.protect(function(gett) | ||
325 | if base.type(gett) == "string" then return sget(gett) | ||
326 | else return tget(gett) end | ||
327 | end) | ||
328 | |||
329 | return _M | ||
diff --git a/vendor/luasocket/src/headers.lua b/vendor/luasocket/src/headers.lua new file mode 100644 index 00000000..1eb8223b --- /dev/null +++ b/vendor/luasocket/src/headers.lua | |||
@@ -0,0 +1,104 @@ | |||
1 | ----------------------------------------------------------------------------- | ||
2 | -- Canonic header field capitalization | ||
3 | -- LuaSocket toolkit. | ||
4 | -- Author: Diego Nehab | ||
5 | ----------------------------------------------------------------------------- | ||
6 | local socket = require("socket") | ||
7 | socket.headers = {} | ||
8 | local _M = socket.headers | ||
9 | |||
10 | _M.canonic = { | ||
11 | ["accept"] = "Accept", | ||
12 | ["accept-charset"] = "Accept-Charset", | ||
13 | ["accept-encoding"] = "Accept-Encoding", | ||
14 | ["accept-language"] = "Accept-Language", | ||
15 | ["accept-ranges"] = "Accept-Ranges", | ||
16 | ["action"] = "Action", | ||
17 | ["alternate-recipient"] = "Alternate-Recipient", | ||
18 | ["age"] = "Age", | ||
19 | ["allow"] = "Allow", | ||
20 | ["arrival-date"] = "Arrival-Date", | ||
21 | ["authorization"] = "Authorization", | ||
22 | ["bcc"] = "Bcc", | ||
23 | ["cache-control"] = "Cache-Control", | ||
24 | ["cc"] = "Cc", | ||
25 | ["comments"] = "Comments", | ||
26 | ["connection"] = "Connection", | ||
27 | ["content-description"] = "Content-Description", | ||
28 | ["content-disposition"] = "Content-Disposition", | ||
29 | ["content-encoding"] = "Content-Encoding", | ||
30 | ["content-id"] = "Content-ID", | ||
31 | ["content-language"] = "Content-Language", | ||
32 | ["content-length"] = "Content-Length", | ||
33 | ["content-location"] = "Content-Location", | ||
34 | ["content-md5"] = "Content-MD5", | ||
35 | ["content-range"] = "Content-Range", | ||
36 | ["content-transfer-encoding"] = "Content-Transfer-Encoding", | ||
37 | ["content-type"] = "Content-Type", | ||
38 | ["cookie"] = "Cookie", | ||
39 | ["date"] = "Date", | ||
40 | ["diagnostic-code"] = "Diagnostic-Code", | ||
41 | ["dsn-gateway"] = "DSN-Gateway", | ||
42 | ["etag"] = "ETag", | ||
43 | ["expect"] = "Expect", | ||
44 | ["expires"] = "Expires", | ||
45 | ["final-log-id"] = "Final-Log-ID", | ||
46 | ["final-recipient"] = "Final-Recipient", | ||
47 | ["from"] = "From", | ||
48 | ["host"] = "Host", | ||
49 | ["if-match"] = "If-Match", | ||
50 | ["if-modified-since"] = "If-Modified-Since", | ||
51 | ["if-none-match"] = "If-None-Match", | ||
52 | ["if-range"] = "If-Range", | ||
53 | ["if-unmodified-since"] = "If-Unmodified-Since", | ||
54 | ["in-reply-to"] = "In-Reply-To", | ||
55 | ["keywords"] = "Keywords", | ||
56 | ["last-attempt-date"] = "Last-Attempt-Date", | ||
57 | ["last-modified"] = "Last-Modified", | ||
58 | ["location"] = "Location", | ||
59 | ["max-forwards"] = "Max-Forwards", | ||
60 | ["message-id"] = "Message-ID", | ||
61 | ["mime-version"] = "MIME-Version", | ||
62 | ["original-envelope-id"] = "Original-Envelope-ID", | ||
63 | ["original-recipient"] = "Original-Recipient", | ||
64 | ["pragma"] = "Pragma", | ||
65 | ["proxy-authenticate"] = "Proxy-Authenticate", | ||
66 | ["proxy-authorization"] = "Proxy-Authorization", | ||
67 | ["range"] = "Range", | ||
68 | ["received"] = "Received", | ||
69 | ["received-from-mta"] = "Received-From-MTA", | ||
70 | ["references"] = "References", | ||
71 | ["referer"] = "Referer", | ||
72 | ["remote-mta"] = "Remote-MTA", | ||
73 | ["reply-to"] = "Reply-To", | ||
74 | ["reporting-mta"] = "Reporting-MTA", | ||
75 | ["resent-bcc"] = "Resent-Bcc", | ||
76 | ["resent-cc"] = "Resent-Cc", | ||
77 | ["resent-date"] = "Resent-Date", | ||
78 | ["resent-from"] = "Resent-From", | ||
79 | ["resent-message-id"] = "Resent-Message-ID", | ||
80 | ["resent-reply-to"] = "Resent-Reply-To", | ||
81 | ["resent-sender"] = "Resent-Sender", | ||
82 | ["resent-to"] = "Resent-To", | ||
83 | ["retry-after"] = "Retry-After", | ||
84 | ["return-path"] = "Return-Path", | ||
85 | ["sender"] = "Sender", | ||
86 | ["server"] = "Server", | ||
87 | ["smtp-remote-recipient"] = "SMTP-Remote-Recipient", | ||
88 | ["status"] = "Status", | ||
89 | ["subject"] = "Subject", | ||
90 | ["te"] = "TE", | ||
91 | ["to"] = "To", | ||
92 | ["trailer"] = "Trailer", | ||
93 | ["transfer-encoding"] = "Transfer-Encoding", | ||
94 | ["upgrade"] = "Upgrade", | ||
95 | ["user-agent"] = "User-Agent", | ||
96 | ["vary"] = "Vary", | ||
97 | ["via"] = "Via", | ||
98 | ["warning"] = "Warning", | ||
99 | ["will-retry-until"] = "Will-Retry-Until", | ||
100 | ["www-authenticate"] = "WWW-Authenticate", | ||
101 | ["x-mailer"] = "X-Mailer", | ||
102 | } | ||
103 | |||
104 | return _M \ No newline at end of file | ||
diff --git a/vendor/luasocket/src/http.lua b/vendor/luasocket/src/http.lua new file mode 100644 index 00000000..1330355f --- /dev/null +++ b/vendor/luasocket/src/http.lua | |||
@@ -0,0 +1,424 @@ | |||
1 | ----------------------------------------------------------------------------- | ||
2 | -- HTTP/1.1 client support for the Lua language. | ||
3 | -- LuaSocket toolkit. | ||
4 | -- Author: Diego Nehab | ||
5 | ----------------------------------------------------------------------------- | ||
6 | |||
7 | ----------------------------------------------------------------------------- | ||
8 | -- Declare module and import dependencies | ||
9 | ------------------------------------------------------------------------------- | ||
10 | local socket = require("socket") | ||
11 | local url = require("socket.url") | ||
12 | local ltn12 = require("ltn12") | ||
13 | local mime = require("mime") | ||
14 | local string = require("string") | ||
15 | local headers = require("socket.headers") | ||
16 | local base = _G | ||
17 | local table = require("table") | ||
18 | socket.http = {} | ||
19 | local _M = socket.http | ||
20 | |||
21 | ----------------------------------------------------------------------------- | ||
22 | -- Program constants | ||
23 | ----------------------------------------------------------------------------- | ||
24 | -- connection timeout in seconds | ||
25 | _M.TIMEOUT = 60 | ||
26 | -- user agent field sent in request | ||
27 | _M.USERAGENT = socket._VERSION | ||
28 | |||
29 | -- supported schemes and their particulars | ||
30 | local SCHEMES = { | ||
31 | http = { | ||
32 | port = 80 | ||
33 | , create = function(t) | ||
34 | return socket.tcp end } | ||
35 | , https = { | ||
36 | port = 443 | ||
37 | , create = function(t) | ||
38 | local https = assert( | ||
39 | require("ssl.https"), 'LuaSocket: LuaSec not found') | ||
40 | local tcp = assert( | ||
41 | https.tcp, 'LuaSocket: Function tcp() not available from LuaSec') | ||
42 | return tcp(t) end }} | ||
43 | |||
44 | ----------------------------------------------------------------------------- | ||
45 | -- Reads MIME headers from a connection, unfolding where needed | ||
46 | ----------------------------------------------------------------------------- | ||
47 | local function receiveheaders(sock, headers) | ||
48 | local line, name, value, err | ||
49 | headers = headers or {} | ||
50 | -- get first line | ||
51 | line, err = sock:receive() | ||
52 | if err then return nil, err end | ||
53 | -- headers go until a blank line is found | ||
54 | while line ~= "" do | ||
55 | -- get field-name and value | ||
56 | name, value = socket.skip(2, string.find(line, "^(.-):%s*(.*)")) | ||
57 | if not (name and value) then return nil, "malformed reponse headers" end | ||
58 | name = string.lower(name) | ||
59 | -- get next line (value might be folded) | ||
60 | line, err = sock:receive() | ||
61 | if err then return nil, err end | ||
62 | -- unfold any folded values | ||
63 | while string.find(line, "^%s") do | ||
64 | value = value .. line | ||
65 | line = sock:receive() | ||
66 | if err then return nil, err end | ||
67 | end | ||
68 | -- save pair in table | ||
69 | if headers[name] then headers[name] = headers[name] .. ", " .. value | ||
70 | else headers[name] = value end | ||
71 | end | ||
72 | return headers | ||
73 | end | ||
74 | |||
75 | ----------------------------------------------------------------------------- | ||
76 | -- Extra sources and sinks | ||
77 | ----------------------------------------------------------------------------- | ||
78 | socket.sourcet["http-chunked"] = function(sock, headers) | ||
79 | return base.setmetatable({ | ||
80 | getfd = function() return sock:getfd() end, | ||
81 | dirty = function() return sock:dirty() end | ||
82 | }, { | ||
83 | __call = function() | ||
84 | -- get chunk size, skip extention | ||
85 | local line, err = sock:receive() | ||
86 | if err then return nil, err end | ||
87 | local size = base.tonumber(string.gsub(line, ";.*", ""), 16) | ||
88 | if not size then return nil, "invalid chunk size" end | ||
89 | -- was it the last chunk? | ||
90 | if size > 0 then | ||
91 | -- if not, get chunk and skip terminating CRLF | ||
92 | local chunk, err, _ = sock:receive(size) | ||
93 | if chunk then sock:receive() end | ||
94 | return chunk, err | ||
95 | else | ||
96 | -- if it was, read trailers into headers table | ||
97 | headers, err = receiveheaders(sock, headers) | ||
98 | if not headers then return nil, err end | ||
99 | end | ||
100 | end | ||
101 | }) | ||
102 | end | ||
103 | |||
104 | socket.sinkt["http-chunked"] = function(sock) | ||
105 | return base.setmetatable({ | ||
106 | getfd = function() return sock:getfd() end, | ||
107 | dirty = function() return sock:dirty() end | ||
108 | }, { | ||
109 | __call = function(self, chunk, err) | ||
110 | if not chunk then return sock:send("0\r\n\r\n") end | ||
111 | local size = string.format("%X\r\n", string.len(chunk)) | ||
112 | return sock:send(size .. chunk .. "\r\n") | ||
113 | end | ||
114 | }) | ||
115 | end | ||
116 | |||
117 | ----------------------------------------------------------------------------- | ||
118 | -- Low level HTTP API | ||
119 | ----------------------------------------------------------------------------- | ||
120 | local metat = { __index = {} } | ||
121 | |||
122 | function _M.open(host, port, create) | ||
123 | -- create socket with user connect function, or with default | ||
124 | local c = socket.try(create()) | ||
125 | local h = base.setmetatable({ c = c }, metat) | ||
126 | -- create finalized try | ||
127 | h.try = socket.newtry(function() h:close() end) | ||
128 | -- set timeout before connecting | ||
129 | h.try(c:settimeout(_M.TIMEOUT)) | ||
130 | h.try(c:connect(host, port)) | ||
131 | -- here everything worked | ||
132 | return h | ||
133 | end | ||
134 | |||
135 | function metat.__index:sendrequestline(method, uri) | ||
136 | local reqline = string.format("%s %s HTTP/1.1\r\n", method or "GET", uri) | ||
137 | return self.try(self.c:send(reqline)) | ||
138 | end | ||
139 | |||
140 | function metat.__index:sendheaders(tosend) | ||
141 | local canonic = headers.canonic | ||
142 | local h = "\r\n" | ||
143 | for f, v in base.pairs(tosend) do | ||
144 | h = (canonic[f] or f) .. ": " .. v .. "\r\n" .. h | ||
145 | end | ||
146 | self.try(self.c:send(h)) | ||
147 | return 1 | ||
148 | end | ||
149 | |||
150 | function metat.__index:sendbody(headers, source, step) | ||
151 | source = source or ltn12.source.empty() | ||
152 | step = step or ltn12.pump.step | ||
153 | -- if we don't know the size in advance, send chunked and hope for the best | ||
154 | local mode = "http-chunked" | ||
155 | if headers["content-length"] then mode = "keep-open" end | ||
156 | return self.try(ltn12.pump.all(source, socket.sink(mode, self.c), step)) | ||
157 | end | ||
158 | |||
159 | function metat.__index:receivestatusline() | ||
160 | local status,ec = self.try(self.c:receive(5)) | ||
161 | -- identify HTTP/0.9 responses, which do not contain a status line | ||
162 | -- this is just a heuristic, but is what the RFC recommends | ||
163 | if status ~= "HTTP/" then | ||
164 | if ec == "timeout" then | ||
165 | return 408 | ||
166 | end | ||
167 | return nil, status | ||
168 | end | ||
169 | -- otherwise proceed reading a status line | ||
170 | status = self.try(self.c:receive("*l", status)) | ||
171 | local code = socket.skip(2, string.find(status, "HTTP/%d*%.%d* (%d%d%d)")) | ||
172 | return self.try(base.tonumber(code), status) | ||
173 | end | ||
174 | |||
175 | function metat.__index:receiveheaders() | ||
176 | return self.try(receiveheaders(self.c)) | ||
177 | end | ||
178 | |||
179 | function metat.__index:receivebody(headers, sink, step) | ||
180 | sink = sink or ltn12.sink.null() | ||
181 | step = step or ltn12.pump.step | ||
182 | local length = base.tonumber(headers["content-length"]) | ||
183 | local t = headers["transfer-encoding"] -- shortcut | ||
184 | local mode = "default" -- connection close | ||
185 | if t and t ~= "identity" then mode = "http-chunked" | ||
186 | elseif base.tonumber(headers["content-length"]) then mode = "by-length" end | ||
187 | return self.try(ltn12.pump.all(socket.source(mode, self.c, length), | ||
188 | sink, step)) | ||
189 | end | ||
190 | |||
191 | function metat.__index:receive09body(status, sink, step) | ||
192 | local source = ltn12.source.rewind(socket.source("until-closed", self.c)) | ||
193 | source(status) | ||
194 | return self.try(ltn12.pump.all(source, sink, step)) | ||
195 | end | ||
196 | |||
197 | function metat.__index:close() | ||
198 | return self.c:close() | ||
199 | end | ||
200 | |||
201 | ----------------------------------------------------------------------------- | ||
202 | -- High level HTTP API | ||
203 | ----------------------------------------------------------------------------- | ||
204 | local function adjusturi(reqt) | ||
205 | local u = reqt | ||
206 | -- if there is a proxy, we need the full url. otherwise, just a part. | ||
207 | if not reqt.proxy and not _M.PROXY then | ||
208 | u = { | ||
209 | path = socket.try(reqt.path, "invalid path 'nil'"), | ||
210 | params = reqt.params, | ||
211 | query = reqt.query, | ||
212 | fragment = reqt.fragment | ||
213 | } | ||
214 | end | ||
215 | return url.build(u) | ||
216 | end | ||
217 | |||
218 | local function adjustproxy(reqt) | ||
219 | local proxy = reqt.proxy or _M.PROXY | ||
220 | if proxy then | ||
221 | proxy = url.parse(proxy) | ||
222 | return proxy.host, proxy.port or 3128 | ||
223 | else | ||
224 | return reqt.host, reqt.port | ||
225 | end | ||
226 | end | ||
227 | |||
228 | local function adjustheaders(reqt) | ||
229 | -- default headers | ||
230 | local host = reqt.host | ||
231 | local port = tostring(reqt.port) | ||
232 | if port ~= tostring(SCHEMES[reqt.scheme].port) then | ||
233 | host = host .. ':' .. port end | ||
234 | local lower = { | ||
235 | ["user-agent"] = _M.USERAGENT, | ||
236 | ["host"] = host, | ||
237 | ["connection"] = "close, TE", | ||
238 | ["te"] = "trailers" | ||
239 | } | ||
240 | -- if we have authentication information, pass it along | ||
241 | if reqt.user and reqt.password then | ||
242 | lower["authorization"] = | ||
243 | "Basic " .. (mime.b64(reqt.user .. ":" .. | ||
244 | url.unescape(reqt.password))) | ||
245 | end | ||
246 | -- if we have proxy authentication information, pass it along | ||
247 | local proxy = reqt.proxy or _M.PROXY | ||
248 | if proxy then | ||
249 | proxy = url.parse(proxy) | ||
250 | if proxy.user and proxy.password then | ||
251 | lower["proxy-authorization"] = | ||
252 | "Basic " .. (mime.b64(proxy.user .. ":" .. proxy.password)) | ||
253 | end | ||
254 | end | ||
255 | -- override with user headers | ||
256 | for i,v in base.pairs(reqt.headers or lower) do | ||
257 | lower[string.lower(i)] = v | ||
258 | end | ||
259 | return lower | ||
260 | end | ||
261 | |||
262 | -- default url parts | ||
263 | local default = { | ||
264 | path ="/" | ||
265 | , scheme = "http" | ||
266 | } | ||
267 | |||
268 | local function adjustrequest(reqt) | ||
269 | -- parse url if provided | ||
270 | local nreqt = reqt.url and url.parse(reqt.url, default) or {} | ||
271 | -- explicit components override url | ||
272 | for i,v in base.pairs(reqt) do nreqt[i] = v end | ||
273 | -- default to scheme particulars | ||
274 | local schemedefs, host, port, method | ||
275 | = SCHEMES[nreqt.scheme], nreqt.host, nreqt.port, nreqt.method | ||
276 | if not nreqt.create then nreqt.create = schemedefs.create(nreqt) end | ||
277 | if not (port and port ~= '') then nreqt.port = schemedefs.port end | ||
278 | if not (method and method ~= '') then nreqt.method = 'GET' end | ||
279 | if not (host and host ~= "") then | ||
280 | socket.try(nil, "invalid host '" .. base.tostring(nreqt.host) .. "'") | ||
281 | end | ||
282 | -- compute uri if user hasn't overriden | ||
283 | nreqt.uri = reqt.uri or adjusturi(nreqt) | ||
284 | -- adjust headers in request | ||
285 | nreqt.headers = adjustheaders(nreqt) | ||
286 | if nreqt.source | ||
287 | and not nreqt.headers["content-length"] | ||
288 | and not nreqt.headers["transfer-encoding"] | ||
289 | then | ||
290 | nreqt.headers["transfer-encoding"] = "chunked" | ||
291 | end | ||
292 | |||
293 | -- ajust host and port if there is a proxy | ||
294 | nreqt.host, nreqt.port = adjustproxy(nreqt) | ||
295 | return nreqt | ||
296 | end | ||
297 | |||
298 | local function shouldredirect(reqt, code, headers) | ||
299 | local location = headers.location | ||
300 | if not location then return false end | ||
301 | location = string.gsub(location, "%s", "") | ||
302 | if location == "" then return false end | ||
303 | local scheme = url.parse(location).scheme | ||
304 | if scheme and (not SCHEMES[scheme]) then return false end | ||
305 | -- avoid https downgrades | ||
306 | if ('https' == reqt.scheme) and ('https' ~= scheme) then return false end | ||
307 | return (reqt.redirect ~= false) and | ||
308 | (code == 301 or code == 302 or code == 303 or code == 307) and | ||
309 | (not reqt.method or reqt.method == "GET" or reqt.method == "HEAD") | ||
310 | and ((false == reqt.maxredirects) | ||
311 | or ((reqt.nredirects or 0) | ||
312 | < (reqt.maxredirects or 5))) | ||
313 | end | ||
314 | |||
315 | local function shouldreceivebody(reqt, code) | ||
316 | if reqt.method == "HEAD" then return nil end | ||
317 | if code == 204 or code == 304 then return nil end | ||
318 | if code >= 100 and code < 200 then return nil end | ||
319 | return 1 | ||
320 | end | ||
321 | |||
322 | -- forward declarations | ||
323 | local trequest, tredirect | ||
324 | |||
325 | --[[local]] function tredirect(reqt, location) | ||
326 | -- the RFC says the redirect URL has to be absolute, but some | ||
327 | -- servers do not respect that | ||
328 | local newurl = url.absolute(reqt.url, location) | ||
329 | -- if switching schemes, reset port and create function | ||
330 | if url.parse(newurl).scheme ~= reqt.scheme then | ||
331 | reqt.port = nil | ||
332 | reqt.create = nil end | ||
333 | -- make new request | ||
334 | local result, code, headers, status = trequest { | ||
335 | url = newurl, | ||
336 | source = reqt.source, | ||
337 | sink = reqt.sink, | ||
338 | headers = reqt.headers, | ||
339 | proxy = reqt.proxy, | ||
340 | maxredirects = reqt.maxredirects, | ||
341 | nredirects = (reqt.nredirects or 0) + 1, | ||
342 | create = reqt.create | ||
343 | } | ||
344 | -- pass location header back as a hint we redirected | ||
345 | headers = headers or {} | ||
346 | headers.location = headers.location or location | ||
347 | return result, code, headers, status | ||
348 | end | ||
349 | |||
350 | --[[local]] function trequest(reqt) | ||
351 | -- we loop until we get what we want, or | ||
352 | -- until we are sure there is no way to get it | ||
353 | local nreqt = adjustrequest(reqt) | ||
354 | local h = _M.open(nreqt.host, nreqt.port, nreqt.create) | ||
355 | -- send request line and headers | ||
356 | h:sendrequestline(nreqt.method, nreqt.uri) | ||
357 | h:sendheaders(nreqt.headers) | ||
358 | -- if there is a body, send it | ||
359 | if nreqt.source then | ||
360 | h:sendbody(nreqt.headers, nreqt.source, nreqt.step) | ||
361 | end | ||
362 | local code, status = h:receivestatusline() | ||
363 | -- if it is an HTTP/0.9 server, simply get the body and we are done | ||
364 | if not code then | ||
365 | h:receive09body(status, nreqt.sink, nreqt.step) | ||
366 | return 1, 200 | ||
367 | elseif code == 408 then | ||
368 | return 1, code | ||
369 | end | ||
370 | local headers | ||
371 | -- ignore any 100-continue messages | ||
372 | while code == 100 do | ||
373 | h:receiveheaders() | ||
374 | code, status = h:receivestatusline() | ||
375 | end | ||
376 | headers = h:receiveheaders() | ||
377 | -- at this point we should have a honest reply from the server | ||
378 | -- we can't redirect if we already used the source, so we report the error | ||
379 | if shouldredirect(nreqt, code, headers) and not nreqt.source then | ||
380 | h:close() | ||
381 | return tredirect(reqt, headers.location) | ||
382 | end | ||
383 | -- here we are finally done | ||
384 | if shouldreceivebody(nreqt, code) then | ||
385 | h:receivebody(headers, nreqt.sink, nreqt.step) | ||
386 | end | ||
387 | h:close() | ||
388 | return 1, code, headers, status | ||
389 | end | ||
390 | |||
391 | -- turns an url and a body into a generic request | ||
392 | local function genericform(u, b) | ||
393 | local t = {} | ||
394 | local reqt = { | ||
395 | url = u, | ||
396 | sink = ltn12.sink.table(t), | ||
397 | target = t | ||
398 | } | ||
399 | if b then | ||
400 | reqt.source = ltn12.source.string(b) | ||
401 | reqt.headers = { | ||
402 | ["content-length"] = string.len(b), | ||
403 | ["content-type"] = "application/x-www-form-urlencoded" | ||
404 | } | ||
405 | reqt.method = "POST" | ||
406 | end | ||
407 | return reqt | ||
408 | end | ||
409 | |||
410 | _M.genericform = genericform | ||
411 | |||
412 | local function srequest(u, b) | ||
413 | local reqt = genericform(u, b) | ||
414 | local _, code, headers, status = trequest(reqt) | ||
415 | return table.concat(reqt.target), code, headers, status | ||
416 | end | ||
417 | |||
418 | _M.request = socket.protect(function(reqt, body) | ||
419 | if base.type(reqt) == "string" then return srequest(reqt, body) | ||
420 | else return trequest(reqt) end | ||
421 | end) | ||
422 | |||
423 | _M.schemes = SCHEMES | ||
424 | return _M | ||
diff --git a/vendor/luasocket/src/inet.c b/vendor/luasocket/src/inet.c new file mode 100755 index 00000000..138c9abe --- /dev/null +++ b/vendor/luasocket/src/inet.c | |||
@@ -0,0 +1,537 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * Internet domain functions | ||
3 | * LuaSocket toolkit | ||
4 | \*=========================================================================*/ | ||
5 | #include "luasocket.h" | ||
6 | #include "inet.h" | ||
7 | |||
8 | #include <stdio.h> | ||
9 | #include <stdlib.h> | ||
10 | #include <string.h> | ||
11 | |||
12 | /*=========================================================================*\ | ||
13 | * Internal function prototypes. | ||
14 | \*=========================================================================*/ | ||
15 | static int inet_global_toip(lua_State *L); | ||
16 | static int inet_global_getaddrinfo(lua_State *L); | ||
17 | static int inet_global_tohostname(lua_State *L); | ||
18 | static int inet_global_getnameinfo(lua_State *L); | ||
19 | static void inet_pushresolved(lua_State *L, struct hostent *hp); | ||
20 | static int inet_global_gethostname(lua_State *L); | ||
21 | |||
22 | /* DNS functions */ | ||
23 | static luaL_Reg func[] = { | ||
24 | { "toip", inet_global_toip}, | ||
25 | { "getaddrinfo", inet_global_getaddrinfo}, | ||
26 | { "tohostname", inet_global_tohostname}, | ||
27 | { "getnameinfo", inet_global_getnameinfo}, | ||
28 | { "gethostname", inet_global_gethostname}, | ||
29 | { NULL, NULL} | ||
30 | }; | ||
31 | |||
32 | /*-------------------------------------------------------------------------*\ | ||
33 | * Initializes module | ||
34 | \*-------------------------------------------------------------------------*/ | ||
35 | int inet_open(lua_State *L) | ||
36 | { | ||
37 | lua_pushstring(L, "dns"); | ||
38 | lua_newtable(L); | ||
39 | luaL_setfuncs(L, func, 0); | ||
40 | lua_settable(L, -3); | ||
41 | return 0; | ||
42 | } | ||
43 | |||
44 | /*=========================================================================*\ | ||
45 | * Global Lua functions | ||
46 | \*=========================================================================*/ | ||
47 | /*-------------------------------------------------------------------------*\ | ||
48 | * Returns all information provided by the resolver given a host name | ||
49 | * or ip address | ||
50 | \*-------------------------------------------------------------------------*/ | ||
51 | static int inet_gethost(const char *address, struct hostent **hp) { | ||
52 | struct in_addr addr; | ||
53 | if (inet_aton(address, &addr)) | ||
54 | return socket_gethostbyaddr((char *) &addr, sizeof(addr), hp); | ||
55 | else | ||
56 | return socket_gethostbyname(address, hp); | ||
57 | } | ||
58 | |||
59 | /*-------------------------------------------------------------------------*\ | ||
60 | * Returns all information provided by the resolver given a host name | ||
61 | * or ip address | ||
62 | \*-------------------------------------------------------------------------*/ | ||
63 | static int inet_global_tohostname(lua_State *L) { | ||
64 | const char *address = luaL_checkstring(L, 1); | ||
65 | struct hostent *hp = NULL; | ||
66 | int err = inet_gethost(address, &hp); | ||
67 | if (err != IO_DONE) { | ||
68 | lua_pushnil(L); | ||
69 | lua_pushstring(L, socket_hoststrerror(err)); | ||
70 | return 2; | ||
71 | } | ||
72 | lua_pushstring(L, hp->h_name); | ||
73 | inet_pushresolved(L, hp); | ||
74 | return 2; | ||
75 | } | ||
76 | |||
77 | static int inet_global_getnameinfo(lua_State *L) { | ||
78 | char hbuf[NI_MAXHOST]; | ||
79 | char sbuf[NI_MAXSERV]; | ||
80 | int i, ret; | ||
81 | struct addrinfo hints; | ||
82 | struct addrinfo *resolved, *iter; | ||
83 | const char *host = luaL_optstring(L, 1, NULL); | ||
84 | const char *serv = luaL_optstring(L, 2, NULL); | ||
85 | |||
86 | if (!(host || serv)) | ||
87 | luaL_error(L, "host and serv cannot be both nil"); | ||
88 | |||
89 | memset(&hints, 0, sizeof(hints)); | ||
90 | hints.ai_socktype = SOCK_STREAM; | ||
91 | hints.ai_family = AF_UNSPEC; | ||
92 | |||
93 | ret = getaddrinfo(host, serv, &hints, &resolved); | ||
94 | if (ret != 0) { | ||
95 | lua_pushnil(L); | ||
96 | lua_pushstring(L, socket_gaistrerror(ret)); | ||
97 | return 2; | ||
98 | } | ||
99 | |||
100 | lua_newtable(L); | ||
101 | for (i = 1, iter = resolved; iter; i++, iter = iter->ai_next) { | ||
102 | getnameinfo(iter->ai_addr, (socklen_t) iter->ai_addrlen, | ||
103 | hbuf, host? (socklen_t) sizeof(hbuf): 0, | ||
104 | sbuf, serv? (socklen_t) sizeof(sbuf): 0, 0); | ||
105 | if (host) { | ||
106 | lua_pushnumber(L, i); | ||
107 | lua_pushstring(L, hbuf); | ||
108 | lua_settable(L, -3); | ||
109 | } | ||
110 | } | ||
111 | freeaddrinfo(resolved); | ||
112 | |||
113 | if (serv) { | ||
114 | lua_pushstring(L, sbuf); | ||
115 | return 2; | ||
116 | } else { | ||
117 | return 1; | ||
118 | } | ||
119 | } | ||
120 | |||
121 | /*-------------------------------------------------------------------------*\ | ||
122 | * Returns all information provided by the resolver given a host name | ||
123 | * or ip address | ||
124 | \*-------------------------------------------------------------------------*/ | ||
125 | static int inet_global_toip(lua_State *L) | ||
126 | { | ||
127 | const char *address = luaL_checkstring(L, 1); | ||
128 | struct hostent *hp = NULL; | ||
129 | int err = inet_gethost(address, &hp); | ||
130 | if (err != IO_DONE) { | ||
131 | lua_pushnil(L); | ||
132 | lua_pushstring(L, socket_hoststrerror(err)); | ||
133 | return 2; | ||
134 | } | ||
135 | lua_pushstring(L, inet_ntoa(*((struct in_addr *) hp->h_addr))); | ||
136 | inet_pushresolved(L, hp); | ||
137 | return 2; | ||
138 | } | ||
139 | |||
140 | int inet_optfamily(lua_State* L, int narg, const char* def) | ||
141 | { | ||
142 | static const char* optname[] = { "unspec", "inet", "inet6", NULL }; | ||
143 | static int optvalue[] = { AF_UNSPEC, AF_INET, AF_INET6, 0 }; | ||
144 | |||
145 | return optvalue[luaL_checkoption(L, narg, def, optname)]; | ||
146 | } | ||
147 | |||
148 | int inet_optsocktype(lua_State* L, int narg, const char* def) | ||
149 | { | ||
150 | static const char* optname[] = { "stream", "dgram", NULL }; | ||
151 | static int optvalue[] = { SOCK_STREAM, SOCK_DGRAM, 0 }; | ||
152 | |||
153 | return optvalue[luaL_checkoption(L, narg, def, optname)]; | ||
154 | } | ||
155 | |||
156 | static int inet_global_getaddrinfo(lua_State *L) | ||
157 | { | ||
158 | const char *hostname = luaL_checkstring(L, 1); | ||
159 | struct addrinfo *iterator = NULL, *resolved = NULL; | ||
160 | struct addrinfo hints; | ||
161 | int i = 1, ret = 0; | ||
162 | memset(&hints, 0, sizeof(hints)); | ||
163 | hints.ai_socktype = SOCK_STREAM; | ||
164 | hints.ai_family = AF_UNSPEC; | ||
165 | ret = getaddrinfo(hostname, NULL, &hints, &resolved); | ||
166 | if (ret != 0) { | ||
167 | lua_pushnil(L); | ||
168 | lua_pushstring(L, socket_gaistrerror(ret)); | ||
169 | return 2; | ||
170 | } | ||
171 | lua_newtable(L); | ||
172 | for (iterator = resolved; iterator; iterator = iterator->ai_next) { | ||
173 | char hbuf[NI_MAXHOST]; | ||
174 | ret = getnameinfo(iterator->ai_addr, (socklen_t) iterator->ai_addrlen, | ||
175 | hbuf, (socklen_t) sizeof(hbuf), NULL, 0, NI_NUMERICHOST); | ||
176 | if (ret){ | ||
177 | freeaddrinfo(resolved); | ||
178 | lua_pushnil(L); | ||
179 | lua_pushstring(L, socket_gaistrerror(ret)); | ||
180 | return 2; | ||
181 | } | ||
182 | lua_pushnumber(L, i); | ||
183 | lua_newtable(L); | ||
184 | switch (iterator->ai_family) { | ||
185 | case AF_INET: | ||
186 | lua_pushliteral(L, "family"); | ||
187 | lua_pushliteral(L, "inet"); | ||
188 | lua_settable(L, -3); | ||
189 | break; | ||
190 | case AF_INET6: | ||
191 | lua_pushliteral(L, "family"); | ||
192 | lua_pushliteral(L, "inet6"); | ||
193 | lua_settable(L, -3); | ||
194 | break; | ||
195 | case AF_UNSPEC: | ||
196 | lua_pushliteral(L, "family"); | ||
197 | lua_pushliteral(L, "unspec"); | ||
198 | lua_settable(L, -3); | ||
199 | break; | ||
200 | default: | ||
201 | lua_pushliteral(L, "family"); | ||
202 | lua_pushliteral(L, "unknown"); | ||
203 | lua_settable(L, -3); | ||
204 | break; | ||
205 | } | ||
206 | lua_pushliteral(L, "addr"); | ||
207 | lua_pushstring(L, hbuf); | ||
208 | lua_settable(L, -3); | ||
209 | lua_settable(L, -3); | ||
210 | i++; | ||
211 | } | ||
212 | freeaddrinfo(resolved); | ||
213 | return 1; | ||
214 | } | ||
215 | |||
216 | /*-------------------------------------------------------------------------*\ | ||
217 | * Gets the host name | ||
218 | \*-------------------------------------------------------------------------*/ | ||
219 | static int inet_global_gethostname(lua_State *L) | ||
220 | { | ||
221 | char name[257]; | ||
222 | name[256] = '\0'; | ||
223 | if (gethostname(name, 256) < 0) { | ||
224 | lua_pushnil(L); | ||
225 | lua_pushstring(L, socket_strerror(errno)); | ||
226 | return 2; | ||
227 | } else { | ||
228 | lua_pushstring(L, name); | ||
229 | return 1; | ||
230 | } | ||
231 | } | ||
232 | |||
233 | /*=========================================================================*\ | ||
234 | * Lua methods | ||
235 | \*=========================================================================*/ | ||
236 | /*-------------------------------------------------------------------------*\ | ||
237 | * Retrieves socket peer name | ||
238 | \*-------------------------------------------------------------------------*/ | ||
239 | int inet_meth_getpeername(lua_State *L, p_socket ps, int family) | ||
240 | { | ||
241 | int err; | ||
242 | struct sockaddr_storage peer; | ||
243 | socklen_t peer_len = sizeof(peer); | ||
244 | char name[INET6_ADDRSTRLEN]; | ||
245 | char port[6]; /* 65535 = 5 bytes + 0 to terminate it */ | ||
246 | if (getpeername(*ps, (SA *) &peer, &peer_len) < 0) { | ||
247 | lua_pushnil(L); | ||
248 | lua_pushstring(L, socket_strerror(errno)); | ||
249 | return 2; | ||
250 | } | ||
251 | err = getnameinfo((struct sockaddr *) &peer, peer_len, | ||
252 | name, INET6_ADDRSTRLEN, | ||
253 | port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV); | ||
254 | if (err) { | ||
255 | lua_pushnil(L); | ||
256 | lua_pushstring(L, LUA_GAI_STRERROR(err)); | ||
257 | return 2; | ||
258 | } | ||
259 | lua_pushstring(L, name); | ||
260 | lua_pushinteger(L, (int) strtol(port, (char **) NULL, 10)); | ||
261 | switch (family) { | ||
262 | case AF_INET: lua_pushliteral(L, "inet"); break; | ||
263 | case AF_INET6: lua_pushliteral(L, "inet6"); break; | ||
264 | case AF_UNSPEC: lua_pushliteral(L, "unspec"); break; | ||
265 | default: lua_pushliteral(L, "unknown"); break; | ||
266 | } | ||
267 | return 3; | ||
268 | } | ||
269 | |||
270 | /*-------------------------------------------------------------------------*\ | ||
271 | * Retrieves socket local name | ||
272 | \*-------------------------------------------------------------------------*/ | ||
273 | int inet_meth_getsockname(lua_State *L, p_socket ps, int family) | ||
274 | { | ||
275 | int err; | ||
276 | struct sockaddr_storage peer; | ||
277 | socklen_t peer_len = sizeof(peer); | ||
278 | char name[INET6_ADDRSTRLEN]; | ||
279 | char port[6]; /* 65535 = 5 bytes + 0 to terminate it */ | ||
280 | if (getsockname(*ps, (SA *) &peer, &peer_len) < 0) { | ||
281 | lua_pushnil(L); | ||
282 | lua_pushstring(L, socket_strerror(errno)); | ||
283 | return 2; | ||
284 | } | ||
285 | err=getnameinfo((struct sockaddr *)&peer, peer_len, | ||
286 | name, INET6_ADDRSTRLEN, port, 6, NI_NUMERICHOST | NI_NUMERICSERV); | ||
287 | if (err) { | ||
288 | lua_pushnil(L); | ||
289 | lua_pushstring(L, LUA_GAI_STRERROR(err)); | ||
290 | return 2; | ||
291 | } | ||
292 | lua_pushstring(L, name); | ||
293 | lua_pushstring(L, port); | ||
294 | switch (family) { | ||
295 | case AF_INET: lua_pushliteral(L, "inet"); break; | ||
296 | case AF_INET6: lua_pushliteral(L, "inet6"); break; | ||
297 | case AF_UNSPEC: lua_pushliteral(L, "unspec"); break; | ||
298 | default: lua_pushliteral(L, "unknown"); break; | ||
299 | } | ||
300 | return 3; | ||
301 | } | ||
302 | |||
303 | /*=========================================================================*\ | ||
304 | * Internal functions | ||
305 | \*=========================================================================*/ | ||
306 | /*-------------------------------------------------------------------------*\ | ||
307 | * Passes all resolver information to Lua as a table | ||
308 | \*-------------------------------------------------------------------------*/ | ||
309 | static void inet_pushresolved(lua_State *L, struct hostent *hp) | ||
310 | { | ||
311 | char **alias; | ||
312 | struct in_addr **addr; | ||
313 | int i, resolved; | ||
314 | lua_newtable(L); resolved = lua_gettop(L); | ||
315 | lua_pushstring(L, "name"); | ||
316 | lua_pushstring(L, hp->h_name); | ||
317 | lua_settable(L, resolved); | ||
318 | lua_pushstring(L, "ip"); | ||
319 | lua_pushstring(L, "alias"); | ||
320 | i = 1; | ||
321 | alias = hp->h_aliases; | ||
322 | lua_newtable(L); | ||
323 | if (alias) { | ||
324 | while (*alias) { | ||
325 | lua_pushnumber(L, i); | ||
326 | lua_pushstring(L, *alias); | ||
327 | lua_settable(L, -3); | ||
328 | i++; alias++; | ||
329 | } | ||
330 | } | ||
331 | lua_settable(L, resolved); | ||
332 | i = 1; | ||
333 | lua_newtable(L); | ||
334 | addr = (struct in_addr **) hp->h_addr_list; | ||
335 | if (addr) { | ||
336 | while (*addr) { | ||
337 | lua_pushnumber(L, i); | ||
338 | lua_pushstring(L, inet_ntoa(**addr)); | ||
339 | lua_settable(L, -3); | ||
340 | i++; addr++; | ||
341 | } | ||
342 | } | ||
343 | lua_settable(L, resolved); | ||
344 | } | ||
345 | |||
346 | /*-------------------------------------------------------------------------*\ | ||
347 | * Tries to create a new inet socket | ||
348 | \*-------------------------------------------------------------------------*/ | ||
349 | const char *inet_trycreate(p_socket ps, int family, int type, int protocol) { | ||
350 | const char *err = socket_strerror(socket_create(ps, family, type, protocol)); | ||
351 | if (err == NULL && family == AF_INET6) { | ||
352 | int yes = 1; | ||
353 | setsockopt(*ps, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&yes, sizeof(yes)); | ||
354 | } | ||
355 | return err; | ||
356 | } | ||
357 | |||
358 | /*-------------------------------------------------------------------------*\ | ||
359 | * "Disconnects" a DGRAM socket | ||
360 | \*-------------------------------------------------------------------------*/ | ||
361 | const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm) | ||
362 | { | ||
363 | switch (family) { | ||
364 | case AF_INET: { | ||
365 | struct sockaddr_in sin; | ||
366 | memset((char *) &sin, 0, sizeof(sin)); | ||
367 | sin.sin_family = AF_UNSPEC; | ||
368 | sin.sin_addr.s_addr = INADDR_ANY; | ||
369 | return socket_strerror(socket_connect(ps, (SA *) &sin, | ||
370 | sizeof(sin), tm)); | ||
371 | } | ||
372 | case AF_INET6: { | ||
373 | struct sockaddr_in6 sin6; | ||
374 | struct in6_addr addrany = IN6ADDR_ANY_INIT; | ||
375 | memset((char *) &sin6, 0, sizeof(sin6)); | ||
376 | sin6.sin6_family = AF_UNSPEC; | ||
377 | sin6.sin6_addr = addrany; | ||
378 | return socket_strerror(socket_connect(ps, (SA *) &sin6, | ||
379 | sizeof(sin6), tm)); | ||
380 | } | ||
381 | } | ||
382 | return NULL; | ||
383 | } | ||
384 | |||
385 | /*-------------------------------------------------------------------------*\ | ||
386 | * Tries to connect to remote address (address, port) | ||
387 | \*-------------------------------------------------------------------------*/ | ||
388 | const char *inet_tryconnect(p_socket ps, int *family, const char *address, | ||
389 | const char *serv, p_timeout tm, struct addrinfo *connecthints) | ||
390 | { | ||
391 | struct addrinfo *iterator = NULL, *resolved = NULL; | ||
392 | const char *err = NULL; | ||
393 | int current_family = *family; | ||
394 | /* try resolving */ | ||
395 | err = socket_gaistrerror(getaddrinfo(address, serv, | ||
396 | connecthints, &resolved)); | ||
397 | if (err != NULL) { | ||
398 | if (resolved) freeaddrinfo(resolved); | ||
399 | return err; | ||
400 | } | ||
401 | for (iterator = resolved; iterator; iterator = iterator->ai_next) { | ||
402 | timeout_markstart(tm); | ||
403 | /* create new socket if necessary. if there was no | ||
404 | * bind, we need to create one for every new family | ||
405 | * that shows up while iterating. if there was a | ||
406 | * bind, all families will be the same and we will | ||
407 | * not enter this branch. */ | ||
408 | if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) { | ||
409 | socket_destroy(ps); | ||
410 | err = inet_trycreate(ps, iterator->ai_family, | ||
411 | iterator->ai_socktype, iterator->ai_protocol); | ||
412 | if (err) continue; | ||
413 | current_family = iterator->ai_family; | ||
414 | /* set non-blocking before connect */ | ||
415 | socket_setnonblocking(ps); | ||
416 | } | ||
417 | /* try connecting to remote address */ | ||
418 | err = socket_strerror(socket_connect(ps, (SA *) iterator->ai_addr, | ||
419 | (socklen_t) iterator->ai_addrlen, tm)); | ||
420 | /* if success or timeout is zero, break out of loop */ | ||
421 | if (err == NULL || timeout_iszero(tm)) { | ||
422 | *family = current_family; | ||
423 | break; | ||
424 | } | ||
425 | } | ||
426 | freeaddrinfo(resolved); | ||
427 | /* here, if err is set, we failed */ | ||
428 | return err; | ||
429 | } | ||
430 | |||
431 | /*-------------------------------------------------------------------------*\ | ||
432 | * Tries to accept a socket | ||
433 | \*-------------------------------------------------------------------------*/ | ||
434 | const char *inet_tryaccept(p_socket server, int family, p_socket client, | ||
435 | p_timeout tm) { | ||
436 | socklen_t len; | ||
437 | t_sockaddr_storage addr; | ||
438 | switch (family) { | ||
439 | case AF_INET6: len = sizeof(struct sockaddr_in6); break; | ||
440 | case AF_INET: len = sizeof(struct sockaddr_in); break; | ||
441 | default: len = sizeof(addr); break; | ||
442 | } | ||
443 | return socket_strerror(socket_accept(server, client, (SA *) &addr, | ||
444 | &len, tm)); | ||
445 | } | ||
446 | |||
447 | /*-------------------------------------------------------------------------*\ | ||
448 | * Tries to bind socket to (address, port) | ||
449 | \*-------------------------------------------------------------------------*/ | ||
450 | const char *inet_trybind(p_socket ps, int *family, const char *address, | ||
451 | const char *serv, struct addrinfo *bindhints) { | ||
452 | struct addrinfo *iterator = NULL, *resolved = NULL; | ||
453 | const char *err = NULL; | ||
454 | int current_family = *family; | ||
455 | /* translate luasocket special values to C */ | ||
456 | if (strcmp(address, "*") == 0) address = NULL; | ||
457 | if (!serv) serv = "0"; | ||
458 | /* try resolving */ | ||
459 | err = socket_gaistrerror(getaddrinfo(address, serv, bindhints, &resolved)); | ||
460 | if (err) { | ||
461 | if (resolved) freeaddrinfo(resolved); | ||
462 | return err; | ||
463 | } | ||
464 | /* iterate over resolved addresses until one is good */ | ||
465 | for (iterator = resolved; iterator; iterator = iterator->ai_next) { | ||
466 | if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) { | ||
467 | socket_destroy(ps); | ||
468 | err = inet_trycreate(ps, iterator->ai_family, | ||
469 | iterator->ai_socktype, iterator->ai_protocol); | ||
470 | if (err) continue; | ||
471 | current_family = iterator->ai_family; | ||
472 | } | ||
473 | /* try binding to local address */ | ||
474 | err = socket_strerror(socket_bind(ps, (SA *) iterator->ai_addr, | ||
475 | (socklen_t) iterator->ai_addrlen)); | ||
476 | /* keep trying unless bind succeeded */ | ||
477 | if (err == NULL) { | ||
478 | *family = current_family; | ||
479 | /* set to non-blocking after bind */ | ||
480 | socket_setnonblocking(ps); | ||
481 | break; | ||
482 | } | ||
483 | } | ||
484 | /* cleanup and return error */ | ||
485 | freeaddrinfo(resolved); | ||
486 | /* here, if err is set, we failed */ | ||
487 | return err; | ||
488 | } | ||
489 | |||
490 | /*-------------------------------------------------------------------------*\ | ||
491 | * Some systems do not provide these so that we provide our own. | ||
492 | \*-------------------------------------------------------------------------*/ | ||
493 | #ifdef LUASOCKET_INET_ATON | ||
494 | int inet_aton(const char *cp, struct in_addr *inp) | ||
495 | { | ||
496 | unsigned int a = 0, b = 0, c = 0, d = 0; | ||
497 | int n = 0, r; | ||
498 | unsigned long int addr = 0; | ||
499 | r = sscanf(cp, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n); | ||
500 | if (r == 0 || n == 0) return 0; | ||
501 | cp += n; | ||
502 | if (*cp) return 0; | ||
503 | if (a > 255 || b > 255 || c > 255 || d > 255) return 0; | ||
504 | if (inp) { | ||
505 | addr += a; addr <<= 8; | ||
506 | addr += b; addr <<= 8; | ||
507 | addr += c; addr <<= 8; | ||
508 | addr += d; | ||
509 | inp->s_addr = htonl(addr); | ||
510 | } | ||
511 | return 1; | ||
512 | } | ||
513 | #endif | ||
514 | |||
515 | #ifdef LUASOCKET_INET_PTON | ||
516 | int inet_pton(int af, const char *src, void *dst) | ||
517 | { | ||
518 | struct addrinfo hints, *res; | ||
519 | int ret = 1; | ||
520 | memset(&hints, 0, sizeof(struct addrinfo)); | ||
521 | hints.ai_family = af; | ||
522 | hints.ai_flags = AI_NUMERICHOST; | ||
523 | if (getaddrinfo(src, NULL, &hints, &res) != 0) return -1; | ||
524 | if (af == AF_INET) { | ||
525 | struct sockaddr_in *in = (struct sockaddr_in *) res->ai_addr; | ||
526 | memcpy(dst, &in->sin_addr, sizeof(in->sin_addr)); | ||
527 | } else if (af == AF_INET6) { | ||
528 | struct sockaddr_in6 *in = (struct sockaddr_in6 *) res->ai_addr; | ||
529 | memcpy(dst, &in->sin6_addr, sizeof(in->sin6_addr)); | ||
530 | } else { | ||
531 | ret = -1; | ||
532 | } | ||
533 | freeaddrinfo(res); | ||
534 | return ret; | ||
535 | } | ||
536 | |||
537 | #endif | ||
diff --git a/vendor/luasocket/src/inet.h b/vendor/luasocket/src/inet.h new file mode 100644 index 00000000..5618b61b --- /dev/null +++ b/vendor/luasocket/src/inet.h | |||
@@ -0,0 +1,56 @@ | |||
1 | #ifndef INET_H | ||
2 | #define INET_H | ||
3 | /*=========================================================================*\ | ||
4 | * Internet domain functions | ||
5 | * LuaSocket toolkit | ||
6 | * | ||
7 | * This module implements the creation and connection of internet domain | ||
8 | * sockets, on top of the socket.h interface, and the interface of with the | ||
9 | * resolver. | ||
10 | * | ||
11 | * The function inet_aton is provided for the platforms where it is not | ||
12 | * available. The module also implements the interface of the internet | ||
13 | * getpeername and getsockname functions as seen by Lua programs. | ||
14 | * | ||
15 | * The Lua functions toip and tohostname are also implemented here. | ||
16 | \*=========================================================================*/ | ||
17 | #include "luasocket.h" | ||
18 | #include "socket.h" | ||
19 | #include "timeout.h" | ||
20 | |||
21 | #ifdef _WIN32 | ||
22 | #define LUASOCKET_INET_ATON | ||
23 | #endif | ||
24 | |||
25 | #ifndef _WIN32 | ||
26 | #pragma GCC visibility push(hidden) | ||
27 | #endif | ||
28 | |||
29 | int inet_open(lua_State *L); | ||
30 | |||
31 | int inet_optfamily(lua_State* L, int narg, const char* def); | ||
32 | int inet_optsocktype(lua_State* L, int narg, const char* def); | ||
33 | |||
34 | int inet_meth_getpeername(lua_State *L, p_socket ps, int family); | ||
35 | int inet_meth_getsockname(lua_State *L, p_socket ps, int family); | ||
36 | |||
37 | const char *inet_trycreate(p_socket ps, int family, int type, int protocol); | ||
38 | const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm); | ||
39 | const char *inet_tryconnect(p_socket ps, int *family, const char *address, const char *serv, p_timeout tm, struct addrinfo *connecthints); | ||
40 | const char *inet_tryaccept(p_socket server, int family, p_socket client, p_timeout tm); | ||
41 | const char *inet_trybind(p_socket ps, int *family, const char *address, const char *serv, struct addrinfo *bindhints); | ||
42 | |||
43 | #ifdef LUASOCKET_INET_ATON | ||
44 | int inet_aton(const char *cp, struct in_addr *inp); | ||
45 | #endif | ||
46 | |||
47 | #ifdef LUASOCKET_INET_PTON | ||
48 | const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt); | ||
49 | int inet_pton(int af, const char *src, void *dst); | ||
50 | #endif | ||
51 | |||
52 | #ifndef _WIN32 | ||
53 | #pragma GCC visibility pop | ||
54 | #endif | ||
55 | |||
56 | #endif /* INET_H */ | ||
diff --git a/vendor/luasocket/src/io.c b/vendor/luasocket/src/io.c new file mode 100644 index 00000000..5ad4b3af --- /dev/null +++ b/vendor/luasocket/src/io.c | |||
@@ -0,0 +1,28 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * Input/Output abstraction | ||
3 | * LuaSocket toolkit | ||
4 | \*=========================================================================*/ | ||
5 | #include "luasocket.h" | ||
6 | #include "io.h" | ||
7 | |||
8 | /*-------------------------------------------------------------------------*\ | ||
9 | * Initializes C structure | ||
10 | \*-------------------------------------------------------------------------*/ | ||
11 | void io_init(p_io io, p_send send, p_recv recv, p_error error, void *ctx) { | ||
12 | io->send = send; | ||
13 | io->recv = recv; | ||
14 | io->error = error; | ||
15 | io->ctx = ctx; | ||
16 | } | ||
17 | |||
18 | /*-------------------------------------------------------------------------*\ | ||
19 | * I/O error strings | ||
20 | \*-------------------------------------------------------------------------*/ | ||
21 | const char *io_strerror(int err) { | ||
22 | switch (err) { | ||
23 | case IO_DONE: return NULL; | ||
24 | case IO_CLOSED: return "closed"; | ||
25 | case IO_TIMEOUT: return "timeout"; | ||
26 | default: return "unknown error"; | ||
27 | } | ||
28 | } | ||
diff --git a/vendor/luasocket/src/io.h b/vendor/luasocket/src/io.h new file mode 100644 index 00000000..b8a54df6 --- /dev/null +++ b/vendor/luasocket/src/io.h | |||
@@ -0,0 +1,70 @@ | |||
1 | #ifndef IO_H | ||
2 | #define IO_H | ||
3 | /*=========================================================================*\ | ||
4 | * Input/Output abstraction | ||
5 | * LuaSocket toolkit | ||
6 | * | ||
7 | * This module defines the interface that LuaSocket expects from the | ||
8 | * transport layer for streamed input/output. The idea is that if any | ||
9 | * transport implements this interface, then the buffer.c functions | ||
10 | * automatically work on it. | ||
11 | * | ||
12 | * The module socket.h implements this interface, and thus the module tcp.h | ||
13 | * is very simple. | ||
14 | \*=========================================================================*/ | ||
15 | #include "luasocket.h" | ||
16 | #include "timeout.h" | ||
17 | |||
18 | /* IO error codes */ | ||
19 | enum { | ||
20 | IO_DONE = 0, /* operation completed successfully */ | ||
21 | IO_TIMEOUT = -1, /* operation timed out */ | ||
22 | IO_CLOSED = -2, /* the connection has been closed */ | ||
23 | IO_UNKNOWN = -3 | ||
24 | }; | ||
25 | |||
26 | /* interface to error message function */ | ||
27 | typedef const char *(*p_error) ( | ||
28 | void *ctx, /* context needed by send */ | ||
29 | int err /* error code */ | ||
30 | ); | ||
31 | |||
32 | /* interface to send function */ | ||
33 | typedef int (*p_send) ( | ||
34 | void *ctx, /* context needed by send */ | ||
35 | const char *data, /* pointer to buffer with data to send */ | ||
36 | size_t count, /* number of bytes to send from buffer */ | ||
37 | size_t *sent, /* number of bytes sent uppon return */ | ||
38 | p_timeout tm /* timeout control */ | ||
39 | ); | ||
40 | |||
41 | /* interface to recv function */ | ||
42 | typedef int (*p_recv) ( | ||
43 | void *ctx, /* context needed by recv */ | ||
44 | char *data, /* pointer to buffer where data will be writen */ | ||
45 | size_t count, /* number of bytes to receive into buffer */ | ||
46 | size_t *got, /* number of bytes received uppon return */ | ||
47 | p_timeout tm /* timeout control */ | ||
48 | ); | ||
49 | |||
50 | /* IO driver definition */ | ||
51 | typedef struct t_io_ { | ||
52 | void *ctx; /* context needed by send/recv */ | ||
53 | p_send send; /* send function pointer */ | ||
54 | p_recv recv; /* receive function pointer */ | ||
55 | p_error error; /* strerror function */ | ||
56 | } t_io; | ||
57 | typedef t_io *p_io; | ||
58 | |||
59 | #ifndef _WIN32 | ||
60 | #pragma GCC visibility push(hidden) | ||
61 | #endif | ||
62 | |||
63 | void io_init(p_io io, p_send send, p_recv recv, p_error error, void *ctx); | ||
64 | const char *io_strerror(int err); | ||
65 | |||
66 | #ifndef _WIN32 | ||
67 | #pragma GCC visibility pop | ||
68 | #endif | ||
69 | |||
70 | #endif /* IO_H */ | ||
diff --git a/vendor/luasocket/src/ltn12.lua b/vendor/luasocket/src/ltn12.lua new file mode 100644 index 00000000..4cb17f53 --- /dev/null +++ b/vendor/luasocket/src/ltn12.lua | |||
@@ -0,0 +1,318 @@ | |||
1 | ----------------------------------------------------------------------------- | ||
2 | -- LTN12 - Filters, sources, sinks and pumps. | ||
3 | -- LuaSocket toolkit. | ||
4 | -- Author: Diego Nehab | ||
5 | ----------------------------------------------------------------------------- | ||
6 | |||
7 | ----------------------------------------------------------------------------- | ||
8 | -- Declare module | ||
9 | ----------------------------------------------------------------------------- | ||
10 | local string = require("string") | ||
11 | local table = require("table") | ||
12 | local unpack = unpack or table.unpack | ||
13 | local base = _G | ||
14 | local select = select | ||
15 | |||
16 | local _M = {} | ||
17 | if module then -- heuristic for exporting a global package table | ||
18 | ltn12 = _M -- luacheck: ignore | ||
19 | end | ||
20 | local filter,source,sink,pump = {},{},{},{} | ||
21 | |||
22 | _M.filter = filter | ||
23 | _M.source = source | ||
24 | _M.sink = sink | ||
25 | _M.pump = pump | ||
26 | |||
27 | -- 2048 seems to be better in windows... | ||
28 | _M.BLOCKSIZE = 2048 | ||
29 | _M._VERSION = "LTN12 1.0.3" | ||
30 | |||
31 | ----------------------------------------------------------------------------- | ||
32 | -- Filter stuff | ||
33 | ----------------------------------------------------------------------------- | ||
34 | -- returns a high level filter that cycles a low-level filter | ||
35 | function filter.cycle(low, ctx, extra) | ||
36 | base.assert(low) | ||
37 | return function(chunk) | ||
38 | local ret | ||
39 | ret, ctx = low(ctx, chunk, extra) | ||
40 | return ret | ||
41 | end | ||
42 | end | ||
43 | |||
44 | -- chains a bunch of filters together | ||
45 | -- (thanks to Wim Couwenberg) | ||
46 | function filter.chain(...) | ||
47 | local arg = {...} | ||
48 | local n = select('#',...) | ||
49 | local top, index = 1, 1 | ||
50 | local retry = "" | ||
51 | return function(chunk) | ||
52 | retry = chunk and retry | ||
53 | while true do | ||
54 | if index == top then | ||
55 | chunk = arg[index](chunk) | ||
56 | if chunk == "" or top == n then return chunk | ||
57 | elseif chunk then index = index + 1 | ||
58 | else | ||
59 | top = top+1 | ||
60 | index = top | ||
61 | end | ||
62 | else | ||
63 | chunk = arg[index](chunk or "") | ||
64 | if chunk == "" then | ||
65 | index = index - 1 | ||
66 | chunk = retry | ||
67 | elseif chunk then | ||
68 | if index == n then return chunk | ||
69 | else index = index + 1 end | ||
70 | else base.error("filter returned inappropriate nil") end | ||
71 | end | ||
72 | end | ||
73 | end | ||
74 | end | ||
75 | |||
76 | ----------------------------------------------------------------------------- | ||
77 | -- Source stuff | ||
78 | ----------------------------------------------------------------------------- | ||
79 | -- create an empty source | ||
80 | local function empty() | ||
81 | return nil | ||
82 | end | ||
83 | |||
84 | function source.empty() | ||
85 | return empty | ||
86 | end | ||
87 | |||
88 | -- returns a source that just outputs an error | ||
89 | function source.error(err) | ||
90 | return function() | ||
91 | return nil, err | ||
92 | end | ||
93 | end | ||
94 | |||
95 | -- creates a file source | ||
96 | function source.file(handle, io_err) | ||
97 | if handle then | ||
98 | return function() | ||
99 | local chunk = handle:read(_M.BLOCKSIZE) | ||
100 | if not chunk then handle:close() end | ||
101 | return chunk | ||
102 | end | ||
103 | else return source.error(io_err or "unable to open file") end | ||
104 | end | ||
105 | |||
106 | -- turns a fancy source into a simple source | ||
107 | function source.simplify(src) | ||
108 | base.assert(src) | ||
109 | return function() | ||
110 | local chunk, err_or_new = src() | ||
111 | src = err_or_new or src | ||
112 | if not chunk then return nil, err_or_new | ||
113 | else return chunk end | ||
114 | end | ||
115 | end | ||
116 | |||
117 | -- creates string source | ||
118 | function source.string(s) | ||
119 | if s then | ||
120 | local i = 1 | ||
121 | return function() | ||
122 | local chunk = string.sub(s, i, i+_M.BLOCKSIZE-1) | ||
123 | i = i + _M.BLOCKSIZE | ||
124 | if chunk ~= "" then return chunk | ||
125 | else return nil end | ||
126 | end | ||
127 | else return source.empty() end | ||
128 | end | ||
129 | |||
130 | -- creates table source | ||
131 | function source.table(t) | ||
132 | base.assert('table' == type(t)) | ||
133 | local i = 0 | ||
134 | return function() | ||
135 | i = i + 1 | ||
136 | return t[i] | ||
137 | end | ||
138 | end | ||
139 | |||
140 | -- creates rewindable source | ||
141 | function source.rewind(src) | ||
142 | base.assert(src) | ||
143 | local t = {} | ||
144 | return function(chunk) | ||
145 | if not chunk then | ||
146 | chunk = table.remove(t) | ||
147 | if not chunk then return src() | ||
148 | else return chunk end | ||
149 | else | ||
150 | table.insert(t, chunk) | ||
151 | end | ||
152 | end | ||
153 | end | ||
154 | |||
155 | -- chains a source with one or several filter(s) | ||
156 | function source.chain(src, f, ...) | ||
157 | if ... then f=filter.chain(f, ...) end | ||
158 | base.assert(src and f) | ||
159 | local last_in, last_out = "", "" | ||
160 | local state = "feeding" | ||
161 | local err | ||
162 | return function() | ||
163 | if not last_out then | ||
164 | base.error('source is empty!', 2) | ||
165 | end | ||
166 | while true do | ||
167 | if state == "feeding" then | ||
168 | last_in, err = src() | ||
169 | if err then return nil, err end | ||
170 | last_out = f(last_in) | ||
171 | if not last_out then | ||
172 | if last_in then | ||
173 | base.error('filter returned inappropriate nil') | ||
174 | else | ||
175 | return nil | ||
176 | end | ||
177 | elseif last_out ~= "" then | ||
178 | state = "eating" | ||
179 | if last_in then last_in = "" end | ||
180 | return last_out | ||
181 | end | ||
182 | else | ||
183 | last_out = f(last_in) | ||
184 | if last_out == "" then | ||
185 | if last_in == "" then | ||
186 | state = "feeding" | ||
187 | else | ||
188 | base.error('filter returned ""') | ||
189 | end | ||
190 | elseif not last_out then | ||
191 | if last_in then | ||
192 | base.error('filter returned inappropriate nil') | ||
193 | else | ||
194 | return nil | ||
195 | end | ||
196 | else | ||
197 | return last_out | ||
198 | end | ||
199 | end | ||
200 | end | ||
201 | end | ||
202 | end | ||
203 | |||
204 | -- creates a source that produces contents of several sources, one after the | ||
205 | -- other, as if they were concatenated | ||
206 | -- (thanks to Wim Couwenberg) | ||
207 | function source.cat(...) | ||
208 | local arg = {...} | ||
209 | local src = table.remove(arg, 1) | ||
210 | return function() | ||
211 | while src do | ||
212 | local chunk, err = src() | ||
213 | if chunk then return chunk end | ||
214 | if err then return nil, err end | ||
215 | src = table.remove(arg, 1) | ||
216 | end | ||
217 | end | ||
218 | end | ||
219 | |||
220 | ----------------------------------------------------------------------------- | ||
221 | -- Sink stuff | ||
222 | ----------------------------------------------------------------------------- | ||
223 | -- creates a sink that stores into a table | ||
224 | function sink.table(t) | ||
225 | t = t or {} | ||
226 | local f = function(chunk, err) | ||
227 | if chunk then table.insert(t, chunk) end | ||
228 | return 1 | ||
229 | end | ||
230 | return f, t | ||
231 | end | ||
232 | |||
233 | -- turns a fancy sink into a simple sink | ||
234 | function sink.simplify(snk) | ||
235 | base.assert(snk) | ||
236 | return function(chunk, err) | ||
237 | local ret, err_or_new = snk(chunk, err) | ||
238 | if not ret then return nil, err_or_new end | ||
239 | snk = err_or_new or snk | ||
240 | return 1 | ||
241 | end | ||
242 | end | ||
243 | |||
244 | -- creates a file sink | ||
245 | function sink.file(handle, io_err) | ||
246 | if handle then | ||
247 | return function(chunk, err) | ||
248 | if not chunk then | ||
249 | handle:close() | ||
250 | return 1 | ||
251 | else return handle:write(chunk) end | ||
252 | end | ||
253 | else return sink.error(io_err or "unable to open file") end | ||
254 | end | ||
255 | |||
256 | -- creates a sink that discards data | ||
257 | local function null() | ||
258 | return 1 | ||
259 | end | ||
260 | |||
261 | function sink.null() | ||
262 | return null | ||
263 | end | ||
264 | |||
265 | -- creates a sink that just returns an error | ||
266 | function sink.error(err) | ||
267 | return function() | ||
268 | return nil, err | ||
269 | end | ||
270 | end | ||
271 | |||
272 | -- chains a sink with one or several filter(s) | ||
273 | function sink.chain(f, snk, ...) | ||
274 | if ... then | ||
275 | local args = { f, snk, ... } | ||
276 | snk = table.remove(args, #args) | ||
277 | f = filter.chain(unpack(args)) | ||
278 | end | ||
279 | base.assert(f and snk) | ||
280 | return function(chunk, err) | ||
281 | if chunk ~= "" then | ||
282 | local filtered = f(chunk) | ||
283 | local done = chunk and "" | ||
284 | while true do | ||
285 | local ret, snkerr = snk(filtered, err) | ||
286 | if not ret then return nil, snkerr end | ||
287 | if filtered == done then return 1 end | ||
288 | filtered = f(done) | ||
289 | end | ||
290 | else return 1 end | ||
291 | end | ||
292 | end | ||
293 | |||
294 | ----------------------------------------------------------------------------- | ||
295 | -- Pump stuff | ||
296 | ----------------------------------------------------------------------------- | ||
297 | -- pumps one chunk from the source to the sink | ||
298 | function pump.step(src, snk) | ||
299 | local chunk, src_err = src() | ||
300 | local ret, snk_err = snk(chunk, src_err) | ||
301 | if chunk and ret then return 1 | ||
302 | else return nil, src_err or snk_err end | ||
303 | end | ||
304 | |||
305 | -- pumps all data from a source to a sink, using a step function | ||
306 | function pump.all(src, snk, step) | ||
307 | base.assert(src and snk) | ||
308 | step = step or pump.step | ||
309 | while true do | ||
310 | local ret, err = step(src, snk) | ||
311 | if not ret then | ||
312 | if err then return nil, err | ||
313 | else return 1 end | ||
314 | end | ||
315 | end | ||
316 | end | ||
317 | |||
318 | return _M | ||
diff --git a/vendor/luasocket/src/luasocket.c b/vendor/luasocket/src/luasocket.c new file mode 100755 index 00000000..0fd99f70 --- /dev/null +++ b/vendor/luasocket/src/luasocket.c | |||
@@ -0,0 +1,104 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * LuaSocket toolkit | ||
3 | * Networking support for the Lua language | ||
4 | * Diego Nehab | ||
5 | * 26/11/1999 | ||
6 | * | ||
7 | * This library is part of an effort to progressively increase the network | ||
8 | * connectivity of the Lua language. The Lua interface to networking | ||
9 | * functions follows the Sockets API closely, trying to simplify all tasks | ||
10 | * involved in setting up both client and server connections. The provided | ||
11 | * IO routines, however, follow the Lua style, being very similar to the | ||
12 | * standard Lua read and write functions. | ||
13 | \*=========================================================================*/ | ||
14 | |||
15 | #include "luasocket.h" | ||
16 | #include "auxiliar.h" | ||
17 | #include "except.h" | ||
18 | #include "timeout.h" | ||
19 | #include "buffer.h" | ||
20 | #include "inet.h" | ||
21 | #include "tcp.h" | ||
22 | #include "udp.h" | ||
23 | #include "select.h" | ||
24 | |||
25 | /*-------------------------------------------------------------------------*\ | ||
26 | * Internal function prototypes | ||
27 | \*-------------------------------------------------------------------------*/ | ||
28 | static int global_skip(lua_State *L); | ||
29 | static int global_unload(lua_State *L); | ||
30 | static int base_open(lua_State *L); | ||
31 | |||
32 | /*-------------------------------------------------------------------------*\ | ||
33 | * Modules and functions | ||
34 | \*-------------------------------------------------------------------------*/ | ||
35 | static const luaL_Reg mod[] = { | ||
36 | {"auxiliar", auxiliar_open}, | ||
37 | {"except", except_open}, | ||
38 | {"timeout", timeout_open}, | ||
39 | {"buffer", buffer_open}, | ||
40 | {"inet", inet_open}, | ||
41 | {"tcp", tcp_open}, | ||
42 | {"udp", udp_open}, | ||
43 | {"select", select_open}, | ||
44 | {NULL, NULL} | ||
45 | }; | ||
46 | |||
47 | static luaL_Reg func[] = { | ||
48 | {"skip", global_skip}, | ||
49 | {"__unload", global_unload}, | ||
50 | {NULL, NULL} | ||
51 | }; | ||
52 | |||
53 | /*-------------------------------------------------------------------------*\ | ||
54 | * Skip a few arguments | ||
55 | \*-------------------------------------------------------------------------*/ | ||
56 | static int global_skip(lua_State *L) { | ||
57 | int amount = (int) luaL_checkinteger(L, 1); | ||
58 | int ret = lua_gettop(L) - amount - 1; | ||
59 | return ret >= 0 ? ret : 0; | ||
60 | } | ||
61 | |||
62 | /*-------------------------------------------------------------------------*\ | ||
63 | * Unloads the library | ||
64 | \*-------------------------------------------------------------------------*/ | ||
65 | static int global_unload(lua_State *L) { | ||
66 | (void) L; | ||
67 | socket_close(); | ||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | /*-------------------------------------------------------------------------*\ | ||
72 | * Setup basic stuff. | ||
73 | \*-------------------------------------------------------------------------*/ | ||
74 | static int base_open(lua_State *L) { | ||
75 | if (socket_open()) { | ||
76 | /* export functions (and leave namespace table on top of stack) */ | ||
77 | lua_newtable(L); | ||
78 | luaL_setfuncs(L, func, 0); | ||
79 | #ifdef LUASOCKET_DEBUG | ||
80 | lua_pushstring(L, "_DEBUG"); | ||
81 | lua_pushboolean(L, 1); | ||
82 | lua_rawset(L, -3); | ||
83 | #endif | ||
84 | /* make version string available to scripts */ | ||
85 | lua_pushstring(L, "_VERSION"); | ||
86 | lua_pushstring(L, LUASOCKET_VERSION); | ||
87 | lua_rawset(L, -3); | ||
88 | return 1; | ||
89 | } else { | ||
90 | lua_pushstring(L, "unable to initialize library"); | ||
91 | lua_error(L); | ||
92 | return 0; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | /*-------------------------------------------------------------------------*\ | ||
97 | * Initializes all library modules. | ||
98 | \*-------------------------------------------------------------------------*/ | ||
99 | LUASOCKET_API int luaopen_socket_core(lua_State *L) { | ||
100 | int i; | ||
101 | base_open(L); | ||
102 | for (i = 0; mod[i].name; i++) mod[i].func(L); | ||
103 | return 1; | ||
104 | } | ||
diff --git a/vendor/luasocket/src/luasocket.h b/vendor/luasocket/src/luasocket.h new file mode 100644 index 00000000..1017fbaa --- /dev/null +++ b/vendor/luasocket/src/luasocket.h | |||
@@ -0,0 +1,36 @@ | |||
1 | #ifndef LUASOCKET_H | ||
2 | #define LUASOCKET_H | ||
3 | /*=========================================================================*\ | ||
4 | * LuaSocket toolkit | ||
5 | * Networking support for the Lua language | ||
6 | * Diego Nehab | ||
7 | * 9/11/1999 | ||
8 | \*=========================================================================*/ | ||
9 | |||
10 | /*-------------------------------------------------------------------------* \ | ||
11 | * Current socket library version | ||
12 | \*-------------------------------------------------------------------------*/ | ||
13 | #define LUASOCKET_VERSION "LuaSocket 3.0.0" | ||
14 | #define LUASOCKET_COPYRIGHT "Copyright (C) 1999-2013 Diego Nehab" | ||
15 | |||
16 | /*-------------------------------------------------------------------------*\ | ||
17 | * This macro prefixes all exported API functions | ||
18 | \*-------------------------------------------------------------------------*/ | ||
19 | #ifndef LUASOCKET_API | ||
20 | #ifdef _WIN32 | ||
21 | #define LUASOCKET_API __declspec(dllexport) | ||
22 | #else | ||
23 | #define LUASOCKET_API __attribute__ ((visibility ("default"))) | ||
24 | #endif | ||
25 | #endif | ||
26 | |||
27 | #include "lua.h" | ||
28 | #include "lauxlib.h" | ||
29 | #include "compat.h" | ||
30 | |||
31 | /*-------------------------------------------------------------------------*\ | ||
32 | * Initializes the library. | ||
33 | \*-------------------------------------------------------------------------*/ | ||
34 | LUASOCKET_API int luaopen_socket_core(lua_State *L); | ||
35 | |||
36 | #endif /* LUASOCKET_H */ | ||
diff --git a/vendor/luasocket/src/makefile b/vendor/luasocket/src/makefile new file mode 100755 index 00000000..06f4d192 --- /dev/null +++ b/vendor/luasocket/src/makefile | |||
@@ -0,0 +1,461 @@ | |||
1 | # luasocket src/makefile | ||
2 | # | ||
3 | # Definitions in this section can be overriden on the command line or in the | ||
4 | # environment. | ||
5 | # | ||
6 | # These are equivalent: | ||
7 | # | ||
8 | # export PLAT=linux DEBUG=DEBUG LUAV=5.2 prefix=/sw | ||
9 | # make | ||
10 | # | ||
11 | # and | ||
12 | # | ||
13 | # make PLAT=linux DEBUG=DEBUG LUAV=5.2 prefix=/sw | ||
14 | |||
15 | # PLAT: linux macosx win32 win64 mingw | ||
16 | # platform to build for | ||
17 | PLAT?=linux | ||
18 | |||
19 | # LUAV: 5.1 5.2 5.3 5.4 | ||
20 | # lua version to build against | ||
21 | LUAV?=5.1 | ||
22 | |||
23 | # MYCFLAGS: to be set by user if needed | ||
24 | MYCFLAGS?= | ||
25 | |||
26 | # MYLDFLAGS: to be set by user if needed | ||
27 | MYLDFLAGS?= | ||
28 | |||
29 | # DEBUG: NODEBUG DEBUG | ||
30 | # debug mode causes luasocket to collect and returns timing information useful | ||
31 | # for testing and debugging luasocket itself | ||
32 | DEBUG?=NODEBUG | ||
33 | |||
34 | # where lua headers are found for macosx builds | ||
35 | # LUAINC_macosx: | ||
36 | # /opt/local/include | ||
37 | LUAINC_macosx_base?=/opt/local/include | ||
38 | LUAINC_macosx?=$(LUAINC_macosx_base)/lua/$(LUAV) $(LUAINC_macosx_base)/lua$(LUAV) $(LUAINC_macosx_base)/lua-$(LUAV) | ||
39 | |||
40 | # FIXME default should this default to fink or to macports? | ||
41 | # What happens when more than one Lua version is installed? | ||
42 | LUAPREFIX_macosx?=/opt/local | ||
43 | CDIR_macosx?=lib/lua/$(LUAV) | ||
44 | LDIR_macosx?=share/lua/$(LUAV) | ||
45 | |||
46 | # LUAINC_linux: | ||
47 | # /usr/include/lua$(LUAV) | ||
48 | # /usr/local/include | ||
49 | # /usr/local/include/lua$(LUAV) | ||
50 | # where lua headers are found for linux builds | ||
51 | LUAINC_linux_base?=/usr/include | ||
52 | LUAINC_linux?=$(LUAINC_linux_base)/lua/$(LUAV) $(LUAINC_linux_base)/lua$(LUAV) | ||
53 | LUAPREFIX_linux?=/usr/local | ||
54 | CDIR_linux?=lib/lua/$(LUAV) | ||
55 | LDIR_linux?=share/lua/$(LUAV) | ||
56 | |||
57 | # LUAINC_freebsd: | ||
58 | # /usr/local/include/lua$(LUAV) | ||
59 | # where lua headers are found for freebsd builds | ||
60 | LUAINC_freebsd_base?=/usr/local/include/ | ||
61 | LUAINC_freebsd?=$(LUAINC_freebsd_base)/lua/$(LUAV) $(LUAINC_freebsd_base)/lua$(LUAV) | ||
62 | LUAPREFIX_freebsd?=/usr/local/ | ||
63 | CDIR_freebsd?=lib/lua/$(LUAV) | ||
64 | LDIR_freebsd?=share/lua/$(LUAV) | ||
65 | |||
66 | # where lua headers are found for mingw builds | ||
67 | # LUAINC_mingw: | ||
68 | # /opt/local/include | ||
69 | LUAINC_mingw_base?=/usr/include | ||
70 | LUAINC_mingw?=$(LUAINC_mingw_base)/lua/$(LUAV) $(LUAINC_mingw_base)/lua$(LUAV) | ||
71 | LUALIB_mingw_base?=/usr/bin | ||
72 | LUALIB_mingw?=$(LUALIB_mingw_base)/lua/$(LUAV)/lua$(subst .,,$(LUAV)).dll | ||
73 | LUAPREFIX_mingw?=/usr | ||
74 | CDIR_mingw?=lua/$(LUAV) | ||
75 | LDIR_mingw?=lua/$(LUAV)/lua | ||
76 | |||
77 | |||
78 | # LUAINC_win32: | ||
79 | # LUALIB_win32: | ||
80 | # where lua headers and libraries are found for win32 builds | ||
81 | LUAPREFIX_win32?= | ||
82 | LUAINC_win32?=$(LUAPREFIX_win32)/include/lua/$(LUAV) $(LUAPREFIX_win32)/include/lua$(LUAV) | ||
83 | PLATFORM_win32?=Release | ||
84 | CDIR_win32?=bin/lua/$(LUAV)/$(PLATFORM_win32) | ||
85 | LDIR_win32?=bin/lua/$(LUAV)/$(PLATFORM_win32)/lua | ||
86 | LUALIB_win32?=$(LUAPREFIX_win32)/lib/lua/$(LUAV)/$(PLATFORM_win32) | ||
87 | LUALIBNAME_win32?=lua$(subst .,,$(LUAV)).lib | ||
88 | |||
89 | # LUAINC_win64: | ||
90 | # LUALIB_win64: | ||
91 | # where lua headers and libraries are found for win64 builds | ||
92 | LUAPREFIX_win64?= | ||
93 | LUAINC_win64?=$(LUAPREFIX_win64)/include/lua/$(LUAV) $(LUAPREFIX_win64)/include/lua$(LUAV) | ||
94 | PLATFORM_win64?=x64/Release | ||
95 | CDIR_win64?=bin/lua/$(LUAV)/$(PLATFORM_win64) | ||
96 | LDIR_win64?=bin/lua/$(LUAV)/$(PLATFORM_win64)/lua | ||
97 | LUALIB_win64?=$(LUAPREFIX_win64)/lib/lua/$(LUAV)/$(PLATFORM_win64) | ||
98 | LUALIBNAME_win64?=lua$(subst .,,$(LUAV)).lib | ||
99 | |||
100 | |||
101 | # LUAINC_solaris: | ||
102 | LUAINC_solaris_base?=/usr/include | ||
103 | LUAINC_solaris?=$(LUAINC_solaris_base)/lua/$(LUAV) $(LUAINC_solaris_base)/lua$(LUAV) | ||
104 | LUAPREFIX_solaris?=/usr/local | ||
105 | CDIR_solaris?=lib/lua/$(LUAV) | ||
106 | LDIR_solaris?=share/lua/$(LUAV) | ||
107 | |||
108 | # prefix: /usr/local /usr /opt/local /sw | ||
109 | # the top of the default install tree | ||
110 | prefix?=$(LUAPREFIX_$(PLAT)) | ||
111 | |||
112 | CDIR?=$(CDIR_$(PLAT)) | ||
113 | LDIR?=$(LDIR_$(PLAT)) | ||
114 | |||
115 | # DESTDIR: (no default) | ||
116 | # used by package managers to install into a temporary destination | ||
117 | DESTDIR?= | ||
118 | |||
119 | #------ | ||
120 | # Definitions below can be overridden on the make command line, but | ||
121 | # shouldn't have to be. | ||
122 | |||
123 | |||
124 | #------ | ||
125 | # Install directories | ||
126 | # | ||
127 | |||
128 | INSTALL_DIR=install -d | ||
129 | INSTALL_DATA=install -m644 | ||
130 | INSTALL_EXEC=install | ||
131 | INSTALL_TOP=$(DESTDIR)$(prefix) | ||
132 | |||
133 | INSTALL_TOP_LDIR=$(INSTALL_TOP)/$(LDIR) | ||
134 | INSTALL_TOP_CDIR=$(INSTALL_TOP)/$(CDIR) | ||
135 | |||
136 | INSTALL_SOCKET_LDIR=$(INSTALL_TOP_LDIR)/socket | ||
137 | INSTALL_SOCKET_CDIR=$(INSTALL_TOP_CDIR)/socket | ||
138 | INSTALL_MIME_LDIR=$(INSTALL_TOP_LDIR)/mime | ||
139 | INSTALL_MIME_CDIR=$(INSTALL_TOP_CDIR)/mime | ||
140 | |||
141 | print: | ||
142 | @echo PLAT=$(PLAT) | ||
143 | @echo LUAV=$(LUAV) | ||
144 | @echo DEBUG=$(DEBUG) | ||
145 | @echo prefix=$(prefix) | ||
146 | @echo LUAINC_$(PLAT)=$(LUAINC_$(PLAT)) | ||
147 | @echo LUALIB_$(PLAT)=$(LUALIB_$(PLAT)) | ||
148 | @echo INSTALL_TOP_CDIR=$(INSTALL_TOP_CDIR) | ||
149 | @echo INSTALL_TOP_LDIR=$(INSTALL_TOP_LDIR) | ||
150 | @echo CFLAGS=$(CFLAGS) | ||
151 | @echo LDFLAGS=$(LDFLAGS) | ||
152 | |||
153 | #------ | ||
154 | # Supported platforms | ||
155 | # | ||
156 | PLATS= macosx linux win32 win64 mingw solaris | ||
157 | |||
158 | #------ | ||
159 | # Compiler and linker settings | ||
160 | # for Mac OS X | ||
161 | SO_macosx=so | ||
162 | O_macosx=o | ||
163 | CC_macosx=gcc | ||
164 | DEF_macosx= -DLUASOCKET_$(DEBUG) -DUNIX_HAS_SUN_LEN | ||
165 | CFLAGS_macosx=$(LUAINC:%=-I%) $(DEF) -Wall -O2 -fno-common | ||
166 | LDFLAGS_macosx= -bundle -undefined dynamic_lookup -o | ||
167 | LD_macosx=gcc | ||
168 | SOCKET_macosx=usocket.o | ||
169 | |||
170 | #------ | ||
171 | # Compiler and linker settings | ||
172 | # for Linux | ||
173 | SO_linux=so | ||
174 | O_linux=o | ||
175 | CC_linux=gcc | ||
176 | DEF_linux=-DLUASOCKET_$(DEBUG) | ||
177 | CFLAGS_linux=$(LUAINC:%=-I%) $(DEF) -Wall -Wshadow -Wextra \ | ||
178 | -Wimplicit -O2 -ggdb3 -fpic | ||
179 | LDFLAGS_linux=-O -shared -fpic -o | ||
180 | LD_linux=gcc | ||
181 | SOCKET_linux=usocket.o | ||
182 | |||
183 | #------ | ||
184 | # Compiler and linker settings | ||
185 | # for FreeBSD | ||
186 | SO_freebsd=so | ||
187 | O_freebsd=o | ||
188 | CC_freebsd=gcc | ||
189 | DEF_freebsd=-DLUASOCKET_$(DEBUG) -DUNIX_HAS_SUN_LEN | ||
190 | CFLAGS_freebsd=$(LUAINC:%=-I%) $(DEF) -Wall -Wshadow -Wextra \ | ||
191 | -Wimplicit -O2 -ggdb3 -fpic | ||
192 | LDFLAGS_freebsd=-O -shared -fpic -o | ||
193 | LD_freebsd=gcc | ||
194 | SOCKET_freebsd=usocket.o | ||
195 | |||
196 | #------ | ||
197 | # Compiler and linker settings | ||
198 | # for Solaris | ||
199 | SO_solaris=so | ||
200 | O_solaris=o | ||
201 | CC_solaris=gcc | ||
202 | DEF_solaris=-DLUASOCKET_$(DEBUG) | ||
203 | CFLAGS_solaris=$(LUAINC:%=-I%) $(DEF) -Wall -Wshadow -Wextra \ | ||
204 | -Wimplicit -O2 -ggdb3 -fpic | ||
205 | LDFLAGS_solaris=-lnsl -lsocket -lresolv -O -shared -fpic -o | ||
206 | LD_solaris=gcc | ||
207 | SOCKET_solaris=usocket.o | ||
208 | |||
209 | #------ | ||
210 | # Compiler and linker settings | ||
211 | # for MingW | ||
212 | SO_mingw=dll | ||
213 | O_mingw=o | ||
214 | CC_mingw=gcc | ||
215 | DEF_mingw= -DLUASOCKET_$(DEBUG) \ | ||
216 | -DWINVER=0x0501 | ||
217 | CFLAGS_mingw=$(LUAINC:%=-I%) $(DEF) -Wall -O2 -fno-common | ||
218 | LDFLAGS_mingw= $(LUALIB) -shared -Wl,-s -lws2_32 -o | ||
219 | LD_mingw=gcc | ||
220 | SOCKET_mingw=wsocket.o | ||
221 | |||
222 | |||
223 | #------ | ||
224 | # Compiler and linker settings | ||
225 | # for Win32 | ||
226 | SO_win32=dll | ||
227 | O_win32=obj | ||
228 | CC_win32=cl | ||
229 | DEF_win32= //D "WIN32" //D "NDEBUG" //D "_WINDOWS" //D "_USRDLL" \ | ||
230 | //D "_CRT_SECURE_NO_WARNINGS" \ | ||
231 | //D "_WINDLL" \ | ||
232 | //D "LUASOCKET_$(DEBUG)" | ||
233 | CFLAGS_win32=$(LUAINC:%=//I "%") $(DEF) //O2 //Ot //MD //W3 //nologo | ||
234 | LDFLAGS_win32= //nologo //link //NOLOGO //DLL //INCREMENTAL:NO \ | ||
235 | //MANIFEST //MANIFESTFILE:"intermediate.manifest" \ | ||
236 | /MANIFESTUAC:"level='asInvoker' uiAccess='false'" \ | ||
237 | //SUBSYSTEM:WINDOWS //OPT:REF //OPT:ICF //DYNAMICBASE:NO \ | ||
238 | //MACHINE:X86 /LIBPATH:"$(LUALIB)" \ | ||
239 | $(LUALIBNAME_win32) ws2_32.lib //OUT: | ||
240 | |||
241 | LD_win32=cl | ||
242 | SOCKET_win32=wsocket.obj | ||
243 | |||
244 | #------ | ||
245 | # Compiler and linker settings | ||
246 | # for Win64 | ||
247 | SO_win64=dll | ||
248 | O_win64=obj | ||
249 | CC_win64=cl | ||
250 | DEF_win64= //D "WIN32" //D "NDEBUG" //D "_WINDOWS" //D "_USRDLL" \ | ||
251 | //D "_CRT_SECURE_NO_WARNINGS" \ | ||
252 | //D "_WINDLL" \ | ||
253 | //D "LUASOCKET_$(DEBUG)" | ||
254 | CFLAGS_win64=$(LUAINC:%=//I "%") $(DEF) //O2 //Ot //MD //W3 //nologo | ||
255 | LDFLAGS_win64= //nologo //link //NOLOGO //DLL //INCREMENTAL:NO \ | ||
256 | //MANIFEST //MANIFESTFILE:"intermediate.manifest" \ | ||
257 | /MANIFESTUAC:"level='asInvoker' uiAccess='false'" \ | ||
258 | //SUBSYSTEM:WINDOWS //OPT:REF //OPT:ICF //DYNAMICBASE:NO \ | ||
259 | /LIBPATH:"$(LUALIB)" \ | ||
260 | $(LUALIBNAME_win64) ws2_32.lib //OUT: | ||
261 | |||
262 | LD_win64=cl | ||
263 | SOCKET_win64=wsocket.obj | ||
264 | |||
265 | .SUFFIXES: .obj | ||
266 | |||
267 | .c.obj: | ||
268 | $(CC) $(CFLAGS) //Fo"$@" //c $< | ||
269 | |||
270 | #------ | ||
271 | # Output file names | ||
272 | # | ||
273 | SO=$(SO_$(PLAT)) | ||
274 | O=$(O_$(PLAT)) | ||
275 | SOCKET_V=3.0.0 | ||
276 | MIME_V=1.0.3 | ||
277 | SOCKET_SO=socket-$(SOCKET_V).$(SO) | ||
278 | MIME_SO=mime-$(MIME_V).$(SO) | ||
279 | UNIX_SO=unix.$(SO) | ||
280 | SERIAL_SO=serial.$(SO) | ||
281 | SOCKET=$(SOCKET_$(PLAT)) | ||
282 | |||
283 | #------ | ||
284 | # Settings selected for platform | ||
285 | # | ||
286 | CC=$(CC_$(PLAT)) | ||
287 | DEF=$(DEF_$(PLAT)) | ||
288 | CFLAGS=$(MYCFLAGS) $(CFLAGS_$(PLAT)) | ||
289 | LDFLAGS=$(MYLDFLAGS) $(LDFLAGS_$(PLAT)) | ||
290 | LD=$(LD_$(PLAT)) | ||
291 | LUAINC= $(LUAINC_$(PLAT)) | ||
292 | LUALIB= $(LUALIB_$(PLAT)) | ||
293 | |||
294 | #------ | ||
295 | # Modules belonging to socket-core | ||
296 | # | ||
297 | SOCKET_OBJS= \ | ||
298 | luasocket.$(O) \ | ||
299 | timeout.$(O) \ | ||
300 | buffer.$(O) \ | ||
301 | io.$(O) \ | ||
302 | auxiliar.$(O) \ | ||
303 | compat.$(O) \ | ||
304 | options.$(O) \ | ||
305 | inet.$(O) \ | ||
306 | $(SOCKET) \ | ||
307 | except.$(O) \ | ||
308 | select.$(O) \ | ||
309 | tcp.$(O) \ | ||
310 | udp.$(O) | ||
311 | |||
312 | #------ | ||
313 | # Modules belonging mime-core | ||
314 | # | ||
315 | MIME_OBJS= \ | ||
316 | mime.$(O) \ | ||
317 | compat.$(O) | ||
318 | |||
319 | #------ | ||
320 | # Modules belonging unix (local domain sockets) | ||
321 | # | ||
322 | UNIX_OBJS=\ | ||
323 | buffer.$(O) \ | ||
324 | auxiliar.$(O) \ | ||
325 | options.$(O) \ | ||
326 | timeout.$(O) \ | ||
327 | io.$(O) \ | ||
328 | usocket.$(O) \ | ||
329 | unixstream.$(O) \ | ||
330 | unixdgram.$(O) \ | ||
331 | compat.$(O) \ | ||
332 | unix.$(O) | ||
333 | |||
334 | #------ | ||
335 | # Modules belonging to serial (device streams) | ||
336 | # | ||
337 | SERIAL_OBJS=\ | ||
338 | buffer.$(O) \ | ||
339 | compat.$(O) \ | ||
340 | auxiliar.$(O) \ | ||
341 | options.$(O) \ | ||
342 | timeout.$(O) \ | ||
343 | io.$(O) \ | ||
344 | usocket.$(O) \ | ||
345 | serial.$(O) | ||
346 | |||
347 | #------ | ||
348 | # Files to install | ||
349 | # | ||
350 | TO_SOCKET_LDIR= \ | ||
351 | http.lua \ | ||
352 | url.lua \ | ||
353 | tp.lua \ | ||
354 | ftp.lua \ | ||
355 | headers.lua \ | ||
356 | smtp.lua | ||
357 | |||
358 | TO_TOP_LDIR= \ | ||
359 | ltn12.lua \ | ||
360 | socket.lua \ | ||
361 | mime.lua | ||
362 | |||
363 | #------ | ||
364 | # Targets | ||
365 | # | ||
366 | default: $(PLAT) | ||
367 | |||
368 | |||
369 | freebsd: | ||
370 | $(MAKE) all-unix PLAT=freebsd | ||
371 | |||
372 | macosx: | ||
373 | $(MAKE) all-unix PLAT=macosx | ||
374 | |||
375 | win32: | ||
376 | $(MAKE) all PLAT=win32 | ||
377 | |||
378 | win64: | ||
379 | $(MAKE) all PLAT=win64 | ||
380 | |||
381 | linux: | ||
382 | $(MAKE) all-unix PLAT=linux | ||
383 | |||
384 | mingw: | ||
385 | $(MAKE) all PLAT=mingw | ||
386 | |||
387 | solaris: | ||
388 | $(MAKE) all-unix PLAT=solaris | ||
389 | |||
390 | none: | ||
391 | @echo "Please run" | ||
392 | @echo " make PLATFORM" | ||
393 | @echo "where PLATFORM is one of these:" | ||
394 | @echo " $(PLATS)" | ||
395 | |||
396 | all: $(SOCKET_SO) $(MIME_SO) | ||
397 | |||
398 | $(SOCKET_SO): $(SOCKET_OBJS) | ||
399 | $(LD) $(SOCKET_OBJS) $(LDFLAGS)$@ | ||
400 | |||
401 | $(MIME_SO): $(MIME_OBJS) | ||
402 | $(LD) $(MIME_OBJS) $(LDFLAGS)$@ | ||
403 | |||
404 | all-unix: all $(UNIX_SO) $(SERIAL_SO) | ||
405 | |||
406 | $(UNIX_SO): $(UNIX_OBJS) | ||
407 | $(LD) $(UNIX_OBJS) $(LDFLAGS)$@ | ||
408 | |||
409 | $(SERIAL_SO): $(SERIAL_OBJS) | ||
410 | $(LD) $(SERIAL_OBJS) $(LDFLAGS)$@ | ||
411 | |||
412 | install: | ||
413 | $(INSTALL_DIR) $(INSTALL_TOP_LDIR) | ||
414 | $(INSTALL_DATA) $(TO_TOP_LDIR) $(INSTALL_TOP_LDIR) | ||
415 | $(INSTALL_DIR) $(INSTALL_SOCKET_LDIR) | ||
416 | $(INSTALL_DATA) $(TO_SOCKET_LDIR) $(INSTALL_SOCKET_LDIR) | ||
417 | $(INSTALL_DIR) $(INSTALL_SOCKET_CDIR) | ||
418 | $(INSTALL_EXEC) $(SOCKET_SO) $(INSTALL_SOCKET_CDIR)/core.$(SO) | ||
419 | $(INSTALL_DIR) $(INSTALL_MIME_CDIR) | ||
420 | $(INSTALL_EXEC) $(MIME_SO) $(INSTALL_MIME_CDIR)/core.$(SO) | ||
421 | |||
422 | install-unix: install | ||
423 | $(INSTALL_EXEC) $(UNIX_SO) $(INSTALL_SOCKET_CDIR)/$(UNIX_SO) | ||
424 | $(INSTALL_EXEC) $(SERIAL_SO) $(INSTALL_SOCKET_CDIR)/$(SERIAL_SO) | ||
425 | |||
426 | local: | ||
427 | $(MAKE) install INSTALL_TOP_CDIR=.. INSTALL_TOP_LDIR=.. | ||
428 | |||
429 | clean: | ||
430 | rm -f $(SOCKET_SO) $(SOCKET_OBJS) $(SERIAL_OBJS) | ||
431 | rm -f $(MIME_SO) $(UNIX_SO) $(SERIAL_SO) $(MIME_OBJS) $(UNIX_OBJS) | ||
432 | |||
433 | .PHONY: all $(PLATS) default clean echo none | ||
434 | |||
435 | #------ | ||
436 | # List of dependencies | ||
437 | # | ||
438 | compat.$(O): compat.c compat.h | ||
439 | auxiliar.$(O): auxiliar.c auxiliar.h | ||
440 | buffer.$(O): buffer.c buffer.h io.h timeout.h | ||
441 | except.$(O): except.c except.h | ||
442 | inet.$(O): inet.c inet.h socket.h io.h timeout.h usocket.h | ||
443 | io.$(O): io.c io.h timeout.h | ||
444 | luasocket.$(O): luasocket.c luasocket.h auxiliar.h except.h \ | ||
445 | timeout.h buffer.h io.h inet.h socket.h usocket.h tcp.h \ | ||
446 | udp.h select.h | ||
447 | mime.$(O): mime.c mime.h | ||
448 | options.$(O): options.c auxiliar.h options.h socket.h io.h \ | ||
449 | timeout.h usocket.h inet.h | ||
450 | select.$(O): select.c socket.h io.h timeout.h usocket.h select.h | ||
451 | serial.$(O): serial.c auxiliar.h socket.h io.h timeout.h usocket.h \ | ||
452 | options.h unix.h buffer.h | ||
453 | tcp.$(O): tcp.c auxiliar.h socket.h io.h timeout.h usocket.h \ | ||
454 | inet.h options.h tcp.h buffer.h | ||
455 | timeout.$(O): timeout.c auxiliar.h timeout.h | ||
456 | udp.$(O): udp.c auxiliar.h socket.h io.h timeout.h usocket.h \ | ||
457 | inet.h options.h udp.h | ||
458 | unix.$(O): unix.c auxiliar.h socket.h io.h timeout.h usocket.h \ | ||
459 | options.h unix.h buffer.h | ||
460 | usocket.$(O): usocket.c socket.h io.h timeout.h usocket.h | ||
461 | wsocket.$(O): wsocket.c socket.h io.h timeout.h usocket.h | ||
diff --git a/vendor/luasocket/src/mbox.lua b/vendor/luasocket/src/mbox.lua new file mode 100644 index 00000000..12823b0a --- /dev/null +++ b/vendor/luasocket/src/mbox.lua | |||
@@ -0,0 +1,93 @@ | |||
1 | local _M = {} | ||
2 | |||
3 | if module then | ||
4 | mbox = _M -- luacheck: ignore | ||
5 | end | ||
6 | |||
7 | function _M.split_message(message_s) | ||
8 | local message = {} | ||
9 | message_s = string.gsub(message_s, "\r\n", "\n") | ||
10 | string.gsub(message_s, "^(.-\n)\n", function (h) message.headers = h end) | ||
11 | string.gsub(message_s, "^.-\n\n(.*)", function (b) message.body = b end) | ||
12 | if not message.body then | ||
13 | string.gsub(message_s, "^\n(.*)", function (b) message.body = b end) | ||
14 | end | ||
15 | if not message.headers and not message.body then | ||
16 | message.headers = message_s | ||
17 | end | ||
18 | return message.headers or "", message.body or "" | ||
19 | end | ||
20 | |||
21 | function _M.split_headers(headers_s) | ||
22 | local headers = {} | ||
23 | headers_s = string.gsub(headers_s, "\r\n", "\n") | ||
24 | headers_s = string.gsub(headers_s, "\n[ ]+", " ") | ||
25 | string.gsub("\n" .. headers_s, "\n([^\n]+)", function (h) table.insert(headers, h) end) | ||
26 | return headers | ||
27 | end | ||
28 | |||
29 | function _M.parse_header(header_s) | ||
30 | header_s = string.gsub(header_s, "\n[ ]+", " ") | ||
31 | header_s = string.gsub(header_s, "\n+", "") | ||
32 | local _, _, name, value = string.find(header_s, "([^%s:]-):%s*(.*)") | ||
33 | return name, value | ||
34 | end | ||
35 | |||
36 | function _M.parse_headers(headers_s) | ||
37 | local headers_t = _M.split_headers(headers_s) | ||
38 | local headers = {} | ||
39 | for i = 1, #headers_t do | ||
40 | local name, value = _M.parse_header(headers_t[i]) | ||
41 | if name then | ||
42 | name = string.lower(name) | ||
43 | if headers[name] then | ||
44 | headers[name] = headers[name] .. ", " .. value | ||
45 | else headers[name] = value end | ||
46 | end | ||
47 | end | ||
48 | return headers | ||
49 | end | ||
50 | |||
51 | function _M.parse_from(from) | ||
52 | local _, _, name, address = string.find(from, "^%s*(.-)%s*%<(.-)%>") | ||
53 | if not address then | ||
54 | _, _, address = string.find(from, "%s*(.+)%s*") | ||
55 | end | ||
56 | name = name or "" | ||
57 | address = address or "" | ||
58 | if name == "" then name = address end | ||
59 | name = string.gsub(name, '"', "") | ||
60 | return name, address | ||
61 | end | ||
62 | |||
63 | function _M.split_mbox(mbox_s) | ||
64 | local mbox = {} | ||
65 | mbox_s = string.gsub(mbox_s, "\r\n", "\n") .."\n\nFrom \n" | ||
66 | local nj, i | ||
67 | local j = 1 | ||
68 | while 1 do | ||
69 | i, nj = string.find(mbox_s, "\n\nFrom .-\n", j) | ||
70 | if not i then break end | ||
71 | local message = string.sub(mbox_s, j, i-1) | ||
72 | table.insert(mbox, message) | ||
73 | j = nj+1 | ||
74 | end | ||
75 | return mbox | ||
76 | end | ||
77 | |||
78 | function _M.parse(mbox_s) | ||
79 | local mbox = _M.split_mbox(mbox_s) | ||
80 | for i = 1, #mbox do | ||
81 | mbox[i] = _M.parse_message(mbox[i]) | ||
82 | end | ||
83 | return mbox | ||
84 | end | ||
85 | |||
86 | function _M.parse_message(message_s) | ||
87 | local message = {} | ||
88 | message.headers, message.body = _M.split_message(message_s) | ||
89 | message.headers = _M.parse_headers(message.headers) | ||
90 | return message | ||
91 | end | ||
92 | |||
93 | return _M | ||
diff --git a/vendor/luasocket/src/mime.c b/vendor/luasocket/src/mime.c new file mode 100755 index 00000000..05602f56 --- /dev/null +++ b/vendor/luasocket/src/mime.c | |||
@@ -0,0 +1,852 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * MIME support functions | ||
3 | * LuaSocket toolkit | ||
4 | \*=========================================================================*/ | ||
5 | #include "luasocket.h" | ||
6 | #include "mime.h" | ||
7 | #include <string.h> | ||
8 | #include <ctype.h> | ||
9 | |||
10 | /*=========================================================================*\ | ||
11 | * Don't want to trust escape character constants | ||
12 | \*=========================================================================*/ | ||
13 | typedef unsigned char UC; | ||
14 | static const char CRLF[] = "\r\n"; | ||
15 | static const char EQCRLF[] = "=\r\n"; | ||
16 | |||
17 | /*=========================================================================*\ | ||
18 | * Internal function prototypes. | ||
19 | \*=========================================================================*/ | ||
20 | static int mime_global_wrp(lua_State *L); | ||
21 | static int mime_global_b64(lua_State *L); | ||
22 | static int mime_global_unb64(lua_State *L); | ||
23 | static int mime_global_qp(lua_State *L); | ||
24 | static int mime_global_unqp(lua_State *L); | ||
25 | static int mime_global_qpwrp(lua_State *L); | ||
26 | static int mime_global_eol(lua_State *L); | ||
27 | static int mime_global_dot(lua_State *L); | ||
28 | |||
29 | static size_t dot(int c, size_t state, luaL_Buffer *buffer); | ||
30 | /*static void b64setup(UC *base);*/ | ||
31 | static size_t b64encode(UC c, UC *input, size_t size, luaL_Buffer *buffer); | ||
32 | static size_t b64pad(const UC *input, size_t size, luaL_Buffer *buffer); | ||
33 | static size_t b64decode(UC c, UC *input, size_t size, luaL_Buffer *buffer); | ||
34 | |||
35 | /*static void qpsetup(UC *class, UC *unbase);*/ | ||
36 | static void qpquote(UC c, luaL_Buffer *buffer); | ||
37 | static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer); | ||
38 | static size_t qpencode(UC c, UC *input, size_t size, | ||
39 | const char *marker, luaL_Buffer *buffer); | ||
40 | static size_t qppad(UC *input, size_t size, luaL_Buffer *buffer); | ||
41 | |||
42 | /* code support functions */ | ||
43 | static luaL_Reg func[] = { | ||
44 | { "dot", mime_global_dot }, | ||
45 | { "b64", mime_global_b64 }, | ||
46 | { "eol", mime_global_eol }, | ||
47 | { "qp", mime_global_qp }, | ||
48 | { "qpwrp", mime_global_qpwrp }, | ||
49 | { "unb64", mime_global_unb64 }, | ||
50 | { "unqp", mime_global_unqp }, | ||
51 | { "wrp", mime_global_wrp }, | ||
52 | { NULL, NULL } | ||
53 | }; | ||
54 | |||
55 | /*-------------------------------------------------------------------------*\ | ||
56 | * Quoted-printable globals | ||
57 | \*-------------------------------------------------------------------------*/ | ||
58 | enum {QP_PLAIN, QP_QUOTED, QP_CR, QP_IF_LAST}; | ||
59 | |||
60 | static const UC qpclass[] = { | ||
61 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
62 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_IF_LAST, QP_QUOTED, QP_QUOTED, | ||
63 | QP_QUOTED, QP_CR, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
64 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
65 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
66 | QP_QUOTED, QP_QUOTED, QP_IF_LAST, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
67 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
68 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
69 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
70 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
71 | QP_PLAIN, QP_QUOTED, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
72 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
73 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
74 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
75 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
76 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
77 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
78 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
79 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
80 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
81 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
82 | QP_PLAIN, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
83 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
84 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
85 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
86 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
87 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
88 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
89 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
90 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
91 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
92 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
93 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
94 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
95 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
96 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
97 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
98 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
99 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
100 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
101 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
102 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
103 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED | ||
104 | }; | ||
105 | |||
106 | static const UC qpbase[] = "0123456789ABCDEF"; | ||
107 | |||
108 | static const UC qpunbase[] = { | ||
109 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
110 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
111 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
112 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
113 | 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, | ||
114 | 255, 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, | ||
115 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
116 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
117 | 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 255, 255, | ||
118 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
119 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
120 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
121 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
122 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
123 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
124 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
125 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
126 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
127 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
128 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
129 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
130 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
131 | 255, 255, 255, 255, 255, 255, 255, 255 | ||
132 | }; | ||
133 | |||
134 | /*-------------------------------------------------------------------------*\ | ||
135 | * Base64 globals | ||
136 | \*-------------------------------------------------------------------------*/ | ||
137 | static const UC b64base[] = | ||
138 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | ||
139 | |||
140 | static const UC b64unbase[] = { | ||
141 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
142 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
143 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
144 | 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63, | ||
145 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 0, | ||
146 | 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, | ||
147 | 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, | ||
148 | 255, 255, 255, 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, | ||
149 | 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, | ||
150 | 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
151 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
152 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
153 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
154 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
155 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
156 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
157 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
158 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
159 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
160 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
161 | 255, 255 | ||
162 | }; | ||
163 | |||
164 | /*=========================================================================*\ | ||
165 | * Exported functions | ||
166 | \*=========================================================================*/ | ||
167 | /*-------------------------------------------------------------------------*\ | ||
168 | * Initializes module | ||
169 | \*-------------------------------------------------------------------------*/ | ||
170 | LUASOCKET_API int luaopen_mime_core(lua_State *L) | ||
171 | { | ||
172 | lua_newtable(L); | ||
173 | luaL_setfuncs(L, func, 0); | ||
174 | /* make version string available to scripts */ | ||
175 | lua_pushstring(L, "_VERSION"); | ||
176 | lua_pushstring(L, MIME_VERSION); | ||
177 | lua_rawset(L, -3); | ||
178 | /* initialize lookup tables */ | ||
179 | /*qpsetup(qpclass, qpunbase);*/ | ||
180 | /*b64setup(b64unbase);*/ | ||
181 | return 1; | ||
182 | } | ||
183 | |||
184 | /*=========================================================================*\ | ||
185 | * Global Lua functions | ||
186 | \*=========================================================================*/ | ||
187 | /*-------------------------------------------------------------------------*\ | ||
188 | * Incrementaly breaks a string into lines. The string can have CRLF breaks. | ||
189 | * A, n = wrp(l, B, length) | ||
190 | * A is a copy of B, broken into lines of at most 'length' bytes. | ||
191 | * 'l' is how many bytes are left for the first line of B. | ||
192 | * 'n' is the number of bytes left in the last line of A. | ||
193 | \*-------------------------------------------------------------------------*/ | ||
194 | static int mime_global_wrp(lua_State *L) | ||
195 | { | ||
196 | size_t size = 0; | ||
197 | int left = (int) luaL_checknumber(L, 1); | ||
198 | const UC *input = (const UC *) luaL_optlstring(L, 2, NULL, &size); | ||
199 | const UC *last = input + size; | ||
200 | int length = (int) luaL_optnumber(L, 3, 76); | ||
201 | luaL_Buffer buffer; | ||
202 | /* end of input black-hole */ | ||
203 | if (!input) { | ||
204 | /* if last line has not been terminated, add a line break */ | ||
205 | if (left < length) lua_pushstring(L, CRLF); | ||
206 | /* otherwise, we are done */ | ||
207 | else lua_pushnil(L); | ||
208 | lua_pushnumber(L, length); | ||
209 | return 2; | ||
210 | } | ||
211 | luaL_buffinit(L, &buffer); | ||
212 | while (input < last) { | ||
213 | switch (*input) { | ||
214 | case '\r': | ||
215 | break; | ||
216 | case '\n': | ||
217 | luaL_addstring(&buffer, CRLF); | ||
218 | left = length; | ||
219 | break; | ||
220 | default: | ||
221 | if (left <= 0) { | ||
222 | left = length; | ||
223 | luaL_addstring(&buffer, CRLF); | ||
224 | } | ||
225 | luaL_addchar(&buffer, *input); | ||
226 | left--; | ||
227 | break; | ||
228 | } | ||
229 | input++; | ||
230 | } | ||
231 | luaL_pushresult(&buffer); | ||
232 | lua_pushnumber(L, left); | ||
233 | return 2; | ||
234 | } | ||
235 | |||
236 | #if 0 | ||
237 | /*-------------------------------------------------------------------------*\ | ||
238 | * Fill base64 decode map. | ||
239 | \*-------------------------------------------------------------------------*/ | ||
240 | static void b64setup(UC *unbase) | ||
241 | { | ||
242 | int i; | ||
243 | for (i = 0; i <= 255; i++) unbase[i] = (UC) 255; | ||
244 | for (i = 0; i < 64; i++) unbase[b64base[i]] = (UC) i; | ||
245 | unbase['='] = 0; | ||
246 | |||
247 | printf("static const UC b64unbase[] = {\n"); | ||
248 | for (int i = 0; i < 256; i++) { | ||
249 | printf("%d, ", unbase[i]); | ||
250 | } | ||
251 | printf("\n}\n;"); | ||
252 | } | ||
253 | #endif | ||
254 | |||
255 | /*-------------------------------------------------------------------------*\ | ||
256 | * Acumulates bytes in input buffer until 3 bytes are available. | ||
257 | * Translate the 3 bytes into Base64 form and append to buffer. | ||
258 | * Returns new number of bytes in buffer. | ||
259 | \*-------------------------------------------------------------------------*/ | ||
260 | static size_t b64encode(UC c, UC *input, size_t size, | ||
261 | luaL_Buffer *buffer) | ||
262 | { | ||
263 | input[size++] = c; | ||
264 | if (size == 3) { | ||
265 | UC code[4]; | ||
266 | unsigned long value = 0; | ||
267 | value += input[0]; value <<= 8; | ||
268 | value += input[1]; value <<= 8; | ||
269 | value += input[2]; | ||
270 | code[3] = b64base[value & 0x3f]; value >>= 6; | ||
271 | code[2] = b64base[value & 0x3f]; value >>= 6; | ||
272 | code[1] = b64base[value & 0x3f]; value >>= 6; | ||
273 | code[0] = b64base[value]; | ||
274 | luaL_addlstring(buffer, (char *) code, 4); | ||
275 | size = 0; | ||
276 | } | ||
277 | return size; | ||
278 | } | ||
279 | |||
280 | /*-------------------------------------------------------------------------*\ | ||
281 | * Encodes the Base64 last 1 or 2 bytes and adds padding '=' | ||
282 | * Result, if any, is appended to buffer. | ||
283 | * Returns 0. | ||
284 | \*-------------------------------------------------------------------------*/ | ||
285 | static size_t b64pad(const UC *input, size_t size, | ||
286 | luaL_Buffer *buffer) | ||
287 | { | ||
288 | unsigned long value = 0; | ||
289 | UC code[4] = {'=', '=', '=', '='}; | ||
290 | switch (size) { | ||
291 | case 1: | ||
292 | value = input[0] << 4; | ||
293 | code[1] = b64base[value & 0x3f]; value >>= 6; | ||
294 | code[0] = b64base[value]; | ||
295 | luaL_addlstring(buffer, (char *) code, 4); | ||
296 | break; | ||
297 | case 2: | ||
298 | value = input[0]; value <<= 8; | ||
299 | value |= input[1]; value <<= 2; | ||
300 | code[2] = b64base[value & 0x3f]; value >>= 6; | ||
301 | code[1] = b64base[value & 0x3f]; value >>= 6; | ||
302 | code[0] = b64base[value]; | ||
303 | luaL_addlstring(buffer, (char *) code, 4); | ||
304 | break; | ||
305 | default: | ||
306 | break; | ||
307 | } | ||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | /*-------------------------------------------------------------------------*\ | ||
312 | * Acumulates bytes in input buffer until 4 bytes are available. | ||
313 | * Translate the 4 bytes from Base64 form and append to buffer. | ||
314 | * Returns new number of bytes in buffer. | ||
315 | \*-------------------------------------------------------------------------*/ | ||
316 | static size_t b64decode(UC c, UC *input, size_t size, | ||
317 | luaL_Buffer *buffer) | ||
318 | { | ||
319 | /* ignore invalid characters */ | ||
320 | if (b64unbase[c] > 64) return size; | ||
321 | input[size++] = c; | ||
322 | /* decode atom */ | ||
323 | if (size == 4) { | ||
324 | UC decoded[3]; | ||
325 | int valid, value = 0; | ||
326 | value = b64unbase[input[0]]; value <<= 6; | ||
327 | value |= b64unbase[input[1]]; value <<= 6; | ||
328 | value |= b64unbase[input[2]]; value <<= 6; | ||
329 | value |= b64unbase[input[3]]; | ||
330 | decoded[2] = (UC) (value & 0xff); value >>= 8; | ||
331 | decoded[1] = (UC) (value & 0xff); value >>= 8; | ||
332 | decoded[0] = (UC) value; | ||
333 | /* take care of paddding */ | ||
334 | valid = (input[2] == '=') ? 1 : (input[3] == '=') ? 2 : 3; | ||
335 | luaL_addlstring(buffer, (char *) decoded, valid); | ||
336 | return 0; | ||
337 | /* need more data */ | ||
338 | } else return size; | ||
339 | } | ||
340 | |||
341 | /*-------------------------------------------------------------------------*\ | ||
342 | * Incrementally applies the Base64 transfer content encoding to a string | ||
343 | * A, B = b64(C, D) | ||
344 | * A is the encoded version of the largest prefix of C .. D that is | ||
345 | * divisible by 3. B has the remaining bytes of C .. D, *without* encoding. | ||
346 | * The easiest thing would be to concatenate the two strings and | ||
347 | * encode the result, but we can't afford that or Lua would dupplicate | ||
348 | * every chunk we received. | ||
349 | \*-------------------------------------------------------------------------*/ | ||
350 | static int mime_global_b64(lua_State *L) | ||
351 | { | ||
352 | UC atom[3]; | ||
353 | size_t isize = 0, asize = 0; | ||
354 | const UC *input = (const UC *) luaL_optlstring(L, 1, NULL, &isize); | ||
355 | const UC *last = input + isize; | ||
356 | luaL_Buffer buffer; | ||
357 | /* end-of-input blackhole */ | ||
358 | if (!input) { | ||
359 | lua_pushnil(L); | ||
360 | lua_pushnil(L); | ||
361 | return 2; | ||
362 | } | ||
363 | /* make sure we don't confuse buffer stuff with arguments */ | ||
364 | lua_settop(L, 2); | ||
365 | /* process first part of the input */ | ||
366 | luaL_buffinit(L, &buffer); | ||
367 | while (input < last) | ||
368 | asize = b64encode(*input++, atom, asize, &buffer); | ||
369 | input = (const UC *) luaL_optlstring(L, 2, NULL, &isize); | ||
370 | /* if second part is nil, we are done */ | ||
371 | if (!input) { | ||
372 | size_t osize = 0; | ||
373 | asize = b64pad(atom, asize, &buffer); | ||
374 | luaL_pushresult(&buffer); | ||
375 | /* if the output is empty and the input is nil, return nil */ | ||
376 | lua_tolstring(L, -1, &osize); | ||
377 | if (osize == 0) lua_pushnil(L); | ||
378 | lua_pushnil(L); | ||
379 | return 2; | ||
380 | } | ||
381 | /* otherwise process the second part */ | ||
382 | last = input + isize; | ||
383 | while (input < last) | ||
384 | asize = b64encode(*input++, atom, asize, &buffer); | ||
385 | luaL_pushresult(&buffer); | ||
386 | lua_pushlstring(L, (char *) atom, asize); | ||
387 | return 2; | ||
388 | } | ||
389 | |||
390 | /*-------------------------------------------------------------------------*\ | ||
391 | * Incrementally removes the Base64 transfer content encoding from a string | ||
392 | * A, B = b64(C, D) | ||
393 | * A is the encoded version of the largest prefix of C .. D that is | ||
394 | * divisible by 4. B has the remaining bytes of C .. D, *without* encoding. | ||
395 | \*-------------------------------------------------------------------------*/ | ||
396 | static int mime_global_unb64(lua_State *L) | ||
397 | { | ||
398 | UC atom[4]; | ||
399 | size_t isize = 0, asize = 0; | ||
400 | const UC *input = (const UC *) luaL_optlstring(L, 1, NULL, &isize); | ||
401 | const UC *last = input + isize; | ||
402 | luaL_Buffer buffer; | ||
403 | /* end-of-input blackhole */ | ||
404 | if (!input) { | ||
405 | lua_pushnil(L); | ||
406 | lua_pushnil(L); | ||
407 | return 2; | ||
408 | } | ||
409 | /* make sure we don't confuse buffer stuff with arguments */ | ||
410 | lua_settop(L, 2); | ||
411 | /* process first part of the input */ | ||
412 | luaL_buffinit(L, &buffer); | ||
413 | while (input < last) | ||
414 | asize = b64decode(*input++, atom, asize, &buffer); | ||
415 | input = (const UC *) luaL_optlstring(L, 2, NULL, &isize); | ||
416 | /* if second is nil, we are done */ | ||
417 | if (!input) { | ||
418 | size_t osize = 0; | ||
419 | luaL_pushresult(&buffer); | ||
420 | /* if the output is empty and the input is nil, return nil */ | ||
421 | lua_tolstring(L, -1, &osize); | ||
422 | if (osize == 0) lua_pushnil(L); | ||
423 | lua_pushnil(L); | ||
424 | return 2; | ||
425 | } | ||
426 | /* otherwise, process the rest of the input */ | ||
427 | last = input + isize; | ||
428 | while (input < last) | ||
429 | asize = b64decode(*input++, atom, asize, &buffer); | ||
430 | luaL_pushresult(&buffer); | ||
431 | lua_pushlstring(L, (char *) atom, asize); | ||
432 | return 2; | ||
433 | } | ||
434 | |||
435 | /*-------------------------------------------------------------------------*\ | ||
436 | * Quoted-printable encoding scheme | ||
437 | * all (except CRLF in text) can be =XX | ||
438 | * CLRL in not text must be =XX=XX | ||
439 | * 33 through 60 inclusive can be plain | ||
440 | * 62 through 126 inclusive can be plain | ||
441 | * 9 and 32 can be plain, unless in the end of a line, where must be =XX | ||
442 | * encoded lines must be no longer than 76 not counting CRLF | ||
443 | * soft line-break are =CRLF | ||
444 | * To encode one byte, we need to see the next two. | ||
445 | * Worst case is when we see a space, and wonder if a CRLF is comming | ||
446 | \*-------------------------------------------------------------------------*/ | ||
447 | #if 0 | ||
448 | /*-------------------------------------------------------------------------*\ | ||
449 | * Split quoted-printable characters into classes | ||
450 | * Precompute reverse map for encoding | ||
451 | \*-------------------------------------------------------------------------*/ | ||
452 | static void qpsetup(UC *cl, UC *unbase) | ||
453 | { | ||
454 | |||
455 | int i; | ||
456 | for (i = 0; i < 256; i++) cl[i] = QP_QUOTED; | ||
457 | for (i = 33; i <= 60; i++) cl[i] = QP_PLAIN; | ||
458 | for (i = 62; i <= 126; i++) cl[i] = QP_PLAIN; | ||
459 | cl['\t'] = QP_IF_LAST; | ||
460 | cl[' '] = QP_IF_LAST; | ||
461 | cl['\r'] = QP_CR; | ||
462 | for (i = 0; i < 256; i++) unbase[i] = 255; | ||
463 | unbase['0'] = 0; unbase['1'] = 1; unbase['2'] = 2; | ||
464 | unbase['3'] = 3; unbase['4'] = 4; unbase['5'] = 5; | ||
465 | unbase['6'] = 6; unbase['7'] = 7; unbase['8'] = 8; | ||
466 | unbase['9'] = 9; unbase['A'] = 10; unbase['a'] = 10; | ||
467 | unbase['B'] = 11; unbase['b'] = 11; unbase['C'] = 12; | ||
468 | unbase['c'] = 12; unbase['D'] = 13; unbase['d'] = 13; | ||
469 | unbase['E'] = 14; unbase['e'] = 14; unbase['F'] = 15; | ||
470 | unbase['f'] = 15; | ||
471 | |||
472 | printf("static UC qpclass[] = {"); | ||
473 | for (int i = 0; i < 256; i++) { | ||
474 | if (i % 6 == 0) { | ||
475 | printf("\n "); | ||
476 | } | ||
477 | switch(cl[i]) { | ||
478 | case QP_QUOTED: | ||
479 | printf("QP_QUOTED, "); | ||
480 | break; | ||
481 | case QP_PLAIN: | ||
482 | printf("QP_PLAIN, "); | ||
483 | break; | ||
484 | case QP_CR: | ||
485 | printf("QP_CR, "); | ||
486 | break; | ||
487 | case QP_IF_LAST: | ||
488 | printf("QP_IF_LAST, "); | ||
489 | break; | ||
490 | } | ||
491 | } | ||
492 | printf("\n};\n"); | ||
493 | |||
494 | printf("static const UC qpunbase[] = {"); | ||
495 | for (int i = 0; i < 256; i++) { | ||
496 | int c = qpunbase[i]; | ||
497 | printf("%d, ", c); | ||
498 | } | ||
499 | printf("\";\n"); | ||
500 | } | ||
501 | #endif | ||
502 | |||
503 | /*-------------------------------------------------------------------------*\ | ||
504 | * Output one character in form =XX | ||
505 | \*-------------------------------------------------------------------------*/ | ||
506 | static void qpquote(UC c, luaL_Buffer *buffer) | ||
507 | { | ||
508 | luaL_addchar(buffer, '='); | ||
509 | luaL_addchar(buffer, qpbase[c >> 4]); | ||
510 | luaL_addchar(buffer, qpbase[c & 0x0F]); | ||
511 | } | ||
512 | |||
513 | /*-------------------------------------------------------------------------*\ | ||
514 | * Accumulate characters until we are sure about how to deal with them. | ||
515 | * Once we are sure, output to the buffer, in the correct form. | ||
516 | \*-------------------------------------------------------------------------*/ | ||
517 | static size_t qpencode(UC c, UC *input, size_t size, | ||
518 | const char *marker, luaL_Buffer *buffer) | ||
519 | { | ||
520 | input[size++] = c; | ||
521 | /* deal with all characters we can have */ | ||
522 | while (size > 0) { | ||
523 | switch (qpclass[input[0]]) { | ||
524 | /* might be the CR of a CRLF sequence */ | ||
525 | case QP_CR: | ||
526 | if (size < 2) return size; | ||
527 | if (input[1] == '\n') { | ||
528 | luaL_addstring(buffer, marker); | ||
529 | return 0; | ||
530 | } else qpquote(input[0], buffer); | ||
531 | break; | ||
532 | /* might be a space and that has to be quoted if last in line */ | ||
533 | case QP_IF_LAST: | ||
534 | if (size < 3) return size; | ||
535 | /* if it is the last, quote it and we are done */ | ||
536 | if (input[1] == '\r' && input[2] == '\n') { | ||
537 | qpquote(input[0], buffer); | ||
538 | luaL_addstring(buffer, marker); | ||
539 | return 0; | ||
540 | } else luaL_addchar(buffer, input[0]); | ||
541 | break; | ||
542 | /* might have to be quoted always */ | ||
543 | case QP_QUOTED: | ||
544 | qpquote(input[0], buffer); | ||
545 | break; | ||
546 | /* might never have to be quoted */ | ||
547 | default: | ||
548 | luaL_addchar(buffer, input[0]); | ||
549 | break; | ||
550 | } | ||
551 | input[0] = input[1]; input[1] = input[2]; | ||
552 | size--; | ||
553 | } | ||
554 | return 0; | ||
555 | } | ||
556 | |||
557 | /*-------------------------------------------------------------------------*\ | ||
558 | * Deal with the final characters | ||
559 | \*-------------------------------------------------------------------------*/ | ||
560 | static size_t qppad(UC *input, size_t size, luaL_Buffer *buffer) | ||
561 | { | ||
562 | size_t i; | ||
563 | for (i = 0; i < size; i++) { | ||
564 | if (qpclass[input[i]] == QP_PLAIN) luaL_addchar(buffer, input[i]); | ||
565 | else qpquote(input[i], buffer); | ||
566 | } | ||
567 | if (size > 0) luaL_addstring(buffer, EQCRLF); | ||
568 | return 0; | ||
569 | } | ||
570 | |||
571 | /*-------------------------------------------------------------------------*\ | ||
572 | * Incrementally converts a string to quoted-printable | ||
573 | * A, B = qp(C, D, marker) | ||
574 | * Marker is the text to be used to replace CRLF sequences found in A. | ||
575 | * A is the encoded version of the largest prefix of C .. D that | ||
576 | * can be encoded without doubts. | ||
577 | * B has the remaining bytes of C .. D, *without* encoding. | ||
578 | \*-------------------------------------------------------------------------*/ | ||
579 | static int mime_global_qp(lua_State *L) | ||
580 | { | ||
581 | size_t asize = 0, isize = 0; | ||
582 | UC atom[3]; | ||
583 | const UC *input = (const UC *) luaL_optlstring(L, 1, NULL, &isize); | ||
584 | const UC *last = input + isize; | ||
585 | const char *marker = luaL_optstring(L, 3, CRLF); | ||
586 | luaL_Buffer buffer; | ||
587 | /* end-of-input blackhole */ | ||
588 | if (!input) { | ||
589 | lua_pushnil(L); | ||
590 | lua_pushnil(L); | ||
591 | return 2; | ||
592 | } | ||
593 | /* make sure we don't confuse buffer stuff with arguments */ | ||
594 | lua_settop(L, 3); | ||
595 | /* process first part of input */ | ||
596 | luaL_buffinit(L, &buffer); | ||
597 | while (input < last) | ||
598 | asize = qpencode(*input++, atom, asize, marker, &buffer); | ||
599 | input = (const UC *) luaL_optlstring(L, 2, NULL, &isize); | ||
600 | /* if second part is nil, we are done */ | ||
601 | if (!input) { | ||
602 | asize = qppad(atom, asize, &buffer); | ||
603 | luaL_pushresult(&buffer); | ||
604 | if (!(*lua_tostring(L, -1))) lua_pushnil(L); | ||
605 | lua_pushnil(L); | ||
606 | return 2; | ||
607 | } | ||
608 | /* otherwise process rest of input */ | ||
609 | last = input + isize; | ||
610 | while (input < last) | ||
611 | asize = qpencode(*input++, atom, asize, marker, &buffer); | ||
612 | luaL_pushresult(&buffer); | ||
613 | lua_pushlstring(L, (char *) atom, asize); | ||
614 | return 2; | ||
615 | } | ||
616 | |||
617 | /*-------------------------------------------------------------------------*\ | ||
618 | * Accumulate characters until we are sure about how to deal with them. | ||
619 | * Once we are sure, output the to the buffer, in the correct form. | ||
620 | \*-------------------------------------------------------------------------*/ | ||
621 | static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer) { | ||
622 | int d; | ||
623 | input[size++] = c; | ||
624 | /* deal with all characters we can deal */ | ||
625 | switch (input[0]) { | ||
626 | /* if we have an escape character */ | ||
627 | case '=': | ||
628 | if (size < 3) return size; | ||
629 | /* eliminate soft line break */ | ||
630 | if (input[1] == '\r' && input[2] == '\n') return 0; | ||
631 | /* decode quoted representation */ | ||
632 | c = qpunbase[input[1]]; d = qpunbase[input[2]]; | ||
633 | /* if it is an invalid, do not decode */ | ||
634 | if (c > 15 || d > 15) luaL_addlstring(buffer, (char *)input, 3); | ||
635 | else luaL_addchar(buffer, (char) ((c << 4) + d)); | ||
636 | return 0; | ||
637 | case '\r': | ||
638 | if (size < 2) return size; | ||
639 | if (input[1] == '\n') luaL_addlstring(buffer, (char *)input, 2); | ||
640 | return 0; | ||
641 | default: | ||
642 | if (input[0] == '\t' || (input[0] > 31 && input[0] < 127)) | ||
643 | luaL_addchar(buffer, input[0]); | ||
644 | return 0; | ||
645 | } | ||
646 | } | ||
647 | |||
648 | /*-------------------------------------------------------------------------*\ | ||
649 | * Incrementally decodes a string in quoted-printable | ||
650 | * A, B = qp(C, D) | ||
651 | * A is the decoded version of the largest prefix of C .. D that | ||
652 | * can be decoded without doubts. | ||
653 | * B has the remaining bytes of C .. D, *without* decoding. | ||
654 | \*-------------------------------------------------------------------------*/ | ||
655 | static int mime_global_unqp(lua_State *L) | ||
656 | { | ||
657 | size_t asize = 0, isize = 0; | ||
658 | UC atom[3]; | ||
659 | const UC *input = (const UC *) luaL_optlstring(L, 1, NULL, &isize); | ||
660 | const UC *last = input + isize; | ||
661 | luaL_Buffer buffer; | ||
662 | /* end-of-input blackhole */ | ||
663 | if (!input) { | ||
664 | lua_pushnil(L); | ||
665 | lua_pushnil(L); | ||
666 | return 2; | ||
667 | } | ||
668 | /* make sure we don't confuse buffer stuff with arguments */ | ||
669 | lua_settop(L, 2); | ||
670 | /* process first part of input */ | ||
671 | luaL_buffinit(L, &buffer); | ||
672 | while (input < last) | ||
673 | asize = qpdecode(*input++, atom, asize, &buffer); | ||
674 | input = (const UC *) luaL_optlstring(L, 2, NULL, &isize); | ||
675 | /* if second part is nil, we are done */ | ||
676 | if (!input) { | ||
677 | luaL_pushresult(&buffer); | ||
678 | if (!(*lua_tostring(L, -1))) lua_pushnil(L); | ||
679 | lua_pushnil(L); | ||
680 | return 2; | ||
681 | } | ||
682 | /* otherwise process rest of input */ | ||
683 | last = input + isize; | ||
684 | while (input < last) | ||
685 | asize = qpdecode(*input++, atom, asize, &buffer); | ||
686 | luaL_pushresult(&buffer); | ||
687 | lua_pushlstring(L, (char *) atom, asize); | ||
688 | return 2; | ||
689 | } | ||
690 | |||
691 | /*-------------------------------------------------------------------------*\ | ||
692 | * Incrementally breaks a quoted-printed string into lines | ||
693 | * A, n = qpwrp(l, B, length) | ||
694 | * A is a copy of B, broken into lines of at most 'length' bytes. | ||
695 | * 'l' is how many bytes are left for the first line of B. | ||
696 | * 'n' is the number of bytes left in the last line of A. | ||
697 | * There are two complications: lines can't be broken in the middle | ||
698 | * of an encoded =XX, and there might be line breaks already | ||
699 | \*-------------------------------------------------------------------------*/ | ||
700 | static int mime_global_qpwrp(lua_State *L) | ||
701 | { | ||
702 | size_t size = 0; | ||
703 | int left = (int) luaL_checknumber(L, 1); | ||
704 | const UC *input = (const UC *) luaL_optlstring(L, 2, NULL, &size); | ||
705 | const UC *last = input + size; | ||
706 | int length = (int) luaL_optnumber(L, 3, 76); | ||
707 | luaL_Buffer buffer; | ||
708 | /* end-of-input blackhole */ | ||
709 | if (!input) { | ||
710 | if (left < length) lua_pushstring(L, EQCRLF); | ||
711 | else lua_pushnil(L); | ||
712 | lua_pushnumber(L, length); | ||
713 | return 2; | ||
714 | } | ||
715 | /* process all input */ | ||
716 | luaL_buffinit(L, &buffer); | ||
717 | while (input < last) { | ||
718 | switch (*input) { | ||
719 | case '\r': | ||
720 | break; | ||
721 | case '\n': | ||
722 | left = length; | ||
723 | luaL_addstring(&buffer, CRLF); | ||
724 | break; | ||
725 | case '=': | ||
726 | if (left <= 3) { | ||
727 | left = length; | ||
728 | luaL_addstring(&buffer, EQCRLF); | ||
729 | } | ||
730 | luaL_addchar(&buffer, *input); | ||
731 | left--; | ||
732 | break; | ||
733 | default: | ||
734 | if (left <= 1) { | ||
735 | left = length; | ||
736 | luaL_addstring(&buffer, EQCRLF); | ||
737 | } | ||
738 | luaL_addchar(&buffer, *input); | ||
739 | left--; | ||
740 | break; | ||
741 | } | ||
742 | input++; | ||
743 | } | ||
744 | luaL_pushresult(&buffer); | ||
745 | lua_pushnumber(L, left); | ||
746 | return 2; | ||
747 | } | ||
748 | |||
749 | /*-------------------------------------------------------------------------*\ | ||
750 | * Here is what we do: \n, and \r are considered candidates for line | ||
751 | * break. We issue *one* new line marker if any of them is seen alone, or | ||
752 | * followed by a different one. That is, \n\n and \r\r will issue two | ||
753 | * end of line markers each, but \r\n, \n\r etc will only issue *one* | ||
754 | * marker. This covers Mac OS, Mac OS X, VMS, Unix and DOS, as well as | ||
755 | * probably other more obscure conventions. | ||
756 | * | ||
757 | * c is the current character being processed | ||
758 | * last is the previous character | ||
759 | \*-------------------------------------------------------------------------*/ | ||
760 | #define eolcandidate(c) (c == '\r' || c == '\n') | ||
761 | static int eolprocess(int c, int last, const char *marker, | ||
762 | luaL_Buffer *buffer) | ||
763 | { | ||
764 | if (eolcandidate(c)) { | ||
765 | if (eolcandidate(last)) { | ||
766 | if (c == last) luaL_addstring(buffer, marker); | ||
767 | return 0; | ||
768 | } else { | ||
769 | luaL_addstring(buffer, marker); | ||
770 | return c; | ||
771 | } | ||
772 | } else { | ||
773 | luaL_addchar(buffer, (char) c); | ||
774 | return 0; | ||
775 | } | ||
776 | } | ||
777 | |||
778 | /*-------------------------------------------------------------------------*\ | ||
779 | * Converts a string to uniform EOL convention. | ||
780 | * A, n = eol(o, B, marker) | ||
781 | * A is the converted version of the largest prefix of B that can be | ||
782 | * converted unambiguously. 'o' is the context returned by the previous | ||
783 | * call. 'n' is the new context. | ||
784 | \*-------------------------------------------------------------------------*/ | ||
785 | static int mime_global_eol(lua_State *L) | ||
786 | { | ||
787 | int ctx = (int) luaL_checkinteger(L, 1); | ||
788 | size_t isize = 0; | ||
789 | const char *input = luaL_optlstring(L, 2, NULL, &isize); | ||
790 | const char *last = input + isize; | ||
791 | const char *marker = luaL_optstring(L, 3, CRLF); | ||
792 | luaL_Buffer buffer; | ||
793 | luaL_buffinit(L, &buffer); | ||
794 | /* end of input blackhole */ | ||
795 | if (!input) { | ||
796 | lua_pushnil(L); | ||
797 | lua_pushnumber(L, 0); | ||
798 | return 2; | ||
799 | } | ||
800 | /* process all input */ | ||
801 | while (input < last) | ||
802 | ctx = eolprocess(*input++, ctx, marker, &buffer); | ||
803 | luaL_pushresult(&buffer); | ||
804 | lua_pushnumber(L, ctx); | ||
805 | return 2; | ||
806 | } | ||
807 | |||
808 | /*-------------------------------------------------------------------------*\ | ||
809 | * Takes one byte and stuff it if needed. | ||
810 | \*-------------------------------------------------------------------------*/ | ||
811 | static size_t dot(int c, size_t state, luaL_Buffer *buffer) | ||
812 | { | ||
813 | luaL_addchar(buffer, (char) c); | ||
814 | switch (c) { | ||
815 | case '\r': | ||
816 | return 1; | ||
817 | case '\n': | ||
818 | return (state == 1)? 2: 0; | ||
819 | case '.': | ||
820 | if (state == 2) | ||
821 | luaL_addchar(buffer, '.'); | ||
822 | /* Falls through. */ | ||
823 | default: | ||
824 | return 0; | ||
825 | } | ||
826 | } | ||
827 | |||
828 | /*-------------------------------------------------------------------------*\ | ||
829 | * Incrementally applies smtp stuffing to a string | ||
830 | * A, n = dot(l, D) | ||
831 | \*-------------------------------------------------------------------------*/ | ||
832 | static int mime_global_dot(lua_State *L) | ||
833 | { | ||
834 | size_t isize = 0, state = (size_t) luaL_checknumber(L, 1); | ||
835 | const char *input = luaL_optlstring(L, 2, NULL, &isize); | ||
836 | const char *last = input + isize; | ||
837 | luaL_Buffer buffer; | ||
838 | /* end-of-input blackhole */ | ||
839 | if (!input) { | ||
840 | lua_pushnil(L); | ||
841 | lua_pushnumber(L, 2); | ||
842 | return 2; | ||
843 | } | ||
844 | /* process all input */ | ||
845 | luaL_buffinit(L, &buffer); | ||
846 | while (input < last) | ||
847 | state = dot(*input++, state, &buffer); | ||
848 | luaL_pushresult(&buffer); | ||
849 | lua_pushnumber(L, (lua_Number) state); | ||
850 | return 2; | ||
851 | } | ||
852 | |||
diff --git a/vendor/luasocket/src/mime.h b/vendor/luasocket/src/mime.h new file mode 100644 index 00000000..4d938f46 --- /dev/null +++ b/vendor/luasocket/src/mime.h | |||
@@ -0,0 +1,22 @@ | |||
1 | #ifndef MIME_H | ||
2 | #define MIME_H | ||
3 | /*=========================================================================*\ | ||
4 | * Core MIME support | ||
5 | * LuaSocket toolkit | ||
6 | * | ||
7 | * This module provides functions to implement transfer content encodings | ||
8 | * and formatting conforming to RFC 2045. It is used by mime.lua, which | ||
9 | * provide a higher level interface to this functionality. | ||
10 | \*=========================================================================*/ | ||
11 | #include "luasocket.h" | ||
12 | |||
13 | /*-------------------------------------------------------------------------*\ | ||
14 | * Current MIME library version | ||
15 | \*-------------------------------------------------------------------------*/ | ||
16 | #define MIME_VERSION "MIME 1.0.3" | ||
17 | #define MIME_COPYRIGHT "Copyright (C) 2004-2013 Diego Nehab" | ||
18 | #define MIME_AUTHORS "Diego Nehab" | ||
19 | |||
20 | LUASOCKET_API int luaopen_mime_core(lua_State *L); | ||
21 | |||
22 | #endif /* MIME_H */ | ||
diff --git a/vendor/luasocket/src/mime.lua b/vendor/luasocket/src/mime.lua new file mode 100644 index 00000000..93539de6 --- /dev/null +++ b/vendor/luasocket/src/mime.lua | |||
@@ -0,0 +1,81 @@ | |||
1 | ----------------------------------------------------------------------------- | ||
2 | -- MIME support for the Lua language. | ||
3 | -- Author: Diego Nehab | ||
4 | -- Conforming to RFCs 2045-2049 | ||
5 | ----------------------------------------------------------------------------- | ||
6 | |||
7 | ----------------------------------------------------------------------------- | ||
8 | -- Declare module and import dependencies | ||
9 | ----------------------------------------------------------------------------- | ||
10 | local base = _G | ||
11 | local ltn12 = require("ltn12") | ||
12 | local mime = require("mime.core") | ||
13 | local _M = mime | ||
14 | |||
15 | -- encode, decode and wrap algorithm tables | ||
16 | local encodet, decodet, wrapt = {},{},{} | ||
17 | |||
18 | _M.encodet = encodet | ||
19 | _M.decodet = decodet | ||
20 | _M.wrapt = wrapt | ||
21 | |||
22 | -- creates a function that chooses a filter by name from a given table | ||
23 | local function choose(table) | ||
24 | return function(name, opt1, opt2) | ||
25 | if base.type(name) ~= "string" then | ||
26 | name, opt1, opt2 = "default", name, opt1 | ||
27 | end | ||
28 | local f = table[name or "nil"] | ||
29 | if not f then | ||
30 | base.error("unknown key (" .. base.tostring(name) .. ")", 3) | ||
31 | else return f(opt1, opt2) end | ||
32 | end | ||
33 | end | ||
34 | |||
35 | -- define the encoding filters | ||
36 | encodet['base64'] = function() | ||
37 | return ltn12.filter.cycle(_M.b64, "") | ||
38 | end | ||
39 | |||
40 | encodet['quoted-printable'] = function(mode) | ||
41 | return ltn12.filter.cycle(_M.qp, "", | ||
42 | (mode == "binary") and "=0D=0A" or "\r\n") | ||
43 | end | ||
44 | |||
45 | -- define the decoding filters | ||
46 | decodet['base64'] = function() | ||
47 | return ltn12.filter.cycle(_M.unb64, "") | ||
48 | end | ||
49 | |||
50 | decodet['quoted-printable'] = function() | ||
51 | return ltn12.filter.cycle(_M.unqp, "") | ||
52 | end | ||
53 | |||
54 | -- define the line-wrap filters | ||
55 | wrapt['text'] = function(length) | ||
56 | length = length or 76 | ||
57 | return ltn12.filter.cycle(_M.wrp, length, length) | ||
58 | end | ||
59 | wrapt['base64'] = wrapt['text'] | ||
60 | wrapt['default'] = wrapt['text'] | ||
61 | |||
62 | wrapt['quoted-printable'] = function() | ||
63 | return ltn12.filter.cycle(_M.qpwrp, 76, 76) | ||
64 | end | ||
65 | |||
66 | -- function that choose the encoding, decoding or wrap algorithm | ||
67 | _M.encode = choose(encodet) | ||
68 | _M.decode = choose(decodet) | ||
69 | _M.wrap = choose(wrapt) | ||
70 | |||
71 | -- define the end-of-line normalization filter | ||
72 | function _M.normalize(marker) | ||
73 | return ltn12.filter.cycle(_M.eol, 0, marker) | ||
74 | end | ||
75 | |||
76 | -- high level stuffing filter | ||
77 | function _M.stuff() | ||
78 | return ltn12.filter.cycle(_M.dot, 2) | ||
79 | end | ||
80 | |||
81 | return _M | ||
diff --git a/vendor/luasocket/src/options.c b/vendor/luasocket/src/options.c new file mode 100644 index 00000000..3280c51d --- /dev/null +++ b/vendor/luasocket/src/options.c | |||
@@ -0,0 +1,480 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * Common option interface | ||
3 | * LuaSocket toolkit | ||
4 | \*=========================================================================*/ | ||
5 | #include "luasocket.h" | ||
6 | #include "auxiliar.h" | ||
7 | #include "options.h" | ||
8 | #include "inet.h" | ||
9 | #include <string.h> | ||
10 | |||
11 | /*=========================================================================*\ | ||
12 | * Internal functions prototypes | ||
13 | \*=========================================================================*/ | ||
14 | static int opt_setmembership(lua_State *L, p_socket ps, int level, int name); | ||
15 | static int opt_ip6_setmembership(lua_State *L, p_socket ps, int level, int name); | ||
16 | static int opt_setboolean(lua_State *L, p_socket ps, int level, int name); | ||
17 | static int opt_getboolean(lua_State *L, p_socket ps, int level, int name); | ||
18 | static int opt_setint(lua_State *L, p_socket ps, int level, int name); | ||
19 | static int opt_getint(lua_State *L, p_socket ps, int level, int name); | ||
20 | static int opt_set(lua_State *L, p_socket ps, int level, int name, | ||
21 | void *val, int len); | ||
22 | static int opt_get(lua_State *L, p_socket ps, int level, int name, | ||
23 | void *val, int* len); | ||
24 | |||
25 | /*=========================================================================*\ | ||
26 | * Exported functions | ||
27 | \*=========================================================================*/ | ||
28 | /*-------------------------------------------------------------------------*\ | ||
29 | * Calls appropriate option handler | ||
30 | \*-------------------------------------------------------------------------*/ | ||
31 | int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps) | ||
32 | { | ||
33 | const char *name = luaL_checkstring(L, 2); /* obj, name, ... */ | ||
34 | while (opt->name && strcmp(name, opt->name)) | ||
35 | opt++; | ||
36 | if (!opt->func) { | ||
37 | char msg[57]; | ||
38 | sprintf(msg, "unsupported option `%.35s'", name); | ||
39 | luaL_argerror(L, 2, msg); | ||
40 | } | ||
41 | return opt->func(L, ps); | ||
42 | } | ||
43 | |||
44 | int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps) | ||
45 | { | ||
46 | const char *name = luaL_checkstring(L, 2); /* obj, name, ... */ | ||
47 | while (opt->name && strcmp(name, opt->name)) | ||
48 | opt++; | ||
49 | if (!opt->func) { | ||
50 | char msg[57]; | ||
51 | sprintf(msg, "unsupported option `%.35s'", name); | ||
52 | luaL_argerror(L, 2, msg); | ||
53 | } | ||
54 | return opt->func(L, ps); | ||
55 | } | ||
56 | |||
57 | /*------------------------------------------------------*/ | ||
58 | /* enables reuse of local address */ | ||
59 | int opt_set_reuseaddr(lua_State *L, p_socket ps) | ||
60 | { | ||
61 | return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEADDR); | ||
62 | } | ||
63 | |||
64 | int opt_get_reuseaddr(lua_State *L, p_socket ps) | ||
65 | { | ||
66 | return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEADDR); | ||
67 | } | ||
68 | |||
69 | /*------------------------------------------------------*/ | ||
70 | /* enables reuse of local port */ | ||
71 | int opt_set_reuseport(lua_State *L, p_socket ps) | ||
72 | { | ||
73 | return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEPORT); | ||
74 | } | ||
75 | |||
76 | int opt_get_reuseport(lua_State *L, p_socket ps) | ||
77 | { | ||
78 | return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEPORT); | ||
79 | } | ||
80 | |||
81 | /*------------------------------------------------------*/ | ||
82 | /* disables the Nagle algorithm */ | ||
83 | int opt_set_tcp_nodelay(lua_State *L, p_socket ps) | ||
84 | { | ||
85 | return opt_setboolean(L, ps, IPPROTO_TCP, TCP_NODELAY); | ||
86 | } | ||
87 | |||
88 | int opt_get_tcp_nodelay(lua_State *L, p_socket ps) | ||
89 | { | ||
90 | return opt_getboolean(L, ps, IPPROTO_TCP, TCP_NODELAY); | ||
91 | } | ||
92 | |||
93 | /*------------------------------------------------------*/ | ||
94 | #ifdef TCP_KEEPIDLE | ||
95 | |||
96 | int opt_get_tcp_keepidle(lua_State *L, p_socket ps) | ||
97 | { | ||
98 | return opt_getint(L, ps, IPPROTO_TCP, TCP_KEEPIDLE); | ||
99 | } | ||
100 | |||
101 | int opt_set_tcp_keepidle(lua_State *L, p_socket ps) | ||
102 | { | ||
103 | return opt_setint(L, ps, IPPROTO_TCP, TCP_KEEPIDLE); | ||
104 | } | ||
105 | |||
106 | #endif | ||
107 | |||
108 | /*------------------------------------------------------*/ | ||
109 | #ifdef TCP_KEEPCNT | ||
110 | |||
111 | int opt_get_tcp_keepcnt(lua_State *L, p_socket ps) | ||
112 | { | ||
113 | return opt_getint(L, ps, IPPROTO_TCP, TCP_KEEPCNT); | ||
114 | } | ||
115 | |||
116 | int opt_set_tcp_keepcnt(lua_State *L, p_socket ps) | ||
117 | { | ||
118 | return opt_setint(L, ps, IPPROTO_TCP, TCP_KEEPCNT); | ||
119 | } | ||
120 | |||
121 | #endif | ||
122 | |||
123 | /*------------------------------------------------------*/ | ||
124 | #ifdef TCP_KEEPINTVL | ||
125 | |||
126 | int opt_get_tcp_keepintvl(lua_State *L, p_socket ps) | ||
127 | { | ||
128 | return opt_getint(L, ps, IPPROTO_TCP, TCP_KEEPINTVL); | ||
129 | } | ||
130 | |||
131 | int opt_set_tcp_keepintvl(lua_State *L, p_socket ps) | ||
132 | { | ||
133 | return opt_setint(L, ps, IPPROTO_TCP, TCP_KEEPINTVL); | ||
134 | } | ||
135 | |||
136 | #endif | ||
137 | |||
138 | /*------------------------------------------------------*/ | ||
139 | int opt_set_keepalive(lua_State *L, p_socket ps) | ||
140 | { | ||
141 | return opt_setboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE); | ||
142 | } | ||
143 | |||
144 | int opt_get_keepalive(lua_State *L, p_socket ps) | ||
145 | { | ||
146 | return opt_getboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE); | ||
147 | } | ||
148 | |||
149 | /*------------------------------------------------------*/ | ||
150 | int opt_set_dontroute(lua_State *L, p_socket ps) | ||
151 | { | ||
152 | return opt_setboolean(L, ps, SOL_SOCKET, SO_DONTROUTE); | ||
153 | } | ||
154 | |||
155 | int opt_get_dontroute(lua_State *L, p_socket ps) | ||
156 | { | ||
157 | return opt_getboolean(L, ps, SOL_SOCKET, SO_DONTROUTE); | ||
158 | } | ||
159 | |||
160 | /*------------------------------------------------------*/ | ||
161 | int opt_set_broadcast(lua_State *L, p_socket ps) | ||
162 | { | ||
163 | return opt_setboolean(L, ps, SOL_SOCKET, SO_BROADCAST); | ||
164 | } | ||
165 | |||
166 | int opt_get_broadcast(lua_State *L, p_socket ps) | ||
167 | { | ||
168 | return opt_getboolean(L, ps, SOL_SOCKET, SO_BROADCAST); | ||
169 | } | ||
170 | |||
171 | /*------------------------------------------------------*/ | ||
172 | int opt_set_recv_buf_size(lua_State *L, p_socket ps) | ||
173 | { | ||
174 | return opt_setint(L, ps, SOL_SOCKET, SO_RCVBUF); | ||
175 | } | ||
176 | |||
177 | int opt_get_recv_buf_size(lua_State *L, p_socket ps) | ||
178 | { | ||
179 | return opt_getint(L, ps, SOL_SOCKET, SO_RCVBUF); | ||
180 | } | ||
181 | |||
182 | /*------------------------------------------------------*/ | ||
183 | int opt_get_send_buf_size(lua_State *L, p_socket ps) | ||
184 | { | ||
185 | return opt_getint(L, ps, SOL_SOCKET, SO_SNDBUF); | ||
186 | } | ||
187 | |||
188 | int opt_set_send_buf_size(lua_State *L, p_socket ps) | ||
189 | { | ||
190 | return opt_setint(L, ps, SOL_SOCKET, SO_SNDBUF); | ||
191 | } | ||
192 | |||
193 | // /*------------------------------------------------------*/ | ||
194 | |||
195 | #ifdef TCP_FASTOPEN | ||
196 | int opt_set_tcp_fastopen(lua_State *L, p_socket ps) | ||
197 | { | ||
198 | return opt_setint(L, ps, IPPROTO_TCP, TCP_FASTOPEN); | ||
199 | } | ||
200 | #endif | ||
201 | |||
202 | #ifdef TCP_FASTOPEN_CONNECT | ||
203 | int opt_set_tcp_fastopen_connect(lua_State *L, p_socket ps) | ||
204 | { | ||
205 | return opt_setint(L, ps, IPPROTO_TCP, TCP_FASTOPEN_CONNECT); | ||
206 | } | ||
207 | #endif | ||
208 | |||
209 | /*------------------------------------------------------*/ | ||
210 | |||
211 | #ifdef TCP_DEFER_ACCEPT | ||
212 | int opt_set_tcp_defer_accept(lua_State *L, p_socket ps) | ||
213 | { | ||
214 | return opt_setint(L, ps, IPPROTO_TCP, TCP_DEFER_ACCEPT); | ||
215 | } | ||
216 | #endif | ||
217 | |||
218 | /*------------------------------------------------------*/ | ||
219 | int opt_set_ip6_unicast_hops(lua_State *L, p_socket ps) | ||
220 | { | ||
221 | return opt_setint(L, ps, IPPROTO_IPV6, IPV6_UNICAST_HOPS); | ||
222 | } | ||
223 | |||
224 | int opt_get_ip6_unicast_hops(lua_State *L, p_socket ps) | ||
225 | { | ||
226 | return opt_getint(L, ps, IPPROTO_IPV6, IPV6_UNICAST_HOPS); | ||
227 | } | ||
228 | |||
229 | /*------------------------------------------------------*/ | ||
230 | int opt_set_ip6_multicast_hops(lua_State *L, p_socket ps) | ||
231 | { | ||
232 | return opt_setint(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_HOPS); | ||
233 | } | ||
234 | |||
235 | int opt_get_ip6_multicast_hops(lua_State *L, p_socket ps) | ||
236 | { | ||
237 | return opt_getint(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_HOPS); | ||
238 | } | ||
239 | |||
240 | /*------------------------------------------------------*/ | ||
241 | int opt_set_ip_multicast_loop(lua_State *L, p_socket ps) | ||
242 | { | ||
243 | return opt_setboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP); | ||
244 | } | ||
245 | |||
246 | int opt_get_ip_multicast_loop(lua_State *L, p_socket ps) | ||
247 | { | ||
248 | return opt_getboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP); | ||
249 | } | ||
250 | |||
251 | /*------------------------------------------------------*/ | ||
252 | int opt_set_ip6_multicast_loop(lua_State *L, p_socket ps) | ||
253 | { | ||
254 | return opt_setboolean(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_LOOP); | ||
255 | } | ||
256 | |||
257 | int opt_get_ip6_multicast_loop(lua_State *L, p_socket ps) | ||
258 | { | ||
259 | return opt_getboolean(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_LOOP); | ||
260 | } | ||
261 | |||
262 | /*------------------------------------------------------*/ | ||
263 | int opt_set_linger(lua_State *L, p_socket ps) | ||
264 | { | ||
265 | struct linger li; /* obj, name, table */ | ||
266 | if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE)); | ||
267 | lua_pushstring(L, "on"); | ||
268 | lua_gettable(L, 3); | ||
269 | if (!lua_isboolean(L, -1)) | ||
270 | luaL_argerror(L, 3, "boolean 'on' field expected"); | ||
271 | li.l_onoff = (u_short) lua_toboolean(L, -1); | ||
272 | lua_pushstring(L, "timeout"); | ||
273 | lua_gettable(L, 3); | ||
274 | if (!lua_isnumber(L, -1)) | ||
275 | luaL_argerror(L, 3, "number 'timeout' field expected"); | ||
276 | li.l_linger = (u_short) lua_tonumber(L, -1); | ||
277 | return opt_set(L, ps, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof(li)); | ||
278 | } | ||
279 | |||
280 | int opt_get_linger(lua_State *L, p_socket ps) | ||
281 | { | ||
282 | struct linger li; /* obj, name */ | ||
283 | int len = sizeof(li); | ||
284 | int err = opt_get(L, ps, SOL_SOCKET, SO_LINGER, (char *) &li, &len); | ||
285 | if (err) | ||
286 | return err; | ||
287 | lua_newtable(L); | ||
288 | lua_pushboolean(L, li.l_onoff); | ||
289 | lua_setfield(L, -2, "on"); | ||
290 | lua_pushinteger(L, li.l_linger); | ||
291 | lua_setfield(L, -2, "timeout"); | ||
292 | return 1; | ||
293 | } | ||
294 | |||
295 | /*------------------------------------------------------*/ | ||
296 | int opt_set_ip_multicast_ttl(lua_State *L, p_socket ps) | ||
297 | { | ||
298 | return opt_setint(L, ps, IPPROTO_IP, IP_MULTICAST_TTL); | ||
299 | } | ||
300 | |||
301 | /*------------------------------------------------------*/ | ||
302 | int opt_set_ip_multicast_if(lua_State *L, p_socket ps) | ||
303 | { | ||
304 | const char *address = luaL_checkstring(L, 3); /* obj, name, ip */ | ||
305 | struct in_addr val; | ||
306 | val.s_addr = htonl(INADDR_ANY); | ||
307 | if (strcmp(address, "*") && !inet_aton(address, &val)) | ||
308 | luaL_argerror(L, 3, "ip expected"); | ||
309 | return opt_set(L, ps, IPPROTO_IP, IP_MULTICAST_IF, | ||
310 | (char *) &val, sizeof(val)); | ||
311 | } | ||
312 | |||
313 | int opt_get_ip_multicast_if(lua_State *L, p_socket ps) | ||
314 | { | ||
315 | struct in_addr val; | ||
316 | socklen_t len = sizeof(val); | ||
317 | if (getsockopt(*ps, IPPROTO_IP, IP_MULTICAST_IF, (char *) &val, &len) < 0) { | ||
318 | lua_pushnil(L); | ||
319 | lua_pushstring(L, "getsockopt failed"); | ||
320 | return 2; | ||
321 | } | ||
322 | lua_pushstring(L, inet_ntoa(val)); | ||
323 | return 1; | ||
324 | } | ||
325 | |||
326 | /*------------------------------------------------------*/ | ||
327 | int opt_set_ip_add_membership(lua_State *L, p_socket ps) | ||
328 | { | ||
329 | return opt_setmembership(L, ps, IPPROTO_IP, IP_ADD_MEMBERSHIP); | ||
330 | } | ||
331 | |||
332 | int opt_set_ip_drop_membersip(lua_State *L, p_socket ps) | ||
333 | { | ||
334 | return opt_setmembership(L, ps, IPPROTO_IP, IP_DROP_MEMBERSHIP); | ||
335 | } | ||
336 | |||
337 | /*------------------------------------------------------*/ | ||
338 | int opt_set_ip6_add_membership(lua_State *L, p_socket ps) | ||
339 | { | ||
340 | return opt_ip6_setmembership(L, ps, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP); | ||
341 | } | ||
342 | |||
343 | int opt_set_ip6_drop_membersip(lua_State *L, p_socket ps) | ||
344 | { | ||
345 | return opt_ip6_setmembership(L, ps, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP); | ||
346 | } | ||
347 | |||
348 | /*------------------------------------------------------*/ | ||
349 | int opt_get_ip6_v6only(lua_State *L, p_socket ps) | ||
350 | { | ||
351 | return opt_getboolean(L, ps, IPPROTO_IPV6, IPV6_V6ONLY); | ||
352 | } | ||
353 | |||
354 | int opt_set_ip6_v6only(lua_State *L, p_socket ps) | ||
355 | { | ||
356 | return opt_setboolean(L, ps, IPPROTO_IPV6, IPV6_V6ONLY); | ||
357 | } | ||
358 | |||
359 | /*------------------------------------------------------*/ | ||
360 | int opt_get_error(lua_State *L, p_socket ps) | ||
361 | { | ||
362 | int val = 0; | ||
363 | socklen_t len = sizeof(val); | ||
364 | if (getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *) &val, &len) < 0) { | ||
365 | lua_pushnil(L); | ||
366 | lua_pushstring(L, "getsockopt failed"); | ||
367 | return 2; | ||
368 | } | ||
369 | lua_pushstring(L, socket_strerror(val)); | ||
370 | return 1; | ||
371 | } | ||
372 | |||
373 | /*=========================================================================*\ | ||
374 | * Auxiliar functions | ||
375 | \*=========================================================================*/ | ||
376 | static int opt_setmembership(lua_State *L, p_socket ps, int level, int name) | ||
377 | { | ||
378 | struct ip_mreq val; /* obj, name, table */ | ||
379 | if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE)); | ||
380 | lua_pushstring(L, "multiaddr"); | ||
381 | lua_gettable(L, 3); | ||
382 | if (!lua_isstring(L, -1)) | ||
383 | luaL_argerror(L, 3, "string 'multiaddr' field expected"); | ||
384 | if (!inet_aton(lua_tostring(L, -1), &val.imr_multiaddr)) | ||
385 | luaL_argerror(L, 3, "invalid 'multiaddr' ip address"); | ||
386 | lua_pushstring(L, "interface"); | ||
387 | lua_gettable(L, 3); | ||
388 | if (!lua_isstring(L, -1)) | ||
389 | luaL_argerror(L, 3, "string 'interface' field expected"); | ||
390 | val.imr_interface.s_addr = htonl(INADDR_ANY); | ||
391 | if (strcmp(lua_tostring(L, -1), "*") && | ||
392 | !inet_aton(lua_tostring(L, -1), &val.imr_interface)) | ||
393 | luaL_argerror(L, 3, "invalid 'interface' ip address"); | ||
394 | return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); | ||
395 | } | ||
396 | |||
397 | static int opt_ip6_setmembership(lua_State *L, p_socket ps, int level, int name) | ||
398 | { | ||
399 | struct ipv6_mreq val; /* obj, opt-name, table */ | ||
400 | memset(&val, 0, sizeof(val)); | ||
401 | if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE)); | ||
402 | lua_pushstring(L, "multiaddr"); | ||
403 | lua_gettable(L, 3); | ||
404 | if (!lua_isstring(L, -1)) | ||
405 | luaL_argerror(L, 3, "string 'multiaddr' field expected"); | ||
406 | if (!inet_pton(AF_INET6, lua_tostring(L, -1), &val.ipv6mr_multiaddr)) | ||
407 | luaL_argerror(L, 3, "invalid 'multiaddr' ip address"); | ||
408 | lua_pushstring(L, "interface"); | ||
409 | lua_gettable(L, 3); | ||
410 | /* By default we listen to interface on default route | ||
411 | * (sigh). However, interface= can override it. We should | ||
412 | * support either number, or name for it. Waiting for | ||
413 | * windows port of if_nametoindex */ | ||
414 | if (!lua_isnil(L, -1)) { | ||
415 | if (lua_isnumber(L, -1)) { | ||
416 | val.ipv6mr_interface = (unsigned int) lua_tonumber(L, -1); | ||
417 | } else | ||
418 | luaL_argerror(L, -1, "number 'interface' field expected"); | ||
419 | } | ||
420 | return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); | ||
421 | } | ||
422 | |||
423 | static | ||
424 | int opt_get(lua_State *L, p_socket ps, int level, int name, void *val, int* len) | ||
425 | { | ||
426 | socklen_t socklen = *len; | ||
427 | if (getsockopt(*ps, level, name, (char *) val, &socklen) < 0) { | ||
428 | lua_pushnil(L); | ||
429 | lua_pushstring(L, "getsockopt failed"); | ||
430 | return 2; | ||
431 | } | ||
432 | *len = socklen; | ||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | static | ||
437 | int opt_set(lua_State *L, p_socket ps, int level, int name, void *val, int len) | ||
438 | { | ||
439 | if (setsockopt(*ps, level, name, (char *) val, len) < 0) { | ||
440 | lua_pushnil(L); | ||
441 | lua_pushstring(L, "setsockopt failed"); | ||
442 | return 2; | ||
443 | } | ||
444 | lua_pushnumber(L, 1); | ||
445 | return 1; | ||
446 | } | ||
447 | |||
448 | static int opt_getboolean(lua_State *L, p_socket ps, int level, int name) | ||
449 | { | ||
450 | int val = 0; | ||
451 | int len = sizeof(val); | ||
452 | int err = opt_get(L, ps, level, name, (char *) &val, &len); | ||
453 | if (err) | ||
454 | return err; | ||
455 | lua_pushboolean(L, val); | ||
456 | return 1; | ||
457 | } | ||
458 | |||
459 | static int opt_setboolean(lua_State *L, p_socket ps, int level, int name) | ||
460 | { | ||
461 | int val = auxiliar_checkboolean(L, 3); /* obj, name, bool */ | ||
462 | return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); | ||
463 | } | ||
464 | |||
465 | static int opt_getint(lua_State *L, p_socket ps, int level, int name) | ||
466 | { | ||
467 | int val = 0; | ||
468 | int len = sizeof(val); | ||
469 | int err = opt_get(L, ps, level, name, (char *) &val, &len); | ||
470 | if (err) | ||
471 | return err; | ||
472 | lua_pushnumber(L, val); | ||
473 | return 1; | ||
474 | } | ||
475 | |||
476 | static int opt_setint(lua_State *L, p_socket ps, int level, int name) | ||
477 | { | ||
478 | int val = (int) lua_tonumber(L, 3); /* obj, name, int */ | ||
479 | return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); | ||
480 | } | ||
diff --git a/vendor/luasocket/src/options.h b/vendor/luasocket/src/options.h new file mode 100644 index 00000000..456eeb5f --- /dev/null +++ b/vendor/luasocket/src/options.h | |||
@@ -0,0 +1,113 @@ | |||
1 | #ifndef OPTIONS_H | ||
2 | #define OPTIONS_H | ||
3 | /*=========================================================================*\ | ||
4 | * Common option interface | ||
5 | * LuaSocket toolkit | ||
6 | * | ||
7 | * This module provides a common interface to socket options, used mainly by | ||
8 | * modules UDP and TCP. | ||
9 | \*=========================================================================*/ | ||
10 | |||
11 | #include "luasocket.h" | ||
12 | #include "socket.h" | ||
13 | |||
14 | /* option registry */ | ||
15 | typedef struct t_opt { | ||
16 | const char *name; | ||
17 | int (*func)(lua_State *L, p_socket ps); | ||
18 | } t_opt; | ||
19 | typedef t_opt *p_opt; | ||
20 | |||
21 | #ifndef _WIN32 | ||
22 | #pragma GCC visibility push(hidden) | ||
23 | #endif | ||
24 | |||
25 | int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps); | ||
26 | int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps); | ||
27 | |||
28 | int opt_set_reuseaddr(lua_State *L, p_socket ps); | ||
29 | int opt_get_reuseaddr(lua_State *L, p_socket ps); | ||
30 | |||
31 | int opt_set_reuseport(lua_State *L, p_socket ps); | ||
32 | int opt_get_reuseport(lua_State *L, p_socket ps); | ||
33 | |||
34 | int opt_set_tcp_nodelay(lua_State *L, p_socket ps); | ||
35 | int opt_get_tcp_nodelay(lua_State *L, p_socket ps); | ||
36 | |||
37 | #ifdef TCP_KEEPIDLE | ||
38 | int opt_set_tcp_keepidle(lua_State *L, p_socket ps); | ||
39 | int opt_get_tcp_keepidle(lua_State *L, p_socket ps); | ||
40 | #endif | ||
41 | |||
42 | #ifdef TCP_KEEPCNT | ||
43 | int opt_set_tcp_keepcnt(lua_State *L, p_socket ps); | ||
44 | int opt_get_tcp_keepcnt(lua_State *L, p_socket ps); | ||
45 | #endif | ||
46 | |||
47 | #ifdef TCP_KEEPINTVL | ||
48 | int opt_set_tcp_keepintvl(lua_State *L, p_socket ps); | ||
49 | int opt_get_tcp_keepintvl(lua_State *L, p_socket ps); | ||
50 | #endif | ||
51 | |||
52 | #ifdef TCP_DEFER_ACCEPT | ||
53 | int opt_set_tcp_defer_accept(lua_State *L, p_socket ps); | ||
54 | #endif | ||
55 | |||
56 | int opt_set_keepalive(lua_State *L, p_socket ps); | ||
57 | int opt_get_keepalive(lua_State *L, p_socket ps); | ||
58 | |||
59 | int opt_set_dontroute(lua_State *L, p_socket ps); | ||
60 | int opt_get_dontroute(lua_State *L, p_socket ps); | ||
61 | |||
62 | int opt_set_broadcast(lua_State *L, p_socket ps); | ||
63 | int opt_get_broadcast(lua_State *L, p_socket ps); | ||
64 | |||
65 | int opt_set_recv_buf_size(lua_State *L, p_socket ps); | ||
66 | int opt_get_recv_buf_size(lua_State *L, p_socket ps); | ||
67 | |||
68 | int opt_set_send_buf_size(lua_State *L, p_socket ps); | ||
69 | int opt_get_send_buf_size(lua_State *L, p_socket ps); | ||
70 | |||
71 | #ifdef TCP_FASTOPEN | ||
72 | int opt_set_tcp_fastopen(lua_State *L, p_socket ps); | ||
73 | #endif | ||
74 | #ifdef TCP_FASTOPEN_CONNECT | ||
75 | int opt_set_tcp_fastopen_connect(lua_State *L, p_socket ps); | ||
76 | #endif | ||
77 | |||
78 | int opt_set_ip6_unicast_hops(lua_State *L, p_socket ps); | ||
79 | int opt_get_ip6_unicast_hops(lua_State *L, p_socket ps); | ||
80 | |||
81 | int opt_set_ip6_multicast_hops(lua_State *L, p_socket ps); | ||
82 | int opt_get_ip6_multicast_hops(lua_State *L, p_socket ps); | ||
83 | |||
84 | int opt_set_ip_multicast_loop(lua_State *L, p_socket ps); | ||
85 | int opt_get_ip_multicast_loop(lua_State *L, p_socket ps); | ||
86 | |||
87 | int opt_set_ip6_multicast_loop(lua_State *L, p_socket ps); | ||
88 | int opt_get_ip6_multicast_loop(lua_State *L, p_socket ps); | ||
89 | |||
90 | int opt_set_linger(lua_State *L, p_socket ps); | ||
91 | int opt_get_linger(lua_State *L, p_socket ps); | ||
92 | |||
93 | int opt_set_ip_multicast_ttl(lua_State *L, p_socket ps); | ||
94 | |||
95 | int opt_set_ip_multicast_if(lua_State *L, p_socket ps); | ||
96 | int opt_get_ip_multicast_if(lua_State *L, p_socket ps); | ||
97 | |||
98 | int opt_set_ip_add_membership(lua_State *L, p_socket ps); | ||
99 | int opt_set_ip_drop_membersip(lua_State *L, p_socket ps); | ||
100 | |||
101 | int opt_set_ip6_add_membership(lua_State *L, p_socket ps); | ||
102 | int opt_set_ip6_drop_membersip(lua_State *L, p_socket ps); | ||
103 | |||
104 | int opt_set_ip6_v6only(lua_State *L, p_socket ps); | ||
105 | int opt_get_ip6_v6only(lua_State *L, p_socket ps); | ||
106 | |||
107 | int opt_get_error(lua_State *L, p_socket ps); | ||
108 | |||
109 | #ifndef _WIN32 | ||
110 | #pragma GCC visibility pop | ||
111 | #endif | ||
112 | |||
113 | #endif | ||
diff --git a/vendor/luasocket/src/pierror.h b/vendor/luasocket/src/pierror.h new file mode 100644 index 00000000..cb773ab7 --- /dev/null +++ b/vendor/luasocket/src/pierror.h | |||
@@ -0,0 +1,28 @@ | |||
1 | #ifndef PIERROR_H | ||
2 | #define PIERROR_H | ||
3 | /*=========================================================================*\ | ||
4 | * Error messages | ||
5 | * Defines platform independent error messages | ||
6 | \*=========================================================================*/ | ||
7 | |||
8 | #define PIE_HOST_NOT_FOUND "host not found" | ||
9 | #define PIE_ADDRINUSE "address already in use" | ||
10 | #define PIE_ISCONN "already connected" | ||
11 | #define PIE_ACCESS "permission denied" | ||
12 | #define PIE_CONNREFUSED "connection refused" | ||
13 | #define PIE_CONNABORTED "closed" | ||
14 | #define PIE_CONNRESET "closed" | ||
15 | #define PIE_TIMEDOUT "timeout" | ||
16 | #define PIE_AGAIN "temporary failure in name resolution" | ||
17 | #define PIE_BADFLAGS "invalid value for ai_flags" | ||
18 | #define PIE_BADHINTS "invalid value for hints" | ||
19 | #define PIE_FAIL "non-recoverable failure in name resolution" | ||
20 | #define PIE_FAMILY "ai_family not supported" | ||
21 | #define PIE_MEMORY "memory allocation failure" | ||
22 | #define PIE_NONAME "host or service not provided, or not known" | ||
23 | #define PIE_OVERFLOW "argument buffer overflow" | ||
24 | #define PIE_PROTOCOL "resolved protocol is unknown" | ||
25 | #define PIE_SERVICE "service not supported for socket type" | ||
26 | #define PIE_SOCKTYPE "ai_socktype not supported" | ||
27 | |||
28 | #endif | ||
diff --git a/vendor/luasocket/src/select.c b/vendor/luasocket/src/select.c new file mode 100644 index 00000000..bb47c459 --- /dev/null +++ b/vendor/luasocket/src/select.c | |||
@@ -0,0 +1,214 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * Select implementation | ||
3 | * LuaSocket toolkit | ||
4 | \*=========================================================================*/ | ||
5 | #include "luasocket.h" | ||
6 | |||
7 | #include "socket.h" | ||
8 | #include "timeout.h" | ||
9 | #include "select.h" | ||
10 | |||
11 | #include <string.h> | ||
12 | |||
13 | /*=========================================================================*\ | ||
14 | * Internal function prototypes. | ||
15 | \*=========================================================================*/ | ||
16 | static t_socket getfd(lua_State *L); | ||
17 | static int dirty(lua_State *L); | ||
18 | static void collect_fd(lua_State *L, int tab, int itab, | ||
19 | fd_set *set, t_socket *max_fd); | ||
20 | static int check_dirty(lua_State *L, int tab, int dtab, fd_set *set); | ||
21 | static void return_fd(lua_State *L, fd_set *set, t_socket max_fd, | ||
22 | int itab, int tab, int start); | ||
23 | static void make_assoc(lua_State *L, int tab); | ||
24 | static int global_select(lua_State *L); | ||
25 | |||
26 | /* functions in library namespace */ | ||
27 | static luaL_Reg func[] = { | ||
28 | {"select", global_select}, | ||
29 | {NULL, NULL} | ||
30 | }; | ||
31 | |||
32 | /*-------------------------------------------------------------------------*\ | ||
33 | * Initializes module | ||
34 | \*-------------------------------------------------------------------------*/ | ||
35 | int select_open(lua_State *L) { | ||
36 | lua_pushstring(L, "_SETSIZE"); | ||
37 | lua_pushinteger(L, FD_SETSIZE); | ||
38 | lua_rawset(L, -3); | ||
39 | lua_pushstring(L, "_SOCKETINVALID"); | ||
40 | lua_pushinteger(L, SOCKET_INVALID); | ||
41 | lua_rawset(L, -3); | ||
42 | luaL_setfuncs(L, func, 0); | ||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | /*=========================================================================*\ | ||
47 | * Global Lua functions | ||
48 | \*=========================================================================*/ | ||
49 | /*-------------------------------------------------------------------------*\ | ||
50 | * Waits for a set of sockets until a condition is met or timeout. | ||
51 | \*-------------------------------------------------------------------------*/ | ||
52 | static int global_select(lua_State *L) { | ||
53 | int rtab, wtab, itab, ret, ndirty; | ||
54 | t_socket max_fd = SOCKET_INVALID; | ||
55 | fd_set rset, wset; | ||
56 | t_timeout tm; | ||
57 | double t = luaL_optnumber(L, 3, -1); | ||
58 | FD_ZERO(&rset); FD_ZERO(&wset); | ||
59 | lua_settop(L, 3); | ||
60 | lua_newtable(L); itab = lua_gettop(L); | ||
61 | lua_newtable(L); rtab = lua_gettop(L); | ||
62 | lua_newtable(L); wtab = lua_gettop(L); | ||
63 | collect_fd(L, 1, itab, &rset, &max_fd); | ||
64 | collect_fd(L, 2, itab, &wset, &max_fd); | ||
65 | ndirty = check_dirty(L, 1, rtab, &rset); | ||
66 | t = ndirty > 0? 0.0: t; | ||
67 | timeout_init(&tm, t, -1); | ||
68 | timeout_markstart(&tm); | ||
69 | ret = socket_select(max_fd+1, &rset, &wset, NULL, &tm); | ||
70 | if (ret > 0 || ndirty > 0) { | ||
71 | return_fd(L, &rset, max_fd+1, itab, rtab, ndirty); | ||
72 | return_fd(L, &wset, max_fd+1, itab, wtab, 0); | ||
73 | make_assoc(L, rtab); | ||
74 | make_assoc(L, wtab); | ||
75 | return 2; | ||
76 | } else if (ret == 0) { | ||
77 | lua_pushstring(L, "timeout"); | ||
78 | return 3; | ||
79 | } else { | ||
80 | luaL_error(L, "select failed"); | ||
81 | return 3; | ||
82 | } | ||
83 | } | ||
84 | |||
85 | /*=========================================================================*\ | ||
86 | * Internal functions | ||
87 | \*=========================================================================*/ | ||
88 | static t_socket getfd(lua_State *L) { | ||
89 | t_socket fd = SOCKET_INVALID; | ||
90 | lua_pushstring(L, "getfd"); | ||
91 | lua_gettable(L, -2); | ||
92 | if (!lua_isnil(L, -1)) { | ||
93 | lua_pushvalue(L, -2); | ||
94 | lua_call(L, 1, 1); | ||
95 | if (lua_isnumber(L, -1)) { | ||
96 | double numfd = lua_tonumber(L, -1); | ||
97 | fd = (numfd >= 0.0)? (t_socket) numfd: SOCKET_INVALID; | ||
98 | } | ||
99 | } | ||
100 | lua_pop(L, 1); | ||
101 | return fd; | ||
102 | } | ||
103 | |||
104 | static int dirty(lua_State *L) { | ||
105 | int is = 0; | ||
106 | lua_pushstring(L, "dirty"); | ||
107 | lua_gettable(L, -2); | ||
108 | if (!lua_isnil(L, -1)) { | ||
109 | lua_pushvalue(L, -2); | ||
110 | lua_call(L, 1, 1); | ||
111 | is = lua_toboolean(L, -1); | ||
112 | } | ||
113 | lua_pop(L, 1); | ||
114 | return is; | ||
115 | } | ||
116 | |||
117 | static void collect_fd(lua_State *L, int tab, int itab, | ||
118 | fd_set *set, t_socket *max_fd) { | ||
119 | int i = 1, n = 0; | ||
120 | /* nil is the same as an empty table */ | ||
121 | if (lua_isnil(L, tab)) return; | ||
122 | /* otherwise we need it to be a table */ | ||
123 | luaL_checktype(L, tab, LUA_TTABLE); | ||
124 | for ( ;; ) { | ||
125 | t_socket fd; | ||
126 | lua_pushnumber(L, i); | ||
127 | lua_gettable(L, tab); | ||
128 | if (lua_isnil(L, -1)) { | ||
129 | lua_pop(L, 1); | ||
130 | break; | ||
131 | } | ||
132 | /* getfd figures out if this is a socket */ | ||
133 | fd = getfd(L); | ||
134 | if (fd != SOCKET_INVALID) { | ||
135 | /* make sure we don't overflow the fd_set */ | ||
136 | #ifdef _WIN32 | ||
137 | if (n >= FD_SETSIZE) | ||
138 | luaL_argerror(L, tab, "too many sockets"); | ||
139 | #else | ||
140 | if (fd >= FD_SETSIZE) | ||
141 | luaL_argerror(L, tab, "descriptor too large for set size"); | ||
142 | #endif | ||
143 | FD_SET(fd, set); | ||
144 | n++; | ||
145 | /* keep track of the largest descriptor so far */ | ||
146 | if (*max_fd == SOCKET_INVALID || *max_fd < fd) | ||
147 | *max_fd = fd; | ||
148 | /* make sure we can map back from descriptor to the object */ | ||
149 | lua_pushnumber(L, (lua_Number) fd); | ||
150 | lua_pushvalue(L, -2); | ||
151 | lua_settable(L, itab); | ||
152 | } | ||
153 | lua_pop(L, 1); | ||
154 | i = i + 1; | ||
155 | } | ||
156 | } | ||
157 | |||
158 | static int check_dirty(lua_State *L, int tab, int dtab, fd_set *set) { | ||
159 | int ndirty = 0, i = 1; | ||
160 | if (lua_isnil(L, tab)) | ||
161 | return 0; | ||
162 | for ( ;; ) { | ||
163 | t_socket fd; | ||
164 | lua_pushnumber(L, i); | ||
165 | lua_gettable(L, tab); | ||
166 | if (lua_isnil(L, -1)) { | ||
167 | lua_pop(L, 1); | ||
168 | break; | ||
169 | } | ||
170 | fd = getfd(L); | ||
171 | if (fd != SOCKET_INVALID && dirty(L)) { | ||
172 | lua_pushnumber(L, ++ndirty); | ||
173 | lua_pushvalue(L, -2); | ||
174 | lua_settable(L, dtab); | ||
175 | FD_CLR(fd, set); | ||
176 | } | ||
177 | lua_pop(L, 1); | ||
178 | i = i + 1; | ||
179 | } | ||
180 | return ndirty; | ||
181 | } | ||
182 | |||
183 | static void return_fd(lua_State *L, fd_set *set, t_socket max_fd, | ||
184 | int itab, int tab, int start) { | ||
185 | t_socket fd; | ||
186 | for (fd = 0; fd < max_fd; fd++) { | ||
187 | if (FD_ISSET(fd, set)) { | ||
188 | lua_pushnumber(L, ++start); | ||
189 | lua_pushnumber(L, (lua_Number) fd); | ||
190 | lua_gettable(L, itab); | ||
191 | lua_settable(L, tab); | ||
192 | } | ||
193 | } | ||
194 | } | ||
195 | |||
196 | static void make_assoc(lua_State *L, int tab) { | ||
197 | int i = 1, atab; | ||
198 | lua_newtable(L); atab = lua_gettop(L); | ||
199 | for ( ;; ) { | ||
200 | lua_pushnumber(L, i); | ||
201 | lua_gettable(L, tab); | ||
202 | if (!lua_isnil(L, -1)) { | ||
203 | lua_pushnumber(L, i); | ||
204 | lua_pushvalue(L, -2); | ||
205 | lua_settable(L, atab); | ||
206 | lua_pushnumber(L, i); | ||
207 | lua_settable(L, atab); | ||
208 | } else { | ||
209 | lua_pop(L, 1); | ||
210 | break; | ||
211 | } | ||
212 | i = i+1; | ||
213 | } | ||
214 | } | ||
diff --git a/vendor/luasocket/src/select.h b/vendor/luasocket/src/select.h new file mode 100644 index 00000000..5d45fe75 --- /dev/null +++ b/vendor/luasocket/src/select.h | |||
@@ -0,0 +1,23 @@ | |||
1 | #ifndef SELECT_H | ||
2 | #define SELECT_H | ||
3 | /*=========================================================================*\ | ||
4 | * Select implementation | ||
5 | * LuaSocket toolkit | ||
6 | * | ||
7 | * Each object that can be passed to the select function has to export | ||
8 | * method getfd() which returns the descriptor to be passed to the | ||
9 | * underlying select function. Another method, dirty(), should return | ||
10 | * true if there is data ready for reading (required for buffered input). | ||
11 | \*=========================================================================*/ | ||
12 | |||
13 | #ifndef _WIN32 | ||
14 | #pragma GCC visibility push(hidden) | ||
15 | #endif | ||
16 | |||
17 | int select_open(lua_State *L); | ||
18 | |||
19 | #ifndef _WIN32 | ||
20 | #pragma GCC visibility pop | ||
21 | #endif | ||
22 | |||
23 | #endif /* SELECT_H */ | ||
diff --git a/vendor/luasocket/src/serial.c b/vendor/luasocket/src/serial.c new file mode 100644 index 00000000..21485d3e --- /dev/null +++ b/vendor/luasocket/src/serial.c | |||
@@ -0,0 +1,171 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * Serial stream | ||
3 | * LuaSocket toolkit | ||
4 | \*=========================================================================*/ | ||
5 | #include "luasocket.h" | ||
6 | |||
7 | #include "auxiliar.h" | ||
8 | #include "socket.h" | ||
9 | #include "options.h" | ||
10 | #include "unix.h" | ||
11 | |||
12 | #include <string.h> | ||
13 | #include <sys/un.h> | ||
14 | |||
15 | /* | ||
16 | Reuses userdata definition from unix.h, since it is useful for all | ||
17 | stream-like objects. | ||
18 | |||
19 | If we stored the serial path for use in error messages or userdata | ||
20 | printing, we might need our own userdata definition. | ||
21 | |||
22 | Group usage is semi-inherited from unix.c, but unnecessary since we | ||
23 | have only one object type. | ||
24 | */ | ||
25 | |||
26 | /*=========================================================================*\ | ||
27 | * Internal function prototypes | ||
28 | \*=========================================================================*/ | ||
29 | static int global_create(lua_State *L); | ||
30 | static int meth_send(lua_State *L); | ||
31 | static int meth_receive(lua_State *L); | ||
32 | static int meth_close(lua_State *L); | ||
33 | static int meth_settimeout(lua_State *L); | ||
34 | static int meth_getfd(lua_State *L); | ||
35 | static int meth_setfd(lua_State *L); | ||
36 | static int meth_dirty(lua_State *L); | ||
37 | static int meth_getstats(lua_State *L); | ||
38 | static int meth_setstats(lua_State *L); | ||
39 | |||
40 | /* serial object methods */ | ||
41 | static luaL_Reg serial_methods[] = { | ||
42 | {"__gc", meth_close}, | ||
43 | {"__tostring", auxiliar_tostring}, | ||
44 | {"close", meth_close}, | ||
45 | {"dirty", meth_dirty}, | ||
46 | {"getfd", meth_getfd}, | ||
47 | {"getstats", meth_getstats}, | ||
48 | {"setstats", meth_setstats}, | ||
49 | {"receive", meth_receive}, | ||
50 | {"send", meth_send}, | ||
51 | {"setfd", meth_setfd}, | ||
52 | {"settimeout", meth_settimeout}, | ||
53 | {NULL, NULL} | ||
54 | }; | ||
55 | |||
56 | /*-------------------------------------------------------------------------*\ | ||
57 | * Initializes module | ||
58 | \*-------------------------------------------------------------------------*/ | ||
59 | LUASOCKET_API int luaopen_socket_serial(lua_State *L) { | ||
60 | /* create classes */ | ||
61 | auxiliar_newclass(L, "serial{client}", serial_methods); | ||
62 | /* create class groups */ | ||
63 | auxiliar_add2group(L, "serial{client}", "serial{any}"); | ||
64 | lua_pushcfunction(L, global_create); | ||
65 | return 1; | ||
66 | } | ||
67 | |||
68 | /*=========================================================================*\ | ||
69 | * Lua methods | ||
70 | \*=========================================================================*/ | ||
71 | /*-------------------------------------------------------------------------*\ | ||
72 | * Just call buffered IO methods | ||
73 | \*-------------------------------------------------------------------------*/ | ||
74 | static int meth_send(lua_State *L) { | ||
75 | p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1); | ||
76 | return buffer_meth_send(L, &un->buf); | ||
77 | } | ||
78 | |||
79 | static int meth_receive(lua_State *L) { | ||
80 | p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1); | ||
81 | return buffer_meth_receive(L, &un->buf); | ||
82 | } | ||
83 | |||
84 | static int meth_getstats(lua_State *L) { | ||
85 | p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1); | ||
86 | return buffer_meth_getstats(L, &un->buf); | ||
87 | } | ||
88 | |||
89 | static int meth_setstats(lua_State *L) { | ||
90 | p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1); | ||
91 | return buffer_meth_setstats(L, &un->buf); | ||
92 | } | ||
93 | |||
94 | /*-------------------------------------------------------------------------*\ | ||
95 | * Select support methods | ||
96 | \*-------------------------------------------------------------------------*/ | ||
97 | static int meth_getfd(lua_State *L) { | ||
98 | p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1); | ||
99 | lua_pushnumber(L, (int) un->sock); | ||
100 | return 1; | ||
101 | } | ||
102 | |||
103 | /* this is very dangerous, but can be handy for those that are brave enough */ | ||
104 | static int meth_setfd(lua_State *L) { | ||
105 | p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1); | ||
106 | un->sock = (t_socket) luaL_checknumber(L, 2); | ||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static int meth_dirty(lua_State *L) { | ||
111 | p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1); | ||
112 | lua_pushboolean(L, !buffer_isempty(&un->buf)); | ||
113 | return 1; | ||
114 | } | ||
115 | |||
116 | /*-------------------------------------------------------------------------*\ | ||
117 | * Closes socket used by object | ||
118 | \*-------------------------------------------------------------------------*/ | ||
119 | static int meth_close(lua_State *L) | ||
120 | { | ||
121 | p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1); | ||
122 | socket_destroy(&un->sock); | ||
123 | lua_pushnumber(L, 1); | ||
124 | return 1; | ||
125 | } | ||
126 | |||
127 | |||
128 | /*-------------------------------------------------------------------------*\ | ||
129 | * Just call tm methods | ||
130 | \*-------------------------------------------------------------------------*/ | ||
131 | static int meth_settimeout(lua_State *L) { | ||
132 | p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1); | ||
133 | return timeout_meth_settimeout(L, &un->tm); | ||
134 | } | ||
135 | |||
136 | /*=========================================================================*\ | ||
137 | * Library functions | ||
138 | \*=========================================================================*/ | ||
139 | |||
140 | |||
141 | /*-------------------------------------------------------------------------*\ | ||
142 | * Creates a serial object | ||
143 | \*-------------------------------------------------------------------------*/ | ||
144 | static int global_create(lua_State *L) { | ||
145 | const char* path = luaL_checkstring(L, 1); | ||
146 | |||
147 | /* allocate unix object */ | ||
148 | p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix)); | ||
149 | |||
150 | /* open serial device */ | ||
151 | t_socket sock = open(path, O_NOCTTY|O_RDWR); | ||
152 | |||
153 | /*printf("open %s on %d\n", path, sock);*/ | ||
154 | |||
155 | if (sock < 0) { | ||
156 | lua_pushnil(L); | ||
157 | lua_pushstring(L, socket_strerror(errno)); | ||
158 | lua_pushnumber(L, errno); | ||
159 | return 3; | ||
160 | } | ||
161 | /* set its type as client object */ | ||
162 | auxiliar_setclass(L, "serial{client}", -1); | ||
163 | /* initialize remaining structure fields */ | ||
164 | socket_setnonblocking(&sock); | ||
165 | un->sock = sock; | ||
166 | io_init(&un->io, (p_send) socket_write, (p_recv) socket_read, | ||
167 | (p_error) socket_ioerror, &un->sock); | ||
168 | timeout_init(&un->tm, -1, -1); | ||
169 | buffer_init(&un->buf, &un->io, &un->tm); | ||
170 | return 1; | ||
171 | } | ||
diff --git a/vendor/luasocket/src/smtp.lua b/vendor/luasocket/src/smtp.lua new file mode 100644 index 00000000..b113d006 --- /dev/null +++ b/vendor/luasocket/src/smtp.lua | |||
@@ -0,0 +1,256 @@ | |||
1 | ----------------------------------------------------------------------------- | ||
2 | -- SMTP client support for the Lua language. | ||
3 | -- LuaSocket toolkit. | ||
4 | -- Author: Diego Nehab | ||
5 | ----------------------------------------------------------------------------- | ||
6 | |||
7 | ----------------------------------------------------------------------------- | ||
8 | -- Declare module and import dependencies | ||
9 | ----------------------------------------------------------------------------- | ||
10 | local base = _G | ||
11 | local coroutine = require("coroutine") | ||
12 | local string = require("string") | ||
13 | local math = require("math") | ||
14 | local os = require("os") | ||
15 | local socket = require("socket") | ||
16 | local tp = require("socket.tp") | ||
17 | local ltn12 = require("ltn12") | ||
18 | local headers = require("socket.headers") | ||
19 | local mime = require("mime") | ||
20 | |||
21 | socket.smtp = {} | ||
22 | local _M = socket.smtp | ||
23 | |||
24 | ----------------------------------------------------------------------------- | ||
25 | -- Program constants | ||
26 | ----------------------------------------------------------------------------- | ||
27 | -- timeout for connection | ||
28 | _M.TIMEOUT = 60 | ||
29 | -- default server used to send e-mails | ||
30 | _M.SERVER = "localhost" | ||
31 | -- default port | ||
32 | _M.PORT = 25 | ||
33 | -- domain used in HELO command and default sendmail | ||
34 | -- If we are under a CGI, try to get from environment | ||
35 | _M.DOMAIN = os.getenv("SERVER_NAME") or "localhost" | ||
36 | -- default time zone (means we don't know) | ||
37 | _M.ZONE = "-0000" | ||
38 | |||
39 | --------------------------------------------------------------------------- | ||
40 | -- Low level SMTP API | ||
41 | ----------------------------------------------------------------------------- | ||
42 | local metat = { __index = {} } | ||
43 | |||
44 | function metat.__index:greet(domain) | ||
45 | self.try(self.tp:check("2..")) | ||
46 | self.try(self.tp:command("EHLO", domain or _M.DOMAIN)) | ||
47 | return socket.skip(1, self.try(self.tp:check("2.."))) | ||
48 | end | ||
49 | |||
50 | function metat.__index:mail(from) | ||
51 | self.try(self.tp:command("MAIL", "FROM:" .. from)) | ||
52 | return self.try(self.tp:check("2..")) | ||
53 | end | ||
54 | |||
55 | function metat.__index:rcpt(to) | ||
56 | self.try(self.tp:command("RCPT", "TO:" .. to)) | ||
57 | return self.try(self.tp:check("2..")) | ||
58 | end | ||
59 | |||
60 | function metat.__index:data(src, step) | ||
61 | self.try(self.tp:command("DATA")) | ||
62 | self.try(self.tp:check("3..")) | ||
63 | self.try(self.tp:source(src, step)) | ||
64 | self.try(self.tp:send("\r\n.\r\n")) | ||
65 | return self.try(self.tp:check("2..")) | ||
66 | end | ||
67 | |||
68 | function metat.__index:quit() | ||
69 | self.try(self.tp:command("QUIT")) | ||
70 | return self.try(self.tp:check("2..")) | ||
71 | end | ||
72 | |||
73 | function metat.__index:close() | ||
74 | return self.tp:close() | ||
75 | end | ||
76 | |||
77 | function metat.__index:login(user, password) | ||
78 | self.try(self.tp:command("AUTH", "LOGIN")) | ||
79 | self.try(self.tp:check("3..")) | ||
80 | self.try(self.tp:send(mime.b64(user) .. "\r\n")) | ||
81 | self.try(self.tp:check("3..")) | ||
82 | self.try(self.tp:send(mime.b64(password) .. "\r\n")) | ||
83 | return self.try(self.tp:check("2..")) | ||
84 | end | ||
85 | |||
86 | function metat.__index:plain(user, password) | ||
87 | local auth = "PLAIN " .. mime.b64("\0" .. user .. "\0" .. password) | ||
88 | self.try(self.tp:command("AUTH", auth)) | ||
89 | return self.try(self.tp:check("2..")) | ||
90 | end | ||
91 | |||
92 | function metat.__index:auth(user, password, ext) | ||
93 | if not user or not password then return 1 end | ||
94 | if string.find(ext, "AUTH[^\n]+LOGIN") then | ||
95 | return self:login(user, password) | ||
96 | elseif string.find(ext, "AUTH[^\n]+PLAIN") then | ||
97 | return self:plain(user, password) | ||
98 | else | ||
99 | self.try(nil, "authentication not supported") | ||
100 | end | ||
101 | end | ||
102 | |||
103 | -- send message or throw an exception | ||
104 | function metat.__index:send(mailt) | ||
105 | self:mail(mailt.from) | ||
106 | if base.type(mailt.rcpt) == "table" then | ||
107 | for i,v in base.ipairs(mailt.rcpt) do | ||
108 | self:rcpt(v) | ||
109 | end | ||
110 | else | ||
111 | self:rcpt(mailt.rcpt) | ||
112 | end | ||
113 | self:data(ltn12.source.chain(mailt.source, mime.stuff()), mailt.step) | ||
114 | end | ||
115 | |||
116 | function _M.open(server, port, create) | ||
117 | local tp = socket.try(tp.connect(server or _M.SERVER, port or _M.PORT, | ||
118 | _M.TIMEOUT, create)) | ||
119 | local s = base.setmetatable({tp = tp}, metat) | ||
120 | -- make sure tp is closed if we get an exception | ||
121 | s.try = socket.newtry(function() | ||
122 | s:close() | ||
123 | end) | ||
124 | return s | ||
125 | end | ||
126 | |||
127 | -- convert headers to lowercase | ||
128 | local function lower_headers(headers) | ||
129 | local lower = {} | ||
130 | for i,v in base.pairs(headers or lower) do | ||
131 | lower[string.lower(i)] = v | ||
132 | end | ||
133 | return lower | ||
134 | end | ||
135 | |||
136 | --------------------------------------------------------------------------- | ||
137 | -- Multipart message source | ||
138 | ----------------------------------------------------------------------------- | ||
139 | -- returns a hopefully unique mime boundary | ||
140 | local seqno = 0 | ||
141 | local function newboundary() | ||
142 | seqno = seqno + 1 | ||
143 | return string.format('%s%05d==%05u', os.date('%d%m%Y%H%M%S'), | ||
144 | math.random(0, 99999), seqno) | ||
145 | end | ||
146 | |||
147 | -- send_message forward declaration | ||
148 | local send_message | ||
149 | |||
150 | -- yield the headers all at once, it's faster | ||
151 | local function send_headers(tosend) | ||
152 | local canonic = headers.canonic | ||
153 | local h = "\r\n" | ||
154 | for f,v in base.pairs(tosend) do | ||
155 | h = (canonic[f] or f) .. ': ' .. v .. "\r\n" .. h | ||
156 | end | ||
157 | coroutine.yield(h) | ||
158 | end | ||
159 | |||
160 | -- yield multipart message body from a multipart message table | ||
161 | local function send_multipart(mesgt) | ||
162 | -- make sure we have our boundary and send headers | ||
163 | local bd = newboundary() | ||
164 | local headers = lower_headers(mesgt.headers or {}) | ||
165 | headers['content-type'] = headers['content-type'] or 'multipart/mixed' | ||
166 | headers['content-type'] = headers['content-type'] .. | ||
167 | '; boundary="' .. bd .. '"' | ||
168 | send_headers(headers) | ||
169 | -- send preamble | ||
170 | if mesgt.body.preamble then | ||
171 | coroutine.yield(mesgt.body.preamble) | ||
172 | coroutine.yield("\r\n") | ||
173 | end | ||
174 | -- send each part separated by a boundary | ||
175 | for i, m in base.ipairs(mesgt.body) do | ||
176 | coroutine.yield("\r\n--" .. bd .. "\r\n") | ||
177 | send_message(m) | ||
178 | end | ||
179 | -- send last boundary | ||
180 | coroutine.yield("\r\n--" .. bd .. "--\r\n\r\n") | ||
181 | -- send epilogue | ||
182 | if mesgt.body.epilogue then | ||
183 | coroutine.yield(mesgt.body.epilogue) | ||
184 | coroutine.yield("\r\n") | ||
185 | end | ||
186 | end | ||
187 | |||
188 | -- yield message body from a source | ||
189 | local function send_source(mesgt) | ||
190 | -- make sure we have a content-type | ||
191 | local headers = lower_headers(mesgt.headers or {}) | ||
192 | headers['content-type'] = headers['content-type'] or | ||
193 | 'text/plain; charset="iso-8859-1"' | ||
194 | send_headers(headers) | ||
195 | -- send body from source | ||
196 | while true do | ||
197 | local chunk, err = mesgt.body() | ||
198 | if err then coroutine.yield(nil, err) | ||
199 | elseif chunk then coroutine.yield(chunk) | ||
200 | else break end | ||
201 | end | ||
202 | end | ||
203 | |||
204 | -- yield message body from a string | ||
205 | local function send_string(mesgt) | ||
206 | -- make sure we have a content-type | ||
207 | local headers = lower_headers(mesgt.headers or {}) | ||
208 | headers['content-type'] = headers['content-type'] or | ||
209 | 'text/plain; charset="iso-8859-1"' | ||
210 | send_headers(headers) | ||
211 | -- send body from string | ||
212 | coroutine.yield(mesgt.body) | ||
213 | end | ||
214 | |||
215 | -- message source | ||
216 | function send_message(mesgt) | ||
217 | if base.type(mesgt.body) == "table" then send_multipart(mesgt) | ||
218 | elseif base.type(mesgt.body) == "function" then send_source(mesgt) | ||
219 | else send_string(mesgt) end | ||
220 | end | ||
221 | |||
222 | -- set defaul headers | ||
223 | local function adjust_headers(mesgt) | ||
224 | local lower = lower_headers(mesgt.headers) | ||
225 | lower["date"] = lower["date"] or | ||
226 | os.date("!%a, %d %b %Y %H:%M:%S ") .. (mesgt.zone or _M.ZONE) | ||
227 | lower["x-mailer"] = lower["x-mailer"] or socket._VERSION | ||
228 | -- this can't be overriden | ||
229 | lower["mime-version"] = "1.0" | ||
230 | return lower | ||
231 | end | ||
232 | |||
233 | function _M.message(mesgt) | ||
234 | mesgt.headers = adjust_headers(mesgt) | ||
235 | -- create and return message source | ||
236 | local co = coroutine.create(function() send_message(mesgt) end) | ||
237 | return function() | ||
238 | local ret, a, b = coroutine.resume(co) | ||
239 | if ret then return a, b | ||
240 | else return nil, a end | ||
241 | end | ||
242 | end | ||
243 | |||
244 | --------------------------------------------------------------------------- | ||
245 | -- High level SMTP API | ||
246 | ----------------------------------------------------------------------------- | ||
247 | _M.send = socket.protect(function(mailt) | ||
248 | local s = _M.open(mailt.server, mailt.port, mailt.create) | ||
249 | local ext = s:greet(mailt.domain) | ||
250 | s:auth(mailt.user, mailt.password, ext) | ||
251 | s:send(mailt) | ||
252 | s:quit() | ||
253 | return s:close() | ||
254 | end) | ||
255 | |||
256 | return _M \ No newline at end of file | ||
diff --git a/vendor/luasocket/src/socket.h b/vendor/luasocket/src/socket.h new file mode 100755 index 00000000..2555bab6 --- /dev/null +++ b/vendor/luasocket/src/socket.h | |||
@@ -0,0 +1,75 @@ | |||
1 | #ifndef SOCKET_H | ||
2 | #define SOCKET_H | ||
3 | /*=========================================================================*\ | ||
4 | * Socket compatibilization module | ||
5 | * LuaSocket toolkit | ||
6 | * | ||
7 | * BSD Sockets and WinSock are similar, but there are a few irritating | ||
8 | * differences. Also, not all *nix platforms behave the same. This module | ||
9 | * (and the associated usocket.h and wsocket.h) factor these differences and | ||
10 | * creates a interface compatible with the io.h module. | ||
11 | \*=========================================================================*/ | ||
12 | #include "io.h" | ||
13 | |||
14 | /*=========================================================================*\ | ||
15 | * Platform specific compatibilization | ||
16 | \*=========================================================================*/ | ||
17 | #ifdef _WIN32 | ||
18 | #include "wsocket.h" | ||
19 | #define LUA_GAI_STRERROR gai_strerrorA | ||
20 | #else | ||
21 | #include "usocket.h" | ||
22 | #define LUA_GAI_STRERROR gai_strerror | ||
23 | #endif | ||
24 | |||
25 | /*=========================================================================*\ | ||
26 | * The connect and accept functions accept a timeout and their | ||
27 | * implementations are somewhat complicated. We chose to move | ||
28 | * the timeout control into this module for these functions in | ||
29 | * order to simplify the modules that use them. | ||
30 | \*=========================================================================*/ | ||
31 | #include "timeout.h" | ||
32 | |||
33 | /* convenient shorthand */ | ||
34 | typedef struct sockaddr SA; | ||
35 | |||
36 | /*=========================================================================*\ | ||
37 | * Functions bellow implement a comfortable platform independent | ||
38 | * interface to sockets | ||
39 | \*=========================================================================*/ | ||
40 | |||
41 | #ifndef _WIN32 | ||
42 | #pragma GCC visibility push(hidden) | ||
43 | #endif | ||
44 | |||
45 | int socket_waitfd(p_socket ps, int sw, p_timeout tm); | ||
46 | int socket_open(void); | ||
47 | int socket_close(void); | ||
48 | void socket_destroy(p_socket ps); | ||
49 | int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, p_timeout tm); | ||
50 | int socket_create(p_socket ps, int domain, int type, int protocol); | ||
51 | int socket_bind(p_socket ps, SA *addr, socklen_t addr_len); | ||
52 | int socket_listen(p_socket ps, int backlog); | ||
53 | void socket_shutdown(p_socket ps, int how); | ||
54 | int socket_connect(p_socket ps, SA *addr, socklen_t addr_len, p_timeout tm); | ||
55 | int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *addr_len, p_timeout tm); | ||
56 | int socket_send(p_socket ps, const char *data, size_t count, size_t *sent, p_timeout tm); | ||
57 | int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, SA *addr, socklen_t addr_len, p_timeout tm); | ||
58 | int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm); | ||
59 | int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, SA *addr, socklen_t *addr_len, p_timeout tm); | ||
60 | int socket_write(p_socket ps, const char *data, size_t count, size_t *sent, p_timeout tm); | ||
61 | int socket_read(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm); | ||
62 | void socket_setblocking(p_socket ps); | ||
63 | void socket_setnonblocking(p_socket ps); | ||
64 | int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp); | ||
65 | int socket_gethostbyname(const char *addr, struct hostent **hp); | ||
66 | const char *socket_hoststrerror(int err); | ||
67 | const char *socket_strerror(int err); | ||
68 | const char *socket_ioerror(p_socket ps, int err); | ||
69 | const char *socket_gaistrerror(int err); | ||
70 | |||
71 | #ifndef _WIN32 | ||
72 | #pragma GCC visibility pop | ||
73 | #endif | ||
74 | |||
75 | #endif /* SOCKET_H */ | ||
diff --git a/vendor/luasocket/src/socket.lua b/vendor/luasocket/src/socket.lua new file mode 100644 index 00000000..d1c0b164 --- /dev/null +++ b/vendor/luasocket/src/socket.lua | |||
@@ -0,0 +1,149 @@ | |||
1 | ----------------------------------------------------------------------------- | ||
2 | -- LuaSocket helper module | ||
3 | -- Author: Diego Nehab | ||
4 | ----------------------------------------------------------------------------- | ||
5 | |||
6 | ----------------------------------------------------------------------------- | ||
7 | -- Declare module and import dependencies | ||
8 | ----------------------------------------------------------------------------- | ||
9 | local base = _G | ||
10 | local string = require("string") | ||
11 | local math = require("math") | ||
12 | local socket = require("socket.core") | ||
13 | |||
14 | local _M = socket | ||
15 | |||
16 | ----------------------------------------------------------------------------- | ||
17 | -- Exported auxiliar functions | ||
18 | ----------------------------------------------------------------------------- | ||
19 | function _M.connect4(address, port, laddress, lport) | ||
20 | return socket.connect(address, port, laddress, lport, "inet") | ||
21 | end | ||
22 | |||
23 | function _M.connect6(address, port, laddress, lport) | ||
24 | return socket.connect(address, port, laddress, lport, "inet6") | ||
25 | end | ||
26 | |||
27 | function _M.bind(host, port, backlog) | ||
28 | if host == "*" then host = "0.0.0.0" end | ||
29 | local addrinfo, err = socket.dns.getaddrinfo(host); | ||
30 | if not addrinfo then return nil, err end | ||
31 | local sock, res | ||
32 | err = "no info on address" | ||
33 | for i, alt in base.ipairs(addrinfo) do | ||
34 | if alt.family == "inet" then | ||
35 | sock, err = socket.tcp4() | ||
36 | else | ||
37 | sock, err = socket.tcp6() | ||
38 | end | ||
39 | if not sock then return nil, err end | ||
40 | sock:setoption("reuseaddr", true) | ||
41 | res, err = sock:bind(alt.addr, port) | ||
42 | if not res then | ||
43 | sock:close() | ||
44 | else | ||
45 | res, err = sock:listen(backlog) | ||
46 | if not res then | ||
47 | sock:close() | ||
48 | else | ||
49 | return sock | ||
50 | end | ||
51 | end | ||
52 | end | ||
53 | return nil, err | ||
54 | end | ||
55 | |||
56 | _M.try = _M.newtry() | ||
57 | |||
58 | function _M.choose(table) | ||
59 | return function(name, opt1, opt2) | ||
60 | if base.type(name) ~= "string" then | ||
61 | name, opt1, opt2 = "default", name, opt1 | ||
62 | end | ||
63 | local f = table[name or "nil"] | ||
64 | if not f then base.error("unknown key (".. base.tostring(name) ..")", 3) | ||
65 | else return f(opt1, opt2) end | ||
66 | end | ||
67 | end | ||
68 | |||
69 | ----------------------------------------------------------------------------- | ||
70 | -- Socket sources and sinks, conforming to LTN12 | ||
71 | ----------------------------------------------------------------------------- | ||
72 | -- create namespaces inside LuaSocket namespace | ||
73 | local sourcet, sinkt = {}, {} | ||
74 | _M.sourcet = sourcet | ||
75 | _M.sinkt = sinkt | ||
76 | |||
77 | _M.BLOCKSIZE = 2048 | ||
78 | |||
79 | sinkt["close-when-done"] = function(sock) | ||
80 | return base.setmetatable({ | ||
81 | getfd = function() return sock:getfd() end, | ||
82 | dirty = function() return sock:dirty() end | ||
83 | }, { | ||
84 | __call = function(self, chunk, err) | ||
85 | if not chunk then | ||
86 | sock:close() | ||
87 | return 1 | ||
88 | else return sock:send(chunk) end | ||
89 | end | ||
90 | }) | ||
91 | end | ||
92 | |||
93 | sinkt["keep-open"] = function(sock) | ||
94 | return base.setmetatable({ | ||
95 | getfd = function() return sock:getfd() end, | ||
96 | dirty = function() return sock:dirty() end | ||
97 | }, { | ||
98 | __call = function(self, chunk, err) | ||
99 | if chunk then return sock:send(chunk) | ||
100 | else return 1 end | ||
101 | end | ||
102 | }) | ||
103 | end | ||
104 | |||
105 | sinkt["default"] = sinkt["keep-open"] | ||
106 | |||
107 | _M.sink = _M.choose(sinkt) | ||
108 | |||
109 | sourcet["by-length"] = function(sock, length) | ||
110 | return base.setmetatable({ | ||
111 | getfd = function() return sock:getfd() end, | ||
112 | dirty = function() return sock:dirty() end | ||
113 | }, { | ||
114 | __call = function() | ||
115 | if length <= 0 then return nil end | ||
116 | local size = math.min(socket.BLOCKSIZE, length) | ||
117 | local chunk, err = sock:receive(size) | ||
118 | if err then return nil, err end | ||
119 | length = length - string.len(chunk) | ||
120 | return chunk | ||
121 | end | ||
122 | }) | ||
123 | end | ||
124 | |||
125 | sourcet["until-closed"] = function(sock) | ||
126 | local done | ||
127 | return base.setmetatable({ | ||
128 | getfd = function() return sock:getfd() end, | ||
129 | dirty = function() return sock:dirty() end | ||
130 | }, { | ||
131 | __call = function() | ||
132 | if done then return nil end | ||
133 | local chunk, err, partial = sock:receive(socket.BLOCKSIZE) | ||
134 | if not err then return chunk | ||
135 | elseif err == "closed" then | ||
136 | sock:close() | ||
137 | done = 1 | ||
138 | return partial | ||
139 | else return nil, err end | ||
140 | end | ||
141 | }) | ||
142 | end | ||
143 | |||
144 | |||
145 | sourcet["default"] = sourcet["until-closed"] | ||
146 | |||
147 | _M.source = _M.choose(sourcet) | ||
148 | |||
149 | return _M | ||
diff --git a/vendor/luasocket/src/tcp.c b/vendor/luasocket/src/tcp.c new file mode 100644 index 00000000..e84db845 --- /dev/null +++ b/vendor/luasocket/src/tcp.c | |||
@@ -0,0 +1,480 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * TCP object | ||
3 | * LuaSocket toolkit | ||
4 | \*=========================================================================*/ | ||
5 | #include "luasocket.h" | ||
6 | |||
7 | #include "auxiliar.h" | ||
8 | #include "socket.h" | ||
9 | #include "inet.h" | ||
10 | #include "options.h" | ||
11 | #include "tcp.h" | ||
12 | |||
13 | #include <string.h> | ||
14 | |||
15 | /*=========================================================================*\ | ||
16 | * Internal function prototypes | ||
17 | \*=========================================================================*/ | ||
18 | static int global_create(lua_State *L); | ||
19 | static int global_create4(lua_State *L); | ||
20 | static int global_create6(lua_State *L); | ||
21 | static int global_connect(lua_State *L); | ||
22 | static int meth_connect(lua_State *L); | ||
23 | static int meth_listen(lua_State *L); | ||
24 | static int meth_getfamily(lua_State *L); | ||
25 | static int meth_bind(lua_State *L); | ||
26 | static int meth_send(lua_State *L); | ||
27 | static int meth_getstats(lua_State *L); | ||
28 | static int meth_setstats(lua_State *L); | ||
29 | static int meth_getsockname(lua_State *L); | ||
30 | static int meth_getpeername(lua_State *L); | ||
31 | static int meth_shutdown(lua_State *L); | ||
32 | static int meth_receive(lua_State *L); | ||
33 | static int meth_accept(lua_State *L); | ||
34 | static int meth_close(lua_State *L); | ||
35 | static int meth_getoption(lua_State *L); | ||
36 | static int meth_setoption(lua_State *L); | ||
37 | static int meth_gettimeout(lua_State *L); | ||
38 | static int meth_settimeout(lua_State *L); | ||
39 | static int meth_getfd(lua_State *L); | ||
40 | static int meth_setfd(lua_State *L); | ||
41 | static int meth_dirty(lua_State *L); | ||
42 | |||
43 | /* tcp object methods */ | ||
44 | static luaL_Reg tcp_methods[] = { | ||
45 | {"__gc", meth_close}, | ||
46 | {"__tostring", auxiliar_tostring}, | ||
47 | {"accept", meth_accept}, | ||
48 | {"bind", meth_bind}, | ||
49 | {"close", meth_close}, | ||
50 | {"connect", meth_connect}, | ||
51 | {"dirty", meth_dirty}, | ||
52 | {"getfamily", meth_getfamily}, | ||
53 | {"getfd", meth_getfd}, | ||
54 | {"getoption", meth_getoption}, | ||
55 | {"getpeername", meth_getpeername}, | ||
56 | {"getsockname", meth_getsockname}, | ||
57 | {"getstats", meth_getstats}, | ||
58 | {"setstats", meth_setstats}, | ||
59 | {"listen", meth_listen}, | ||
60 | {"receive", meth_receive}, | ||
61 | {"send", meth_send}, | ||
62 | {"setfd", meth_setfd}, | ||
63 | {"setoption", meth_setoption}, | ||
64 | {"setpeername", meth_connect}, | ||
65 | {"setsockname", meth_bind}, | ||
66 | {"settimeout", meth_settimeout}, | ||
67 | {"gettimeout", meth_gettimeout}, | ||
68 | {"shutdown", meth_shutdown}, | ||
69 | {NULL, NULL} | ||
70 | }; | ||
71 | |||
72 | /* socket option handlers */ | ||
73 | static t_opt optget[] = { | ||
74 | {"keepalive", opt_get_keepalive}, | ||
75 | {"reuseaddr", opt_get_reuseaddr}, | ||
76 | {"reuseport", opt_get_reuseport}, | ||
77 | {"tcp-nodelay", opt_get_tcp_nodelay}, | ||
78 | #ifdef TCP_KEEPIDLE | ||
79 | {"tcp-keepidle", opt_get_tcp_keepidle}, | ||
80 | #endif | ||
81 | #ifdef TCP_KEEPCNT | ||
82 | {"tcp-keepcnt", opt_get_tcp_keepcnt}, | ||
83 | #endif | ||
84 | #ifdef TCP_KEEPINTVL | ||
85 | {"tcp-keepintvl", opt_get_tcp_keepintvl}, | ||
86 | #endif | ||
87 | {"linger", opt_get_linger}, | ||
88 | {"error", opt_get_error}, | ||
89 | {"recv-buffer-size", opt_get_recv_buf_size}, | ||
90 | {"send-buffer-size", opt_get_send_buf_size}, | ||
91 | {NULL, NULL} | ||
92 | }; | ||
93 | |||
94 | static t_opt optset[] = { | ||
95 | {"keepalive", opt_set_keepalive}, | ||
96 | {"reuseaddr", opt_set_reuseaddr}, | ||
97 | {"reuseport", opt_set_reuseport}, | ||
98 | {"tcp-nodelay", opt_set_tcp_nodelay}, | ||
99 | #ifdef TCP_KEEPIDLE | ||
100 | {"tcp-keepidle", opt_set_tcp_keepidle}, | ||
101 | #endif | ||
102 | #ifdef TCP_KEEPCNT | ||
103 | {"tcp-keepcnt", opt_set_tcp_keepcnt}, | ||
104 | #endif | ||
105 | #ifdef TCP_KEEPINTVL | ||
106 | {"tcp-keepintvl", opt_set_tcp_keepintvl}, | ||
107 | #endif | ||
108 | {"ipv6-v6only", opt_set_ip6_v6only}, | ||
109 | {"linger", opt_set_linger}, | ||
110 | {"recv-buffer-size", opt_set_recv_buf_size}, | ||
111 | {"send-buffer-size", opt_set_send_buf_size}, | ||
112 | #ifdef TCP_DEFER_ACCEPT | ||
113 | {"tcp-defer-accept", opt_set_tcp_defer_accept}, | ||
114 | #endif | ||
115 | #ifdef TCP_FASTOPEN | ||
116 | {"tcp-fastopen", opt_set_tcp_fastopen}, | ||
117 | #endif | ||
118 | #ifdef TCP_FASTOPEN_CONNECT | ||
119 | {"tcp-fastopen-connect", opt_set_tcp_fastopen_connect}, | ||
120 | #endif | ||
121 | {NULL, NULL} | ||
122 | }; | ||
123 | |||
124 | /* functions in library namespace */ | ||
125 | static luaL_Reg func[] = { | ||
126 | {"tcp", global_create}, | ||
127 | {"tcp4", global_create4}, | ||
128 | {"tcp6", global_create6}, | ||
129 | {"connect", global_connect}, | ||
130 | {NULL, NULL} | ||
131 | }; | ||
132 | |||
133 | /*-------------------------------------------------------------------------*\ | ||
134 | * Initializes module | ||
135 | \*-------------------------------------------------------------------------*/ | ||
136 | int tcp_open(lua_State *L) | ||
137 | { | ||
138 | /* create classes */ | ||
139 | auxiliar_newclass(L, "tcp{master}", tcp_methods); | ||
140 | auxiliar_newclass(L, "tcp{client}", tcp_methods); | ||
141 | auxiliar_newclass(L, "tcp{server}", tcp_methods); | ||
142 | /* create class groups */ | ||
143 | auxiliar_add2group(L, "tcp{master}", "tcp{any}"); | ||
144 | auxiliar_add2group(L, "tcp{client}", "tcp{any}"); | ||
145 | auxiliar_add2group(L, "tcp{server}", "tcp{any}"); | ||
146 | /* define library functions */ | ||
147 | luaL_setfuncs(L, func, 0); | ||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | /*=========================================================================*\ | ||
152 | * Lua methods | ||
153 | \*=========================================================================*/ | ||
154 | /*-------------------------------------------------------------------------*\ | ||
155 | * Just call buffered IO methods | ||
156 | \*-------------------------------------------------------------------------*/ | ||
157 | static int meth_send(lua_State *L) { | ||
158 | p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1); | ||
159 | return buffer_meth_send(L, &tcp->buf); | ||
160 | } | ||
161 | |||
162 | static int meth_receive(lua_State *L) { | ||
163 | p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1); | ||
164 | return buffer_meth_receive(L, &tcp->buf); | ||
165 | } | ||
166 | |||
167 | static int meth_getstats(lua_State *L) { | ||
168 | p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1); | ||
169 | return buffer_meth_getstats(L, &tcp->buf); | ||
170 | } | ||
171 | |||
172 | static int meth_setstats(lua_State *L) { | ||
173 | p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1); | ||
174 | return buffer_meth_setstats(L, &tcp->buf); | ||
175 | } | ||
176 | |||
177 | /*-------------------------------------------------------------------------*\ | ||
178 | * Just call option handler | ||
179 | \*-------------------------------------------------------------------------*/ | ||
180 | static int meth_getoption(lua_State *L) | ||
181 | { | ||
182 | p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); | ||
183 | return opt_meth_getoption(L, optget, &tcp->sock); | ||
184 | } | ||
185 | |||
186 | static int meth_setoption(lua_State *L) | ||
187 | { | ||
188 | p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); | ||
189 | return opt_meth_setoption(L, optset, &tcp->sock); | ||
190 | } | ||
191 | |||
192 | /*-------------------------------------------------------------------------*\ | ||
193 | * Select support methods | ||
194 | \*-------------------------------------------------------------------------*/ | ||
195 | static int meth_getfd(lua_State *L) | ||
196 | { | ||
197 | p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); | ||
198 | lua_pushnumber(L, (int) tcp->sock); | ||
199 | return 1; | ||
200 | } | ||
201 | |||
202 | /* this is very dangerous, but can be handy for those that are brave enough */ | ||
203 | static int meth_setfd(lua_State *L) | ||
204 | { | ||
205 | p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); | ||
206 | tcp->sock = (t_socket) luaL_checknumber(L, 2); | ||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | static int meth_dirty(lua_State *L) | ||
211 | { | ||
212 | p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); | ||
213 | lua_pushboolean(L, !buffer_isempty(&tcp->buf)); | ||
214 | return 1; | ||
215 | } | ||
216 | |||
217 | /*-------------------------------------------------------------------------*\ | ||
218 | * Waits for and returns a client object attempting connection to the | ||
219 | * server object | ||
220 | \*-------------------------------------------------------------------------*/ | ||
221 | static int meth_accept(lua_State *L) | ||
222 | { | ||
223 | p_tcp server = (p_tcp) auxiliar_checkclass(L, "tcp{server}", 1); | ||
224 | p_timeout tm = timeout_markstart(&server->tm); | ||
225 | t_socket sock; | ||
226 | const char *err = inet_tryaccept(&server->sock, server->family, &sock, tm); | ||
227 | /* if successful, push client socket */ | ||
228 | if (err == NULL) { | ||
229 | p_tcp clnt = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); | ||
230 | auxiliar_setclass(L, "tcp{client}", -1); | ||
231 | /* initialize structure fields */ | ||
232 | memset(clnt, 0, sizeof(t_tcp)); | ||
233 | socket_setnonblocking(&sock); | ||
234 | clnt->sock = sock; | ||
235 | io_init(&clnt->io, (p_send) socket_send, (p_recv) socket_recv, | ||
236 | (p_error) socket_ioerror, &clnt->sock); | ||
237 | timeout_init(&clnt->tm, -1, -1); | ||
238 | buffer_init(&clnt->buf, &clnt->io, &clnt->tm); | ||
239 | clnt->family = server->family; | ||
240 | return 1; | ||
241 | } else { | ||
242 | lua_pushnil(L); | ||
243 | lua_pushstring(L, err); | ||
244 | return 2; | ||
245 | } | ||
246 | } | ||
247 | |||
248 | /*-------------------------------------------------------------------------*\ | ||
249 | * Binds an object to an address | ||
250 | \*-------------------------------------------------------------------------*/ | ||
251 | static int meth_bind(lua_State *L) { | ||
252 | p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{master}", 1); | ||
253 | const char *address = luaL_checkstring(L, 2); | ||
254 | const char *port = luaL_checkstring(L, 3); | ||
255 | const char *err; | ||
256 | struct addrinfo bindhints; | ||
257 | memset(&bindhints, 0, sizeof(bindhints)); | ||
258 | bindhints.ai_socktype = SOCK_STREAM; | ||
259 | bindhints.ai_family = tcp->family; | ||
260 | bindhints.ai_flags = AI_PASSIVE; | ||
261 | err = inet_trybind(&tcp->sock, &tcp->family, address, port, &bindhints); | ||
262 | if (err) { | ||
263 | lua_pushnil(L); | ||
264 | lua_pushstring(L, err); | ||
265 | return 2; | ||
266 | } | ||
267 | lua_pushnumber(L, 1); | ||
268 | return 1; | ||
269 | } | ||
270 | |||
271 | /*-------------------------------------------------------------------------*\ | ||
272 | * Turns a master tcp object into a client object. | ||
273 | \*-------------------------------------------------------------------------*/ | ||
274 | static int meth_connect(lua_State *L) { | ||
275 | p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); | ||
276 | const char *address = luaL_checkstring(L, 2); | ||
277 | const char *port = luaL_checkstring(L, 3); | ||
278 | struct addrinfo connecthints; | ||
279 | const char *err; | ||
280 | memset(&connecthints, 0, sizeof(connecthints)); | ||
281 | connecthints.ai_socktype = SOCK_STREAM; | ||
282 | /* make sure we try to connect only to the same family */ | ||
283 | connecthints.ai_family = tcp->family; | ||
284 | timeout_markstart(&tcp->tm); | ||
285 | err = inet_tryconnect(&tcp->sock, &tcp->family, address, port, | ||
286 | &tcp->tm, &connecthints); | ||
287 | /* have to set the class even if it failed due to non-blocking connects */ | ||
288 | auxiliar_setclass(L, "tcp{client}", 1); | ||
289 | if (err) { | ||
290 | lua_pushnil(L); | ||
291 | lua_pushstring(L, err); | ||
292 | return 2; | ||
293 | } | ||
294 | lua_pushnumber(L, 1); | ||
295 | return 1; | ||
296 | } | ||
297 | |||
298 | /*-------------------------------------------------------------------------*\ | ||
299 | * Closes socket used by object | ||
300 | \*-------------------------------------------------------------------------*/ | ||
301 | static int meth_close(lua_State *L) | ||
302 | { | ||
303 | p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); | ||
304 | socket_destroy(&tcp->sock); | ||
305 | lua_pushnumber(L, 1); | ||
306 | return 1; | ||
307 | } | ||
308 | |||
309 | /*-------------------------------------------------------------------------*\ | ||
310 | * Returns family as string | ||
311 | \*-------------------------------------------------------------------------*/ | ||
312 | static int meth_getfamily(lua_State *L) | ||
313 | { | ||
314 | p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); | ||
315 | if (tcp->family == AF_INET6) { | ||
316 | lua_pushliteral(L, "inet6"); | ||
317 | return 1; | ||
318 | } else if (tcp->family == AF_INET) { | ||
319 | lua_pushliteral(L, "inet4"); | ||
320 | return 1; | ||
321 | } else { | ||
322 | lua_pushliteral(L, "inet4"); | ||
323 | return 1; | ||
324 | } | ||
325 | } | ||
326 | |||
327 | /*-------------------------------------------------------------------------*\ | ||
328 | * Puts the sockt in listen mode | ||
329 | \*-------------------------------------------------------------------------*/ | ||
330 | static int meth_listen(lua_State *L) | ||
331 | { | ||
332 | p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{master}", 1); | ||
333 | int backlog = (int) luaL_optnumber(L, 2, 32); | ||
334 | int err = socket_listen(&tcp->sock, backlog); | ||
335 | if (err != IO_DONE) { | ||
336 | lua_pushnil(L); | ||
337 | lua_pushstring(L, socket_strerror(err)); | ||
338 | return 2; | ||
339 | } | ||
340 | /* turn master object into a server object */ | ||
341 | auxiliar_setclass(L, "tcp{server}", 1); | ||
342 | lua_pushnumber(L, 1); | ||
343 | return 1; | ||
344 | } | ||
345 | |||
346 | /*-------------------------------------------------------------------------*\ | ||
347 | * Shuts the connection down partially | ||
348 | \*-------------------------------------------------------------------------*/ | ||
349 | static int meth_shutdown(lua_State *L) | ||
350 | { | ||
351 | /* SHUT_RD, SHUT_WR, SHUT_RDWR have the value 0, 1, 2, so we can use method index directly */ | ||
352 | static const char* methods[] = { "receive", "send", "both", NULL }; | ||
353 | p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1); | ||
354 | int how = luaL_checkoption(L, 2, "both", methods); | ||
355 | socket_shutdown(&tcp->sock, how); | ||
356 | lua_pushnumber(L, 1); | ||
357 | return 1; | ||
358 | } | ||
359 | |||
360 | /*-------------------------------------------------------------------------*\ | ||
361 | * Just call inet methods | ||
362 | \*-------------------------------------------------------------------------*/ | ||
363 | static int meth_getpeername(lua_State *L) | ||
364 | { | ||
365 | p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); | ||
366 | return inet_meth_getpeername(L, &tcp->sock, tcp->family); | ||
367 | } | ||
368 | |||
369 | static int meth_getsockname(lua_State *L) | ||
370 | { | ||
371 | p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); | ||
372 | return inet_meth_getsockname(L, &tcp->sock, tcp->family); | ||
373 | } | ||
374 | |||
375 | /*-------------------------------------------------------------------------*\ | ||
376 | * Just call tm methods | ||
377 | \*-------------------------------------------------------------------------*/ | ||
378 | static int meth_settimeout(lua_State *L) | ||
379 | { | ||
380 | p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); | ||
381 | return timeout_meth_settimeout(L, &tcp->tm); | ||
382 | } | ||
383 | |||
384 | static int meth_gettimeout(lua_State *L) | ||
385 | { | ||
386 | p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); | ||
387 | return timeout_meth_gettimeout(L, &tcp->tm); | ||
388 | } | ||
389 | |||
390 | /*=========================================================================*\ | ||
391 | * Library functions | ||
392 | \*=========================================================================*/ | ||
393 | /*-------------------------------------------------------------------------*\ | ||
394 | * Creates a master tcp object | ||
395 | \*-------------------------------------------------------------------------*/ | ||
396 | static int tcp_create(lua_State *L, int family) { | ||
397 | p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); | ||
398 | memset(tcp, 0, sizeof(t_tcp)); | ||
399 | /* set its type as master object */ | ||
400 | auxiliar_setclass(L, "tcp{master}", -1); | ||
401 | /* if family is AF_UNSPEC, we leave the socket invalid and | ||
402 | * store AF_UNSPEC into family. This will allow it to later be | ||
403 | * replaced with an AF_INET6 or AF_INET socket upon first use. */ | ||
404 | tcp->sock = SOCKET_INVALID; | ||
405 | tcp->family = family; | ||
406 | io_init(&tcp->io, (p_send) socket_send, (p_recv) socket_recv, | ||
407 | (p_error) socket_ioerror, &tcp->sock); | ||
408 | timeout_init(&tcp->tm, -1, -1); | ||
409 | buffer_init(&tcp->buf, &tcp->io, &tcp->tm); | ||
410 | if (family != AF_UNSPEC) { | ||
411 | const char *err = inet_trycreate(&tcp->sock, family, SOCK_STREAM, 0); | ||
412 | if (err != NULL) { | ||
413 | lua_pushnil(L); | ||
414 | lua_pushstring(L, err); | ||
415 | return 2; | ||
416 | } | ||
417 | socket_setnonblocking(&tcp->sock); | ||
418 | } | ||
419 | return 1; | ||
420 | } | ||
421 | |||
422 | static int global_create(lua_State *L) { | ||
423 | return tcp_create(L, AF_UNSPEC); | ||
424 | } | ||
425 | |||
426 | static int global_create4(lua_State *L) { | ||
427 | return tcp_create(L, AF_INET); | ||
428 | } | ||
429 | |||
430 | static int global_create6(lua_State *L) { | ||
431 | return tcp_create(L, AF_INET6); | ||
432 | } | ||
433 | |||
434 | static int global_connect(lua_State *L) { | ||
435 | const char *remoteaddr = luaL_checkstring(L, 1); | ||
436 | const char *remoteserv = luaL_checkstring(L, 2); | ||
437 | const char *localaddr = luaL_optstring(L, 3, NULL); | ||
438 | const char *localserv = luaL_optstring(L, 4, "0"); | ||
439 | int family = inet_optfamily(L, 5, "unspec"); | ||
440 | p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); | ||
441 | struct addrinfo bindhints, connecthints; | ||
442 | const char *err = NULL; | ||
443 | /* initialize tcp structure */ | ||
444 | memset(tcp, 0, sizeof(t_tcp)); | ||
445 | io_init(&tcp->io, (p_send) socket_send, (p_recv) socket_recv, | ||
446 | (p_error) socket_ioerror, &tcp->sock); | ||
447 | timeout_init(&tcp->tm, -1, -1); | ||
448 | buffer_init(&tcp->buf, &tcp->io, &tcp->tm); | ||
449 | tcp->sock = SOCKET_INVALID; | ||
450 | tcp->family = AF_UNSPEC; | ||
451 | /* allow user to pick local address and port */ | ||
452 | memset(&bindhints, 0, sizeof(bindhints)); | ||
453 | bindhints.ai_socktype = SOCK_STREAM; | ||
454 | bindhints.ai_family = family; | ||
455 | bindhints.ai_flags = AI_PASSIVE; | ||
456 | if (localaddr) { | ||
457 | err = inet_trybind(&tcp->sock, &tcp->family, localaddr, | ||
458 | localserv, &bindhints); | ||
459 | if (err) { | ||
460 | lua_pushnil(L); | ||
461 | lua_pushstring(L, err); | ||
462 | return 2; | ||
463 | } | ||
464 | } | ||
465 | /* try to connect to remote address and port */ | ||
466 | memset(&connecthints, 0, sizeof(connecthints)); | ||
467 | connecthints.ai_socktype = SOCK_STREAM; | ||
468 | /* make sure we try to connect only to the same family */ | ||
469 | connecthints.ai_family = tcp->family; | ||
470 | err = inet_tryconnect(&tcp->sock, &tcp->family, remoteaddr, remoteserv, | ||
471 | &tcp->tm, &connecthints); | ||
472 | if (err) { | ||
473 | socket_destroy(&tcp->sock); | ||
474 | lua_pushnil(L); | ||
475 | lua_pushstring(L, err); | ||
476 | return 2; | ||
477 | } | ||
478 | auxiliar_setclass(L, "tcp{client}", -1); | ||
479 | return 1; | ||
480 | } | ||
diff --git a/vendor/luasocket/src/tcp.h b/vendor/luasocket/src/tcp.h new file mode 100644 index 00000000..9b282efe --- /dev/null +++ b/vendor/luasocket/src/tcp.h | |||
@@ -0,0 +1,43 @@ | |||
1 | #ifndef TCP_H | ||
2 | #define TCP_H | ||
3 | /*=========================================================================*\ | ||
4 | * TCP object | ||
5 | * LuaSocket toolkit | ||
6 | * | ||
7 | * The tcp.h module is basicly a glue that puts together modules buffer.h, | ||
8 | * timeout.h socket.h and inet.h to provide the LuaSocket TCP (AF_INET, | ||
9 | * SOCK_STREAM) support. | ||
10 | * | ||
11 | * Three classes are defined: master, client and server. The master class is | ||
12 | * a newly created tcp object, that has not been bound or connected. Server | ||
13 | * objects are tcp objects bound to some local address. Client objects are | ||
14 | * tcp objects either connected to some address or returned by the accept | ||
15 | * method of a server object. | ||
16 | \*=========================================================================*/ | ||
17 | #include "luasocket.h" | ||
18 | |||
19 | #include "buffer.h" | ||
20 | #include "timeout.h" | ||
21 | #include "socket.h" | ||
22 | |||
23 | typedef struct t_tcp_ { | ||
24 | t_socket sock; | ||
25 | t_io io; | ||
26 | t_buffer buf; | ||
27 | t_timeout tm; | ||
28 | int family; | ||
29 | } t_tcp; | ||
30 | |||
31 | typedef t_tcp *p_tcp; | ||
32 | |||
33 | #ifndef _WIN32 | ||
34 | #pragma GCC visibility push(hidden) | ||
35 | #endif | ||
36 | |||
37 | int tcp_open(lua_State *L); | ||
38 | |||
39 | #ifndef _WIN32 | ||
40 | #pragma GCC visibility pop | ||
41 | #endif | ||
42 | |||
43 | #endif /* TCP_H */ | ||
diff --git a/vendor/luasocket/src/timeout.c b/vendor/luasocket/src/timeout.c new file mode 100644 index 00000000..2bdc0698 --- /dev/null +++ b/vendor/luasocket/src/timeout.c | |||
@@ -0,0 +1,226 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * Timeout management functions | ||
3 | * LuaSocket toolkit | ||
4 | \*=========================================================================*/ | ||
5 | #include "luasocket.h" | ||
6 | |||
7 | #include "auxiliar.h" | ||
8 | #include "timeout.h" | ||
9 | |||
10 | #include <stdio.h> | ||
11 | #include <limits.h> | ||
12 | #include <float.h> | ||
13 | |||
14 | #ifdef _WIN32 | ||
15 | #include <windows.h> | ||
16 | #else | ||
17 | #include <time.h> | ||
18 | #include <sys/time.h> | ||
19 | #endif | ||
20 | |||
21 | /* min and max macros */ | ||
22 | #ifndef MIN | ||
23 | #define MIN(x, y) ((x) < (y) ? x : y) | ||
24 | #endif | ||
25 | #ifndef MAX | ||
26 | #define MAX(x, y) ((x) > (y) ? x : y) | ||
27 | #endif | ||
28 | |||
29 | /*=========================================================================*\ | ||
30 | * Internal function prototypes | ||
31 | \*=========================================================================*/ | ||
32 | static int timeout_lua_gettime(lua_State *L); | ||
33 | static int timeout_lua_sleep(lua_State *L); | ||
34 | |||
35 | static luaL_Reg func[] = { | ||
36 | { "gettime", timeout_lua_gettime }, | ||
37 | { "sleep", timeout_lua_sleep }, | ||
38 | { NULL, NULL } | ||
39 | }; | ||
40 | |||
41 | /*=========================================================================*\ | ||
42 | * Exported functions. | ||
43 | \*=========================================================================*/ | ||
44 | /*-------------------------------------------------------------------------*\ | ||
45 | * Initialize structure | ||
46 | \*-------------------------------------------------------------------------*/ | ||
47 | void timeout_init(p_timeout tm, double block, double total) { | ||
48 | tm->block = block; | ||
49 | tm->total = total; | ||
50 | } | ||
51 | |||
52 | /*-------------------------------------------------------------------------*\ | ||
53 | * Determines how much time we have left for the next system call, | ||
54 | * if the previous call was successful | ||
55 | * Input | ||
56 | * tm: timeout control structure | ||
57 | * Returns | ||
58 | * the number of ms left or -1 if there is no time limit | ||
59 | \*-------------------------------------------------------------------------*/ | ||
60 | double timeout_get(p_timeout tm) { | ||
61 | if (tm->block < 0.0 && tm->total < 0.0) { | ||
62 | return -1; | ||
63 | } else if (tm->block < 0.0) { | ||
64 | double t = tm->total - timeout_gettime() + tm->start; | ||
65 | return MAX(t, 0.0); | ||
66 | } else if (tm->total < 0.0) { | ||
67 | return tm->block; | ||
68 | } else { | ||
69 | double t = tm->total - timeout_gettime() + tm->start; | ||
70 | return MIN(tm->block, MAX(t, 0.0)); | ||
71 | } | ||
72 | } | ||
73 | |||
74 | /*-------------------------------------------------------------------------*\ | ||
75 | * Returns time since start of operation | ||
76 | * Input | ||
77 | * tm: timeout control structure | ||
78 | * Returns | ||
79 | * start field of structure | ||
80 | \*-------------------------------------------------------------------------*/ | ||
81 | double timeout_getstart(p_timeout tm) { | ||
82 | return tm->start; | ||
83 | } | ||
84 | |||
85 | /*-------------------------------------------------------------------------*\ | ||
86 | * Determines how much time we have left for the next system call, | ||
87 | * if the previous call was a failure | ||
88 | * Input | ||
89 | * tm: timeout control structure | ||
90 | * Returns | ||
91 | * the number of ms left or -1 if there is no time limit | ||
92 | \*-------------------------------------------------------------------------*/ | ||
93 | double timeout_getretry(p_timeout tm) { | ||
94 | if (tm->block < 0.0 && tm->total < 0.0) { | ||
95 | return -1; | ||
96 | } else if (tm->block < 0.0) { | ||
97 | double t = tm->total - timeout_gettime() + tm->start; | ||
98 | return MAX(t, 0.0); | ||
99 | } else if (tm->total < 0.0) { | ||
100 | double t = tm->block - timeout_gettime() + tm->start; | ||
101 | return MAX(t, 0.0); | ||
102 | } else { | ||
103 | double t = tm->total - timeout_gettime() + tm->start; | ||
104 | return MIN(tm->block, MAX(t, 0.0)); | ||
105 | } | ||
106 | } | ||
107 | |||
108 | /*-------------------------------------------------------------------------*\ | ||
109 | * Marks the operation start time in structure | ||
110 | * Input | ||
111 | * tm: timeout control structure | ||
112 | \*-------------------------------------------------------------------------*/ | ||
113 | p_timeout timeout_markstart(p_timeout tm) { | ||
114 | tm->start = timeout_gettime(); | ||
115 | return tm; | ||
116 | } | ||
117 | |||
118 | /*-------------------------------------------------------------------------*\ | ||
119 | * Gets time in s, relative to January 1, 1970 (UTC) | ||
120 | * Returns | ||
121 | * time in s. | ||
122 | \*-------------------------------------------------------------------------*/ | ||
123 | #ifdef _WIN32 | ||
124 | double timeout_gettime(void) { | ||
125 | FILETIME ft; | ||
126 | double t; | ||
127 | GetSystemTimeAsFileTime(&ft); | ||
128 | /* Windows file time (time since January 1, 1601 (UTC)) */ | ||
129 | t = ft.dwLowDateTime/1.0e7 + ft.dwHighDateTime*(4294967296.0/1.0e7); | ||
130 | /* convert to Unix Epoch time (time since January 1, 1970 (UTC)) */ | ||
131 | return (t - 11644473600.0); | ||
132 | } | ||
133 | #else | ||
134 | double timeout_gettime(void) { | ||
135 | struct timeval v; | ||
136 | gettimeofday(&v, (struct timezone *) NULL); | ||
137 | /* Unix Epoch time (time since January 1, 1970 (UTC)) */ | ||
138 | return v.tv_sec + v.tv_usec/1.0e6; | ||
139 | } | ||
140 | #endif | ||
141 | |||
142 | /*-------------------------------------------------------------------------*\ | ||
143 | * Initializes module | ||
144 | \*-------------------------------------------------------------------------*/ | ||
145 | int timeout_open(lua_State *L) { | ||
146 | luaL_setfuncs(L, func, 0); | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | /*-------------------------------------------------------------------------*\ | ||
151 | * Sets timeout values for IO operations | ||
152 | * Lua Input: base, time [, mode] | ||
153 | * time: time out value in seconds | ||
154 | * mode: "b" for block timeout, "t" for total timeout. (default: b) | ||
155 | \*-------------------------------------------------------------------------*/ | ||
156 | int timeout_meth_settimeout(lua_State *L, p_timeout tm) { | ||
157 | double t = luaL_optnumber(L, 2, -1); | ||
158 | const char *mode = luaL_optstring(L, 3, "b"); | ||
159 | switch (*mode) { | ||
160 | case 'b': | ||
161 | tm->block = t; | ||
162 | break; | ||
163 | case 'r': case 't': | ||
164 | tm->total = t; | ||
165 | break; | ||
166 | default: | ||
167 | luaL_argcheck(L, 0, 3, "invalid timeout mode"); | ||
168 | break; | ||
169 | } | ||
170 | lua_pushnumber(L, 1); | ||
171 | return 1; | ||
172 | } | ||
173 | |||
174 | /*-------------------------------------------------------------------------*\ | ||
175 | * Gets timeout values for IO operations | ||
176 | * Lua Output: block, total | ||
177 | \*-------------------------------------------------------------------------*/ | ||
178 | int timeout_meth_gettimeout(lua_State *L, p_timeout tm) { | ||
179 | lua_pushnumber(L, tm->block); | ||
180 | lua_pushnumber(L, tm->total); | ||
181 | return 2; | ||
182 | } | ||
183 | |||
184 | /*=========================================================================*\ | ||
185 | * Test support functions | ||
186 | \*=========================================================================*/ | ||
187 | /*-------------------------------------------------------------------------*\ | ||
188 | * Returns the time the system has been up, in secconds. | ||
189 | \*-------------------------------------------------------------------------*/ | ||
190 | static int timeout_lua_gettime(lua_State *L) | ||
191 | { | ||
192 | lua_pushnumber(L, timeout_gettime()); | ||
193 | return 1; | ||
194 | } | ||
195 | |||
196 | /*-------------------------------------------------------------------------*\ | ||
197 | * Sleep for n seconds. | ||
198 | \*-------------------------------------------------------------------------*/ | ||
199 | #ifdef _WIN32 | ||
200 | int timeout_lua_sleep(lua_State *L) | ||
201 | { | ||
202 | double n = luaL_checknumber(L, 1); | ||
203 | if (n < 0.0) n = 0.0; | ||
204 | if (n < DBL_MAX/1000.0) n *= 1000.0; | ||
205 | if (n > INT_MAX) n = INT_MAX; | ||
206 | Sleep((int)n); | ||
207 | return 0; | ||
208 | } | ||
209 | #else | ||
210 | int timeout_lua_sleep(lua_State *L) | ||
211 | { | ||
212 | double n = luaL_checknumber(L, 1); | ||
213 | struct timespec t, r; | ||
214 | if (n < 0.0) n = 0.0; | ||
215 | if (n > INT_MAX) n = INT_MAX; | ||
216 | t.tv_sec = (int) n; | ||
217 | n -= t.tv_sec; | ||
218 | t.tv_nsec = (int) (n * 1000000000); | ||
219 | if (t.tv_nsec >= 1000000000) t.tv_nsec = 999999999; | ||
220 | while (nanosleep(&t, &r) != 0) { | ||
221 | t.tv_sec = r.tv_sec; | ||
222 | t.tv_nsec = r.tv_nsec; | ||
223 | } | ||
224 | return 0; | ||
225 | } | ||
226 | #endif | ||
diff --git a/vendor/luasocket/src/timeout.h b/vendor/luasocket/src/timeout.h new file mode 100644 index 00000000..9e5250d3 --- /dev/null +++ b/vendor/luasocket/src/timeout.h | |||
@@ -0,0 +1,40 @@ | |||
1 | #ifndef TIMEOUT_H | ||
2 | #define TIMEOUT_H | ||
3 | /*=========================================================================*\ | ||
4 | * Timeout management functions | ||
5 | * LuaSocket toolkit | ||
6 | \*=========================================================================*/ | ||
7 | #include "luasocket.h" | ||
8 | |||
9 | /* timeout control structure */ | ||
10 | typedef struct t_timeout_ { | ||
11 | double block; /* maximum time for blocking calls */ | ||
12 | double total; /* total number of miliseconds for operation */ | ||
13 | double start; /* time of start of operation */ | ||
14 | } t_timeout; | ||
15 | typedef t_timeout *p_timeout; | ||
16 | |||
17 | #ifndef _WIN32 | ||
18 | #pragma GCC visibility push(hidden) | ||
19 | #endif | ||
20 | |||
21 | void timeout_init(p_timeout tm, double block, double total); | ||
22 | double timeout_get(p_timeout tm); | ||
23 | double timeout_getstart(p_timeout tm); | ||
24 | double timeout_getretry(p_timeout tm); | ||
25 | p_timeout timeout_markstart(p_timeout tm); | ||
26 | |||
27 | double timeout_gettime(void); | ||
28 | |||
29 | int timeout_open(lua_State *L); | ||
30 | |||
31 | int timeout_meth_settimeout(lua_State *L, p_timeout tm); | ||
32 | int timeout_meth_gettimeout(lua_State *L, p_timeout tm); | ||
33 | |||
34 | #ifndef _WIN32 | ||
35 | #pragma GCC visibility pop | ||
36 | #endif | ||
37 | |||
38 | #define timeout_iszero(tm) ((tm)->block == 0.0) | ||
39 | |||
40 | #endif /* TIMEOUT_H */ | ||
diff --git a/vendor/luasocket/src/tp.lua b/vendor/luasocket/src/tp.lua new file mode 100644 index 00000000..b8ebc56d --- /dev/null +++ b/vendor/luasocket/src/tp.lua | |||
@@ -0,0 +1,134 @@ | |||
1 | ----------------------------------------------------------------------------- | ||
2 | -- Unified SMTP/FTP subsystem | ||
3 | -- LuaSocket toolkit. | ||
4 | -- Author: Diego Nehab | ||
5 | ----------------------------------------------------------------------------- | ||
6 | |||
7 | ----------------------------------------------------------------------------- | ||
8 | -- Declare module and import dependencies | ||
9 | ----------------------------------------------------------------------------- | ||
10 | local base = _G | ||
11 | local string = require("string") | ||
12 | local socket = require("socket") | ||
13 | local ltn12 = require("ltn12") | ||
14 | |||
15 | socket.tp = {} | ||
16 | local _M = socket.tp | ||
17 | |||
18 | ----------------------------------------------------------------------------- | ||
19 | -- Program constants | ||
20 | ----------------------------------------------------------------------------- | ||
21 | _M.TIMEOUT = 60 | ||
22 | |||
23 | ----------------------------------------------------------------------------- | ||
24 | -- Implementation | ||
25 | ----------------------------------------------------------------------------- | ||
26 | -- gets server reply (works for SMTP and FTP) | ||
27 | local function get_reply(c) | ||
28 | local code, current, sep | ||
29 | local line, err = c:receive() | ||
30 | local reply = line | ||
31 | if err then return nil, err end | ||
32 | code, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)")) | ||
33 | if not code then return nil, "invalid server reply" end | ||
34 | if sep == "-" then -- reply is multiline | ||
35 | repeat | ||
36 | line, err = c:receive() | ||
37 | if err then return nil, err end | ||
38 | current, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)")) | ||
39 | reply = reply .. "\n" .. line | ||
40 | -- reply ends with same code | ||
41 | until code == current and sep == " " | ||
42 | end | ||
43 | return code, reply | ||
44 | end | ||
45 | |||
46 | -- metatable for sock object | ||
47 | local metat = { __index = {} } | ||
48 | |||
49 | function metat.__index:getpeername() | ||
50 | return self.c:getpeername() | ||
51 | end | ||
52 | |||
53 | function metat.__index:getsockname() | ||
54 | return self.c:getpeername() | ||
55 | end | ||
56 | |||
57 | function metat.__index:check(ok) | ||
58 | local code, reply = get_reply(self.c) | ||
59 | if not code then return nil, reply end | ||
60 | if base.type(ok) ~= "function" then | ||
61 | if base.type(ok) == "table" then | ||
62 | for i, v in base.ipairs(ok) do | ||
63 | if string.find(code, v) then | ||
64 | return base.tonumber(code), reply | ||
65 | end | ||
66 | end | ||
67 | return nil, reply | ||
68 | else | ||
69 | if string.find(code, ok) then return base.tonumber(code), reply | ||
70 | else return nil, reply end | ||
71 | end | ||
72 | else return ok(base.tonumber(code), reply) end | ||
73 | end | ||
74 | |||
75 | function metat.__index:command(cmd, arg) | ||
76 | cmd = string.upper(cmd) | ||
77 | if arg then | ||
78 | return self.c:send(cmd .. " " .. arg.. "\r\n") | ||
79 | else | ||
80 | return self.c:send(cmd .. "\r\n") | ||
81 | end | ||
82 | end | ||
83 | |||
84 | function metat.__index:sink(snk, pat) | ||
85 | local chunk, err = self.c:receive(pat) | ||
86 | return snk(chunk, err) | ||
87 | end | ||
88 | |||
89 | function metat.__index:send(data) | ||
90 | return self.c:send(data) | ||
91 | end | ||
92 | |||
93 | function metat.__index:receive(pat) | ||
94 | return self.c:receive(pat) | ||
95 | end | ||
96 | |||
97 | function metat.__index:getfd() | ||
98 | return self.c:getfd() | ||
99 | end | ||
100 | |||
101 | function metat.__index:dirty() | ||
102 | return self.c:dirty() | ||
103 | end | ||
104 | |||
105 | function metat.__index:getcontrol() | ||
106 | return self.c | ||
107 | end | ||
108 | |||
109 | function metat.__index:source(source, step) | ||
110 | local sink = socket.sink("keep-open", self.c) | ||
111 | local ret, err = ltn12.pump.all(source, sink, step or ltn12.pump.step) | ||
112 | return ret, err | ||
113 | end | ||
114 | |||
115 | -- closes the underlying c | ||
116 | function metat.__index:close() | ||
117 | self.c:close() | ||
118 | return 1 | ||
119 | end | ||
120 | |||
121 | -- connect with server and return c object | ||
122 | function _M.connect(host, port, timeout, create) | ||
123 | local c, e = (create or socket.tcp)() | ||
124 | if not c then return nil, e end | ||
125 | c:settimeout(timeout or _M.TIMEOUT) | ||
126 | local r, e = c:connect(host, port) | ||
127 | if not r then | ||
128 | c:close() | ||
129 | return nil, e | ||
130 | end | ||
131 | return base.setmetatable({c = c}, metat) | ||
132 | end | ||
133 | |||
134 | return _M | ||
diff --git a/vendor/luasocket/src/udp.c b/vendor/luasocket/src/udp.c new file mode 100755 index 00000000..712ad50f --- /dev/null +++ b/vendor/luasocket/src/udp.c | |||
@@ -0,0 +1,488 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * UDP object | ||
3 | * LuaSocket toolkit | ||
4 | \*=========================================================================*/ | ||
5 | #include "luasocket.h" | ||
6 | |||
7 | #include "auxiliar.h" | ||
8 | #include "socket.h" | ||
9 | #include "inet.h" | ||
10 | #include "options.h" | ||
11 | #include "udp.h" | ||
12 | |||
13 | #include <string.h> | ||
14 | #include <stdlib.h> | ||
15 | |||
16 | /* min and max macros */ | ||
17 | #ifndef MIN | ||
18 | #define MIN(x, y) ((x) < (y) ? x : y) | ||
19 | #endif | ||
20 | #ifndef MAX | ||
21 | #define MAX(x, y) ((x) > (y) ? x : y) | ||
22 | #endif | ||
23 | |||
24 | /*=========================================================================*\ | ||
25 | * Internal function prototypes | ||
26 | \*=========================================================================*/ | ||
27 | static int global_create(lua_State *L); | ||
28 | static int global_create4(lua_State *L); | ||
29 | static int global_create6(lua_State *L); | ||
30 | static int meth_send(lua_State *L); | ||
31 | static int meth_sendto(lua_State *L); | ||
32 | static int meth_receive(lua_State *L); | ||
33 | static int meth_receivefrom(lua_State *L); | ||
34 | static int meth_getfamily(lua_State *L); | ||
35 | static int meth_getsockname(lua_State *L); | ||
36 | static int meth_getpeername(lua_State *L); | ||
37 | static int meth_gettimeout(lua_State *L); | ||
38 | static int meth_setsockname(lua_State *L); | ||
39 | static int meth_setpeername(lua_State *L); | ||
40 | static int meth_close(lua_State *L); | ||
41 | static int meth_setoption(lua_State *L); | ||
42 | static int meth_getoption(lua_State *L); | ||
43 | static int meth_settimeout(lua_State *L); | ||
44 | static int meth_getfd(lua_State *L); | ||
45 | static int meth_setfd(lua_State *L); | ||
46 | static int meth_dirty(lua_State *L); | ||
47 | |||
48 | /* udp object methods */ | ||
49 | static luaL_Reg udp_methods[] = { | ||
50 | {"__gc", meth_close}, | ||
51 | {"__tostring", auxiliar_tostring}, | ||
52 | {"close", meth_close}, | ||
53 | {"dirty", meth_dirty}, | ||
54 | {"getfamily", meth_getfamily}, | ||
55 | {"getfd", meth_getfd}, | ||
56 | {"getpeername", meth_getpeername}, | ||
57 | {"getsockname", meth_getsockname}, | ||
58 | {"receive", meth_receive}, | ||
59 | {"receivefrom", meth_receivefrom}, | ||
60 | {"send", meth_send}, | ||
61 | {"sendto", meth_sendto}, | ||
62 | {"setfd", meth_setfd}, | ||
63 | {"setoption", meth_setoption}, | ||
64 | {"getoption", meth_getoption}, | ||
65 | {"setpeername", meth_setpeername}, | ||
66 | {"setsockname", meth_setsockname}, | ||
67 | {"settimeout", meth_settimeout}, | ||
68 | {"gettimeout", meth_gettimeout}, | ||
69 | {NULL, NULL} | ||
70 | }; | ||
71 | |||
72 | /* socket options for setoption */ | ||
73 | static t_opt optset[] = { | ||
74 | {"dontroute", opt_set_dontroute}, | ||
75 | {"broadcast", opt_set_broadcast}, | ||
76 | {"reuseaddr", opt_set_reuseaddr}, | ||
77 | {"reuseport", opt_set_reuseport}, | ||
78 | {"ip-multicast-if", opt_set_ip_multicast_if}, | ||
79 | {"ip-multicast-ttl", opt_set_ip_multicast_ttl}, | ||
80 | {"ip-multicast-loop", opt_set_ip_multicast_loop}, | ||
81 | {"ip-add-membership", opt_set_ip_add_membership}, | ||
82 | {"ip-drop-membership", opt_set_ip_drop_membersip}, | ||
83 | {"ipv6-unicast-hops", opt_set_ip6_unicast_hops}, | ||
84 | {"ipv6-multicast-hops", opt_set_ip6_unicast_hops}, | ||
85 | {"ipv6-multicast-loop", opt_set_ip6_multicast_loop}, | ||
86 | {"ipv6-add-membership", opt_set_ip6_add_membership}, | ||
87 | {"ipv6-drop-membership", opt_set_ip6_drop_membersip}, | ||
88 | {"ipv6-v6only", opt_set_ip6_v6only}, | ||
89 | {"recv-buffer-size", opt_set_recv_buf_size}, | ||
90 | {"send-buffer-size", opt_set_send_buf_size}, | ||
91 | {NULL, NULL} | ||
92 | }; | ||
93 | |||
94 | /* socket options for getoption */ | ||
95 | static t_opt optget[] = { | ||
96 | {"dontroute", opt_get_dontroute}, | ||
97 | {"broadcast", opt_get_broadcast}, | ||
98 | {"reuseaddr", opt_get_reuseaddr}, | ||
99 | {"reuseport", opt_get_reuseport}, | ||
100 | {"ip-multicast-if", opt_get_ip_multicast_if}, | ||
101 | {"ip-multicast-loop", opt_get_ip_multicast_loop}, | ||
102 | {"error", opt_get_error}, | ||
103 | {"ipv6-unicast-hops", opt_get_ip6_unicast_hops}, | ||
104 | {"ipv6-multicast-hops", opt_get_ip6_unicast_hops}, | ||
105 | {"ipv6-multicast-loop", opt_get_ip6_multicast_loop}, | ||
106 | {"ipv6-v6only", opt_get_ip6_v6only}, | ||
107 | {"recv-buffer-size", opt_get_recv_buf_size}, | ||
108 | {"send-buffer-size", opt_get_send_buf_size}, | ||
109 | {NULL, NULL} | ||
110 | }; | ||
111 | |||
112 | /* functions in library namespace */ | ||
113 | static luaL_Reg func[] = { | ||
114 | {"udp", global_create}, | ||
115 | {"udp4", global_create4}, | ||
116 | {"udp6", global_create6}, | ||
117 | {NULL, NULL} | ||
118 | }; | ||
119 | |||
120 | /*-------------------------------------------------------------------------*\ | ||
121 | * Initializes module | ||
122 | \*-------------------------------------------------------------------------*/ | ||
123 | int udp_open(lua_State *L) { | ||
124 | /* create classes */ | ||
125 | auxiliar_newclass(L, "udp{connected}", udp_methods); | ||
126 | auxiliar_newclass(L, "udp{unconnected}", udp_methods); | ||
127 | /* create class groups */ | ||
128 | auxiliar_add2group(L, "udp{connected}", "udp{any}"); | ||
129 | auxiliar_add2group(L, "udp{unconnected}", "udp{any}"); | ||
130 | auxiliar_add2group(L, "udp{connected}", "select{able}"); | ||
131 | auxiliar_add2group(L, "udp{unconnected}", "select{able}"); | ||
132 | /* define library functions */ | ||
133 | luaL_setfuncs(L, func, 0); | ||
134 | /* export default UDP size */ | ||
135 | lua_pushliteral(L, "_DATAGRAMSIZE"); | ||
136 | lua_pushinteger(L, UDP_DATAGRAMSIZE); | ||
137 | lua_rawset(L, -3); | ||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | /*=========================================================================*\ | ||
142 | * Lua methods | ||
143 | \*=========================================================================*/ | ||
144 | static const char *udp_strerror(int err) { | ||
145 | /* a 'closed' error on an unconnected means the target address was not | ||
146 | * accepted by the transport layer */ | ||
147 | if (err == IO_CLOSED) return "refused"; | ||
148 | else return socket_strerror(err); | ||
149 | } | ||
150 | |||
151 | /*-------------------------------------------------------------------------*\ | ||
152 | * Send data through connected udp socket | ||
153 | \*-------------------------------------------------------------------------*/ | ||
154 | static int meth_send(lua_State *L) { | ||
155 | p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{connected}", 1); | ||
156 | p_timeout tm = &udp->tm; | ||
157 | size_t count, sent = 0; | ||
158 | int err; | ||
159 | const char *data = luaL_checklstring(L, 2, &count); | ||
160 | timeout_markstart(tm); | ||
161 | err = socket_send(&udp->sock, data, count, &sent, tm); | ||
162 | if (err != IO_DONE) { | ||
163 | lua_pushnil(L); | ||
164 | lua_pushstring(L, udp_strerror(err)); | ||
165 | return 2; | ||
166 | } | ||
167 | lua_pushnumber(L, (lua_Number) sent); | ||
168 | return 1; | ||
169 | } | ||
170 | |||
171 | /*-------------------------------------------------------------------------*\ | ||
172 | * Send data through unconnected udp socket | ||
173 | \*-------------------------------------------------------------------------*/ | ||
174 | static int meth_sendto(lua_State *L) { | ||
175 | p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); | ||
176 | size_t count, sent = 0; | ||
177 | const char *data = luaL_checklstring(L, 2, &count); | ||
178 | const char *ip = luaL_checkstring(L, 3); | ||
179 | const char *port = luaL_checkstring(L, 4); | ||
180 | p_timeout tm = &udp->tm; | ||
181 | int err; | ||
182 | struct addrinfo aihint; | ||
183 | struct addrinfo *ai; | ||
184 | memset(&aihint, 0, sizeof(aihint)); | ||
185 | aihint.ai_family = udp->family; | ||
186 | aihint.ai_socktype = SOCK_DGRAM; | ||
187 | aihint.ai_flags = AI_NUMERICHOST; | ||
188 | #ifdef AI_NUMERICSERV | ||
189 | aihint.ai_flags |= AI_NUMERICSERV; | ||
190 | #endif | ||
191 | err = getaddrinfo(ip, port, &aihint, &ai); | ||
192 | if (err) { | ||
193 | lua_pushnil(L); | ||
194 | lua_pushstring(L, LUA_GAI_STRERROR(err)); | ||
195 | return 2; | ||
196 | } | ||
197 | |||
198 | /* create socket if on first sendto if AF_UNSPEC was set */ | ||
199 | if (udp->family == AF_UNSPEC && udp->sock == SOCKET_INVALID) { | ||
200 | struct addrinfo *ap; | ||
201 | const char *errstr = NULL; | ||
202 | for (ap = ai; ap != NULL; ap = ap->ai_next) { | ||
203 | errstr = inet_trycreate(&udp->sock, ap->ai_family, SOCK_DGRAM, 0); | ||
204 | if (errstr == NULL) { | ||
205 | socket_setnonblocking(&udp->sock); | ||
206 | udp->family = ap->ai_family; | ||
207 | break; | ||
208 | } | ||
209 | } | ||
210 | if (errstr != NULL) { | ||
211 | lua_pushnil(L); | ||
212 | lua_pushstring(L, errstr); | ||
213 | freeaddrinfo(ai); | ||
214 | return 2; | ||
215 | } | ||
216 | } | ||
217 | |||
218 | timeout_markstart(tm); | ||
219 | err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr, | ||
220 | (socklen_t) ai->ai_addrlen, tm); | ||
221 | freeaddrinfo(ai); | ||
222 | if (err != IO_DONE) { | ||
223 | lua_pushnil(L); | ||
224 | lua_pushstring(L, udp_strerror(err)); | ||
225 | return 2; | ||
226 | } | ||
227 | lua_pushnumber(L, (lua_Number) sent); | ||
228 | return 1; | ||
229 | } | ||
230 | |||
231 | /*-------------------------------------------------------------------------*\ | ||
232 | * Receives data from a UDP socket | ||
233 | \*-------------------------------------------------------------------------*/ | ||
234 | static int meth_receive(lua_State *L) { | ||
235 | p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); | ||
236 | char buf[UDP_DATAGRAMSIZE]; | ||
237 | size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf)); | ||
238 | char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf; | ||
239 | int err; | ||
240 | p_timeout tm = &udp->tm; | ||
241 | timeout_markstart(tm); | ||
242 | if (!dgram) { | ||
243 | lua_pushnil(L); | ||
244 | lua_pushliteral(L, "out of memory"); | ||
245 | return 2; | ||
246 | } | ||
247 | err = socket_recv(&udp->sock, dgram, wanted, &got, tm); | ||
248 | /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ | ||
249 | if (err != IO_DONE && err != IO_CLOSED) { | ||
250 | lua_pushnil(L); | ||
251 | lua_pushstring(L, udp_strerror(err)); | ||
252 | if (wanted > sizeof(buf)) free(dgram); | ||
253 | return 2; | ||
254 | } | ||
255 | lua_pushlstring(L, dgram, got); | ||
256 | if (wanted > sizeof(buf)) free(dgram); | ||
257 | return 1; | ||
258 | } | ||
259 | |||
260 | /*-------------------------------------------------------------------------*\ | ||
261 | * Receives data and sender from a UDP socket | ||
262 | \*-------------------------------------------------------------------------*/ | ||
263 | static int meth_receivefrom(lua_State *L) { | ||
264 | p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); | ||
265 | char buf[UDP_DATAGRAMSIZE]; | ||
266 | size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf)); | ||
267 | char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf; | ||
268 | struct sockaddr_storage addr; | ||
269 | socklen_t addr_len = sizeof(addr); | ||
270 | char addrstr[INET6_ADDRSTRLEN]; | ||
271 | char portstr[6]; | ||
272 | int err; | ||
273 | p_timeout tm = &udp->tm; | ||
274 | timeout_markstart(tm); | ||
275 | if (!dgram) { | ||
276 | lua_pushnil(L); | ||
277 | lua_pushliteral(L, "out of memory"); | ||
278 | return 2; | ||
279 | } | ||
280 | err = socket_recvfrom(&udp->sock, dgram, wanted, &got, (SA *) &addr, | ||
281 | &addr_len, tm); | ||
282 | /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ | ||
283 | if (err != IO_DONE && err != IO_CLOSED) { | ||
284 | lua_pushnil(L); | ||
285 | lua_pushstring(L, udp_strerror(err)); | ||
286 | if (wanted > sizeof(buf)) free(dgram); | ||
287 | return 2; | ||
288 | } | ||
289 | err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr, | ||
290 | INET6_ADDRSTRLEN, portstr, 6, NI_NUMERICHOST | NI_NUMERICSERV); | ||
291 | if (err) { | ||
292 | lua_pushnil(L); | ||
293 | lua_pushstring(L, LUA_GAI_STRERROR(err)); | ||
294 | if (wanted > sizeof(buf)) free(dgram); | ||
295 | return 2; | ||
296 | } | ||
297 | lua_pushlstring(L, dgram, got); | ||
298 | lua_pushstring(L, addrstr); | ||
299 | lua_pushinteger(L, (int) strtol(portstr, (char **) NULL, 10)); | ||
300 | if (wanted > sizeof(buf)) free(dgram); | ||
301 | return 3; | ||
302 | } | ||
303 | |||
304 | /*-------------------------------------------------------------------------*\ | ||
305 | * Returns family as string | ||
306 | \*-------------------------------------------------------------------------*/ | ||
307 | static int meth_getfamily(lua_State *L) { | ||
308 | p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); | ||
309 | if (udp->family == AF_INET6) { | ||
310 | lua_pushliteral(L, "inet6"); | ||
311 | return 1; | ||
312 | } else { | ||
313 | lua_pushliteral(L, "inet4"); | ||
314 | return 1; | ||
315 | } | ||
316 | } | ||
317 | |||
318 | /*-------------------------------------------------------------------------*\ | ||
319 | * Select support methods | ||
320 | \*-------------------------------------------------------------------------*/ | ||
321 | static int meth_getfd(lua_State *L) { | ||
322 | p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); | ||
323 | lua_pushnumber(L, (int) udp->sock); | ||
324 | return 1; | ||
325 | } | ||
326 | |||
327 | /* this is very dangerous, but can be handy for those that are brave enough */ | ||
328 | static int meth_setfd(lua_State *L) { | ||
329 | p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); | ||
330 | udp->sock = (t_socket) luaL_checknumber(L, 2); | ||
331 | return 0; | ||
332 | } | ||
333 | |||
334 | static int meth_dirty(lua_State *L) { | ||
335 | p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); | ||
336 | (void) udp; | ||
337 | lua_pushboolean(L, 0); | ||
338 | return 1; | ||
339 | } | ||
340 | |||
341 | /*-------------------------------------------------------------------------*\ | ||
342 | * Just call inet methods | ||
343 | \*-------------------------------------------------------------------------*/ | ||
344 | static int meth_getpeername(lua_State *L) { | ||
345 | p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{connected}", 1); | ||
346 | return inet_meth_getpeername(L, &udp->sock, udp->family); | ||
347 | } | ||
348 | |||
349 | static int meth_getsockname(lua_State *L) { | ||
350 | p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); | ||
351 | return inet_meth_getsockname(L, &udp->sock, udp->family); | ||
352 | } | ||
353 | |||
354 | /*-------------------------------------------------------------------------*\ | ||
355 | * Just call option handler | ||
356 | \*-------------------------------------------------------------------------*/ | ||
357 | static int meth_setoption(lua_State *L) { | ||
358 | p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); | ||
359 | return opt_meth_setoption(L, optset, &udp->sock); | ||
360 | } | ||
361 | |||
362 | /*-------------------------------------------------------------------------*\ | ||
363 | * Just call option handler | ||
364 | \*-------------------------------------------------------------------------*/ | ||
365 | static int meth_getoption(lua_State *L) { | ||
366 | p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); | ||
367 | return opt_meth_getoption(L, optget, &udp->sock); | ||
368 | } | ||
369 | |||
370 | /*-------------------------------------------------------------------------*\ | ||
371 | * Just call tm methods | ||
372 | \*-------------------------------------------------------------------------*/ | ||
373 | static int meth_settimeout(lua_State *L) { | ||
374 | p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); | ||
375 | return timeout_meth_settimeout(L, &udp->tm); | ||
376 | } | ||
377 | |||
378 | static int meth_gettimeout(lua_State *L) { | ||
379 | p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); | ||
380 | return timeout_meth_gettimeout(L, &udp->tm); | ||
381 | } | ||
382 | |||
383 | /*-------------------------------------------------------------------------*\ | ||
384 | * Turns a master udp object into a client object. | ||
385 | \*-------------------------------------------------------------------------*/ | ||
386 | static int meth_setpeername(lua_State *L) { | ||
387 | p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); | ||
388 | p_timeout tm = &udp->tm; | ||
389 | const char *address = luaL_checkstring(L, 2); | ||
390 | int connecting = strcmp(address, "*"); | ||
391 | const char *port = connecting? luaL_checkstring(L, 3): "0"; | ||
392 | struct addrinfo connecthints; | ||
393 | const char *err; | ||
394 | memset(&connecthints, 0, sizeof(connecthints)); | ||
395 | connecthints.ai_socktype = SOCK_DGRAM; | ||
396 | /* make sure we try to connect only to the same family */ | ||
397 | connecthints.ai_family = udp->family; | ||
398 | if (connecting) { | ||
399 | err = inet_tryconnect(&udp->sock, &udp->family, address, | ||
400 | port, tm, &connecthints); | ||
401 | if (err) { | ||
402 | lua_pushnil(L); | ||
403 | lua_pushstring(L, err); | ||
404 | return 2; | ||
405 | } | ||
406 | auxiliar_setclass(L, "udp{connected}", 1); | ||
407 | } else { | ||
408 | /* we ignore possible errors because Mac OS X always | ||
409 | * returns EAFNOSUPPORT */ | ||
410 | inet_trydisconnect(&udp->sock, udp->family, tm); | ||
411 | auxiliar_setclass(L, "udp{unconnected}", 1); | ||
412 | } | ||
413 | lua_pushnumber(L, 1); | ||
414 | return 1; | ||
415 | } | ||
416 | |||
417 | /*-------------------------------------------------------------------------*\ | ||
418 | * Closes socket used by object | ||
419 | \*-------------------------------------------------------------------------*/ | ||
420 | static int meth_close(lua_State *L) { | ||
421 | p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); | ||
422 | socket_destroy(&udp->sock); | ||
423 | lua_pushnumber(L, 1); | ||
424 | return 1; | ||
425 | } | ||
426 | |||
427 | /*-------------------------------------------------------------------------*\ | ||
428 | * Turns a master object into a server object | ||
429 | \*-------------------------------------------------------------------------*/ | ||
430 | static int meth_setsockname(lua_State *L) { | ||
431 | p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); | ||
432 | const char *address = luaL_checkstring(L, 2); | ||
433 | const char *port = luaL_checkstring(L, 3); | ||
434 | const char *err; | ||
435 | struct addrinfo bindhints; | ||
436 | memset(&bindhints, 0, sizeof(bindhints)); | ||
437 | bindhints.ai_socktype = SOCK_DGRAM; | ||
438 | bindhints.ai_family = udp->family; | ||
439 | bindhints.ai_flags = AI_PASSIVE; | ||
440 | err = inet_trybind(&udp->sock, &udp->family, address, port, &bindhints); | ||
441 | if (err) { | ||
442 | lua_pushnil(L); | ||
443 | lua_pushstring(L, err); | ||
444 | return 2; | ||
445 | } | ||
446 | lua_pushnumber(L, 1); | ||
447 | return 1; | ||
448 | } | ||
449 | |||
450 | /*=========================================================================*\ | ||
451 | * Library functions | ||
452 | \*=========================================================================*/ | ||
453 | /*-------------------------------------------------------------------------*\ | ||
454 | * Creates a master udp object | ||
455 | \*-------------------------------------------------------------------------*/ | ||
456 | static int udp_create(lua_State *L, int family) { | ||
457 | /* allocate udp object */ | ||
458 | p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp)); | ||
459 | auxiliar_setclass(L, "udp{unconnected}", -1); | ||
460 | /* if family is AF_UNSPEC, we leave the socket invalid and | ||
461 | * store AF_UNSPEC into family. This will allow it to later be | ||
462 | * replaced with an AF_INET6 or AF_INET socket upon first use. */ | ||
463 | udp->sock = SOCKET_INVALID; | ||
464 | timeout_init(&udp->tm, -1, -1); | ||
465 | udp->family = family; | ||
466 | if (family != AF_UNSPEC) { | ||
467 | const char *err = inet_trycreate(&udp->sock, family, SOCK_DGRAM, 0); | ||
468 | if (err != NULL) { | ||
469 | lua_pushnil(L); | ||
470 | lua_pushstring(L, err); | ||
471 | return 2; | ||
472 | } | ||
473 | socket_setnonblocking(&udp->sock); | ||
474 | } | ||
475 | return 1; | ||
476 | } | ||
477 | |||
478 | static int global_create(lua_State *L) { | ||
479 | return udp_create(L, AF_UNSPEC); | ||
480 | } | ||
481 | |||
482 | static int global_create4(lua_State *L) { | ||
483 | return udp_create(L, AF_INET); | ||
484 | } | ||
485 | |||
486 | static int global_create6(lua_State *L) { | ||
487 | return udp_create(L, AF_INET6); | ||
488 | } | ||
diff --git a/vendor/luasocket/src/udp.h b/vendor/luasocket/src/udp.h new file mode 100644 index 00000000..07d5247f --- /dev/null +++ b/vendor/luasocket/src/udp.h | |||
@@ -0,0 +1,39 @@ | |||
1 | #ifndef UDP_H | ||
2 | #define UDP_H | ||
3 | /*=========================================================================*\ | ||
4 | * UDP object | ||
5 | * LuaSocket toolkit | ||
6 | * | ||
7 | * The udp.h module provides LuaSocket with support for UDP protocol | ||
8 | * (AF_INET, SOCK_DGRAM). | ||
9 | * | ||
10 | * Two classes are defined: connected and unconnected. UDP objects are | ||
11 | * originally unconnected. They can be "connected" to a given address | ||
12 | * with a call to the setpeername function. The same function can be used to | ||
13 | * break the connection. | ||
14 | \*=========================================================================*/ | ||
15 | #include "luasocket.h" | ||
16 | |||
17 | #include "timeout.h" | ||
18 | #include "socket.h" | ||
19 | |||
20 | #define UDP_DATAGRAMSIZE 8192 | ||
21 | |||
22 | typedef struct t_udp_ { | ||
23 | t_socket sock; | ||
24 | t_timeout tm; | ||
25 | int family; | ||
26 | } t_udp; | ||
27 | typedef t_udp *p_udp; | ||
28 | |||
29 | #ifndef _WIN32 | ||
30 | #pragma GCC visibility push(hidden) | ||
31 | #endif | ||
32 | |||
33 | int udp_open(lua_State *L); | ||
34 | |||
35 | #ifndef _WIN32 | ||
36 | #pragma GCC visibility pop | ||
37 | #endif | ||
38 | |||
39 | #endif /* UDP_H */ | ||
diff --git a/vendor/luasocket/src/unix.c b/vendor/luasocket/src/unix.c new file mode 100644 index 00000000..268d8b21 --- /dev/null +++ b/vendor/luasocket/src/unix.c | |||
@@ -0,0 +1,69 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * Unix domain socket | ||
3 | * LuaSocket toolkit | ||
4 | \*=========================================================================*/ | ||
5 | #include "luasocket.h" | ||
6 | |||
7 | #include "unixstream.h" | ||
8 | #include "unixdgram.h" | ||
9 | |||
10 | /*-------------------------------------------------------------------------*\ | ||
11 | * Modules and functions | ||
12 | \*-------------------------------------------------------------------------*/ | ||
13 | static const luaL_Reg mod[] = { | ||
14 | {"stream", unixstream_open}, | ||
15 | {"dgram", unixdgram_open}, | ||
16 | {NULL, NULL} | ||
17 | }; | ||
18 | |||
19 | static void add_alias(lua_State *L, int index, const char *name, const char *target) | ||
20 | { | ||
21 | lua_getfield(L, index, target); | ||
22 | lua_setfield(L, index, name); | ||
23 | } | ||
24 | |||
25 | static int compat_socket_unix_call(lua_State *L) | ||
26 | { | ||
27 | /* Look up socket.unix.stream in the socket.unix table (which is the first | ||
28 | * argument). */ | ||
29 | lua_getfield(L, 1, "stream"); | ||
30 | |||
31 | /* Replace the stack entry for the socket.unix table with the | ||
32 | * socket.unix.stream function. */ | ||
33 | lua_replace(L, 1); | ||
34 | |||
35 | /* Call socket.unix.stream, passing along any arguments. */ | ||
36 | int n = lua_gettop(L); | ||
37 | lua_call(L, n-1, LUA_MULTRET); | ||
38 | |||
39 | /* Pass along the return values from socket.unix.stream. */ | ||
40 | n = lua_gettop(L); | ||
41 | return n; | ||
42 | } | ||
43 | |||
44 | /*-------------------------------------------------------------------------*\ | ||
45 | * Initializes module | ||
46 | \*-------------------------------------------------------------------------*/ | ||
47 | LUASOCKET_API int luaopen_socket_unix(lua_State *L) | ||
48 | { | ||
49 | int i; | ||
50 | lua_newtable(L); | ||
51 | int socket_unix_table = lua_gettop(L); | ||
52 | |||
53 | for (i = 0; mod[i].name; i++) | ||
54 | mod[i].func(L); | ||
55 | |||
56 | /* Add backwards compatibility aliases "tcp" and "udp" for the "stream" and | ||
57 | * "dgram" functions. */ | ||
58 | add_alias(L, socket_unix_table, "tcp", "stream"); | ||
59 | add_alias(L, socket_unix_table, "udp", "dgram"); | ||
60 | |||
61 | /* Add a backwards compatibility function and a metatable setup to call it | ||
62 | * for the old socket.unix() interface. */ | ||
63 | lua_pushcfunction(L, compat_socket_unix_call); | ||
64 | lua_setfield(L, socket_unix_table, "__call"); | ||
65 | lua_pushvalue(L, socket_unix_table); | ||
66 | lua_setmetatable(L, socket_unix_table); | ||
67 | |||
68 | return 1; | ||
69 | } | ||
diff --git a/vendor/luasocket/src/unix.h b/vendor/luasocket/src/unix.h new file mode 100644 index 00000000..c2035618 --- /dev/null +++ b/vendor/luasocket/src/unix.h | |||
@@ -0,0 +1,26 @@ | |||
1 | #ifndef UNIX_H | ||
2 | #define UNIX_H | ||
3 | /*=========================================================================*\ | ||
4 | * Unix domain object | ||
5 | * LuaSocket toolkit | ||
6 | * | ||
7 | * This module is just an example of how to extend LuaSocket with a new | ||
8 | * domain. | ||
9 | \*=========================================================================*/ | ||
10 | #include "luasocket.h" | ||
11 | |||
12 | #include "buffer.h" | ||
13 | #include "timeout.h" | ||
14 | #include "socket.h" | ||
15 | |||
16 | typedef struct t_unix_ { | ||
17 | t_socket sock; | ||
18 | t_io io; | ||
19 | t_buffer buf; | ||
20 | t_timeout tm; | ||
21 | } t_unix; | ||
22 | typedef t_unix *p_unix; | ||
23 | |||
24 | LUASOCKET_API int luaopen_socket_unix(lua_State *L); | ||
25 | |||
26 | #endif /* UNIX_H */ | ||
diff --git a/vendor/luasocket/src/unixdgram.c b/vendor/luasocket/src/unixdgram.c new file mode 100644 index 00000000..69093d73 --- /dev/null +++ b/vendor/luasocket/src/unixdgram.c | |||
@@ -0,0 +1,405 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * Unix domain socket dgram submodule | ||
3 | * LuaSocket toolkit | ||
4 | \*=========================================================================*/ | ||
5 | #include "luasocket.h" | ||
6 | |||
7 | #include "auxiliar.h" | ||
8 | #include "socket.h" | ||
9 | #include "options.h" | ||
10 | #include "unix.h" | ||
11 | |||
12 | #include <string.h> | ||
13 | #include <stdlib.h> | ||
14 | |||
15 | #include <sys/un.h> | ||
16 | |||
17 | #define UNIXDGRAM_DATAGRAMSIZE 8192 | ||
18 | |||
19 | /* provide a SUN_LEN macro if sys/un.h doesn't (e.g. Android) */ | ||
20 | #ifndef SUN_LEN | ||
21 | #define SUN_LEN(ptr) \ | ||
22 | ((size_t) (((struct sockaddr_un *) 0)->sun_path) \ | ||
23 | + strlen ((ptr)->sun_path)) | ||
24 | #endif | ||
25 | |||
26 | /*=========================================================================*\ | ||
27 | * Internal function prototypes | ||
28 | \*=========================================================================*/ | ||
29 | static int global_create(lua_State *L); | ||
30 | static int meth_connect(lua_State *L); | ||
31 | static int meth_bind(lua_State *L); | ||
32 | static int meth_send(lua_State *L); | ||
33 | static int meth_receive(lua_State *L); | ||
34 | static int meth_close(lua_State *L); | ||
35 | static int meth_setoption(lua_State *L); | ||
36 | static int meth_settimeout(lua_State *L); | ||
37 | static int meth_gettimeout(lua_State *L); | ||
38 | static int meth_getfd(lua_State *L); | ||
39 | static int meth_setfd(lua_State *L); | ||
40 | static int meth_dirty(lua_State *L); | ||
41 | static int meth_receivefrom(lua_State *L); | ||
42 | static int meth_sendto(lua_State *L); | ||
43 | static int meth_getsockname(lua_State *L); | ||
44 | |||
45 | static const char *unixdgram_tryconnect(p_unix un, const char *path); | ||
46 | static const char *unixdgram_trybind(p_unix un, const char *path); | ||
47 | |||
48 | /* unixdgram object methods */ | ||
49 | static luaL_Reg unixdgram_methods[] = { | ||
50 | {"__gc", meth_close}, | ||
51 | {"__tostring", auxiliar_tostring}, | ||
52 | {"bind", meth_bind}, | ||
53 | {"close", meth_close}, | ||
54 | {"connect", meth_connect}, | ||
55 | {"dirty", meth_dirty}, | ||
56 | {"getfd", meth_getfd}, | ||
57 | {"send", meth_send}, | ||
58 | {"sendto", meth_sendto}, | ||
59 | {"receive", meth_receive}, | ||
60 | {"receivefrom", meth_receivefrom}, | ||
61 | {"setfd", meth_setfd}, | ||
62 | {"setoption", meth_setoption}, | ||
63 | {"setpeername", meth_connect}, | ||
64 | {"setsockname", meth_bind}, | ||
65 | {"getsockname", meth_getsockname}, | ||
66 | {"settimeout", meth_settimeout}, | ||
67 | {"gettimeout", meth_gettimeout}, | ||
68 | {NULL, NULL} | ||
69 | }; | ||
70 | |||
71 | /* socket option handlers */ | ||
72 | static t_opt optset[] = { | ||
73 | {"reuseaddr", opt_set_reuseaddr}, | ||
74 | {NULL, NULL} | ||
75 | }; | ||
76 | |||
77 | /* functions in library namespace */ | ||
78 | static luaL_Reg func[] = { | ||
79 | {"dgram", global_create}, | ||
80 | {NULL, NULL} | ||
81 | }; | ||
82 | |||
83 | /*-------------------------------------------------------------------------*\ | ||
84 | * Initializes module | ||
85 | \*-------------------------------------------------------------------------*/ | ||
86 | int unixdgram_open(lua_State *L) | ||
87 | { | ||
88 | /* create classes */ | ||
89 | auxiliar_newclass(L, "unixdgram{connected}", unixdgram_methods); | ||
90 | auxiliar_newclass(L, "unixdgram{unconnected}", unixdgram_methods); | ||
91 | /* create class groups */ | ||
92 | auxiliar_add2group(L, "unixdgram{connected}", "unixdgram{any}"); | ||
93 | auxiliar_add2group(L, "unixdgram{unconnected}", "unixdgram{any}"); | ||
94 | auxiliar_add2group(L, "unixdgram{connected}", "select{able}"); | ||
95 | auxiliar_add2group(L, "unixdgram{unconnected}", "select{able}"); | ||
96 | |||
97 | luaL_setfuncs(L, func, 0); | ||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | /*=========================================================================*\ | ||
102 | * Lua methods | ||
103 | \*=========================================================================*/ | ||
104 | static const char *unixdgram_strerror(int err) | ||
105 | { | ||
106 | /* a 'closed' error on an unconnected means the target address was not | ||
107 | * accepted by the transport layer */ | ||
108 | if (err == IO_CLOSED) return "refused"; | ||
109 | else return socket_strerror(err); | ||
110 | } | ||
111 | |||
112 | static int meth_send(lua_State *L) | ||
113 | { | ||
114 | p_unix un = (p_unix) auxiliar_checkclass(L, "unixdgram{connected}", 1); | ||
115 | p_timeout tm = &un->tm; | ||
116 | size_t count, sent = 0; | ||
117 | int err; | ||
118 | const char *data = luaL_checklstring(L, 2, &count); | ||
119 | timeout_markstart(tm); | ||
120 | err = socket_send(&un->sock, data, count, &sent, tm); | ||
121 | if (err != IO_DONE) { | ||
122 | lua_pushnil(L); | ||
123 | lua_pushstring(L, unixdgram_strerror(err)); | ||
124 | return 2; | ||
125 | } | ||
126 | lua_pushnumber(L, (lua_Number) sent); | ||
127 | return 1; | ||
128 | } | ||
129 | |||
130 | /*-------------------------------------------------------------------------*\ | ||
131 | * Send data through unconnected unixdgram socket | ||
132 | \*-------------------------------------------------------------------------*/ | ||
133 | static int meth_sendto(lua_State *L) | ||
134 | { | ||
135 | p_unix un = (p_unix) auxiliar_checkclass(L, "unixdgram{unconnected}", 1); | ||
136 | size_t count, sent = 0; | ||
137 | const char *data = luaL_checklstring(L, 2, &count); | ||
138 | const char *path = luaL_checkstring(L, 3); | ||
139 | p_timeout tm = &un->tm; | ||
140 | int err; | ||
141 | struct sockaddr_un remote; | ||
142 | size_t len = strlen(path); | ||
143 | |||
144 | if (len >= sizeof(remote.sun_path)) { | ||
145 | lua_pushnil(L); | ||
146 | lua_pushstring(L, "path too long"); | ||
147 | return 2; | ||
148 | } | ||
149 | |||
150 | memset(&remote, 0, sizeof(remote)); | ||
151 | strcpy(remote.sun_path, path); | ||
152 | remote.sun_family = AF_UNIX; | ||
153 | timeout_markstart(tm); | ||
154 | #ifdef UNIX_HAS_SUN_LEN | ||
155 | remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len) | ||
156 | + len + 1; | ||
157 | err = socket_sendto(&un->sock, data, count, &sent, (SA *) &remote, remote.sun_len, tm); | ||
158 | #else | ||
159 | err = socket_sendto(&un->sock, data, count, &sent, (SA *) &remote, | ||
160 | sizeof(remote.sun_family) + len, tm); | ||
161 | #endif | ||
162 | if (err != IO_DONE) { | ||
163 | lua_pushnil(L); | ||
164 | lua_pushstring(L, unixdgram_strerror(err)); | ||
165 | return 2; | ||
166 | } | ||
167 | lua_pushnumber(L, (lua_Number) sent); | ||
168 | return 1; | ||
169 | } | ||
170 | |||
171 | static int meth_receive(lua_State *L) { | ||
172 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1); | ||
173 | char buf[UNIXDGRAM_DATAGRAMSIZE]; | ||
174 | size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf)); | ||
175 | char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf; | ||
176 | int err; | ||
177 | p_timeout tm = &un->tm; | ||
178 | timeout_markstart(tm); | ||
179 | if (!dgram) { | ||
180 | lua_pushnil(L); | ||
181 | lua_pushliteral(L, "out of memory"); | ||
182 | return 2; | ||
183 | } | ||
184 | err = socket_recv(&un->sock, dgram, wanted, &got, tm); | ||
185 | /* Unlike STREAM, recv() of zero is not closed, but a zero-length packet. */ | ||
186 | if (err != IO_DONE && err != IO_CLOSED) { | ||
187 | lua_pushnil(L); | ||
188 | lua_pushstring(L, unixdgram_strerror(err)); | ||
189 | if (wanted > sizeof(buf)) free(dgram); | ||
190 | return 2; | ||
191 | } | ||
192 | lua_pushlstring(L, dgram, got); | ||
193 | if (wanted > sizeof(buf)) free(dgram); | ||
194 | return 1; | ||
195 | } | ||
196 | |||
197 | /*-------------------------------------------------------------------------*\ | ||
198 | * Receives data and sender from a DGRAM socket | ||
199 | \*-------------------------------------------------------------------------*/ | ||
200 | static int meth_receivefrom(lua_State *L) { | ||
201 | p_unix un = (p_unix) auxiliar_checkclass(L, "unixdgram{unconnected}", 1); | ||
202 | char buf[UNIXDGRAM_DATAGRAMSIZE]; | ||
203 | size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf)); | ||
204 | char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf; | ||
205 | struct sockaddr_un addr; | ||
206 | socklen_t addr_len = sizeof(addr); | ||
207 | int err; | ||
208 | p_timeout tm = &un->tm; | ||
209 | timeout_markstart(tm); | ||
210 | if (!dgram) { | ||
211 | lua_pushnil(L); | ||
212 | lua_pushliteral(L, "out of memory"); | ||
213 | return 2; | ||
214 | } | ||
215 | addr.sun_path[0] = '\0'; | ||
216 | err = socket_recvfrom(&un->sock, dgram, wanted, &got, (SA *) &addr, | ||
217 | &addr_len, tm); | ||
218 | /* Unlike STREAM, recv() of zero is not closed, but a zero-length packet. */ | ||
219 | if (err != IO_DONE && err != IO_CLOSED) { | ||
220 | lua_pushnil(L); | ||
221 | lua_pushstring(L, unixdgram_strerror(err)); | ||
222 | if (wanted > sizeof(buf)) free(dgram); | ||
223 | return 2; | ||
224 | } | ||
225 | |||
226 | lua_pushlstring(L, dgram, got); | ||
227 | /* the path may be empty, when client send without bind */ | ||
228 | lua_pushstring(L, addr.sun_path); | ||
229 | if (wanted > sizeof(buf)) free(dgram); | ||
230 | return 2; | ||
231 | } | ||
232 | |||
233 | /*-------------------------------------------------------------------------*\ | ||
234 | * Just call option handler | ||
235 | \*-------------------------------------------------------------------------*/ | ||
236 | static int meth_setoption(lua_State *L) { | ||
237 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1); | ||
238 | return opt_meth_setoption(L, optset, &un->sock); | ||
239 | } | ||
240 | |||
241 | /*-------------------------------------------------------------------------*\ | ||
242 | * Select support methods | ||
243 | \*-------------------------------------------------------------------------*/ | ||
244 | static int meth_getfd(lua_State *L) { | ||
245 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1); | ||
246 | lua_pushnumber(L, (int) un->sock); | ||
247 | return 1; | ||
248 | } | ||
249 | |||
250 | /* this is very dangerous, but can be handy for those that are brave enough */ | ||
251 | static int meth_setfd(lua_State *L) { | ||
252 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1); | ||
253 | un->sock = (t_socket) luaL_checknumber(L, 2); | ||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | static int meth_dirty(lua_State *L) { | ||
258 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1); | ||
259 | (void) un; | ||
260 | lua_pushboolean(L, 0); | ||
261 | return 1; | ||
262 | } | ||
263 | |||
264 | /*-------------------------------------------------------------------------*\ | ||
265 | * Binds an object to an address | ||
266 | \*-------------------------------------------------------------------------*/ | ||
267 | static const char *unixdgram_trybind(p_unix un, const char *path) { | ||
268 | struct sockaddr_un local; | ||
269 | size_t len = strlen(path); | ||
270 | if (len >= sizeof(local.sun_path)) return "path too long"; | ||
271 | memset(&local, 0, sizeof(local)); | ||
272 | strcpy(local.sun_path, path); | ||
273 | local.sun_family = AF_UNIX; | ||
274 | size_t addrlen = SUN_LEN(&local); | ||
275 | #ifdef UNIX_HAS_SUN_LEN | ||
276 | local.sun_len = addrlen + 1; | ||
277 | #endif | ||
278 | int err = socket_bind(&un->sock, (SA *) &local, addrlen); | ||
279 | if (err != IO_DONE) socket_destroy(&un->sock); | ||
280 | return socket_strerror(err); | ||
281 | } | ||
282 | |||
283 | static int meth_bind(lua_State *L) | ||
284 | { | ||
285 | p_unix un = (p_unix) auxiliar_checkclass(L, "unixdgram{unconnected}", 1); | ||
286 | const char *path = luaL_checkstring(L, 2); | ||
287 | const char *err = unixdgram_trybind(un, path); | ||
288 | if (err) { | ||
289 | lua_pushnil(L); | ||
290 | lua_pushstring(L, err); | ||
291 | return 2; | ||
292 | } | ||
293 | lua_pushnumber(L, 1); | ||
294 | return 1; | ||
295 | } | ||
296 | |||
297 | static int meth_getsockname(lua_State *L) | ||
298 | { | ||
299 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1); | ||
300 | struct sockaddr_un peer = {0}; | ||
301 | socklen_t peer_len = sizeof(peer); | ||
302 | |||
303 | if (getsockname(un->sock, (SA *) &peer, &peer_len) < 0) { | ||
304 | lua_pushnil(L); | ||
305 | lua_pushstring(L, socket_strerror(errno)); | ||
306 | return 2; | ||
307 | } | ||
308 | |||
309 | lua_pushstring(L, peer.sun_path); | ||
310 | return 1; | ||
311 | } | ||
312 | |||
313 | /*-------------------------------------------------------------------------*\ | ||
314 | * Turns a master unixdgram object into a client object. | ||
315 | \*-------------------------------------------------------------------------*/ | ||
316 | static const char *unixdgram_tryconnect(p_unix un, const char *path) | ||
317 | { | ||
318 | struct sockaddr_un remote; | ||
319 | size_t len = strlen(path); | ||
320 | if (len >= sizeof(remote.sun_path)) return "path too long"; | ||
321 | memset(&remote, 0, sizeof(remote)); | ||
322 | strcpy(remote.sun_path, path); | ||
323 | remote.sun_family = AF_UNIX; | ||
324 | timeout_markstart(&un->tm); | ||
325 | size_t addrlen = SUN_LEN(&remote); | ||
326 | #ifdef UNIX_HAS_SUN_LEN | ||
327 | remote.sun_len = addrlen + 1; | ||
328 | #endif | ||
329 | int err = socket_connect(&un->sock, (SA *) &remote, addrlen, &un->tm); | ||
330 | if (err != IO_DONE) socket_destroy(&un->sock); | ||
331 | return socket_strerror(err); | ||
332 | } | ||
333 | |||
334 | static int meth_connect(lua_State *L) | ||
335 | { | ||
336 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1); | ||
337 | const char *path = luaL_checkstring(L, 2); | ||
338 | const char *err = unixdgram_tryconnect(un, path); | ||
339 | if (err) { | ||
340 | lua_pushnil(L); | ||
341 | lua_pushstring(L, err); | ||
342 | return 2; | ||
343 | } | ||
344 | /* turn unconnected object into a connected object */ | ||
345 | auxiliar_setclass(L, "unixdgram{connected}", 1); | ||
346 | lua_pushnumber(L, 1); | ||
347 | return 1; | ||
348 | } | ||
349 | |||
350 | /*-------------------------------------------------------------------------*\ | ||
351 | * Closes socket used by object | ||
352 | \*-------------------------------------------------------------------------*/ | ||
353 | static int meth_close(lua_State *L) | ||
354 | { | ||
355 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1); | ||
356 | socket_destroy(&un->sock); | ||
357 | lua_pushnumber(L, 1); | ||
358 | return 1; | ||
359 | } | ||
360 | |||
361 | /*-------------------------------------------------------------------------*\ | ||
362 | * Just call tm methods | ||
363 | \*-------------------------------------------------------------------------*/ | ||
364 | static int meth_settimeout(lua_State *L) | ||
365 | { | ||
366 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1); | ||
367 | return timeout_meth_settimeout(L, &un->tm); | ||
368 | } | ||
369 | |||
370 | static int meth_gettimeout(lua_State *L) | ||
371 | { | ||
372 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1); | ||
373 | return timeout_meth_gettimeout(L, &un->tm); | ||
374 | } | ||
375 | |||
376 | /*=========================================================================*\ | ||
377 | * Library functions | ||
378 | \*=========================================================================*/ | ||
379 | /*-------------------------------------------------------------------------*\ | ||
380 | * Creates a master unixdgram object | ||
381 | \*-------------------------------------------------------------------------*/ | ||
382 | static int global_create(lua_State *L) | ||
383 | { | ||
384 | t_socket sock; | ||
385 | int err = socket_create(&sock, AF_UNIX, SOCK_DGRAM, 0); | ||
386 | /* try to allocate a system socket */ | ||
387 | if (err == IO_DONE) { | ||
388 | /* allocate unixdgram object */ | ||
389 | p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix)); | ||
390 | /* set its type as master object */ | ||
391 | auxiliar_setclass(L, "unixdgram{unconnected}", -1); | ||
392 | /* initialize remaining structure fields */ | ||
393 | socket_setnonblocking(&sock); | ||
394 | un->sock = sock; | ||
395 | io_init(&un->io, (p_send) socket_send, (p_recv) socket_recv, | ||
396 | (p_error) socket_ioerror, &un->sock); | ||
397 | timeout_init(&un->tm, -1, -1); | ||
398 | buffer_init(&un->buf, &un->io, &un->tm); | ||
399 | return 1; | ||
400 | } else { | ||
401 | lua_pushnil(L); | ||
402 | lua_pushstring(L, socket_strerror(err)); | ||
403 | return 2; | ||
404 | } | ||
405 | } | ||
diff --git a/vendor/luasocket/src/unixdgram.h b/vendor/luasocket/src/unixdgram.h new file mode 100644 index 00000000..a1a0166b --- /dev/null +++ b/vendor/luasocket/src/unixdgram.h | |||
@@ -0,0 +1,28 @@ | |||
1 | #ifndef UNIXDGRAM_H | ||
2 | #define UNIXDGRAM_H | ||
3 | /*=========================================================================*\ | ||
4 | * DGRAM object | ||
5 | * LuaSocket toolkit | ||
6 | * | ||
7 | * The dgram.h module provides LuaSocket with support for DGRAM protocol | ||
8 | * (AF_INET, SOCK_DGRAM). | ||
9 | * | ||
10 | * Two classes are defined: connected and unconnected. DGRAM objects are | ||
11 | * originally unconnected. They can be "connected" to a given address | ||
12 | * with a call to the setpeername function. The same function can be used to | ||
13 | * break the connection. | ||
14 | \*=========================================================================*/ | ||
15 | |||
16 | #include "unix.h" | ||
17 | |||
18 | #ifndef _WIN32 | ||
19 | #pragma GCC visibility push(hidden) | ||
20 | #endif | ||
21 | |||
22 | int unixdgram_open(lua_State *L); | ||
23 | |||
24 | #ifndef _WIN32 | ||
25 | #pragma GCC visibility pop | ||
26 | #endif | ||
27 | |||
28 | #endif /* UNIXDGRAM_H */ | ||
diff --git a/vendor/luasocket/src/unixstream.c b/vendor/luasocket/src/unixstream.c new file mode 100644 index 00000000..02aced9c --- /dev/null +++ b/vendor/luasocket/src/unixstream.c | |||
@@ -0,0 +1,355 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * Unix domain socket stream sub module | ||
3 | * LuaSocket toolkit | ||
4 | \*=========================================================================*/ | ||
5 | #include "luasocket.h" | ||
6 | |||
7 | #include "auxiliar.h" | ||
8 | #include "socket.h" | ||
9 | #include "options.h" | ||
10 | #include "unixstream.h" | ||
11 | |||
12 | #include <string.h> | ||
13 | #include <sys/un.h> | ||
14 | |||
15 | /*=========================================================================*\ | ||
16 | * Internal function prototypes | ||
17 | \*=========================================================================*/ | ||
18 | static int global_create(lua_State *L); | ||
19 | static int meth_connect(lua_State *L); | ||
20 | static int meth_listen(lua_State *L); | ||
21 | static int meth_bind(lua_State *L); | ||
22 | static int meth_send(lua_State *L); | ||
23 | static int meth_shutdown(lua_State *L); | ||
24 | static int meth_receive(lua_State *L); | ||
25 | static int meth_accept(lua_State *L); | ||
26 | static int meth_close(lua_State *L); | ||
27 | static int meth_setoption(lua_State *L); | ||
28 | static int meth_settimeout(lua_State *L); | ||
29 | static int meth_getfd(lua_State *L); | ||
30 | static int meth_setfd(lua_State *L); | ||
31 | static int meth_dirty(lua_State *L); | ||
32 | static int meth_getstats(lua_State *L); | ||
33 | static int meth_setstats(lua_State *L); | ||
34 | static int meth_getsockname(lua_State *L); | ||
35 | |||
36 | static const char *unixstream_tryconnect(p_unix un, const char *path); | ||
37 | static const char *unixstream_trybind(p_unix un, const char *path); | ||
38 | |||
39 | /* unixstream object methods */ | ||
40 | static luaL_Reg unixstream_methods[] = { | ||
41 | {"__gc", meth_close}, | ||
42 | {"__tostring", auxiliar_tostring}, | ||
43 | {"accept", meth_accept}, | ||
44 | {"bind", meth_bind}, | ||
45 | {"close", meth_close}, | ||
46 | {"connect", meth_connect}, | ||
47 | {"dirty", meth_dirty}, | ||
48 | {"getfd", meth_getfd}, | ||
49 | {"getstats", meth_getstats}, | ||
50 | {"setstats", meth_setstats}, | ||
51 | {"listen", meth_listen}, | ||
52 | {"receive", meth_receive}, | ||
53 | {"send", meth_send}, | ||
54 | {"setfd", meth_setfd}, | ||
55 | {"setoption", meth_setoption}, | ||
56 | {"setpeername", meth_connect}, | ||
57 | {"setsockname", meth_bind}, | ||
58 | {"getsockname", meth_getsockname}, | ||
59 | {"settimeout", meth_settimeout}, | ||
60 | {"shutdown", meth_shutdown}, | ||
61 | {NULL, NULL} | ||
62 | }; | ||
63 | |||
64 | /* socket option handlers */ | ||
65 | static t_opt optset[] = { | ||
66 | {"keepalive", opt_set_keepalive}, | ||
67 | {"reuseaddr", opt_set_reuseaddr}, | ||
68 | {"linger", opt_set_linger}, | ||
69 | {NULL, NULL} | ||
70 | }; | ||
71 | |||
72 | /* functions in library namespace */ | ||
73 | static luaL_Reg func[] = { | ||
74 | {"stream", global_create}, | ||
75 | {NULL, NULL} | ||
76 | }; | ||
77 | |||
78 | /*-------------------------------------------------------------------------*\ | ||
79 | * Initializes module | ||
80 | \*-------------------------------------------------------------------------*/ | ||
81 | int unixstream_open(lua_State *L) | ||
82 | { | ||
83 | /* create classes */ | ||
84 | auxiliar_newclass(L, "unixstream{master}", unixstream_methods); | ||
85 | auxiliar_newclass(L, "unixstream{client}", unixstream_methods); | ||
86 | auxiliar_newclass(L, "unixstream{server}", unixstream_methods); | ||
87 | |||
88 | /* create class groups */ | ||
89 | auxiliar_add2group(L, "unixstream{master}", "unixstream{any}"); | ||
90 | auxiliar_add2group(L, "unixstream{client}", "unixstream{any}"); | ||
91 | auxiliar_add2group(L, "unixstream{server}", "unixstream{any}"); | ||
92 | |||
93 | luaL_setfuncs(L, func, 0); | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | /*=========================================================================*\ | ||
98 | * Lua methods | ||
99 | \*=========================================================================*/ | ||
100 | /*-------------------------------------------------------------------------*\ | ||
101 | * Just call buffered IO methods | ||
102 | \*-------------------------------------------------------------------------*/ | ||
103 | static int meth_send(lua_State *L) { | ||
104 | p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{client}", 1); | ||
105 | return buffer_meth_send(L, &un->buf); | ||
106 | } | ||
107 | |||
108 | static int meth_receive(lua_State *L) { | ||
109 | p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{client}", 1); | ||
110 | return buffer_meth_receive(L, &un->buf); | ||
111 | } | ||
112 | |||
113 | static int meth_getstats(lua_State *L) { | ||
114 | p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{client}", 1); | ||
115 | return buffer_meth_getstats(L, &un->buf); | ||
116 | } | ||
117 | |||
118 | static int meth_setstats(lua_State *L) { | ||
119 | p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{client}", 1); | ||
120 | return buffer_meth_setstats(L, &un->buf); | ||
121 | } | ||
122 | |||
123 | /*-------------------------------------------------------------------------*\ | ||
124 | * Just call option handler | ||
125 | \*-------------------------------------------------------------------------*/ | ||
126 | static int meth_setoption(lua_State *L) { | ||
127 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1); | ||
128 | return opt_meth_setoption(L, optset, &un->sock); | ||
129 | } | ||
130 | |||
131 | /*-------------------------------------------------------------------------*\ | ||
132 | * Select support methods | ||
133 | \*-------------------------------------------------------------------------*/ | ||
134 | static int meth_getfd(lua_State *L) { | ||
135 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1); | ||
136 | lua_pushnumber(L, (int) un->sock); | ||
137 | return 1; | ||
138 | } | ||
139 | |||
140 | /* this is very dangerous, but can be handy for those that are brave enough */ | ||
141 | static int meth_setfd(lua_State *L) { | ||
142 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1); | ||
143 | un->sock = (t_socket) luaL_checknumber(L, 2); | ||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | static int meth_dirty(lua_State *L) { | ||
148 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1); | ||
149 | lua_pushboolean(L, !buffer_isempty(&un->buf)); | ||
150 | return 1; | ||
151 | } | ||
152 | |||
153 | /*-------------------------------------------------------------------------*\ | ||
154 | * Waits for and returns a client object attempting connection to the | ||
155 | * server object | ||
156 | \*-------------------------------------------------------------------------*/ | ||
157 | static int meth_accept(lua_State *L) { | ||
158 | p_unix server = (p_unix) auxiliar_checkclass(L, "unixstream{server}", 1); | ||
159 | p_timeout tm = timeout_markstart(&server->tm); | ||
160 | t_socket sock; | ||
161 | int err = socket_accept(&server->sock, &sock, NULL, NULL, tm); | ||
162 | /* if successful, push client socket */ | ||
163 | if (err == IO_DONE) { | ||
164 | p_unix clnt = (p_unix) lua_newuserdata(L, sizeof(t_unix)); | ||
165 | auxiliar_setclass(L, "unixstream{client}", -1); | ||
166 | /* initialize structure fields */ | ||
167 | socket_setnonblocking(&sock); | ||
168 | clnt->sock = sock; | ||
169 | io_init(&clnt->io, (p_send)socket_send, (p_recv)socket_recv, | ||
170 | (p_error) socket_ioerror, &clnt->sock); | ||
171 | timeout_init(&clnt->tm, -1, -1); | ||
172 | buffer_init(&clnt->buf, &clnt->io, &clnt->tm); | ||
173 | return 1; | ||
174 | } else { | ||
175 | lua_pushnil(L); | ||
176 | lua_pushstring(L, socket_strerror(err)); | ||
177 | return 2; | ||
178 | } | ||
179 | } | ||
180 | |||
181 | /*-------------------------------------------------------------------------*\ | ||
182 | * Binds an object to an address | ||
183 | \*-------------------------------------------------------------------------*/ | ||
184 | static const char *unixstream_trybind(p_unix un, const char *path) { | ||
185 | struct sockaddr_un local; | ||
186 | size_t len = strlen(path); | ||
187 | int err; | ||
188 | if (len >= sizeof(local.sun_path)) return "path too long"; | ||
189 | memset(&local, 0, sizeof(local)); | ||
190 | strcpy(local.sun_path, path); | ||
191 | local.sun_family = AF_UNIX; | ||
192 | #ifdef UNIX_HAS_SUN_LEN | ||
193 | local.sun_len = sizeof(local.sun_family) + sizeof(local.sun_len) | ||
194 | + len + 1; | ||
195 | err = socket_bind(&un->sock, (SA *) &local, local.sun_len); | ||
196 | |||
197 | #else | ||
198 | err = socket_bind(&un->sock, (SA *) &local, | ||
199 | sizeof(local.sun_family) + len); | ||
200 | #endif | ||
201 | if (err != IO_DONE) socket_destroy(&un->sock); | ||
202 | return socket_strerror(err); | ||
203 | } | ||
204 | |||
205 | static int meth_bind(lua_State *L) { | ||
206 | p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{master}", 1); | ||
207 | const char *path = luaL_checkstring(L, 2); | ||
208 | const char *err = unixstream_trybind(un, path); | ||
209 | if (err) { | ||
210 | lua_pushnil(L); | ||
211 | lua_pushstring(L, err); | ||
212 | return 2; | ||
213 | } | ||
214 | lua_pushnumber(L, 1); | ||
215 | return 1; | ||
216 | } | ||
217 | |||
218 | static int meth_getsockname(lua_State *L) | ||
219 | { | ||
220 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1); | ||
221 | struct sockaddr_un peer = {0}; | ||
222 | socklen_t peer_len = sizeof(peer); | ||
223 | |||
224 | if (getsockname(un->sock, (SA *) &peer, &peer_len) < 0) { | ||
225 | lua_pushnil(L); | ||
226 | lua_pushstring(L, socket_strerror(errno)); | ||
227 | return 2; | ||
228 | } | ||
229 | |||
230 | lua_pushstring(L, peer.sun_path); | ||
231 | return 1; | ||
232 | } | ||
233 | |||
234 | /*-------------------------------------------------------------------------*\ | ||
235 | * Turns a master unixstream object into a client object. | ||
236 | \*-------------------------------------------------------------------------*/ | ||
237 | static const char *unixstream_tryconnect(p_unix un, const char *path) | ||
238 | { | ||
239 | struct sockaddr_un remote; | ||
240 | int err; | ||
241 | size_t len = strlen(path); | ||
242 | if (len >= sizeof(remote.sun_path)) return "path too long"; | ||
243 | memset(&remote, 0, sizeof(remote)); | ||
244 | strcpy(remote.sun_path, path); | ||
245 | remote.sun_family = AF_UNIX; | ||
246 | timeout_markstart(&un->tm); | ||
247 | #ifdef UNIX_HAS_SUN_LEN | ||
248 | remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len) | ||
249 | + len + 1; | ||
250 | err = socket_connect(&un->sock, (SA *) &remote, remote.sun_len, &un->tm); | ||
251 | #else | ||
252 | err = socket_connect(&un->sock, (SA *) &remote, | ||
253 | sizeof(remote.sun_family) + len, &un->tm); | ||
254 | #endif | ||
255 | if (err != IO_DONE) socket_destroy(&un->sock); | ||
256 | return socket_strerror(err); | ||
257 | } | ||
258 | |||
259 | static int meth_connect(lua_State *L) | ||
260 | { | ||
261 | p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{master}", 1); | ||
262 | const char *path = luaL_checkstring(L, 2); | ||
263 | const char *err = unixstream_tryconnect(un, path); | ||
264 | if (err) { | ||
265 | lua_pushnil(L); | ||
266 | lua_pushstring(L, err); | ||
267 | return 2; | ||
268 | } | ||
269 | /* turn master object into a client object */ | ||
270 | auxiliar_setclass(L, "unixstream{client}", 1); | ||
271 | lua_pushnumber(L, 1); | ||
272 | return 1; | ||
273 | } | ||
274 | |||
275 | /*-------------------------------------------------------------------------*\ | ||
276 | * Closes socket used by object | ||
277 | \*-------------------------------------------------------------------------*/ | ||
278 | static int meth_close(lua_State *L) | ||
279 | { | ||
280 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1); | ||
281 | socket_destroy(&un->sock); | ||
282 | lua_pushnumber(L, 1); | ||
283 | return 1; | ||
284 | } | ||
285 | |||
286 | /*-------------------------------------------------------------------------*\ | ||
287 | * Puts the sockt in listen mode | ||
288 | \*-------------------------------------------------------------------------*/ | ||
289 | static int meth_listen(lua_State *L) | ||
290 | { | ||
291 | p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{master}", 1); | ||
292 | int backlog = (int) luaL_optnumber(L, 2, 32); | ||
293 | int err = socket_listen(&un->sock, backlog); | ||
294 | if (err != IO_DONE) { | ||
295 | lua_pushnil(L); | ||
296 | lua_pushstring(L, socket_strerror(err)); | ||
297 | return 2; | ||
298 | } | ||
299 | /* turn master object into a server object */ | ||
300 | auxiliar_setclass(L, "unixstream{server}", 1); | ||
301 | lua_pushnumber(L, 1); | ||
302 | return 1; | ||
303 | } | ||
304 | |||
305 | /*-------------------------------------------------------------------------*\ | ||
306 | * Shuts the connection down partially | ||
307 | \*-------------------------------------------------------------------------*/ | ||
308 | static int meth_shutdown(lua_State *L) | ||
309 | { | ||
310 | /* SHUT_RD, SHUT_WR, SHUT_RDWR have the value 0, 1, 2, so we can use method index directly */ | ||
311 | static const char* methods[] = { "receive", "send", "both", NULL }; | ||
312 | p_unix stream = (p_unix) auxiliar_checkclass(L, "unixstream{client}", 1); | ||
313 | int how = luaL_checkoption(L, 2, "both", methods); | ||
314 | socket_shutdown(&stream->sock, how); | ||
315 | lua_pushnumber(L, 1); | ||
316 | return 1; | ||
317 | } | ||
318 | |||
319 | /*-------------------------------------------------------------------------*\ | ||
320 | * Just call tm methods | ||
321 | \*-------------------------------------------------------------------------*/ | ||
322 | static int meth_settimeout(lua_State *L) { | ||
323 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1); | ||
324 | return timeout_meth_settimeout(L, &un->tm); | ||
325 | } | ||
326 | |||
327 | /*=========================================================================*\ | ||
328 | * Library functions | ||
329 | \*=========================================================================*/ | ||
330 | /*-------------------------------------------------------------------------*\ | ||
331 | * Creates a master unixstream object | ||
332 | \*-------------------------------------------------------------------------*/ | ||
333 | static int global_create(lua_State *L) { | ||
334 | t_socket sock; | ||
335 | int err = socket_create(&sock, AF_UNIX, SOCK_STREAM, 0); | ||
336 | /* try to allocate a system socket */ | ||
337 | if (err == IO_DONE) { | ||
338 | /* allocate unixstream object */ | ||
339 | p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix)); | ||
340 | /* set its type as master object */ | ||
341 | auxiliar_setclass(L, "unixstream{master}", -1); | ||
342 | /* initialize remaining structure fields */ | ||
343 | socket_setnonblocking(&sock); | ||
344 | un->sock = sock; | ||
345 | io_init(&un->io, (p_send) socket_send, (p_recv) socket_recv, | ||
346 | (p_error) socket_ioerror, &un->sock); | ||
347 | timeout_init(&un->tm, -1, -1); | ||
348 | buffer_init(&un->buf, &un->io, &un->tm); | ||
349 | return 1; | ||
350 | } else { | ||
351 | lua_pushnil(L); | ||
352 | lua_pushstring(L, socket_strerror(err)); | ||
353 | return 2; | ||
354 | } | ||
355 | } | ||
diff --git a/vendor/luasocket/src/unixstream.h b/vendor/luasocket/src/unixstream.h new file mode 100644 index 00000000..7916affa --- /dev/null +++ b/vendor/luasocket/src/unixstream.h | |||
@@ -0,0 +1,29 @@ | |||
1 | #ifndef UNIXSTREAM_H | ||
2 | #define UNIXSTREAM_H | ||
3 | /*=========================================================================*\ | ||
4 | * UNIX STREAM object | ||
5 | * LuaSocket toolkit | ||
6 | * | ||
7 | * The unixstream.h module is basicly a glue that puts together modules buffer.h, | ||
8 | * timeout.h socket.h and inet.h to provide the LuaSocket UNIX STREAM (AF_UNIX, | ||
9 | * SOCK_STREAM) support. | ||
10 | * | ||
11 | * Three classes are defined: master, client and server. The master class is | ||
12 | * a newly created unixstream object, that has not been bound or connected. Server | ||
13 | * objects are unixstream objects bound to some local address. Client objects are | ||
14 | * unixstream objects either connected to some address or returned by the accept | ||
15 | * method of a server object. | ||
16 | \*=========================================================================*/ | ||
17 | #include "unix.h" | ||
18 | |||
19 | #ifndef _WIN32 | ||
20 | #pragma GCC visibility push(hidden) | ||
21 | #endif | ||
22 | |||
23 | int unixstream_open(lua_State *L); | ||
24 | |||
25 | #ifndef _WIN32 | ||
26 | #pragma GCC visibility pop | ||
27 | #endif | ||
28 | |||
29 | #endif /* UNIXSTREAM_H */ | ||
diff --git a/vendor/luasocket/src/url.lua b/vendor/luasocket/src/url.lua new file mode 100644 index 00000000..8e0dc5ce --- /dev/null +++ b/vendor/luasocket/src/url.lua | |||
@@ -0,0 +1,331 @@ | |||
1 | ----------------------------------------------------------------------------- | ||
2 | -- URI parsing, composition and relative URL resolution | ||
3 | -- LuaSocket toolkit. | ||
4 | -- Author: Diego Nehab | ||
5 | ----------------------------------------------------------------------------- | ||
6 | |||
7 | ----------------------------------------------------------------------------- | ||
8 | -- Declare module | ||
9 | ----------------------------------------------------------------------------- | ||
10 | local string = require("string") | ||
11 | local base = _G | ||
12 | local table = require("table") | ||
13 | local socket = require("socket") | ||
14 | |||
15 | socket.url = {} | ||
16 | local _M = socket.url | ||
17 | |||
18 | ----------------------------------------------------------------------------- | ||
19 | -- Module version | ||
20 | ----------------------------------------------------------------------------- | ||
21 | _M._VERSION = "URL 1.0.3" | ||
22 | |||
23 | ----------------------------------------------------------------------------- | ||
24 | -- Encodes a string into its escaped hexadecimal representation | ||
25 | -- Input | ||
26 | -- s: binary string to be encoded | ||
27 | -- Returns | ||
28 | -- escaped representation of string binary | ||
29 | ----------------------------------------------------------------------------- | ||
30 | function _M.escape(s) | ||
31 | return (string.gsub(s, "([^A-Za-z0-9_])", function(c) | ||
32 | return string.format("%%%02x", string.byte(c)) | ||
33 | end)) | ||
34 | end | ||
35 | |||
36 | ----------------------------------------------------------------------------- | ||
37 | -- Protects a path segment, to prevent it from interfering with the | ||
38 | -- url parsing. | ||
39 | -- Input | ||
40 | -- s: binary string to be encoded | ||
41 | -- Returns | ||
42 | -- escaped representation of string binary | ||
43 | ----------------------------------------------------------------------------- | ||
44 | local function make_set(t) | ||
45 | local s = {} | ||
46 | for i,v in base.ipairs(t) do | ||
47 | s[t[i]] = 1 | ||
48 | end | ||
49 | return s | ||
50 | end | ||
51 | |||
52 | -- these are allowed within a path segment, along with alphanum | ||
53 | -- other characters must be escaped | ||
54 | local segment_set = make_set { | ||
55 | "-", "_", ".", "!", "~", "*", "'", "(", | ||
56 | ")", ":", "@", "&", "=", "+", "$", ",", | ||
57 | } | ||
58 | |||
59 | local function protect_segment(s) | ||
60 | return string.gsub(s, "([^A-Za-z0-9_])", function (c) | ||
61 | if segment_set[c] then return c | ||
62 | else return string.format("%%%02X", string.byte(c)) end | ||
63 | end) | ||
64 | end | ||
65 | |||
66 | ----------------------------------------------------------------------------- | ||
67 | -- Unencodes a escaped hexadecimal string into its binary representation | ||
68 | -- Input | ||
69 | -- s: escaped hexadecimal string to be unencoded | ||
70 | -- Returns | ||
71 | -- unescaped binary representation of escaped hexadecimal binary | ||
72 | ----------------------------------------------------------------------------- | ||
73 | function _M.unescape(s) | ||
74 | return (string.gsub(s, "%%(%x%x)", function(hex) | ||
75 | return string.char(base.tonumber(hex, 16)) | ||
76 | end)) | ||
77 | end | ||
78 | |||
79 | ----------------------------------------------------------------------------- | ||
80 | -- Removes '..' and '.' components appropriately from a path. | ||
81 | -- Input | ||
82 | -- path | ||
83 | -- Returns | ||
84 | -- dot-normalized path | ||
85 | local function remove_dot_components(path) | ||
86 | local marker = string.char(1) | ||
87 | repeat | ||
88 | local was = path | ||
89 | path = path:gsub('//', '/'..marker..'/', 1) | ||
90 | until path == was | ||
91 | repeat | ||
92 | local was = path | ||
93 | path = path:gsub('/%./', '/', 1) | ||
94 | until path == was | ||
95 | repeat | ||
96 | local was = path | ||
97 | path = path:gsub('[^/]+/%.%./([^/]+)', '%1', 1) | ||
98 | until path == was | ||
99 | path = path:gsub('[^/]+/%.%./*$', '') | ||
100 | path = path:gsub('/%.%.$', '/') | ||
101 | path = path:gsub('/%.$', '/') | ||
102 | path = path:gsub('^/%.%./', '/') | ||
103 | path = path:gsub(marker, '') | ||
104 | return path | ||
105 | end | ||
106 | |||
107 | ----------------------------------------------------------------------------- | ||
108 | -- Builds a path from a base path and a relative path | ||
109 | -- Input | ||
110 | -- base_path | ||
111 | -- relative_path | ||
112 | -- Returns | ||
113 | -- corresponding absolute path | ||
114 | ----------------------------------------------------------------------------- | ||
115 | local function absolute_path(base_path, relative_path) | ||
116 | if string.sub(relative_path, 1, 1) == "/" then | ||
117 | return remove_dot_components(relative_path) end | ||
118 | base_path = base_path:gsub("[^/]*$", "") | ||
119 | if not base_path:find'/$' then base_path = base_path .. '/' end | ||
120 | local path = base_path .. relative_path | ||
121 | path = remove_dot_components(path) | ||
122 | return path | ||
123 | end | ||
124 | |||
125 | ----------------------------------------------------------------------------- | ||
126 | -- Parses a url and returns a table with all its parts according to RFC 2396 | ||
127 | -- The following grammar describes the names given to the URL parts | ||
128 | -- <url> ::= <scheme>://<authority>/<path>;<params>?<query>#<fragment> | ||
129 | -- <authority> ::= <userinfo>@<host>:<port> | ||
130 | -- <userinfo> ::= <user>[:<password>] | ||
131 | -- <path> :: = {<segment>/}<segment> | ||
132 | -- Input | ||
133 | -- url: uniform resource locator of request | ||
134 | -- default: table with default values for each field | ||
135 | -- Returns | ||
136 | -- table with the following fields, where RFC naming conventions have | ||
137 | -- been preserved: | ||
138 | -- scheme, authority, userinfo, user, password, host, port, | ||
139 | -- path, params, query, fragment | ||
140 | -- Obs: | ||
141 | -- the leading '/' in {/<path>} is considered part of <path> | ||
142 | ----------------------------------------------------------------------------- | ||
143 | function _M.parse(url, default) | ||
144 | -- initialize default parameters | ||
145 | local parsed = {} | ||
146 | for i,v in base.pairs(default or parsed) do parsed[i] = v end | ||
147 | -- empty url is parsed to nil | ||
148 | if not url or url == "" then return nil, "invalid url" end | ||
149 | -- remove whitespace | ||
150 | -- url = string.gsub(url, "%s", "") | ||
151 | -- get scheme | ||
152 | url = string.gsub(url, "^([%w][%w%+%-%.]*)%:", | ||
153 | function(s) parsed.scheme = s; return "" end) | ||
154 | -- get authority | ||
155 | url = string.gsub(url, "^//([^/]*)", function(n) | ||
156 | parsed.authority = n | ||
157 | return "" | ||
158 | end) | ||
159 | -- get fragment | ||
160 | url = string.gsub(url, "#(.*)$", function(f) | ||
161 | parsed.fragment = f | ||
162 | return "" | ||
163 | end) | ||
164 | -- get query string | ||
165 | url = string.gsub(url, "%?(.*)", function(q) | ||
166 | parsed.query = q | ||
167 | return "" | ||
168 | end) | ||
169 | -- get params | ||
170 | url = string.gsub(url, "%;(.*)", function(p) | ||
171 | parsed.params = p | ||
172 | return "" | ||
173 | end) | ||
174 | -- path is whatever was left | ||
175 | if url ~= "" then parsed.path = url end | ||
176 | local authority = parsed.authority | ||
177 | if not authority then return parsed end | ||
178 | authority = string.gsub(authority,"^([^@]*)@", | ||
179 | function(u) parsed.userinfo = u; return "" end) | ||
180 | authority = string.gsub(authority, ":([^:%]]*)$", | ||
181 | function(p) parsed.port = p; return "" end) | ||
182 | if authority ~= "" then | ||
183 | -- IPv6? | ||
184 | parsed.host = string.match(authority, "^%[(.+)%]$") or authority | ||
185 | end | ||
186 | local userinfo = parsed.userinfo | ||
187 | if not userinfo then return parsed end | ||
188 | userinfo = string.gsub(userinfo, ":([^:]*)$", | ||
189 | function(p) parsed.password = p; return "" end) | ||
190 | parsed.user = userinfo | ||
191 | return parsed | ||
192 | end | ||
193 | |||
194 | ----------------------------------------------------------------------------- | ||
195 | -- Rebuilds a parsed URL from its components. | ||
196 | -- Components are protected if any reserved or unallowed characters are found | ||
197 | -- Input | ||
198 | -- parsed: parsed URL, as returned by parse | ||
199 | -- Returns | ||
200 | -- a stringing with the corresponding URL | ||
201 | ----------------------------------------------------------------------------- | ||
202 | function _M.build(parsed) | ||
203 | --local ppath = _M.parse_path(parsed.path or "") | ||
204 | --local url = _M.build_path(ppath) | ||
205 | local url = parsed.path or "" | ||
206 | if parsed.params then url = url .. ";" .. parsed.params end | ||
207 | if parsed.query then url = url .. "?" .. parsed.query end | ||
208 | local authority = parsed.authority | ||
209 | if parsed.host then | ||
210 | authority = parsed.host | ||
211 | if string.find(authority, ":") then -- IPv6? | ||
212 | authority = "[" .. authority .. "]" | ||
213 | end | ||
214 | if parsed.port then authority = authority .. ":" .. base.tostring(parsed.port) end | ||
215 | local userinfo = parsed.userinfo | ||
216 | if parsed.user then | ||
217 | userinfo = parsed.user | ||
218 | if parsed.password then | ||
219 | userinfo = userinfo .. ":" .. parsed.password | ||
220 | end | ||
221 | end | ||
222 | if userinfo then authority = userinfo .. "@" .. authority end | ||
223 | end | ||
224 | if authority then url = "//" .. authority .. url end | ||
225 | if parsed.scheme then url = parsed.scheme .. ":" .. url end | ||
226 | if parsed.fragment then url = url .. "#" .. parsed.fragment end | ||
227 | -- url = string.gsub(url, "%s", "") | ||
228 | return url | ||
229 | end | ||
230 | |||
231 | ----------------------------------------------------------------------------- | ||
232 | -- Builds a absolute URL from a base and a relative URL according to RFC 2396 | ||
233 | -- Input | ||
234 | -- base_url | ||
235 | -- relative_url | ||
236 | -- Returns | ||
237 | -- corresponding absolute url | ||
238 | ----------------------------------------------------------------------------- | ||
239 | function _M.absolute(base_url, relative_url) | ||
240 | local base_parsed | ||
241 | if base.type(base_url) == "table" then | ||
242 | base_parsed = base_url | ||
243 | base_url = _M.build(base_parsed) | ||
244 | else | ||
245 | base_parsed = _M.parse(base_url) | ||
246 | end | ||
247 | local result | ||
248 | local relative_parsed = _M.parse(relative_url) | ||
249 | if not base_parsed then | ||
250 | result = relative_url | ||
251 | elseif not relative_parsed then | ||
252 | result = base_url | ||
253 | elseif relative_parsed.scheme then | ||
254 | result = relative_url | ||
255 | else | ||
256 | relative_parsed.scheme = base_parsed.scheme | ||
257 | if not relative_parsed.authority then | ||
258 | relative_parsed.authority = base_parsed.authority | ||
259 | if not relative_parsed.path then | ||
260 | relative_parsed.path = base_parsed.path | ||
261 | if not relative_parsed.params then | ||
262 | relative_parsed.params = base_parsed.params | ||
263 | if not relative_parsed.query then | ||
264 | relative_parsed.query = base_parsed.query | ||
265 | end | ||
266 | end | ||
267 | else | ||
268 | relative_parsed.path = absolute_path(base_parsed.path or "", | ||
269 | relative_parsed.path) | ||
270 | end | ||
271 | end | ||
272 | result = _M.build(relative_parsed) | ||
273 | end | ||
274 | return remove_dot_components(result) | ||
275 | end | ||
276 | |||
277 | ----------------------------------------------------------------------------- | ||
278 | -- Breaks a path into its segments, unescaping the segments | ||
279 | -- Input | ||
280 | -- path | ||
281 | -- Returns | ||
282 | -- segment: a table with one entry per segment | ||
283 | ----------------------------------------------------------------------------- | ||
284 | function _M.parse_path(path) | ||
285 | local parsed = {} | ||
286 | path = path or "" | ||
287 | --path = string.gsub(path, "%s", "") | ||
288 | string.gsub(path, "([^/]+)", function (s) table.insert(parsed, s) end) | ||
289 | for i = 1, #parsed do | ||
290 | parsed[i] = _M.unescape(parsed[i]) | ||
291 | end | ||
292 | if string.sub(path, 1, 1) == "/" then parsed.is_absolute = 1 end | ||
293 | if string.sub(path, -1, -1) == "/" then parsed.is_directory = 1 end | ||
294 | return parsed | ||
295 | end | ||
296 | |||
297 | ----------------------------------------------------------------------------- | ||
298 | -- Builds a path component from its segments, escaping protected characters. | ||
299 | -- Input | ||
300 | -- parsed: path segments | ||
301 | -- unsafe: if true, segments are not protected before path is built | ||
302 | -- Returns | ||
303 | -- path: corresponding path stringing | ||
304 | ----------------------------------------------------------------------------- | ||
305 | function _M.build_path(parsed, unsafe) | ||
306 | local path = "" | ||
307 | local n = #parsed | ||
308 | if unsafe then | ||
309 | for i = 1, n-1 do | ||
310 | path = path .. parsed[i] | ||
311 | path = path .. "/" | ||
312 | end | ||
313 | if n > 0 then | ||
314 | path = path .. parsed[n] | ||
315 | if parsed.is_directory then path = path .. "/" end | ||
316 | end | ||
317 | else | ||
318 | for i = 1, n-1 do | ||
319 | path = path .. protect_segment(parsed[i]) | ||
320 | path = path .. "/" | ||
321 | end | ||
322 | if n > 0 then | ||
323 | path = path .. protect_segment(parsed[n]) | ||
324 | if parsed.is_directory then path = path .. "/" end | ||
325 | end | ||
326 | end | ||
327 | if parsed.is_absolute then path = "/" .. path end | ||
328 | return path | ||
329 | end | ||
330 | |||
331 | return _M | ||
diff --git a/vendor/luasocket/src/usocket.c b/vendor/luasocket/src/usocket.c new file mode 100644 index 00000000..69635daa --- /dev/null +++ b/vendor/luasocket/src/usocket.c | |||
@@ -0,0 +1,454 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * Socket compatibilization module for Unix | ||
3 | * LuaSocket toolkit | ||
4 | * | ||
5 | * The code is now interrupt-safe. | ||
6 | * The penalty of calling select to avoid busy-wait is only paid when | ||
7 | * the I/O call fail in the first place. | ||
8 | \*=========================================================================*/ | ||
9 | #include "luasocket.h" | ||
10 | |||
11 | #include "socket.h" | ||
12 | #include "pierror.h" | ||
13 | |||
14 | #include <string.h> | ||
15 | #include <signal.h> | ||
16 | |||
17 | /*-------------------------------------------------------------------------*\ | ||
18 | * Wait for readable/writable/connected socket with timeout | ||
19 | \*-------------------------------------------------------------------------*/ | ||
20 | #ifndef SOCKET_SELECT | ||
21 | #include <sys/poll.h> | ||
22 | |||
23 | #define WAITFD_R POLLIN | ||
24 | #define WAITFD_W POLLOUT | ||
25 | #define WAITFD_C (POLLIN|POLLOUT) | ||
26 | int socket_waitfd(p_socket ps, int sw, p_timeout tm) { | ||
27 | int ret; | ||
28 | struct pollfd pfd; | ||
29 | pfd.fd = *ps; | ||
30 | pfd.events = sw; | ||
31 | pfd.revents = 0; | ||
32 | if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */ | ||
33 | do { | ||
34 | int t = (int)(timeout_getretry(tm)*1e3); | ||
35 | ret = poll(&pfd, 1, t >= 0? t: -1); | ||
36 | } while (ret == -1 && errno == EINTR); | ||
37 | if (ret == -1) return errno; | ||
38 | if (ret == 0) return IO_TIMEOUT; | ||
39 | if (sw == WAITFD_C && (pfd.revents & (POLLIN|POLLERR))) return IO_CLOSED; | ||
40 | return IO_DONE; | ||
41 | } | ||
42 | #else | ||
43 | |||
44 | #define WAITFD_R 1 | ||
45 | #define WAITFD_W 2 | ||
46 | #define WAITFD_C (WAITFD_R|WAITFD_W) | ||
47 | |||
48 | int socket_waitfd(p_socket ps, int sw, p_timeout tm) { | ||
49 | int ret; | ||
50 | fd_set rfds, wfds, *rp, *wp; | ||
51 | struct timeval tv, *tp; | ||
52 | double t; | ||
53 | if (*ps >= FD_SETSIZE) return EINVAL; | ||
54 | if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */ | ||
55 | do { | ||
56 | /* must set bits within loop, because select may have modifed them */ | ||
57 | rp = wp = NULL; | ||
58 | if (sw & WAITFD_R) { FD_ZERO(&rfds); FD_SET(*ps, &rfds); rp = &rfds; } | ||
59 | if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; } | ||
60 | t = timeout_getretry(tm); | ||
61 | tp = NULL; | ||
62 | if (t >= 0.0) { | ||
63 | tv.tv_sec = (int)t; | ||
64 | tv.tv_usec = (int)((t-tv.tv_sec)*1.0e6); | ||
65 | tp = &tv; | ||
66 | } | ||
67 | ret = select(*ps+1, rp, wp, NULL, tp); | ||
68 | } while (ret == -1 && errno == EINTR); | ||
69 | if (ret == -1) return errno; | ||
70 | if (ret == 0) return IO_TIMEOUT; | ||
71 | if (sw == WAITFD_C && FD_ISSET(*ps, &rfds)) return IO_CLOSED; | ||
72 | return IO_DONE; | ||
73 | } | ||
74 | #endif | ||
75 | |||
76 | |||
77 | /*-------------------------------------------------------------------------*\ | ||
78 | * Initializes module | ||
79 | \*-------------------------------------------------------------------------*/ | ||
80 | int socket_open(void) { | ||
81 | /* installs a handler to ignore sigpipe or it will crash us */ | ||
82 | signal(SIGPIPE, SIG_IGN); | ||
83 | return 1; | ||
84 | } | ||
85 | |||
86 | /*-------------------------------------------------------------------------*\ | ||
87 | * Close module | ||
88 | \*-------------------------------------------------------------------------*/ | ||
89 | int socket_close(void) { | ||
90 | return 1; | ||
91 | } | ||
92 | |||
93 | /*-------------------------------------------------------------------------*\ | ||
94 | * Close and inutilize socket | ||
95 | \*-------------------------------------------------------------------------*/ | ||
96 | void socket_destroy(p_socket ps) { | ||
97 | if (*ps != SOCKET_INVALID) { | ||
98 | close(*ps); | ||
99 | *ps = SOCKET_INVALID; | ||
100 | } | ||
101 | } | ||
102 | |||
103 | /*-------------------------------------------------------------------------*\ | ||
104 | * Select with timeout control | ||
105 | \*-------------------------------------------------------------------------*/ | ||
106 | int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, | ||
107 | p_timeout tm) { | ||
108 | int ret; | ||
109 | do { | ||
110 | struct timeval tv; | ||
111 | double t = timeout_getretry(tm); | ||
112 | tv.tv_sec = (int) t; | ||
113 | tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6); | ||
114 | /* timeout = 0 means no wait */ | ||
115 | ret = select(n, rfds, wfds, efds, t >= 0.0 ? &tv: NULL); | ||
116 | } while (ret < 0 && errno == EINTR); | ||
117 | return ret; | ||
118 | } | ||
119 | |||
120 | /*-------------------------------------------------------------------------*\ | ||
121 | * Creates and sets up a socket | ||
122 | \*-------------------------------------------------------------------------*/ | ||
123 | int socket_create(p_socket ps, int domain, int type, int protocol) { | ||
124 | *ps = socket(domain, type, protocol); | ||
125 | if (*ps != SOCKET_INVALID) return IO_DONE; | ||
126 | else return errno; | ||
127 | } | ||
128 | |||
129 | /*-------------------------------------------------------------------------*\ | ||
130 | * Binds or returns error message | ||
131 | \*-------------------------------------------------------------------------*/ | ||
132 | int socket_bind(p_socket ps, SA *addr, socklen_t len) { | ||
133 | int err = IO_DONE; | ||
134 | socket_setblocking(ps); | ||
135 | if (bind(*ps, addr, len) < 0) err = errno; | ||
136 | socket_setnonblocking(ps); | ||
137 | return err; | ||
138 | } | ||
139 | |||
140 | /*-------------------------------------------------------------------------*\ | ||
141 | * | ||
142 | \*-------------------------------------------------------------------------*/ | ||
143 | int socket_listen(p_socket ps, int backlog) { | ||
144 | int err = IO_DONE; | ||
145 | if (listen(*ps, backlog)) err = errno; | ||
146 | return err; | ||
147 | } | ||
148 | |||
149 | /*-------------------------------------------------------------------------*\ | ||
150 | * | ||
151 | \*-------------------------------------------------------------------------*/ | ||
152 | void socket_shutdown(p_socket ps, int how) { | ||
153 | shutdown(*ps, how); | ||
154 | } | ||
155 | |||
156 | /*-------------------------------------------------------------------------*\ | ||
157 | * Connects or returns error message | ||
158 | \*-------------------------------------------------------------------------*/ | ||
159 | int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) { | ||
160 | int err; | ||
161 | /* avoid calling on closed sockets */ | ||
162 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
163 | /* call connect until done or failed without being interrupted */ | ||
164 | do if (connect(*ps, addr, len) == 0) return IO_DONE; | ||
165 | while ((err = errno) == EINTR); | ||
166 | /* if connection failed immediately, return error code */ | ||
167 | if (err != EINPROGRESS && err != EAGAIN) return err; | ||
168 | /* zero timeout case optimization */ | ||
169 | if (timeout_iszero(tm)) return IO_TIMEOUT; | ||
170 | /* wait until we have the result of the connection attempt or timeout */ | ||
171 | err = socket_waitfd(ps, WAITFD_C, tm); | ||
172 | if (err == IO_CLOSED) { | ||
173 | if (recv(*ps, (char *) &err, 0, 0) == 0) return IO_DONE; | ||
174 | else return errno; | ||
175 | } else return err; | ||
176 | } | ||
177 | |||
178 | /*-------------------------------------------------------------------------*\ | ||
179 | * Accept with timeout | ||
180 | \*-------------------------------------------------------------------------*/ | ||
181 | int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, p_timeout tm) { | ||
182 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
183 | for ( ;; ) { | ||
184 | int err; | ||
185 | if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID) return IO_DONE; | ||
186 | err = errno; | ||
187 | if (err == EINTR) continue; | ||
188 | if (err != EAGAIN && err != ECONNABORTED) return err; | ||
189 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; | ||
190 | } | ||
191 | /* can't reach here */ | ||
192 | return IO_UNKNOWN; | ||
193 | } | ||
194 | |||
195 | /*-------------------------------------------------------------------------*\ | ||
196 | * Send with timeout | ||
197 | \*-------------------------------------------------------------------------*/ | ||
198 | int socket_send(p_socket ps, const char *data, size_t count, | ||
199 | size_t *sent, p_timeout tm) | ||
200 | { | ||
201 | int err; | ||
202 | *sent = 0; | ||
203 | /* avoid making system calls on closed sockets */ | ||
204 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
205 | /* loop until we send something or we give up on error */ | ||
206 | for ( ;; ) { | ||
207 | long put = (long) send(*ps, data, count, 0); | ||
208 | /* if we sent anything, we are done */ | ||
209 | if (put >= 0) { | ||
210 | *sent = put; | ||
211 | return IO_DONE; | ||
212 | } | ||
213 | err = errno; | ||
214 | /* EPIPE means the connection was closed */ | ||
215 | if (err == EPIPE) return IO_CLOSED; | ||
216 | /* EPROTOTYPE means the connection is being closed (on Yosemite!)*/ | ||
217 | if (err == EPROTOTYPE) continue; | ||
218 | /* we call was interrupted, just try again */ | ||
219 | if (err == EINTR) continue; | ||
220 | /* if failed fatal reason, report error */ | ||
221 | if (err != EAGAIN) return err; | ||
222 | /* wait until we can send something or we timeout */ | ||
223 | if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; | ||
224 | } | ||
225 | /* can't reach here */ | ||
226 | return IO_UNKNOWN; | ||
227 | } | ||
228 | |||
229 | /*-------------------------------------------------------------------------*\ | ||
230 | * Sendto with timeout | ||
231 | \*-------------------------------------------------------------------------*/ | ||
232 | int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, | ||
233 | SA *addr, socklen_t len, p_timeout tm) | ||
234 | { | ||
235 | int err; | ||
236 | *sent = 0; | ||
237 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
238 | for ( ;; ) { | ||
239 | long put = (long) sendto(*ps, data, count, 0, addr, len); | ||
240 | if (put >= 0) { | ||
241 | *sent = put; | ||
242 | return IO_DONE; | ||
243 | } | ||
244 | err = errno; | ||
245 | if (err == EPIPE) return IO_CLOSED; | ||
246 | if (err == EPROTOTYPE) continue; | ||
247 | if (err == EINTR) continue; | ||
248 | if (err != EAGAIN) return err; | ||
249 | if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; | ||
250 | } | ||
251 | return IO_UNKNOWN; | ||
252 | } | ||
253 | |||
254 | /*-------------------------------------------------------------------------*\ | ||
255 | * Receive with timeout | ||
256 | \*-------------------------------------------------------------------------*/ | ||
257 | int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm) { | ||
258 | int err; | ||
259 | *got = 0; | ||
260 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
261 | for ( ;; ) { | ||
262 | long taken = (long) recv(*ps, data, count, 0); | ||
263 | if (taken > 0) { | ||
264 | *got = taken; | ||
265 | return IO_DONE; | ||
266 | } | ||
267 | err = errno; | ||
268 | if (taken == 0) return IO_CLOSED; | ||
269 | if (err == EINTR) continue; | ||
270 | if (err != EAGAIN) return err; | ||
271 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; | ||
272 | } | ||
273 | return IO_UNKNOWN; | ||
274 | } | ||
275 | |||
276 | /*-------------------------------------------------------------------------*\ | ||
277 | * Recvfrom with timeout | ||
278 | \*-------------------------------------------------------------------------*/ | ||
279 | int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, | ||
280 | SA *addr, socklen_t *len, p_timeout tm) { | ||
281 | int err; | ||
282 | *got = 0; | ||
283 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
284 | for ( ;; ) { | ||
285 | long taken = (long) recvfrom(*ps, data, count, 0, addr, len); | ||
286 | if (taken > 0) { | ||
287 | *got = taken; | ||
288 | return IO_DONE; | ||
289 | } | ||
290 | err = errno; | ||
291 | if (taken == 0) return IO_CLOSED; | ||
292 | if (err == EINTR) continue; | ||
293 | if (err != EAGAIN) return err; | ||
294 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; | ||
295 | } | ||
296 | return IO_UNKNOWN; | ||
297 | } | ||
298 | |||
299 | |||
300 | /*-------------------------------------------------------------------------*\ | ||
301 | * Write with timeout | ||
302 | * | ||
303 | * socket_read and socket_write are cut-n-paste of socket_send and socket_recv, | ||
304 | * with send/recv replaced with write/read. We can't just use write/read | ||
305 | * in the socket version, because behaviour when size is zero is different. | ||
306 | \*-------------------------------------------------------------------------*/ | ||
307 | int socket_write(p_socket ps, const char *data, size_t count, | ||
308 | size_t *sent, p_timeout tm) | ||
309 | { | ||
310 | int err; | ||
311 | *sent = 0; | ||
312 | /* avoid making system calls on closed sockets */ | ||
313 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
314 | /* loop until we send something or we give up on error */ | ||
315 | for ( ;; ) { | ||
316 | long put = (long) write(*ps, data, count); | ||
317 | /* if we sent anything, we are done */ | ||
318 | if (put >= 0) { | ||
319 | *sent = put; | ||
320 | return IO_DONE; | ||
321 | } | ||
322 | err = errno; | ||
323 | /* EPIPE means the connection was closed */ | ||
324 | if (err == EPIPE) return IO_CLOSED; | ||
325 | /* EPROTOTYPE means the connection is being closed (on Yosemite!)*/ | ||
326 | if (err == EPROTOTYPE) continue; | ||
327 | /* we call was interrupted, just try again */ | ||
328 | if (err == EINTR) continue; | ||
329 | /* if failed fatal reason, report error */ | ||
330 | if (err != EAGAIN) return err; | ||
331 | /* wait until we can send something or we timeout */ | ||
332 | if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; | ||
333 | } | ||
334 | /* can't reach here */ | ||
335 | return IO_UNKNOWN; | ||
336 | } | ||
337 | |||
338 | /*-------------------------------------------------------------------------*\ | ||
339 | * Read with timeout | ||
340 | * See note for socket_write | ||
341 | \*-------------------------------------------------------------------------*/ | ||
342 | int socket_read(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm) { | ||
343 | int err; | ||
344 | *got = 0; | ||
345 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
346 | for ( ;; ) { | ||
347 | long taken = (long) read(*ps, data, count); | ||
348 | if (taken > 0) { | ||
349 | *got = taken; | ||
350 | return IO_DONE; | ||
351 | } | ||
352 | err = errno; | ||
353 | if (taken == 0) return IO_CLOSED; | ||
354 | if (err == EINTR) continue; | ||
355 | if (err != EAGAIN) return err; | ||
356 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; | ||
357 | } | ||
358 | return IO_UNKNOWN; | ||
359 | } | ||
360 | |||
361 | /*-------------------------------------------------------------------------*\ | ||
362 | * Put socket into blocking mode | ||
363 | \*-------------------------------------------------------------------------*/ | ||
364 | void socket_setblocking(p_socket ps) { | ||
365 | int flags = fcntl(*ps, F_GETFL, 0); | ||
366 | flags &= (~(O_NONBLOCK)); | ||
367 | fcntl(*ps, F_SETFL, flags); | ||
368 | } | ||
369 | |||
370 | /*-------------------------------------------------------------------------*\ | ||
371 | * Put socket into non-blocking mode | ||
372 | \*-------------------------------------------------------------------------*/ | ||
373 | void socket_setnonblocking(p_socket ps) { | ||
374 | int flags = fcntl(*ps, F_GETFL, 0); | ||
375 | flags |= O_NONBLOCK; | ||
376 | fcntl(*ps, F_SETFL, flags); | ||
377 | } | ||
378 | |||
379 | /*-------------------------------------------------------------------------*\ | ||
380 | * DNS helpers | ||
381 | \*-------------------------------------------------------------------------*/ | ||
382 | int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) { | ||
383 | *hp = gethostbyaddr(addr, len, AF_INET); | ||
384 | if (*hp) return IO_DONE; | ||
385 | else if (h_errno) return h_errno; | ||
386 | else if (errno) return errno; | ||
387 | else return IO_UNKNOWN; | ||
388 | } | ||
389 | |||
390 | int socket_gethostbyname(const char *addr, struct hostent **hp) { | ||
391 | *hp = gethostbyname(addr); | ||
392 | if (*hp) return IO_DONE; | ||
393 | else if (h_errno) return h_errno; | ||
394 | else if (errno) return errno; | ||
395 | else return IO_UNKNOWN; | ||
396 | } | ||
397 | |||
398 | /*-------------------------------------------------------------------------*\ | ||
399 | * Error translation functions | ||
400 | * Make sure important error messages are standard | ||
401 | \*-------------------------------------------------------------------------*/ | ||
402 | const char *socket_hoststrerror(int err) { | ||
403 | if (err <= 0) return io_strerror(err); | ||
404 | switch (err) { | ||
405 | case HOST_NOT_FOUND: return PIE_HOST_NOT_FOUND; | ||
406 | default: return hstrerror(err); | ||
407 | } | ||
408 | } | ||
409 | |||
410 | const char *socket_strerror(int err) { | ||
411 | if (err <= 0) return io_strerror(err); | ||
412 | switch (err) { | ||
413 | case EADDRINUSE: return PIE_ADDRINUSE; | ||
414 | case EISCONN: return PIE_ISCONN; | ||
415 | case EACCES: return PIE_ACCESS; | ||
416 | case ECONNREFUSED: return PIE_CONNREFUSED; | ||
417 | case ECONNABORTED: return PIE_CONNABORTED; | ||
418 | case ECONNRESET: return PIE_CONNRESET; | ||
419 | case ETIMEDOUT: return PIE_TIMEDOUT; | ||
420 | default: { | ||
421 | return strerror(err); | ||
422 | } | ||
423 | } | ||
424 | } | ||
425 | |||
426 | const char *socket_ioerror(p_socket ps, int err) { | ||
427 | (void) ps; | ||
428 | return socket_strerror(err); | ||
429 | } | ||
430 | |||
431 | const char *socket_gaistrerror(int err) { | ||
432 | if (err == 0) return NULL; | ||
433 | switch (err) { | ||
434 | case EAI_AGAIN: return PIE_AGAIN; | ||
435 | case EAI_BADFLAGS: return PIE_BADFLAGS; | ||
436 | #ifdef EAI_BADHINTS | ||
437 | case EAI_BADHINTS: return PIE_BADHINTS; | ||
438 | #endif | ||
439 | case EAI_FAIL: return PIE_FAIL; | ||
440 | case EAI_FAMILY: return PIE_FAMILY; | ||
441 | case EAI_MEMORY: return PIE_MEMORY; | ||
442 | case EAI_NONAME: return PIE_NONAME; | ||
443 | #ifdef EAI_OVERFLOW | ||
444 | case EAI_OVERFLOW: return PIE_OVERFLOW; | ||
445 | #endif | ||
446 | #ifdef EAI_PROTOCOL | ||
447 | case EAI_PROTOCOL: return PIE_PROTOCOL; | ||
448 | #endif | ||
449 | case EAI_SERVICE: return PIE_SERVICE; | ||
450 | case EAI_SOCKTYPE: return PIE_SOCKTYPE; | ||
451 | case EAI_SYSTEM: return strerror(errno); | ||
452 | default: return LUA_GAI_STRERROR(err); | ||
453 | } | ||
454 | } | ||
diff --git a/vendor/luasocket/src/usocket.h b/vendor/luasocket/src/usocket.h new file mode 100644 index 00000000..45f2f99f --- /dev/null +++ b/vendor/luasocket/src/usocket.h | |||
@@ -0,0 +1,59 @@ | |||
1 | #ifndef USOCKET_H | ||
2 | #define USOCKET_H | ||
3 | /*=========================================================================*\ | ||
4 | * Socket compatibilization module for Unix | ||
5 | * LuaSocket toolkit | ||
6 | \*=========================================================================*/ | ||
7 | |||
8 | /*=========================================================================*\ | ||
9 | * BSD include files | ||
10 | \*=========================================================================*/ | ||
11 | /* error codes */ | ||
12 | #include <errno.h> | ||
13 | /* close function */ | ||
14 | #include <unistd.h> | ||
15 | /* fnctnl function and associated constants */ | ||
16 | #include <fcntl.h> | ||
17 | /* struct sockaddr */ | ||
18 | #include <sys/types.h> | ||
19 | /* socket function */ | ||
20 | #include <sys/socket.h> | ||
21 | /* struct timeval */ | ||
22 | #include <sys/time.h> | ||
23 | /* gethostbyname and gethostbyaddr functions */ | ||
24 | #include <netdb.h> | ||
25 | /* sigpipe handling */ | ||
26 | #include <signal.h> | ||
27 | /* IP stuff*/ | ||
28 | #include <netinet/in.h> | ||
29 | #include <arpa/inet.h> | ||
30 | /* TCP options (nagle algorithm disable) */ | ||
31 | #include <netinet/tcp.h> | ||
32 | #include <net/if.h> | ||
33 | |||
34 | #ifndef SO_REUSEPORT | ||
35 | #define SO_REUSEPORT SO_REUSEADDR | ||
36 | #endif | ||
37 | |||
38 | /* Some platforms use IPV6_JOIN_GROUP instead if | ||
39 | * IPV6_ADD_MEMBERSHIP. The semantics are same, though. */ | ||
40 | #ifndef IPV6_ADD_MEMBERSHIP | ||
41 | #ifdef IPV6_JOIN_GROUP | ||
42 | #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP | ||
43 | #endif /* IPV6_JOIN_GROUP */ | ||
44 | #endif /* !IPV6_ADD_MEMBERSHIP */ | ||
45 | |||
46 | /* Same with IPV6_DROP_MEMBERSHIP / IPV6_LEAVE_GROUP. */ | ||
47 | #ifndef IPV6_DROP_MEMBERSHIP | ||
48 | #ifdef IPV6_LEAVE_GROUP | ||
49 | #define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP | ||
50 | #endif /* IPV6_LEAVE_GROUP */ | ||
51 | #endif /* !IPV6_DROP_MEMBERSHIP */ | ||
52 | |||
53 | typedef int t_socket; | ||
54 | typedef t_socket *p_socket; | ||
55 | typedef struct sockaddr_storage t_sockaddr_storage; | ||
56 | |||
57 | #define SOCKET_INVALID (-1) | ||
58 | |||
59 | #endif /* USOCKET_H */ | ||
diff --git a/vendor/luasocket/src/wsocket.c b/vendor/luasocket/src/wsocket.c new file mode 100755 index 00000000..6cb1e415 --- /dev/null +++ b/vendor/luasocket/src/wsocket.c | |||
@@ -0,0 +1,434 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * Socket compatibilization module for Win32 | ||
3 | * LuaSocket toolkit | ||
4 | * | ||
5 | * The penalty of calling select to avoid busy-wait is only paid when | ||
6 | * the I/O call fail in the first place. | ||
7 | \*=========================================================================*/ | ||
8 | #include "luasocket.h" | ||
9 | |||
10 | #include <string.h> | ||
11 | |||
12 | #include "socket.h" | ||
13 | #include "pierror.h" | ||
14 | |||
15 | /* WinSock doesn't have a strerror... */ | ||
16 | static const char *wstrerror(int err); | ||
17 | |||
18 | /*-------------------------------------------------------------------------*\ | ||
19 | * Initializes module | ||
20 | \*-------------------------------------------------------------------------*/ | ||
21 | int socket_open(void) { | ||
22 | WSADATA wsaData; | ||
23 | WORD wVersionRequested = MAKEWORD(2, 0); | ||
24 | int err = WSAStartup(wVersionRequested, &wsaData ); | ||
25 | if (err != 0) return 0; | ||
26 | if ((LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) && | ||
27 | (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)) { | ||
28 | WSACleanup(); | ||
29 | return 0; | ||
30 | } | ||
31 | return 1; | ||
32 | } | ||
33 | |||
34 | /*-------------------------------------------------------------------------*\ | ||
35 | * Close module | ||
36 | \*-------------------------------------------------------------------------*/ | ||
37 | int socket_close(void) { | ||
38 | WSACleanup(); | ||
39 | return 1; | ||
40 | } | ||
41 | |||
42 | /*-------------------------------------------------------------------------*\ | ||
43 | * Wait for readable/writable/connected socket with timeout | ||
44 | \*-------------------------------------------------------------------------*/ | ||
45 | #define WAITFD_R 1 | ||
46 | #define WAITFD_W 2 | ||
47 | #define WAITFD_E 4 | ||
48 | #define WAITFD_C (WAITFD_E|WAITFD_W) | ||
49 | |||
50 | int socket_waitfd(p_socket ps, int sw, p_timeout tm) { | ||
51 | int ret; | ||
52 | fd_set rfds, wfds, efds, *rp = NULL, *wp = NULL, *ep = NULL; | ||
53 | struct timeval tv, *tp = NULL; | ||
54 | double t; | ||
55 | if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */ | ||
56 | if (sw & WAITFD_R) { | ||
57 | FD_ZERO(&rfds); | ||
58 | FD_SET(*ps, &rfds); | ||
59 | rp = &rfds; | ||
60 | } | ||
61 | if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; } | ||
62 | if (sw & WAITFD_C) { FD_ZERO(&efds); FD_SET(*ps, &efds); ep = &efds; } | ||
63 | if ((t = timeout_get(tm)) >= 0.0) { | ||
64 | tv.tv_sec = (int) t; | ||
65 | tv.tv_usec = (int) ((t-tv.tv_sec)*1.0e6); | ||
66 | tp = &tv; | ||
67 | } | ||
68 | ret = select(0, rp, wp, ep, tp); | ||
69 | if (ret == -1) return WSAGetLastError(); | ||
70 | if (ret == 0) return IO_TIMEOUT; | ||
71 | if (sw == WAITFD_C && FD_ISSET(*ps, &efds)) return IO_CLOSED; | ||
72 | return IO_DONE; | ||
73 | } | ||
74 | |||
75 | /*-------------------------------------------------------------------------*\ | ||
76 | * Select with int timeout in ms | ||
77 | \*-------------------------------------------------------------------------*/ | ||
78 | int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, | ||
79 | p_timeout tm) { | ||
80 | struct timeval tv; | ||
81 | double t = timeout_get(tm); | ||
82 | tv.tv_sec = (int) t; | ||
83 | tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6); | ||
84 | if (n <= 0) { | ||
85 | Sleep((DWORD) (1000*t)); | ||
86 | return 0; | ||
87 | } else return select(0, rfds, wfds, efds, t >= 0.0? &tv: NULL); | ||
88 | } | ||
89 | |||
90 | /*-------------------------------------------------------------------------*\ | ||
91 | * Close and inutilize socket | ||
92 | \*-------------------------------------------------------------------------*/ | ||
93 | void socket_destroy(p_socket ps) { | ||
94 | if (*ps != SOCKET_INVALID) { | ||
95 | socket_setblocking(ps); /* close can take a long time on WIN32 */ | ||
96 | closesocket(*ps); | ||
97 | *ps = SOCKET_INVALID; | ||
98 | } | ||
99 | } | ||
100 | |||
101 | /*-------------------------------------------------------------------------*\ | ||
102 | * | ||
103 | \*-------------------------------------------------------------------------*/ | ||
104 | void socket_shutdown(p_socket ps, int how) { | ||
105 | socket_setblocking(ps); | ||
106 | shutdown(*ps, how); | ||
107 | socket_setnonblocking(ps); | ||
108 | } | ||
109 | |||
110 | /*-------------------------------------------------------------------------*\ | ||
111 | * Creates and sets up a socket | ||
112 | \*-------------------------------------------------------------------------*/ | ||
113 | int socket_create(p_socket ps, int domain, int type, int protocol) { | ||
114 | *ps = socket(domain, type, protocol); | ||
115 | if (*ps != SOCKET_INVALID) return IO_DONE; | ||
116 | else return WSAGetLastError(); | ||
117 | } | ||
118 | |||
119 | /*-------------------------------------------------------------------------*\ | ||
120 | * Connects or returns error message | ||
121 | \*-------------------------------------------------------------------------*/ | ||
122 | int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) { | ||
123 | int err; | ||
124 | /* don't call on closed socket */ | ||
125 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
126 | /* ask system to connect */ | ||
127 | if (connect(*ps, addr, len) == 0) return IO_DONE; | ||
128 | /* make sure the system is trying to connect */ | ||
129 | err = WSAGetLastError(); | ||
130 | if (err != WSAEWOULDBLOCK && err != WSAEINPROGRESS) return err; | ||
131 | /* zero timeout case optimization */ | ||
132 | if (timeout_iszero(tm)) return IO_TIMEOUT; | ||
133 | /* we wait until something happens */ | ||
134 | err = socket_waitfd(ps, WAITFD_C, tm); | ||
135 | if (err == IO_CLOSED) { | ||
136 | int elen = sizeof(err); | ||
137 | /* give windows time to set the error (yes, disgusting) */ | ||
138 | Sleep(10); | ||
139 | /* find out why we failed */ | ||
140 | getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &elen); | ||
141 | /* we KNOW there was an error. if 'why' is 0, we will return | ||
142 | * "unknown error", but it's not really our fault */ | ||
143 | return err > 0? err: IO_UNKNOWN; | ||
144 | } else return err; | ||
145 | |||
146 | } | ||
147 | |||
148 | /*-------------------------------------------------------------------------*\ | ||
149 | * Binds or returns error message | ||
150 | \*-------------------------------------------------------------------------*/ | ||
151 | int socket_bind(p_socket ps, SA *addr, socklen_t len) { | ||
152 | int err = IO_DONE; | ||
153 | socket_setblocking(ps); | ||
154 | if (bind(*ps, addr, len) < 0) err = WSAGetLastError(); | ||
155 | socket_setnonblocking(ps); | ||
156 | return err; | ||
157 | } | ||
158 | |||
159 | /*-------------------------------------------------------------------------*\ | ||
160 | * | ||
161 | \*-------------------------------------------------------------------------*/ | ||
162 | int socket_listen(p_socket ps, int backlog) { | ||
163 | int err = IO_DONE; | ||
164 | socket_setblocking(ps); | ||
165 | if (listen(*ps, backlog) < 0) err = WSAGetLastError(); | ||
166 | socket_setnonblocking(ps); | ||
167 | return err; | ||
168 | } | ||
169 | |||
170 | /*-------------------------------------------------------------------------*\ | ||
171 | * Accept with timeout | ||
172 | \*-------------------------------------------------------------------------*/ | ||
173 | int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, | ||
174 | p_timeout tm) { | ||
175 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
176 | for ( ;; ) { | ||
177 | int err; | ||
178 | /* try to get client socket */ | ||
179 | if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID) return IO_DONE; | ||
180 | /* find out why we failed */ | ||
181 | err = WSAGetLastError(); | ||
182 | /* if we failed because there was no connectoin, keep trying */ | ||
183 | if (err != WSAEWOULDBLOCK && err != WSAECONNABORTED) return err; | ||
184 | /* call select to avoid busy wait */ | ||
185 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; | ||
186 | } | ||
187 | } | ||
188 | |||
189 | /*-------------------------------------------------------------------------*\ | ||
190 | * Send with timeout | ||
191 | * On windows, if you try to send 10MB, the OS will buffer EVERYTHING | ||
192 | * this can take an awful lot of time and we will end up blocked. | ||
193 | * Therefore, whoever calls this function should not pass a huge buffer. | ||
194 | \*-------------------------------------------------------------------------*/ | ||
195 | int socket_send(p_socket ps, const char *data, size_t count, | ||
196 | size_t *sent, p_timeout tm) | ||
197 | { | ||
198 | int err; | ||
199 | *sent = 0; | ||
200 | /* avoid making system calls on closed sockets */ | ||
201 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
202 | /* loop until we send something or we give up on error */ | ||
203 | for ( ;; ) { | ||
204 | /* try to send something */ | ||
205 | int put = send(*ps, data, (int) count, 0); | ||
206 | /* if we sent something, we are done */ | ||
207 | if (put > 0) { | ||
208 | *sent = put; | ||
209 | return IO_DONE; | ||
210 | } | ||
211 | /* deal with failure */ | ||
212 | err = WSAGetLastError(); | ||
213 | /* we can only proceed if there was no serious error */ | ||
214 | if (err != WSAEWOULDBLOCK) return err; | ||
215 | /* avoid busy wait */ | ||
216 | if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; | ||
217 | } | ||
218 | } | ||
219 | |||
220 | /*-------------------------------------------------------------------------*\ | ||
221 | * Sendto with timeout | ||
222 | \*-------------------------------------------------------------------------*/ | ||
223 | int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, | ||
224 | SA *addr, socklen_t len, p_timeout tm) | ||
225 | { | ||
226 | int err; | ||
227 | *sent = 0; | ||
228 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
229 | for ( ;; ) { | ||
230 | int put = sendto(*ps, data, (int) count, 0, addr, len); | ||
231 | if (put > 0) { | ||
232 | *sent = put; | ||
233 | return IO_DONE; | ||
234 | } | ||
235 | err = WSAGetLastError(); | ||
236 | if (err != WSAEWOULDBLOCK) return err; | ||
237 | if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; | ||
238 | } | ||
239 | } | ||
240 | |||
241 | /*-------------------------------------------------------------------------*\ | ||
242 | * Receive with timeout | ||
243 | \*-------------------------------------------------------------------------*/ | ||
244 | int socket_recv(p_socket ps, char *data, size_t count, size_t *got, | ||
245 | p_timeout tm) | ||
246 | { | ||
247 | int err, prev = IO_DONE; | ||
248 | *got = 0; | ||
249 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
250 | for ( ;; ) { | ||
251 | int taken = recv(*ps, data, (int) count, 0); | ||
252 | if (taken > 0) { | ||
253 | *got = taken; | ||
254 | return IO_DONE; | ||
255 | } | ||
256 | if (taken == 0) return IO_CLOSED; | ||
257 | err = WSAGetLastError(); | ||
258 | /* On UDP, a connreset simply means the previous send failed. | ||
259 | * So we try again. | ||
260 | * On TCP, it means our socket is now useless, so the error passes. | ||
261 | * (We will loop again, exiting because the same error will happen) */ | ||
262 | if (err != WSAEWOULDBLOCK) { | ||
263 | if (err != WSAECONNRESET || prev == WSAECONNRESET) return err; | ||
264 | prev = err; | ||
265 | } | ||
266 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; | ||
267 | } | ||
268 | } | ||
269 | |||
270 | /*-------------------------------------------------------------------------*\ | ||
271 | * Recvfrom with timeout | ||
272 | \*-------------------------------------------------------------------------*/ | ||
273 | int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, | ||
274 | SA *addr, socklen_t *len, p_timeout tm) | ||
275 | { | ||
276 | int err, prev = IO_DONE; | ||
277 | *got = 0; | ||
278 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
279 | for ( ;; ) { | ||
280 | int taken = recvfrom(*ps, data, (int) count, 0, addr, len); | ||
281 | if (taken > 0) { | ||
282 | *got = taken; | ||
283 | return IO_DONE; | ||
284 | } | ||
285 | if (taken == 0) return IO_CLOSED; | ||
286 | err = WSAGetLastError(); | ||
287 | /* On UDP, a connreset simply means the previous send failed. | ||
288 | * So we try again. | ||
289 | * On TCP, it means our socket is now useless, so the error passes. | ||
290 | * (We will loop again, exiting because the same error will happen) */ | ||
291 | if (err != WSAEWOULDBLOCK) { | ||
292 | if (err != WSAECONNRESET || prev == WSAECONNRESET) return err; | ||
293 | prev = err; | ||
294 | } | ||
295 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; | ||
296 | } | ||
297 | } | ||
298 | |||
299 | /*-------------------------------------------------------------------------*\ | ||
300 | * Put socket into blocking mode | ||
301 | \*-------------------------------------------------------------------------*/ | ||
302 | void socket_setblocking(p_socket ps) { | ||
303 | u_long argp = 0; | ||
304 | ioctlsocket(*ps, FIONBIO, &argp); | ||
305 | } | ||
306 | |||
307 | /*-------------------------------------------------------------------------*\ | ||
308 | * Put socket into non-blocking mode | ||
309 | \*-------------------------------------------------------------------------*/ | ||
310 | void socket_setnonblocking(p_socket ps) { | ||
311 | u_long argp = 1; | ||
312 | ioctlsocket(*ps, FIONBIO, &argp); | ||
313 | } | ||
314 | |||
315 | /*-------------------------------------------------------------------------*\ | ||
316 | * DNS helpers | ||
317 | \*-------------------------------------------------------------------------*/ | ||
318 | int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) { | ||
319 | *hp = gethostbyaddr(addr, len, AF_INET); | ||
320 | if (*hp) return IO_DONE; | ||
321 | else return WSAGetLastError(); | ||
322 | } | ||
323 | |||
324 | int socket_gethostbyname(const char *addr, struct hostent **hp) { | ||
325 | *hp = gethostbyname(addr); | ||
326 | if (*hp) return IO_DONE; | ||
327 | else return WSAGetLastError(); | ||
328 | } | ||
329 | |||
330 | /*-------------------------------------------------------------------------*\ | ||
331 | * Error translation functions | ||
332 | \*-------------------------------------------------------------------------*/ | ||
333 | const char *socket_hoststrerror(int err) { | ||
334 | if (err <= 0) return io_strerror(err); | ||
335 | switch (err) { | ||
336 | case WSAHOST_NOT_FOUND: return PIE_HOST_NOT_FOUND; | ||
337 | default: return wstrerror(err); | ||
338 | } | ||
339 | } | ||
340 | |||
341 | const char *socket_strerror(int err) { | ||
342 | if (err <= 0) return io_strerror(err); | ||
343 | switch (err) { | ||
344 | case WSAEADDRINUSE: return PIE_ADDRINUSE; | ||
345 | case WSAECONNREFUSED : return PIE_CONNREFUSED; | ||
346 | case WSAEISCONN: return PIE_ISCONN; | ||
347 | case WSAEACCES: return PIE_ACCESS; | ||
348 | case WSAECONNABORTED: return PIE_CONNABORTED; | ||
349 | case WSAECONNRESET: return PIE_CONNRESET; | ||
350 | case WSAETIMEDOUT: return PIE_TIMEDOUT; | ||
351 | default: return wstrerror(err); | ||
352 | } | ||
353 | } | ||
354 | |||
355 | const char *socket_ioerror(p_socket ps, int err) { | ||
356 | (void) ps; | ||
357 | return socket_strerror(err); | ||
358 | } | ||
359 | |||
360 | static const char *wstrerror(int err) { | ||
361 | switch (err) { | ||
362 | case WSAEINTR: return "Interrupted function call"; | ||
363 | case WSAEACCES: return PIE_ACCESS; /* "Permission denied"; */ | ||
364 | case WSAEFAULT: return "Bad address"; | ||
365 | case WSAEINVAL: return "Invalid argument"; | ||
366 | case WSAEMFILE: return "Too many open files"; | ||
367 | case WSAEWOULDBLOCK: return "Resource temporarily unavailable"; | ||
368 | case WSAEINPROGRESS: return "Operation now in progress"; | ||
369 | case WSAEALREADY: return "Operation already in progress"; | ||
370 | case WSAENOTSOCK: return "Socket operation on nonsocket"; | ||
371 | case WSAEDESTADDRREQ: return "Destination address required"; | ||
372 | case WSAEMSGSIZE: return "Message too long"; | ||
373 | case WSAEPROTOTYPE: return "Protocol wrong type for socket"; | ||
374 | case WSAENOPROTOOPT: return "Bad protocol option"; | ||
375 | case WSAEPROTONOSUPPORT: return "Protocol not supported"; | ||
376 | case WSAESOCKTNOSUPPORT: return PIE_SOCKTYPE; /* "Socket type not supported"; */ | ||
377 | case WSAEOPNOTSUPP: return "Operation not supported"; | ||
378 | case WSAEPFNOSUPPORT: return "Protocol family not supported"; | ||
379 | case WSAEAFNOSUPPORT: return PIE_FAMILY; /* "Address family not supported by protocol family"; */ | ||
380 | case WSAEADDRINUSE: return PIE_ADDRINUSE; /* "Address already in use"; */ | ||
381 | case WSAEADDRNOTAVAIL: return "Cannot assign requested address"; | ||
382 | case WSAENETDOWN: return "Network is down"; | ||
383 | case WSAENETUNREACH: return "Network is unreachable"; | ||
384 | case WSAENETRESET: return "Network dropped connection on reset"; | ||
385 | case WSAECONNABORTED: return "Software caused connection abort"; | ||
386 | case WSAECONNRESET: return PIE_CONNRESET; /* "Connection reset by peer"; */ | ||
387 | case WSAENOBUFS: return "No buffer space available"; | ||
388 | case WSAEISCONN: return PIE_ISCONN; /* "Socket is already connected"; */ | ||
389 | case WSAENOTCONN: return "Socket is not connected"; | ||
390 | case WSAESHUTDOWN: return "Cannot send after socket shutdown"; | ||
391 | case WSAETIMEDOUT: return PIE_TIMEDOUT; /* "Connection timed out"; */ | ||
392 | case WSAECONNREFUSED: return PIE_CONNREFUSED; /* "Connection refused"; */ | ||
393 | case WSAEHOSTDOWN: return "Host is down"; | ||
394 | case WSAEHOSTUNREACH: return "No route to host"; | ||
395 | case WSAEPROCLIM: return "Too many processes"; | ||
396 | case WSASYSNOTREADY: return "Network subsystem is unavailable"; | ||
397 | case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range"; | ||
398 | case WSANOTINITIALISED: | ||
399 | return "Successful WSAStartup not yet performed"; | ||
400 | case WSAEDISCON: return "Graceful shutdown in progress"; | ||
401 | case WSAHOST_NOT_FOUND: return PIE_HOST_NOT_FOUND; /* "Host not found"; */ | ||
402 | case WSATRY_AGAIN: return "Nonauthoritative host not found"; | ||
403 | case WSANO_RECOVERY: return PIE_FAIL; /* "Nonrecoverable name lookup error"; */ | ||
404 | case WSANO_DATA: return "Valid name, no data record of requested type"; | ||
405 | default: return "Unknown error"; | ||
406 | } | ||
407 | } | ||
408 | |||
409 | const char *socket_gaistrerror(int err) { | ||
410 | if (err == 0) return NULL; | ||
411 | switch (err) { | ||
412 | case EAI_AGAIN: return PIE_AGAIN; | ||
413 | case EAI_BADFLAGS: return PIE_BADFLAGS; | ||
414 | #ifdef EAI_BADHINTS | ||
415 | case EAI_BADHINTS: return PIE_BADHINTS; | ||
416 | #endif | ||
417 | case EAI_FAIL: return PIE_FAIL; | ||
418 | case EAI_FAMILY: return PIE_FAMILY; | ||
419 | case EAI_MEMORY: return PIE_MEMORY; | ||
420 | case EAI_NONAME: return PIE_NONAME; | ||
421 | #ifdef EAI_OVERFLOW | ||
422 | case EAI_OVERFLOW: return PIE_OVERFLOW; | ||
423 | #endif | ||
424 | #ifdef EAI_PROTOCOL | ||
425 | case EAI_PROTOCOL: return PIE_PROTOCOL; | ||
426 | #endif | ||
427 | case EAI_SERVICE: return PIE_SERVICE; | ||
428 | case EAI_SOCKTYPE: return PIE_SOCKTYPE; | ||
429 | #ifdef EAI_SYSTEM | ||
430 | case EAI_SYSTEM: return strerror(errno); | ||
431 | #endif | ||
432 | default: return LUA_GAI_STRERROR(err); | ||
433 | } | ||
434 | } | ||
diff --git a/vendor/luasocket/src/wsocket.h b/vendor/luasocket/src/wsocket.h new file mode 100644 index 00000000..39866402 --- /dev/null +++ b/vendor/luasocket/src/wsocket.h | |||
@@ -0,0 +1,33 @@ | |||
1 | #ifndef WSOCKET_H | ||
2 | #define WSOCKET_H | ||
3 | /*=========================================================================*\ | ||
4 | * Socket compatibilization module for Win32 | ||
5 | * LuaSocket toolkit | ||
6 | \*=========================================================================*/ | ||
7 | |||
8 | /*=========================================================================*\ | ||
9 | * WinSock include files | ||
10 | \*=========================================================================*/ | ||
11 | #include <winsock2.h> | ||
12 | #include <ws2tcpip.h> | ||
13 | |||
14 | typedef int socklen_t; | ||
15 | typedef SOCKADDR_STORAGE t_sockaddr_storage; | ||
16 | typedef SOCKET t_socket; | ||
17 | typedef t_socket *p_socket; | ||
18 | |||
19 | #ifndef IPV6_V6ONLY | ||
20 | #define IPV6_V6ONLY 27 | ||
21 | #endif | ||
22 | |||
23 | #define SOCKET_INVALID (INVALID_SOCKET) | ||
24 | |||
25 | #ifndef SO_REUSEPORT | ||
26 | #define SO_REUSEPORT SO_REUSEADDR | ||
27 | #endif | ||
28 | |||
29 | #ifndef AI_NUMERICSERV | ||
30 | #define AI_NUMERICSERV (0) | ||
31 | #endif | ||
32 | |||
33 | #endif /* WSOCKET_H */ | ||
diff --git a/vendor/md5/.gitignore b/vendor/md5/.gitignore new file mode 100644 index 00000000..9776091d --- /dev/null +++ b/vendor/md5/.gitignore | |||
@@ -0,0 +1,4 @@ | |||
1 | *.o | ||
2 | *.obj | ||
3 | *.so | ||
4 | *.dll | ||
diff --git a/vendor/md5/README.md b/vendor/md5/README.md new file mode 100644 index 00000000..d51492e0 --- /dev/null +++ b/vendor/md5/README.md | |||
@@ -0,0 +1,47 @@ | |||
1 | # MD5 - Cryptographic Library for Lua | ||
2 | |||
3 | http://keplerproject.github.io/md5/ | ||
4 | |||
5 | MD5 offers basic cryptographic facilities for Lua 5.1: a hash (digest) | ||
6 | function, a pair crypt/decrypt based on MD5 and CFB, and a pair crypt/decrypt based | ||
7 | on DES with 56-bit keys. | ||
8 | |||
9 | MD5 current version is 1.2. | ||
10 | |||
11 | Please check the documentation at /doc/us/ for more information. | ||
12 | |||
13 | ## Installation | ||
14 | |||
15 | To install using [LuaRocks](https://github.com/keplerproject/luarocks) run: | ||
16 | |||
17 | ``` | ||
18 | luarocks install md5 | ||
19 | ``` | ||
20 | |||
21 | To install on Linux/OSX/BSD, please edit the config file and then call | ||
22 | |||
23 | ``` | ||
24 | make | ||
25 | make install | ||
26 | ``` | ||
27 | |||
28 | The last step may require root privileges. | ||
29 | |||
30 | ## History | ||
31 | |||
32 | Version 1.2 [06/Sep/2013] | ||
33 | |||
34 | * Code adapted to compile for Lua 5.0, 5.1 and 5.2 | ||
35 | |||
36 | Version 1.1.2 [12/May/2008] | ||
37 | |||
38 | * Fixed bug in 64-bit systems | ||
39 | * Fixed the Windows makefile to accept longer directory names | ||
40 | (patch by Alessandro Hecht and Ignacio Burgueño). | ||
41 | |||
42 | |||
43 | ## License | ||
44 | |||
45 | MD5 is free software and uses the same license as Lua (MIT). | ||
46 | |||
47 | The DES 56 C library was implemented by Stuart Levy and uses a MIT license too (check the source). | ||
diff --git a/vendor/md5/rockspec/md5-1.2-1.rockspec b/vendor/md5/rockspec/md5-1.2-1.rockspec new file mode 100644 index 00000000..04f61ce4 --- /dev/null +++ b/vendor/md5/rockspec/md5-1.2-1.rockspec | |||
@@ -0,0 +1,35 @@ | |||
1 | package = "MD5" | ||
2 | version = "1.2-1" | ||
3 | source = { | ||
4 | url = "https://github.com/keplerproject/md5/archive/v1.2.tar.gz", | ||
5 | md5 = "c166f8a983401802a86655a8c733441e", | ||
6 | dir = "md5-1.2", | ||
7 | } | ||
8 | description = { | ||
9 | summary = "Basic cryptographic library", | ||
10 | detailed = [[ | ||
11 | MD5 offers basic cryptographic facilities for Lua 5.X: | ||
12 | a hash (digest) function, a pair crypt/decrypt based on MD5 and CFB, | ||
13 | and a pair crypt/decrypt based on DES with 56-bit keys. | ||
14 | ]], | ||
15 | license = "MIT/X11", | ||
16 | homepage = "http://www.keplerproject.org/md5/", | ||
17 | } | ||
18 | dependencies = { | ||
19 | "lua >= 5.0" | ||
20 | } | ||
21 | build = { | ||
22 | type = "builtin", | ||
23 | modules = { | ||
24 | md5 = "src/md5.lua", | ||
25 | ["md5.core"] = { | ||
26 | sources = { "src/compat-5.2.c", "src/md5.c", "src/md5lib.c", }, | ||
27 | incdirs = { "src/", }, | ||
28 | }, | ||
29 | des56 = { | ||
30 | sources = { "src/compat-5.2.c", "src/des56.c", "src/ldes56.c", }, | ||
31 | incdirs = { "src/", }, | ||
32 | }, | ||
33 | }, | ||
34 | copy_directories = { "doc", "tests", }, | ||
35 | } | ||
diff --git a/vendor/md5/src/compat-5.2.c b/vendor/md5/src/compat-5.2.c new file mode 100644 index 00000000..ce57660b --- /dev/null +++ b/vendor/md5/src/compat-5.2.c | |||
@@ -0,0 +1,21 @@ | |||
1 | #include "lua.h" | ||
2 | #include "lauxlib.h" | ||
3 | #include "compat-5.2.h" | ||
4 | |||
5 | #if !defined LUA_VERSION_NUM || LUA_VERSION_NUM==501 | ||
6 | /* | ||
7 | ** Adapted from Lua 5.2.0 | ||
8 | */ | ||
9 | void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { | ||
10 | luaL_checkstack(L, nup+1, "too many upvalues"); | ||
11 | for (; l->name != NULL; l++) { /* fill the table with given functions */ | ||
12 | int i; | ||
13 | lua_pushstring(L, l->name); | ||
14 | for (i = 0; i < nup; i++) /* copy upvalues to the top */ | ||
15 | lua_pushvalue(L, -(nup + 1)); | ||
16 | lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ | ||
17 | lua_settable(L, -(nup + 3)); /* table must be below the upvalues, the name and the closure */ | ||
18 | } | ||
19 | lua_pop(L, nup); /* remove upvalues */ | ||
20 | } | ||
21 | #endif | ||
diff --git a/vendor/md5/src/compat-5.2.h b/vendor/md5/src/compat-5.2.h new file mode 100644 index 00000000..c80fd616 --- /dev/null +++ b/vendor/md5/src/compat-5.2.h | |||
@@ -0,0 +1,15 @@ | |||
1 | #if !defined LUA_VERSION_NUM | ||
2 | /* Lua 5.0 */ | ||
3 | #define luaL_Reg luaL_reg | ||
4 | |||
5 | #define luaL_addchar(B,c) \ | ||
6 | ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ | ||
7 | (*(B)->p++ = (char)(c))) | ||
8 | #endif | ||
9 | |||
10 | #if LUA_VERSION_NUM==501 | ||
11 | /* Lua 5.1 */ | ||
12 | #define lua_rawlen lua_objlen | ||
13 | #endif | ||
14 | |||
15 | void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup); | ||
diff --git a/vendor/md5/src/des56.c b/vendor/md5/src/des56.c new file mode 100755 index 00000000..1fb377b9 --- /dev/null +++ b/vendor/md5/src/des56.c | |||
@@ -0,0 +1,548 @@ | |||
1 | |||
2 | /* | ||
3 | * Fast implementation of the DES, as described in the Federal Register, | ||
4 | * Vol. 40, No. 52, p. 12134, March 17, 1975. | ||
5 | * | ||
6 | * Stuart Levy, Minnesota Supercomputer Center, April 1988. | ||
7 | * Currently (2007) slevy@ncsa.uiuc.edu | ||
8 | * NCSA, University of Illinois Urbana-Champaign | ||
9 | * | ||
10 | * Calling sequence: | ||
11 | * | ||
12 | * typedef unsigned long keysched[32]; | ||
13 | * | ||
14 | * fsetkey(key, keysched) / * Converts a DES key to a "key schedule" * / | ||
15 | * unsigned char key[8]; | ||
16 | * keysched *ks; | ||
17 | * | ||
18 | * fencrypt(block, decrypt, keysched) / * En/decrypts one 64-bit block * / | ||
19 | * unsigned char block[8]; / * data, en/decrypted in place * / | ||
20 | * int decrypt; / * 0=>encrypt, 1=>decrypt * / | ||
21 | * keysched *ks; / * key schedule, as set by fsetkey * / | ||
22 | * | ||
23 | * Key and data block representation: | ||
24 | * The 56-bit key (bits 1..64 including "parity" bits 8, 16, 24, ..., 64) | ||
25 | * and the 64-bit data block (bits 1..64) | ||
26 | * are each stored in arrays of 8 bytes. | ||
27 | * Following the NBS numbering, the MSB has the bit number 1, so | ||
28 | * key[0] = 128*bit1 + 64*bit2 + ... + 1*bit8, ... through | ||
29 | * key[7] = 128*bit57 + 64*bit58 + ... + 1*bit64. | ||
30 | * In the key, "parity" bits are not checked; their values are ignored. | ||
31 | * | ||
32 | */ | ||
33 | |||
34 | /* | ||
35 | =============================================================================== | ||
36 | License | ||
37 | |||
38 | des56.c is licensed under the terms of the MIT license reproduced below. | ||
39 | This means that des56.c is free software and can be used for both academic | ||
40 | and commercial purposes at absolutely no cost. | ||
41 | =============================================================================== | ||
42 | Copyright (C) 1988 Stuart Levy | ||
43 | |||
44 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
45 | of this software and associated documentation files (the "Software"), to deal | ||
46 | in the Software without restriction, including without limitation the rights | ||
47 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
48 | copies of the Software, and to permit persons to whom the Software is | ||
49 | furnished to do so, subject to the following conditions: | ||
50 | |||
51 | The above copyright notice and this permission notice shall be included in | ||
52 | all copies or substantial portions of the Software. | ||
53 | |||
54 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
55 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
56 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
57 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
58 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
59 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
60 | THE SOFTWARE. | ||
61 | */ | ||
62 | |||
63 | |||
64 | #include "des56.h" | ||
65 | |||
66 | |||
67 | /* | ||
68 | * Key schedule generation. | ||
69 | * We begin by pointlessly permuting the 56 useful key bits into | ||
70 | * two groups of 28 bits called C and D. | ||
71 | * bK_C and bK_D are indexed by C and D bit numbers, respectively, | ||
72 | * and give the key bit number (1..64) which should initialize that C/D bit. | ||
73 | * This is the "permuted choice 1" table. | ||
74 | */ | ||
75 | |||
76 | static tiny bK_C[28] = { | ||
77 | 57, 49, 41, 33, 25, 17, 9, | ||
78 | 1, 58, 50, 42, 34, 26, 18, | ||
79 | 10, 2, 59, 51, 43, 35, 27, | ||
80 | 19, 11, 3, 60, 52, 44, 36, | ||
81 | }; | ||
82 | static tiny bK_D[28] = { | ||
83 | 63, 55, 47, 39, 31, 23, 15, | ||
84 | 7, 62, 54, 46, 38, 30, 22, | ||
85 | 14, 6, 61, 53, 45, 37, 29, | ||
86 | 21, 13, 5, 28, 20, 12, 4, | ||
87 | }; | ||
88 | |||
89 | /* | ||
90 | * For speed, we invert these, building tables to map groups of | ||
91 | * key bits into the corresponding C and D bits. | ||
92 | * We represent C and D each as 28 contiguous bits right-justified in a | ||
93 | * word, padded on the left with zeros. | ||
94 | * If key byte `i' is said to contain bits Ki,0 (MSB) Ki,1 ... Ki,7 (LSB) | ||
95 | * then | ||
96 | * wC_K4[i][Ki,0 Ki,1 Ki,2 Ki,3] gives the C bits for Ki,0..3, | ||
97 | * wD_K4[i][Ki,0 Ki,1 Ki,2 Ki,3] the corresponding D bits, | ||
98 | * wC_K3[i][Ki,4 Ki,5 Ki,6] the C bits for Ki,4..6, | ||
99 | * and wD_K3[i][Ki,4 Ki,5 Ki,6] the D bits for Ki,4..6. | ||
100 | * Ki,7 is ignored since it is the nominal parity bit. | ||
101 | * We could just use a single table for [i][Ki,0 .. Ki,6] but that | ||
102 | * would take a lot of storage for such a rarely-used function. | ||
103 | */ | ||
104 | |||
105 | static word32 wC_K4[8][16], wC_K3[8][8]; | ||
106 | static word32 wD_K4[8][16], wD_K3[8][8]; | ||
107 | |||
108 | /* | ||
109 | * Successive Ci and Di for the sixteen steps in the key schedule are | ||
110 | * created by independent 28-bit left circular shifts on C and D. | ||
111 | * The shift count varies with the step number. | ||
112 | */ | ||
113 | static tiny preshift[16] = { | ||
114 | 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, | ||
115 | }; | ||
116 | |||
117 | /* | ||
118 | * Each step in the key schedule is generated by selecting 48 bits | ||
119 | * (8 groups of 6 bits) from the appropriately shifted Ci and Di. | ||
120 | * bCD_KS, indexed by the key schedule bit number, gives the bit number | ||
121 | * in CD (CD1 = MSB of C, CD28 = LSB of C, CD29 = MSB of D, CD56 = LSB of D) | ||
122 | * which determines that bit of the key schedule. | ||
123 | * Note that only C bits (1..28) appear in the first (upper) 24 bits of | ||
124 | * the key schedule, and D bits (29..56) in the second (lower) 24 bits. | ||
125 | * This is the "permuted-choice-2" table. | ||
126 | */ | ||
127 | |||
128 | static tiny bCD_KS[48] = { | ||
129 | 14, 17, 11, 24, 1, 5, | ||
130 | 3, 28, 15, 6, 21, 10, | ||
131 | 23, 19, 12, 4, 26, 8, | ||
132 | 16, 7, 27, 20, 13, 2, | ||
133 | 41, 52, 31, 37, 47, 55, | ||
134 | 30, 40, 51, 45, 33, 48, | ||
135 | 44, 49, 39, 56, 34, 53, | ||
136 | 46, 42, 50, 36, 29, 32, | ||
137 | }; | ||
138 | |||
139 | /* | ||
140 | * We invert bCD_KS into a pair of tables which map groups of 4 | ||
141 | * C or D bits into corresponding key schedule bits. | ||
142 | * We represent each step of the key schedule as 8 groups of 8 bits, | ||
143 | * with the 6 real bits right-justified in each 8-bit group. | ||
144 | * hKS_C4[i][C4i+1 .. C4i+4] gives the bits in the high order (first four) | ||
145 | * key schedule "bytes" which correspond to C bits 4i+1 .. 4i+4. | ||
146 | * lKS_D4[i][D4i+1 .. D4i+4] gives the appropriate bits in the latter (last 4) | ||
147 | * key schedule bytes, from the corresponding D bits. | ||
148 | */ | ||
149 | |||
150 | static word32 hKS_C4[7][16]; | ||
151 | static word32 lKS_D4[7][16]; | ||
152 | |||
153 | /* | ||
154 | * Encryption/decryption. | ||
155 | * Before beginning, and after ending, we perform another useless permutation | ||
156 | * on the bits in the data block. | ||
157 | * | ||
158 | * The initial permutation and its inverse, final permutation | ||
159 | * are too simple to need a table for. If we break the input I1 .. I64 into | ||
160 | * 8-bit chunks I0,0 I0,1 ... I0,7 I1,0 I1,1 ... I7,7 | ||
161 | * then the initial permutation sets LR as follows: | ||
162 | * L = I7,1 I6,1 I5,1 ... I0,1 I7,3 I6,3 ... I0,3 I7,5 ... I0,5 I7,7 ... I0,7 | ||
163 | * and | ||
164 | * R = I7,0 I6,0 I5,0 ... I0,0 I7,2 I6,2 ... I0,2 I7,4 ... I0,4 I7,6 ... I0,6 | ||
165 | * | ||
166 | * If we number the bits in the final LR similarly, | ||
167 | * L = L0,0 L0,1 ... L3,7 R = R0,0 R0,1 ... R3,7 | ||
168 | * then the output is | ||
169 | * O = R0,7 L0,7 R1,7 L1,7 ... R3,7 L3,7 R0,6 L0,6 ... L3,6 R0,5 ... R3,0 L3,0 | ||
170 | * | ||
171 | * To speed I => LR shuffling we use an array of 32-bit values indexed by | ||
172 | * 8-bit input bytes. | ||
173 | * wL_I8[ 0 I0,1 0 I0,3 0 I0,5 0 I0,7 ] = the corresponding L bits. | ||
174 | * Other R and L bits are derived from wL_I8 by shifting. | ||
175 | * | ||
176 | * To speed LR => O shuffling, an array of 32-bit values indexed by 4-bit lumps: | ||
177 | * wO_L4[ L0,4 L0,5 L0,6 L0,7 ] = the corresponding high-order 32 O bits. | ||
178 | */ | ||
179 | |||
180 | static word32 wL_I8[0x55 + 1]; | ||
181 | static word32 wO_L4[16]; | ||
182 | |||
183 | /* | ||
184 | * Core of encryption/decryption. | ||
185 | * In each key schedule stage, we: | ||
186 | * take 8 overlapping groups of 6 bits each from R | ||
187 | * (the NBS tabulates the bit selections in the E table, | ||
188 | * but it's so simple we just use shifting to get the right bits) | ||
189 | * XOR each group with the corresponding bits from the key schedule | ||
190 | * Use the resulting 6 bits as an index into the appropriate S table | ||
191 | * (there are 8 such tables, one per group of 6 bits) | ||
192 | * Each S entry yields 4 bits. | ||
193 | * The 8 groups of 4 bits are catenated into a 32-bit value. | ||
194 | * Those 32 bits are permuted according to the P table. | ||
195 | * Finally the permuted 32-bit value is XORed with L and becomes | ||
196 | * the R value for the next stage, while the previous R becomes the new L. | ||
197 | * | ||
198 | * Here, we merge the P permutation with the S tables by making the | ||
199 | * S entries be 32-bit masks, already suitably permuted. | ||
200 | * Also, the bits in each six-bit group must be permuted before use as | ||
201 | * an index into the NBS-tabulated S tables. | ||
202 | * We rearrange entries in wPS so that natural bit order can be used. | ||
203 | */ | ||
204 | |||
205 | static word32 wPS[8][64]; | ||
206 | |||
207 | static tiny P[32] = { | ||
208 | 16, 7, 20, 21, | ||
209 | 29, 12, 28, 17, | ||
210 | 1, 15, 23, 26, | ||
211 | 5, 18, 31, 10, | ||
212 | 2, 8, 24, 14, | ||
213 | 32, 27, 3, 9, | ||
214 | 19, 13, 30, 6, | ||
215 | 22, 11, 4, 25, | ||
216 | }; | ||
217 | |||
218 | static tiny S[8][64] = { | ||
219 | { | ||
220 | 14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7, | ||
221 | 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8, | ||
222 | 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0, | ||
223 | 15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13, | ||
224 | }, | ||
225 | |||
226 | { | ||
227 | 15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10, | ||
228 | 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5, | ||
229 | 0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15, | ||
230 | 13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9, | ||
231 | }, | ||
232 | |||
233 | { | ||
234 | 10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8, | ||
235 | 13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1, | ||
236 | 13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7, | ||
237 | 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12, | ||
238 | }, | ||
239 | |||
240 | { | ||
241 | 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15, | ||
242 | 13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9, | ||
243 | 10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4, | ||
244 | 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14, | ||
245 | }, | ||
246 | |||
247 | { | ||
248 | 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9, | ||
249 | 14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6, | ||
250 | 4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14, | ||
251 | 11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3, | ||
252 | }, | ||
253 | |||
254 | { | ||
255 | 12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11, | ||
256 | 10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8, | ||
257 | 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6, | ||
258 | 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13, | ||
259 | }, | ||
260 | |||
261 | { | ||
262 | 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1, | ||
263 | 13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6, | ||
264 | 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2, | ||
265 | 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12, | ||
266 | }, | ||
267 | |||
268 | { | ||
269 | 13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7, | ||
270 | 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2, | ||
271 | 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8, | ||
272 | 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11, | ||
273 | }, | ||
274 | }; | ||
275 | |||
276 | static void buildtables( void ) | ||
277 | { | ||
278 | register int i, j; | ||
279 | register word32 v; | ||
280 | word32 wC_K[64], wD_K[64]; | ||
281 | word32 hKS_C[28], lKS_D[28]; | ||
282 | int Smap[64]; | ||
283 | word32 wP[32]; | ||
284 | |||
285 | #if USG | ||
286 | # define ZERO(array) memset((char *)(array), '\0', sizeof(array)) | ||
287 | #else | ||
288 | # if BSD | ||
289 | # define ZERO(array) bzero((char *)(array), sizeof(array)) | ||
290 | # else | ||
291 | # define ZERO(array) { register word32 *p = (word32 *)(array); \ | ||
292 | i = sizeof(array) / sizeof(*p); \ | ||
293 | do { *p++ = 0; } while(--i > 0); \ | ||
294 | } | ||
295 | # endif | ||
296 | #endif | ||
297 | |||
298 | |||
299 | /* Invert permuted-choice-1 (key => C,D) */ | ||
300 | |||
301 | ZERO(wC_K); | ||
302 | ZERO(wD_K); | ||
303 | v = 1; | ||
304 | for(j = 28; --j >= 0; ) { | ||
305 | wC_K[ bK_C[j] - 1 ] = wD_K[ bK_D[j] - 1 ] = v; | ||
306 | v += v; /* (i.e. v <<= 1) */ | ||
307 | } | ||
308 | |||
309 | for(i = 0; i < 64; i++) { | ||
310 | int t = 8 >> (i & 3); | ||
311 | for(j = 0; j < 16; j++) { | ||
312 | if(j & t) { | ||
313 | wC_K4[i >> 3][j] |= wC_K[i]; | ||
314 | wD_K4[i >> 3][j] |= wD_K[i]; | ||
315 | if(j < 8) { | ||
316 | wC_K3[i >> 3][j] |= wC_K[i + 3]; | ||
317 | wD_K3[i >> 3][j] |= wD_K[i + 3]; | ||
318 | } | ||
319 | } | ||
320 | } | ||
321 | /* Generate the sequence 0,1,2,3, 8,9,10,11, ..., 56,57,58,59. */ | ||
322 | if(t == 1) i += 4; | ||
323 | } | ||
324 | |||
325 | /* Invert permuted-choice-2 */ | ||
326 | |||
327 | ZERO(hKS_C); | ||
328 | ZERO(lKS_D); | ||
329 | v = 1; | ||
330 | for(i = 24; (i -= 6) >= 0; ) { | ||
331 | j = i+5; | ||
332 | do { | ||
333 | hKS_C[ bCD_KS[j] - 1 ] = lKS_D[ bCD_KS[j+24] - 28 - 1 ] = v; | ||
334 | v += v; /* Like v <<= 1 but may be faster */ | ||
335 | } while(--j >= i); | ||
336 | v <<= 2; /* Keep byte aligned */ | ||
337 | } | ||
338 | |||
339 | for(i = 0; i < 28; i++) { | ||
340 | v = 8 >> (i & 3); | ||
341 | for(j = 0; j < 16; j++) { | ||
342 | if(j & v) { | ||
343 | hKS_C4[i >> 2][j] |= hKS_C[i]; | ||
344 | lKS_D4[i >> 2][j] |= lKS_D[i]; | ||
345 | } | ||
346 | } | ||
347 | } | ||
348 | |||
349 | /* Initial permutation */ | ||
350 | |||
351 | for(i = 0; i <= 0x55; i++) { | ||
352 | v = 0; | ||
353 | if(i & 64) v = (word32) 1 << 24; | ||
354 | if(i & 16) v |= (word32) 1 << 16; | ||
355 | if(i & 4) v |= (word32) 1 << 8; | ||
356 | if(i & 1) v |= 1; | ||
357 | wL_I8[i] = v; | ||
358 | } | ||
359 | |||
360 | /* Final permutation */ | ||
361 | |||
362 | for(i = 0; i < 16; i++) { | ||
363 | v = 0; | ||
364 | if(i & 1) v = (word32) 1 << 24; | ||
365 | if(i & 2) v |= (word32) 1 << 16; | ||
366 | if(i & 4) v |= (word32) 1 << 8; | ||
367 | if(i & 8) v |= (word32) 1; | ||
368 | wO_L4[i] = v; | ||
369 | } | ||
370 | |||
371 | /* Funny bit rearrangement on second index into S tables */ | ||
372 | |||
373 | for(i = 0; i < 64; i++) { | ||
374 | Smap[i] = (i & 0x20) | (i & 1) << 4 | (i & 0x1e) >> 1; | ||
375 | } | ||
376 | |||
377 | /* Invert permutation P into mask indexed by R bit number */ | ||
378 | |||
379 | v = 1; | ||
380 | for(i = 32; --i >= 0; ) { | ||
381 | wP[ P[i] - 1 ] = v; | ||
382 | v += v; | ||
383 | } | ||
384 | |||
385 | /* Build bit-mask versions of S tables, indexed in natural bit order */ | ||
386 | |||
387 | for(i = 0; i < 8; i++) { | ||
388 | for(j = 0; j < 64; j++) { | ||
389 | int k, t; | ||
390 | |||
391 | t = S[i][ Smap[j] ]; | ||
392 | for(k = 0; k < 4; k++) { | ||
393 | if(t & 8) | ||
394 | wPS[i][j] |= wP[4*i + k]; | ||
395 | t += t; | ||
396 | } | ||
397 | } | ||
398 | } | ||
399 | } | ||
400 | |||
401 | |||
402 | void fsetkey(char key[8], keysched *ks) | ||
403 | { | ||
404 | register int i; | ||
405 | register word32 C, D; | ||
406 | static int built = 0; | ||
407 | |||
408 | if(!built) { | ||
409 | buildtables(); | ||
410 | built = 1; | ||
411 | } | ||
412 | |||
413 | C = D = 0; | ||
414 | for(i = 0; i < 8; i++) { | ||
415 | register int v; | ||
416 | |||
417 | v = key[i] >> 1; /* Discard "parity" bit */ | ||
418 | C |= wC_K4[i][(v>>3) & 15] | wC_K3[i][v & 7]; | ||
419 | D |= wD_K4[i][(v>>3) & 15] | wD_K3[i][v & 7]; | ||
420 | } | ||
421 | |||
422 | /* | ||
423 | * C and D now hold the suitably right-justified | ||
424 | * 28 permuted key bits each. | ||
425 | */ | ||
426 | for(i = 0; i < 16; i++) { | ||
427 | #ifdef CRAY | ||
428 | #define choice2(x, v) x[6][v&15] | x[5][(v>>4)&15] | x[4][(v>>8)&15] | \ | ||
429 | x[3][(v>>12)&15] | x[2][(v>>16)&15] | x[1][(v>>20)&15] | \ | ||
430 | x[0][(v>>24)&15] | ||
431 | #else | ||
432 | register word32 *ap; | ||
433 | |||
434 | # define choice2(x, v) ( \ | ||
435 | ap = &(x)[0][0], \ | ||
436 | ap[16*6 + (v&15)] | \ | ||
437 | ap[16*5 + ((v>>4)&15)] | ap[16*4 + ((v>>8)&15)] | \ | ||
438 | ap[16*3 + ((v>>12)&15)] | ap[16*2 + ((v>>16)&15)] | \ | ||
439 | ap[16*1 + ((v>>20)&15)] | ap[16*0 + ((v>>24)&15)] ) | ||
440 | #endif | ||
441 | |||
442 | |||
443 | /* 28-bit left circular shift */ | ||
444 | C <<= preshift[i]; | ||
445 | C = ((C >> 28) & 3) | (C & (((word32)1<<28) - 1)); | ||
446 | ks->KS[i].h = choice2(hKS_C4, C); | ||
447 | |||
448 | D <<= preshift[i]; | ||
449 | D = ((D >> 28) & 3) | (D & (((word32)1<<28) - 1)); | ||
450 | ks->KS[i].l = choice2(lKS_D4, D); | ||
451 | } | ||
452 | } | ||
453 | |||
454 | void | ||
455 | fencrypt(char block[8], int decrypt, keysched *ks) | ||
456 | { | ||
457 | int i; | ||
458 | register word32 L, R; | ||
459 | register struct keystage *ksp; | ||
460 | register word32 *ap; | ||
461 | |||
462 | /* Initial permutation */ | ||
463 | |||
464 | L = R = 0; | ||
465 | i = 7; | ||
466 | ap = wL_I8; | ||
467 | do { | ||
468 | register int v; | ||
469 | |||
470 | v = block[i]; /* Could optimize according to ENDIAN */ | ||
471 | L = ap[v & 0x55] | (L << 1); | ||
472 | R = ap[(v >> 1) & 0x55] | (R << 1); | ||
473 | } while(--i >= 0); | ||
474 | |||
475 | if(decrypt) { | ||
476 | ksp = &ks->KS[15]; | ||
477 | } else { | ||
478 | ksp = &ks->KS[0]; | ||
479 | } | ||
480 | |||
481 | #ifdef CRAY | ||
482 | # define PS(i,j) wPS[i][j] | ||
483 | #else | ||
484 | # define PS(i,j) ap[64*(i) + (j)] | ||
485 | ap = &wPS[0][0]; | ||
486 | #endif | ||
487 | |||
488 | i = 16; | ||
489 | do { | ||
490 | register word32 k, tR; | ||
491 | |||
492 | tR = (R >> 15) | (R << 17); | ||
493 | |||
494 | k = ksp->h; | ||
495 | L ^= PS(0, ((tR >> 12) ^ (k >> 24)) & 63) | ||
496 | | PS(1, ((tR >> 8) ^ (k >> 16)) & 63) | ||
497 | | PS(2, ((tR >> 4) ^ (k >> 8)) & 63) | ||
498 | | PS(3, (tR ^ k) & 63); | ||
499 | |||
500 | k = ksp->l; | ||
501 | L ^= PS(4, ((R >> 11) ^ (k >> 24)) & 63) | ||
502 | | PS(5, ((R >> 7) ^ (k >> 16)) & 63) | ||
503 | | PS(6, ((R >> 3) ^ (k >> 8)) & 63) | ||
504 | | PS(7, ((tR >> 16) ^ k) & 63); | ||
505 | |||
506 | tR = L; | ||
507 | L = R; | ||
508 | R = tR; | ||
509 | |||
510 | |||
511 | if(decrypt) | ||
512 | ksp--; | ||
513 | else | ||
514 | ksp++; | ||
515 | } while(--i > 0); | ||
516 | { | ||
517 | register word32 t; | ||
518 | |||
519 | #ifdef CRAY | ||
520 | # define FP(k) (wO_L4[ (L >> (k)) & 15 ] << 1 | wO_L4[ (R >> (k)) & 15 ]) | ||
521 | #else | ||
522 | # define FP(k) (ap[ (L >> (k)) & 15 ] << 1 | ap[ (R >> (k)) & 15 ]) | ||
523 | |||
524 | ap = wO_L4; | ||
525 | #endif | ||
526 | |||
527 | t = FP(0) | (FP(8) | (FP(16) | (FP(24) << 2)) << 2) << 2; | ||
528 | R = FP(4) | (FP(12) | (FP(20) | (FP(28) << 2)) << 2) << 2; | ||
529 | L = t; | ||
530 | } | ||
531 | { | ||
532 | register word32 t; | ||
533 | register char *bp; | ||
534 | |||
535 | bp = &block[7]; | ||
536 | t = R; | ||
537 | *bp = t & 255; | ||
538 | *--bp = (t >>= 8) & 255; | ||
539 | *--bp = (t >>= 8) & 255; | ||
540 | *--bp = (t >> 8) & 255; | ||
541 | t = L; | ||
542 | *--bp = t & 255; | ||
543 | *--bp = (t >>= 8) & 255; | ||
544 | *--bp = (t >>= 8) & 255; | ||
545 | *--bp = (t >> 8) & 255; | ||
546 | } | ||
547 | } | ||
548 | |||
diff --git a/vendor/md5/src/des56.def b/vendor/md5/src/des56.def new file mode 100644 index 00000000..c0493a73 --- /dev/null +++ b/vendor/md5/src/des56.def | |||
@@ -0,0 +1,5 @@ | |||
1 | LIBRARY des56.dll | ||
2 | DESCRIPTION "DES56" | ||
3 | VERSION 1.3 | ||
4 | EXPORTS | ||
5 | luaopen_des56 | ||
diff --git a/vendor/md5/src/des56.h b/vendor/md5/src/des56.h new file mode 100755 index 00000000..88e5f137 --- /dev/null +++ b/vendor/md5/src/des56.h | |||
@@ -0,0 +1,77 @@ | |||
1 | #ifndef DES56_H | ||
2 | #define DES56_H 1 | ||
3 | /* | ||
4 | * Fast implementation of the DES, as described in the Federal Register, | ||
5 | * Vol. 40, No. 52, p. 12134, March 17, 1975. | ||
6 | * | ||
7 | * Stuart Levy, Minnesota Supercomputer Center, April 1988. | ||
8 | * Currently (2007) slevy@ncsa.uiuc.edu | ||
9 | * NCSA, University of Illinois Urbana-Champaign | ||
10 | * | ||
11 | * Calling sequence: | ||
12 | * | ||
13 | * typedef unsigned long keysched[32]; | ||
14 | * | ||
15 | * fsetkey(key, keysched) / * Converts a DES key to a "key schedule" * / | ||
16 | * unsigned char key[8]; | ||
17 | * keysched *ks; | ||
18 | * | ||
19 | * fencrypt(block, decrypt, keysched) / * En/decrypts one 64-bit block * / | ||
20 | * unsigned char block[8]; / * data, en/decrypted in place * / | ||
21 | * int decrypt; / * 0=>encrypt, 1=>decrypt * / | ||
22 | * keysched *ks; / * key schedule, as set by fsetkey * / | ||
23 | * | ||
24 | * Key and data block representation: | ||
25 | * The 56-bit key (bits 1..64 including "parity" bits 8, 16, 24, ..., 64) | ||
26 | * and the 64-bit data block (bits 1..64) | ||
27 | * are each stored in arrays of 8 bytes. | ||
28 | * Following the NBS numbering, the MSB has the bit number 1, so | ||
29 | * key[0] = 128*bit1 + 64*bit2 + ... + 1*bit8, ... through | ||
30 | * key[7] = 128*bit57 + 64*bit58 + ... + 1*bit64. | ||
31 | * In the key, "parity" bits are not checked; their values are ignored. | ||
32 | * | ||
33 | */ | ||
34 | |||
35 | /* | ||
36 | =============================================================================== | ||
37 | License | ||
38 | |||
39 | des56.c is licensed under the terms of the MIT license reproduced below. | ||
40 | This means that des56.c is free software and can be used for both academic | ||
41 | and commercial purposes at absolutely no cost. | ||
42 | =============================================================================== | ||
43 | Copyright (C) 1988 Stuart Levy | ||
44 | |||
45 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
46 | of this software and associated documentation files (the "Software"), to deal | ||
47 | in the Software without restriction, including without limitation the rights | ||
48 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
49 | copies of the Software, and to permit persons to whom the Software is | ||
50 | furnished to do so, subject to the following conditions: | ||
51 | |||
52 | The above copyright notice and this permission notice shall be included in | ||
53 | all copies or substantial portions of the Software. | ||
54 | |||
55 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
56 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
57 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
58 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
59 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
60 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
61 | THE SOFTWARE. | ||
62 | */ | ||
63 | |||
64 | typedef unsigned long word32; | ||
65 | typedef unsigned char tiny; | ||
66 | |||
67 | typedef struct keysched { | ||
68 | struct keystage { | ||
69 | word32 h, l; | ||
70 | } KS[16]; | ||
71 | } keysched; | ||
72 | |||
73 | extern void fsetkey(char key[8], keysched *ks); | ||
74 | |||
75 | extern void fencrypt(char block[8], int decrypt, keysched *ks); | ||
76 | |||
77 | #endif /*DES56_H*/ | ||
diff --git a/vendor/md5/src/ldes56.c b/vendor/md5/src/ldes56.c new file mode 100644 index 00000000..8c29ec1d --- /dev/null +++ b/vendor/md5/src/ldes56.c | |||
@@ -0,0 +1,152 @@ | |||
1 | #include <stdlib.h> | ||
2 | #include <string.h> | ||
3 | |||
4 | #include "des56.h" | ||
5 | |||
6 | #include "lua.h" | ||
7 | #include "lauxlib.h" | ||
8 | |||
9 | #include "compat-5.2.h" | ||
10 | #include "ldes56.h" | ||
11 | |||
12 | static int des56_decrypt( lua_State *L ) | ||
13 | { | ||
14 | char* decypheredText; | ||
15 | keysched KS; | ||
16 | int rel_index, abs_index; | ||
17 | size_t cypherlen; | ||
18 | const char *cypheredText = | ||
19 | luaL_checklstring( L, 1, &cypherlen ); | ||
20 | const char *key = luaL_optstring( L, 2, NULL ); | ||
21 | int padinfo; | ||
22 | |||
23 | padinfo = cypheredText[cypherlen-1]; | ||
24 | cypherlen--; | ||
25 | |||
26 | /* Aloca array */ | ||
27 | decypheredText = | ||
28 | (char *) malloc( (cypherlen+1) * sizeof(char)); | ||
29 | if(decypheredText == NULL) { | ||
30 | lua_pushstring(L, "Error decrypting file. Not enough memory."); | ||
31 | lua_error(L); | ||
32 | } | ||
33 | |||
34 | /* Inicia decifragem */ | ||
35 | if (key && strlen(key) >= 8) | ||
36 | { | ||
37 | char k[8]; | ||
38 | int i; | ||
39 | |||
40 | for (i=0; i<8; i++) | ||
41 | k[i] = (unsigned char)key[i]; | ||
42 | fsetkey(k, &KS); | ||
43 | } else { | ||
44 | lua_pushstring(L, "Error decrypting file. Invalid key."); | ||
45 | lua_error(L); | ||
46 | } | ||
47 | |||
48 | rel_index = 0; | ||
49 | abs_index = 0; | ||
50 | |||
51 | while (abs_index < (int) cypherlen) | ||
52 | { | ||
53 | decypheredText[abs_index] = cypheredText[abs_index]; | ||
54 | abs_index++; | ||
55 | rel_index++; | ||
56 | if( rel_index == 8 ) | ||
57 | { | ||
58 | rel_index = 0; | ||
59 | fencrypt(&(decypheredText[abs_index - 8]), 1, &KS); | ||
60 | } | ||
61 | } | ||
62 | decypheredText[abs_index] = 0; | ||
63 | |||
64 | lua_pushlstring(L, decypheredText, (abs_index-padinfo)); | ||
65 | free( decypheredText ); | ||
66 | return 1; | ||
67 | } | ||
68 | |||
69 | static int des56_crypt( lua_State *L ) | ||
70 | { | ||
71 | char *cypheredText; | ||
72 | keysched KS; | ||
73 | int rel_index, pad, abs_index; | ||
74 | size_t plainlen; | ||
75 | const char *plainText = luaL_checklstring( L, 1, &plainlen ); | ||
76 | const char *key = luaL_optstring( L, 2, NULL ); | ||
77 | |||
78 | cypheredText = (char *) malloc( (plainlen+8) * sizeof(char)); | ||
79 | if(cypheredText == NULL) { | ||
80 | lua_pushstring(L, "Error encrypting file. Not enough memory."); | ||
81 | lua_error(L); | ||
82 | } | ||
83 | |||
84 | if (key && strlen(key) >= 8) | ||
85 | { | ||
86 | char k[8]; | ||
87 | int i; | ||
88 | |||
89 | for (i=0; i<8; i++) | ||
90 | k[i] = (unsigned char)key[i]; | ||
91 | fsetkey(k, &KS); | ||
92 | } else { | ||
93 | lua_pushstring(L, "Error encrypting file. Invalid key."); | ||
94 | lua_error(L); | ||
95 | } | ||
96 | |||
97 | rel_index = 0; | ||
98 | abs_index = 0; | ||
99 | while (abs_index < (int) plainlen) { | ||
100 | cypheredText[abs_index] = plainText[abs_index]; | ||
101 | abs_index++; | ||
102 | rel_index++; | ||
103 | if( rel_index == 8 ) { | ||
104 | rel_index = 0; | ||
105 | fencrypt(&(cypheredText[abs_index - 8]), 0, &KS); | ||
106 | } | ||
107 | } | ||
108 | |||
109 | pad = 0; | ||
110 | if(rel_index != 0) { /* Pads remaining bytes with zeroes */ | ||
111 | while(rel_index < 8) | ||
112 | { | ||
113 | pad++; | ||
114 | cypheredText[abs_index++] = 0; | ||
115 | rel_index++; | ||
116 | } | ||
117 | fencrypt(&(cypheredText[abs_index - 8]), 0, &KS); | ||
118 | } | ||
119 | cypheredText[abs_index] = pad; | ||
120 | |||
121 | lua_pushlstring( L, cypheredText, abs_index+1 ); | ||
122 | free( cypheredText ); | ||
123 | return 1; | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | ** Assumes the table is on top of the stack. | ||
128 | */ | ||
129 | static void set_info (lua_State *L) { | ||
130 | lua_pushliteral (L, "_COPYRIGHT"); | ||
131 | lua_pushliteral (L, "Copyright (C) 2007-2019 PUC-Rio"); | ||
132 | lua_settable (L, -3); | ||
133 | lua_pushliteral (L, "_DESCRIPTION"); | ||
134 | lua_pushliteral (L, "DES 56 cryptographic facilities for Lua"); | ||
135 | lua_settable (L, -3); | ||
136 | lua_pushliteral (L, "_VERSION"); | ||
137 | lua_pushliteral (L, "DES56 1.3"); | ||
138 | lua_settable (L, -3); | ||
139 | } | ||
140 | |||
141 | static const struct luaL_Reg des56lib[] = { | ||
142 | {"crypt", des56_crypt}, | ||
143 | {"decrypt", des56_decrypt}, | ||
144 | {NULL, NULL}, | ||
145 | }; | ||
146 | |||
147 | int luaopen_des56 (lua_State *L) { | ||
148 | lua_newtable(L); | ||
149 | luaL_setfuncs(L, des56lib, 0); | ||
150 | set_info (L); | ||
151 | return 1; | ||
152 | } | ||
diff --git a/vendor/md5/src/ldes56.h b/vendor/md5/src/ldes56.h new file mode 100755 index 00000000..8c2e86a8 --- /dev/null +++ b/vendor/md5/src/ldes56.h | |||
@@ -0,0 +1 @@ | |||
int luaopen_des56 (lua_State *L); | |||
diff --git a/vendor/md5/src/md5.c b/vendor/md5/src/md5.c new file mode 100755 index 00000000..f35c8e14 --- /dev/null +++ b/vendor/md5/src/md5.c | |||
@@ -0,0 +1,262 @@ | |||
1 | /** | ||
2 | * $Id: md5.c,v 1.2 2008/03/24 20:59:12 mascarenhas Exp $ | ||
3 | * Hash function MD5 | ||
4 | * @author Marcela Ozorio Suarez, Roberto I. | ||
5 | */ | ||
6 | |||
7 | |||
8 | #include <stdio.h> | ||
9 | #include <stdlib.h> | ||
10 | #include <string.h> | ||
11 | #include <time.h> | ||
12 | |||
13 | #include "md5.h" | ||
14 | |||
15 | |||
16 | #define WORD 32 | ||
17 | #define MASK 0xFFFFFFFF | ||
18 | |||
19 | |||
20 | /** | ||
21 | * md5 hash function. | ||
22 | * @param message: aribtary string. | ||
23 | * @param len: message length. | ||
24 | * @param output: buffer to receive the hash value. Its size must be | ||
25 | * (at least) HASHSIZE. | ||
26 | */ | ||
27 | void md5 (const char *message, size_t len, char output[HASHSIZE]); | ||
28 | |||
29 | /** | ||
30 | * init a new md5 calculate context | ||
31 | * @param m a uninitialized md5_t type context | ||
32 | */ | ||
33 | void md5_init (md5_t *m); | ||
34 | |||
35 | /** | ||
36 | * update message to md5 context | ||
37 | * @param m a initialized md5_t type context | ||
38 | * @param message aribtary string | ||
39 | * @param len message length | ||
40 | * @return true if update completed, means len is not the multiples of 64. | ||
41 | * false if you can continue update. | ||
42 | */ | ||
43 | int md5_update (md5_t *m, const char *message, size_t len); | ||
44 | |||
45 | /** | ||
46 | * finish md5 calculate. | ||
47 | * @param m a md5_type context which previous md5_update on it return true. | ||
48 | * @param output buffer to receive the hash value. its size must be | ||
49 | * (at least) HASHSIZE. | ||
50 | */ | ||
51 | void md5_finish (md5_t *m, char output[HASHSIZE]); | ||
52 | |||
53 | /* | ||
54 | ** Realiza a rotacao no sentido horario dos bits da variavel 'D' do tipo WORD32. | ||
55 | ** Os bits sao deslocados de 'num' posicoes | ||
56 | */ | ||
57 | #define rotate(D, num) (D<<num) | (D>>(WORD-num)) | ||
58 | |||
59 | /*Macros que definem operacoes relizadas pelo algoritmo md5 */ | ||
60 | #define F(x, y, z) (((x) & (y)) | ((~(x)) & (z))) | ||
61 | #define G(x, y, z) (((x) & (z)) | ((y) & (~(z)))) | ||
62 | #define H(x, y, z) ((x) ^ (y) ^ (z)) | ||
63 | #define I(x, y, z) ((y) ^ ((x) | (~(z)))) | ||
64 | |||
65 | |||
66 | /*vetor de numeros utilizados pelo algoritmo md5 para embaralhar bits */ | ||
67 | static const WORD32 T[64]={ | ||
68 | 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, | ||
69 | 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, | ||
70 | 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, | ||
71 | 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, | ||
72 | 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, | ||
73 | 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, | ||
74 | 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, | ||
75 | 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, | ||
76 | 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, | ||
77 | 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, | ||
78 | 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, | ||
79 | 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, | ||
80 | 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, | ||
81 | 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, | ||
82 | 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, | ||
83 | 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 | ||
84 | }; | ||
85 | |||
86 | |||
87 | static void word32tobytes (const WORD32 *input, char *output) { | ||
88 | int j = 0; | ||
89 | while (j<4*4) { | ||
90 | WORD32 v = *input++; | ||
91 | output[j++] = (char)(v & 0xff); v >>= 8; | ||
92 | output[j++] = (char)(v & 0xff); v >>= 8; | ||
93 | output[j++] = (char)(v & 0xff); v >>= 8; | ||
94 | output[j++] = (char)(v & 0xff); | ||
95 | } | ||
96 | } | ||
97 | |||
98 | |||
99 | static void inic_digest(WORD32 *d) { | ||
100 | d[0] = 0x67452301; | ||
101 | d[1] = 0xEFCDAB89; | ||
102 | d[2] = 0x98BADCFE; | ||
103 | d[3] = 0x10325476; | ||
104 | } | ||
105 | |||
106 | |||
107 | /*funcao que implemeta os quatro passos principais do algoritmo MD5 */ | ||
108 | static void digest(const WORD32 *m, WORD32 *d) { | ||
109 | int j; | ||
110 | /*MD5 PASSO1 */ | ||
111 | for (j=0; j<4*4; j+=4) { | ||
112 | d[0] = d[0]+ F(d[1], d[2], d[3])+ m[j] + T[j]; d[0]=rotate(d[0], 7); | ||
113 | d[0]+=d[1]; | ||
114 | d[3] = d[3]+ F(d[0], d[1], d[2])+ m[(j)+1] + T[j+1]; d[3]=rotate(d[3], 12); | ||
115 | d[3]+=d[0]; | ||
116 | d[2] = d[2]+ F(d[3], d[0], d[1])+ m[(j)+2] + T[j+2]; d[2]=rotate(d[2], 17); | ||
117 | d[2]+=d[3]; | ||
118 | d[1] = d[1]+ F(d[2], d[3], d[0])+ m[(j)+3] + T[j+3]; d[1]=rotate(d[1], 22); | ||
119 | d[1]+=d[2]; | ||
120 | } | ||
121 | /*MD5 PASSO2 */ | ||
122 | for (j=0; j<4*4; j+=4) { | ||
123 | d[0] = d[0]+ G(d[1], d[2], d[3])+ m[(5*j+1)&0x0f] + T[(j-1)+17]; | ||
124 | d[0] = rotate(d[0],5); | ||
125 | d[0]+=d[1]; | ||
126 | d[3] = d[3]+ G(d[0], d[1], d[2])+ m[((5*(j+1)+1)&0x0f)] + T[(j+0)+17]; | ||
127 | d[3] = rotate(d[3], 9); | ||
128 | d[3]+=d[0]; | ||
129 | d[2] = d[2]+ G(d[3], d[0], d[1])+ m[((5*(j+2)+1)&0x0f)] + T[(j+1)+17]; | ||
130 | d[2] = rotate(d[2], 14); | ||
131 | d[2]+=d[3]; | ||
132 | d[1] = d[1]+ G(d[2], d[3], d[0])+ m[((5*(j+3)+1)&0x0f)] + T[(j+2)+17]; | ||
133 | d[1] = rotate(d[1], 20); | ||
134 | d[1]+=d[2]; | ||
135 | } | ||
136 | /*MD5 PASSO3 */ | ||
137 | for (j=0; j<4*4; j+=4) { | ||
138 | d[0] = d[0]+ H(d[1], d[2], d[3])+ m[(3*j+5)&0x0f] + T[(j-1)+33]; | ||
139 | d[0] = rotate(d[0], 4); | ||
140 | d[0]+=d[1]; | ||
141 | d[3] = d[3]+ H(d[0], d[1], d[2])+ m[(3*(j+1)+5)&0x0f] + T[(j+0)+33]; | ||
142 | d[3] = rotate(d[3], 11); | ||
143 | d[3]+=d[0]; | ||
144 | d[2] = d[2]+ H(d[3], d[0], d[1])+ m[(3*(j+2)+5)&0x0f] + T[(j+1)+33]; | ||
145 | d[2] = rotate(d[2], 16); | ||
146 | d[2]+=d[3]; | ||
147 | d[1] = d[1]+ H(d[2], d[3], d[0])+ m[(3*(j+3)+5)&0x0f] + T[(j+2)+33]; | ||
148 | d[1] = rotate(d[1], 23); | ||
149 | d[1]+=d[2]; | ||
150 | } | ||
151 | /*MD5 PASSO4 */ | ||
152 | for (j=0; j<4*4; j+=4) { | ||
153 | d[0] = d[0]+ I(d[1], d[2], d[3])+ m[(7*j)&0x0f] + T[(j-1)+49]; | ||
154 | d[0] = rotate(d[0], 6); | ||
155 | d[0]+=d[1]; | ||
156 | d[3] = d[3]+ I(d[0], d[1], d[2])+ m[(7*(j+1))&0x0f] + T[(j+0)+49]; | ||
157 | d[3] = rotate(d[3], 10); | ||
158 | d[3]+=d[0]; | ||
159 | d[2] = d[2]+ I(d[3], d[0], d[1])+ m[(7*(j+2))&0x0f] + T[(j+1)+49]; | ||
160 | d[2] = rotate(d[2], 15); | ||
161 | d[2]+=d[3]; | ||
162 | d[1] = d[1]+ I(d[2], d[3], d[0])+ m[(7*(j+3))&0x0f] + T[(j+2)+49]; | ||
163 | d[1] = rotate(d[1], 21); | ||
164 | d[1]+=d[2]; | ||
165 | } | ||
166 | } | ||
167 | |||
168 | |||
169 | static void bytestoword32 (WORD32 *x, const char *pt) { | ||
170 | int i; | ||
171 | for (i=0; i<16; i++) { | ||
172 | int j=i*4; | ||
173 | x[i] = (((WORD32)(unsigned char)pt[j+3] << 8 | | ||
174 | (WORD32)(unsigned char)pt[j+2]) << 8 | | ||
175 | (WORD32)(unsigned char)pt[j+1]) << 8 | | ||
176 | (WORD32)(unsigned char)pt[j]; | ||
177 | } | ||
178 | |||
179 | } | ||
180 | |||
181 | |||
182 | static void put_length(WORD32 *x, long len) { | ||
183 | /* in bits! */ | ||
184 | x[14] = (WORD32)((len<<3) & MASK); | ||
185 | x[15] = (WORD32)(len>>(32-3) & 0x7); | ||
186 | } | ||
187 | |||
188 | |||
189 | /* | ||
190 | ** returned status: | ||
191 | * 0 - normal message (full 64 bytes) | ||
192 | * 1 - enough room for 0x80, but not for message length (two 4-byte words) | ||
193 | * 2 - enough room for 0x80 plus message length (at least 9 bytes free) | ||
194 | */ | ||
195 | static int converte (WORD32 *x, const char *pt, int num, int old_status) { | ||
196 | int new_status = 0; | ||
197 | char buff[64]; | ||
198 | if (num<64) { | ||
199 | memcpy(buff, pt, num); /* to avoid changing original string */ | ||
200 | memset(buff+num, 0, 64-num); | ||
201 | if (old_status == 0) | ||
202 | buff[num] = '\200'; | ||
203 | new_status = 1; | ||
204 | pt = buff; | ||
205 | } | ||
206 | bytestoword32(x, pt); | ||
207 | if (num <= (64 - 9)) | ||
208 | new_status = 2; | ||
209 | return new_status; | ||
210 | } | ||
211 | |||
212 | |||
213 | void md5 (const char *message, size_t len, char output[HASHSIZE]) { | ||
214 | WORD32 d[4]; | ||
215 | int status = 0; | ||
216 | long i = 0; | ||
217 | inic_digest(d); | ||
218 | while (status != 2) { | ||
219 | WORD32 d_old[4]; | ||
220 | WORD32 wbuff[16]; | ||
221 | int numbytes = (len-i >= 64) ? 64 : len-i; | ||
222 | /*salva os valores do vetor digest*/ | ||
223 | d_old[0]=d[0]; d_old[1]=d[1]; d_old[2]=d[2]; d_old[3]=d[3]; | ||
224 | status = converte(wbuff, message+i, numbytes, status); | ||
225 | if (status == 2) put_length(wbuff, len); | ||
226 | digest(wbuff, d); | ||
227 | d[0]+=d_old[0]; d[1]+=d_old[1]; d[2]+=d_old[2]; d[3]+=d_old[3]; | ||
228 | i += numbytes; | ||
229 | } | ||
230 | word32tobytes(d, output); | ||
231 | } | ||
232 | |||
233 | void md5_init(md5_t *m) { | ||
234 | inic_digest(m->d); | ||
235 | m->len = 0; | ||
236 | } | ||
237 | |||
238 | int md5_update(md5_t *m, const char *message, size_t len) { | ||
239 | WORD32 *d = m->d; | ||
240 | size_t addlen = m->len; | ||
241 | int status = 0, i = 0; | ||
242 | while (status != 2) { | ||
243 | WORD32 d_old[4]; | ||
244 | WORD32 wbuff[16]; | ||
245 | int numbytes = (len-i >= 64) ? 64 : len-i; | ||
246 | if (status != 1 && numbytes == 0 && len != 0) | ||
247 | break; | ||
248 | /*salva os valores do vetor digest*/ | ||
249 | d_old[0]=d[0]; d_old[1]=d[1]; d_old[2]=d[2]; d_old[3]=d[3]; | ||
250 | status = converte(wbuff, message+i, numbytes, status); | ||
251 | if (status == 2) put_length(wbuff, addlen+len); | ||
252 | digest(wbuff, d); | ||
253 | d[0]+=d_old[0]; d[1]+=d_old[1]; d[2]+=d_old[2]; d[3]+=d_old[3]; | ||
254 | i += numbytes; | ||
255 | } | ||
256 | m->len += len; | ||
257 | return status == 2; | ||
258 | } | ||
259 | |||
260 | void md5_finish (md5_t *m, char output[HASHSIZE]) { | ||
261 | word32tobytes(m->d, output); | ||
262 | } | ||
diff --git a/vendor/md5/src/md5.def b/vendor/md5/src/md5.def new file mode 100644 index 00000000..8ab09e76 --- /dev/null +++ b/vendor/md5/src/md5.def | |||
@@ -0,0 +1,5 @@ | |||
1 | LIBRARY core.dll | ||
2 | DESCRIPTION "LuaMD5" | ||
3 | VERSION 1.3 | ||
4 | EXPORTS | ||
5 | luaopen_md5_core | ||
diff --git a/vendor/md5/src/md5.h b/vendor/md5/src/md5.h new file mode 100755 index 00000000..522ede81 --- /dev/null +++ b/vendor/md5/src/md5.h | |||
@@ -0,0 +1,40 @@ | |||
1 | /** | ||
2 | * $Id: md5.h,v 1.2 2006/03/03 15:04:49 tomas Exp $ | ||
3 | * Cryptographic module for Lua. | ||
4 | * @author Roberto Ierusalimschy | ||
5 | */ | ||
6 | |||
7 | |||
8 | #ifndef md5_h | ||
9 | #define md5_h | ||
10 | |||
11 | #include <lua.h> | ||
12 | #include <stddef.h> | ||
13 | |||
14 | |||
15 | #define HASHSIZE 16 | ||
16 | |||
17 | #if __STDC_VERSION__ >= 199901L | ||
18 | #include <stdint.h> | ||
19 | typedef uint32_t WORD32; | ||
20 | #else | ||
21 | /* static assert that int equal or greater than 32bit. */ | ||
22 | typedef char static_assert_sizeof_int | ||
23 | [sizeof(unsigned int) >= 4 ? 1 : -1]; | ||
24 | typedef unsigned int WORD32; | ||
25 | #endif | ||
26 | |||
27 | typedef struct md5_t { | ||
28 | WORD32 d[4]; | ||
29 | size_t len; | ||
30 | } md5_t; | ||
31 | |||
32 | void md5_init (md5_t *m); | ||
33 | int md5_update (md5_t *m, const char *message, size_t len); | ||
34 | void md5_finish (md5_t *m, char output[HASHSIZE]); | ||
35 | void md5 (const char *message, size_t len, char output[HASHSIZE]); | ||
36 | |||
37 | LUALIB_API int luaopen_md5_core (lua_State *L); | ||
38 | |||
39 | |||
40 | #endif | ||
diff --git a/vendor/md5/src/md5.lua b/vendor/md5/src/md5.lua new file mode 100644 index 00000000..4eeda2dd --- /dev/null +++ b/vendor/md5/src/md5.lua | |||
@@ -0,0 +1,26 @@ | |||
1 | ---------------------------------------------------------------------------- | ||
2 | -- $Id: md5.lua,v 1.4 2006/08/21 19:24:21 carregal Exp $ | ||
3 | ---------------------------------------------------------------------------- | ||
4 | |||
5 | local core | ||
6 | local string = string or require"string" | ||
7 | if string.find(_VERSION, "Lua 5.0") then | ||
8 | local cpath = os.getenv"LUA_CPATH" or "/usr/local/lib/lua/5.0/" | ||
9 | core = loadlib(cpath.."md5/core.so", "luaopen_md5_core")() | ||
10 | else | ||
11 | core = require"md5.core" | ||
12 | end | ||
13 | |||
14 | |||
15 | ---------------------------------------------------------------------------- | ||
16 | -- @param k String with original message. | ||
17 | -- @return String with the md5 hash value converted to hexadecimal digits | ||
18 | |||
19 | function core.sumhexa (k) | ||
20 | k = core.sum(k) | ||
21 | return (string.gsub(k, ".", function (c) | ||
22 | return string.format("%02x", string.byte(c)) | ||
23 | end)) | ||
24 | end | ||
25 | |||
26 | return core | ||
diff --git a/vendor/md5/src/md5lib.c b/vendor/md5/src/md5lib.c new file mode 100644 index 00000000..19abc85f --- /dev/null +++ b/vendor/md5/src/md5lib.c | |||
@@ -0,0 +1,200 @@ | |||
1 | /** | ||
2 | * $Id: md5lib.c,v 1.10 2008/05/12 20:51:27 carregal Exp $ | ||
3 | * Cryptographic and Hash functions for Lua | ||
4 | * @author Roberto Ierusalimschy | ||
5 | */ | ||
6 | |||
7 | |||
8 | #include <stdlib.h> | ||
9 | #include <string.h> | ||
10 | #include <time.h> | ||
11 | |||
12 | #include <lua.h> | ||
13 | #include <lauxlib.h> | ||
14 | |||
15 | #include "md5.h" | ||
16 | #include "compat-5.2.h" | ||
17 | |||
18 | |||
19 | /** | ||
20 | * Hash function. Returns a hash for a given string. | ||
21 | * @param message: arbitrary binary string. | ||
22 | * @return A 128-bit hash string. | ||
23 | */ | ||
24 | static int lmd5 (lua_State *L) { | ||
25 | char buff[16]; | ||
26 | size_t l; | ||
27 | const char *message = luaL_checklstring(L, 1, &l); | ||
28 | md5(message, l, buff); | ||
29 | lua_pushlstring(L, buff, 16L); | ||
30 | return 1; | ||
31 | } | ||
32 | |||
33 | |||
34 | /** | ||
35 | * X-Or. Does a bit-a-bit exclusive-or of two strings. | ||
36 | * @param s1: arbitrary binary string. | ||
37 | * @param s2: arbitrary binary string with same length as s1. | ||
38 | * @return a binary string with same length as s1 and s2, | ||
39 | * where each bit is the exclusive-or of the corresponding bits in s1-s2. | ||
40 | */ | ||
41 | static int ex_or (lua_State *L) { | ||
42 | size_t l1, l2; | ||
43 | const char *s1 = luaL_checklstring(L, 1, &l1); | ||
44 | const char *s2 = luaL_checklstring(L, 2, &l2); | ||
45 | luaL_Buffer b; | ||
46 | luaL_argcheck( L, l1 == l2, 2, "lengths must be equal" ); | ||
47 | luaL_buffinit(L, &b); | ||
48 | while (l1--) luaL_addchar(&b, (*s1++)^(*s2++)); | ||
49 | luaL_pushresult(&b); | ||
50 | return 1; | ||
51 | } | ||
52 | |||
53 | |||
54 | static void checkseed (lua_State *L) { | ||
55 | if (lua_isnone(L, 3)) { /* no seed? */ | ||
56 | time_t tm = time(NULL); /* for `random' seed */ | ||
57 | lua_pushlstring(L, (char *)&tm, sizeof(tm)); | ||
58 | } | ||
59 | } | ||
60 | |||
61 | |||
62 | #define MAXKEY 256 | ||
63 | #define BLOCKSIZE 16 | ||
64 | |||
65 | |||
66 | |||
67 | static int initblock (lua_State *L, const char *seed, int lseed, char *block) { | ||
68 | size_t lkey; | ||
69 | const char *key = luaL_checklstring(L, 2, &lkey); | ||
70 | if (lkey > MAXKEY) | ||
71 | luaL_error(L, "key too long (> %d)", MAXKEY); | ||
72 | memset(block, 0, BLOCKSIZE); | ||
73 | memcpy(block, seed, lseed); | ||
74 | memcpy(block+BLOCKSIZE, key, lkey); | ||
75 | return (int)lkey+BLOCKSIZE; | ||
76 | } | ||
77 | |||
78 | |||
79 | static void codestream (lua_State *L, const char *msg, size_t lmsg, | ||
80 | char *block, int lblock) { | ||
81 | luaL_Buffer b; | ||
82 | luaL_buffinit(L, &b); | ||
83 | while (lmsg > 0) { | ||
84 | char code[BLOCKSIZE]; | ||
85 | int i; | ||
86 | md5(block, lblock, code); | ||
87 | for (i=0; i<BLOCKSIZE && lmsg > 0; i++, lmsg--) | ||
88 | code[i] ^= *msg++; | ||
89 | luaL_addlstring(&b, code, i); | ||
90 | memcpy(block, code, i); /* update seed */ | ||
91 | } | ||
92 | luaL_pushresult(&b); | ||
93 | } | ||
94 | |||
95 | |||
96 | static void decodestream (lua_State *L, const char *cypher, size_t lcypher, | ||
97 | char *block, int lblock) { | ||
98 | luaL_Buffer b; | ||
99 | luaL_buffinit(L, &b); | ||
100 | while (lcypher > 0) { | ||
101 | char code[BLOCKSIZE]; | ||
102 | int i; | ||
103 | md5(block, lblock, code); /* update seed */ | ||
104 | for (i=0; i<BLOCKSIZE && lcypher > 0; i++, lcypher--) | ||
105 | code[i] ^= *cypher++; | ||
106 | luaL_addlstring(&b, code, i); | ||
107 | memcpy(block, cypher-i, i); | ||
108 | } | ||
109 | luaL_pushresult(&b); | ||
110 | } | ||
111 | |||
112 | |||
113 | /** | ||
114 | * Encrypts a string. Uses the hash function md5 in CFB (Cipher-feedback | ||
115 | * mode). | ||
116 | * @param message: arbitrary binary string to be encrypted. | ||
117 | * @param key: arbitrary binary string to be used as a key. | ||
118 | * @param [seed]: optional arbitrary binary string to be used as a seed. | ||
119 | * if no seed is provided, the function uses the result of | ||
120 | * <code>time()</code> as a seed. | ||
121 | * @return The cyphertext (as a binary string). | ||
122 | */ | ||
123 | static int crypt (lua_State *L) { | ||
124 | size_t lmsg; | ||
125 | const char *msg = luaL_checklstring(L, 1, &lmsg); | ||
126 | size_t lseed; | ||
127 | const char *seed; | ||
128 | int lblock; | ||
129 | char block[BLOCKSIZE+MAXKEY]; | ||
130 | checkseed(L); | ||
131 | seed = luaL_checklstring(L, 3, &lseed); | ||
132 | if (lseed > BLOCKSIZE) | ||
133 | luaL_error(L, "seed too long (> %d)", BLOCKSIZE); | ||
134 | /* put seed and seed length at the beginning of result */ | ||
135 | block[0] = (char)lseed; | ||
136 | memcpy(block+1, seed, lseed); | ||
137 | lua_pushlstring(L, block, lseed+1); /* to concat with result */ | ||
138 | lblock = initblock(L, seed, lseed, block); | ||
139 | codestream(L, msg, lmsg, block, lblock); | ||
140 | lua_concat(L, 2); | ||
141 | return 1; | ||
142 | } | ||
143 | |||
144 | |||
145 | /** | ||
146 | * Decrypts a string. For any message, key, and seed, we have that | ||
147 | * <code>decrypt(crypt(msg, key, seed), key) == msg</code>. | ||
148 | * @param cyphertext: message to be decrypted (this must be the result of | ||
149 | a previous call to <code>crypt</code>. | ||
150 | * @param key: arbitrary binary string to be used as a key. | ||
151 | * @return The plaintext. | ||
152 | */ | ||
153 | static int decrypt (lua_State *L) { | ||
154 | size_t lcyphertext; | ||
155 | const char *cyphertext = luaL_checklstring(L, 1, &lcyphertext); | ||
156 | size_t lseed = cyphertext[0]; | ||
157 | const char *seed = cyphertext+1; | ||
158 | int lblock; | ||
159 | char block[BLOCKSIZE+MAXKEY]; | ||
160 | luaL_argcheck(L, lcyphertext >= lseed+1 && lseed <= BLOCKSIZE, 1, | ||
161 | "invalid cyphered string"); | ||
162 | cyphertext += lseed+1; | ||
163 | lcyphertext -= lseed+1; | ||
164 | lblock = initblock(L, seed, lseed, block); | ||
165 | decodestream(L, cyphertext, lcyphertext, block, lblock); | ||
166 | return 1; | ||
167 | } | ||
168 | |||
169 | |||
170 | /* | ||
171 | ** Assumes the table is on top of the stack. | ||
172 | */ | ||
173 | static void set_info (lua_State *L) { | ||
174 | lua_pushliteral (L, "_COPYRIGHT"); | ||
175 | lua_pushliteral (L, "Copyright (C) 2003-2019 PUC-Rio"); | ||
176 | lua_settable (L, -3); | ||
177 | lua_pushliteral (L, "_DESCRIPTION"); | ||
178 | lua_pushliteral (L, "Checksum facilities for Lua"); | ||
179 | lua_settable (L, -3); | ||
180 | lua_pushliteral (L, "_VERSION"); | ||
181 | lua_pushliteral (L, "MD5 1.3"); | ||
182 | lua_settable (L, -3); | ||
183 | } | ||
184 | |||
185 | |||
186 | static struct luaL_Reg md5lib[] = { | ||
187 | {"sum", lmd5}, | ||
188 | {"exor", ex_or}, | ||
189 | {"crypt", crypt}, | ||
190 | {"decrypt", decrypt}, | ||
191 | {NULL, NULL} | ||
192 | }; | ||
193 | |||
194 | |||
195 | int luaopen_md5_core (lua_State *L) { | ||
196 | lua_newtable(L); | ||
197 | luaL_setfuncs(L, md5lib, 0); | ||
198 | set_info (L); | ||
199 | return 1; | ||
200 | } | ||