aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2004-02-04 14:29:11 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2004-02-04 14:29:11 +0000
commit0b2542d1a61fc5425ff65ab3dbf7ba7de174763f (patch)
tree8a6188e11db0c9ef6891c31e8a1bebca050b23b2
parentf67864f86c7d703325e86b14d0ba33992c52891b (diff)
downloadluasocket-0b2542d1a61fc5425ff65ab3dbf7ba7de174763f.tar.gz
luasocket-0b2542d1a61fc5425ff65ab3dbf7ba7de174763f.tar.bz2
luasocket-0b2542d1a61fc5425ff65ab3dbf7ba7de174763f.zip
Worked on the manual.
Implemented stuffing (needs test) Added cddb and qp examples.
-rw-r--r--TODO62
-rw-r--r--doc/callback.html158
-rw-r--r--doc/dns.html19
-rw-r--r--doc/http.html2
-rw-r--r--doc/index.html18
-rw-r--r--doc/reference.html8
-rw-r--r--doc/tcp.html148
-rw-r--r--doc/url.html44
-rw-r--r--etc/qp.lua18
-rw-r--r--samples/cddb.lua43
-rw-r--r--src/auxiliar.c14
-rw-r--r--src/auxiliar.h3
-rw-r--r--src/buffer.c3
-rw-r--r--src/buffer.h2
-rw-r--r--src/ftp.lua2
-rw-r--r--src/http.lua2
-rw-r--r--src/inet.c9
-rw-r--r--src/inet.h2
-rw-r--r--src/luasocket.c50
-rw-r--r--src/mime.c138
-rw-r--r--src/mime.h2
-rw-r--r--src/mime.lua71
-rw-r--r--src/select.c3
-rw-r--r--src/select.h2
-rw-r--r--src/smtp.lua6
-rw-r--r--src/tcp.c33
-rw-r--r--src/tcp.h2
-rw-r--r--src/timeout.c3
-rw-r--r--src/timeout.h2
-rw-r--r--src/udp.c32
-rw-r--r--src/udp.h2
-rw-r--r--src/url.lua2
-rw-r--r--src/usocket.c5
-rw-r--r--src/wsocket.c6
-rw-r--r--test/mimetest.lua15
-rw-r--r--test/testclnt.lua28
-rw-r--r--test/urltest.lua2
37 files changed, 639 insertions, 322 deletions
diff --git a/TODO b/TODO
index 4dd0766..9e9923c 100644
--- a/TODO
+++ b/TODO
@@ -1,7 +1,36 @@
1* should be interrupt-safe
2* notice the change in callback conventions
3* new mime module replacing old code module (faster, more functionality)
4* new socket options (many)
5* only allocate in case of success
6* optimize for success (only call select if fails)
7* add proxy support to http
8* add gethostname
9* local connect
10* connect with timeout
11* change code to mime
12* change stay to redirect
13* add shutdown
14* change send/recv to avoid using select
15* O location do "redirect" pode ser relativo ao servidor atual (não pode,
16 mas os servidores fazem merda...)
17* Ajeitar para Lua 5.0
18* Padronizar os retornos de funccao
19* Separar as classes em arquivos
20* Retorno de sendto em datagram sockets pode ser refused
21
22
23check garbage collection in test*.lua
24pop3???
25
26add socket.TIMEOUT to be default timeout?
27
1manual 28manual
29 add socket.connect and socket.bind to the manual
30 say what a nil callback does for http
2 check all occurences of it's 31 check all occurences of it's
3 add shutdown 32 - add shutdown
4 add gethostname 33 - add gethostname
5 the need of a content-length header in the post method... 34 the need of a content-length header in the post method...
6 notice the change in callback conventions 35 notice the change in callback conventions
7 the callback.lua module and the new mime module. 36 the callback.lua module and the new mime module.
@@ -9,11 +38,11 @@ manual
9 add timeout and proxy to request table 38 add timeout and proxy to request table
10 change stay to redirect 39 change stay to redirect
11 socket.time and socket.sleep 40 socket.time and socket.sleep
12 connect with timeout 41 - connect with timeout
13 local connect 42 local connect
14 add thanks to 'carlos cassino' and 'david burgess' 43 add thanks to 'carlos cassino' and 'david burgess'
15 add new ip- options and reuseaddr option 44 add new ip- options and reuseaddr option
16 add listen to manual 45 - add listen to manual
17 bind method doesn't do listen anymore 46 bind method doesn't do listen anymore
18 bind doesn't turn an object into a server object: listen does. 47 bind doesn't turn an object into a server object: listen does.
19 48
@@ -23,6 +52,9 @@ tests
23 checar garbage collection 52 checar garbage collection
24 check for interrupts 53 check for interrupts
25 54
55wrp can't break lines in the middle of a line break.
56call select before accept, not after, dumbass!
57get rid of setnonblocking/setblocking in the bind function
26close has to block... 58close has to block...
27fmt is not a good name 59fmt is not a good name
28change wrap() to accept a number and default to "character" 60change wrap() to accept a number and default to "character"
@@ -76,30 +108,10 @@ Ajeitar o protocolo da luaopen_socket()... sei lá qual é.
76 108
77- adicionar exemplos de expansão: pipe, local, named pipe 109- adicionar exemplos de expansão: pipe, local, named pipe
78 110
79* should be interrupt-safe
80* notice the change in callback conventions
81* new mime module replacing old code module (faster, more functionality)
82* new socket options (many)
83* only allocate in case of success
84* optimize for success (only call select if fails)
85* add proxy support to http
86* add gethostname
87* local connect
88* connect with timeout
89* change code to mime
90* change stay to redirect
91* add shutdown
92* change send/recv to avoid using select
93* O location do "redirect" pode ser relativo ao servidor atual (não pode,
94 mas os servidores fazem merda...)
95* Ajeitar para Lua 5.0
96* Padronizar os retornos de funccao
97* Separar as classes em arquivos
98* Retorno de sendto em datagram sockets pode ser refused
99 111
100- Fazer compilar com g++ 112- Fazer compilar com g++
101- Thread-safe 113- Thread-safe
102 - proteger gethostby*.* com um mutex GLOBAL! 114 - proteger get*by*.* com um mutex GLOBAL!
103 - proteger ou atomizar o conjunto (timedout, receive), (timedout, send) 115 - proteger ou atomizar o conjunto (timedout, receive), (timedout, send)
104 - inet_ntoa também é uma merda. 116 - inet_ntoa também é uma merda.
105- SSL 117- SSL
diff --git a/doc/callback.html b/doc/callback.html
index 94af8ff..98b4476 100644
--- a/doc/callback.html
+++ b/doc/callback.html
@@ -31,16 +31,16 @@
31<hr> 31<hr>
32</div> 32</div>
33 33
34<!-- stream ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> 34<!-- stream ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
35 35
36<h2 id=stream>Streaming with Callbacks</h2> 36<h2 id=stream>Callbacks</h2>
37 37
38<p> 38<p>
39HTTP, FTP, and SMTP transfers sometimes involve large amounts of 39HTTP, FTP, and SMTP transfers sometimes involve large amounts of
40information. Sometimes an application needs to generate outgoing data 40information. Sometimes an application needs to generate outgoing data
41in real time, or needs to process incoming information as it is being 41in real time, or needs to process incoming information as it is being
42received. To address these problems, LuaSocket allows HTTP and SMTP message 42received. To address these problems, LuaSocket allows HTTP and SMTP message
43bodies and FTP file contents to be received or sent through the 43bodies and FTP file contents to be streamed through the
44callback mechanism outlined below. 44callback mechanism outlined below.
45</p> 45</p>
46 46
@@ -52,7 +52,7 @@ chunks of data, as the data becomes available. Conversely, the <em>send
52callback</em> mechanism can be used when the application wants to incrementally provide LuaSocket with the data to be sent. 52callback</em> mechanism can be used when the application wants to incrementally provide LuaSocket with the data to be sent.
53</p> 53</p>
54 54
55<!-- tohostname +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> 55<!-- receive +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
56 56
57<p class=name id=receive> 57<p class=name id=receive>
58<b>receive_cb(</b>chunk, err<b>)</b> 58<b>receive_cb(</b>chunk, err<b>)</b>
@@ -60,7 +60,7 @@ callback</em> mechanism can be used when the application wants to incrementally
60 60
61<p class=description> 61<p class=description>
62A receive callback will be repeatedly called by 62A receive callback will be repeatedly called by
63LuaSocket wheneve new data is available. Each time it is called, the 63LuaSocket whenever new data is available. Each time it is called, the
64callback receives successive chunks of downloaded data. 64callback receives successive chunks of downloaded data.
65</p> 65</p>
66 66
@@ -113,10 +113,129 @@ Together, these two modules provide a powerful interface to send and
113receive information. 113receive information.
114</p> 114</p>
115 115
116<!-- done +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
117
118<p class=name id=done>
119socket.callback.<b>done()</b>
120</p>
121
122<p class=description>
123This function creates and returns a callback that successfully terminates
124the transmission.
125</p>
126
127<!-- fail +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
128
129<p class=name id=fail>
130socket.callback.<b>fail(</b>message<b>)</b>
131</p>
132
133<p class=description>
134This function creates and returns a callback that aborts the
135transmission with a given error <tt>message</tt>.
136</p>
137
138<!-- receive.concat +++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
139
140<p class=name id=receive.concat>
141socket.callback.<b>receive.concat(</b>cat<b>)</b>
142</p>
143
144<p class=description>
145This function creates a receive callback that stores whatever it receives
146into a concat object. When done, the application can get the contents
147received as a single string, directly from the concat object.
148</p>
149
150<p class=parameters>
151<tt>Cat</tt> is the target concat object, or <b><tt>nil</tt></b>.
152If <tt>cat</tt> is <b><tt>nil</tt></b>, the function creates its own
153concat object.
154</p>
155
156<p class=return>
157The function returns a receive callback for the file, and the concat object
158that will be used to store the received contents.
159</p>
160
161<!-- receive.file +++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
162
163<p class=name id=receive.file>
164socket.callback.<b>receive.file(</b>file, io_err<b>)</b>
165</p>
166
167<p class=description>
168This function creates a receive callback that stores whatever it receives
169into a file. When done, the callback closes the file.
170</p>
171
172<p class=parameters>
173<tt>File</tt> is a file handle opened for writing. If <tt>file</tt> is
174<b><tt>nil</tt></b>, <tt>io_err</tt> can contain an error message. In this
175case, the function returns a callback that just aborts
176transmission with the error message.
177</p>
178
179<p class=return>
180The function returns a receive callback for the file.
181</p>
182
183<p class=note>
184Note: This function is designed so that it directly accepts the return
185values of Lua's IO <tt>io.open</tt> library function.
186</p>
187
188<!-- receive.chain ++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
189
190<p class=name id=receive.chain>
191socket.callback.<b>receive.chain(</b>filter, receive_cb<b>)</b>
192</p>
193
194<p class=description>
195This function creates a receive callback that passes all received data
196through a filter, before handing it to a given receive callback.
197</p>
198
199<p class=parameters>
200<tt>Cat</tt> is the target concat object, or <b><tt>nil</tt></b>.
201If <tt>cat</tt> is <b><tt>nil</tt></b>, the function creates its own
202concat object.
203</p>
204
205<p class=return>
206The function returns a receive callback for the file, and the concat object
207that will be used to store the received contents.
208</p>
209
210<p class=note>
211Note: Several filters are defined in the <a href=mime.html>MIME</a>
212module. Below is an example that creates a receive callback that
213creates a string from the received contents, after decoding the
214Quoted-Printable transfer content encoding.
215</p>
216
217<pre class=example>
218string_cb, concat = socket.callback.receive.concat()
219receive_cb = socket.callback.receive.chain(
220 socket.mime.decode("quoted-printable"),
221 string_cb
222)
223</pre>
224
225<p class=note>
226The call to <tt>callback.chain</tt> creates a chained
227receive callback that decodes data using the
228<tt><a href=mime.html#decode>mime.decode</a></tt>
229Quoted-Printable MIME filter and
230hands the decoded data to a concat receive callback.
231The concatenated decoded data can be retrieved later
232from the associated concat object.
233</p>
234
116<!-- send.file ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> 235<!-- send.file ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
117 236
118<p class=name id=send.file> 237<p class=name id=send.file>
119<b>send.file</b>(file, io_err<b>)</b> 238socket.callback.<b>send.file(</b>file, io_err<b>)</b>
120</p> 239</p>
121 240
122<p class=description> 241<p class=description>
@@ -126,25 +245,25 @@ When done, the callback closes the file.
126</p> 245</p>
127 246
128<p class=parameters> 247<p class=parameters>
129<tt>File</tt> is a file opened for reading. If <tt>file</tt> is 248<tt>File</tt> is a file handle opened for reading. If <tt>file</tt> is
130<b><tt>nil</tt></b>, <tt>io_err</tt> can contain an error message. In this 249<b><tt>nil</tt></b>, <tt>io_err</tt> can contain an error message. In this
131case, the function returns a callback that just aborts 250case, the function returns a callback that just aborts
132transmission with the error message. 251transmission with the error message.
133</p> 252</p>
134 253
135<p class=return> 254<p class=return>
136Returns a send callback for the file. 255The function returns a send callback for the file.
137</p> 256</p>
138 257
139<p class=note> 258<p class=note>
140Note: This function is designed so that it directly accepts the return 259Note: This function is designed so that it directly accepts the return
141values of the <tt>io.open</tt> function. 260values of Lua's IO <tt>io.open</tt> library function.
142</p> 261</p>
143 262
144<!-- send.string ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> 263<!-- send.string ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
145 264
146<p class=name id=send.string> 265<p class=name id=send.string>
147<b>send.string(</b>str, err<b>)</b> 266socket.callback.<b>send.string(</b>str, err<b>)</b>
148</p> 267</p>
149 268
150<p class=description> 269<p class=description>
@@ -154,26 +273,17 @@ the contents of a string.
154 273
155<p class=parameters> 274<p class=parameters>
156<tt>Str</tt> is the string to be sent. 275<tt>Str</tt> is the string to be sent.
157<!--
158If <tt>str</tt> is
159<b><tt>nil</tt></b>, <tt>err</tt> can optionally contain an error message.
160-->
161</p> 276</p>
162 277
163<p class=return> 278<p class=return>
164Returns a send callback for the string, or <b><tt>nil</tt></b> if the string is 279It returns a send callback for the string,
165<b><tt>nil</tt></b>. 280or <b><tt>nil</tt></b> if <tt>str</tt> is <b><tt>nil</tt></b>.
166</p>
167
168<p class=note>
169Note: A <tt>nil</tt></b>
170send callback is equivalent to a callback that returns the empty string.
171</p> 281</p>
172 282
173<!-- send.chain ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> 283<!-- send.chain ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
174 284
175<p class=name id=send.chain> 285<p class=name id=send.chain>
176<b>send.chain(</b>send_cb, filter<b>)</b> 286socket.callback.<b>send.chain(</b>send_cb, filter<b>)</b>
177</p> 287</p>
178 288
179<p class=description> 289<p class=description>
@@ -207,9 +317,9 @@ send_cb = socket.callback.send.chain(
207</pre> 317</pre>
208 318
209<p class=note> 319<p class=note>
210The call to <a href=mime.html#chain><tt>socket.mime.chain</tt></a> 320The call to <a href=mime.html#chain><tt>mime.chain</tt></a>
211creates a chained filter that encodes it's input and then breaks it 321creates a chained filter that encodes it's input and then breaks it
212into lines. The call to <tt>socket.callback.chain</tt> creates a chained 322into lines. The call to <tt>callback.chain</tt> creates a chained
213send callback that reads the file from disk and passes it through the 323send callback that reads the file from disk and passes it through the
214filter before sending it. 324filter before sending it.
215</p> 325</p>
diff --git a/doc/dns.html b/doc/dns.html
index 17cee45..71a9719 100644
--- a/doc/dns.html
+++ b/doc/dns.html
@@ -36,8 +36,7 @@
36<h2 id=dns>DNS</h2> 36<h2 id=dns>DNS</h2>
37 37
38<p> 38<p>
39The following functions can be used to convert between host names and IP 39Name resolution function return <em>all</em> information returned by the
40addresses. Both functions return <em>all</em> information returned by the
41resolver in a table of the form: 40resolver in a table of the form:
42</p> 41</p>
43 42
@@ -53,6 +52,21 @@ resolved = {<br>
53Note that the <tt>alias</tt> list can be empty. 52Note that the <tt>alias</tt> list can be empty.
54</p> 53</p>
55 54
55<!-- gethostname ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
56
57<p class=name id=gethostname>
58socket.dns.<b>gethostname()</b>
59</p>
60
61<p class=description>
62Returns the standard host name for the machine.
63</p>
64
65<p class=return>
66The function returns a string with the host name.
67</p>
68
69
56<!-- tohostname +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> 70<!-- tohostname +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
57 71
58<p class=name id=tohostname> 72<p class=name id=tohostname>
@@ -74,7 +88,6 @@ the resolver. In case of error, the function returns <b><tt>nil</tt></b>
74followed by an error message. 88followed by an error message.
75</p> 89</p>
76 90
77
78<!-- toip +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> 91<!-- toip +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
79 92
80<p class=name id=toip> 93<p class=name id=toip>
diff --git a/doc/http.html b/doc/http.html
index f977ea9..f82f515 100644
--- a/doc/http.html
+++ b/doc/http.html
@@ -49,7 +49,7 @@ implementation conforms to the HTTP/1.1 standard,
49The module exports functions that provide HTTP functionality in different 49The module exports functions that provide HTTP functionality in different
50levels of abstraction, from a simple <a 50levels of abstraction, from a simple <a
51href="#get"><tt>get</tt></a>, to the generic, stream oriented 51href="#get"><tt>get</tt></a>, to the generic, stream oriented
52<a href="#request_cb"> <tt>request_cb</tt></a>. 52<a href="#request_cb"><tt>request_cb</tt></a>.
53</p> 53</p>
54 54
55<p> 55<p>
diff --git a/doc/index.html b/doc/index.html
index 620f385..a2c2d59 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -40,7 +40,8 @@ LuaSocket is a <a href="http://www.lua.org">Lua</a> extension library
40that is composed by two parts: a C layer that provides support for the TCP 40that is composed by two parts: a C layer that provides support for the TCP
41and UDP transport layers, and a set of Lua modules that add support for 41and UDP transport layers, and a set of Lua modules that add support for
42the SMTP (sending e-mails), HTTP (WWW access) and FTP (uploading and 42the SMTP (sending e-mails), HTTP (WWW access) and FTP (uploading and
43downloading files) protocols. 43downloading files) protocols and other functionality commonly needed by
44applications that deal with the Internet.
44</p> 45</p>
45 46
46<p> 47<p>
@@ -106,10 +107,25 @@ This binary has been compiled with the <tt>LUASOCKET_DEBUG</tt>
106option, and should be able to run the automatic test procedures. 107option, and should be able to run the automatic test procedures.
107</p> 108</p>
108 109
110<!-- thanks +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
111
112<h2 id=thanks>Special thanks</h2>
113
114<p>
115Throughout LuaSocket its history, many people gave sugestions that helped
116improve it. For that, I thank the Lua comunity.
117Special thanks go to
118David Burgess, who has pushed the library to a new level of quality and
119from whom I have learned a lot stuff that doesn't show up in RFCs.
120Special thanks also to Carlos Cassino, who played a big part in the
121extensible design seen in the C core of LuaSocket 2.0.
122</p>
123
109<!-- whatsnew +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> 124<!-- whatsnew +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
110 125
111<h2 id=new>What's New</h2> 126<h2 id=new>What's New</h2>
112 127
128
113<p> 129<p>
114Most of the changes for 2.0 happened in the C layer, which 130Most of the changes for 2.0 happened in the C layer, which
115has been almost completely rewritten. The code has been ported to Lua 5.0 131has been almost completely rewritten. The code has been ported to Lua 5.0
diff --git a/doc/reference.html b/doc/reference.html
index 0bfd378..e6efb6e 100644
--- a/doc/reference.html
+++ b/doc/reference.html
@@ -40,6 +40,10 @@
40<blockquote> 40<blockquote>
41<a href="callback.html">Callbacks (socket.callback)</a> 41<a href="callback.html">Callbacks (socket.callback)</a>
42<blockquote> 42<blockquote>
43<a href="callback.html#done">done</a>,
44<a href="callback.html#fail">fail</a>.
45</blockquote>
46<blockquote>
43<a href="callback.html#send">send</a>: 47<a href="callback.html#send">send</a>:
44<a href="callback.html#send.chain">chain</a>, 48<a href="callback.html#send.chain">chain</a>,
45<a href="callback.html#send.file">file</a>, 49<a href="callback.html#send.file">file</a>,
@@ -121,7 +125,7 @@
121<blockquote> 125<blockquote>
122<a href="mime.html">MIME (socket.mime) </a> 126<a href="mime.html">MIME (socket.mime) </a>
123<blockquote> 127<blockquote>
124<a href="mime.html#filters">filters</a>: 128<a href="mime.html#high">high-level</a>:
125<a href="mime.html#decode">canonic</a>, 129<a href="mime.html#decode">canonic</a>,
126<a href="mime.html#chain">chain</a>, 130<a href="mime.html#chain">chain</a>,
127<a href="mime.html#decode">decode</a>, 131<a href="mime.html#decode">decode</a>,
@@ -129,7 +133,7 @@
129<a href="mime.html#wrap">wrap</a>. 133<a href="mime.html#wrap">wrap</a>.
130</blockquote> 134</blockquote>
131<blockquote> 135<blockquote>
132<a href="mime.html#low-level">low-level</a>: 136<a href="mime.html#low">low-level</a>:
133<a href="mime.html#b64">b64</a>, 137<a href="mime.html#b64">b64</a>,
134<a href="mime.html#unb64">unb64</a>, 138<a href="mime.html#unb64">unb64</a>,
135<a href="mime.html#eol">eol</a>, 139<a href="mime.html#eol">eol</a>,
diff --git a/doc/tcp.html b/doc/tcp.html
index eb4cdfa..34d6c6e 100644
--- a/doc/tcp.html
+++ b/doc/tcp.html
@@ -44,10 +44,11 @@ socket.<b>tcp()</b>
44<p class=description> 44<p class=description>
45Creates and returns a TCP master object. A master object can 45Creates and returns a TCP master object. A master object can
46be transformed into a server object with the method 46be transformed into a server object with the method
47<a href=#bind><tt>bind</tt></a> or into a client object with the method 47<a href=#listen><tt>listen</tt></a> (after a call to <a
48<a href=#connect><tt>connect</tt></a>. The only other method 48href=#bind><tt>bind</tt></a>) or into a client object with
49supported by a master object is the <a href=#close><tt>close</tt></a> 49the method <a href=#connect><tt>connect</tt></a>. The only other
50method.</p> 50method supported by a master object is the
51<a href=#close><tt>close</tt></a> method.</p>
51 52
52<p class=return> 53<p class=return>
53In case of success, a new master object is returned. In case of error, 54In case of success, a new master object is returned. In case of error,
@@ -67,8 +68,9 @@ object and returns a client object representing that connection.
67 68
68<p class=return> 69<p class=return>
69If a connection is successfully initiated, a client object is returned. 70If a connection is successfully initiated, a client object is returned.
70If a timeout condition is met, the method returns <b><tt>nil</tt></b> followed 71If a timeout condition is met, the method returns <b><tt>nil</tt></b>
71by the error string '<tt>timeout</tt>'. 72followed by the error string '<tt>timeout</tt>'. Other errors are
73reported by <b><tt>nil</tt></b> followed by a message describing the error.
72</p> 74</p>
73 75
74<p class=note> 76<p class=note>
@@ -77,25 +79,18 @@ with a server object in
77the <tt>receive</tt> parameter before a call to <tt>accept</tt> does 79the <tt>receive</tt> parameter before a call to <tt>accept</tt> does
78<em>not</em> guarantee <tt>accept</tt> will return immediately. Use the <a 80<em>not</em> guarantee <tt>accept</tt> will return immediately. Use the <a
79href=#settimeout><tt>settimeout</tt></a> method or <tt>accept</tt> 81href=#settimeout><tt>settimeout</tt></a> method or <tt>accept</tt>
80might block until <em>another</em> client shows up. 82might block until <em>another</em> client shows up.
81</p> 83</p>
82 84
83<!-- bind +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> 85<!-- bind +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
84 86
85<p class=name id=bind> 87<p class=name id=bind>
86master:<b>bind(</b>address, port [, backlog]<b>)</b> 88master:<b>bind(</b>address, port<b>)</b>
87</p> 89</p>
88 90
89<p class=description> 91<p class=description>
90Binds a master object to <tt>address</tt> and <tt>port</tt> on the 92Binds a master object to <tt>address</tt> and <tt>port</tt> on the
91local host, transforming it into a server object. Server 93local host.
92objects support the
93<a href=#accept><tt>accept</tt></a>,
94<a href=#getsockname><tt>getsockname</tt></a>,
95<a href=#setoption><tt>setoption</tt></a>,
96<a href=#settimeout><tt>settimeout</tt></a>,
97and <a href=#close><tt>close</tt></a> methods.
98</p>
99 94
100<p class=parameters> 95<p class=parameters>
101<tt>Address</tt> can be an IP address or a host name. 96<tt>Address</tt> can be an IP address or a host name.
@@ -103,10 +98,7 @@ and <a href=#close><tt>close</tt></a> methods.
103If <tt>address</tt> 98If <tt>address</tt>
104is '<tt>*</tt>', the system binds to all local interfaces 99is '<tt>*</tt>', the system binds to all local interfaces
105using the <tt>INADDR_ANY</tt> constant. If <tt>port</tt> is 0, the system automatically 100using the <tt>INADDR_ANY</tt> constant. If <tt>port</tt> is 0, the system automatically
106chooses an ephemeral port. The optional parameter <tt>backlog</tt>, which 101chooses an ephemeral port.
107defaults to 1, specifies the number of client connections that can
108be queued waiting for service. If the queue is full and another client
109attempts connection, the connection is refused.
110</p> 102</p>
111 103
112<p class=return> 104<p class=return>
@@ -115,8 +107,8 @@ method returns <b><tt>nil</tt></b> followed by an error message.
115</p> 107</p>
116 108
117<p class=note> 109<p class=note>
118Note: The function <tt>socket.bind</tt> is available and is a short 110Note: The function <a href=#socket.bind><tt>socket.bind</tt></a>
119for <a href=#socket.tcp><tt>socket.tcp</tt></a> followed by the <tt>bind</tt> method. 111is available and is a shortcut for the creation server sockets.
120</p> 112</p>
121 113
122<!-- close ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> 114<!-- close ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
@@ -150,7 +142,8 @@ master:<b>connect(</b>address, port<b>)</b>
150 142
151<p class=description> 143<p class=description>
152Attempts to connect a master object to a remote host, transforming it into a 144Attempts to connect a master object to a remote host, transforming it into a
153client object. Client objects support methods 145client object.
146Client objects support methods
154<a href=#send><tt>send</tt></a>, 147<a href=#send><tt>send</tt></a>,
155<a href=#receive><tt>receive</tt></a>, 148<a href=#receive><tt>receive</tt></a>,
156<a href=#getsockname><tt>getsockname</tt></a>, 149<a href=#getsockname><tt>getsockname</tt></a>,
@@ -170,8 +163,15 @@ describing the error. In case of success, the method returns 1.
170</p> 163</p>
171 164
172<p class=note> 165<p class=note>
173Note: The function <tt>socket.connect</tt> is available and is a short 166Note: The function <a href=#socket.connect><tt>socket.connect</tt></a>
174for <a href=#socket.tcp><tt>socket.tcp</tt></a> followed by the <tt>connect</tt> method. 167is available and is a shortcut for the creation of client sockets.
168</p>
169
170<p class=note>
171Note: Starting with LuaSocket 2.0,
172the <a href=#settimeout><tt>settimeout</tt></a>
173function affects the behavior of connect, causing it to return in case of
174a timeout error.
175</p> 175</p>
176 176
177<!-- getpeername ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> 177<!-- getpeername ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
@@ -210,12 +210,32 @@ The method returns a string with local IP address and a number with
210the port. In case of error, the method returns <b><tt>nil</tt></b>. 210the port. In case of error, the method returns <b><tt>nil</tt></b>.
211</p> 211</p>
212 212
213<p class=note> 213<!-- listen ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
214Note: Naturally, for a server object, the address and port returned are 214
215those passed to the <a href=#bind>bind</a> method. If the port value 215<p class=name id=listen>
216passed to bind was 0, the OS assigned ephemeral port is returned. For 216master:<b>listen(</b>backlog<b>)</b>
217client objects, both the address and port are ephemeral and these are the 217</p>
218values returned. 218
219<p class=description>
220Specifies the socket is willing to receive connections, transforming the
221object into a server object. Server objects support the
222<a href=#accept><tt>accept</tt></a>,
223<a href=#getsockname><tt>getsockname</tt></a>,
224<a href=#setoption><tt>setoption</tt></a>,
225<a href=#settimeout><tt>settimeout</tt></a>,
226and <a href=#close><tt>close</tt></a> methods.
227</p>
228
229<p class=parameters>
230The parameter <tt>backlog</tt> specifies the number of client
231connections that can
232be queued waiting for service. If the queue is full and another client
233attempts connection, the connection is refused.
234</p>
235
236<p class=return>
237In case of success, the method returns 1. In case of error, the
238method returns <b><tt>nil</tt></b> followed by an error message.
219</p> 239</p>
220 240
221<!-- receive ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> 241<!-- receive ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
@@ -242,8 +262,8 @@ closed. No end-of-line translation is performed;
242terminated by a LF character (ASCII&nbsp;10), optionally preceded by a 262terminated by a LF character (ASCII&nbsp;10), optionally preceded by a
243CR character (ASCII&nbsp;13). The CR and LF characters are not included in 263CR character (ASCII&nbsp;13). The CR and LF characters are not included in
244the returned line. This is the default pattern; 264the returned line. This is the default pattern;
245<li> <tt>number</tt>: causes the method to read <tt>number</tt> raw 265<li> <tt>number</tt>: causes the method to read a specified <tt>number</tt>
246bytes from the socket. 266of bytes from the socket.
247</ul> 267</ul>
248 268
249<p class=return> 269<p class=return>
@@ -311,22 +331,30 @@ are sure you need it.
311depends on the option being set: 331depends on the option being set:
312 332
313<ul> 333<ul>
314<li> '<tt>tcp-nodelay</tt>': Setting this option to <tt>true</tt> disables the 334
315Nagle's algorithm for the connection; 335<li> '<tt>keepalive</tt>': Setting this option to <tt>true</tt> enables
336the periodic transmission of messages on a connected socket. Should the
337connected party fail to respond to these messages, the connection is
338considered broken and processes using the socket are notified;
339
316<li> '<tt>linger</tt>': Controls the action taken when unsent data are 340<li> '<tt>linger</tt>': Controls the action taken when unsent data are
317queued on a socket and a close is performed. The value is a table with a 341queued on a socket and a close is performed. The value is a table with a
318boolean entry '<tt>on</tt>' and a numeric entry for the time interval 342boolean entry '<tt>on</tt>' and a numeric entry for the time interval
319'<tt>timeout</tt>' in seconds. 343'<tt>timeout</tt>' in seconds. If the '<tt>on</tt>' field is set to
320 If the '<tt>on</tt>' field is set to <tt>true</tt>, 344<tt>true</tt>, the system will block the process on the close attempt until
321the system will block the process on the close attempt until it is able to 345it is able to transmit the data or until '<tt>timeout</tt>' has passed. If
322transmit the data or until '<tt>timeout</tt>' has passed. If '<tt>on</tt>' 346'<tt>on</tt>' is <tt>false</tt> and a close is issued, the system will
323is <tt>false</tt> and a close is issued, the system will process the close 347process the close in a manner that allows the process to continue as
324in a manner that allows the process to continue as quickly as possible. I 348quickly as possible. I do not advise you to set this to anything other than
325do not advise you to set this to anything other than zero. 349zero;
326<li> '<tt>keepalive</tt>': Setting this option to <tt>true</tt> enables 350
327the periodic transmission of messages on a connected socket. Should the 351<li> '<tt>reuseaddr</tt>': Setting this option indicates that the rules
328 connected party fail to respond to these messages, the connection is 352used in validating addresses supplied in a call to
329considered broken and processes using the socket are notified. 353<a href=#bind><tt>bind</tt></a> should allow reuse of local addresses;
354
355<li> '<tt>tcp-nodelay</tt>': Setting this option to <tt>true</tt>
356disables the Nagle's algorithm for the connection.
357
330</ul> 358</ul>
331 359
332<p class=return> 360<p class=return>
@@ -382,7 +410,9 @@ indefinitely. Negative timeout values have the same effect.
382Note: although timeout values have millisecond precision in LuaSocket, 410Note: although timeout values have millisecond precision in LuaSocket,
383large blocks can cause I/O functions not to respect timeout values due 411large blocks can cause I/O functions not to respect timeout values due
384to the time the library takes to transfer blocks to and from the OS 412to the time the library takes to transfer blocks to and from the OS
385and to and from the Lua interpreter. 413and to and from the Lua interpreter. Also, function that accept host names
414and perform automatic name resolution might be blocked by the resolver for
415longer than the specified timeout value.
386</p> 416</p>
387 417
388<p class=note> 418<p class=note>
@@ -391,6 +421,30 @@ changed for sake of uniformity, since all other method names already
391contained verbs making their imperative nature obvious. 421contained verbs making their imperative nature obvious.
392</p> 422</p>
393 423
424<!-- shutdown +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
425
426<p class=name id=shutdown>
427client:<b>shutdown(</b>mode<b>)</b><br>
428</p>
429
430<p class=description>
431Shuts down part of a full duplex connection.
432</p>
433
434<p class=parameters>
435Mode tells which way of the connection should be shut down and can
436take the value:
437<ul>
438<li>"<tt>both</tt>": disallow further sends and receives on the object.
439This is the default mode;
440<li>"<tt>send</tt>": disallow further sends on the object;
441<li>"<tt>receive</tt>": disallow further receives on the object.
442</ul>
443
444<p class=return>
445This function returns 1.
446</p>
447
394<!-- footer +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> 448<!-- footer +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
395 449
396<div class=footer> 450<div class=footer>
diff --git a/doc/url.html b/doc/url.html
index 0eafafa..f3a7cb7 100644
--- a/doc/url.html
+++ b/doc/url.html
@@ -241,6 +241,50 @@ returning a list with all the parsed segments, the function unescapes all
241of them. 241of them.
242</p> 242</p>
243 243
244<!-- escape +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
245
246<p class=name id="escape">
247socket.url.<b>escape(</b>content<b>)</b>
248</p>
249
250<p class=description>
251Applies the URL escaping content coding to a string
252Each byte is encoded as a percent character followed
253by the two byte hexadecimal representation of its integer
254value.
255</p>
256
257<p class=parameters>
258<tt>Content</tt> is the string to be encoded.
259</p>
260
261<p class=result>
262The function returns the encoded string.
263</p>
264
265<pre class=example>
266code = socket.url.escape("/#?;")
267-- code = "%2f%23%3f%3b"
268</pre>
269
270<!-- unescape +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
271
272<p class=name id="unescape">
273socket.url.<b>unescape(</b>content<b>)</b>
274</p>
275
276<p class=description>
277Removes the URL escaping content coding from a string.
278</p>
279
280<p class=parameters>
281<tt>Content</tt> is the string to be decoded.
282</p>
283
284<p class=return>
285The function returns the decoded string.
286</p>
287
244<!-- footer +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> 288<!-- footer +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
245 289
246<div class=footer> 290<div class=footer>
diff --git a/etc/qp.lua b/etc/qp.lua
new file mode 100644
index 0000000..23c834a
--- /dev/null
+++ b/etc/qp.lua
@@ -0,0 +1,18 @@
1local convert
2arg = arg or {}
3local mode = arg and arg[1] or "-et"
4if mode == "-et" then
5 local canonic = socket.mime.canonic()
6 local qp = socket.mime.encode("quoted-printable")
7 local wrap = socket.mime.wrap("quoted-printable")
8 convert = socket.mime.chain(canonic, qp, wrap)
9elseif mode == "-eb" then
10 local qp = socket.mime.encode("quoted-printable", "binary")
11 local wrap = socket.mime.wrap("quoted-printable")
12 convert = socket.mime.chain(qp, wrap)
13else convert = socket.mime.decode("quoted-printable") end
14while 1 do
15 local chunk = io.read(4096)
16 io.write(convert(chunk))
17 if not chunk then break end
18end
diff --git a/samples/cddb.lua b/samples/cddb.lua
new file mode 100644
index 0000000..6ade3c0
--- /dev/null
+++ b/samples/cddb.lua
@@ -0,0 +1,43 @@
1if not arg or not arg[1] or not arg[2] then
2 print("luasocket cddb.lua <category> <disc-id> [<server>]")
3 os.exit(1)
4end
5
6local server = arg[3] or "http://freedb.freedb.org/~cddb/cddb.cgi"
7
8function parse(body)
9 local lines = string.gfind(body, "(.-)\r\n")
10 local status = lines()
11 local _, _, code, message = string.find(status, "(%d%d%d) (.*)")
12 if tonumber(code) ~= 210 then
13 return nil, code, message
14 end
15 local data = {}
16 for l in lines do
17 local c = string.sub(l, 1, 1)
18 if c ~= '#' and c ~= '.' then
19 local _, _, key, value = string.find(l, "(.-)=(.*)")
20 value = string.gsub(value, "\\n", "\n")
21 value = string.gsub(value, "\\\\", "\\")
22 value = string.gsub(value, "\\t", "\t")
23 data[key] = value
24 end
25 end
26 return data, code, message
27end
28
29local host = socket.dns.gethostname()
30local query = "%s?cmd=cddb+read+%s+%s&hello=LuaSocket+%s+LuaSocket+2.0&proto=6"
31local url = string.format(query, server, arg[1], arg[2], host)
32local body, headers, code, error = socket.http.get(url)
33
34if code == 200 then
35 local data, code, error = parse(body)
36 if not data then
37 print(error or code)
38 else
39 for i,v in data do
40 io.write(i, ': ', v, '\n')
41 end
42 end
43else print(error) end
diff --git a/src/auxiliar.c b/src/auxiliar.c
index 9a249b6..812d7fc 100644
--- a/src/auxiliar.c
+++ b/src/auxiliar.c
@@ -37,9 +37,9 @@ error:
37/*-------------------------------------------------------------------------*\ 37/*-------------------------------------------------------------------------*\
38* Initializes the module 38* Initializes the module
39\*-------------------------------------------------------------------------*/ 39\*-------------------------------------------------------------------------*/
40void aux_open(lua_State *L) 40int aux_open(lua_State *L)
41{ 41{
42 ; 42 return 0;
43} 43}
44 44
45/*-------------------------------------------------------------------------*\ 45/*-------------------------------------------------------------------------*\
@@ -159,3 +159,13 @@ void *aux_getclassudata(lua_State *L, const char *classname, int objidx)
159 return luaL_checkudata(L, objidx, classname); 159 return luaL_checkudata(L, objidx, classname);
160} 160}
161 161
162/*-------------------------------------------------------------------------*\
163* Accept "false" as nil
164\*-------------------------------------------------------------------------*/
165const char *aux_optlstring(lua_State *L, int n, const char *v, size_t *l)
166{
167 if (lua_isnil(L, n) || (lua_isboolean(L, n) && !lua_toboolean(L, n))) {
168 *l = 0;
169 return NULL;
170 } else return luaL_optlstring(L, n, v, l);
171}
diff --git a/src/auxiliar.h b/src/auxiliar.h
index b98eb9c..ac62ecd 100644
--- a/src/auxiliar.h
+++ b/src/auxiliar.h
@@ -40,7 +40,7 @@
40#define MAX(x, y) ((x) > (y) ? x : y) 40#define MAX(x, y) ((x) > (y) ? x : y)
41#endif 41#endif
42 42
43void aux_open(lua_State *L); 43int aux_open(lua_State *L);
44void aux_newclass(lua_State *L, const char *classname, luaL_reg *func); 44void aux_newclass(lua_State *L, const char *classname, luaL_reg *func);
45void aux_add2group(lua_State *L, const char *classname, const char *group); 45void aux_add2group(lua_State *L, const char *classname, const char *group);
46void aux_setclass(lua_State *L, const char *classname, int objidx); 46void aux_setclass(lua_State *L, const char *classname, int objidx);
@@ -49,5 +49,6 @@ void *aux_checkgroup(lua_State *L, const char *groupname, int objidx);
49void *aux_getclassudata(lua_State *L, const char *groupname, int objidx); 49void *aux_getclassudata(lua_State *L, const char *groupname, int objidx);
50void *aux_getgroupudata(lua_State *L, const char *groupname, int objidx); 50void *aux_getgroupudata(lua_State *L, const char *groupname, int objidx);
51int aux_checkboolean(lua_State *L, int objidx); 51int aux_checkboolean(lua_State *L, int objidx);
52const char *aux_optlstring(lua_State *L, int n, const char *v, size_t *l);
52 53
53#endif /* AUX_H */ 54#endif /* AUX_H */
diff --git a/src/buffer.c b/src/buffer.c
index e6d4ce8..d9ba779 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -26,9 +26,10 @@ static int sendraw(p_buf buf, const char *data, size_t count, size_t *sent);
26/*-------------------------------------------------------------------------*\ 26/*-------------------------------------------------------------------------*\
27* Initializes module 27* Initializes module
28\*-------------------------------------------------------------------------*/ 28\*-------------------------------------------------------------------------*/
29void buf_open(lua_State *L) 29int buf_open(lua_State *L)
30{ 30{
31 (void) L; 31 (void) L;
32 return 0;
32} 33}
33 34
34/*-------------------------------------------------------------------------*\ 35/*-------------------------------------------------------------------------*\
diff --git a/src/buffer.h b/src/buffer.h
index 12b90a0..4b7563f 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -34,7 +34,7 @@ typedef struct t_buf_ {
34} t_buf; 34} t_buf;
35typedef t_buf *p_buf; 35typedef t_buf *p_buf;
36 36
37void buf_open(lua_State *L); 37int buf_open(lua_State *L);
38void buf_init(p_buf buf, p_io io, p_tm tm); 38void buf_init(p_buf buf, p_io io, p_tm tm);
39int buf_meth_send(lua_State *L, p_buf buf); 39int buf_meth_send(lua_State *L, p_buf buf);
40int buf_meth_receive(lua_State *L, p_buf buf); 40int buf_meth_receive(lua_State *L, p_buf buf);
diff --git a/src/ftp.lua b/src/ftp.lua
index bfc4ece..e596416 100644
--- a/src/ftp.lua
+++ b/src/ftp.lua
@@ -649,3 +649,5 @@ function Public.get(url_or_request)
649 local err = Public.get_cb(request) 649 local err = Public.get_cb(request)
650 return concat:getresult(), err 650 return concat:getresult(), err
651end 651end
652
653return ftp
diff --git a/src/http.lua b/src/http.lua
index 4d6e426..74c29ba 100644
--- a/src/http.lua
+++ b/src/http.lua
@@ -11,7 +11,7 @@ if not LUASOCKET_LIBNAME then error('module requires LuaSocket') end
11local socket = _G[LUASOCKET_LIBNAME] 11local socket = _G[LUASOCKET_LIBNAME]
12if not socket then error('module requires LuaSocket') end 12if not socket then error('module requires LuaSocket') end
13-- create smtp namespace inside LuaSocket namespace 13-- create smtp namespace inside LuaSocket namespace
14local http = {} 14local http = socket.http or {}
15socket.http = http 15socket.http = http
16-- make all module globals fall into smtp namespace 16-- make all module globals fall into smtp namespace
17setmetatable(http, { __index = _G }) 17setmetatable(http, { __index = _G })
diff --git a/src/inet.c b/src/inet.c
index d626b86..096e2e3 100644
--- a/src/inet.c
+++ b/src/inet.c
@@ -35,17 +35,10 @@ static luaL_reg func[] = {
35/*-------------------------------------------------------------------------*\ 35/*-------------------------------------------------------------------------*\
36* Initializes module 36* Initializes module
37\*-------------------------------------------------------------------------*/ 37\*-------------------------------------------------------------------------*/
38void inet_open(lua_State *L) 38int inet_open(lua_State *L)
39{ 39{
40 lua_pushstring(L, LUASOCKET_LIBNAME); 40 lua_pushstring(L, LUASOCKET_LIBNAME);
41 lua_gettable(L, LUA_GLOBALSINDEX); 41 lua_gettable(L, LUA_GLOBALSINDEX);
42 if (lua_isnil(L, -1)) {
43 lua_pop(L, 1);
44 lua_newtable(L);
45 lua_pushstring(L, LUASOCKET_LIBNAME);
46 lua_pushvalue(L, -2);
47 lua_settable(L, LUA_GLOBALSINDEX);
48 }
49 lua_pushstring(L, "dns"); 42 lua_pushstring(L, "dns");
50 lua_newtable(L); 43 lua_newtable(L);
51 luaL_openlib(L, NULL, func, 0); 44 luaL_openlib(L, NULL, func, 0);
diff --git a/src/inet.h b/src/inet.h
index 87da23a..92e16f8 100644
--- a/src/inet.h
+++ b/src/inet.h
@@ -24,7 +24,7 @@
24#define INET_ATON 24#define INET_ATON
25#endif 25#endif
26 26
27void inet_open(lua_State *L); 27int inet_open(lua_State *L);
28 28
29const char *inet_trycreate(p_sock ps, int type); 29const char *inet_trycreate(p_sock ps, int type);
30const char *inet_tryconnect(p_sock ps, const char *address, 30const char *inet_tryconnect(p_sock ps, const char *address,
diff --git a/src/luasocket.c b/src/luasocket.c
index bfe71c2..e99fcdf 100644
--- a/src/luasocket.c
+++ b/src/luasocket.c
@@ -33,12 +33,14 @@
33#include "tcp.h" 33#include "tcp.h"
34#include "udp.h" 34#include "udp.h"
35#include "select.h" 35#include "select.h"
36#include "smtp.h"
36#include "mime.h" 37#include "mime.h"
37 38
38/*=========================================================================*\ 39/*=========================================================================*\
39* Declarations 40* Declarations
40\*=========================================================================*/ 41\*=========================================================================*/
41static int base_open(lua_State *L); 42static int base_open(lua_State *L);
43static int mod_open(lua_State *L, const luaL_reg *mod);
42 44
43/*-------------------------------------------------------------------------*\ 45/*-------------------------------------------------------------------------*\
44* Setup basic stuff. 46* Setup basic stuff.
@@ -66,22 +68,9 @@ static int base_open(lua_State *L)
66 return 0; 68 return 0;
67} 69}
68 70
69/*-------------------------------------------------------------------------*\ 71static int mod_open(lua_State *L, const luaL_reg *mod)
70* Initializes all library modules.
71\*-------------------------------------------------------------------------*/
72LUASOCKET_API int luaopen_socket(lua_State *L)
73{ 72{
74 if (!sock_open()) return 0; 73 for (; mod->name; mod++) mod->func(L);
75 /* initialize all modules */
76 base_open(L);
77 aux_open(L);
78 tm_open(L);
79 buf_open(L);
80 inet_open(L);
81 tcp_open(L);
82 udp_open(L);
83 select_open(L);
84 mime_open(L);
85#ifdef LUASOCKET_COMPILED 74#ifdef LUASOCKET_COMPILED
86#include "auxiliar.lch" 75#include "auxiliar.lch"
87#include "concat.lch" 76#include "concat.lch"
@@ -101,5 +90,36 @@ LUASOCKET_API int luaopen_socket(lua_State *L)
101 lua_dofile(L, "ftp.lua"); 90 lua_dofile(L, "ftp.lua");
102 lua_dofile(L, "http.lua"); 91 lua_dofile(L, "http.lua");
103#endif 92#endif
93 return 0;
94}
95
96/*-------------------------------------------------------------------------*\
97* Modules
98\*-------------------------------------------------------------------------*/
99static const luaL_reg mod[] = {
100 {"base", base_open},
101 {"aux", aux_open},
102 {"tm", tm_open},
103 {"buf", buf_open},
104 {"inet", inet_open},
105 {"tcp", tcp_open},
106 {"udp", udp_open},
107 {"select", select_open},
108 {"mime", mime_open},
109 {"smtp", smtp_open},
110 {NULL, NULL}
111};
112
113/*-------------------------------------------------------------------------*\
114* Initializes all library modules.
115\*-------------------------------------------------------------------------*/
116LUASOCKET_API int luaopen_socket(lua_State *L)
117{
118 if (!sock_open()) {
119 lua_pushnil(L);
120 lua_pushstring(L, "unable to initialize library");
121 return 2;
122 }
123 mod_open(L, mod);
104 return 1; 124 return 1;
105} 125}
diff --git a/src/mime.c b/src/mime.c
index 95cd400..9fc4f51 100644
--- a/src/mime.c
+++ b/src/mime.c
@@ -10,6 +10,7 @@
10#include <lauxlib.h> 10#include <lauxlib.h>
11 11
12#include "luasocket.h" 12#include "luasocket.h"
13#include "auxiliar.h"
13#include "mime.h" 14#include "mime.h"
14 15
15/*=========================================================================*\ 16/*=========================================================================*\
@@ -45,18 +46,16 @@ static void qpquote(UC c, luaL_Buffer *buffer);
45static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer); 46static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer);
46static size_t qpencode(UC c, UC *input, size_t size, 47static size_t qpencode(UC c, UC *input, size_t size,
47 const char *marker, luaL_Buffer *buffer); 48 const char *marker, luaL_Buffer *buffer);
48 49static size_t qppad(UC *input, size_t size, luaL_Buffer *buffer);
49static const char *checklstring(lua_State *L, int n, size_t *l);
50static const char *optlstring(lua_State *L, int n, const char *v, size_t *l);
51 50
52/* code support functions */ 51/* code support functions */
53static luaL_reg func[] = { 52static luaL_reg func[] = {
53 { "b64", mime_global_b64 },
54 { "eol", mime_global_eol }, 54 { "eol", mime_global_eol },
55 { "qp", mime_global_qp }, 55 { "qp", mime_global_qp },
56 { "unqp", mime_global_unqp },
57 { "qpwrp", mime_global_qpwrp }, 56 { "qpwrp", mime_global_qpwrp },
58 { "b64", mime_global_b64 },
59 { "unb64", mime_global_unb64 }, 57 { "unb64", mime_global_unb64 },
58 { "unqp", mime_global_unqp },
60 { "wrp", mime_global_wrp }, 59 { "wrp", mime_global_wrp },
61 { NULL, NULL } 60 { NULL, NULL }
62}; 61};
@@ -82,17 +81,10 @@ static UC b64unbase[256];
82/*-------------------------------------------------------------------------*\ 81/*-------------------------------------------------------------------------*\
83* Initializes module 82* Initializes module
84\*-------------------------------------------------------------------------*/ 83\*-------------------------------------------------------------------------*/
85void mime_open(lua_State *L) 84int mime_open(lua_State *L)
86{ 85{
87 lua_pushstring(L, LUASOCKET_LIBNAME); 86 lua_pushstring(L, LUASOCKET_LIBNAME);
88 lua_gettable(L, LUA_GLOBALSINDEX); 87 lua_gettable(L, LUA_GLOBALSINDEX);
89 if (lua_isnil(L, -1)) {
90 lua_pop(L, 1);
91 lua_newtable(L);
92 lua_pushstring(L, LUASOCKET_LIBNAME);
93 lua_pushvalue(L, -2);
94 lua_settable(L, LUA_GLOBALSINDEX);
95 }
96 lua_pushstring(L, "mime"); 88 lua_pushstring(L, "mime");
97 lua_newtable(L); 89 lua_newtable(L);
98 luaL_openlib(L, NULL, func, 0); 90 luaL_openlib(L, NULL, func, 0);
@@ -101,25 +93,7 @@ void mime_open(lua_State *L)
101 /* initialize lookup tables */ 93 /* initialize lookup tables */
102 qpsetup(qpclass, qpunbase); 94 qpsetup(qpclass, qpunbase);
103 b64setup(b64unbase); 95 b64setup(b64unbase);
104} 96 return 0;
105
106/*-------------------------------------------------------------------------*\
107* Check if a string was provided. We accept false also.
108\*-------------------------------------------------------------------------*/
109static const char *checklstring(lua_State *L, int n, size_t *l)
110{
111 if (lua_isnil(L, n) || (lua_isboolean(L, n) && !lua_toboolean(L, n))) {
112 *l = 0;
113 return NULL;
114 } else return luaL_checklstring(L, n, l);
115}
116
117static const char *optlstring(lua_State *L, int n, const char *v, size_t *l)
118{
119 if (lua_isnil(L, n) || (lua_isboolean(L, n) && !lua_toboolean(L, n))) {
120 *l = 0;
121 return NULL;
122 } else return luaL_optlstring(L, n, v, l);
123} 97}
124 98
125/*=========================================================================*\ 99/*=========================================================================*\
@@ -127,31 +101,42 @@ static const char *optlstring(lua_State *L, int n, const char *v, size_t *l)
127\*=========================================================================*/ 101\*=========================================================================*/
128/*-------------------------------------------------------------------------*\ 102/*-------------------------------------------------------------------------*\
129* Incrementaly breaks a string into lines 103* Incrementaly breaks a string into lines
130* A, n = wrp(l, B, length, marker) 104* A, n = wrp(l, B, length)
131* A is a copy of B, broken into lines of at most 'length' bytes. 105* A is a copy of B, broken into lines of at most 'length' bytes.
132* 'l' is how many bytes are left for the first line of B. 106* 'l' is how many bytes are left for the first line of B.
133* 'n' is the number of bytes left in the last line of A. 107* 'n' is the number of bytes left in the last line of A.
134* Marker is the end-of-line marker.
135\*-------------------------------------------------------------------------*/ 108\*-------------------------------------------------------------------------*/
136static int mime_global_wrp(lua_State *L) 109static int mime_global_wrp(lua_State *L)
137{ 110{
138 size_t size = 0; 111 size_t size = 0;
139 int left = (int) luaL_checknumber(L, 1); 112 int left = (int) luaL_checknumber(L, 1);
140 const UC *input = (UC *) checklstring(L, 2, &size); 113 const UC *input = (UC *) aux_optlstring(L, 2, NULL, &size);
141 const UC *last = input + size; 114 const UC *last = input + size;
142 int length = (int) luaL_optnumber(L, 3, 76); 115 int length = (int) luaL_optnumber(L, 3, 76);
143 const char *marker = luaL_optstring(L, 4, CRLF);
144 luaL_Buffer buffer; 116 luaL_Buffer buffer;
145 luaL_buffinit(L, &buffer); 117 luaL_buffinit(L, &buffer);
146 while (input < last) { 118 while (input < last) {
147 luaL_putchar(&buffer, *input++); 119 switch (*input) {
148 if (--left <= 0) { 120 case CR:
149 luaL_addstring(&buffer, marker); 121 break;
150 left = length; 122 case LF:
123 luaL_addstring(&buffer, CRLF);
124 left = length;
125 break;
126 default:
127 if (left <= 0) {
128 left = length;
129 luaL_addstring(&buffer, CRLF);
130 }
131 luaL_putchar(&buffer, *input);
132 left--;
133 break;
151 } 134 }
135 input++;
152 } 136 }
137 /* if in last chunk and last line wasn't terminated, add a line-break */
153 if (!input && left < length) { 138 if (!input && left < length) {
154 luaL_addstring(&buffer, marker); 139 luaL_addstring(&buffer, CRLF);
155 left = length; 140 left = length;
156 } 141 }
157 luaL_pushresult(&buffer); 142 luaL_pushresult(&buffer);
@@ -235,7 +220,6 @@ static size_t b64pad(const UC *input, size_t size,
235static size_t b64decode(UC c, UC *input, size_t size, 220static size_t b64decode(UC c, UC *input, size_t size,
236 luaL_Buffer *buffer) 221 luaL_Buffer *buffer)
237{ 222{
238
239 /* ignore invalid characters */ 223 /* ignore invalid characters */
240 if (b64unbase[c] > 64) return size; 224 if (b64unbase[c] > 64) return size;
241 input[size++] = c; 225 input[size++] = c;
@@ -277,7 +261,7 @@ static int mime_global_b64(lua_State *L)
277 luaL_buffinit(L, &buffer); 261 luaL_buffinit(L, &buffer);
278 while (input < last) 262 while (input < last)
279 asize = b64encode(*input++, atom, asize, &buffer); 263 asize = b64encode(*input++, atom, asize, &buffer);
280 input = (UC *) optlstring(L, 2, NULL, &isize); 264 input = (UC *) aux_optlstring(L, 2, NULL, &isize);
281 if (input) { 265 if (input) {
282 last = input + isize; 266 last = input + isize;
283 while (input < last) 267 while (input < last)
@@ -305,12 +289,14 @@ static int mime_global_unb64(lua_State *L)
305 luaL_buffinit(L, &buffer); 289 luaL_buffinit(L, &buffer);
306 while (input < last) 290 while (input < last)
307 asize = b64decode(*input++, atom, asize, &buffer); 291 asize = b64decode(*input++, atom, asize, &buffer);
308 input = (UC *) optlstring(L, 2, NULL, &isize); 292 input = (UC *) aux_optlstring(L, 2, NULL, &isize);
309 if (input) { 293 if (input) {
310 last = input + isize; 294 last = input + isize;
311 while (input < last) 295 while (input < last)
312 asize = b64decode(*input++, atom, asize, &buffer); 296 asize = b64decode(*input++, atom, asize, &buffer);
313 } 297 }
298 /* if !input we are done. if atom > 0, the remaning is invalid. we just
299 * return it undecoded. */
314 luaL_pushresult(&buffer); 300 luaL_pushresult(&buffer);
315 lua_pushlstring(L, (char *) atom, asize); 301 lua_pushlstring(L, (char *) atom, asize);
316 return 2; 302 return 2;
@@ -416,7 +402,7 @@ static size_t qpencode(UC c, UC *input, size_t size,
416/*-------------------------------------------------------------------------*\ 402/*-------------------------------------------------------------------------*\
417* Deal with the final characters 403* Deal with the final characters
418\*-------------------------------------------------------------------------*/ 404\*-------------------------------------------------------------------------*/
419static void qppad(UC *input, size_t size, luaL_Buffer *buffer) 405static size_t qppad(UC *input, size_t size, luaL_Buffer *buffer)
420{ 406{
421 size_t i; 407 size_t i;
422 for (i = 0; i < size; i++) { 408 for (i = 0; i < size; i++) {
@@ -424,12 +410,13 @@ static void qppad(UC *input, size_t size, luaL_Buffer *buffer)
424 else qpquote(input[i], buffer); 410 else qpquote(input[i], buffer);
425 } 411 }
426 luaL_addstring(buffer, EQCRLF); 412 luaL_addstring(buffer, EQCRLF);
413 return 0;
427} 414}
428 415
429/*-------------------------------------------------------------------------*\ 416/*-------------------------------------------------------------------------*\
430* Incrementally converts a string to quoted-printable 417* Incrementally converts a string to quoted-printable
431* A, B = qp(C, D, marker) 418* A, B = qp(C, D, marker)
432* Crlf is the text to be used to replace CRLF sequences found in A. 419* Marker is the text to be used to replace CRLF sequences found in A.
433* A is the encoded version of the largest prefix of C .. D that 420* A is the encoded version of the largest prefix of C .. D that
434* can be encoded without doubts. 421* can be encoded without doubts.
435* B has the remaining bytes of C .. D, *without* encoding. 422* B has the remaining bytes of C .. D, *without* encoding.
@@ -439,19 +426,20 @@ static int mime_global_qp(lua_State *L)
439 426
440 size_t asize = 0, isize = 0; 427 size_t asize = 0, isize = 0;
441 UC atom[3]; 428 UC atom[3];
442 const UC *input = (UC *) checklstring(L, 1, &isize); 429 const UC *input = (UC *) aux_optlstring(L, 1, NULL, &isize);
443 const UC *last = input + isize; 430 const UC *last = input + isize;
444 const char *marker = luaL_optstring(L, 3, CRLF); 431 const char *marker = luaL_optstring(L, 3, CRLF);
445 luaL_Buffer buffer; 432 luaL_Buffer buffer;
446 luaL_buffinit(L, &buffer); 433 luaL_buffinit(L, &buffer);
447 while (input < last) 434 while (input < last)
448 asize = qpencode(*input++, atom, asize, marker, &buffer); 435 asize = qpencode(*input++, atom, asize, marker, &buffer);
449 input = (UC *) optlstring(L, 2, NULL, &isize); 436 input = (UC *) aux_optlstring(L, 2, NULL, &isize);
450 if (input) { 437 if (input) {
451 last = input + isize; 438 last = input + isize;
452 while (input < last) 439 while (input < last)
453 asize = qpencode(*input++, atom, asize, marker, &buffer); 440 asize = qpencode(*input++, atom, asize, marker, &buffer);
454 } else qppad(atom, asize, &buffer); 441 } else
442 asize = qppad(atom, asize, &buffer);
455 luaL_pushresult(&buffer); 443 luaL_pushresult(&buffer);
456 lua_pushlstring(L, (char *) atom, asize); 444 lua_pushlstring(L, (char *) atom, asize);
457 return 2; 445 return 2;
@@ -507,13 +495,13 @@ static int mime_global_unqp(lua_State *L)
507 495
508 size_t asize = 0, isize = 0; 496 size_t asize = 0, isize = 0;
509 UC atom[3]; 497 UC atom[3];
510 const UC *input = (UC *) checklstring(L, 1, &isize); 498 const UC *input = (UC *) aux_optlstring(L, 1, NULL, &isize);
511 const UC *last = input + isize; 499 const UC *last = input + isize;
512 luaL_Buffer buffer; 500 luaL_Buffer buffer;
513 luaL_buffinit(L, &buffer); 501 luaL_buffinit(L, &buffer);
514 while (input < last) 502 while (input < last)
515 asize = qpdecode(*input++, atom, asize, &buffer); 503 asize = qpdecode(*input++, atom, asize, &buffer);
516 input = (UC *) optlstring(L, 2, NULL, &isize); 504 input = (UC *) aux_optlstring(L, 2, NULL, &isize);
517 if (input) { 505 if (input) {
518 last = input + isize; 506 last = input + isize;
519 while (input < last) 507 while (input < last)
@@ -537,38 +525,39 @@ static int mime_global_qpwrp(lua_State *L)
537{ 525{
538 size_t size = 0; 526 size_t size = 0;
539 int left = (int) luaL_checknumber(L, 1); 527 int left = (int) luaL_checknumber(L, 1);
540 const UC *input = (UC *) checklstring(L, 2, &size); 528 const UC *input = (UC *) aux_optlstring(L, 2, NULL, &size);
541 const UC *last = input + size; 529 const UC *last = input + size;
542 int length = (int) luaL_optnumber(L, 3, 76); 530 int length = (int) luaL_optnumber(L, 3, 76);
543 luaL_Buffer buffer; 531 luaL_Buffer buffer;
544 luaL_buffinit(L, &buffer); 532 luaL_buffinit(L, &buffer);
545 while (input < last) { 533 while (input < last) {
546 left--;
547 switch (*input) { 534 switch (*input) {
548 case '=': 535 case CR:
549 /* if there's no room in this line for the quoted char,
550 * output a soft line break now */
551 if (left <= 3) {
552 luaL_addstring(&buffer, EQCRLF);
553 left = length;
554 }
555 break;
556 /* \r\n starts a new line */
557 case CR:
558 break; 536 break;
559 case LF: 537 case LF:
560 left = length; 538 left = length;
539 luaL_addstring(&buffer, CRLF);
561 break; 540 break;
562 default: 541 case '=':
563 /* if in last column, output a soft line break */ 542 if (left <= 3) {
564 if (left <= 1) { 543 left = length;
565 luaL_addstring(&buffer, EQCRLF); 544 luaL_addstring(&buffer, EQCRLF);
545 }
546 luaL_putchar(&buffer, *input);
547 left--;
548 break;
549 default:
550 if (left <= 1) {
566 left = length; 551 left = length;
552 luaL_addstring(&buffer, EQCRLF);
567 } 553 }
554 luaL_putchar(&buffer, *input);
555 left--;
556 break;
568 } 557 }
569 luaL_putchar(&buffer, *input);
570 input++; 558 input++;
571 } 559 }
560 /* if in last chunk and last line wasn't terminated, add a soft-break */
572 if (!input && left < length) { 561 if (!input && left < length) {
573 luaL_addstring(&buffer, EQCRLF); 562 luaL_addstring(&buffer, EQCRLF);
574 left = length; 563 left = length;
@@ -579,10 +568,10 @@ static int mime_global_qpwrp(lua_State *L)
579} 568}
580 569
581/*-------------------------------------------------------------------------*\ 570/*-------------------------------------------------------------------------*\
582* Here is what we do: \n, \r and \f are considered candidates for line 571* Here is what we do: \n, and \r are considered candidates for line
583* break. We issue *one* new line marker if any of them is seen alone, or 572* break. We issue *one* new line marker if any of them is seen alone, or
584* followed by a different one. That is, \n\n, \r\r and \f\f will issue two 573* followed by a different one. That is, \n\n and \r\r will issue two
585* end of line markers each, but \r\n, \n\r, \r\f etc will only issue *one* 574* end of line markers each, but \r\n, \n\r etc will only issue *one*
586* marker. This covers Mac OS, Mac OS X, VMS, Unix and DOS, as well as 575* marker. This covers Mac OS, Mac OS X, VMS, Unix and DOS, as well as
587* probably other more obscure conventions. 576* probably other more obscure conventions.
588\*-------------------------------------------------------------------------*/ 577\*-------------------------------------------------------------------------*/
@@ -616,21 +605,24 @@ static int mime_global_eol(lua_State *L)
616{ 605{
617 size_t asize = 0, isize = 0; 606 size_t asize = 0, isize = 0;
618 UC atom[2]; 607 UC atom[2];
619 const UC *input = (UC *) checklstring(L, 1, &isize); 608 const UC *input = (UC *) aux_optlstring(L, 1, NULL, &isize);
620 const UC *last = input + isize; 609 const UC *last = input + isize;
621 const char *marker = luaL_optstring(L, 3, CRLF); 610 const char *marker = luaL_optstring(L, 3, CRLF);
622 luaL_Buffer buffer; 611 luaL_Buffer buffer;
623 luaL_buffinit(L, &buffer); 612 luaL_buffinit(L, &buffer);
624 while (input < last) 613 while (input < last)
625 asize = eolconvert(*input++, atom, asize, marker, &buffer); 614 asize = eolconvert(*input++, atom, asize, marker, &buffer);
626 input = (UC *) optlstring(L, 2, NULL, &isize); 615 input = (UC *) aux_optlstring(L, 2, NULL, &isize);
627 if (input) { 616 if (input) {
628 last = input + isize; 617 last = input + isize;
629 while (input < last) 618 while (input < last)
630 asize = eolconvert(*input++, atom, asize, marker, &buffer); 619 asize = eolconvert(*input++, atom, asize, marker, &buffer);
631 /* if there is something in atom, it's one character, and it 620 /* if there is something in atom, it's one character, and it
632 * is a candidate. so we output a new line */ 621 * is a candidate. so we output a new line */
633 } else if (asize > 0) luaL_addstring(&buffer, marker); 622 } else if (asize > 0) {
623 luaL_addstring(&buffer, marker);
624 asize = 0;
625 }
634 luaL_pushresult(&buffer); 626 luaL_pushresult(&buffer);
635 lua_pushlstring(L, (char *) atom, asize); 627 lua_pushlstring(L, (char *) atom, asize);
636 return 2; 628 return 2;
diff --git a/src/mime.h b/src/mime.h
index 8323783..b91f735 100644
--- a/src/mime.h
+++ b/src/mime.h
@@ -12,6 +12,6 @@
12\*=========================================================================*/ 12\*=========================================================================*/
13#include <lua.h> 13#include <lua.h>
14 14
15void mime_open(lua_State *L); 15int mime_open(lua_State *L);
16 16
17#endif /* MIME_H */ 17#endif /* MIME_H */
diff --git a/src/mime.lua b/src/mime.lua
index 30c6b38..369567f 100644
--- a/src/mime.lua
+++ b/src/mime.lua
@@ -15,70 +15,57 @@ local et = {}
15local dt = {} 15local dt = {}
16local wt = {} 16local wt = {}
17 17
18-- creates a function that chooses an algorithm from a given table 18-- creates a function that chooses a filter from a given table
19local function choose(table) 19local function choose(table)
20 return function(method, ...) 20 return function(filter, ...)
21 local f = table[method or "nil"] 21 local f = table[filter or "nil"]
22 if not f then error("unknown method (" .. tostring(method) .. ")", 3) 22 if not f then error("unknown filter (" .. tostring(filter) .. ")", 3)
23 else return f(unpack(arg)) end 23 else return f(unpack(arg)) end
24 end 24 end
25end 25end
26 26
27-- creates a function that cicles a filter with a given initial 27-- define the encoding filters
28-- context and extra arguments
29local function cicle(f, ctx, ...)
30 return function(chunk)
31 local ret
32 ret, ctx = f(ctx, chunk, unpack(arg))
33 return ret
34 end
35end
36
37-- function that choose the encoding, decoding or wrap algorithm
38encode = choose(et)
39decode = choose(dt)
40
41-- the wrap filter has default parameters
42local cwt = choose(wt)
43function wrap(...)
44 if not arg[1] or type(arg[1]) ~= "string" then
45 table.insert(arg, 1, "base64")
46 end
47 return cwt(unpack(arg))
48end
49
50-- define the encoding algorithms
51et['base64'] = function() 28et['base64'] = function()
52 return cicle(b64, "") 29 return socket.cicle(b64, "")
53end 30end
54 31
55et['quoted-printable'] = function(mode) 32et['quoted-printable'] = function(mode)
56 return cicle(qp, "", (mode == "binary") and "=0D=0A" or "\13\10") 33 return socket.cicle(qp, "", (mode == "binary") and "=0D=0A" or "\13\10")
57end 34end
58 35
59-- define the decoding algorithms 36-- define the decoding filters
60dt['base64'] = function() 37dt['base64'] = function()
61 return cicle(unb64, "") 38 return socket.cicle(unb64, "")
62end 39end
63 40
64dt['quoted-printable'] = function() 41dt['quoted-printable'] = function()
65 return cicle(unqp, "") 42 return socket.cicle(unqp, "")
66end 43end
67 44
68-- define the wrap algorithms 45-- define the line-wrap filters
69wt['base64'] = function(length, marker) 46wt['text'] = function(length)
70 length = length or 76 47 length = length or 76
71 return cicle(wrp, length, length, marker) 48 return socket.cicle(wrp, length, length)
72end 49end
50wt['base64'] = wt['text']
73 51
74wt['quoted-printable'] = function(length) 52wt['quoted-printable'] = function()
75 length = length or 76 53 return socket.cicle(qpwrp, 76, 76)
76 return cicle(qpwrp, length, length) 54end
55
56-- function that choose the encoding, decoding or wrap algorithm
57encode = choose(et)
58decode = choose(dt)
59-- there is a default wrap filter
60local cwt = choose(wt)
61function wrap(...)
62 if type(arg[1]) ~= "string" then table.insert(arg, 1, "text") end
63 return cwt(unpack(arg))
77end 64end
78 65
79-- define the end-of-line translation function 66-- define the end-of-line translation filter
80function canonic(marker) 67function canonic(marker)
81 return cicle(eol, "", marker) 68 return socket.cicle(eol, "", marker)
82end 69end
83 70
84-- chains several filters together 71-- chains several filters together
@@ -104,4 +91,4 @@ function chain(...)
104 end 91 end
105end 92end
106 93
107return code 94return mime
diff --git a/src/select.c b/src/select.c
index 9769667..8590b96 100644
--- a/src/select.c
+++ b/src/select.c
@@ -42,7 +42,7 @@ static luaL_reg func[] = {
42/*-------------------------------------------------------------------------*\ 42/*-------------------------------------------------------------------------*\
43* Initializes module 43* Initializes module
44\*-------------------------------------------------------------------------*/ 44\*-------------------------------------------------------------------------*/
45void select_open(lua_State *L) 45int select_open(lua_State *L)
46{ 46{
47 /* get select auxiliar lua function from lua code and register 47 /* get select auxiliar lua function from lua code and register
48 * pass it as an upvalue to global_select */ 48 * pass it as an upvalue to global_select */
@@ -54,6 +54,7 @@ void select_open(lua_State *L)
54 luaL_openlib(L, LUASOCKET_LIBNAME, func, 1); 54 luaL_openlib(L, LUASOCKET_LIBNAME, func, 1);
55 lua_pop(L, 1); 55 lua_pop(L, 1);
56 aux_newclass(L, "select{fd_set}", set); 56 aux_newclass(L, "select{fd_set}", set);
57 return 0;
57} 58}
58 59
59/*=========================================================================*\ 60/*=========================================================================*\
diff --git a/src/select.h b/src/select.h
index 0e1eeb4..de10ea4 100644
--- a/src/select.h
+++ b/src/select.h
@@ -15,6 +15,6 @@
15* RCS ID: $Id$ 15* RCS ID: $Id$
16\*=========================================================================*/ 16\*=========================================================================*/
17 17
18void select_open(lua_State *L); 18int select_open(lua_State *L);
19 19
20#endif /* SELECT_H */ 20#endif /* SELECT_H */
diff --git a/src/smtp.lua b/src/smtp.lua
index 25d7f74..8b65e44 100644
--- a/src/smtp.lua
+++ b/src/smtp.lua
@@ -4,7 +4,7 @@ if not LUASOCKET_LIBNAME then error('module requires LuaSocket') end
4local socket = _G[LUASOCKET_LIBNAME] 4local socket = _G[LUASOCKET_LIBNAME]
5if not socket then error('module requires LuaSocket') end 5if not socket then error('module requires LuaSocket') end
6-- create smtp namespace inside LuaSocket namespace 6-- create smtp namespace inside LuaSocket namespace
7local smtp = {} 7local smtp = socket.smtp or {}
8socket.smtp = smtp 8socket.smtp = smtp
9-- make all module globals fall into smtp namespace 9-- make all module globals fall into smtp namespace
10setmetatable(smtp, { __index = _G }) 10setmetatable(smtp, { __index = _G })
@@ -18,6 +18,10 @@ DOMAIN = os.getenv("SERVER_NAME") or "localhost"
18-- default server used to send e-mails 18-- default server used to send e-mails
19SERVER = "localhost" 19SERVER = "localhost"
20 20
21function stuff()
22 return socket.cicle(dot, 2)
23end
24
21-- tries to get a pattern from the server and closes socket on error 25-- tries to get a pattern from the server and closes socket on error
22local function try_receiving(connection, pattern) 26local function try_receiving(connection, pattern)
23 local data, message = connection:receive(pattern) 27 local data, message = connection:receive(pattern)
diff --git a/src/tcp.c b/src/tcp.c
index 4b3b0cc..46efac2 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -39,25 +39,26 @@ static int meth_dirty(lua_State *L);
39 39
40/* tcp object methods */ 40/* tcp object methods */
41static luaL_reg tcp[] = { 41static luaL_reg tcp[] = {
42 {"connect", meth_connect}, 42 {"__gc", meth_close},
43 {"send", meth_send}, 43 {"accept", meth_accept},
44 {"receive", meth_receive},
45 {"bind", meth_bind}, 44 {"bind", meth_bind},
45 {"close", meth_close},
46 {"connect", meth_connect},
47 {"dirty", meth_dirty},
48 {"getfd", meth_getfd},
49 {"getpeername", meth_getpeername},
50 {"getsockname", meth_getsockname},
46 {"listen", meth_listen}, 51 {"listen", meth_listen},
47 {"accept", meth_accept}, 52 {"receive", meth_receive},
53 {"send", meth_send},
54 {"setfd", meth_setfd},
55 {"setoption", meth_setoption},
48 {"setpeername", meth_connect}, 56 {"setpeername", meth_connect},
49 {"setsockname", meth_bind}, 57 {"setsockname", meth_bind},
50 {"getpeername", meth_getpeername},
51 {"getsockname", meth_getsockname},
52 {"settimeout", meth_settimeout}, 58 {"settimeout", meth_settimeout},
53 {"close", meth_close},
54 {"shutdown", meth_shutdown}, 59 {"shutdown", meth_shutdown},
55 {"setoption", meth_setoption},
56 {"__gc", meth_close},
57 {"getfd", meth_getfd},
58 {"setfd", meth_setfd},
59 {"dirty", meth_dirty},
60 {NULL, NULL} 60 {NULL, NULL}
61
61}; 62};
62 63
63/* socket option handlers */ 64/* socket option handlers */
@@ -78,7 +79,7 @@ static luaL_reg func[] = {
78/*-------------------------------------------------------------------------*\ 79/*-------------------------------------------------------------------------*\
79* Initializes module 80* Initializes module
80\*-------------------------------------------------------------------------*/ 81\*-------------------------------------------------------------------------*/
81void tcp_open(lua_State *L) 82int tcp_open(lua_State *L)
82{ 83{
83 /* create classes */ 84 /* create classes */
84 aux_newclass(L, "tcp{master}", tcp); 85 aux_newclass(L, "tcp{master}", tcp);
@@ -96,6 +97,7 @@ void tcp_open(lua_State *L)
96 /* define library functions */ 97 /* define library functions */
97 luaL_openlib(L, LUASOCKET_LIBNAME, func, 0); 98 luaL_openlib(L, LUASOCKET_LIBNAME, func, 0);
98 lua_pop(L, 1); 99 lua_pop(L, 1);
100 return 0;
99} 101}
100 102
101/*=========================================================================*\ 103/*=========================================================================*\
@@ -250,7 +252,7 @@ static int meth_listen(lua_State *L)
250\*-------------------------------------------------------------------------*/ 252\*-------------------------------------------------------------------------*/
251static int meth_shutdown(lua_State *L) 253static int meth_shutdown(lua_State *L)
252{ 254{
253 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1); 255 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client}", 1);
254 const char *how = luaL_optstring(L, 2, "both"); 256 const char *how = luaL_optstring(L, 2, "both");
255 switch (how[0]) { 257 switch (how[0]) {
256 case 'b': 258 case 'b':
@@ -266,7 +268,8 @@ static int meth_shutdown(lua_State *L)
266 sock_shutdown(&tcp->sock, 0); 268 sock_shutdown(&tcp->sock, 0);
267 break; 269 break;
268 } 270 }
269 return 0; 271 lua_pushnumber(L, 1);
272 return 1;
270error: 273error:
271 luaL_argerror(L, 2, "invalid shutdown method"); 274 luaL_argerror(L, 2, "invalid shutdown method");
272 return 0; 275 return 0;
diff --git a/src/tcp.h b/src/tcp.h
index ae99b8c..708023e 100644
--- a/src/tcp.h
+++ b/src/tcp.h
@@ -31,6 +31,6 @@ typedef struct t_tcp_ {
31 31
32typedef t_tcp *p_tcp; 32typedef t_tcp *p_tcp;
33 33
34void tcp_open(lua_State *L); 34int tcp_open(lua_State *L);
35 35
36#endif /* TCP_H */ 36#endif /* TCP_H */
diff --git a/src/timeout.c b/src/timeout.c
index 83bffc9..73a1146 100644
--- a/src/timeout.c
+++ b/src/timeout.c
@@ -141,10 +141,11 @@ int tm_gettime(void)
141/*-------------------------------------------------------------------------*\ 141/*-------------------------------------------------------------------------*\
142* Initializes module 142* Initializes module
143\*-------------------------------------------------------------------------*/ 143\*-------------------------------------------------------------------------*/
144void tm_open(lua_State *L) 144int tm_open(lua_State *L)
145{ 145{
146 luaL_openlib(L, LUASOCKET_LIBNAME, func, 0); 146 luaL_openlib(L, LUASOCKET_LIBNAME, func, 0);
147 lua_pop(L, 1); 147 lua_pop(L, 1);
148 return 0;
148} 149}
149 150
150/*-------------------------------------------------------------------------*\ 151/*-------------------------------------------------------------------------*\
diff --git a/src/timeout.h b/src/timeout.h
index 6584a8e..6b105c3 100644
--- a/src/timeout.h
+++ b/src/timeout.h
@@ -16,7 +16,7 @@ typedef struct t_tm_ {
16} t_tm; 16} t_tm;
17typedef t_tm *p_tm; 17typedef t_tm *p_tm;
18 18
19void tm_open(lua_State *L); 19int tm_open(lua_State *L);
20void tm_init(p_tm tm, int block, int total); 20void tm_init(p_tm tm, int block, int total);
21int tm_get(p_tm tm); 21int tm_get(p_tm tm);
22int tm_getretry(p_tm tm); 22int tm_getretry(p_tm tm);
diff --git a/src/udp.c b/src/udp.c
index 14029f9..a0fdcc0 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -30,7 +30,6 @@ static int meth_getpeername(lua_State *L);
30static int meth_setsockname(lua_State *L); 30static int meth_setsockname(lua_State *L);
31static int meth_setpeername(lua_State *L); 31static int meth_setpeername(lua_State *L);
32static int meth_close(lua_State *L); 32static int meth_close(lua_State *L);
33static int meth_shutdown(lua_State *L);
34static int meth_setoption(lua_State *L); 33static int meth_setoption(lua_State *L);
35static int meth_settimeout(lua_State *L); 34static int meth_settimeout(lua_State *L);
36static int meth_getfd(lua_State *L); 35static int meth_getfd(lua_State *L);
@@ -49,7 +48,6 @@ static luaL_reg udp[] = {
49 {"receivefrom", meth_receivefrom}, 48 {"receivefrom", meth_receivefrom},
50 {"settimeout", meth_settimeout}, 49 {"settimeout", meth_settimeout},
51 {"close", meth_close}, 50 {"close", meth_close},
52 {"shutdown", meth_shutdown},
53 {"setoption", meth_setoption}, 51 {"setoption", meth_setoption},
54 {"__gc", meth_close}, 52 {"__gc", meth_close},
55 {"getfd", meth_getfd}, 53 {"getfd", meth_getfd},
@@ -79,7 +77,7 @@ static luaL_reg func[] = {
79/*-------------------------------------------------------------------------*\ 77/*-------------------------------------------------------------------------*\
80* Initializes module 78* Initializes module
81\*-------------------------------------------------------------------------*/ 79\*-------------------------------------------------------------------------*/
82void udp_open(lua_State *L) 80int udp_open(lua_State *L)
83{ 81{
84 /* create classes */ 82 /* create classes */
85 aux_newclass(L, "udp{connected}", udp); 83 aux_newclass(L, "udp{connected}", udp);
@@ -92,6 +90,7 @@ void udp_open(lua_State *L)
92 /* define library functions */ 90 /* define library functions */
93 luaL_openlib(L, LUASOCKET_LIBNAME, func, 0); 91 luaL_openlib(L, LUASOCKET_LIBNAME, func, 0);
94 lua_pop(L, 1); 92 lua_pop(L, 1);
93 return 0;
95} 94}
96 95
97/*=========================================================================*\ 96/*=========================================================================*\
@@ -288,33 +287,6 @@ static int meth_close(lua_State *L)
288} 287}
289 288
290/*-------------------------------------------------------------------------*\ 289/*-------------------------------------------------------------------------*\
291* Shuts the connection down partially
292\*-------------------------------------------------------------------------*/
293static int meth_shutdown(lua_State *L)
294{
295 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
296 const char *how = luaL_optstring(L, 2, "both");
297 switch (how[0]) {
298 case 'b':
299 if (strcmp(how, "both")) goto error;
300 sock_shutdown(&udp->sock, 2);
301 break;
302 case 's':
303 if (strcmp(how, "send")) goto error;
304 sock_shutdown(&udp->sock, 1);
305 break;
306 case 'r':
307 if (strcmp(how, "receive")) goto error;
308 sock_shutdown(&udp->sock, 0);
309 break;
310 }
311 return 0;
312error:
313 luaL_argerror(L, 2, "invalid shutdown method");
314 return 0;
315}
316
317/*-------------------------------------------------------------------------*\
318* Turns a master object into a server object 290* Turns a master object into a server object
319\*-------------------------------------------------------------------------*/ 291\*-------------------------------------------------------------------------*/
320static int meth_setsockname(lua_State *L) 292static int meth_setsockname(lua_State *L)
diff --git a/src/udp.h b/src/udp.h
index 699e31a..0d8e5f4 100644
--- a/src/udp.h
+++ b/src/udp.h
@@ -27,6 +27,6 @@ typedef struct t_udp_ {
27} t_udp; 27} t_udp;
28typedef t_udp *p_udp; 28typedef t_udp *p_udp;
29 29
30void udp_open(lua_State *L); 30int udp_open(lua_State *L);
31 31
32#endif /* UDP_H */ 32#endif /* UDP_H */
diff --git a/src/url.lua b/src/url.lua
index ab3a922..de0474b 100644
--- a/src/url.lua
+++ b/src/url.lua
@@ -12,7 +12,7 @@ if not LUASOCKET_LIBNAME then error('module requires LuaSocket') end
12local socket = _G[LUASOCKET_LIBNAME] 12local socket = _G[LUASOCKET_LIBNAME]
13if not socket then error('module requires LuaSocket') end 13if not socket then error('module requires LuaSocket') end
14-- create smtp namespace inside LuaSocket namespace 14-- create smtp namespace inside LuaSocket namespace
15local url = {} 15local url = socket.url or {}
16socket.url = url 16socket.url = url
17-- make all module globals fall into smtp namespace 17-- make all module globals fall into smtp namespace
18setmetatable(url, { __index = _G }) 18setmetatable(url, { __index = _G })
diff --git a/src/usocket.c b/src/usocket.c
index bece354..eb1a49a 100644
--- a/src/usocket.c
+++ b/src/usocket.c
@@ -70,12 +70,10 @@ int sock_select(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, int timeout)
70\*-------------------------------------------------------------------------*/ 70\*-------------------------------------------------------------------------*/
71const char *sock_create(p_sock ps, int domain, int type, int protocol) 71const char *sock_create(p_sock ps, int domain, int type, int protocol)
72{ 72{
73 int val = 1;
74 t_sock sock = socket(domain, type, protocol); 73 t_sock sock = socket(domain, type, protocol);
75 if (sock == SOCK_INVALID) return sock_createstrerror(errno); 74 if (sock == SOCK_INVALID) return sock_createstrerror(errno);
76 *ps = sock; 75 *ps = sock;
77 sock_setnonblocking(ps); 76 sock_setnonblocking(ps);
78 setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof(val));
79 return NULL; 77 return NULL;
80} 78}
81 79
@@ -167,13 +165,14 @@ const char *sock_accept(p_sock ps, p_sock pa, SA *addr,
167 for (;;) { 165 for (;;) {
168 int err; 166 int err;
169 fd_set fds; 167 fd_set fds;
168 /* try to accept */
170 *pa = accept(sock, addr, addr_len); 169 *pa = accept(sock, addr, addr_len);
171 /* if result is valid, we are done */ 170 /* if result is valid, we are done */
172 if (*pa != SOCK_INVALID) return NULL; 171 if (*pa != SOCK_INVALID) return NULL;
173 /* find out if we failed for a fatal reason */ 172 /* find out if we failed for a fatal reason */
174 if (errno != EWOULDBLOCK && errno != ECONNABORTED) 173 if (errno != EWOULDBLOCK && errno != ECONNABORTED)
175 return sock_acceptstrerror(errno); 174 return sock_acceptstrerror(errno);
176 /* call select just to avoid busy-wait. */ 175 /* call select to avoid busy-wait. */
177 FD_ZERO(&fds); 176 FD_ZERO(&fds);
178 FD_SET(sock, &fds); 177 FD_SET(sock, &fds);
179 do err = sock_select(sock+1, &fds, NULL, NULL, tm_getretry(tm)); 178 do err = sock_select(sock+1, &fds, NULL, NULL, tm_getretry(tm));
diff --git a/src/wsocket.c b/src/wsocket.c
index f33e154..fcd2fff 100644
--- a/src/wsocket.c
+++ b/src/wsocket.c
@@ -75,12 +75,10 @@ void sock_shutdown(p_sock ps, int how)
75\*-------------------------------------------------------------------------*/ 75\*-------------------------------------------------------------------------*/
76const char *sock_create(p_sock ps, int domain, int type, int protocol) 76const char *sock_create(p_sock ps, int domain, int type, int protocol)
77{ 77{
78 int val = 1;
79 t_sock sock = socket(domain, type, protocol); 78 t_sock sock = socket(domain, type, protocol);
80 if (sock == SOCK_INVALID) 79 if (sock == SOCK_INVALID)
81 return sock_createstrerror(WSAGetLastError()); 80 return sock_createstrerror(WSAGetLastError());
82 *ps = sock; 81 *ps = sock;
83 setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof(val));
84 sock_setnonblocking(ps); 82 sock_setnonblocking(ps);
85 return NULL; 83 return NULL;
86} 84}
@@ -112,8 +110,12 @@ const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len, p_tm tm)
112 /* if was in efds, we failed */ 110 /* if was in efds, we failed */
113 if (FD_ISSET(sock, &efds)) { 111 if (FD_ISSET(sock, &efds)) {
114 int why, len = sizeof(why); 112 int why, len = sizeof(why);
113 /* give windows time to set the error (disgusting) */
114 Sleep(0);
115 /* find out why we failed */ 115 /* find out why we failed */
116 getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&why, &len); 116 getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&why, &len);
117 /* we KNOW there was an error. if why is 0, we will return
118 * "unknown error", but it's not really our fault */
117 return sock_connectstrerror(why); 119 return sock_connectstrerror(why);
118 /* otherwise it must be in wfds, so we succeeded */ 120 /* otherwise it must be in wfds, so we succeeded */
119 } else return NULL; 121 } else return NULL;
diff --git a/test/mimetest.lua b/test/mimetest.lua
index 81814de..5a461fa 100644
--- a/test/mimetest.lua
+++ b/test/mimetest.lua
@@ -181,6 +181,19 @@ local function compare_b64test()
181 compare(b64test, db64test) 181 compare(b64test, db64test)
182end 182end
183 183
184local function identity_test()
185 local chain = socket.mime.chain(
186 socket.mime.encode("quoted-printable"),
187 socket.mime.encode("base64"),
188 socket.mime.decode("base64"),
189 socket.mime.decode("quoted-printable")
190 )
191 transform(b64test, eb64test, chain)
192 compare(b64test, eb64test)
193 os.remove(eb64test)
194end
195
196
184local function padcheck(original, encoded) 197local function padcheck(original, encoded)
185 local e = (socket.mime.b64(original)) 198 local e = (socket.mime.b64(original))
186 local d = (socket.mime.unb64(encoded)) 199 local d = (socket.mime.unb64(encoded))
@@ -233,4 +246,6 @@ compare_b64test()
233cleanup_b64test() 246cleanup_b64test()
234padding_b64test() 247padding_b64test()
235 248
249identity_test()
250
236print(string.format("done in %.2fs", socket.time() - t)) 251print(string.format("done in %.2fs", socket.time() - t))
diff --git a/test/testclnt.lua b/test/testclnt.lua
index 348439a..1b64abd 100644
--- a/test/testclnt.lua
+++ b/test/testclnt.lua
@@ -3,18 +3,18 @@ port = port or "8080"
3 3
4function pass(...) 4function pass(...)
5 local s = string.format(unpack(arg)) 5 local s = string.format(unpack(arg))
6 io.write(s, "\n") 6 io.stderr:write(s, "\n")
7end 7end
8 8
9function fail(...) 9function fail(...)
10 local s = string.format(unpack(arg)) 10 local s = string.format(unpack(arg))
11 io.write("ERROR: ", s, "!\n") 11 io.stderr:write("ERROR: ", s, "!\n")
12 os.exit() 12 os.exit()
13end 13end
14 14
15function warn(...) 15function warn(...)
16 local s = string.format(unpack(arg)) 16 local s = string.format(unpack(arg))
17 io.write("WARNING: ", s, "\n") 17 io.stderr:write("WARNING: ", s, "\n")
18end 18end
19 19
20pad = string.rep(" ", 8192) 20pad = string.rep(" ", 8192)
@@ -29,7 +29,7 @@ function remote(...)
29end 29end
30 30
31function test(test) 31function test(test)
32 io.write("----------------------------------------------\n", 32 io.stderr:write("----------------------------------------------\n",
33 "testing: ", test, "\n", 33 "testing: ", test, "\n",
34 "----------------------------------------------\n") 34 "----------------------------------------------\n")
35end 35end
@@ -72,14 +72,14 @@ if not socket.debug then
72 fail("Please define LUASOCKET_DEBUG and recompile LuaSocket") 72 fail("Please define LUASOCKET_DEBUG and recompile LuaSocket")
73end 73end
74 74
75io.write("----------------------------------------------\n", 75io.stderr:write("----------------------------------------------\n",
76"LuaSocket Test Procedures\n", 76"LuaSocket Test Procedures\n",
77"----------------------------------------------\n") 77"----------------------------------------------\n")
78 78
79start = socket.time() 79start = socket.time()
80 80
81function reconnect() 81function reconnect()
82 io.write("attempting data connection... ") 82 io.stderr:write("attempting data connection... ")
83 if data then data:close() end 83 if data then data:close() end
84 remote [[ 84 remote [[
85 if data then data:close() data = nil end 85 if data then data:close() data = nil end
@@ -348,7 +348,7 @@ end
348 348
349------------------------------------------------------------------------ 349------------------------------------------------------------------------
350function accept_timeout() 350function accept_timeout()
351 io.write("accept with timeout (if it hangs, it failed): ") 351 io.stderr:write("accept with timeout (if it hangs, it failed): ")
352 local s, e = socket.bind("*", 0, 0) 352 local s, e = socket.bind("*", 0, 0)
353 assert(s, e) 353 assert(s, e)
354 local t = socket.time() 354 local t = socket.time()
@@ -364,7 +364,8 @@ end
364 364
365------------------------------------------------------------------------ 365------------------------------------------------------------------------
366function connect_timeout() 366function connect_timeout()
367 io.write("connect with timeout (if it hangs, it failed): ") 367 io.stderr:write("connect with timeout (if it hangs, it failed): ")
368 local t = socket.time()
368 local c, e = socket.tcp() 369 local c, e = socket.tcp()
369 assert(c, e) 370 assert(c, e)
370 c:settimeout(0.1) 371 c:settimeout(0.1)
@@ -380,16 +381,17 @@ end
380 381
381------------------------------------------------------------------------ 382------------------------------------------------------------------------
382function accept_errors() 383function accept_errors()
383 io.write("not listening: ") 384 io.stderr:write("not listening: ")
384 local d, e = socket.bind("*", 0) 385 local d, e = socket.bind("*", 0)
385 assert(d, e); 386 assert(d, e);
386 local c, e = socket.tcp(); 387 local c, e = socket.tcp();
387 assert(c, e); 388 assert(c, e);
388 d:setfd(c:getfd()) 389 d:setfd(c:getfd())
390 d:settimeout(2)
389 local r, e = d:accept() 391 local r, e = d:accept()
390 assert(not r and e == "not listening", e) 392 assert(not r and e == "not listening", e)
391 print("ok") 393 print("ok")
392 io.write("not supported: ") 394 io.stderr:write("not supported: ")
393 local c, e = socket.udp() 395 local c, e = socket.udp()
394 assert(c, e); 396 assert(c, e);
395 d:setfd(c:getfd()) 397 d:setfd(c:getfd())
@@ -400,11 +402,11 @@ end
400 402
401------------------------------------------------------------------------ 403------------------------------------------------------------------------
402function connect_errors() 404function connect_errors()
403 io.write("connection refused: ") 405 io.stderr:write("connection refused: ")
404 local c, e = socket.connect("localhost", 1); 406 local c, e = socket.connect("localhost", 1);
405 assert(not c and e == "connection refused", e) 407 assert(not c and e == "connection refused", e)
406 print("ok") 408 print("ok")
407 io.write("host not found: ") 409 io.stderr:write("host not found: ")
408 local c, e = socket.connect("not.exist.com", 1); 410 local c, e = socket.connect("not.exist.com", 1);
409 assert(not c and e == "host not found", e) 411 assert(not c and e == "host not found", e)
410 print("ok") 412 print("ok")
@@ -534,7 +536,7 @@ test_raw(1)
534test("non-blocking transfer") 536test("non-blocking transfer")
535reconnect() 537reconnect()
536-- the value is not important, we only want 538-- the value is not important, we only want
537-- to test non-blockin I/O anyways 539-- to test non-blocking I/O anyways
538data:settimeout(200) 540data:settimeout(200)
539test_raw(1) 541test_raw(1)
540test_raw(17) 542test_raw(17)
diff --git a/test/urltest.lua b/test/urltest.lua
index 7b1f0c0..990a3e5 100644
--- a/test/urltest.lua
+++ b/test/urltest.lua
@@ -35,8 +35,6 @@ local check_parse_path = function(path, expect)
35 for i = 1, math.max(table.getn(parsed), table.getn(expect)) do 35 for i = 1, math.max(table.getn(parsed), table.getn(expect)) do
36 if parsed[i] ~= expect[i] then 36 if parsed[i] ~= expect[i] then
37 print(path) 37 print(path)
38 write("segment: ", i, " = '", Code.hexa(tostring(parsed[i])),
39 "' but expected '", Code.hexa(tostring(expect[i])), "'\n")
40 exit() 38 exit()
41 end 39 end
42 end 40 end