2 LuaEvent - Copyright (C) 2007 Thomas Harning <harningt@gmail.com>
3 Licensed as LGPL - See doc/COPYING for details.
5 module("luaevent", package
.seeall
)
6 require("luaevent.core")
11 local EV_READ
= luaevent
.core
.EV_READ
12 local EV_WRITE
= luaevent
.core
.EV_WRITE
13 local base
= luaevent
.core
.new()
15 local function addevent(...)
16 return base
:addevent(...)
19 local function getWrapper()
20 local running
= coroutine
.running()
22 return select(2, coroutine
.resume(running
, ...))
25 -- Weak keys.. the keys are the client sockets
26 local clientTable
= setmetatable({}, {'__mode', 'kv'})
27 local function socketWait(sock
, event
)
28 if not clientTable
[sock
] then clientTable
[sock
] = addevent(sock
, event
, getWrapper()) end
29 coroutine
.yield(event
)
33 function send(sock
, data
, start
, stop
)
35 local from
= start
or 1
39 s
, err
, sent
= sock
:send(data
, from
, stop
)
40 if s
or err
~= "timeout" then return s
, err
, sent
end
41 socketWait(sock
, EV_WRITE
)
44 function receive(sock
, pattern
, part
)
46 pattern
= pattern
or '*l'
48 s
, err
, part
= sock
:receive(pattern
, part
)
49 if s
or err
~= "timeout" then return s
, err
, part
end
50 socketWait(sock
, EV_READ
)
53 -- same as above but with special treatment when reading chunks,
54 -- unblocks on any data received.
55 function receivePartial(client
, pattern
)
57 pattern
= pattern
or "*l"
59 s
, err
, part
= client
:receive(pattern
)
60 if s
or ( (type(pattern
)=="number") and part
~="" and part
~=nil ) or
61 err
~= "timeout" then return s
, err
, part
end
62 socketWait(sock
, EV_READ
)
65 function connect(sock
, ...)
67 local ret
, err
= sock
:connect(...)
68 if ret
or err
~= "timeout" then return ret
, err
end
69 socketWait(sock
, EV_WRITE
)
70 ret
, err
= sock
:connect(...)
71 if err
== "already connected" then
79 local function clientCoroutine(sock
, handler
)
80 -- Figure out what to do ......
83 local function handleClient(co
, client
, handler
)
84 local ok
, res
, event
= coroutine
.resume(co
, client
, handler
)
86 local function serverCoroutine(sock
, callback
)
87 local listenItem
= addevent(sock
, EV_READ
, getWrapper())
89 local event
= coroutine
.yield(EV_READ
)
91 local client
= sock
:accept()
94 local co
= coroutine
.create(clientCoroutine
)
95 handleClient(co
, client
, callback
)
99 function addserver(sock
, callback
)
100 local coro
= coroutine
.create(serverCoroutine
)
101 assert(coroutine
.resume(coro
, sock
, callback
))
103 function addthread(func
, ...)
104 return coroutine
.resume(coroutine
.create(func
), ...)
106 local _skt_mt
= {__index
= {
107 connect
= function(self
, ...)
108 return connect(self
.socket
, ...)
110 send
= function (self
, data
)
111 return send(self
.socket
, data
)
114 receive
= function (self
, pattern
)
115 if (self
.timeout
==0) then
116 return receivePartial(self
.socket
, pattern
)
118 return receive(self
.socket
, pattern
)
121 flush = function (self
)
122 return flush(self
.socket
)
125 settimeout
= function (self
,time
)
130 close
= function(self
)
131 clientTable
[self
.socket
]:close()
136 return setmetatable({socket
= sock
}, _skt_mt
)
138 loop
= function(...) base
:loop(...) end