aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEW3
-rw-r--r--TODO3
-rw-r--r--doc/index.html7
-rw-r--r--doc/tcp.html3
-rw-r--r--gem/TODO2
-rw-r--r--gem/ltn012.tex46
-rw-r--r--makefile.dist2
-rw-r--r--src/http.lua28
-rw-r--r--src/usocket.c2
9 files changed, 59 insertions, 37 deletions
diff --git a/NEW b/NEW
index cffa73c..0191ccd 100644
--- a/NEW
+++ b/NEW
@@ -2,6 +2,9 @@ What's New
2 2
3This is just a bug-fix/update release. 3This is just a bug-fix/update release.
4 4
5 * Improved: http.request() now supports deprecated HTTP/0.9
6 servers (Florian Berger)
7 * Fixed: could return "timedout" instead of "timeout" (Leo Leo)
5 * Fixed: crash when reading '*a' on closed socket (Paul Ducklin); 8 * Fixed: crash when reading '*a' on closed socket (Paul Ducklin);
6 * Fixed: return values are consistent when reading from closed sockets; 9 * Fixed: return values are consistent when reading from closed sockets;
7 * Fixed: case sensitivity in headers of multipart messages in 10 * Fixed: case sensitivity in headers of multipart messages in
diff --git a/TODO b/TODO
index 07814a5..a07ebe4 100644
--- a/TODO
+++ b/TODO
@@ -1,7 +1,6 @@
1replace \r\n with \0xD\0xA in everything
1New mime support 2New mime support
2 3
3
4
5ftp send should return server replies? 4ftp send should return server replies?
6make sure there are no object files in the distribution tarball 5make sure there are no object files in the distribution tarball
7http handling of 100-continue, see DB patch 6http handling of 100-continue, see DB patch
diff --git a/doc/index.html b/doc/index.html
index 1605af1..57a7907 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -124,7 +124,7 @@ Special thanks go to
124David Burgess, who has helped push the library to a new level of quality and 124David Burgess, who has helped push the library to a new level of quality and
125from whom I have learned a lot of stuff that doesn't show up in RFCs. 125from whom I have learned a lot of stuff that doesn't show up in RFCs.
126Special thanks also to Carlos Cassino, who played a big part in the 126Special thanks also to Carlos Cassino, who played a big part in the
127extensible design seen in the C core of LuaSocket 2.0. Recently, Mike Pall 127extensible design seen in the C core of LuaSocket 2.0. Mike Pall
128has been helping a lot too! Thanks to you all! 128has been helping a lot too! Thanks to you all!
129</p> 129</p>
130 130
@@ -137,6 +137,9 @@ has been helping a lot too! Thanks to you all!
137</p> 137</p>
138 138
139<ul> 139<ul>
140<li> Improved: http.request() now supports deprecated
141HTTP/0.9 servers (Florian Berger);
142<li> Fixed: could return "timedout" instead of "timeout" (Leo Leo);
140<li> Fixed: crash when reading '*a' on closed socket (Paul Ducklin); 143<li> Fixed: crash when reading '*a' on closed socket (Paul Ducklin);
141<li> Fixed: return values are consistent when reading from closed sockets; 144<li> Fixed: return values are consistent when reading from closed sockets;
142<li> Fixed: case sensitivity in headers of multipart 145<li> Fixed: case sensitivity in headers of multipart
@@ -195,7 +198,7 @@ still available for those that have compatibility issues.
195<p> 198<p>
196<small> 199<small>
197Last modified by Diego Nehab on <br> 200Last modified by Diego Nehab on <br>
198Thu Apr 20 00:25:23 EDT 2006 201Wed Oct 3 02:07:59 BRT 2007
199</small> 202</small>
200</p> 203</p>
201</center> 204</center>
diff --git a/doc/tcp.html b/doc/tcp.html
index 602c73c..a16a09e 100644
--- a/doc/tcp.html
+++ b/doc/tcp.html
@@ -284,7 +284,8 @@ closed. No end-of-line translation is performed;
284<li> '<tt>*l</tt>': reads a line of text from the socket. The line is 284<li> '<tt>*l</tt>': reads a line of text from the socket. The line is
285terminated by a LF character (ASCII&nbsp;10), optionally preceded by a 285terminated by a LF character (ASCII&nbsp;10), optionally preceded by a
286CR character (ASCII&nbsp;13). The CR and LF characters are not included in 286CR character (ASCII&nbsp;13). The CR and LF characters are not included in
287the returned line. This is the default pattern; 287the returned line. In fact, <em>all</em> CR characters are
288ignored by the pattern. This is the default pattern;
288<li> <tt>number</tt>: causes the method to read a specified <tt>number</tt> 289<li> <tt>number</tt>: causes the method to read a specified <tt>number</tt>
289of bytes from the socket. 290of bytes from the socket.
290</ul> 291</ul>
diff --git a/gem/TODO b/gem/TODO
deleted file mode 100644
index bdbe84e..0000000
--- a/gem/TODO
+++ /dev/null
@@ -1,2 +0,0 @@
1Talk a bout Wim
2Move thanks into the acknowledgement section.
diff --git a/gem/ltn012.tex b/gem/ltn012.tex
index 8eccd46..8027ecc 100644
--- a/gem/ltn012.tex
+++ b/gem/ltn012.tex
@@ -61,7 +61,7 @@ sinks, and pumps, which we introduce below.
61 61
62\emph{Filters} are functions that can be repeatedly invoked 62\emph{Filters} are functions that can be repeatedly invoked
63with chunks of input, successively returning processed 63with chunks of input, successively returning processed
64chunks of output. More importantly, the result of 64chunks of output. Naturally, the result of
65concatenating all the output chunks must be the same as the 65concatenating all the output chunks must be the same as the
66result of applying the filter to the concatenation of all 66result of applying the filter to the concatenation of all
67input chunks. In fancier language, filters \emph{commute} 67input chunks. In fancier language, filters \emph{commute}
@@ -81,11 +81,12 @@ which data will flow, potentially being transformed many
81times along the way. Chains connect these nodes together. 81times along the way. Chains connect these nodes together.
82The initial and final nodes of the network are 82The initial and final nodes of the network are
83\emph{sources} and \emph{sinks}, respectively. Less 83\emph{sources} and \emph{sinks}, respectively. Less
84abstractly, a source is a function that produces new data 84abstractly, a source is a function that produces new chunks
85every time it is invoked. Conversely, sinks are functions 85of data every time it is invoked. Conversely, sinks are
86that give a final destination to the data they receive. 86functions that give a final destination to the chunks of
87Naturally, sources and sinks can also be chained with 87data they receive in sucessive calls. Naturally, sources
88filters to produce filtered sources and sinks. 88and sinks can also be chained with filters to produce
89filtered sources and sinks.
89 90
90Finally, filters, chains, sources, and sinks are all passive 91Finally, filters, chains, sources, and sinks are all passive
91entities: they must be repeatedly invoked in order for 92entities: they must be repeatedly invoked in order for
@@ -95,8 +96,8 @@ sink, and indirectly through all intervening filters.
95 96
96In the following sections, we start with a simplified 97In the following sections, we start with a simplified
97interface, which we later refine. The evolution we present 98interface, which we later refine. The evolution we present
98is not contrived: it recreates the steps we followed 99is not contrived: it recreates the steps we ourselves
99ourselves as we consolidated our understanding of these 100followed as we consolidated our understanding of these
100concepts within our application domain. 101concepts within our application domain.
101 102
102\subsection{A simple example} 103\subsection{A simple example}
@@ -290,8 +291,8 @@ static int eol(lua_State *L) {
290\end{C} 291\end{C}
291\end{quote} 292\end{quote}
292 293
293When designing your own filters, the challenging part is to 294When designing filters, the challenging part is usually
294decide what will be in the context. For line breaking, for 295deciding what to store in the context. For line breaking, for
295instance, it could be the number of bytes that still fit in the 296instance, it could be the number of bytes that still fit in the
296current line. For Base64 encoding, it could be a string 297current line. For Base64 encoding, it could be a string
297with the bytes that remain after the division of the input 298with the bytes that remain after the division of the input
@@ -408,8 +409,8 @@ associated filter before returning it to the caller.
408Filtered sources are useful when working with 409Filtered sources are useful when working with
409functions that get their input data from a source (such as 410functions that get their input data from a source (such as
410the pumps in our examples). By chaining a source with one or 411the pumps in our examples). By chaining a source with one or
411more filters, the function can be transparently provided 412more filters, such functions can be transparently provided
412with filtered data, with no need to change its interface. 413with filtered data, with no need to change their interfaces.
413Here is a factory that does the job: 414Here is a factory that does the job:
414\begin{quote} 415\begin{quote}
415\begin{lua} 416\begin{lua}
@@ -434,11 +435,11 @@ end
434 435
435\subsection{Sinks} 436\subsection{Sinks}
436 437
437Just as we defined an interface for source of data, 438Just as we defined an interface for a source of data, we can
438we can also define an interface for a data destination. 439also define an interface for a data destination. We call
439We call any function respecting this 440any function respecting this interface a sink. In our first
440interface a \emph{sink}. In our first example, we used a 441example, we used a file sink connected to the standard
441file sink connected to the standard output. 442output.
442 443
443Sinks receive consecutive chunks of data, until the end of 444Sinks receive consecutive chunks of data, until the end of
444data is signaled by a \nil\ input chunk. A sink can be 445data is signaled by a \nil\ input chunk. A sink can be
@@ -665,7 +666,7 @@ SMTP dot-stuffing filter, connects a socket sink
665with the server, and simply pumps the data. The message is never 666with the server, and simply pumps the data. The message is never
666assembled in memory. Everything is produced on demand, 667assembled in memory. Everything is produced on demand,
667transformed in small pieces, and sent to the server in chunks, 668transformed in small pieces, and sent to the server in chunks,
668including the file attachment that is loaded from disk and 669including the file attachment which is loaded from disk and
669encoded on the fly. It just works. 670encoded on the fly. It just works.
670 671
671\section{Conclusions} 672\section{Conclusions}
@@ -685,11 +686,10 @@ components. Pumps simply push the data through.
685The concepts described in this text are the result of long 686The concepts described in this text are the result of long
686discussions with David Burgess. A version of this text has 687discussions with David Burgess. A version of this text has
687been released on-line as the Lua Technical Note 012, hence 688been released on-line as the Lua Technical Note 012, hence
688the name of the corresponding LuaSocket module, 689the name of the corresponding LuaSocket module, LTN12. Wim
689\texttt{ltn12}. Wim Couwenberg contributed to the 690Couwenberg contributed to the implementation of the module,
690implementation of the module, and Adrian Sietsma was the 691and Adrian Sietsma was the first to notice the
691first to notice the correspondence between sources and Lua 692correspondence between sources and Lua iterators.
692iterators.
693 693
694 694
695\end{document} 695\end{document}
diff --git a/makefile.dist b/makefile.dist
index 58ae5b3..876cf18 100644
--- a/makefile.dist
+++ b/makefile.dist
@@ -86,7 +86,7 @@ MAKE = \
86DOC = \ 86DOC = \
87 doc/dns.html \ 87 doc/dns.html \
88 doc/ftp.html \ 88 doc/ftp.html \
89 doc/home.html \ 89 doc/index.html \
90 doc/http.html \ 90 doc/http.html \
91 doc/installation.html \ 91 doc/installation.html \
92 doc/introduction.html \ 92 doc/introduction.html \
diff --git a/src/http.lua b/src/http.lua
index 9d739a4..3a386a6 100644
--- a/src/http.lua
+++ b/src/http.lua
@@ -142,7 +142,12 @@ function metat.__index:sendbody(headers, source, step)
142end 142end
143 143
144function metat.__index:receivestatusline() 144function metat.__index:receivestatusline()
145 local status = self.try(self.c:receive()) 145 local status = self.try(self.c:receive(5))
146 -- identify HTTP/0.9 responses, which do not contain a status line
147 -- this is just a heuristic, but is what the RFC recommends
148 if status ~= "HTTP/" then return nil, status end
149 -- otherwise proceed reading a status line
150 status = self.try(self.c:receive("*l", status))
146 local code = socket.skip(2, string.find(status, "HTTP/%d*%.%d* (%d%d%d)")) 151 local code = socket.skip(2, string.find(status, "HTTP/%d*%.%d* (%d%d%d)"))
147 return self.try(base.tonumber(code), status) 152 return self.try(base.tonumber(code), status)
148end 153end
@@ -163,6 +168,12 @@ function metat.__index:receivebody(headers, sink, step)
163 sink, step)) 168 sink, step))
164end 169end
165 170
171function metat.__index:receive09body(status, sink, step)
172 local source = ltn12.source.rewind(socket.source("until-closed", self.c))
173 source(status)
174 return self.try(ltn12.pump.all(source, sink, step))
175end
176
166function metat.__index:close() 177function metat.__index:close()
167 return self.c:close() 178 return self.c:close()
168end 179end
@@ -271,6 +282,7 @@ function tredirect(reqt, location)
271 create = reqt.create 282 create = reqt.create
272 } 283 }
273 -- pass location header back as a hint we redirected 284 -- pass location header back as a hint we redirected
285 headers = headers or {}
274 headers.location = headers.location or location 286 headers.location = headers.location or location
275 return result, code, headers, status 287 return result, code, headers, status
276end 288end
@@ -283,17 +295,23 @@ function trequest(reqt)
283 -- send request line and headers 295 -- send request line and headers
284 h:sendrequestline(nreqt.method, nreqt.uri) 296 h:sendrequestline(nreqt.method, nreqt.uri)
285 h:sendheaders(nreqt.headers) 297 h:sendheaders(nreqt.headers)
286 local code = 100 298 -- if there is a body, send it
287 local headers, status
288 -- if there is a body, check for server status
289 if nreqt.source then 299 if nreqt.source then
290 h:sendbody(nreqt.headers, nreqt.source, nreqt.step) 300 h:sendbody(nreqt.headers, nreqt.source, nreqt.step)
291 end 301 end
302 local code, status = h:receivestatusline()
303 -- if it is an HTTP/0.9 server, simply get the body and we are done
304 if not code then
305 h:receive09body(status, nreqt.sink, nreqt.step)
306 return 1, 200
307 end
308 local headers
292 -- ignore any 100-continue messages 309 -- ignore any 100-continue messages
293 while code == 100 do 310 while code == 100 do
294 code, status = h:receivestatusline()
295 headers = h:receiveheaders() 311 headers = h:receiveheaders()
312 code, status = h:receivestatusline()
296 end 313 end
314 headers = h:receiveheaders()
297 -- at this point we should have a honest reply from the server 315 -- at this point we should have a honest reply from the server
298 -- we can't redirect if we already used the source, so we report the error 316 -- we can't redirect if we already used the source, so we report the error
299 if shouldredirect(nreqt, code, headers) and not nreqt.source then 317 if shouldredirect(nreqt, code, headers) and not nreqt.source then
diff --git a/src/usocket.c b/src/usocket.c
index ef275b4..2c30b9a 100644
--- a/src/usocket.c
+++ b/src/usocket.c
@@ -359,7 +359,7 @@ const char *socket_strerror(int err) {
359 case ECONNREFUSED: return "connection refused"; 359 case ECONNREFUSED: return "connection refused";
360 case ECONNABORTED: return "closed"; 360 case ECONNABORTED: return "closed";
361 case ECONNRESET: return "closed"; 361 case ECONNRESET: return "closed";
362 case ETIMEDOUT: return "timedout"; 362 case ETIMEDOUT: return "timeout";
363 default: return strerror(errno); 363 default: return strerror(errno);
364 } 364 }
365} 365}