buffer_event learned get_read/get_write buffer accessors
[luaevent.git] / lua / luaevent.lua
bloba05de29ef324221ca344bc9a4bc625cab4b661d1
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 base = luaevent.core.new()
12 local function addevent(...)
13 return base:addevent(...)
14 end
16 local function getWrapper()
17 local running = coroutine.running()
18 return function(...)
19 return select(2, coroutine.resume(running, ...))
20 end
21 end
22 -- Weak keys.. the keys are the client sockets
23 local clientTable = setmetatable({}, {'__mode', 'kv'})
24 local function socketWait(sock, event)
25 if not clientTable[sock] then clientTable[sock] = addevent(sock, event, getWrapper()) end
26 coroutine.yield(event)
27 end
30 function send(sock, data, start, stop)
31 local s, err
32 local from = start or 1
33 local sent = 0
34 repeat
35 from = from + sent
36 s, err, sent = sock:send(data, from, stop)
37 if s or err ~= "timeout" then return s, err, sent end
38 socketWait(sock, EV_WRITE)
39 until false
40 end
41 function receive(sock, pattern, part)
42 local s, err
43 pattern = pattern or '*l'
44 repeat
45 s, err, part = sock:receive(pattern, part)
46 if s or err ~= "timeout" then return s, err, part end
47 socketWait(sock, EV_READ)
48 until false
49 end
50 -- same as above but with special treatment when reading chunks,
51 -- unblocks on any data received.
52 function receivePartial(client, pattern)
53 local s, err, part
54 pattern = pattern or "*l"
55 repeat
56 s, err, part = client:receive(pattern)
57 if s or ( (type(pattern)=="number") and part~="" and part ~=nil ) or
58 err ~= "timeout" then return s, err, part end
59 socketWait(sock, EV_READ)
60 until false
61 end
62 function connect(sock, ...)
63 sock:settimeout(0)
64 local ret, err = sock:connect(...)
65 if ret or err ~= "timeout" then return ret, err end
66 socketWait(sock, EV_WRITE)
67 ret, err = sock:connect(...)
68 if err == "already connected" then
69 return 1
70 end
71 return ret, err
72 end
73 -- Deprecated..
74 function flush(sock)
75 end
76 local function clientCoroutine(sock, handler)
77 -- Figure out what to do ......
78 return handler(sock)
79 end
80 local function handleClient(co, client, handler)
81 local ok, res, event = coroutine.resume(co, client, handler)
82 end
83 local function serverCoroutine(sock, callback)
84 local listenItem = addevent(sock, EV_READ, getWrapper())
85 repeat
86 local event = coroutine.yield(EV_READ)
87 -- Get new socket
88 local client = sock:accept()
89 if client then
90 client:settimeout(0)
91 local co = coroutine.create(clientCoroutine)
92 handleClient(co, client, callback)
93 end
94 until false
95 end
96 function addserver(sock, callback)
97 local coro = coroutine.create(serverCoroutine)
98 assert(coroutine.resume(coro, sock, callback))
99 end
100 function addthread(func, ...)
101 return coroutine.resume(coroutine.create(func), ...)
103 local _skt_mt = {__index = {
104 connect = function(self, ...)
105 return connect(self.socket, ...)
106 end,
107 send = function (self, data)
108 return send(self.socket, data)
109 end,
111 receive = function (self, pattern)
112 if (self.timeout==0) then
113 return receivePartial(self.socket, pattern)
115 return receive(self.socket, pattern)
116 end,
118 flush = function (self)
119 return flush(self.socket)
120 end,
122 settimeout = function (self,time)
123 self.timeout=time
124 return
125 end,
127 close = function(self)
128 clientTable[self.socket]:close()
129 self.socket:close()
132 function wrap(sock)
133 return setmetatable({socket = sock}, _skt_mt)
135 loop = function(...) base:loop(...) end