[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