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 */ | ||