* Added some cheap protection code for failures in callback
[luaevent.git] / luaevent / luaevent.lua
blob6e6cf05a52ce81c2e7423ba8377d4a39a24260b0
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 local hookedObjectMt = false
14 -- Weak keys.. the keys are the client sockets
15 local clientTable = setmetatable({}, {'__mode', 'k'})
17 function send(sock, data, start, stop)
18 local s, err
19 local from = start or 1
20 local sent = 0
21 repeat
22 from = from + sent
23 s, err, sent = sock:send(data, from, stop)
24 -- Add extra coro swap for fairness
25 -- CURRENTLY DISABLED FOR TESTING......
26 if fair and math.random(100) > 90 then
27 coroutine.yield(EV_WRITE)
28 end
29 if s or err ~= "timeout" then return s, err, sent end
30 coroutine.yield(EV_WRITE)
31 until false
32 end
33 function receive(sock, pattern, part)
34 local s, err
35 pattern = pattern or '*l'
36 repeat
37 s, err, part = sock:receive(pattern, part)
38 if s or err ~= "timeout" then return s, err, part end
39 coroutine.yield(EV_READ)
40 until false
41 end
42 -- same as above but with special treatment when reading chunks,
43 -- unblocks on any data received.
44 function receivePartial(client, pattern)
45 local s, err, part
46 pattern = pattern or "*l"
47 repeat
48 s, err, part = client:receive(pattern)
49 if s or ( (type(pattern)=="number") and part~="" and part ~=nil ) or
50 err ~= "timeout" then return s, err, part end
51 coroutine.yield(EV_READ)
52 until false
53 end
54 function connect(sock, ...)
55 sock:settimeout(0)
56 local ret, err = sock:connect(...)
57 if ret or err ~= "timeout" then return ret, err end
58 coroutine.yield(EV_WRITE)
59 ret, err = sock:connect(...)
60 if err == "already connected" then
61 return 1
62 end
63 return ret, err
64 end
65 -- Deprecated..
66 function flush(sock)
67 end
68 local function clientCoroutine(sock, handler)
69 -- Figure out what to do ......
70 return handler(sock)
71 end
73 local function serverCoroutine(sock, callback)
74 repeat
75 local event = coroutine.yield(EV_READ)
76 -- Get new socket
77 local client = sock:accept()
78 if client then
79 --cl[#cl + 1] = client
80 client:settimeout(0)
81 local coFunc = coroutine.wrap(clientCoroutine)
82 clientTable[client] = luaevent.core.addevent(client, coFunc, client, callback)
83 end
84 until false
85 end
87 local oldAddEvent = luaevent.core.addevent
88 luaevent.core.addevent = function(...)
89 local item = oldAddEvent(...)
90 if not item then print("FAILED TO SETUP ITEM") return item end
91 print("SETUP ITEM FOR: ", debug.getmetatable(item).getfd(item))
92 if not hookedObjectMt then
93 hookedObjectMt = true
94 local mt = debug.getmetatable(item)
95 local oldGC = mt.__gc
96 mt.__gc = function(...)
97 print("RELEASING ITEM FOR: ", mt.getfd(...))
98 return oldGC(...)
99 end
101 return item
104 function addserver(sock, callback)
105 local coFunc = coroutine.wrap(serverCoroutine)
106 clientTable[sock] = luaevent.core.addevent(sock, coFunc, sock, callback)
108 function addthread(sock, func, ...)
109 local coFunc = coroutine.wrap(func)
110 clientTable[sock] = luaevent.core.addevent(sock, coFunc, ...)
112 local _skt_mt = {__index = {
113 connect = function(self, ...)
114 return connect(self.socket, ...)
115 end,
116 send = function (self, data)
117 return send (self.socket, data)
118 end,
120 receive = function (self, pattern)
121 if (self.timeout==0) then
122 return receivePartial(self.socket, pattern)
124 return receive (self.socket, pattern)
125 end,
127 flush = function (self)
128 return flush (self.socket)
129 end,
131 settimeout = function (self,time)
132 self.timeout=time
133 return
134 end,
136 function wrap(sock)
137 return setmetatable({socket = sock}, _skt_mt)
139 loop = luaevent.core.loop