* Adjusted licensing and added README.
[luaevent.git] / luaevent / luaevent.lua
blob3b8ed182bf6faf038b397b2db7d9bc1069862915
1 --[[
2 LuaEvent - Copyright (C) 2007 Thomas Harning <harningt@gmail.com>
3 Licensed as LGPL - See doc/COPYING for details.
4 ]]
5 module("luaevent", package.seeall)
6 require("luaevent.core")
8 local EV_READ = luaevent.core.EV_READ
9 local EV_WRITE = luaevent.core.EV_WRITE
10 local fair = false
12 -- Weak keys.. the keys are the client sockets
13 local clientTable = {} or setmetatable({}, {'__mode', 'k'})
15 local function getWrapper()
16 local running = coroutine.running()
17 return function(...)
18 print(coroutine.running(), running)
19 print(debug.traceback())
20 if coroutine.running() == running then return end
21 return select(2, coroutine.resume(running, ...))
22 end
23 end
25 function send(sock, data, start, stop)
26 local s, err
27 local from = start or 1
28 local sent = 0
29 repeat
30 from = from + sent
31 s, err, sent = sock:send(data, from, stop)
32 -- Add extra coro swap for fairness
33 -- CURRENTLY DISABLED FOR TESTING......
34 if fair and math.random(100) > 90 then
35 coroutine.yield(EV_WRITE)
36 end
37 if s or err ~= "timeout" then return s, err, sent end
38 if not clientTable[sock] then clientTable[sock] = luaevent.core.addevent(sock, EV_WRITE, getWrapper()) end
39 coroutine.yield(EV_WRITE)
40 until false
41 end
42 function receive(sock, pattern, part)
43 local s, err
44 pattern = pattern or '*l'
45 repeat
46 s, err, part = sock:receive(pattern, part)
47 if s or err ~= "timeout" then return s, err, part end
48 if not clientTable[sock] then clientTable[sock] = luaevent.core.addevent(sock, EV_READ, getWrapper()) end
49 coroutine.yield(EV_READ)
50 until false
51 end
52 -- same as above but with special treatment when reading chunks,
53 -- unblocks on any data received.
54 function receivePartial(client, pattern)
55 local s, err, part
56 pattern = pattern or "*l"
57 repeat
58 s, err, part = client:receive(pattern)
59 if s or ( (type(pattern)=="number") and part~="" and part ~=nil ) or
60 err ~= "timeout" then return s, err, part end
61 if not clientTable[sock] then clientTable[sock] = luaevent.core.addevent(sock, EV_READ, getWrapper()) end
62 coroutine.yield(EV_READ)
63 until false
64 end
65 function connect(sock, ...)
66 sock:settimeout(0)
67 local ret, err = sock:connect(...)
68 if ret or err ~= "timeout" then return ret, err end
69 if not clientTable[sock] then clientTable[sock] = luaevent.core.addevent(sock, EV_WRITE, getWrapper()) end
70 coroutine.yield(EV_WRITE)
71 ret, err = sock:connect(...)
72 if err == "already connected" then
73 return 1
74 end
75 return ret, err
76 end
77 -- Deprecated..
78 function flush(sock)
79 end
80 local function clientCoroutine(sock, handler)
81 -- Figure out what to do ......
82 return handler(sock)
83 end
84 local function handleClient(co, client, handler)
85 local ok, res, event = coroutine.resume(co, client, handler)
86 end
87 local function serverCoroutine(sock, callback)
88 local listenItem = luaevent.core.addevent(sock, EV_READ, getWrapper())
89 repeat
90 local event = coroutine.yield(EV_READ)
91 -- Get new socket
92 local client = sock:accept()
93 if client then
94 client:settimeout(0)
95 local co = coroutine.create(clientCoroutine)
96 handleClient(co, client, callback)
97 end
98 until false
99 end
100 function addserver(sock, callback)
101 local coro = coroutine.create(serverCoroutine)
102 assert(coroutine.resume(coro, sock, callback))
104 function addthread(func, ...)
105 return coroutine.resume(coroutine.create(func), ...)
107 local _skt_mt = {__index = {
108 connect = function(self, ...)
109 return connect(self.socket, ...)
110 end,
111 send = function (self, data)
112 return send (self.socket, data)
113 end,
115 receive = function (self, pattern)
116 if (self.timeout==0) then
117 return receivePartial(self.socket, pattern)
119 return receive (self.socket, pattern)
120 end,
122 flush = function (self)
123 return flush (self.socket)
124 end,
126 settimeout = function (self,time)
127 self.timeout=time
128 return
129 end,
131 function wrap(sock)
132 return setmetatable({socket = sock}, _skt_mt)
134 loop = luaevent.core.loop