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 /vendor/luasocket | |
| parent | 9e162d9e980f7e17c0ea41e0cd29173d01ada330 (diff) | |
| download | luarocks-cc887b9b25571e9ce0afa0cd5e4a4a2cbf130d3a.tar.gz luarocks-cc887b9b25571e9ce0afa0cd5e4a4a2cbf130d3a.tar.bz2 luarocks-cc887b9b25571e9ce0afa0cd5e4a4a2cbf130d3a.zip | |
[wip] vendor in dependencies
Diffstat (limited to 'vendor/luasocket')
62 files changed, 10142 insertions, 0 deletions
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 */ | ||
