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