|
1 module("luaevent", package.seeall) |
|
2 require("luaevent.core") |
|
3 |
|
4 local EV_READ = luaevent.core.EV_READ |
|
5 local EV_WRITE = luaevent.core.EV_WRITE |
|
6 local fair = false |
|
7 |
|
8 -- Weak keys.. the keys are the client sockets |
|
9 local clientTable = {} or setmetatable({}, {'__mode', 'k'}) |
|
10 |
|
11 local function getWrapper() |
|
12 local running = coroutine.running() |
|
13 return function(...) |
|
14 print(coroutine.running(), running) |
|
15 print(debug.traceback()) |
|
16 if coroutine.running() == running then return end |
|
17 return select(2, coroutine.resume(running, ...)) |
|
18 end |
|
19 end |
|
20 |
|
21 function send(sock, data, start, stop) |
|
22 local s, err |
|
23 local from = start or 1 |
|
24 local sent = 0 |
|
25 repeat |
|
26 from = from + sent |
|
27 s, err, sent = sock:send(data, from, stop) |
|
28 -- Add extra coro swap for fairness |
|
29 -- CURRENTLY DISABLED FOR TESTING...... |
|
30 if fair and math.random(100) > 90 then |
|
31 coroutine.yield(EV_WRITE) |
|
32 end |
|
33 if s or err ~= "timeout" then return s, err, sent end |
|
34 if not clientTable[sock] then clientTable[sock] = luaevent.core.addevent(sock, EV_WRITE, getWrapper()) end |
|
35 coroutine.yield(EV_WRITE) |
|
36 until false |
|
37 end |
|
38 function receive(sock, pattern, part) |
|
39 local s, err |
|
40 pattern = pattern or '*l' |
|
41 repeat |
|
42 s, err, part = sock:receive(pattern, part) |
|
43 if s or err ~= "timeout" then return s, err, part end |
|
44 if not clientTable[sock] then clientTable[sock] = luaevent.core.addevent(sock, EV_READ, getWrapper()) end |
|
45 coroutine.yield(EV_READ) |
|
46 until false |
|
47 end |
|
48 -- same as above but with special treatment when reading chunks, |
|
49 -- unblocks on any data received. |
|
50 function receivePartial(client, pattern) |
|
51 local s, err, part |
|
52 pattern = pattern or "*l" |
|
53 repeat |
|
54 s, err, part = client:receive(pattern) |
|
55 if s or ( (type(pattern)=="number") and part~="" and part ~=nil ) or |
|
56 err ~= "timeout" then return s, err, part end |
|
57 if not clientTable[sock] then clientTable[sock] = luaevent.core.addevent(sock, EV_READ, getWrapper()) end |
|
58 coroutine.yield(EV_READ) |
|
59 until false |
|
60 end |
|
61 function connect(sock, ...) |
|
62 sock:settimeout(0) |
|
63 local ret, err = sock:connect(...) |
|
64 if ret or err ~= "timeout" then return ret, err end |
|
65 if not clientTable[sock] then clientTable[sock] = luaevent.core.addevent(sock, EV_WRITE, getWrapper()) end |
|
66 coroutine.yield(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 = luaevent.core.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), ...) |
|
102 end |
|
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, |
|
110 |
|
111 receive = function (self, pattern) |
|
112 if (self.timeout==0) then |
|
113 return receivePartial(self.socket, pattern) |
|
114 end |
|
115 return receive (self.socket, pattern) |
|
116 end, |
|
117 |
|
118 flush = function (self) |
|
119 return flush (self.socket) |
|
120 end, |
|
121 |
|
122 settimeout = function (self,time) |
|
123 self.timeout=time |
|
124 return |
|
125 end, |
|
126 }} |
|
127 function wrap(sock) |
|
128 return setmetatable({socket = sock}, _skt_mt) |
|
129 end |
|
130 loop = luaevent.core.loop |