[lua-copas] 1.2.0, support for lua 5.2
Tom Callaway
spot at fedoraproject.org
Fri May 10 17:34:41 UTC 2013
commit fc0f6d29a77c1d56ffb86482c26f43d2427e6fe9
Author: Tom Callaway <spot at fedoraproject.org>
Date: Fri May 10 13:34:09 2013 -0400
1.2.0, support for lua 5.2
copas-1.2.0-git.patch | 1061 +++++++++++++++++++++++++++++++++++++++++++++++++
lua-copas.spec | 19 +-
2 files changed, 1075 insertions(+), 5 deletions(-)
---
diff --git a/copas-1.2.0-git.patch b/copas-1.2.0-git.patch
new file mode 100644
index 0000000..f865103
--- /dev/null
+++ b/copas-1.2.0-git.patch
@@ -0,0 +1,1061 @@
+Only in copas-1.1.6: debugfiles.list
+Only in copas-1.1.6: debuglinks.list
+Only in copas-1.1.6: debugsources.list
+diff -urP copas-1.1.6/doc/us/index.html copas-1.2.0/doc/us/index.html
+--- copas-1.1.6/doc/us/index.html 2010-03-18 12:23:39.000000000 -0400
++++ copas-1.2.0/doc/us/index.html 2013-05-10 13:29:37.530722513 -0400
+@@ -78,7 +78,7 @@
+
+ <h2><a name="status"></a>Status</h2>
+
+-<p>Current version is 1.1.6 and was developed for Lua 5.1.</p>
++<p>Current version is 1.2.0 and supports both Lua 5.1 and Lua 5.2.</p>
+
+ <h2><a name="download"></a>Download</h2>
+
+@@ -98,17 +98,21 @@
+ <h2><a name="dependencies"></a>Dependencies</h2>
+
+ <p>Copas depends on
+-<a href="http://luasocket.luaforge.net">LuaSocket 2.0</a> and
+-<a href="http://coxpcall.luaforge.net/">Coxpcall 1.13</a>.
++<a href="http://luasocket.luaforge.net">LuaSocket 2.1</a> and
++<a href="http://coxpcall.luaforge.net/">Coxpcall 1.14</a>.
+ </p>
+
+ <h2><a name="history"></a>History</h2>
+
+- Copas 1.1.6 [18/Mar/2010]
+-* Now checks to see if socket.http was required before copas
+-
+ <dl class="history">
+- <dt><strong>Copas 1.1.6</strong> [18/Mar/2010]</dt>
++ <dt><strong>Copas 1.2.0</strong> [30/Jan/2013]</dt>
++ <dd><ul>
++ <li>Support for Lua 5.2
++ </li>
++ </ul></dd>
++
++
++ <dt><strong>Copas 1.1.6</strong> [18/Mar/2010]</dt>
+ <dd><ul>
+ <li>Now checks to see if socket.http was required before copas
+ </li>
+@@ -198,4 +202,4 @@
+
+ </div> <!-- id="container" -->
+ </body>
+-</html>
+\ No newline at end of file
++</html>
+diff -urP copas-1.1.6/doc/us/manual.html copas-1.2.0/doc/us/manual.html
+--- copas-1.1.6/doc/us/manual.html 2010-03-18 12:23:39.000000000 -0400
++++ copas-1.2.0/doc/us/manual.html 2013-05-10 13:29:37.531722513 -0400
+@@ -281,6 +281,67 @@
+ <p>During the loop Copas' dispatcher accepts connections from clients and
+ automatically calls the corresponding handler functions.</p>
+
++<h2><a name="udp"></a>Using UDP servers</h2>
++<p>Copas may also be used for UDP servers. Here is an example;</p>
++<pre class="example">
++local port = 51034
++local server = socket.udp()
++server:setsockname("*",port)
++
++function handler(skt)
++ skt = copas.wrap(skt)
++ print("UDP connection handler")
++
++ while true do
++ local s, err
++ print("receiving...")
++ s, err = skt:receive(2048)
++ if not s then
++ print("Receive error: ", err)
++ return
++ end
++ print("Received data, bytes:" , #s)
++ end
++end
++
++copas.addserver(server, handler, 1)
++copas.loop()
++</pre>
++<p>For UDP sockets the <code>receivefrom()</code> and <code>sendto()</code>
++methods are available, both for copas and when the socket is wrapped. These
++methods cannot be used on TCP sockets.</p>
++<p><strong>NOTE:</strong> When using the <code>copas.receive([size])</code> method
++on a UDP socket, the <code>size</code> parameter is NOT optional as with regular
++luasocket UDP sockets. This limitation is removed when the socket is wrapped
++(it then defaults to 8192, the max UDP datagram size luasocket supports).</p>
++
++<h2><a name="thread"></a>Adding threads</h2>
++<p>Additional threads may be added to the scheduler, as long as they use the Copas send and receive methods. Below an example of a thread being added to create an outgoing TCP connection using Copas;</p>
++<pre class="example">
++local socket = require("socket")
++local copas = require("copas.timer")
++
++local host = "127.0.0.1"
++local port = 10000
++
++local skt = socket.connect(host, port)
++
++copas.addthread(function()
++ while true do
++ print("receiving...")
++ local resp = copas.receive(skt, 6)
++ print("received:", resp or "nil")
++ if resp and resp:sub(1,4) == "quit" then
++ skt:close()
++ break
++ end
++ end
++end)
++
++copas.loop()
++</pre>
++<p>The example connects, echoes whatever it receives and exists upon receiving 'quit'.</p>
++
+ <h2><a name="control"></a>Controlling Copas</h2>
+
+ <p>
+diff -urP copas-1.1.6/doc/us/reference.html copas-1.2.0/doc/us/reference.html
+--- copas-1.1.6/doc/us/reference.html 2010-03-18 12:23:39.000000000 -0400
++++ copas-1.2.0/doc/us/reference.html 2013-05-10 13:29:37.531722513 -0400
+@@ -96,6 +96,9 @@
+ handlers. When a server accepts a connection, Copas calls the
+ associated handler passing the client socket returned by
+ <code>socket.accept()</code>. The <code>timeout</code> parameter is optional.
++ It returns <code>false</code> when no data was handled (timeout) or
++ <code>true</code> if there was data handled (or alternatively nil + error
++ message in case of errors).
+ </dd>
+ </dl>
+
+diff -urP copas-1.1.6/README copas-1.2.0/README
+--- copas-1.1.6/README 2010-03-18 12:23:39.000000000 -0400
++++ copas-1.2.0/README 2013-05-10 13:29:37.529722513 -0400
+@@ -1,4 +1,4 @@
+-Copas 1.1.6
++Copas 1.2.0
+ (http://www.keplerproject.org/copas)
+
+ Copas is a dispatcher based on coroutines that can be used by TCP/IP servers.
+@@ -17,10 +17,13 @@
+ luarocks install copas
+
+ Dependencies
+-Copas depends on LuaSocket 2.0 and Coxpcall 1.13.
++Copas depends on LuaSocket 2.1 and Coxpcall 1.14.
+
+ History
+
++Copas 1.2.0 [30/Jan/2013]
++* Support for Lua 5.2
++
+ Copas 1.1.6 [18/Mar/2010]
+ * Now checks to see if socket.http was required before copas
+
+@@ -48,4 +51,4 @@
+ * copas.step() added
+
+ Copas 1.0 Beta[17/Feb/2005]
+-* First public version
+\ No newline at end of file
++* First public version
+diff -urP copas-1.1.6/rockspec/copas-1.2.0-1.rockspec copas-1.2.0/rockspec/copas-1.2.0-1.rockspec
+--- copas-1.1.6/rockspec/copas-1.2.0-1.rockspec 1969-12-31 19:00:00.000000000 -0500
++++ copas-1.2.0/rockspec/copas-1.2.0-1.rockspec 2013-05-10 13:29:37.531722513 -0400
+@@ -0,0 +1,28 @@
++package = "Copas"
++version = "1.2.0-1"
++source = {
++ url = "http://www.keplerproject.org/files/copas-1.2.0.tar.gz",
++}
++description = {
++ summary = "Coroutine Oriented Portable Asynchronous Services",
++ detailed = [[
++ Copas is a dispatcher based on coroutines that can be used by
++ TCP/IP servers. It uses LuaSocket as the interface with the
++ TCP/IP stack. A server registered with Copas should provide a
++ handler for requests and use Copas socket functions to send
++ the response. Copas loops through requests and invokes the
++ corresponding handlers. For a full implementation of a Copas
++ HTTP server you can refer to Xavante as an example.
++ ]],
++ license = "MIT/X11",
++ homepage = "http://www.keplerproject.org/copas/"
++}
++dependencies = {
++ "lua >= 5.1",
++ "luasocket >= 2.1",
++ "coxpcall >= 1.14",
++}
++build = {
++ type = "builtin",
++ modules = { copas = "src/copas/copas.lua" }
++}
+diff -urP copas-1.1.6/src/copas/copas.lua copas-1.2.0/src/copas/copas.lua
+--- copas-1.1.6/src/copas/copas.lua 2010-03-18 12:23:39.000000000 -0400
++++ copas-1.2.0/src/copas/copas.lua 2013-05-10 13:29:37.532722513 -0400
+@@ -4,9 +4,9 @@
+ -- A dispatcher based on coroutines that can be used by TCP/IP servers.
+ -- Uses LuaSocket as the interface with the TCP/IP stack.
+ --
+--- Authors: Andre Carregal and Javier Guerra
++-- Authors: Andre Carregal, Javier Guerra, and Fabio Mascarenhas
+ -- Contributors: Diego Nehab, Mike Pall, David Burgess, Leonardo Godinho,
+--- Thomas Harning Jr. and Gary NG
++-- Thomas Harning Jr., and Gary NG
+ --
+ -- Copyright 2005 - Kepler Project (www.keplerproject.org)
+ --
+@@ -19,93 +19,102 @@
+
+ local socket = require "socket"
+
+-require "coxpcall"
++local coxpcall = require "coxpcall"
+
+ local WATCH_DOG_TIMEOUT = 120
++local UDP_DATAGRAM_MAX = 8192
+
+ -- Redefines LuaSocket functions with coroutine safe versions
+ -- (this allows the use of socket.http from within copas)
+ local function statusHandler(status, ...)
+- if status then return ... end
+- return nil, ...
++ if status then return ... end
++ local err = (...)
++ if type(err) == "table" then
++ return nil, err[1]
++ else
++ error(err)
++ end
+ end
+
+ function socket.protect(func)
+- return function (...)
+- return statusHandler(copcall(func, ...))
+- end
++ return function (...)
++ return statusHandler(coxpcall.pcall(func, ...))
++ end
+ end
+
+ function socket.newtry(finalizer)
+- return function (...)
+- local status = (...) or false
+- if (status==false)then
+- copcall(finalizer, select(2, ...) )
+- error((select(2, ...)), 0)
+- end
+- return ...
+- end
++ return function (...)
++ local status = (...)
++ if not status then
++ coxpcall.pcall(finalizer, select(2, ...))
++ error({ (select(2, ...)) }, 0)
++ end
++ return ...
++ end
+ end
+--- end of LuaSocket redefinitions
+
++-- end of LuaSocket redefinitions
+
+-module ("copas", package.seeall)
++local copas = {}
+
+ -- Meta information is public even if beginning with an "_"
+-_COPYRIGHT = "Copyright (C) 2005 Kepler Project"
+-_DESCRIPTION = "Coroutine Oriented Portable Asynchronous Services"
+-_VERSION = "Copas 1.1.5"
++copas._COPYRIGHT = "Copyright (C) 2005-2010 Kepler Project"
++copas._DESCRIPTION = "Coroutine Oriented Portable Asynchronous Services"
++copas._VERSION = "Copas 1.1.7"
++
++-- Close the socket associated with the current connection after the handler finishes
++copas.autoclose = true
+
+ -------------------------------------------------------------------------------
+ -- Simple set implementation based on LuaSocket's tinyirc.lua example
+ -- adds a FIFO queue for each value in the set
+ -------------------------------------------------------------------------------
+ local function newset()
+- local reverse = {}
+- local set = {}
+- local q = {}
+- setmetatable(set, { __index = {
+- insert = function(set, value)
+- if not reverse[value] then
+- set[#set + 1] = value
+- reverse[value] = #set
+- end
+- end,
+-
+- remove = function(set, value)
+- local index = reverse[value]
+- if index then
+- reverse[value] = nil
+- local top = set[#set]
+- set[#set] = nil
+- if top ~= value then
+- reverse[top] = index
+- set[index] = top
+- end
+- end
+- end,
+-
+- push = function (set, key, itm)
+- local qKey = q[key]
+- if qKey == nil then
+- q[key] = {itm}
+- else
+- qKey[#qKey + 1] = itm
+- end
+- end,
+-
+- pop = function (set, key)
+- local t = q[key]
+- if t ~= nil then
+- local ret = table.remove (t, 1)
+- if t[1] == nil then
+- q[key] = nil
+- end
+- return ret
+- end
+- end
+- }})
+- return set
++ local reverse = {}
++ local set = {}
++ local q = {}
++ setmetatable(set, { __index = {
++ insert = function(set, value)
++ if not reverse[value] then
++ set[#set + 1] = value
++ reverse[value] = #set
++ end
++ end,
++
++ remove = function(set, value)
++ local index = reverse[value]
++ if index then
++ reverse[value] = nil
++ local top = set[#set]
++ set[#set] = nil
++ if top ~= value then
++ reverse[top] = index
++ set[index] = top
++ end
++ end
++ end,
++
++ push = function (set, key, itm)
++ local qKey = q[key]
++ if qKey == nil then
++ q[key] = {itm}
++ else
++ qKey[#qKey + 1] = itm
++ end
++ end,
++
++ pop = function (set, key)
++ local t = q[key]
++ if t ~= nil then
++ local ret = table.remove (t, 1)
++ if t[1] == nil then
++ q[key] = nil
++ end
++ return ret
++ end
++ end
++ }})
++ return set
+ end
+
+ local _servers = newset() -- servers being handled
+@@ -119,106 +128,181 @@
+ -- Coroutine based socket I/O functions.
+ -------------------------------------------------------------------------------
+ -- reads a pattern from a client and yields to the reading set on timeouts
+-function receive(client, pattern, part)
+- local s, err
+- pattern = pattern or "*l"
+- repeat
+- s, err, part = client:receive(pattern, part)
+- if s or err ~= "timeout" then
+- _reading_log[client] = nil
+- return s, err, part
+- end
+- _reading_log[client] = os.time()
+- coroutine.yield(client, _reading)
+- until false
++-- UDP: a UDP socket expects a second argument to be a number, so it MUST
++-- be provided as the 'pattern' below defaults to a string. Will throw a
++-- 'bad argument' error if omitted.
++function copas.receive(client, pattern, part)
++ local s, err
++ pattern = pattern or "*l"
++ repeat
++ s, err, part = client:receive(pattern, part)
++ if s or err ~= "timeout" then
++ _reading_log[client] = nil
++ return s, err, part
++ end
++ _reading_log[client] = os.time()
++ coroutine.yield(client, _reading)
++ until false
++end
++
++-- receives data from a client over UDP. Not available for TCP.
++-- (this is a copy of receive() method, adapted for receivefrom() use)
++function copas.receivefrom(client, size)
++ local s, err, port
++ size = size or UDP_DATAGRAM_MAX
++ repeat
++ s, err, port = client:receivefrom(size) -- upon success err holds ip address
++ if s or err ~= "timeout" then
++ _reading_log[client] = nil
++ return s, err, port
++ end
++ _reading_log[client] = os.time()
++ coroutine.yield(client, _reading)
++ until false
+ end
+
+ -- same as above but with special treatment when reading chunks,
+ -- unblocks on any data received.
+-function receivePartial(client, pattern)
+- local s, err, part
+- pattern = pattern or "*l"
+- repeat
+- s, err, part = client:receive(pattern)
+- if s or ( (type(pattern)=="number") and part~="" and part ~=nil ) or
+- err ~= "timeout" then
+- _reading_log[client] = nil
+- return s, err, part
+- end
+- _reading_log[client] = os.time()
+- coroutine.yield(client, _reading)
+- until false
++function copas.receivePartial(client, pattern)
++ local s, err, part
++ pattern = pattern or "*l"
++ repeat
++ s, err, part = client:receive(pattern)
++ if s or ( (type(pattern)=="number") and part~="" and part ~=nil ) or
++ err ~= "timeout" then
++ _reading_log[client] = nil
++ return s, err, part
++ end
++ _reading_log[client] = os.time()
++ coroutine.yield(client, _reading)
++until false
+ end
+
+ -- sends data to a client. The operation is buffered and
+ -- yields to the writing set on timeouts
+-function send(client,data, from, to)
+- local s, err,sent
+- from = from or 1
+- local lastIndex = from - 1
+-
+- repeat
+- s, err, lastIndex = client:send(data, lastIndex + 1, to)
+- -- adds extra corrotine swap
+- -- garantees that high throuput dont take other threads to starvation
+- if (math.random(100) > 90) then
+- _writing_log[client] = os.time()
+- coroutine.yield(client, _writing)
+- end
+- if s or err ~= "timeout" then
+- _writing_log[client] = nil
+- return s, err,lastIndex
+- end
+- _writing_log[client] = os.time()
+- coroutine.yield(client, _writing)
+- until false
++-- Note: from and to parameters will be ignored by/for UDP sockets
++function copas.send(client, data, from, to)
++ local s, err,sent
++ from = from or 1
++ local lastIndex = from - 1
++
++ repeat
++ s, err, lastIndex = client:send(data, lastIndex + 1, to)
++ -- adds extra corrotine swap
++ -- garantees that high throuput dont take other threads to starvation
++ if (math.random(100) > 90) then
++ _writing_log[client] = os.time()
++ coroutine.yield(client, _writing)
++ end
++ if s or err ~= "timeout" then
++ _writing_log[client] = nil
++ return s, err,lastIndex
++ end
++ _writing_log[client] = os.time()
++ coroutine.yield(client, _writing)
++ until false
++end
++
++-- sends data to a client over UDP. Not available for TCP.
++-- (this is a copy of send() method, adapted for sendto() use)
++function copas.sendto(client, data, ip, port)
++ local s, err,sent
++
++ repeat
++ s, err = client:sendto(data, ip, port)
++ -- adds extra corrotine swap
++ -- garantees that high throuput dont take other threads to starvation
++ if (math.random(100) > 90) then
++ _writing_log[client] = os.time()
++ coroutine.yield(client, _writing)
++ end
++ if s or err ~= "timeout" then
++ _writing_log[client] = nil
++ return s, err
++ end
++ _writing_log[client] = os.time()
++ coroutine.yield(client, _writing)
++ until false
+ end
+
+ -- waits until connection is completed
+-function connect(skt, host, port)
+- skt:settimeout(0)
+- local ret, err
+- repeat
+- ret, err = skt:connect (host, port)
+- if ret or err ~= "timeout" then
+- _writing_log[skt] = nil
+- return ret, err
+- end
+- _writing_log[skt] = os.time()
+- coroutine.yield(skt, _writing)
+- until false
+- return ret, err
++function copas.connect(skt, host, port)
++ skt:settimeout(0)
++ local ret, err
++ repeat
++ ret, err = skt:connect (host, port)
++ if ret or err ~= "timeout" then
++ _writing_log[skt] = nil
++ return ret, err
++ end
++ _writing_log[skt] = os.time()
++ coroutine.yield(skt, _writing)
++ until false
++ return ret, err
+ end
+
+ -- flushes a client write buffer (deprecated)
+-function flush(client)
++function copas.flush(client)
+ end
+
+--- wraps a socket to use Copas methods (send, receive, flush and settimeout)
++-- wraps a TCP socket to use Copas methods (send, receive, flush and settimeout)
+ local _skt_mt = {__index = {
+- send = function (self, data, from, to)
+- return send (self.socket, data, from, to)
+- end,
+-
+- receive = function (self, pattern)
+- if (self.timeout==0) then
+- return receivePartial(self.socket, pattern)
+- end
+- return receive (self.socket, pattern)
+- end,
+-
+- flush = function (self)
+- return flush (self.socket)
+- end,
+-
+- settimeout = function (self,time)
+- self.timeout=time
+- return
+- end,
+-}}
+-
+-function wrap (skt)
+- return setmetatable ({socket = skt}, _skt_mt)
++ send = function (self, data, from, to)
++ return copas.send (self.socket, data, from, to)
++ end,
++
++ receive = function (self, pattern)
++ if (self.timeout==0) then
++ return copas.receivePartial(self.socket, pattern)
++ end
++ return copas.receive(self.socket, pattern)
++ end,
++
++ flush = function (self)
++ return copas.flush(self.socket)
++ end,
++
++ settimeout = function (self,time)
++ self.timeout=time
++ return
++ end,
++ }}
++
++-- wraps a UDP socket, copy of TCP one adapted for UDP.
++-- Mainly adds sendto() and receivefrom()
++local _skt_mt_udp = {__index = {
++ send = function (self, data)
++ return copas.send (self.socket, data)
++ end,
++
++ sendto = function (self, data, ip, port)
++ return copas.sendto (self.socket, data, ip, port)
++ end,
++
++ receive = function (self, size)
++ return copas.receive (self.socket, (size or UDP_DATAGRAM_MAX))
++ end,
++
++ receivefrom = function (self, size)
++ return copas.receivefrom (self.socket, (size or UDP_DATAGRAM_MAX))
++ end,
++
++ flush = function (self)
++ return copas.flush (self.socket)
++ end,
++
++ settimeout = function (self,time)
++ self.timeout=time
++ return
++ end,
++ }}
++
++function copas.wrap (skt)
++ if string.sub(tostring(skt),1,3) == "udp" then
++ return setmetatable ({socket = skt}, _skt_mt_udp)
++ else
++ return setmetatable ({socket = skt}, _skt_mt)
++ end
+ end
+
+ --------------------------------------------------
+@@ -227,15 +311,15 @@
+
+ local _errhandlers = {} -- error handler per coroutine
+
+-function setErrorHandler (err)
+- local co = coroutine.running()
+- if co then
+- _errhandlers [co] = err
+- end
++function copas.setErrorHandler (err)
++ local co = coroutine.running()
++ if co then
++ _errhandlers [co] = err
++ end
+ end
+
+ local function _deferror (msg, co, skt)
+- print (msg, co, skt)
++ print (msg, co, skt)
+ end
+
+ -------------------------------------------------------------------------------
+@@ -243,56 +327,73 @@
+ -------------------------------------------------------------------------------
+
+ local function _doTick (co, skt, ...)
+- if not co then return end
++ if not co then return end
+
+- local ok, res, new_q = coroutine.resume(co, skt, ...)
++ local ok, res, new_q = coroutine.resume(co, skt, ...)
+
+- if ok and res and new_q then
+- new_q:insert (res)
+- new_q:push (res, co)
+- else
+- if not ok then copcall (_errhandlers [co] or _deferror, res, co, skt) end
+- if skt then skt:close() end
+- _errhandlers [co] = nil
+- end
++ if ok and res and new_q then
++ new_q:insert (res)
++ new_q:push (res, co)
++ else
++ if not ok then coxpcall.pcall (_errhandlers [co] or _deferror, res, co, skt) end
++ if skt and copas.autoclose then skt:close() end
++ _errhandlers [co] = nil
++ end
+ end
+
+ -- accepts a connection on socket input
+ local function _accept(input, handler)
+- local client = input:accept()
+- if client then
+- client:settimeout(0)
+- local co = coroutine.create(handler)
+- _doTick (co, client)
+- --_reading:insert(client)
+- end
+- return client
++ local client = input:accept()
++ if client then
++ client:settimeout(0)
++ local co = coroutine.create(handler)
++ _doTick (co, client)
++ --_reading:insert(client)
++ end
++ return client
+ end
+
+ -- handle threads on a queue
+ local function _tickRead (skt)
+- _doTick (_reading:pop (skt), skt)
++ _doTick (_reading:pop (skt), skt)
+ end
+
+ local function _tickWrite (skt)
+- _doTick (_writing:pop (skt), skt)
++ _doTick (_writing:pop (skt), skt)
+ end
+
+ -------------------------------------------------------------------------------
+ -- Adds a server/handler pair to Copas dispatcher
+ -------------------------------------------------------------------------------
+-function addserver(server, handler, timeout)
+- server:settimeout(timeout or 0.1)
+- _servers[server] = handler
+- _reading:insert(server)
++local function addTCPserver(server, handler, timeout)
++ server:settimeout(timeout or 0.1)
++ _servers[server] = handler
++ _reading:insert(server)
++end
++
++local function addUDPserver(server, handler, timeout)
++ server:settimeout(timeout or 0)
++ local co = coroutine.create(handler)
++ _reading:insert(server)
++ _doTick (co, server)
++end
++
++function copas.addserver(server, handler, timeout)
++ if string.sub(tostring(server),1,3) == "udp" then
++ addUDPserver(server, handler, timeout)
++ else
++ addTCPserver(server, handler, timeout)
++ end
+ end
+-
+ -------------------------------------------------------------------------------
+ -- Adds an new courotine thread to Copas dispatcher
+ -------------------------------------------------------------------------------
+-function addthread(thread, ...)
+- local co = coroutine.create(thread)
+- _doTick (co, nil, ...)
++function copas.addthread(thread, ...)
++ if type(thread) ~= "thread" then
++ thread = coroutine.create(thread)
++ end
++ _doTick (thread, nil, ...)
++ return thread
+ end
+
+ -------------------------------------------------------------------------------
+@@ -302,21 +403,21 @@
+ local _tasks = {}
+
+ local function addtaskRead (tsk)
+- -- lets tasks call the default _tick()
+- tsk.def_tick = _tickRead
++ -- lets tasks call the default _tick()
++ tsk.def_tick = _tickRead
+
+- _tasks [tsk] = true
++ _tasks [tsk] = true
+ end
+
+ local function addtaskWrite (tsk)
+- -- lets tasks call the default _tick()
+- tsk.def_tick = _tickWrite
++ -- lets tasks call the default _tick()
++ tsk.def_tick = _tickWrite
+
+- _tasks [tsk] = true
++ _tasks [tsk] = true
+ end
+
+ local function tasks ()
+- return next, _tasks
++ return next, _tasks
+ end
+
+ -------------------------------------------------------------------------------
+@@ -324,23 +425,23 @@
+ -------------------------------------------------------------------------------
+ -- a task to check ready to read events
+ local _readable_t = {
+- events = function(self)
+- local i = 0
+- return function ()
+- i = i + 1
+- return self._evs [i]
+- end
+- end,
+-
+- tick = function (self, input)
+- local handler = _servers[input]
+- if handler then
+- input = _accept(input, handler)
+- else
+- _reading:remove (input)
+- self.def_tick (input)
+- end
+- end
++ events = function(self)
++ local i = 0
++ return function ()
++ i = i + 1
++ return self._evs [i]
++ end
++ end,
++
++ tick = function (self, input)
++ local handler = _servers[input]
++ if handler then
++ input = _accept(input, handler)
++ else
++ _reading:remove (input)
++ self.def_tick (input)
++ end
++ end
+ }
+
+ addtaskRead (_readable_t)
+@@ -348,18 +449,18 @@
+
+ -- a task to check ready to write events
+ local _writable_t = {
+- events = function (self)
+- local i = 0
+- return function ()
+- i = i + 1
+- return self._evs [i]
+- end
+- end,
+-
+- tick = function (self, output)
+- _writing:remove (output)
+- self.def_tick (output)
+- end
++ events = function (self)
++ local i = 0
++ return function ()
++ i = i + 1
++ return self._evs [i]
++ end
++ end,
++
++ tick = function (self, output)
++ _writing:remove (output)
++ self.def_tick (output)
++ end
+ }
+
+ addtaskWrite (_writable_t)
+@@ -370,69 +471,70 @@
+ -- Checks for reads and writes on sockets
+ -------------------------------------------------------------------------------
+ local function _select (timeout)
+- local err
+- local readable={}
+- local writable={}
+- local r={}
+- local w={}
+- local now = os.time()
+- local duration = os.difftime
+-
+- _readable_t._evs, _writable_t._evs, err = socket.select(_reading, _writing, timeout)
+- local r_evs, w_evs = _readable_t._evs, _writable_t._evs
+-
+- if duration(now, last_cleansing) > WATCH_DOG_TIMEOUT then
+- last_cleansing = now
+- for k,v in pairs(_reading_log) do
+- if not r_evs[k] and duration(now, v) > WATCH_DOG_TIMEOUT then
+- _reading_log[k] = nil
+- r_evs[#r_evs + 1] = k
+- r_evs[k] = #r_evs
+- end
+- end
+-
+- for k,v in pairs(_writing_log) do
+- if not w_evs[k] and duration(now, v) > WATCH_DOG_TIMEOUT then
+- _writing_log[k] = nil
+- w_evs[#w_evs + 1] = k
+- w_evs[k] = #w_evs
+- end
+- end
+- end
+-
+- if err == "timeout" and #r_evs + #w_evs > 0 then
+- return nil
+- else
+- return err
+- end
++ local err
++ local now = os.time()
++ local duration = os.difftime
++
++ _readable_t._evs, _writable_t._evs, err = socket.select(_reading, _writing, timeout)
++ local r_evs, w_evs = _readable_t._evs, _writable_t._evs
++
++ if duration(now, last_cleansing) > WATCH_DOG_TIMEOUT then
++ last_cleansing = now
++ for k,v in pairs(_reading_log) do
++ if not r_evs[k] and duration(now, v) > WATCH_DOG_TIMEOUT then
++ _reading_log[k] = nil
++ r_evs[#r_evs + 1] = k
++ r_evs[k] = #r_evs
++ end
++ end
++
++ for k,v in pairs(_writing_log) do
++ if not w_evs[k] and duration(now, v) > WATCH_DOG_TIMEOUT then
++ _writing_log[k] = nil
++ w_evs[#w_evs + 1] = k
++ w_evs[k] = #w_evs
++ end
++ end
++ end
++
++ if err == "timeout" and #r_evs + #w_evs > 0 then
++ return nil
++ else
++ return err
++ end
+ end
+
+
+ -------------------------------------------------------------------------------
+ -- Dispatcher loop step.
+ -- Listen to client requests and handles them
++-- Returns false if no data was handled (timeout), or true if there was data
++-- handled (or nil + error message)
+ -------------------------------------------------------------------------------
+-function step(timeout)
+- local err = _select (timeout)
+- if err == "timeout" then return end
+-
+- if err then
+- error(err)
+- end
+-
+- for tsk in tasks() do
+- for ev in tsk:events() do
+- tsk:tick (ev)
+- end
+- end
++function copas.step(timeout)
++ local err = _select (timeout)
++ if err == "timeout" then return false end
++
++ if err then
++ error(err)
++ end
++
++ for tsk in tasks() do
++ for ev in tsk:events() do
++ tsk:tick (ev)
++ end
++ end
++ return true
+ end
+
+ -------------------------------------------------------------------------------
+ -- Dispatcher endless loop.
+ -- Listen to client requests and handles them forever
+ -------------------------------------------------------------------------------
+-function loop(timeout)
+- while true do
+- step(timeout)
+- end
++function copas.loop(timeout)
++ while true do
++ copas.step(timeout)
++ end
+ end
++
++return copas
+diff -urP copas-1.1.6/tests/cosocket.lua copas-1.2.0/tests/cosocket.lua
+--- copas-1.1.6/tests/cosocket.lua 2010-03-18 12:23:39.000000000 -0400
++++ copas-1.2.0/tests/cosocket.lua 2013-05-10 13:29:37.532722513 -0400
+@@ -5,27 +5,25 @@
+ --
+ -- Written by Leonardo Godinho da Cunha
+ -------------------------------------------------------------------------------
+-require "copas"
++local copas = require "copas"
+
+-module "copas.cosocket"
++local cosocket = {}
+
+ -- Meta information is public even begining with an "_"
+-_COPYRIGHT = "Copyright (C) 2004-2006 Kepler Project"
+-_DESCRIPTION = "Coroutine Oriented Portable Asynchronous Services Wrapper for socket module"
+-_NAME = "Copas.cosocket"
+-_VERSION = "0.1"
++cosocket._COPYRIGHT = "Copyright (C) 2004-2006 Kepler Project"
++cosocket._DESCRIPTION = "Coroutine Oriented Portable Asynchronous Services Wrapper for socket module"
++cosocket._NAME = "Copas.cosocket"
++cosocket._VERSION = "0.1"
+
+-
+-function tcp ()
+- skt=socket.tcp()
+- w_skt_mt={__index = skt
+- }
+- ret_skt = setmetatable ({socket = skt}, w_skt_mt)
++function cosocket.tcp ()
++ local skt = socket.tcp()
++ local w_skt_mt = { __index = skt }
++ local ret_skt = setmetatable ({ socket = skt }, w_skt_mt)
+ ret_skt.settimeout = function (self,val)
+ return self.socket:settimeout (val)
+- end
++ end
+ ret_skt.connect = function (self,host, port)
+- ret,err = copas.connect (self.socket,host, port)
++ local ret,err = copas.connect (self.socket,host, port)
+ local d = copas.wrap(self.socket)
+
+ self.send= function(client, data)
+diff -urP copas-1.1.6/tests/test.lua copas-1.2.0/tests/test.lua
+--- copas-1.1.6/tests/test.lua 2010-03-18 12:23:39.000000000 -0400
++++ copas-1.2.0/tests/test.lua 2013-05-10 13:29:37.532722513 -0400
+@@ -3,13 +3,13 @@
+ -- Run the test file and the connect to the server using telnet on the used port.
+ -- The server should be able to echo any input, to stop the test just send the command "quit"
+
+-require"copas"
++local copas = require"copas"
+
+ local function echoHandler(skt)
+ skt = copas.wrap(skt)
+ while true do
+ local data = skt:receive()
+- if data == "quit" then
++ if not data or data == "quit" then
+ break
+ end
+ skt:send(data)
+@@ -20,4 +20,4 @@
+
+ copas.addserver(server, echoHandler)
+
+-copas.loop()
+\ No newline at end of file
++copas.loop()
diff --git a/lua-copas.spec b/lua-copas.spec
index 559014e..e456d57 100644
--- a/lua-copas.spec
+++ b/lua-copas.spec
@@ -1,18 +1,22 @@
-%define luaver 5.1
+%define luaver 5.2
%define lualibdir %{_libdir}/lua/%{luaver}
%define luapkgdir %{_datadir}/lua/%{luaver}
+%global baseversion 1.1.6
Name: lua-copas
-Version: 1.1.6
-Release: 5%{?dist}
+Version: 1.2.0
+Release: 1%{?dist}
Summary: Coroutine Oriented Portable Asynchronous Services for Lua
Group: Development/Libraries
License: MIT
URL: http://keplerproject.github.com/copas/
-Source0: http://github.com/downloads/keplerproject/copas/copas-%{version}.tar.gz
+Source0: http://github.com/downloads/keplerproject/copas/copas-%{baseversion}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildArch: noarch
+# 1.2.0 marked in git
+# https://github.com/keplerproject/copas
+Patch0: copas-1.2.0-git.patch
BuildRequires: lua >= %{luaver}, lua-devel >= %{luaver}
Requires: lua >= %{luaver}
@@ -28,7 +32,8 @@ invokes the corresponding handlers. For a full implementation of a Copas HTTP
server you can refer to Xavante as an example.
%prep
-%setup -q -n copas-%{version}
+%setup -q -n copas-%{baseversion}
+%patch0 -p1 -b .1.2.0
%build
@@ -52,6 +57,10 @@ rm -rf %{buildroot}
%changelog
+* Fri May 10 2013 Tom Callaway <spot at fedoraproject.org> - 1.2.0-1
+- update to 1.2.0
+- rebuild for lua 5.2
+
* Thu Feb 14 2013 Fedora Release Engineering <rel-eng at lists.fedoraproject.org> - 1.1.6-5
- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild
More information about the scm-commits
mailing list